Skip to content

Instantly share code, notes, and snippets.

@mraleph
Created March 21, 2018 23:32
Show Gist options
  • Save mraleph/a8f49a4268ce5853176252dc1a826150 to your computer and use it in GitHub Desktop.
Save mraleph/a8f49a4268ce5853176252dc1a826150 to your computer and use it in GitHub Desktop.

Background: How we handle mismatched closure invocations

Closures (unlike other methods) can be invoked with mismatched arguments, which then should result in Object.noSuchMethod invocation.

We implement it by tail-calling to the CallClosureNoSuchMethod stub if we discover an arity mismatch or a unmatched named argument. The stub gets original arguments and original argument descriptor and simply redirects to runtime function InvokeClosureNoSuchMethod which does all the heavy lifting related to constructing Invocation and invoking appropriate noSuchMethod.

How to adapt this for our needs

Given code like:

class Mock {
  noSuchMethod(Invocation i) {
    // ...
  }
}

class A extends Mock {
  void foo(...);
}

we should build (pseudo-code)

class A extends Mock {
  void foo(...) {
    tail-call RedirectToNoSuchMethodStub
  }
}

The stub RedirectToNoSuchMethodStub should be more or less the copy of CallClosureNoSuchMethod which then invokes RedirectToNoSuchMethod runtime function, which is also more or less a copy of InvokeClosureNoSuchMethod just without any closure specific processing.

I think most of the code can be shared and reused - there is very little closure specific in these helpers.

@sjindel-google
Copy link

Tail-calling NSM wont' work because we have to type-check the result of the NSM invocation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment