Mill Computing, Inc. Forums The Mill Architecture Living without a Stack

  • Author
  • Veedrac
    Post count: 25
    #1974 |

    One of my favourite features of the Mill is that it seems to give you a super-fast pseudo-stack for free, inside the belt. Naturally, one considers doing away with the real stack as much as possible. For C, it’s rather obvious when this fails. Either you have more parameters than call can accept, you want to call with large composites or you need to take the address of your stack location.

    This does raise the question of how many elements you can pass to call. I found you saying elsewhere that this is member-dependent and basically the whole belt on most models. Given that it’s model-dependent, how does the specializer deal with calls with more arguments than the number of belt positions or calls with more arguments than supported?

    What caught my attention most is how none of the failure cases apply to Java. Ignoring fancy inlining, Java almost always heap allocates and doesn’t take pointers to stack variables. It seems almost like Java doesn’t need a stack on the Mill at all.

    However, the GC will create problems if it runs whilst there are roots on the belt. This means that every call is going to have to save all pointers to the stack… and then load them back out. And Java makes a lot of calls. I don’t know how one should best tackle this, but it seems like the cost is quite dear – you basically can’t chain calls with anything or use belt pointers from across calls as-is. Of course, that leaves you no worse off than a register machine but it seems tantalizingly close to being way better. Thoughts?

    • This topic was modified 7 years ago by  Veedrac.
  • Ivan Godard
    Post count: 629

    Yes, we expect that for static languages (C, COBOL etc) only excess and overlarge arguments, and locals with address taken, will reside on the data stack.

    In general we expect that a GC language will treat the belt as it does registers in a general-register machine: the residence of temporaries, including pointer temporaries. A GC event must identify these as roots. As with registers, one can map each instruction to table entries that identify roots, in the registers or on the belt. However, mapping every instruction gives a lot of table. Some GC systems instead have arrangements by which a GC event can only be triggered at specific points in execution, and maintain maps only for those points; that would also work on a Mill.

    Another possibility is for the GC to assume that anything that looks like a pointer is a pointer, and to treat all such as roots, accepting the occasional false positive. This approach works better on a Mill than a conventional, because pointer-sized data can be distinguished from other data by the width tag on every Mill operand. In addition, if only some combinations of the GC-control bits in a pointer are valid then the root finder can rule out candidates with invalid control fields.

    Note that the root-finder must also examine the scratchpad, and also the saved belts and scratchpad of frames further down the stack.

You must be logged in to reply to this topic.