From: Duncan C. <du...@co...> - 2004-05-03 22:16:34
|
All, Following some discussion on the ghc-users list about the safe use of unsafeCoerce, I've got a patch which uses unsafeCoerce in the implementation of the class hierarchy functions. It removes the space overhead of the class dictionary and the runtime overhead in the casting functions. According to the ghc developers it is safe because newtypes have the same runtime representation as the types they wrap. I've tested it on our various demos (including a larger demo I'm working on) without problem. With this change, the class hierarchy should have zero runtime overhead. The change is best explained by example. At the moment a class declaration looks like so: class WidgetClass o => ContainerClass o toContainer :: ContainerClass o => o -> Container toContainer = fromGObject . toGObject fromContainer :: ContainerClass o => Container -> o fromContainer = fromGObject . toGObject instance ContainerClass Container instance WidgetClass Container instance ObjectClass Container instance GObjectClass Container where toGObject = mkGObject.castForeignPtr.unContainer fromGObject = mkContainer.castForeignPtr.unGObject I propose changing that to: class WidgetClass o => ContainerClass o toContainer :: ContainerClass o => o -> Container toContainer = unsafeCoerce# fromContainer :: ContainerClass o => Container -> o fromContainer = unsafeCoerce# instance ContainerClass Container instance WidgetClass Container instance ObjectClass Container instance GObjectClass Container So, you can see that the to* from* functions are just casting pointers, except that the pointers are wrapped in newtypes. The existing mechanism uses class methods to cast away the newtype. My proposal is to cast directly (which is safe because newtypes do not change representation and casting pointer using unsafeCoerce is also safe). The external types have not changed to the use of unsafeCoerce# is not exposed to the user. I've not attached the patch because it is not terribly informative. Ask if you're interested. Duncan |
From: Axel S. <A....@ke...> - 2004-05-05 07:25:46
|
On 4 May 2004, at 00:16, Duncan Coutts wrote: > So, you can see that the to* from* functions are just casting pointers, > except that the pointers are wrapped in newtypes. The existing > mechanism > uses class methods to cast away the newtype. My proposal is to cast > directly (which is safe because newtypes do not change representation > and casting pointer using unsafeCoerce is also safe). The external > types > have not changed to the use of unsafeCoerce# is not exposed to the > user. To actually get rid of class contexts, we would have to take the to* and from* functions out of the class: toContainer :: ObjectClass o => o -> Container toContainer = unsafeCoerce I guess that GHC will remove the whole class context in this case (since it is not used). This would be a (small) gain if GHC cannot inline these functions when they are passed as a dictionary (I can imagine that GHC can never do that, but I never looked at the core produced). If all the changes are restricted to Hierarchy.chs, then it's alright to commit since it's easily reverted. Axel. |
From: Duncan C. <du...@co...> - 2004-05-05 16:00:48
|
On Wed, 2004-05-05 at 08:28, Axel Simon wrote: > To actually get rid of class contexts, we would have to take the to* > and from* functions out of the class: > > toContainer :: ObjectClass o => o -> Container > toContainer = unsafeCoerce Exactly. There are now no methods in the GObject (or any other) class. Thats what the patch does. > I guess that GHC will remove the whole class context in this case > (since it is not used). This would be a (small) gain if GHC cannot > inline these functions when they are passed as a dictionary (I can > imagine that GHC can never do that, but I never looked at the core > produced). > > If all the changes are restricted to Hierarchy.chs, then it's alright > to commit since it's easily reverted. Ok. Duncan |