2012-05-09 21 views

Trả lời

5

Java được thiết kế để di động từ đầu. Nhưng làm thế nào bạn có thể giữ cho bytecode của bạn di động nếu nó phụ thuộc vào một số thanh ghi có mặt trên nền tảng bạn đang chạy nó? Đặc biệt có tính đến ban đầu nó được dự định để chạy (cũng) trên các hộp set-top, trong đó có một kiến ​​trúc bộ vi xử lý rất khác nhau từ máy tính chủ đạo.

Chỉ có thời gian chạy là JVM thực sự biết các thanh ghi có sẵn và các phần cứng cụ thể khác. Sau đó, trình biên dịch JIT có thể (và sẽ) tối ưu hóa cho những điều này nếu có.

+7

Nói đúng, sổ đăng ký ảo không cần phải được ánh xạ lên thanh ghi vật lý. Từ POV khác, hỗ trợ phần cứng cho ngăn xếp một lần nữa không được bảo đảm, phải không? Ví dụ: – Vlad

+2

ActionScript VM, dựa trên đăng ký. Tôi nghĩ lý do cho một thiết kế như vậy không đơn giản và cuối cùng đi đến một loạt các sự cân bằng mà các nhà thiết kế Oak (tôi đoán đó là họ - trước khi mua lại Sun) liên quan đến tầm nhìn cụ thể về ứng dụng ngôn ngữ của họ . –

+0

Tôi thích giải thích câu hỏi gốc là * ưu điểm của máy ảo dựa trên stack so với các phương tiện khác để xây dựng VM, chẳng hạn như máy ảo dựa trên đăng ký ảo *. Tuy nhiên, có vẻ như OP có thể sống với câu trả lời được lựa chọn (hoặc quên động lực ban đầu của chính mình). – smwikipedia

2

Khi thiết kế một máy ảo, việc đặt một ngăn xếp thay vì tập hợp các thanh ghi ảo dễ dàng hơn nhiều. Nếu máy chủ có một ngăn xếp, như tất cả chúng đều làm, không có gì để làm, và nếu nó có thanh ghi, bạn vẫn có thể sử dụng chúng cho các thứ khác: tạm thời, vv. Nếu mặt khác, máy chủ không có thanh ghi , chỉ có một ngăn xếp, và bạn thiết kế máy ảo của bạn xung quanh sổ đăng ký, bạn có vấn đề triển khai chính trên tay, vì bạn phải sử dụng ngăn xếp riêng, theo cách sẽ can thiệp vào việc sử dụng nó làm chồng ảo.

6

Tôi phải kính trọng không đồng ý với các câu trả lời trước.

Giả định về sự tồn tại của ngăn xếp biểu thức không tốt hơn giả định so với sự tồn tại của thanh ghi. Thông thường các máy đăng ký không thể thực thi trực tiếp các mã lệnh stack, và các máy ngăn xếp không thể trực tiếp thực thi các opcode mã đăng ký. Chúng phải được lập bản đồ.

EJP nói "Nếu máy chủ có ngăn xếp, giống như tất cả, không có gì để làm". Đây là một tuyên bố sai. Đề xuất rằng tất cả các máy có ngăn xếp có khả năng thực hiện tính toán cho thấy sự nhầm lẫn về những gì một máy stack thực sự là.

  1. Máy dựa trên ngăn xếp có bộ hướng dẫn với toán hạng ngầm ở trên cùng của "chồng biểu thức". Không phải là một mục đích chung ngăn xếp. Một ngăn xếp mục đích chung không phải là một máy stack tạo ra. Họ có thể lưu/khôi phục các giá trị. Tất cả các nền tảng đều có điều đó. Nhưng họ không thể thực hiện tính toán.
  2. Máy đăng ký dựa trên thực thi các opcodes điển hình với các toán hạng rõ ràng, số đăng ký ảo , được mã hóa trong luồng lệnh. Những máy ảo này vẫn có các ngăn xếp chung và các opcodes để lưu và khôi phục các thanh ghi. Bạn không thể bản đồ ops tính toán ngăn xếp vào ngăn xếp dữ liệu. Toán hạng của bộ chỉ lệnh cốt lõi là các thanh ghi, các địa chỉ bộ nhớ hoặc ngay lập tức (được mã hóa trong mã opcode).

Vì vậy, chắc chắn còn hơn "không có gì để làm" để ánh xạ các mã opcodes của một kiến ​​trúc máy khác. Trừ khi bạn đang ở trên một chip với tăng tốc opcode Java bản địa, bạn tốt hơn không nên giả định điều đó.

Tôi không tranh luận rằng máy xếp chồng là một lựa chọn tốt cho tính di động. Tôi đang nói rằng có "điều gì đó cần làm" để lập bản đồ hướng dẫn từ ngăn xếp đăng ký hoặc đăng ký để ngăn xếp. Cả hai đều có thể.

Tuy nhiên, rất nhiều cuộc nói chuyện mang tính học thuật. Trong thực hành, vào năm 2014, nền tảng phổ biến được đăng ký.Ngay cả dựa trên bộ xử lý "bộ xử lý" thường chip mềm được thực hiện ở trên cùng của một con chip đăng ký. Xem thông số kỹ thuật Java Card 3 và xem xét các triển khai và tìm ra bộ vi xử lý nào thực sự được sử dụng. Tôi sẽ để nó như một bài tập. Trừ khi chúng tôi đang thiết kế một VM cho một nền tảng rất cụ thể (như chúng tôi đã được yêu cầu thiết kế một JVM sẽ chỉ chạy trên bộ xử lý GreenSpaces mà tôi không thấy xảy ra), thì tôi giả sử ngữ cảnh là ứng dụng chung, các ứng dụng nhúng, thiết lập hộp trên cùng, bộ điều khiển phần mềm, đồ chơi, thậm chí cả thẻ thông minh. Đối với tất cả những điều này, tôi thấy bộ vi xử lý 8-32 bit như ARM, hoặc được sử dụng hoặc có sẵn. JVM chủ đạo được viết bằng C. C làm cho nó có thể thiết kế một thông dịch viên với ngăn xếp ảo hoặc các mã đăng ký ảo. Trong những năm 90, đã có rất nhiều cuộc thảo luận về các bộ xử lý Java dựa trên stack hỗ trợ trực tiếp các opcodes JVM. Trong năm 2014, chúng tôi thấy những triển khai này trên phần cứng dựa trên đăng ký hoặc các hướng dẫn bổ sung như Jazelle (tăng tốc Java) trên ARM926EJ-S, nơi cũng có đăng ký và hỗ trợ cho bộ hướng dẫn ARM.

Đối với ứng dụng chung, máy ảo dựa trên ngăn xếp chắc chắn không ánh xạ tới ngăn xếp trong thực tế. Tất cả các máy này đều sử dụng các hướng dẫn chính dựa trên đăng ký; và các ngăn xếp ngăn xếp là để lưu và khôi phục sổ đăng ký hoặc ngăn xếp cuộc gọi, không thực hiện các phép tính, logic hoặc phân nhánh. Các máy ảo ngăn xếp JIT đến tập lệnh gốc của máy, cho dù đó là một ngăn xếp hay tập lệnh đăng ký. Từ năm 1980, hầu như mọi kiến ​​trúc bộ xử lý mới đều được đăng ký, theo số Hennessy và Patterson - "Kiến trúc máy tính Một phương pháp định lượng". Điều đó có nghĩa là thanh ghi đăng ký, bộ nhớ đăng ký hoặc bộ chỉ dẫn đăng ký ngay lập tức. Bạn không thể thêm 2 giá trị trên ngăn xếp trên máy không có chồng dựa trên thêm. Trên x86, chồng opcodes dựa của bạn cho một hoạt động Thanh có thể dịch từ:

push a 
push b 
add 

mã đăng ký bản địa:

mov eax, [addra] 
mov ebx, [addrb] 
add eax, ebx 

Thứ hai, bất kể dòng opcode được chồng hoặc đăng kí, một JIT có thể biên dịch nó thành mã gốc. Vì vậy, sự lựa chọn của mô hình VM chỉ đơn giản là một mô hình phần mềm. Máy đăng ký chỉ là ảo. Chúng không mã hóa bất kỳ thông tin đăng ký gốc nào, các thanh ghi trong các opcodes là các ký hiệu ảo.

Bây giờ khi Java được thiết kế, các suy nghĩ hướng tới các mã nhỏ và khả năng tương thích bộ xử lý 8 bit. Stack dựa trên opcodes nhỏ hơn opcodes đăng ký. Vì vậy, nó có ý nghĩa. Tôi chắc chắn rằng tôi đọc ở đâu đó rằng đó là một trong những lý do chính mà James Gosling đã chọn cho Oak (tên ban đầu cho Java), bên cạnh sự đơn giản. Tôi chỉ không có một bàn tay tham khảo. Trong đó, tôi đồng ý với Péter Török.

  • Có những lợi ích quan sát được đối với mã vạch ngăn xếp. Các dòng mã thường nhỏ hơn/đậm đặc hơn. Về JVM và CLR, quan sát bytecode xếp chồng lên nhau có thể nhỏ hơn 15-20% so với các máy khác. Stack bytecode có thể được mã hóa dễ dàng trong < = 8 bit. (Forth máy có thể có ít nhất là 20 hoặc hơn opcodes). Các opstream là dễ dàng hơn để mã hóa/giải mã. Hãy thử viết một assembler hoặc disassembler cho Java sau đó cho x86.
  • Có những lợi ích quan sát để đăng ký mã opcode. Ít opcodes hơn để mã hóa một biểu thức = tốt hơn IPC = phân nhánh cấp thấp hơn trong trình thông dịch. Nó cũng có thể ánh xạ trực tiếp một số lượng nhỏ các thanh ghi (8 đến 16) cho hầu như mọi bộ xử lý hiện đại. Sử dụng thanh ghi đạt được thông lượng cao hơn nhiều do bộ nhớ cache tốt hơn địa phương tham chiếu. Ngược lại, các máy stack sử dụng rất nhiều băng thông bộ nhớ.

Trong máy ảo, đăng ký bytecode thường sử dụng bộ đăng ký ảo lớn, yêu cầu mã byte lớn hơn.Trên hầu hết phần cứng thực, thanh ghi thường được mã hóa với khoảng 3 bit (Intel x86) đến 5 bit (Sparc), do đó mật độ có thể khác với VM hoặc VM tới CPU hoặc VM tới CPU. Dalvik sử dụng 4 đến 16 bit để biểu diễn thanh ghi, trong khi Parrot sử dụng 8 bit trên mỗi đăng ký trên tất cả các mã opcode (ít nhất là định dạng bytecode v2 tôi đã sử dụng). Dalvik đạt được mật độ trung bình tốt hơn. Dựa trên kinh nghiệm của tôi với việc xây dựng chúng, thật khó để xây dựng một máy đăng ký có mục đích chung trong vòng 8 bit bytecode trừ khi bạn tuân thủ nghiêm ngặt các nguyên thủy và sử dụng một tệp đăng ký nhỏ. Điều này có vẻ không trực quan, nhưng thường một opcode đơn thực sự có một số mã hóa với các loại đăng ký khác nhau.

Điểm cuối cùng: Rất nhiều tối ưu hóa lõi mềm có khả năng xuất hiện khi cửa sổ JIT xuất hiện trong ảnh.

Ngoại lệ chính tôi thực hiện với lập luận rằng máy xếp chồng bản đồ tốt hơn cho phần cứng là nó bỏ qua nơi JVM chạy và/hoặc nơi công nghệ đang hướng đến. Ngoài Chuck Moore, tôi không biết ai đang thiết kế các bộ xử lý dựa trên stack (IGNITE và GreenSpaces GA144), và hầu hết sự phát triển mới là máy đăng ký. Các đối số cho máy xếp chồng chủ yếu là học tập. Đối với mọi đối số bộ xử lý ngăn xếp 8 bit, tôi có thể hiển thị cho bạn một số máy đăng ký (Hitachi H8 với thanh ghi, ARM926 có đăng ký, Intel 8051) với trình biên dịch C. Bạn có thể có nhiều khả năng được viết trong Forth trên một bộ xử lý ngăn xếp tinh khiết, hơn Java. Đối với một nền tảng mới, nó có ý nghĩa hơn để đi với một bộ xử lý ARM giá rẻ, nơi có các trình biên dịch C, đầy đủ JVM, vv Các bộ hướng dẫn đăng ký chạy.

Vì vậy, nếu thats đúng? Nó có quan trọng không? Ý kiến ​​của tôi, dựa trên kinh nghiệm của tôi, là "không nhiều như mọi người nghĩ". Hãy nhớ rằng, bytecode chỉ là một biểu diễn trung gian. Lõi thông dịch thuần túy của máy thường là một bước đệm, một cây cầu, một lõi không an toàn mặc định. Điểm đến cuối cùng là phiên bản cuối cùng 2 với JITter đến hiệu suất gốc. Vì vậy, quan điểm được tổ chức bởi nhiều người đã thực hiện nó một hoặc hai lần là nó làm cho tinh thần để giữ cho cốt lõi càng đơn giản càng tốt và chuyển sang JIT, chi tiêu 90% tối ưu hóa ở đó. Bất kỳ nỗ lực lãng phí nào điều chỉnh lõi xen kẽ có thể được xem là tối ưu hóa sớm. Mặt khác, nếu bạn không lập kế hoạch một JITter, hoặc JIT là không thực tế do các ràng buộc về bộ nhớ, sau đó tối ưu hóa trên lõi ảo hoặc triển khai VM trên một chip.

+0

Tôi phát hiện một số nhầm lẫn ở đây. Trong # 2 bạn nói về máy ảo khi bạn có nghĩa là bộ vi xử lý vật lý. Tôi không thấy nơi bạn giải thích làm thế nào một máy ảo dựa trên đăng ký có thể được (dễ dàng) thực hiện trên một bộ xử lý dựa trên stack, đó là vấn đề được đề cập. Tôi không nhìn thấy nơi bạn nói những gì sai với câu trả lời của riêng tôi mặc dù bạn nói rằng bạn không đồng ý với nó. Cuối cùng tôi không thấy lý do nào để bạn bảo trợ công việc của những người đã thực sự làm nó. – EJP

+2

Tôi đã có thể bỏ phiếu cho điều này, tôi đã có thể nhận được +50 phiếu bầu cùng một lúc. Một kiến ​​thức sâu sắc hơn với thiết lập kiến ​​trúc nền từ thời điểm thành lập chỉ là tuyệt vời để đọc. Mặc dù, tôi không thể hiểu một số dòng ở giữa, nhưng bài đăng có nội dung phải đọc. Cảm ơn @mrjoltcola vì đã cung cấp thông tin có giá trị như vậy và chỉ trích cho các phần sai một cách tôn trọng! –

+2

@EJP - Theo yêu cầu, tôi đã cập nhật để nêu rõ những gì tôi không đồng ý với câu trả lời của riêng bạn. Để "bảo trợ công việc của những người đã thực sự thực hiện nó", tôi đã triển khai 3 máy ảo từ đầu, hai trong số đó là mã nguồn mở, có sẵn để tải xuống, một trong số đó được bao gồm trong một số cuốn sách của O'Reilly và nhà xuất bản. Tôi cũng đã nghiên cứu, lập trình hoặc viết JIT trên các CPU Intel x86, Sparc, Motorola, PowerPC, PA-RISC, ARM, MIPS và 8051 vì vậy tôi có một ý tưởng chung về bộ vi xử lý. Tôi không tuyên bố tôi đã làm những điều tuyệt vời. Nhưng tôi hầu như không đủ điều kiện như một người đã không làm điều đó. – codenheim

Các vấn đề liên quan