Skip to content

Latest commit

 

History

History
57 lines (37 loc) · 2.51 KB

Method Dispatch - Low Level Detail.md

File metadata and controls

57 lines (37 loc) · 2.51 KB

This is what I understand happens at low-level when you use interface parameters/vars

###Golang Interfaces###

A golang-Interface is a class with no fields and ONLY VIRTUAL methods.

type J interface 
   to-string() ( string )
   dosomea ( x, J )
   dosomeb ( x, k ) (J) 
   dosomec ( x, a string) ( int )

If a struct implements such methods, it “satisfies the interface”.

You can create a “var of type interface” or declare a function param of type interface.

  • a var x of type interface is NIL until a concrete-type its assigned to it.
  • a var x of type interface is internally just 2 pointers. One pointer to an ITable and other to the concrete value stored.

so var x J-interface internally is:

c-struct interface-var
	ITable            *ITable
	concrete-value    any_union

an ITable is:

c-struct ITable
       concrete-type  *type
   	   interface-type *interface
       jmp-table[]    *function

When a concrete type is assigned to a interface-var, golang *creates a jmp-method table on the fly (and caches it). There is a jmp-table for each combination of J-Interface * concrete-type-implementing-J-interface

Let’s assume z is struct Z and there is a bunch of functions as func dosomex ( z ){...} so that struct Z implements interface J

When you do:

 var x J-interface  = z

golang constructs the ITable on the fly. The J-interface has 4 methods, so it needs to calculate x.ITable. Golang will search the method “to-string” of struct Z and put it in ITable.jmp-table[0], then look for “dosomea (struct Z)” and put it in ITable.jmp-table[1] and so on. Then it will store ITable->concrete = &struct-Z, and X.itable->interface= &interface-J”.

x, being an interface type, has two 32bit pointers, the first will point to the newly created ITable “&struct-Z, &interface-J, jmp-table[0...3]” (where the concrete-type-info is stored) and the second points to the concrete-value (in this case a copy of z)

then…

for n:=1; n++<100 {
     print( x.dosomea(x))
}

the call x.dosomea() is:

  • x is var type interface -> struct Z, Interface J
  • so x.ITable -> “struct-Z,interface-J,jmp-table[0..3]”
  • x.dosomea() gets translated to call [x.ITable.jmps[1]] (since “dosomea” => index 1)
  • this is a memory fetch and an indirect-call.
  • interface values are passed by value, so x.ITable and x.value are always available in the stack. To know the concrete type stored in x.value golang must dereference c.ITable->concrete-type.