> From: "John Rose" <john.r.r...@oracle.com> > To: "daniel smith" <daniel.sm...@oracle.com> > Cc: "Kevin Bourrillion" <kev...@google.com>, "Brian Goetz" > <brian.go...@oracle.com>, "valhalla-spec-experts" > <valhalla-spec-experts@openjdk.java.net> > Sent: Jeudi 4 Novembre 2021 02:34:52 > Subject: Re: [External] : Re: Consolidating the user model
> On Nov 3, 2021, at 4:05 PM, Dan Smith < [ mailto:daniel.sm...@oracle.com | > daniel.sm...@oracle.com ] > wrote: >> (It is, I suppose, part of the model that objects of a given class all have a >> finite, matching layout when accessed by value, even if the details of that >> layout are kept abstract. Which is why value types are monomorphic and you >> need >> reference types for polymorphism.) >> The fact that the VM often discards object headers at runtime is a pure >> optimization. > Let’s see what happens if we say that (a) bare values have headers and (b) > Object::getClass allows the user to observe part of the header contents. > It follows then that the expression aPointVal.getClass() will show the > contents > of aPointVal’s header, even if it is a compile-time constant. > Point pv = new Point(42,42); // “class Point” is the definition of Point > assert pv.getClass() == Point.class; // ok, that’s certainly the class > assert pv.getClass() != Point.ref.class; // and it’s not a ref, so good > That is all fine. There’s a little hiccup when you “box” the point and get the > same Class mirror even though the “header” is a very real-heap resident value > now: > Point.ref pr = pv; // same object… now it’s on the heap, though, with a real > live heap header > assert pr.getClass() == Point.class; // same class, but... > assert pr.getClass() != Point.ref.class; // we suppress any distinction the > heap > header might provide > There’s a bigger hiccup when you compare all that with good old int: > int iv = 42; // “class int” is NOT a thing, but “class Integer” is > assert iv.getClass() != int.class; // because int is not a class > assert iv.getClass() == Integer.class; // ah, there’s the class! > assert iv.getClass() == int.ref.class; // this works differently from Point > assert ((Object)iv).getClass() == pr.getClass(); // this should be true also, > right? How can you have int.class not being a class and at the same time having the notation int.ref ?? If you suppose that int is now a primitive class, B3 bucket, then iv.getClass() == int.class, because it's equivalent to new int(iv).getClass() == int.class so assert iv.getClass() != Integer.class; //because Integer is the reference projection assert iv.getClass() != int.ref.class; // because int.ref is equivalent to Integer If you suppose that Integer is B2 bucket (after all, all other value based class are B2), then iv.getClass() == Integer.class because it's equivalent to Integer.valueOf(iv).getClass() == Integer.class so assert iv.getClass() != int.class; //because int.class is a fake type like void.class assert iv.getClass() != int.ref.class; // does not compile because Integer is B2 not B3 I think i've missed something ? Rémi