diff --git a/lib/xdrgen/generators/go.rb b/lib/xdrgen/generators/go.rb index c98b4f42c..1509ddec7 100644 --- a/lib/xdrgen/generators/go.rb +++ b/lib/xdrgen/generators/go.rb @@ -389,7 +389,16 @@ def render_typedef_encode_to_interface(out, typedef) name = name(typedef) type = typedef.declaration.type out.puts "// EncodeTo encodes this value using the Encoder." - out.puts "func (s #{name}) EncodeTo(e *xdr.Encoder) error {" + + if type.is_a?(AST::Typespecs::Opaque) && type.fixed? + # Implement EncodeTo by pointer in fixed opaque types (arrays) + # otherwise (if called by value), Go will make a heap allocation + # for every by-value call since the copy required by the call + # tends to escape the stack due to the large array sizes. + out.puts "func (s *#{name}) EncodeTo(e *xdr.Encoder) error {" + else + out.puts "func (s #{name}) EncodeTo(e *xdr.Encoder) error {" + end out.puts " var err error" render_encode_to_body(out, "s", type, self_encode: true) out.puts " return nil" @@ -461,7 +470,17 @@ def render_encode_to_body(out, var, type, self_encode:) out.puts " if #{var} != nil {" var = "(*#{var})" end - var = "#{name type}(#{var})" if self_encode + if self_encode + newvar = "#{name type}(#{var})" + if type.resolved_type.is_a?(AST::Definitions::Typedef) + declared_type = type.resolved_type.declaration.type + # Fixed opaque types implement EncodeTo by pointer + if declared_type.is_a?(AST::Typespecs::Opaque) && declared_type.fixed? + newvar = "(*#{name type})(&#{var})" + end + end + var = newvar + end out.puts " err = #{var}.EncodeTo(e)" if optional_within out.puts " }"