Path: csiph.com!usenet.pasdenom.info!aioe.org!.POSTED!not-for-mail From: "Rod Pemberton" Newsgroups: comp.lang.forth Subject: Re: Epic Fail Date: Thu, 01 May 2014 16:08:13 -0400 Organization: Aioe.org NNTP Server Lines: 175 Message-ID: References: NNTP-Posting-Host: CNsg4fVcCsvs3UaOgZtQCw.user.speranza.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit X-Complaints-To: abuse@aioe.org User-Agent: Opera Mail/12.16 (Linux) X-Notice: Filtered by postfilter v. 0.8.2 Xref: csiph.com comp.lang.forth:30044 On Thu, 01 May 2014 05:04:07 -0400, Andrew Haley wrote: > Rod Pemberton wrote: >> On Wed, 30 Apr 2014 07:45:47 -0400, Andrew Haley >> wrote: >>> We need to talk about real examples. >>> >>> The problem is that if you have a Forth word like, say: >>> >>> : foo 9 * ; >>> >>> you could implement this in the JVM as a method: >>> >>> public static long bar(long n) { >>> return n * 9; >>> } >>> >>> [snip IR and assembly] >>> >>> but in Forth we have a stack that is accessed by every word, >>> and can be left unbalanced, so we have to expose it as a >>> real array: >>> >>> public static int foo(long[] stack, int sp) { >>> stack[sp] *= 9; >>> return sp; >>> } >>> >>> [snip IR and assembly] >>> >> >> Is there any reason to return 'sp'? You didn't modify it... > > Sure, but the caller can't know that. The point was the function should be smaller if SP doesn't need to be returned. There is code generated for the return if it's not returned. Also, returning SP seems to have no purpose here. So, why would someone set SP to the return value of this function? Can they read the code for this function and see passing SP does nothing? >> Why didn't you do something like this?: >> >> public static int foo(long[] stack, int sp) >> { >> long n; >> n=stack[sp]; >> n*=9; >> stack[sp]=n; >> return n; >> } >> >> I.e., wouldn't the local variable 'n' _allow_ the compiler >> to use a register thereby possibly reducing the code somewhat? > > It's using a register. "It's" refers to what exactly? 1) my locally declared 'long n' in this example 2) your 'long n' parameter in your first example 3) something else #1 would be a confirmation of what I said. #2 would indicate the Java "compiler" passes parameters in registers >> I.e., in C, you might've chosen to pass a pointer to 'sp' >> in the parameter list instead. That would eliminate the >> following line in the main code, replacing it with the next: >> >> sp=foo(stack,sp); /* eliminated */ >> foo(stack,&sp); /* replacement */ Also, you could've just passed a single pointer instead of a pointer and offset, e.g., foo(&stack[sp]); /* only a pointer */ >> [replacement suggestion above] > > In general this would be less efficient, In C, or in the Java "compiler" and/or Java VM? (Don't say C.) For the replacement in C, the pointer is passed in for C. Nothing is passed out for SP. For the original in C, a value for SP is passed in on the stack, and a return value is passed out in register thats stored in SP in memory. (*) (*) conditional to constraints discussed below. > because SP is not passed in a register. If SP is passed *in* by register by the Java "compiler" for the SP passed as a parameter in your example, that's excellent! It would also be very surprising... Obviously, the return value as SP is passed *out* by register. I.e., I think you need to clarify which SP you were discussing for your example when you said: "SP is not passed in a register". In? Out? Both? C compilers almost always pass parameters on a stack. There are numerous important reasons for this. Of course, some C compilers do allow you to pass parameters in registers, if there won't be a register starvation issue. Some of the reasons C uses a stack for parameter passing: -improve the locality of reference for data -index data off of a single pointer to the stack frame -provide memory addesses for data, i.e., for the & address-of operator -prevent register starvation issues which can occur if parameters are passed in registers >> Also, can you make 'stack' and 'sp' have file scope, >> be global, so you don't need to pass them? > > No, because you'd have to write sp back to global > memory after every operation rather than keeping > it in a register. Could you explain how the Java VM keeps SP in a register? If Java VM works like C, you're reading SP from memory to pass it to a procedure. When it's passed to a procedure, it's saved on a stack. When SP is updated, it's written back to memory. Does Java "compiler" have a "register" keyword? If not, is this placement of SP into a register some automatic optimization? Or, is it only for the return value? I readily accept that returns in C are passed back in a register. If SP is a variable, I'd expect SP to be stored in memory somewhere. So, a memory fetch and store will be needed somewhere to use and update it. >> That's probably adding a small >> amount of parameter passing code. I.e., 'void' parameters, >> at least in C, eliminates some passing overhead: >> >> public static void foo(void) >> { >> long n; >> n=stack[sp]; >> n*=9; >> stack[sp]=n; >> } > > How does this help? Surely there is just as much overhead for > accessing a global variable as passing a parameter in a register. If the Java "compiler" for that code works differently from C, I don't know if it helps any. If the Java "compiler" works the same as or similar to a C compiler, then the two voids eliminate most or all of the function's epilog and prolog. The 'long n' being an 'auto' - a procedure local variable - should be optimized by the C compiler to use a register, or a 'register' keyword in C will do that. The local eliminates complicated instructions against memory locations which would be generated if multiplying stack[sp] (in memory) by nine directly. Instead, simpler register multiply is generated. At least, that's how C for a variety of C compilers, including GNU C, typically work on x86. Rod Pemberton