March 24, 2012
On 03/23/12 20:11, Adam D. Ruppe wrote:
> 
> http://dlang.org/traits.html#getVirtualFunctions
> 
> if the name isn't on a list of approved virtuals,
> static assert fail.

And you could probably do it in a clean and unintrusive way, by, for example, extending Object, or doing it on a per-module basis. If it actually worked...

The obvious problem is that the 'virtual' check pretty much has to *prevent* devirtualization, or lie about it and always report the functions as virtual -- otherwise devirtualization has to happen before the checks, and this could change their results.

Also, my gdc (which i haven't updated for a while) does not
even devirtualize this simple case:

-------------------------------------------------------
private class C {
  int bar() { return 42; }
}

pragma(attribute, externally_visible) int main() {
  C c = new C;
  //writeln(__traits(isVirtualFunction, c.bar));
  return c.bar();
}
-------------------------------------------------------

It needs at least the class or method marked as 'final' to do the right thing. Note that the isVirtualFunction check returns true even for the cases where bar() does get inlined. (*VirtualMethod* do not exist here)

artur
March 24, 2012
On Saturday, 24 March 2012 at 14:43:21 UTC, Artur Skawina wrote:
> It needs at least the class or method marked as 'final' to do the right thing.

Indeed, that's what I'm after.

I'm making another post with an implementation in reply
to manu in a minute.
March 24, 2012
On Saturday, 24 March 2012 at 10:56:27 UTC, Manu wrote:
> My objection to virtual-by-default, but, acknowledging that can't be changed, insistence on a virtual keyword
> is this.

I like the idea of a virtual keyword btw.

> Adding a system like you describe to validate virtuals is not a complexity I'm interested in implementing


You already have! Let me quote one of your previous posts:

"I sincerely fear finding myself false-virtual hunting on build night until
2am trying to get the game to hold its frame rate (I already do this in
C++, but at least you can grep for and validate them!)."


In C++, you're hunting for false virtuals right now.

Your solution is to grep for and validate them.


That's what I'm talking about here, but instead of grepping,
using the language's reflection capabilities for an automated
test.

Check out the example I pasted at the end of this message.

The bottom part of that is reusable, the top part is my
test data.

Run it through the compiler with the test code added:

$ dmd test13 -unittest
Warning: A.lol is an unauthorized virtual function
Warning: B.amazing is an unauthorized virtual function


And it greps for virtuals for you, and reports
it at compile time.

If it turns out you want one of them to be virtual,
you add the name to the authorizedVirtuals list.

How would you validate a virtual in C++? If
you have a list of functions you're OK with,
that's exactly what this is!

If you look at the source of each virtual your
grep finds, to ensure it absolutely needs to
be virtual... well, you can do that here too. Between
the warnings and the authorized virtuals list, you know
all the virts here and can review them.


The best way to silence a warning btw is to just
write "final" on the method.

Your code review process can keep the authorized
virtual list to themselves, so most developers
either add final or break the build. Either way,
no virtuals slip in without review.


Also from an old post:

"Aside from that, I want a compile error if someone tries to randomly
override stuff."

Warning: C.goodVirtual is an unauthorized virtual function

the code below checks on a per class level, so if you don't
authorize the override, it gets a warning to.

(You can change these to errors by making it static assert
or something instead of pragma(msg).)


> Who maintains these tables?

Who decides who can write "virtual" in C++?




Example follows:


===
module test13;

class A {
	void goodVirtual() {}
	void lol() {}
}

class B {
	int amazing() { return 0; }
}

class C : A {
	override void goodVirtual() {}
	final void drox() {}
}

template isClass(alias T) if(!is(T)) { enum bool isClass = false; }
template isClass(alias T) if(is(T)) { enum bool isClass = is(T == class); }

unittest {
	enum string[][string] authorizedVirtuals = [
		"A" : ["goodVirtual"],
		"B" : [],
		"C" : ["goodVirtual"],
	];

	import algore = std.algorithm;

	foreach(member; __traits(allMembers, test13)) {
		static if(isClass!(__traits(getMember, test13, member))) {
			foreach(possibleVirt; __traits(derivedMembers, __traits(getMember, test13, member))) {
				static if(
					__traits(isVirtualMethod, __traits(getMember,
						__traits(getMember, test13, member), possibleVirt))
					&&
					!algore.canFind(authorizedVirtuals[member], possibleVirt))
				{
					pragma(msg, "Warning: " ~ member ~ "." ~ possibleVirt ~ " is an unauthorized virtual function");
				}
			}
		}
	}
}

void main() {}

===


March 24, 2012
I think a better system would be to explicitly mark functions are virtual, and then use unittesting to catch virtual functions that don't need to be.

March 24, 2012
On 3/24/12 3:03 AM, Manu wrote:
> On 23 March 2012 17:24, Ary Manzana <ary@esperanto.org.ar
> <mailto:ary@esperanto.org.ar>> wrote:
>
>     On 3/18/12 9:23 AM, Manu wrote:
>
>         The virtual model broken. I've complained about it lots, and people
>         always say "stfu, use 'final:' at the top of your class".
>
>         That sounds tolerable in theory, except there's no 'virtual'
>         keyword to
>         keep the virtual-ness of those 1-2 virtual functions I have...
>         so it's
>         no good (unless I rearrange my class, breaking the logical
>         grouping of
>         stuff in it).
>         So I try that, and when I do, it complains: "Error: variable
>         demu.memmap.MemMap.machine final cannot be applied to variable",
>         allegedly a D1 remnant.
>         So what do I do? Another workaround? Tag everything as final
>         individually?
>
>         My minimum recommendation: D needs an explicit 'virtual'
>         keyword, and to
>         fix that D1 bug, so putting final: at the top of your class
>         works, and
>         everything from there works as it should.
>
>
>     Is virtual-ness your performance bottleneck?
>
>
> Frequently. It's often the most expensive 'trivial' operation many
> processors can be asked to do. Senior programmers (who have much better
> things to waste their time on considering their pay bracket) frequently
> have to spend late nights mitigating this even in C++ where virtual
> isn't default. In D, I'm genuinely concerned by this prospect. Now I
> can't just grep for virtual and fight them off, which is time consuming
> alone, I will need to take every single method, one by one, prove it is
> never overloaded anywhere (hard to do), before I can even begin the
> normal process of de-virtualising it like you do in C++.
> The problem is elevated by the fact that many programmers are taught in
> university that virtual functions are okay. They come to the company,
> write code how they were taught in university, and then we're left to
> fix it up on build night when we can't hold our frame rate. virtual
> functions and scattered/redundant memory access are usually the first
> thing you go hunting for. Fixing virtuals is annoying when the system
> was designed to exploit them, it often requires some extensive
> refactoring, much harder to fix than a bad memory access pattern, which
> might be as simple as rearranging a struct.

Interesting.

I spend most of my work time programming in Ruby, where everything is virtual+ :-P

It's good to know that virtual-ness can be a bottleneck.
March 24, 2012
On 03/24/12 16:16, Adam D. Ruppe wrote:
> On Saturday, 24 March 2012 at 10:56:27 UTC, Manu wrote:
>> My objection to virtual-by-default, but, acknowledging that can't be changed, insistence on a virtual keyword is this.
> 
> I like the idea of a virtual keyword btw.
> 
>> Adding a system like you describe to validate virtuals is not a complexity I'm interested in implementing
> 
> 
> You already have! Let me quote one of your previous posts:
> 
> "I sincerely fear finding myself false-virtual hunting on build night until 2am trying to get the game to hold its frame rate (I already do this in C++, but at least you can grep for and validate them!)."
> 
> 
> In C++, you're hunting for false virtuals right now.
> 
> Your solution is to grep for and validate them.
> 
> 
> That's what I'm talking about here, but instead of grepping, using the language's reflection capabilities for an automated test.
> 
> Check out the example I pasted at the end of this message.

The question is -- are there false positives?
(Ie situations where the compiler managed to devirtualize
methods which __traits reported earlier as being virtual)

artur
March 24, 2012
On Saturday, 24 March 2012 at 16:27:41 UTC, Artur Skawina wrote:
> The question is -- are there false positives?

Yes, almost certainly. This only looks at the function
definition; it is run well before the optimizer.
1 2 3 4 5 6 7 8
Next ›   Last »