Thank you for the explanation Rasmus. I tried (.foo ^Bar bar) and it
behaved exactly like (.foo (new Bar)) as you suggested.

So method invocation via reflection works, while invokevirtual does
not. As a sanity check I compared the bytecode of an AOT'd (working)
invocation of a method compiled and loaded before the JRebel reload
with a failing invocation after the reload. As expected they both
contain the exact same code:

  71c71
  <    10:      invokevirtual   #32; //Method 
foo/core/Bar.sayAhoj:()Ljava/lang/String;
  ---
  >    10:      invokevirtual   #32; //Method
foo/core/Bar.sayHello:()Ljava/lang/String;

The only difference I've been able to spot so far between the vanilla
method invocations (pre JRebel reloading) and the freshly added and
reloaded method invocations is in the object expression:

  InstanceMethodExpr for sayAhoj (newly reloaded JRebel, broken):
  method.clazz = class foo.core.Bar$$M$8e38ee87
  method.parameterTypes = java.lang.Class[1], [0] = [class foo.core.Bar]

  InstanceMethodExpr for sayHello (loaded initially, working):
  method.clazz = class foo.core.Bar
  method.parameterTypes = java.lang.Class[0]

This mostly makes sense since I'm assuming JRebel has to load a new
class and perform some behind the scenes magic to write it up to look
like the original. The extra parameter looks like the [this] from the
function. I tried setting these values to match the sayHello versions,
but it didn't help.

Those differences don't seem to actually matter since at the end of
the day the compiled bytecode is twi identical invokevirtuals.

Rob



On Sun, Jan 16, 2011 at 7:22 PM, Rasmus Svensson <r...@lysator.liu.se> wrote:
> 2011/1/16 Robert Campbell <rrc...@gmail.com>:
>> The second form - (.foo bar), expanded to (. bar foo) - eventually
>> calls Reflector.invokeNoArgInstanceMember.
>
> For that form, the clojure compiler cannot infer the type of bar, and
> does not know which exact method (class + type signature) .foo
> represents. Due to this, a runtime lookup that uses the reflector is
> inserted, since a method invocation in java byte code must be
> statically typed (at least currently).
>
>> The first form - (.foo (new Bar)), expanded to (. (new Bar) foo) -
>> doesn't seem to use any Reflector _invocation_ methods. I also added a
>> breakpoint to java.lang.reflect.Method.invoke() and it never hits that
>> breakpoint.
>
> This is because the compiler knows the type of the arg to .foo, and
> can emit bytecode for a plain old (statically typed) method
> invocation.
>
> Since reflective method invocations are pretty slow, you often try to
> add type hints so that it can be avoided: (.foo ^Bar bar) The
> generated bytecode for this method invocation should be very similar
> (if not identical) to the bytecode for (.foo (new Bar))
>
> // raek
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to