Re: Exotic classes

2019-05-23 Thread Steven Stewart-Gallus
Figured out something bizarre about combining lambdas just the other day.

Code like

static  EqualsSupport makeEquals(Set> getters) {
   EqualsSupport equals = (a, b) -> true;
   for (var getter : getters) {
  if (getter instanceof ObjectGetter) {
 var g = (ObjectGetter) getter;
 var oldEquals = equals;
 equals = (a, b) -> oldEquals.apply(a, b) && Object.equals(g.get(a), 
g.get(b)));
  } else if (getter instanceof IntGetter) {
 var g = (IntGetter) getter;
 var oldEquals = equals;
 equals = (a, b) -> oldEquals.apply(a, b) && g.get(a) == g.get(b));
  }  else {
 // etc...
  }
   }
   return equals;
}

just doesn't work because the VM thinks it is recursive (it is the same 
method on the lambda just not the same lambda).

So what you need to is use MethodHandles combinators to patch the lambdas 
together. Oddly, for a sequence of lambdas I've found the loop one works 
well.

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/mechanical-sympathy/ec9120ca-f3b7-4c9d-90ef-4dacf2e5f810%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-05-16 Thread Steven Stewart-Gallus
Hi,

For a long while, I couldn't think of what to reply with.
I just don't feel the problem of grouping fields together deserves to 
distort the API that much.
I guess part of the problem is Java doesn't support a syntax for field 
references (even though VarHandleDesc are already implemented.)
It occurs to me that the hash and equals don't really need VarHandle 
references.
They really just need getters and don't actually need fields.

There is no reason you couldn't do a hash and equality on generated 
"properties."
Although you'd have to avoid boxing problems.

interface Getter {
}
interface ObjectGetter {
   public T get(R record);

}
interface ValueGetter extends Getter {
}
interface IntGetter extends Getter {
   public int get(R record);
}

private static final Set> GETTERS = Set.of((s) -> sx, (s) 
-> s.y);

private static final EqualsSupport EQUALS = EqualsSupport.of(GETTERS)
private static final HashsSupport HASHER = HashSupport.of(GETTERS);
private static final Stringer TOSTRING = Stringer.of(GETTERS);
// etc..

I think it might be possible to get working without explicit indy

static  EqualsSupport makeEquals(Set> getters) {
   EqualsSupport equals = (a, b) -> true;
   for (var getter : getters) {
  if (getter instanceof ObjectGetter) {
 var g = (ObjectGetter) getter;
 var oldEquals = equals;
 equals = (a, b) -> oldEquals.apply(a, b) && Object.equals(g.get(a), 
g.get(b)));
  } else if (getter instanceof IntGetter) {
 var g = (IntGetter) getter;
 var oldEquals = equals;
 equals = (a, b) -> oldEquals.apply(a, b) && g.get(a) == g.get(b));
  } else {
 // etc...
  }
   }
   return equals;
}

I'm just not sure this would properly inline everything.

But this is starting to get into bikeshedding.

Thank you,
Steven

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/mechanical-sympathy/4cc49b86-cec6-49a5-a200-2836e026a835%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-04-27 Thread Remi Forax
> De: "Steven Stewart-Gallus" 
> À: "mechanical-sympathy" 
> Envoyé: Samedi 27 Avril 2019 00:15:07
> Objet: Re: Exotic classes

> It seems to me you have to do a lot of hacky stuff to get around the "ugly" 
> API
> as you call it.

> Maybe it'd be better to separate out the ObjectSupport class into two separate
> classes, a HasherSupport class and an EqualsSupport class.

> interface HashSupport < T > {
> public static < T > HashSupport < T > of ( Lookup lookup , String ... fields 
> ) {
> var mh = createMh ( lookup , fields );
> return ( obj ) -> {
> mh . invokeExact ( obj );
> };
> }
> int hashCode ( T obj );
> }

> and similar for EqualsSupport.

One usual issue with people hand writing equals and hashCode is that they 
doesn't play well together because there are not using the same set of fields, 
grouping together the implementation of equals and hashCode alleviate this 
issue. 

> I feel like ObjectSupport is a bit nebulous and open ended and you'd 
> inevitably
> end up needing more support methods such as a toString method.

yes, toString and perhaps compare, but i want to get right equals and hashCode 
first. 

Rémi 

> On Friday, April 26, 2019 at 8:13:17 AM UTC-7, Remi Forax wrote:
>>> De: "Steven Stewart-Gallus" < [ javascript-blocked: | 
>>> stevensele...@gmail.com ]
>>> >
>>> À: "mechanical-sympathy" < [ javascript-blocked: | 
>>> mechanica...@googlegroups.com
>>> ] >
>>> Envoyé: Vendredi 26 Avril 2019 01:51:47
>>> Objet: Re: Exotic classes
>> Hi Steven,
>> thanks for spending some time on this,

>>> 1. Why
>>> public abstract class ObjectSupport {
>>> public abstract boolean equals ( Object self , Object other );
>>> public abstract int hashCode ();
>>> public static ObjectSupport of ( Lookup lookup , String ... fields ) {
>>> // impl details
>>> }
>>> // impl details
>>> }

>>> and not something like?
>>> interface ObjectSupport < T > {
>>> public boolean equals ( T self , T other );
>>> public int hashCode ( T obj );
>>> public static < T , U extends ObjectSupport < T >> T of ( Lookup lookup , 
>>> Class
>>> < U > iface , Class < T > obj ) {
>>> // impl details
>>> }
>>> }
>>> @Retention ( RetentionPolicy . RUNTIME )
>>> @Target ( ElementType . FIELD )
>>> @interface ObjectSupportField {
>>> }

>> There are three questions, why not use an interface, why not use generics to
>> make the API more typesafe and why not use an annotation to mark the fields,
>> (1), it should be an interface, yes :
>> (2), yes, the API can be more typesafe, i've implemented that. BTW, the 
>> correct
>> type of equals() if generified is (T, Object), because you can call
>> equals(Person, String), it should return false.
>> (3),the API you propose can be built on top of the existing one, that's why
>> there is an overload of ObjectSupport.of() that takes a function as third
>> parameter
>> see [
>> https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupportTests.java#L310
>> |
>> https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupportTests.java#L310
>> ]

>> so i've updated the code according to (1) and (2).

>>> 2. I don't understand why you can't use [
>>> https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A-
>>> |
>>> https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A-
>>> ] instead of unsafe. If you can use [
>>> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html
>>> |
>>> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html
>>> ] things might be easier to optimise because the VM doesn't trust nonstatic
>>> final fields but I don't think you'll need to rely on that.

>> I need a VM anonymous class otherwise the method handles used to implement
>> equals and hashCode are not considered as constant by the JIT. A previous
>> version of the API was using one lambdas for equals and one for hashCode,
>> but it makes the API ugly. see [
>> https://github.com/forax/exotic/commit/168736c43f32520ef6e280db174bf8a848ee4421#diff-0b01bd4ba5740e6b300bfa38e337dd71R13
>> |
>> https://github.com/fora

Re: Exotic classes

2019-04-26 Thread Steven Stewart-Gallus


It seems to me you have to do a lot of hacky stuff to get around the "ugly" 
API as you call it.

Maybe it'd be better to separate out the ObjectSupport class into two 
separate classes, a HasherSupport class and an EqualsSupport class.

interface HashSupport {
public static  HashSupport of(Lookup lookup, String... fields) {
var mh = createMh(lookup, fields);
return (obj) -> {
mh.invokeExact(obj);
};
}
int hashCode(T obj);
}

and similar for EqualsSupport.

I feel like ObjectSupport is a bit nebulous and open ended and you'd 
inevitably end up needing more support methods such as a toString method.


On Friday, April 26, 2019 at 8:13:17 AM UTC-7, Remi Forax wrote:
>
>
>
> --
>
> *De: *"Steven Stewart-Gallus" >
> *À: *"mechanical-sympathy" >
> *Envoyé: *Vendredi 26 Avril 2019 01:51:47
> *Objet: *Re: Exotic classes
>
>
> Hi Steven,
> thanks for spending some time on this,
>
>
> 1. Why 
> publicabstractclassObjectSupport{
> publicabstractboolean equals(Objectself,Object other);
> publicabstractint hashCode();
> publicstaticObjectSupport of(Lookup lookup,String... fields){
> // impl details
> }
> // impl details
> }
>
> and not something like?
> interfaceObjectSupport{
> publicboolean equals(T self, T other);
> publicint hashCode(T obj);
> publicstatic>T of(Lookup lookup,Class 
> iface,Class obj){
> // impl details
> }
> }
> @Retention(RetentionPolicy.RUNTIME)
> @Target(ElementType.FIELD)
> @interfaceObjectSupportField{
> }
>
>
> There are three questions, why not use an interface, why not use generics 
> to make the API more typesafe and why not use an annotation to mark the 
> fields,
> (1), it should be an interface, yes :
> (2), yes, the API can be more typesafe, i've implemented that. BTW, the 
> correct type of equals() if generified is (T, Object), because you can call 
> equals(Person, String), it should return false.
> (3),the API you propose can be built on top of the existing one, that's 
> why there is an overload of ObjectSupport.of() that takes a function as 
> third parameter
>  see 
> https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupportTests.java#L310
>
> so i've updated the code according to (1) and (2).
>
> 2. I don't understand why you can't use 
> https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A-
>  instead 
> of unsafe. If you can use 
> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html
>  things 
> might be easier to optimise because the VM doesn't trust nonstatic final 
> fields but I don't think you'll need to rely on that.
>
>
> I need a VM anonymous class otherwise the method handles used to implement 
> equals and hashCode are not considered as constant by the JIT. A previous 
> version of the API was using one lambdas for equals and one for hashCode,
> but it makes the API ugly. see 
> https://github.com/forax/exotic/commit/168736c43f32520ef6e280db174bf8a848ee4421#diff-0b01bd4ba5740e6b300bfa38e337dd71R13
>
> 3. The raw class file isn't always available at runtime so you can't 
> necessarily use ObjectSupportImpl as a template.
>
>
> yes, i will inline it (storing it as an array of bytes inside the Java 
> code) once the API is stable enough.
>
> 4. 
> https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L180
>  Pretty 
> sure you want a static final field here. You can do that if you're using 
> ObjectSupportImpl as a raw template. Unfortunately defineClass doesn't 
> accept arguments so you have to use wonky garbage like a hashmap to pass 
> runtime data that can't be embedded in a class file easily.
>
>
> No need for static fields there because ObjectSupportImpl is loaded as a 
> VM anonymous class, so the instance fields are considered as constant if 
> the object itself is a constant (see the answer to your question 2).
>
> There is a JMH test if you want to take a look to the generated assembly 
> code
>
> https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/perf/ObjectSupportBenchMark.java
>
> regards,
> Rémi
>
> -- 
> You received this message because you are subscribed to the Google Groups 
> "mechanical-sympathy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to mechanical-sympathy+unsubscr...@googlegroups.com .
> For more options, visit https://groups.google.com/d/optout.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-04-26 Thread Remi Forax
> De: "Steven Stewart-Gallus" 
> À: "mechanical-sympathy" 
> Envoyé: Vendredi 26 Avril 2019 01:51:47
> Objet: Re: Exotic classes
Hi Steven, 
thanks for spending some time on this, 

> 1. Why
> public abstract class ObjectSupport {
> public abstract boolean equals ( Object self , Object other );
> public abstract int hashCode ();
> public static ObjectSupport of ( Lookup lookup , String ... fields ) {
> // impl details
> }
> // impl details
> }

> and not something like?
> interface ObjectSupport < T > {
> public boolean equals ( T self , T other );
> public int hashCode ( T obj );
> public static < T , U extends ObjectSupport < T >> T of ( Lookup lookup , 
> Class
> < U > iface , Class < T > obj ) {
> // impl details
> }
> }
> @Retention ( RetentionPolicy . RUNTIME )
> @Target ( ElementType . FIELD )
> @interface ObjectSupportField {
> }

There are three questions, why not use an interface, why not use generics to 
make the API more typesafe and why not use an annotation to mark the fields, 
(1), it should be an interface, yes : 
(2), yes, the API can be more typesafe, i've implemented that. BTW, the correct 
type of equals() if generified is (T, Object), because you can call 
equals(Person, String), it should return false. 
(3),the API you propose can be built on top of the existing one, that's why 
there is an overload of ObjectSupport.of() that takes a function as third 
parameter 
see 
https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupportTests.java#L310
 

so i've updated the code according to (1) and (2). 

> 2. I don't understand why you can't use [
> https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A-
> |
> https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A-
> ] instead of unsafe. If you can use [
> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html
> |
> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html
> ] things might be easier to optimise because the VM doesn't trust nonstatic
> final fields but I don't think you'll need to rely on that.

I need a VM anonymous class otherwise the method handles used to implement 
equals and hashCode are not considered as constant by the JIT. A previous 
version of the API was using one lambdas for equals and one for hashCode, 
but it makes the API ugly. see 
https://github.com/forax/exotic/commit/168736c43f32520ef6e280db174bf8a848ee4421#diff-0b01bd4ba5740e6b300bfa38e337dd71R13
 

> 3. The raw class file isn't always available at runtime so you can't 
> necessarily
> use ObjectSupportImpl as a template.

yes, i will inline it (storing it as an array of bytes inside the Java code) 
once the API is stable enough. 

> 4. [
> https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L180
> |
> https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L180
> ] Pretty sure you want a static final field here. You can do that if you're
> using ObjectSupportImpl as a raw template. Unfortunately defineClass doesn't
> accept arguments so you have to use wonky garbage like a hashmap to pass
> runtime data that can't be embedded in a class file easily.

No need for static fields there because ObjectSupportImpl is loaded as a VM 
anonymous class, so the instance fields are considered as constant if the 
object itself is a constant (see the answer to your question 2). 

There is a JMH test if you want to take a look to the generated assembly code 
[ 
https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/perf/ObjectSupportBenchMark.java
 | 
https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/perf/ObjectSupportBenchMark.java
 ] 

regards, 
Rémi 

> --
> You received this message because you are subscribed to the Google Groups
> "mechanical-sympathy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email
> to [ mailto:mechanical-sympathy+unsubscr...@googlegroups.com |
> mechanical-sympathy+unsubscr...@googlegroups.com ] .
> For more options, visit [ https://groups.google.com/d/optout |
> https://groups.google.com/d/optout ] .

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-04-25 Thread Steven Stewart-Gallus

1. Why 
public abstract class ObjectSupport {
public abstract boolean equals(Object self, Object other);
public abstract int hashCode();
public static ObjectSupport of(Lookup lookup, String... fields) {
// impl details
}
// impl details
}

and not something like?
interface ObjectSupport {
public boolean equals(T self, T other);
public int hashCode(T obj);
public static > T of(Lookup lookup, Class<
U> iface, Class obj) {
   // impl details
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface ObjectSupportField {
}

2. I don't understand why you can't use 
https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A-
 instead 
of unsafe. If you can use 
https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html
 things 
might be easier to optimise because the VM doesn't trust nonstatic final 
fields but I don't think you'll need to rely on that.
3. The raw class file isn't always available at runtime so you can't 
necessarily use ObjectSupportImpl as a template.
4. 
https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L180
 Pretty 
sure you want a static final field here. You can do that if you're using 
ObjectSupportImpl as a raw template. Unfortunately defineClass doesn't 
accept arguments so you have to use wonky garbage like a hashmap to pass 
runtime data that can't be embedded in a class file easily.

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-04-24 Thread Remi Forax
> De: "mechanical-sympathy" 
> À: "mechanical-sympathy" 
> Envoyé: Mardi 23 Avril 2019 18:23:48
> Objet: Re: Exotic classes

> Replies inline

> On Monday, April 22, 2019 at 12:37:19 PM UTC-7, Remi Forax wrote:
>>> De: "mechanical-sympathy" < [ javascript-blocked: |
>>> mechanica...@googlegroups.com ] >
>>> À: "mechanical-sympathy" < [ javascript-blocked: | 
>>> mechanica...@googlegroups.com
>>> ] >
>>> Envoyé: Lundi 22 Avril 2019 20:25:01
>>> Objet: Re: Exotic classes

>>> These classes (especially MostlyConstant) are pretty cool. I have some 
>>> questions
>>> about them:
>>> 1. In MostlyConstant I noticed that modifying the constant doesn't call
>>> MutableCallSite.syncAll(). Should it?

>> yes, you're right from a spec POV i should call syncAll(),
>> the thing is that the current OpenJDK implementation doesn't need syncAll, 
>> but
>> it may change in the future or for another implementation.

>>> 2. A followup to #1: MutableCallSite.syncAll() doesn't actually seem 
>>> implemented
>>> in OpenJDK. Is it correct to call it?

>> yes, it's not implemented because the native part of setTarget() do the 
>> deopt,
>> but it's an implementation detail.

>>> 3. In my non-scientific JMH measurements, it seems like modifying the call 
>>> site
>>> takes about 1us. Does that sound about right? From what I can tell modifying
>>> the constant is akin to deoptimizing the code and recompiling it, which 
>>> means
>>> that 1us seems really fast.

>> it's quite fast but it may be because
>> - it may be not optimized yet
>> - the VM mark all the different generated assembly codes that reference the
>> constant as should be removed from the code cache and will do it later,
>> - the VM will not re-optimize directly if a code is deoptimized, but jump in 
>> the
>> interpreter and re-optimize later.

> I was running this in a JMH benchmark, and I inspected the Assembly and 
> Compiler
> output; I believe it was reaching c2 before swapping.

> A followup question: does deoptimization mean it reverts to a C1 copy of the
> code, or directly back to the interpreter? i.e. how much work does it have to
> undo?

no, for a method, the code generated by c1 is often long gone at the time the 
code generated by c2 detects that it should deopt. 
And c1 like c2 generates the code optimistically so even if the code generated 
by c1 was around, there is a good chance it will have to be de-optimized too. 

BTW, i've just added a way to have equals and hashCode automatically 
implemented to exotic [1]. 

Rémi 
[1] 
https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L38
 

>> so there is a good chance that what you are measuring is not all 
>> de-optimization
>> cost.

>> Rémi

>>> On Monday, February 26, 2018 at 11:29:19 AM UTC-8, Remi Forax wrote:
>>>> Hi all,
>>>> i'm preparing a talk at DevoxxFR on how to make a field value, a returned 
>>>> value,
>>>> etc constant for any decent JITs (everything but c1), so i've bundled 
>>>> together
>>>> several patterns i use for implementing dynamic language runtimes into an 
>>>> Java
>>>> API

>>>> [ https://github.com/forax/exotic | https://github.com/forax/exotic ]

>>>> I would like to have your comments about those exotic classes (it's 
>>>> already has
>>>> been done, it's stupid, it's not thread safe, etc)

>>>> regards,
>>>> Rémi

> --
> You received this message because you are subscribed to the Google Groups
> "mechanical-sympathy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email
> to [ mailto:mechanical-sympathy+unsubscr...@googlegroups.com |
> mechanical-sympathy+unsubscr...@googlegroups.com ] .
> For more options, visit [ https://groups.google.com/d/optout |
> https://groups.google.com/d/optout ] .

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-04-23 Thread 'Carl Mastrangelo' via mechanical-sympathy
Replies inline

On Monday, April 22, 2019 at 12:37:19 PM UTC-7, Remi Forax wrote:
>
>
>
> --
>
> *De: *"mechanical-sympathy" >
> *À: *"mechanical-sympathy" >
> *Envoyé: *Lundi 22 Avril 2019 20:25:01
> *Objet: *Re: Exotic classes
>
> These classes (especially MostlyConstant) are pretty cool.  I have some 
> questions about them:
> 1.  In MostlyConstant I noticed that modifying the constant doesn't call 
> MutableCallSite.syncAll().   Should it?
>
>
> yes, you're right from a spec POV i should call syncAll(),
> the thing is that the current OpenJDK implementation doesn't need syncAll, 
> but it may change in the future or for another implementation.
>
>
> 2.  A followup to #1: MutableCallSite.syncAll() doesn't actually seem 
> implemented in OpenJDK.  Is it correct to call it?
>
>
> yes, it's not implemented because the native part of setTarget() do the 
> deopt, but it's an implementation detail. 
>
>
>
> 3.  In my non-scientific JMH measurements, it seems like modifying the 
> call site takes about 1us.   Does that sound about right?   From what I can 
> tell modifying the constant is akin to deoptimizing the code and 
> recompiling it, which means that 1us seems really fast.
>
>
> it's quite fast but it may be because
> - it may be not optimized yet
> - the VM mark all the different generated assembly codes that reference 
> the constant as should be removed from the code cache and will do it later,
> - the VM will not re-optimize directly if a code is deoptimized, but jump 
> in the interpreter and re-optimize later. 
>

I was running this in a JMH benchmark, and I inspected the Assembly and 
Compiler output; I believe it was reaching c2 before swapping.  

A followup question: does deoptimization mean it reverts to a C1 copy of 
the code, or directly back to the interpreter?  i.e. how much work does it 
have to undo?  

 

>
> so there is a good chance that what you are measuring is not all 
> de-optimization cost.
>
> Rémi
>
>
>
> On Monday, February 26, 2018 at 11:29:19 AM UTC-8, Remi Forax wrote:
>>
>> Hi all, 
>> i'm preparing a talk at DevoxxFR on how to make a field value, a returned 
>> value, etc constant for any decent JITs (everything but c1), so i've 
>> bundled together several patterns i use for implementing dynamic language 
>> runtimes into an Java API 
>>
>>   https://github.com/forax/exotic 
>>
>> I would like to have your comments about those exotic classes (it's 
>> already has been done, it's stupid, it's not thread safe, etc) 
>>
>> regards, 
>> Rémi 
>>
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-04-22 Thread Remi Forax
> De: "mechanical-sympathy" 
> À: "mechanical-sympathy" 
> Envoyé: Lundi 22 Avril 2019 20:25:01
> Objet: Re: Exotic classes

> These classes (especially MostlyConstant) are pretty cool. I have some 
> questions
> about them:
> 1. In MostlyConstant I noticed that modifying the constant doesn't call
> MutableCallSite.syncAll(). Should it?

yes, you're right from a spec POV i should call syncAll(), 
the thing is that the current OpenJDK implementation doesn't need syncAll, but 
it may change in the future or for another implementation. 

> 2. A followup to #1: MutableCallSite.syncAll() doesn't actually seem 
> implemented
> in OpenJDK. Is it correct to call it?

yes, it's not implemented because the native part of setTarget() do the deopt, 
but it's an implementation detail. 

> 3. In my non-scientific JMH measurements, it seems like modifying the call 
> site
> takes about 1us. Does that sound about right? From what I can tell modifying
> the constant is akin to deoptimizing the code and recompiling it, which means
> that 1us seems really fast.

it's quite fast but it may be because 
- it may be not optimized yet 
- the VM mark all the different generated assembly codes that reference the 
constant as should be removed from the code cache and will do it later, 
- the VM will not re-optimize directly if a code is deoptimized, but jump in 
the interpreter and re-optimize later. 

so there is a good chance that what you are measuring is not all 
de-optimization cost. 

Rémi 

> On Monday, February 26, 2018 at 11:29:19 AM UTC-8, Remi Forax wrote:
>> Hi all,
>> i'm preparing a talk at DevoxxFR on how to make a field value, a returned 
>> value,
>> etc constant for any decent JITs (everything but c1), so i've bundled 
>> together
>> several patterns i use for implementing dynamic language runtimes into an 
>> Java
>> API

>> [ https://github.com/forax/exotic | https://github.com/forax/exotic ]

>> I would like to have your comments about those exotic classes (it's already 
>> has
>> been done, it's stupid, it's not thread safe, etc)

>> regards,
>> Rémi

> --
> You received this message because you are subscribed to the Google Groups
> "mechanical-sympathy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email
> to [ mailto:mechanical-sympathy+unsubscr...@googlegroups.com |
> mechanical-sympathy+unsubscr...@googlegroups.com ] .
> For more options, visit [ https://groups.google.com/d/optout |
> https://groups.google.com/d/optout ] .

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-04-22 Thread Nitsan Wakart
The cost would be a combination of the deopt, cost of slow down, and cost of 
compilation all of which are variable based on the generated code which embeds 
the constant and the compiler used. 

> On 22 Apr 2019, at 20:25, 'Carl Mastrangelo' via mechanical-sympathy 
>  wrote:
> 
> These classes (especially MostlyConstant) are pretty cool.  I have some 
> questions about them:
> 
> 1.  In MostlyConstant I noticed that modifying the constant doesn't call 
> MutableCallSite.syncAll().   Should it?
> 
> 2.  A followup to #1: MutableCallSite.syncAll() doesn't actually seem 
> implemented in OpenJDK.  Is it correct to call it?
> 
> 3.  In my non-scientific JMH measurements, it seems like modifying the call 
> site takes about 1us.   Does that sound about right?   From what I can tell 
> modifying the constant is akin to deoptimizing the code and recompiling it, 
> which means that 1us seems really fast.
> 
>> On Monday, February 26, 2018 at 11:29:19 AM UTC-8, Remi Forax wrote:
>> Hi all, 
>> i'm preparing a talk at DevoxxFR on how to make a field value, a returned 
>> value, etc constant for any decent JITs (everything but c1), so i've bundled 
>> together several patterns i use for implementing dynamic language runtimes 
>> into an Java API 
>> 
>>   https://github.com/forax/exotic 
>> 
>> I would like to have your comments about those exotic classes (it's already 
>> has been done, it's stupid, it's not thread safe, etc) 
>> 
>> regards, 
>> Rémi 
>> 
>> 
>> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "mechanical-sympathy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to mechanical-sympathy+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-04-22 Thread 'Carl Mastrangelo' via mechanical-sympathy
These classes (especially MostlyConstant) are pretty cool.  I have some 
questions about them:

1.  In MostlyConstant I noticed that modifying the constant doesn't call 
MutableCallSite.syncAll().   Should it?

2.  A followup to #1: MutableCallSite.syncAll() doesn't actually seem 
implemented in OpenJDK.  Is it correct to call it?

3.  In my non-scientific JMH measurements, it seems like modifying the call 
site takes about 1us.   Does that sound about right?   From what I can tell 
modifying the constant is akin to deoptimizing the code and recompiling it, 
which means that 1us seems really fast.

On Monday, February 26, 2018 at 11:29:19 AM UTC-8, Remi Forax wrote:
>
> Hi all, 
> i'm preparing a talk at DevoxxFR on how to make a field value, a returned 
> value, etc constant for any decent JITs (everything but c1), so i've 
> bundled together several patterns i use for implementing dynamic language 
> runtimes into an Java API 
>
>   https://github.com/forax/exotic 
>
> I would like to have your comments about those exotic classes (it's 
> already has been done, it's stupid, it's not thread safe, etc) 
>
> regards, 
> Rémi 
>
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-02-06 Thread Remi Forax
Hi Steven, 

> De: "Steven Stewart-Gallus" 
> À: "mechanical-sympathy" 
> Envoyé: Samedi 19 Janvier 2019 05:19:06
> Objet: Re: Exotic classes

> On Friday, January 18, 2019 at 5:37:58 AM UTC-8, Rémi Forax wrote
>>> no, CHA only works on class, not on interface.
> You're probably know better than me. I seem to remember there's something like
> that for interfaces but very limited such as if you ever only have ever one
> implementation.

You have been prescient :) 
c2 now does CHA on interfaces. 

https://bugs.openjdk.java.net/browse/JDK-6986483 

[...] 

Rémi 

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-01-18 Thread Steven Stewart-Gallus


On Friday, January 18, 2019 at 5:37:58 AM UTC-8, Rémi Forax wrote
>
> no, CHA only works on class, not on interface.
>
> You're probably know better than me. I seem to remember there's something 
like that for interfaces but very limited such as if you ever only have 
ever one implementation. I suppose you could create a class at runtime that 
fills out an abstract class which implements Supplier. You'd just create a 
class with a static final field that returns it as an abstract method impl.
 

> It's not the same semantics, you can not change a StableField more than 
> once so you have the guarantee that once the field is initialized, no 
> deoptimization can occur.
> The other things is the object is not constant, you will get an exception 
> so it's hard to misuse that API.
> The last point is that i expect that at some point i will change the 
> implementation so the slowpath will cost less than the slowpath of 
> MostlyConstant, but i've never had the time to think how to do that in a VM 
> independant way (i know how to do that with Hotspot only).
>

Probably better just to omit it until you can actually make it behave 
differently. By the way, how can you get Hotspot to do it?

but it means that you have if/else branch for String that the program has 
> never encounter.
> I prefer to not add all the branches statically but add then at runtime 
> dynamically when i know i need then. 
>

You just have to be extra lazy about it. It's usually bad style but nothing 
prevents you from doing something like:

private static final class Helper {
static final Config CONFIG = initConfig(configStr);
}
private String configStr = null;

public static Config getConfig() {
return Helper.CONFIG;
}

private static Config initConfig(String initStr){
// ...
}

>
>  

> It will not be inlined by the VM :(
>

Yeah I abandoned trying to make my own ThreadLocalCallSite implementation 
for now.  I couldn't work out many of the details.
 

>
> About having a ThreadLocalCallSite, as part of project Loom, we are 
> discussing about how associate a value to a part of the callstack.
> Anyway, the VM doesn't have a code cache per thread, there is only a 
> global code cache.
>

It seems like for a lot of things it is just simpler to have separate 
isolated processes. I wonder if something like Graal could be hacked to 
have separate separate Java subinterpreters for separate threads.

Another option is to clone key classes/methods per core but I wasn't sure 
about how heavyweight that would be.

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Exotic classes

2019-01-18 Thread Remi Forax
> De: "Steven Stewart-Gallus" 
> À: "mechanical-sympathy" 
> Envoyé: Jeudi 17 Janvier 2019 07:50:13
> Objet: Re: Exotic classes

> I've been working on similar issues trying to optimise something
> heavily.  I made a similar class to this one (I even had a similar
> API) but I found I called it MostlyFinal instead.

> private static final MostlyConstant FOO = new MostlyConstant<>(42,
> int.class);
> private static final IntSupplier FOO_GETTER = FOO.intGetter();

> By the way using a different interface than Supplier can give the JVM
> more class hierarchy analysis info and so potentially allow for
> inlining even without static final.

no, CHA only works on class, not on interface. 

> You can also simply use a closure in some cases sort of like this:

> interface IntBox {
>int get();
> }
> public IntBox makeBox(int x) {
> return () -> x;
> }

> This is better for inlining because the JVM trusts final fields in VM
> anonymous classes more than yours.  Unfortunately
> TrustStaticFinalFields cannot be a thing by default yet for backwards
> compatibility reasons.

> I think a lot of these things are pretty neat but unfortunately hard
> to package in a generic and usable library because people delving into
> these will want to tear into all the internal details for maximum
> performance.

> I don't really understand your StableField class.  How is it supposed
> to be any faster than MostlyConstant?

It's not the same semantics, you can not change a StableField more than once so 
you have the guarantee that once the field is initialized, no deoptimization 
can occur. 
The other things is the object is not constant, you will get an exception so 
it's hard to misuse that API. 
The last point is that i expect that at some point i will change the 
implementation so the slowpath will cost less than the slowpath of 
MostlyConstant, but i've never had the time to think how to do that in a VM 
independant way (i know how to do that with Hotspot only). 

> I would suggest if you wanted the best speed (in some ways and at a cost of
> memory) you could spin a
> static final class with a method that returns a constantdynamic entry
> and then return a methodhandle to that entry.  This seems possibly
> heavyweight IMO so I'm still thinking about this myself.

better, use a lazy static final field (see [ 
https://bugs.openjdk.java.net/browse/JDK-8209964), | 
https://bugs.openjdk.java.net/browse/JDK-8209964), ] 
i.e. tech javac to either emit a ldc to the ConstantDynamic or do a getfield 
that will trigger the ConstantDynamic initialization if needed. 

> If StringSwitchCallSite being a MutableCallSite seems possibly
> unneeded with a reworked API to me.

but it means that you have if/else branch for String that the program has never 
encounter. 
I prefer to not add all the branches statically but add then at runtime 
dynamically when i know i need then. 

> I am highly suspicious TypeSwitch will increase performance in most cases.
> instanceof checks are highly optimized and give info that allow
> further optimizations.

It depends, if instanceof else ... is slow if you have deep hierarchy, if the 
test are not in the right order of occurence and if you have too many branches. 
But yes, the StringSwitch and the TypeSwitch can be slower/faster than the 
equivalent cascade of if/else. 

> You might want to consider using/abusing the JVM's own inline caching
> behaviour for interfaces for some dispatching.

A MethodHandles.guardWithTest is exactly that ! 

> It's not too hard to create a bag of interface implementations at
> runtime that all dispatch to separate CallSite implementations which
> can be faster than exactInvoker/your own MethodHandle lookup logic
> sometimes.

No, believe me, it's hard. It's the reason i've created (with others) the 
java.lang.invoke API. 

> I considered this for a ThreadLocalCallSite class I was
> making but I'm still not sure about the design.

> So basically one hack to get quicker thread local behaviour is to
> subclass Thread and add your own fields/methods like this:

> ((MyIface)Thread.currentThread()).doSpecific();

> If you add your own bag of interface implementations then you can do
> this dynamically:

> MY_IFACE.invokeExact((BagThread)Thread.currentThread()).bag, ...);

It will not be inlined by the VM :( 

About having a ThreadLocalCallSite, as part of project Loom, we are discussing 
about how associate a value to a part of the callstack. 
Anyway, the VM doesn't have a code cache per thread, there is only a global 
code cache. 

> I'm not sure about the bytecode generation here though. I don't want
> to be too blase about that.

> It looks like you have some benchmarks setup but I don't see any

Re: Exotic classes

2019-01-16 Thread Steven Stewart-Gallus


I've been working on similar issues trying to optimise something
heavily.  I made a similar class to this one (I even had a similar
API) but I found I called it MostlyFinal instead.

private static final MostlyConstant FOO = new MostlyConstant<>(42, 
int.class);
private static final IntSupplier FOO_GETTER = FOO.intGetter();

By the way using a different interface than Supplier can give the JVM
more class hierarchy analysis info and so potentially allow for
inlining even without static final.

You can also simply use a closure in some cases sort of like this:

interface IntBox {
   int get();
}
public IntBox makeBox(int x) {
return () -> x;
}

This is better for inlining because the JVM trusts final fields in VM
anonymous classes more than yours.  Unfortunately
TrustStaticFinalFields cannot be a thing by default yet for backwards
compatibility reasons.

I think a lot of these things are pretty neat but unfortunately hard
to package in a generic and usable library because people delving into
these will want to tear into all the internal details for maximum
performance.

I don't really understand your StableField class.  How is it supposed
to be any faster than MostlyConstant?  I would suggest if you wanted
the best speed (in some ways and at a cost of memory) you could spin a
static final class with a method that returns a constantdynamic entry
and then return a methodhandle to that entry.  This seems possibly
heavyweight IMO so I'm still thinking about this myself.

If StringSwitchCallSite being a MutableCallSite seems possibly
unneeded with a reworked API to me.

I am highly suspicious TypeSwitch will increase performance in most cases.
instanceof checks are highly optimized and give info that allow
further optimizations.

You might want to consider using/abusing the JVM's own inline caching
behaviour for interfaces for some dispatching.

It's not too hard to create a bag of interface implementations at
runtime that all dispatch to separate CallSite implementations which
can be faster than exactInvoker/your own MethodHandle lookup logic
sometimes.  I considered this for a ThreadLocalCallSite class I was
making but I'm still not sure about the design.

So basically one hack to get quicker thread local behaviour is to
subclass Thread and add your own fields/methods like this:

((MyIface)Thread.currentThread()).doSpecific();

If you add your own bag of interface implementations then you can do
this dynamically:

MY_IFACE.invokeExact((BagThread)Thread.currentThread()).bag, ...);

I'm not sure about the bytecode generation here though. I don't want
to be too blase about that.

It looks like you have some benchmarks setup but I don't see any txt
files with any perf data listed.  I mentioned a lot of gibberish
earlier but problem my biggest advice would be to add more benchmarks
and look at your benchmarks again and also get real world usage data.

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.