Path: csiph.com!weretis.net!feeder6.news.weretis.net!feeder.usenetexpress.com!feeder-in1.iad1.usenetexpress.com!border1.nntp.dca1.giganews.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!news.iecc.com!.POSTED.news.iecc.com!nerds-end From: bartc Newsgroups: comp.compilers Subject: Re: Opcode handler dispatch in an interpreter: Implementing switch on OpCode. Date: Sat, 7 Oct 2017 19:05:10 +0100 Organization: virginmedia.com Lines: 38 Sender: news@iecc.com Approved: comp.compilers@iecc.com Message-ID: <17-10-011@comp.compilers> References: <17-10-001@comp.compilers> <17-10-004@comp.compilers> <17-10-009@comp.compilers> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Info: gal.iecc.com; posting-host="news.iecc.com:2001:470:1f07:1126:0:676f:7373:6970"; logging-data="2500"; mail-complaints-to="abuse@iecc.com" Keywords: code, optimize Posted-Date: 07 Oct 2017 14:37:42 EDT X-submission-address: compilers@iecc.com X-moderator-address: compilers-request@iecc.com X-FAQ-and-archives: http://compilers.iecc.com Content-Language: en-GB Xref: csiph.com comp.compilers:1925 On 07/10/2017 17:55, George Neuner wrote: >> Am 05.10.2017 um 18:29 schrieb Robert Jacobson: >>> I am trying to wrap my mind around the issue of dynamic dispatch in the >>> context of switching on opcode in a bytecode interpreter ... > Unfortunately, on modern CPUs, *all* branches are predicted. An > indirect jump through the table will mispredict virtually every time. > The same will be true of an indirect jump via register based address. > > The best you can do with an interpreter is to have all the code in L1 > code cache. As soon as you have to go to L2 (which typically is > shared between code and data) or deeper, you risk taking large hits if > the code is not resident. > > comp.lang.asm.x86 has seen extensive discussions of mispredict > problems in interpreters and JIT compiled code. The conclusions there > are applicable to most CPU architectures. I tried an experiment a few years ago, where the byte-code for a test program was expanded into a sequence of instructions in a statically compiled language (or it might have been done at run-time; I can't remember). Each byte-code was represented by some mix of function call, or some inline code. This would have been expected to benefit by eliminating dispatch overheads (it just steps into the next lot of code like an ordinary program), and also by having dedicated code for some things that were otherwise a parameter in a generic byte-code instruction. But in fact the results weren't that great at all; most normal dispatchers were actually faster! Perhaps it was affected by having to fill up the instruction cache with 1000 copies of the same PUSH code sequence, instead of re-using the same single copy when running the byte-code dispatcher. -- bartc