Re: STG to JavaScript translation

I still have some questions regarding the GHC internals. There is a description of STG language in the "Making a Fast Curry: Push/Enter vs. Eval/Apply for Higher-oder Languages" (2004) by Simon Marlow and Simon Peyton Jones paper. In this description the constructor application (CONS closure) can only appear on the right hand side of the bindings. This is totally reasonable if "let" is the only construct that allocates objects. But in the GHC's StgSyn.hs any expression can be constructor application. How does constructor applications are compiled? Are they implicitly transformed to let? For example: f = let g = (THUNK h x) in (CONS g y) Is this exactly the same as (right variant following the paper) f = let g = (THUNK h x) in let freshvar = (CONS g y) in freshvar ? And the second question is how does constructor tag is passed to case when non-vector return is used? In register? In constructor closure? Are there any cases when closure is not build for constructor application? What the case binder is bound to if there is no closure for constructor application? -- vir http://vir.comtv.ru/

I still have some questions regarding the GHC internals. There is a description of STG language in the "Making a Fast Curry: Push/Enter vs. Eval/Apply for Higher-oder Languages" (2004) by Simon Marlow and Simon Peyton Jones paper. In this description the constructor application (CONS closure) can only appear on the right hand side of the bindings. This is totally reasonable if "let" is the only construct that allocates objects. But in the GHC's StgSyn.hs any expression can be constructor application. How does constructor applications are compiled? Are they implicitly transformed to let? For example: f = let g = (THUNK h x) in (CONS g y) Is this exactly the same as (right variant following the paper) f = let g = (THUNK h x) in let freshvar = (CONS g y) in freshvar ? And the second question is how does constructor tag is passed to case when non-vector return is used? In register? In constructor closure? Are there any cases when closure is not build for constructor application? What the case binder is bound to if there is no closure for constructor application? -- vir http://vir.comtv.ru/

On Thu, Sep 20, 2007 at 06:13:38AM +0400, Victor Nazarov wrote:
I still have some questions regarding the GHC internals. There is a description of STG language in the "Making a Fast Curry: Push/Enter vs. Eval/Apply for Higher-oder Languages" (2004) by Simon Marlow and Simon Peyton Jones paper. In this description the constructor application (CONS closure) can only appear on the right hand side of the bindings. This is totally reasonable if "let" is the only construct that allocates objects. But in the GHC's StgSyn.hs any expression can be constructor application. How does constructor applications are compiled? Are they implicitly transformed to let? For example:
f = let g = (THUNK h x) in (CONS g y)
Is this exactly the same as (right variant following the paper)
f = let g = (THUNK h x) in let freshvar = (CONS g y) in freshvar
?
And the second question is how does constructor tag is passed to case when non-vector return is used? In register? In constructor closure? Are there any cases when closure is not build for constructor application? What the case binder is bound to if there is no closure for constructor application?
The StgSyn type *declaration* allows this stuff. In actual use, it's always kept in, and expected to be in, A-normal form. The Simons have said that much of GHC is sadly written as though it was written in a dynamically typed language and then shoddily ported to Haskell; types do NOT describe ghc's data, to borrow one of Conor's catchphrases. (I can't find the original) Stefan

| > For example: | > | > f = | > let g = (THUNK h x) | > in (CONS g y) | > | > Is this exactly the same as (right variant following the paper) | > | > f = | > let g = (THUNK h x) | > in let freshvar = (CONS g y) | > in freshvar Yes that's right. The only problem with the latter is that it's not syntactically apparent that 'freshvar' is a value, and hence can be returned immediately rather than entered. But one can solve that by maintaining an environment telling static info about in-scope variables, which the code gen needs to do anyway. | > And the second question is how does constructor tag is passed to case | > when non-vector return is used? In register? In constructor closure? | > Are there any cases when closure is not build for constructor | > application? What the case binder is bound to if there is no closure | > for constructor application? Read our paper "Faster laziness using dynamic pointer tagging"! It's new (ICFP'07) http://research.microsoft.com/~simonpj/papers/ptr-tag/index.htm simon

Read our paper "Faster laziness using dynamic pointer tagging"! It's new (ICFP'07) http://research.microsoft.com/~simonpj/papers/ptr-tag/index.htm
simon
Cool, is it implemented in 2.8? Function tagging seems promising for performance. But it isn't implementable in JavaScript :) I have one more question. There are know calls (saturated applications) and unknown calls in STG. Is this information is encoded in GHC's STG datatype or should I maintain my own table of known functions. -- vir http://vir.comtv.ru/

| Cool, is it implemented in 2.8? Function tagging seems promising for | performance. But it isn't implementable in JavaScript :) I think it'll be in GHC 6.8. | I have one more question. There are know calls (saturated | applications) and unknown calls in STG. Is this information is encoded | in GHC's STG datatype or should I maintain my own table of known | functions. You need to keep your own table S

On 9/20/07, Simon Peyton-Jones
| Cool, is it implemented in 2.8? Function tagging seems promising for | performance. But it isn't implementable in JavaScript :)
I think it'll be in GHC 6.8.
I've meant 6.8 :) -- vir http://vir.comtv.ru/
participants (3)
-
Simon Peyton-Jones
-
Stefan O'Rear
-
Victor Nazarov