Are local blobs passed by value (copy) or by reference

If I include a locally created blob as parameter in a function call, directly or as an entry in a table, does it get passed by reference or is it copied into a new blob ? Example

	local payload = PcUart.readblob(len);
    calccrc = crc16(payload,0,len);
    ...
    gEvents.SetEvent("HostCmd",{cmd = CmdId, status = "ok",payload = payload});

couple of questions

  • is the function call passing the reference of the blob, or is it copying the blob automatically into a new blob (by value)?

  • if by reference, does the GC destroy the blob as it goes out of scope (hence if the payload parameter is finally consumed it doesn’t necessary exist anymore)

  • if by value, what is the scope of that new blob (i.e. when does it get GCed) ?

  • is it needed to do an explicit copy e.g.

      local payload = PcUart.readblob(len);
      calccrc = crc16(payload,0,len);
      ...    
      gEvents.SetEvent("HostCmd",{cmd = CmdId, status = "ok",payload = payload.readblob(len)});
    
  • also here would be good to understand the lifecycle of the newly created blob through readblob() (when does it get GCed ?)

The latter is what I’m doing right now, but trying to avoid needless copying of data, as the blobs could become pretty large, but I’ve been bitten before by blobs being GCed before they could be consumed.

Squirrel scalar types are passed by value: int, float. Other types are always passed by reference: table, class, instance, array, blob, string. (But because strings are immutable, it’s not possible to write code that can tell that strings are passed by-reference and not by-value.)

The GC always destroys blobs (and other by-reference types) when there are no further references to them. In your first code snippet, there will for a while be two references to the blob: one in payload, one in the new table passed to SetEvent. If SetEvent copies that table or blob, a reference will be retained; otherwise, when SetEvent returns, the reference count goes down to one, and when the calling function returns, payload will go out of scope, the reference count will go to zero, and the blob will be GC’d.

Note that if SetEvent keeps hold of the table or blob, then – because there are two references to the same blob – any changes made to it in the outer function (by modifying payload) will also affect the stored copy. To avoid that – for example, if you want to append more UART data to the same blob, without changing the one that SetEvent was keeping hold of – you’d need to make a copy, like in your second code snippet.

Peter