4 ms·
Whenever you do: v := interfaceType(concreteTypeValue) in Go, what you're actually doing on a lower level is: dataPtr := &concreteTypeValue typePtr :=
by ainar-g 2y ago
Whenever you do:
v := interfaceType(concreteTypeValue)
in Go, what you're actually doing on a lower level is:
dataPtr := &concreteTypeValue
typePtr := typeData[concreteType]()
v := interfaceData{
data: dataPtr,
typ: typePtr,
}
The first line here is the allocation, since (at least, the way I recall the rule) in Go pointers never point to values on the stack, so concreteTypeValue must be allocated on the heap. The rule about pointers not pointing to the stack is there to make it easier for goroutine stacks to grow dynamically.
See https://go.dev/doc/faq#stack_or_heap https://go.dev/doc/faq#stack_or_heap.
- foldr 2y ago>in Go pointers never point to values on the stack This is only the case for pointers that the compiler can't prove not to escape: >In the current compilers, if a variable has its address taken, that variable is a candidate for allocation on the heap. However, a basic escape analysis recognizes some cases when such variables will not live past the return from the function and can reside on the stack.
- ainar-g 2y agoThat could be true, but I've done a few optimizations of allocations in Go code, and I don't recall pointers to stack values ever being optimized (unless the entire branch is removed, of course). If anyone could provide an example of the code that does pointer operations yet doesn't cause allocations, I'd appreciate it!
- foldr 2y agoSure, here you go: https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:go,selection:(endColumn:1,endLineNumber:19,positionColumn:1,positionLineNumber:19,selectionStartColumn:1,selectionStartLineNumber:19,startColumn:1,startLineNumber:19),source:'//+Type+your+code+here,+or+load+an+example.%0A//+Your+function+name+should+start+with+a+capital+letter.%0Apackage+main%0A%0Aimport+%22fmt%22%0A%0A//+example+to+show+what+an+allocation+looks+like+in+the+generated+asm%0Afunc+foo()+*int+%7B%0A++++return+new(int)%0A%7D%0A%0A//+no+allocation+here%0Afunc+main()+%7B%0A++++x+:%3D+7%0A++++px+:%3D+%26x%0A++++*px+%3D+8%0A++++fmt.Printf(%22x:+%25v%5Cn%22,+x)%0A%7D%0A'),l:'5',n:'1',o:'Go+source+%231',t:'0')),k:37.5,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:gl1221,filters:(b:1,binary:'1',binaryObject:'1',commentOnly:1,debugCalls:'1',demangle:'0',directives:1,execute:1,intel:1,libraryCode:'0',trim:'1',verboseDemangling:'0'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:go,libs:!(),options:'',overrides:!(),selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:'5',n:'0',o:'+x86-64+gc+1.22.1+(Editor+%231)',t:'0')),l:'4',m:50,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(fontScale:14,fontUsePx:'0',j:1,wrap:'1'),l:'5',n:'0',o:'Output+of+x86-64+gc+1.22.1+(Compiler+%231)',t:'0')),l:'4',m:50,n:'0',o:'',s:0,t:'0')),k:37.5,l:'3',n:'0',o:'',t:'0'),(g:!((h:executor,i:(argsPanelShown:'1',compilationPanelShown:'0',compiler:gl1221,compilerName:'',compilerOutShown:'1',execArgs:'',execStdin:'',fontScale:14,fontUsePx:'0',j:2,lang:go,libs:!(),options:'',overrides:!(),runtimeTools:!(),source:1,stdinPanelShown:'1',wrap:'1'),l:'5',n:'0',o:'Executor+x86-64+gc+1.22.1+(Go,+Editor+%231)',t:'0')),k:25,l:'4',m:100,n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4 https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename...
- ainar-g 2y agoAh, so extremely localized uses of pointers, got it, thanks.
- foldr 2y agoMore or less, yes, but it doesn't have to be extremely local. Here's a variant of the example that introduces a function call boundary: https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:go,selection:(endColumn:1,endLineNumber:19,positionColumn:1,positionLineNumber:19,selectionStartColumn:1,selectionStartLineNumber:19,startColumn:1,startLineNumber:19),source:'//+Type+your+code+here,+or+load+an+example.%0A//+Your+function+name+should+start+with+a+capital+letter.%0Apackage+main%0A%0Aimport+%22fmt%22%0A%0A//+example+to+show+what+an+allocation+looks+like+in+the+generated+asm%0Afunc+foo()+*int+%7B%0A++++return+new(int)%0A%7D%0A%0A//+no+allocation+here%0Afunc+main()+%7B%0A++++x+:%3D+7%0A++++px+:%3D+%26x%0A++++*px+%3D+8%0A++++fmt.Printf(%22x:+%25v%5Cn%22,+x)%0A%7D%0A'),l:'5',n:'1',o:'Go+source+%231',t:'0')),k:37.5,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:gl1221,filters:(b:1,binary:'1',binaryObject:'1',commentOnly:1,debugCalls:'1',demangle:'0',directives:1,execute:1,intel:1,libraryCode:'0',trim:'1',verboseDemangling:'0'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:go,libs:!(),options:'',overrides:!(),selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:'5',n:'0',o:'+x86-64+gc+1.22.1+(Editor+%231)',t:'0')),l:'4',m:50,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(fontScale:14,fontUsePx:'0',j:1,wrap:'1'),l:'5',n:'0',o:'Output+of+x86-64+gc+1.22.1+(Compiler+%231)',t:'0')),l:'4',m:50,n:'0',o:'',s:0,t:'0')),k:37.5,l:'3',n:'0',o:'',t:'0'),(g:!((h:executor,i:(argsPanelShown:'1',compilationPanelShown:'0',compiler:gl1221,compilerName:'',compilerOutShown:'1',execArgs:'',execStdin:'',fontScale:14,fontUsePx:'0',j:2,lang:go,libs:!(),options:'',overrides:!(),runtimeTools:!(),source:1,stdinPanelShown:'1',wrap:'1'),l:'5',n:'0',o:'Executor+x86-64+gc+1.22.1+(Go,+Editor+%231)',t:'0')),k:25,l:'4',m:100,n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4 https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename...
- foldr 2y agoOops, copy paste error there. Here is the example with the function call boundary: https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:go,selection:(endColumn:1,endLineNumber:23,positionColumn:1,positionLineNumber:23,selectionStartColumn:1,selectionStartLineNumber:23,startColumn:1,startLineNumber:23),source:'//+Type+your+code+here,+or+load+an+example.%0A//+Your+function+name+should+start+with+a+capital+letter.%0Apackage+main%0A%0Aimport+%22fmt%22%0A%0A//+example+to+show+what+an+allocation+looks+like+in+the+generated+asm%0Afunc+foo()+*int+%7B%0A++++return+new(int)%0A%7D%0A%0Afunc+setInt(x+*int,+y+int)+%7B%0A++++*x+%3D+y%0A%7D%0A%0A//+no+allocation+here%0Afunc+main()+%7B%0A++++x+:%3D+7%0A++++px+:%3D+%26x%0A++++setInt(px,+8)%0A++++fmt.Printf(%22x:+%25v%5Cn%22,+x)%0A%7D%0A'),l:'5',n:'1',o:'Go+source+%231',t:'0')),k:37.5,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:gl1221,filters:(b:1,binary:'1',binaryObject:'1',commentOnly:1,debugCalls:'1',demangle:'0',directives:1,execute:1,intel:1,libraryCode:'0',trim:'1',verboseDemangling:'0'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:go,libs:!(),options:'',overrides:!(),selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:'5',n:'0',o:'+x86-64+gc+1.22.1+(Editor+%231)',t:'0')),l:'4',m:50,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(fontScale:14,fontUsePx:'0',j:1,wrap:'1'),l:'5',n:'0',o:'Output+of+x86-64+gc+1.22.1+(Compiler+%231)',t:'0')),l:'4',m:50,n:'0',o:'',s:0,t:'0')),k:37.5,l:'3',n:'0',o:'',t:'0'),(g:!((h:executor,i:(argsPanelShown:'1',compilationPanelShown:'0',compiler:gl1221,compilerName:'',compilerOutShown:'1',execArgs:'',execStdin:'',fontScale:14,fontUsePx:'0',j:2,lang:go,libs:!(),options:'',overrides:!(),runtimeTools:!(),source:1,stdinPanelShown:'1',wrap:'1'),l:'5',n:'0',o:'Executor+x86-64+gc+1.22.1+(Go,+Editor+%231)',t:'0')),k:25,l:'4',m:100,n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4 https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename...