Coding: Fleeting Thoughts

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Xenomortis
Not actually a special flower.
Posts: 1455
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Wed May 29, 2013 5:08 pm UTC

It's an integer type with the same precision as a pointer - http://msdn.microsoft.com/en-us/library/cc230322.aspx.
The article says that DWORD_PTR is commonly used for functions that have been extended to 64bit from 32bit, but it doesn't give a reason for that pattern.
Image

User avatar
Yakk
Poster with most posts but no title.
Posts: 11129
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed May 29, 2013 5:44 pm UTC

Really, they could try migrating away from SHOUTING by just calling it `uint_ptr`. Unless they intend to back port to a 16 bit system sometime shortly.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Wed May 29, 2013 6:36 pm UTC

Yakk wrote:`uint_ptr`

What's with the whispering?

Honestly, the implications of having multiple different types for pointer to integer casts in the first place makes me worry about how windows is written under the covers.
Summum ius, summa iniuria.

User avatar
Xenomortis
Not actually a special flower.
Posts: 1455
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Wed May 29, 2013 6:46 pm UTC

From what I've read, whenever you see something really weird or inconsistent in Windows, particularly API stuff, the answer is often "compatibility".
For instance, I gather that DWORD is historic and DWORD32 is more recent, along with DWORD64.

The downside to making changes and trying to maintain compatibility is that you accrue an awful lot of clutter
Image

User avatar
Yakk
Poster with most posts but no title.
Posts: 11129
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed May 29, 2013 9:35 pm UTC

Thesh wrote:
Yakk wrote:`uint_ptr`

What's with the whispering?

Honestly, the implications of having multiple different types for pointer to integer casts in the first place makes me worry about how windows is written under the covers.

They wanted to replace INT, LONG, DWORD, UINT and ULONG with a type that is large enough to both hold the integer, and a pointer.

So instead of normalizing (which I'd propose), they made _PTR versions. Then, in 32 bit, they #defined them back to the old value. In 64 bit, they are #defined to some 64 bit integer with the right signedness.

See: http://stackoverflow.com/questions/1271 ... ow-and-why
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Thu May 30, 2013 1:48 am UTC

Hell, they have "typedef long LONG;" in there, along with a lot of others. Do you really think they're going to use uintptr_t when they could invent their own?

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Thu May 30, 2013 2:38 am UTC

phlip wrote:Hell, they have "typedef long LONG;" in there, along with a lot of others. Do you really think they're going to use uintptr_t when they could invent their own?
I know you know this, but uintptr_t wasn't around when they did that. Heck, even C89 was a newborn when Win3.0 was released (May 1990), let alone earlier versions (1.0 was 1985). At that point in time it probably made perfect sense to provide typedefs and use them everywhere, hence the LONG typedef.

Not to argue that they don't have a significant NIH problem.

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Thu May 30, 2013 4:04 am UTC

I think uintptr_t was around when DWORD_PTR and friends were added, though. Not 100% on that, but pretty sure.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
Yakk
Poster with most posts but no title.
Posts: 11129
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Thu May 30, 2013 4:31 am UTC

But old code used `LONG` and `DWORD` and `INT` -- if they made the API say `uintptr_t`, the types wouldn't match exactly.

Now, why does that matter? Well, someone might have a pointer to a windows API function somewhere. So its signature must not only be compatible, it must match exactly in win 32 so as not to break any existing code bases. And suppose they used lower case long, or int, or unsigned int, knowing that DWORD expanded to one particular type?

This means for each type you want to conditionally extend to 64 bits, the 32 bit version must remain the same. And with the DRY principle, this means that they need a distinct type for each of the 32 bit types they are conditionally extending to 64 bits, with the guarantee that the types are identical.

So `ulongptr_t` is needed, but doesn't exist (I don't think), which means they need LONG_PTR. And they either have to force `uintptr_t` to be a `typedef` to `unsigned int` (and not say `unsigned long`) in all compilers that compile the windows API, or they define DWORD_PTR and avoid forcing compilers to make decisions about their internal types as much...
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Thu May 30, 2013 4:32 am UTC

phlip wrote:I think uintptr_t was around when DWORD_PTR and friends were added, though. Not 100% on that, but pretty sure.
But in some sense the decision was made when the original functions were defined. LONG_PTR, DWORD_PTR, etc. are "different" types because they are wrapping types which are "different" in the legacy API, and so introducing the _PTR versions of the types and Ptr version of the functions is sort of the "least distance from the current API" and is thus desirable if you want to minimize the changes people will have to make to their old code.

I don't want to argue that it was a good decision, but at least it's not like they're just pulling stuff out off their asses to try to be difficult.

lgw
Posts: 437
Joined: Mon Apr 12, 2010 10:52 pm UTC

Re: Coding: Fleeting Thoughts

Postby lgw » Fri May 31, 2013 11:43 pm UTC

It helps to remember about the DWORD and similar SHOUTY_TYPES that most of it dates from the 16-bit days (which is why DWORD is 32 bits: WORD is 16 bits). When the 16-bit stuff was new (long before win32) this all made some actual sense. Also, back then, the intent was that WORD would be 32-bits on a 32-bit platform, which didn't happen because they didn't enforce that sort of cleanliness. When it came time to write win32 (which was still long before c99 was adopted), the SHOUTY_TYPES made less sense, but were by then firmly ingrained in MS coding culture.

The types in C# make far more sense, and C# (along with the .NET library) is really Microsoft's "do-over" on win32. So, arguably, they did eventually fix it, and remove all SHOUTY_TYPES. I suspect they had to leave win32 alone, and make a new language (not just library) to get sanity, for internal cultural reasons - all the guys who would loudly protest any win32 library changes were ignoring C# and so not blocking it.
"In no set of physics laws do you get two cats." - doogly

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Fri May 31, 2013 11:51 pm UTC

I suggest we use chew to mean 16 bit, and gnaw to mean 32 bit, and chomp to mean 64 bit.
Summum ius, summa iniuria.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Sat Jun 01, 2013 8:48 am UTC

Anyone who is familiar with finite fields know of a way to make this more efficient?

Code: Select all

__m128i m64(__m128i x, __m128i y) {
   __m128i temp, r;
   const __m128i p  = {0x000000000000001B,0};
   temp = __builtin_ia32_pclmulqdq128(x, y, 0x00);
   r = temp ^ __builtin_ia32_pclmulqdq128(p, temp, 0x10);
   return temp ^  __builtin_ia32_pclmulqdq128(p, r, 0x10);
}


This compiles with GCC when the -mpclmul option is set, can't guarantee for anything else. This is probably more math than coding, but here is what this is doing, expressed purely informally.

__builtin_ia32_pclmulqdq128 calls the builtin pclmulqdq instructions in newer x64 processors to preform finite field multiplication. In this case I am doing GF(2^64) multiplication using the irreducible polynomial, p, x64 + x4 + x3 + x + 1, as the modulus. In the constant p, I only store the last 64 bits (excluding only x64). Although __builtin_ia32_pclmulqdq128 takes a 128bit integer, it is really only works on 64-bits at a time.

The first two parameter of __builtin_ia32_pclmulqdq128 are the numbers to multiply together, the second tells whether to use the high or low bits of those parameters. 0x00 says to use both low bits, 0x10, rather confusingly when reading as a big-endian number, means to multiply the low bits of the first parameter to the high bits of the second parameter.

So the first multiplication is straightforward, it's the multiplication without reduction.

For the second, I am multiplying by p to get which bits to reflect to the high bits of r. In the output, the lower bits are ignored. This is so I can then multiply by p again, and xor the low bits of that multiplication to the lower bits of the original multiplication in order to get the final reduced polynomial. For the second multiplication, XORing temp is adding the multiplication by the missing high bit of p, that is the expression can be read as temp*(x64) + temp*(x4 + x3 + x + 1) if you remember you are only looking at the high bits of temp.

The lower bits of the final multiplication, p times the high bits of temp, are the XORd to the lower bits of the first multiplication to form the final reduced polynomial.

I'm playing around with the concept of using a 4x4 matrix in GF(264) and looking at what kind of performance I could get, and the results are disappointing to say the least. I'm wondering if there is an algorithm that allows this to be performed in two multiplications instead of three. Note that the way it is written, it only works for fields with a modulus smaller than, but not equal to x64 + x33, which is perfectly acceptable.
Summum ius, summa iniuria.

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Coding: Fleeting Thoughts

Postby jestingrabbit » Sat Jun 01, 2013 12:47 pm UTC

So, just to be clear, you just want the product of x and y, interpreted as elements of GF(2^64)?
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Sat Jun 01, 2013 12:48 pm UTC

Yes, that's correct.
Summum ius, summa iniuria.

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Coding: Fleeting Thoughts

Postby jestingrabbit » Sat Jun 01, 2013 1:35 pm UTC

Okay, after you do the first multiplication, you can do the rest with some bit fiddling. Not guaranteeing that it'll be faster, just giving you an option.

So, after the multiplication, lets represent the result at a(x) + b(x)*x^64, ie the a(x) is stored in the low significance bits, and b(x) is stored in the high end.

What we want to do is carryless add (ie XOR) your p = x^64 + x^4+x^3+x+1 to our result some number of times to get rid of the high end stuff. So, if you ended up with your first product being x^100, then you can add (x^64 + x^4+x^3+x+1)*x^36 without changing your result mod p, and you get x^100 + (x^100 + x^40 + x^39 + x^37 + x^36) = x^40 + x^39 + x^37 + x^36. But, how do you know what to add?

Well, you do it with a multiplication. This is your "r = temp ^ __builtin_ia32_pclmulqdq128(p, temp, 0x10);" line. But, p is very sparse, not many of its bits are non zero, so you can do it in a more low level way. Basically, call the high end half of temp 'b', and the low end bits 'a'. You can form

(b>>64) xor (b>>63) xor (b>>61) xor (b>>60) xor a

and this will very nearly be the answer you want. It *will* be your value r, and I'll call this operation "possibly quick reduction".

[By my, probably erroneous, calculation, that's 9 1 cycle bit fiddles, not all of which need to be in series. I don't know about the speed of the builtins.]

The problem with the value r is that the very high end bits, ie bits 126, 125, 124 (bit 127 will always be 0 in temp) can set bits 66, 65 and 64 to 1 when you do the xor. So you have to do the same "possibly quick reduction" again.

At the very least, your third multiplication *should* be a "possibly quick reduction": both the high end of r and the low end of p are sparse, and doing the product manually should be faster.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

User avatar
Steax
SecondTalon's Goon Squad
Posts: 3038
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Coding: Fleeting Thoughts

Postby Steax » Sun Jun 02, 2013 11:00 am UTC

In Minecraft, I use the username Rirez.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Sun Jun 02, 2013 11:36 am UTC

I tried with the bit shifts, and it ends up being slower. It also ends up being that 64 bit shifts of 128 bit integers are completely broken for some reason.
Summum ius, summa iniuria.

User avatar
Negrebskoh
Posts: 139
Joined: Fri Mar 01, 2013 11:49 pm UTC
Location: The Netherlands

Re: Coding: Fleeting Thoughts

Postby Negrebskoh » Sun Jun 02, 2013 11:42 am UTC

I currently have very mixed feelings about Java.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Sun Jun 02, 2013 11:49 am UTC

Thesh wrote:I tried with the bit shifts, and it ends up being slower. It also ends up being that 64 bit shifts of 128 bit integers are completely broken for some reason.


Scratch that, my test went from 5.8 to 3.5 seconds... I forgot I changed the counter for something else. :oops:

Code: Select all

uint64_t m64(__m128i x, __m128i y) {
   __m128i z;
   uint64_t temp, r;
   
   z = __builtin_ia32_pclmulqdq128(x, y, 0x00);
   temp = _mm_extract_epi64(z,0);
   r = _mm_extract_epi64(z,1);
   
   r ^= (r>>63) ^ (r>>61) ^ (r >> 60);
   return temp ^ r ^ (r << 1) ^ (r<<3) ^ (r<<4);
}


I'll try and figure out the bit shifts. I can probably gain a little bit if I can keep it as a 128 bit integer until all four multiplications for that row of the matrix are complete.

EDIT: doing it all as 128 bit is actually slower; I figured the extra 128 to 64 bit conversions would have more overhead. And I probably just had something else wrong with the 64-bit shifts because it works fine.
Summum ius, summa iniuria.

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Coding: Fleeting Thoughts

Postby jestingrabbit » Sun Jun 02, 2013 12:35 pm UTC

Sweet, glad I could help. :D
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Sun Jun 02, 2013 12:57 pm UTC

It also gives me a good idea. Since bit shifts are significantly faster, I might be able to switch to sparse coefficients for the matrix (which I'm currently using nothing of the sort), and just make it all in bit shifts and xors. Also, as long as I don't have the high five bits of the coefficients set, I don't have to do reflection. This saves me about half a second.
Summum ius, summa iniuria.

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Coding: Fleeting Thoughts

Postby jestingrabbit » Sun Jun 02, 2013 5:11 pm UTC

Thesh wrote:It also gives me a good idea. Since bit shifts are significantly faster, I might be able to switch to sparse coefficients for the matrix (which I'm currently using nothing of the sort), and just make it all in bit shifts and xors.


I think you're going to run into a problem there. What we've got is quick because we know p is sparse and we know which bits are on. In general, finding the sparse bits might give you slowdown.

Also, as long as I don't have the high five bits of the coefficients set, I don't have to do reflection. This saves me about half a second.


I think there are savings to be made dealing with the very high bits, but this isn't how I would do it.

So, let the product of x and y be a 128 bit array, and call it m. Firstly, m[127] = 0 no matter what, so we don't have to worry about that. Let a = m[0 .. 63] be the low significance bits that we don't have to do anything about, b = m[64 .. 123] which we can store as a 64 bit int with no worries, and c0 = m[124], c1 = m[125] and c2 = m[126], the bits that can cause problems.

The answer that we want is going to be a xor b xor (b<<1) xor (b<<3) xor (b<<4), plus some stuff to do with the very high significance bits, but before we worry about that, we can be a little slippery with doing all the stuff with b.

Code: Select all

b ^= (b<<1)
answer = a ^ b ^ (b<<3)


should give the same values as

Code: Select all

answer = a ^ b ^ (b<<1) ^ (b<<3) ^ (b<<4)


And its an assignment, two shits and 3 xors vs 3 shifts and 4 xors. So, it could be a little quicker (the machine might be doing this already, I don't know, an option).

But dealing with the last few bits, c0, c1 and c2, we go back to theory. They represent x^124, x^125 and x^126. Now

x^124 = x^60 + x^61 + x^63 + x^64 = 1 + x + x^3 + x^4 + x^60 + x^61 + x^63

This is just some 64 bit int constant. So, after you get 'answer', if c0 is set, you can xor answer with that constant. Furthermore

x^125 = 1 + x^2 + x^3 + x^5 + x^61 + x^62
x^126 = x + x^3 + x^4 + x^6 + x^62 + x^63

And you can just do the same thing with those bits. So, three ifs and possibly 3 xors.

Another alternative, for these final bits, have an 8 way case, and at each possibility, you do a single xor. I think that this would be quickest, and least transparent, code.

So, anyway, thoughts, there they are.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Sun Jun 02, 2013 5:25 pm UTC

jestingrabbit wrote:
Thesh wrote:It also gives me a good idea. Since bit shifts are significantly faster, I might be able to switch to sparse coefficients for the matrix (which I'm currently using nothing of the sort), and just make it all in bit shifts and xors.


I think you're going to run into a problem there. What we've got is quick because we know p is sparse and we know which bits are on. In general, finding the sparse bits might give you slowdown.

Also, as long as I don't have the high five bits of the coefficients set, I don't have to do reflection. This saves me about half a second.


I think there are savings to be made dealing with the very high bits, but this isn't how I would do it.


The coefficients are predetermined constants, so I am always free to choose constants that will give me better performance. The problem comes in that finding an invertible matrix that is both sparse and doesn't have the high bits set is either going to be difficult to find or non-existent. That said, an invertible matrix where just the high bits of both the matrix and the inverse of the matrix aren't set is more doable. Also, I realized it's the high three bits that need to be zero, not the high five bits.
Summum ius, summa iniuria.

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Coding: Fleeting Thoughts

Postby jestingrabbit » Sun Jun 02, 2013 5:36 pm UTC

Thesh wrote:Also, I realized it's the high three bits that need to be zero, not the high five bits.


Yeah, I guessed that was a typo.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

elminster
Posts: 1560
Joined: Mon Feb 26, 2007 1:56 pm UTC
Location: London, UK, Dimensions 1 to 42.
Contact:

Re: Coding: Fleeting Thoughts

Postby elminster » Mon Jun 03, 2013 8:59 am UTC

SIMD instructions are really quite awesome. Although, for every new set that comes out, it makes me think of how long it will be before it becomes standard. Naturally in a closed environment where you have control of all the hardware you can use whatever or you could (should) enable/disable use of them as needed, but when when it's public releases it's kind of annoying when you have to consider the average person won't have the newer stuff for many years. Not that it matters so much, but people don't get to experience your fancy new optimizations.

An example of this would be Windows 8 explicitly requiring SSE2 support, despite being around 13 years old and providing significant performance improvements, they couldn't really require it till recently.
Image

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Sat Jun 08, 2013 11:36 pm UTC

The internet is apparently so small that I randomly bumped into this.
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Mon Jun 10, 2013 7:14 pm UTC

I'm noticing now that the code base as work has several classes, that all inherit from the same base class, that all have an exact copy of a specific method.

The method is also marked virtual, as though the person writing it knew about overloads.

The sad thing is I added a classes inheriting the super-parent that made sure to avoid doing something like that a few years ago. Too bad I didn't wander the full class tree to refactor all of it.

EDIT: And now I'm refactoring things I shouldn't. So I probably will just shelve this changeset forever. BUT AT LEAST I'LL KNOW IT COULD BE DONE. <_<

EDIT2: I may have been defeated anyway. Apparently this poorly designed abstraction is a cancer that has infected most of the subclasses. There's a few really really nice classes where it's a drop-in replacement (and removes 4 or so methods that are duplicated in every class) but other inheritors do weird things.

Also, I found out that if there is a virtual property with only a get accessor, you can't add a setter in a derived class. :?

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Mon Jun 10, 2013 10:11 pm UTC

This feels very very anti-pattern. I'm just not sure what the "right" way to fix this would even be. Probably refactoring the class hierarchy but that's way too high risk.

I don't know why X in this case behaves almost entirely different than the base class, but Y goes back...

Code: Select all

class X : SomeBaseClass
{
    protected bool DoBaseClassThing {get; set;}
    protected override void BaseClassThing(){
        if(DoBaseClassThing){
            base.BaseClassThing();
        }
    }
}

class Y : X
{
    public Y(){
        DoBaseClassThing = true;
    }
}

User avatar
Aaeriele
Posts: 2127
Joined: Tue Feb 23, 2010 3:30 am UTC
Location: San Francisco, CA

Re: Coding: Fleeting Thoughts

Postby Aaeriele » Tue Jun 11, 2013 2:12 am UTC

Perhaps add a method to class X that X::BaseClassThing always calls, which in class X is empty but in class Y is overridden to call the proper thing in the base class? (Basically, use overriding of a basic method instead of a flag.)
Vaniver wrote:Harvard is a hedge fund that runs the most prestigious dating agency in the world, and incidentally employs famous scientists to do research.

afuzzyduck wrote:ITS MEANT TO BE FLUTTERSHY BUT I JUST SEE AAERIELE! CURSE YOU FORA!

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Tue Jun 11, 2013 2:48 am UTC

Aaeriele wrote:Perhaps add a method to class X that X::BaseClassThing always calls, which in class X is empty but in class Y is overridden to call the proper thing in the base class? (Basically, use overriding of a basic method instead of a flag.)
I don't know how I would do that without duplicating the code in the BaseClass.BaseClassThing(). Well, maybe instead go all the way up to BaseClass, move all its logic to a separate protected method which the BaseClassThing calls, in X override with an empty method, and in Y override with the same call as in BaseClass (only one 'duplicated' line then).

Given I have to do this for at least 3 different methods I'm not sure leaving the flag intact isn't the lesser of two evils though. Oh well. :?

User avatar
Aaeriele
Posts: 2127
Joined: Tue Feb 23, 2010 3:30 am UTC
Location: San Francisco, CA

Re: Coding: Fleeting Thoughts

Postby Aaeriele » Tue Jun 11, 2013 3:54 am UTC

Xeio wrote:
Aaeriele wrote:Perhaps add a method to class X that X::BaseClassThing always calls, which in class X is empty but in class Y is overridden to call the proper thing in the base class? (Basically, use overriding of a basic method instead of a flag.)
I don't know how I would do that without duplicating the code in the BaseClass.BaseClassThing(). Well, maybe instead go all the way up to BaseClass, move all its logic to a separate protected method which the BaseClassThing calls, in X override with an empty method, and in Y override with the same call as in BaseClass (only one 'duplicated' line then).

Given I have to do this for at least 3 different methods I'm not sure leaving the flag intact isn't the lesser of two evils though. Oh well. :?


Omitting some keywords and pseudocoding a little, for brevity... here is what I was envisioning:

Code: Select all

class X {
   BaseClassThing() {
      // ...
      MaybeBaseClassThing();
      // ...
   }

   MaybeBaseClassThing() {} // do-nothing function
}

class Y : X {
   MaybeBaseClassThing() {
      base.BaseClassThing();
   }
}
Vaniver wrote:Harvard is a hedge fund that runs the most prestigious dating agency in the world, and incidentally employs famous scientists to do research.

afuzzyduck wrote:ITS MEANT TO BE FLUTTERSHY BUT I JUST SEE AAERIELE! CURSE YOU FORA!

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Tue Jun 11, 2013 7:53 am UTC

Renaming things in the example (sorry) to make it a bit easier to follow... Also, switching to C++ because I don't know C#. Say we have, in your example:

Code: Select all

class BaseClass
{
  protected:
  virtual void DoAThing()
  {
    printf("I'm doing a base class thing!\n");
  }
}

class Foo : public BaseClass
{
  protected:
  bool DoBaseClassThing;
  virtual void DoAThing()
  {
    if (DoBaseClassThing)
      BaseClass::DoAThing();
    else
      printf("I'm doing an overridden thing!\n");
  }
  public:
  Foo() : DoBaseClassThing(false) {}
}

class Bar : public Foo
{
  public:
  Bar() : DoBaseClassThing(true) {}
}
It seems to me that if you want to have BaseClass::DoAThing to be available in Bar, you should explicitly make it available, as a protected member of Foo:

Code: Select all

class BaseClass
{
  protected:
  virtual void DoAThing()
  {
    printf("I'm doing a base class thing!\n");
  }
}

class Foo : public BaseClass
{
  protected:
  virtual void DoAThing()
  {
    printf("I'm doing an overridden thing!\n");
  }
  void DoBaseClassThing()
  {
    BaseClass::DoAThing();
  }
}

class Bar : public Foo
{
  protected:
  virtual void DoAThing()
  {
    DoBaseClassThing();
  }
}
Since that's essentially a cleaner way to do what you're doing already, with Foo making the base-class implementation of the method available to further subclasses... but without the weird behavior-controlling flags hanging around.

The whole thing still feels bad, and I'm sure that more indepth refactoring would be very useful in whatever specific case this is coming from, but it seems like this is a way of at least cleaning it up somewhat without being as intrusive...

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Tue Jun 11, 2013 2:23 pm UTC

phlip wrote:The whole thing still feels bad, and I'm sure that more indepth refactoring would be very useful in whatever specific case this is coming from, but it seems like this is a way of at least cleaning it up somewhat without being as intrusive...
I cleaned it up a little and it's a lot easier to read now, particularly now that the only thing the Y/Bar class does is set the flag (and a related field) in its constructor, it doesn't need/have any other methods. So I may just leave it as a flag if only for readability. I don't think adding 6+ new methods and overrides would make it easier to understand, but that's a bit personal preference.

Looking at it a bit more I'm wondering if someone just really wanted to try multiple inheritance, found that they couldn't, and decided that a string of inheritance would work instead. That's a bit of speculation based on the functionality (and my best guess as to the order these classes were created in).

elminster
Posts: 1560
Joined: Mon Feb 26, 2007 1:56 pm UTC
Location: London, UK, Dimensions 1 to 42.
Contact:

Re: Coding: Fleeting Thoughts

Postby elminster » Wed Jun 12, 2013 5:10 am UTC

This may be a stupid question, but can compiler optimisers change the use of function pointers and std::function objects to early/static binding if they're only set once to a know function?
e.g.
Spoiler:

Code: Select all

void print_num(int i)
{
    std::cout << i;
}
 
int main()
{
    std::function<void(int)> display = print_num;
    display(-9);
}
would essentially become

Code: Select all

void print_num(int i)
{
    std::cout << i;
}
 
int main()
{
    print_num(-9);
}
then automatically inline to

Code: Select all

int main()
{
    std::cout << -9;
}
Image

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Wed Jun 12, 2013 5:18 am UTC

It seems pretty unlikely for std::function, given they're actual objects, and you'd have to satisfy a lot more conditions (and be a much more narrow optimisation) to be able to completely optimise them away. For actual function_pointers, though, I can see it being possible... I know many compilers will do constexpr analysis on variables (eg if a non-volatile variable is set to 27 and is never changed, then you can replace a variable-read with just a static 27 when compiling) so I don't see why it couldn't do the same for funcptrs.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Wed Jun 12, 2013 5:31 am UTC

Spoiler:
with -O0

Code: Select all

   .file   "opttest.cpp"
   .section   .rodata
   .type   _ZStL19piecewise_construct, @object
   .size   _ZStL19piecewise_construct, 1
_ZStL19piecewise_construct:
   .zero   1
   .section   .text._ZnwmPv,"axG",@progbits,_ZnwmPv,comdat
   .weak   _ZnwmPv
   .type   _ZnwmPv, @function
_ZnwmPv:
.LFB378:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movq   %rdi, -8(%rbp)
   movq   %rsi, -16(%rbp)
   movq   -16(%rbp), %rax
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE378:
   .size   _ZnwmPv, .-_ZnwmPv
   .local   _ZStL8__ioinit
   .comm   _ZStL8__ioinit,1,1
   .section   .rodata
   .type   _ZStL13allocator_arg, @object
   .size   _ZStL13allocator_arg, 1
_ZStL13allocator_arg:
   .zero   1
   .type   _ZStL6ignore, @object
   .size   _ZStL6ignore, 1
_ZStL6ignore:
   .zero   1
   .section   .text._ZNSt9_Any_data9_M_accessEv,"axG",@progbits,_ZNSt9_Any_data9_M_accessEv,comdat
   .align 2
   .weak   _ZNSt9_Any_data9_M_accessEv
   .type   _ZNSt9_Any_data9_M_accessEv, @function
_ZNSt9_Any_data9_M_accessEv:
.LFB1481:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1481:
   .size   _ZNSt9_Any_data9_M_accessEv, .-_ZNSt9_Any_data9_M_accessEv
   .section   .text._ZNKSt9_Any_data9_M_accessEv,"axG",@progbits,_ZNKSt9_Any_data9_M_accessEv,comdat
   .align 2
   .weak   _ZNKSt9_Any_data9_M_accessEv
   .type   _ZNKSt9_Any_data9_M_accessEv, @function
_ZNKSt9_Any_data9_M_accessEv:
.LFB1482:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1482:
   .size   _ZNKSt9_Any_data9_M_accessEv, .-_ZNKSt9_Any_data9_M_accessEv
   .section   .text._ZNSt14_Function_baseC2Ev,"axG",@progbits,_ZNSt14_Function_baseC5Ev,comdat
   .align 2
   .weak   _ZNSt14_Function_baseC2Ev
   .type   _ZNSt14_Function_baseC2Ev, @function
_ZNSt14_Function_baseC2Ev:
.LFB1507:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   movq   $0, 16(%rax)
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1507:
   .size   _ZNSt14_Function_baseC2Ev, .-_ZNSt14_Function_baseC2Ev
   .weak   _ZNSt14_Function_baseC1Ev
   .set   _ZNSt14_Function_baseC1Ev,_ZNSt14_Function_baseC2Ev
   .section   .text._ZNSt14_Function_baseD2Ev,"axG",@progbits,_ZNSt14_Function_baseD5Ev,comdat
   .align 2
   .weak   _ZNSt14_Function_baseD2Ev
   .type   _ZNSt14_Function_baseD2Ev, @function
_ZNSt14_Function_baseD2Ev:
.LFB1510:
   .cfi_startproc
   .cfi_personality 0x3,__gxx_personality_v0
   .cfi_lsda 0x3,.LLSDA1510
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $16, %rsp
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   movq   16(%rax), %rax
   testq   %rax, %rax
   je   .L8
   movq   -8(%rbp), %rax
   movq   16(%rax), %rax
   movq   -8(%rbp), %rsi
   movq   -8(%rbp), %rcx
   movl   $3, %edx
   movq   %rcx, %rdi
   call   *%rax
.L8:
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1510:
   .globl   __gxx_personality_v0
   .section   .gcc_except_table._ZNSt14_Function_baseD2Ev,"aG",@progbits,_ZNSt14_Function_baseD5Ev,comdat
.LLSDA1510:
   .byte   0xff
   .byte   0xff
   .byte   0x1
   .uleb128 .LLSDACSE1510-.LLSDACSB1510
.LLSDACSB1510:
.LLSDACSE1510:
   .section   .text._ZNSt14_Function_baseD2Ev,"axG",@progbits,_ZNSt14_Function_baseD5Ev,comdat
   .size   _ZNSt14_Function_baseD2Ev, .-_ZNSt14_Function_baseD2Ev
   .weak   _ZNSt14_Function_baseD1Ev
   .set   _ZNSt14_Function_baseD1Ev,_ZNSt14_Function_baseD2Ev
   .section   .text._ZNKSt14_Function_base8_M_emptyEv,"axG",@progbits,_ZNKSt14_Function_base8_M_emptyEv,comdat
   .align 2
   .weak   _ZNKSt14_Function_base8_M_emptyEv
   .type   _ZNKSt14_Function_base8_M_emptyEv, @function
_ZNKSt14_Function_base8_M_emptyEv:
.LFB1512:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   movq   16(%rax), %rax
   testq   %rax, %rax
   sete   %al
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1512:
   .size   _ZNKSt14_Function_base8_M_emptyEv, .-_ZNKSt14_Function_base8_M_emptyEv
   .text
   .globl   _Z9print_numi
   .type   _Z9print_numi, @function
_Z9print_numi:
.LFB1541:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $16, %rsp
   movl   %edi, -4(%rbp)
   movl   -4(%rbp), %eax
   movl   %eax, %esi
   movl   $_ZSt4cout, %edi
   call   _ZNSolsEi
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1541:
   .size   _Z9print_numi, .-_Z9print_numi
   .section   .text._ZNSt8functionIFviEED2Ev,"axG",@progbits,_ZNSt8functionIFviEED5Ev,comdat
   .align 2
   .weak   _ZNSt8functionIFviEED2Ev
   .type   _ZNSt8functionIFviEED2Ev, @function
_ZNSt8functionIFviEED2Ev:
.LFB1544:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $16, %rsp
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt14_Function_baseD2Ev
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1544:
   .size   _ZNSt8functionIFviEED2Ev, .-_ZNSt8functionIFviEED2Ev
   .weak   _ZNSt8functionIFviEED1Ev
   .set   _ZNSt8functionIFviEED1Ev,_ZNSt8functionIFviEED2Ev
   .text
   .globl   main
   .type   main, @function
main:
.LFB1542:
   .cfi_startproc
   .cfi_personality 0x3,__gxx_personality_v0
   .cfi_lsda 0x3,.LLSDA1542
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   pushq   %rbx
   subq   $40, %rsp
   .cfi_offset 3, -24
   leaq   -48(%rbp), %rax
   movl   $_Z9print_numi, %esi
   movq   %rax, %rdi
.LEHB0:
   call   _ZNSt8functionIFviEEC1IPS0_vEET_
.LEHE0:
   leaq   -48(%rbp), %rax
   movl   $-9, %esi
   movq   %rax, %rdi
.LEHB1:
   call   _ZNKSt8functionIFviEEclEi
.LEHE1:
   leaq   -48(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt8functionIFviEED1Ev
   movl   $0, %eax
   jmp   .L21
.L20:
   movq   %rax, %rbx
   leaq   -48(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt8functionIFviEED1Ev
   movq   %rbx, %rax
   jmp   .L18
.L19:
.L18:
   movq   %rax, %rdi
.LEHB2:
   call   _Unwind_Resume
.LEHE2:
.L21:
   addq   $40, %rsp
   popq   %rbx
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1542:
   .section   .gcc_except_table,"a",@progbits
.LLSDA1542:
   .byte   0xff
   .byte   0xff
   .byte   0x1
   .uleb128 .LLSDACSE1542-.LLSDACSB1542
.LLSDACSB1542:
   .uleb128 .LEHB0-.LFB1542
   .uleb128 .LEHE0-.LEHB0
   .uleb128 .L19-.LFB1542
   .uleb128 0
   .uleb128 .LEHB1-.LFB1542
   .uleb128 .LEHE1-.LEHB1
   .uleb128 .L20-.LFB1542
   .uleb128 0
   .uleb128 .LEHB2-.LFB1542
   .uleb128 .LEHE2-.LEHB2
   .uleb128 0
   .uleb128 0
.LLSDACSE1542:
   .text
   .size   main, .-main
   .section   .text._ZNSt14unary_functionIivEC2Ev,"axG",@progbits,_ZNSt14unary_functionIivEC5Ev,comdat
   .align 2
   .weak   _ZNSt14unary_functionIivEC2Ev
   .type   _ZNSt14unary_functionIivEC2Ev, @function
_ZNSt14unary_functionIivEC2Ev:
.LFB1603:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movq   %rdi, -8(%rbp)
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1603:
   .size   _ZNSt14unary_functionIivEC2Ev, .-_ZNSt14unary_functionIivEC2Ev
   .weak   _ZNSt14unary_functionIivEC1Ev
   .set   _ZNSt14unary_functionIivEC1Ev,_ZNSt14unary_functionIivEC2Ev
   .section   .text._ZNSt31_Maybe_unary_or_binary_functionIvIiEEC2Ev,"axG",@progbits,_ZNSt31_Maybe_unary_or_binary_functionIvIiEEC5Ev,comdat
   .align 2
   .weak   _ZNSt31_Maybe_unary_or_binary_functionIvIiEEC2Ev
   .type   _ZNSt31_Maybe_unary_or_binary_functionIvIiEEC2Ev, @function
_ZNSt31_Maybe_unary_or_binary_functionIvIiEEC2Ev:
.LFB1605:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $16, %rsp
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt14unary_functionIivEC2Ev
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1605:
   .size   _ZNSt31_Maybe_unary_or_binary_functionIvIiEEC2Ev, .-_ZNSt31_Maybe_unary_or_binary_functionIvIiEEC2Ev
   .weak   _ZNSt31_Maybe_unary_or_binary_functionIvJiEEC2Ev
   .set   _ZNSt31_Maybe_unary_or_binary_functionIvJiEEC2Ev,_ZNSt31_Maybe_unary_or_binary_functionIvIiEEC2Ev
   .weak   _ZNSt31_Maybe_unary_or_binary_functionIvIiEEC1Ev
   .set   _ZNSt31_Maybe_unary_or_binary_functionIvIiEEC1Ev,_ZNSt31_Maybe_unary_or_binary_functionIvIiEEC2Ev
   .weak   _ZNSt31_Maybe_unary_or_binary_functionIvJiEEC1Ev
   .set   _ZNSt31_Maybe_unary_or_binary_functionIvJiEEC1Ev,_ZNSt31_Maybe_unary_or_binary_functionIvIiEEC1Ev
   .section   .text._ZSt4moveIRPFviEEONSt16remove_referenceIT_E4typeEOS4_,"axG",@progbits,_ZSt4moveIRPFviEEONSt16remove_referenceIT_E4typeEOS4_,comdat
   .weak   _ZSt4moveIRPFviEEONSt16remove_referenceIT_E4typeEOS4_
   .type   _ZSt4moveIRPFviEEONSt16remove_referenceIT_E4typeEOS4_, @function
_ZSt4moveIRPFviEEONSt16remove_referenceIT_E4typeEOS4_:
.LFB1607:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1607:
   .size   _ZSt4moveIRPFviEEONSt16remove_referenceIT_E4typeEOS4_, .-_ZSt4moveIRPFviEEONSt16remove_referenceIT_E4typeEOS4_
   .section   .text._ZNSt8functionIFviEEC2IPS0_vEET_,"axG",@progbits,_ZNSt8functionIFviEEC5IPS0_vEET_,comdat
   .align 2
   .weak   _ZNSt8functionIFviEEC2IPS0_vEET_
   .type   _ZNSt8functionIFviEEC2IPS0_vEET_, @function
_ZNSt8functionIFviEEC2IPS0_vEET_:
.LFB1608:
   .cfi_startproc
   .cfi_personality 0x3,__gxx_personality_v0
   .cfi_lsda 0x3,.LLSDA1608
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   pushq   %rbx
   subq   $24, %rsp
   .cfi_offset 3, -24
   movq   %rdi, -24(%rbp)
   movq   %rsi, -32(%rbp)
   movq   -24(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt31_Maybe_unary_or_binary_functionIvIiEEC2Ev
   movq   -24(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt14_Function_baseC2Ev
   leaq   -32(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt14_Function_base13_Base_managerIPFviEE21_M_not_empty_functionIS2_EEbRKT_
   testb   %al, %al
   je   .L30
   leaq   -32(%rbp), %rax
   movq   %rax, %rdi
   call   _ZSt4moveIRPFviEEONSt16remove_referenceIT_E4typeEOS4_
   movq   %rax, %rdx
   movq   -24(%rbp), %rax
   movq   %rdx, %rsi
   movq   %rax, %rdi
.LEHB3:
   call   _ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_
.LEHE3:
   movq   -24(%rbp), %rax
   movq   $_ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai, 24(%rax)
   movq   -24(%rbp), %rax
   movq   $_ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation, 16(%rax)
   jmp   .L30
.L29:
   movq   %rax, %rbx
   movq   -24(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt14_Function_baseD2Ev
   movq   %rbx, %rax
   movq   %rax, %rdi
.LEHB4:
   call   _Unwind_Resume
.LEHE4:
.L30:
   addq   $24, %rsp
   popq   %rbx
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1608:
   .section   .gcc_except_table
.LLSDA1608:
   .byte   0xff
   .byte   0xff
   .byte   0x1
   .uleb128 .LLSDACSE1608-.LLSDACSB1608
.LLSDACSB1608:
   .uleb128 .LEHB3-.LFB1608
   .uleb128 .LEHE3-.LEHB3
   .uleb128 .L29-.LFB1608
   .uleb128 0
   .uleb128 .LEHB4-.LFB1608
   .uleb128 .LEHE4-.LEHB4
   .uleb128 0
   .uleb128 0
.LLSDACSE1608:
   .section   .text._ZNSt8functionIFviEEC2IPS0_vEET_,"axG",@progbits,_ZNSt8functionIFviEEC5IPS0_vEET_,comdat
   .size   _ZNSt8functionIFviEEC2IPS0_vEET_, .-_ZNSt8functionIFviEEC2IPS0_vEET_
   .weak   _ZNSt8functionIFviEEC1IPS0_vEET_
   .set   _ZNSt8functionIFviEEC1IPS0_vEET_,_ZNSt8functionIFviEEC2IPS0_vEET_
   .section   .text._ZSt7forwardIiEOT_RNSt16remove_referenceIS0_E4typeE,"axG",@progbits,_ZSt7forwardIiEOT_RNSt16remove_referenceIS0_E4typeE,comdat
   .weak   _ZSt7forwardIiEOT_RNSt16remove_referenceIS0_E4typeE
   .type   _ZSt7forwardIiEOT_RNSt16remove_referenceIS0_E4typeE, @function
_ZSt7forwardIiEOT_RNSt16remove_referenceIS0_E4typeE:
.LFB1614:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1614:
   .size   _ZSt7forwardIiEOT_RNSt16remove_referenceIS0_E4typeE, .-_ZSt7forwardIiEOT_RNSt16remove_referenceIS0_E4typeE
   .section   .text._ZNKSt8functionIFviEEclEi,"axG",@progbits,_ZNKSt8functionIFviEEclEi,comdat
   .align 2
   .weak   _ZNKSt8functionIFviEEclEi
   .type   _ZNKSt8functionIFviEEclEi, @function
_ZNKSt8functionIFviEEclEi:
.LFB1613:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   pushq   %rbx
   subq   $24, %rsp
   .cfi_offset 3, -24
   movq   %rdi, -24(%rbp)
   movl   %esi, -28(%rbp)
   movq   -24(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNKSt14_Function_base8_M_emptyEv
   testb   %al, %al
   je   .L34
   call   _ZSt25__throw_bad_function_callv
.L34:
   movq   -24(%rbp), %rax
   movq   24(%rax), %rbx
   leaq   -28(%rbp), %rax
   movq   %rax, %rdi
   call   _ZSt7forwardIiEOT_RNSt16remove_referenceIS0_E4typeE
   movl   (%rax), %edx
   movq   -24(%rbp), %rax
   movl   %edx, %esi
   movq   %rax, %rdi
   call   *%rbx
   addq   $24, %rsp
   popq   %rbx
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1613:
   .size   _ZNKSt8functionIFviEEclEi, .-_ZNKSt8functionIFviEEclEi
   .section   .text._ZNSt14_Function_base13_Base_managerIPFviEE21_M_not_empty_functionIS2_EEbRKT_,"axG",@progbits,_ZNSt14_Function_base13_Base_managerIPFviEE21_M_not_empty_functionIS2_EEbRKT_,comdat
   .weak   _ZNSt14_Function_base13_Base_managerIPFviEE21_M_not_empty_functionIS2_EEbRKT_
   .type   _ZNSt14_Function_base13_Base_managerIPFviEE21_M_not_empty_functionIS2_EEbRKT_, @function
_ZNSt14_Function_base13_Base_managerIPFviEE21_M_not_empty_functionIS2_EEbRKT_:
.LFB1657:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movq   %rdi, -8(%rbp)
   movl   $1, %eax
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1657:
   .size   _ZNSt14_Function_base13_Base_managerIPFviEE21_M_not_empty_functionIS2_EEbRKT_, .-_ZNSt14_Function_base13_Base_managerIPFviEE21_M_not_empty_functionIS2_EEbRKT_
   .section   .text._ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_,"axG",@progbits,_ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_,comdat
   .weak   _ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_
   .type   _ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_, @function
_ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_:
.LFB1658:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   pushq   %rbx
   subq   $56, %rsp
   .cfi_offset 3, -24
   movq   %rdi, -40(%rbp)
   movq   %rsi, -48(%rbp)
   movq   -48(%rbp), %rax
   movq   %rax, %rdi
   call   _ZSt4moveIRPFviEEONSt16remove_referenceIT_E4typeEOS4_
   movq   %rax, %rdx
   movq   -40(%rbp), %rax
   movb   %bl, (%rsp)
   movq   %rdx, %rsi
   movq   %rax, %rdi
   call   _ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_St17integral_constantIbLb1EE
   addq   $56, %rsp
   popq   %rbx
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1658:
   .size   _ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_, .-_ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_
   .section   .text._ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai,"axG",@progbits,_ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai,comdat
   .weak   _ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai
   .type   _ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai, @function
_ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai:
.LFB1659:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   pushq   %rbx
   subq   $24, %rsp
   .cfi_offset 3, -24
   movq   %rdi, -24(%rbp)
   movl   %esi, -28(%rbp)
   movq   -24(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt14_Function_base13_Base_managerIPFviEE14_M_get_pointerERKSt9_Any_data
   movq   (%rax), %rbx
   leaq   -28(%rbp), %rax
   movq   %rax, %rdi
   call   _ZSt7forwardIiEOT_RNSt16remove_referenceIS0_E4typeE
   movl   (%rax), %eax
   movl   %eax, %edi
   call   *%rbx
   addq   $24, %rsp
   popq   %rbx
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1659:
   .size   _ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai, .-_ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai
   .section   .text._ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation,"axG",@progbits,_ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation,comdat
   .weak   _ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation
   .type   _ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation, @function
_ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation:
.LFB1660:
   .cfi_startproc
   .cfi_personality 0x3,__gxx_personality_v0
   .cfi_lsda 0x3,.LLSDA1660
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   pushq   %rbx
   subq   $56, %rsp
   .cfi_offset 3, -24
   movq   %rdi, -40(%rbp)
   movq   %rsi, -48(%rbp)
   movl   %edx, -52(%rbp)
   movl   -52(%rbp), %eax
   cmpl   $1, %eax
   je   .L42
   cmpl   $1, %eax
   jg   .L43
   testl   %eax, %eax
   je   .L44
   jmp   .L41
.L43:
   cmpl   $2, %eax
   je   .L45
   cmpl   $3, %eax
   je   .L46
   jmp   .L41
.L44:
   movq   -40(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt9_Any_data9_M_accessIPKSt9type_infoEERT_v
   movq   $_ZTIPFviE, (%rax)
   jmp   .L41
.L42:
   movq   -40(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt9_Any_data9_M_accessIPPFviEEERT_v
   movq   %rax, %rbx
   movq   -48(%rbp), %rax
   movq   %rax, %rdi
.LEHB5:
   call   _ZNSt14_Function_base13_Base_managerIPFviEE14_M_get_pointerERKSt9_Any_data
.LEHE5:
   movq   %rax, (%rbx)
   jmp   .L41
.L45:
   movq   -48(%rbp), %rdx
   movq   -40(%rbp), %rax
   movb   %r8b, (%rsp)
   movq   %rdx, %rsi
   movq   %rax, %rdi
.LEHB6:
   call   _ZNSt14_Function_base13_Base_managerIPFviEE8_M_cloneERSt9_Any_dataRKS4_St17integral_constantIbLb1EE
.LEHE6:
   jmp   .L41
.L46:
   movq   -40(%rbp), %rax
   movb   %cl, (%rsp)
   movq   %rax, %rdi
.LEHB7:
   call   _ZNSt14_Function_base13_Base_managerIPFviEE10_M_destroyERSt9_Any_dataSt17integral_constantIbLb1EE
.LEHE7:
   nop
.L41:
   movl   $0, %eax
   jmp   .L52
.L50:
   movq   %rax, %rdi
.LEHB8:
   call   _Unwind_Resume
.L51:
   movq   %rax, %rdi
   call   _Unwind_Resume
.LEHE8:
.L52:
   addq   $56, %rsp
   popq   %rbx
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1660:
   .section   .gcc_except_table
.LLSDA1660:
   .byte   0xff
   .byte   0xff
   .byte   0x1
   .uleb128 .LLSDACSE1660-.LLSDACSB1660
.LLSDACSB1660:
   .uleb128 .LEHB5-.LFB1660
   .uleb128 .LEHE5-.LEHB5
   .uleb128 0
   .uleb128 0
   .uleb128 .LEHB6-.LFB1660
   .uleb128 .LEHE6-.LEHB6
   .uleb128 .L50-.LFB1660
   .uleb128 0
   .uleb128 .LEHB7-.LFB1660
   .uleb128 .LEHE7-.LEHB7
   .uleb128 .L51-.LFB1660
   .uleb128 0
   .uleb128 .LEHB8-.LFB1660
   .uleb128 .LEHE8-.LEHB8
   .uleb128 0
   .uleb128 0
.LLSDACSE1660:
   .section   .text._ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation,"axG",@progbits,_ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation,comdat
   .size   _ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation, .-_ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation
   .section   .text._ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_St17integral_constantIbLb1EE,"axG",@progbits,_ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_St17integral_constantIbLb1EE,comdat
   .weak   _ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_St17integral_constantIbLb1EE
   .type   _ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_St17integral_constantIbLb1EE, @function
_ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_St17integral_constantIbLb1EE:
.LFB1690:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   pushq   %rbx
   subq   $24, %rsp
   .cfi_offset 3, -24
   movq   %rdi, -24(%rbp)
   movq   %rsi, -32(%rbp)
   movq   -32(%rbp), %rax
   movq   %rax, %rdi
   call   _ZSt4moveIRPFviEEONSt16remove_referenceIT_E4typeEOS4_
   movq   (%rax), %rbx
   movq   -24(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt9_Any_data9_M_accessEv
   movq   %rax, %rsi
   movl   $8, %edi
   call   _ZnwmPv
   testq   %rax, %rax
   je   .L53
   movq   %rbx, (%rax)
.L53:
   addq   $24, %rsp
   popq   %rbx
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1690:
   .size   _ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_St17integral_constantIbLb1EE, .-_ZNSt14_Function_base13_Base_managerIPFviEE15_M_init_functorERSt9_Any_dataOS2_St17integral_constantIbLb1EE
   .section   .text._ZNSt14_Function_base13_Base_managerIPFviEE14_M_get_pointerERKSt9_Any_data,"axG",@progbits,_ZNSt14_Function_base13_Base_managerIPFviEE14_M_get_pointerERKSt9_Any_data,comdat
   .weak   _ZNSt14_Function_base13_Base_managerIPFviEE14_M_get_pointerERKSt9_Any_data
   .type   _ZNSt14_Function_base13_Base_managerIPFviEE14_M_get_pointerERKSt9_Any_data, @function
_ZNSt14_Function_base13_Base_managerIPFviEE14_M_get_pointerERKSt9_Any_data:
.LFB1691:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $32, %rsp
   movq   %rdi, -24(%rbp)
   movq   -24(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNKSt9_Any_data9_M_accessIPFviEEERKT_v
   movq   %rax, %rdi
   call   _ZSt11__addressofIKPFviEEPT_RS3_
   movq   %rax, -8(%rbp)
   movq   -8(%rbp), %rax
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1691:
   .size   _ZNSt14_Function_base13_Base_managerIPFviEE14_M_get_pointerERKSt9_Any_data, .-_ZNSt14_Function_base13_Base_managerIPFviEE14_M_get_pointerERKSt9_Any_data
   .section   .text._ZNSt9_Any_data9_M_accessIPKSt9type_infoEERT_v,"axG",@progbits,_ZNSt9_Any_data9_M_accessIPKSt9type_infoEERT_v,comdat
   .align 2
   .weak   _ZNSt9_Any_data9_M_accessIPKSt9type_infoEERT_v
   .type   _ZNSt9_Any_data9_M_accessIPKSt9type_infoEERT_v, @function
_ZNSt9_Any_data9_M_accessIPKSt9type_infoEERT_v:
.LFB1692:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $16, %rsp
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt9_Any_data9_M_accessEv
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1692:
   .size   _ZNSt9_Any_data9_M_accessIPKSt9type_infoEERT_v, .-_ZNSt9_Any_data9_M_accessIPKSt9type_infoEERT_v
   .section   .text._ZNSt9_Any_data9_M_accessIPPFviEEERT_v,"axG",@progbits,_ZNSt9_Any_data9_M_accessIPPFviEEERT_v,comdat
   .align 2
   .weak   _ZNSt9_Any_data9_M_accessIPPFviEEERT_v
   .type   _ZNSt9_Any_data9_M_accessIPPFviEEERT_v, @function
_ZNSt9_Any_data9_M_accessIPPFviEEERT_v:
.LFB1693:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $16, %rsp
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt9_Any_data9_M_accessEv
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1693:
   .size   _ZNSt9_Any_data9_M_accessIPPFviEEERT_v, .-_ZNSt9_Any_data9_M_accessIPPFviEEERT_v
   .section   .text._ZNSt14_Function_base13_Base_managerIPFviEE8_M_cloneERSt9_Any_dataRKS4_St17integral_constantIbLb1EE,"axG",@progbits,_ZNSt14_Function_base13_Base_managerIPFviEE8_M_cloneERSt9_Any_dataRKS4_St17integral_constantIbLb1EE,comdat
   .weak   _ZNSt14_Function_base13_Base_managerIPFviEE8_M_cloneERSt9_Any_dataRKS4_St17integral_constantIbLb1EE
   .type   _ZNSt14_Function_base13_Base_managerIPFviEE8_M_cloneERSt9_Any_dataRKS4_St17integral_constantIbLb1EE, @function
_ZNSt14_Function_base13_Base_managerIPFviEE8_M_cloneERSt9_Any_dataRKS4_St17integral_constantIbLb1EE:
.LFB1694:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   pushq   %rbx
   subq   $24, %rsp
   .cfi_offset 3, -24
   movq   %rdi, -24(%rbp)
   movq   %rsi, -32(%rbp)
   movq   -32(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNKSt9_Any_data9_M_accessIPFviEEERKT_v
   movq   (%rax), %rbx
   movq   -24(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt9_Any_data9_M_accessEv
   movq   %rax, %rsi
   movl   $8, %edi
   call   _ZnwmPv
   testq   %rax, %rax
   je   .L62
   movq   %rbx, (%rax)
.L62:
   addq   $24, %rsp
   popq   %rbx
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1694:
   .size   _ZNSt14_Function_base13_Base_managerIPFviEE8_M_cloneERSt9_Any_dataRKS4_St17integral_constantIbLb1EE, .-_ZNSt14_Function_base13_Base_managerIPFviEE8_M_cloneERSt9_Any_dataRKS4_St17integral_constantIbLb1EE
   .section   .text._ZNSt14_Function_base13_Base_managerIPFviEE10_M_destroyERSt9_Any_dataSt17integral_constantIbLb1EE,"axG",@progbits,_ZNSt14_Function_base13_Base_managerIPFviEE10_M_destroyERSt9_Any_dataSt17integral_constantIbLb1EE,comdat
   .weak   _ZNSt14_Function_base13_Base_managerIPFviEE10_M_destroyERSt9_Any_dataSt17integral_constantIbLb1EE
   .type   _ZNSt14_Function_base13_Base_managerIPFviEE10_M_destroyERSt9_Any_dataSt17integral_constantIbLb1EE, @function
_ZNSt14_Function_base13_Base_managerIPFviEE10_M_destroyERSt9_Any_dataSt17integral_constantIbLb1EE:
.LFB1695:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $16, %rsp
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt9_Any_data9_M_accessIPFviEEERT_v
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1695:
   .size   _ZNSt14_Function_base13_Base_managerIPFviEE10_M_destroyERSt9_Any_dataSt17integral_constantIbLb1EE, .-_ZNSt14_Function_base13_Base_managerIPFviEE10_M_destroyERSt9_Any_dataSt17integral_constantIbLb1EE
   .section   .text._ZNKSt9_Any_data9_M_accessIPFviEEERKT_v,"axG",@progbits,_ZNKSt9_Any_data9_M_accessIPFviEEERKT_v,comdat
   .align 2
   .weak   _ZNKSt9_Any_data9_M_accessIPFviEEERKT_v
   .type   _ZNKSt9_Any_data9_M_accessIPFviEEERKT_v, @function
_ZNKSt9_Any_data9_M_accessIPFviEEERKT_v:
.LFB1704:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $16, %rsp
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNKSt9_Any_data9_M_accessEv
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1704:
   .size   _ZNKSt9_Any_data9_M_accessIPFviEEERKT_v, .-_ZNKSt9_Any_data9_M_accessIPFviEEERKT_v
   .section   .text._ZSt11__addressofIKPFviEEPT_RS3_,"axG",@progbits,_ZSt11__addressofIKPFviEEPT_RS3_,comdat
   .weak   _ZSt11__addressofIKPFviEEPT_RS3_
   .type   _ZSt11__addressofIKPFviEEPT_RS3_, @function
_ZSt11__addressofIKPFviEEPT_RS3_:
.LFB1705:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1705:
   .size   _ZSt11__addressofIKPFviEEPT_RS3_, .-_ZSt11__addressofIKPFviEEPT_RS3_
   .section   .text._ZNSt9_Any_data9_M_accessIPFviEEERT_v,"axG",@progbits,_ZNSt9_Any_data9_M_accessIPFviEEERT_v,comdat
   .align 2
   .weak   _ZNSt9_Any_data9_M_accessIPFviEEERT_v
   .type   _ZNSt9_Any_data9_M_accessIPFviEEERT_v, @function
_ZNSt9_Any_data9_M_accessIPFviEEERT_v:
.LFB1707:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $16, %rsp
   movq   %rdi, -8(%rbp)
   movq   -8(%rbp), %rax
   movq   %rax, %rdi
   call   _ZNSt9_Any_data9_M_accessEv
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1707:
   .size   _ZNSt9_Any_data9_M_accessIPFviEEERT_v, .-_ZNSt9_Any_data9_M_accessIPFviEEERT_v
   .weak   _ZTSPFviE
   .section   .rodata._ZTSPFviE,"aG",@progbits,_ZTSPFviE,comdat
   .type   _ZTSPFviE, @object
   .size   _ZTSPFviE, 6
_ZTSPFviE:
   .string   "PFviE"
   .weak   _ZTIPFviE
   .section   .rodata._ZTIPFviE,"aG",@progbits,_ZTIPFviE,comdat
   .align 32
   .type   _ZTIPFviE, @object
   .size   _ZTIPFviE, 32
_ZTIPFviE:
   .quad   _ZTVN10__cxxabiv119__pointer_type_infoE+16
   .quad   _ZTSPFviE
   .long   0
   .zero   4
   .quad   _ZTIFviE
   .text
   .type   _Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB1728:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $16, %rsp
   movl   %edi, -4(%rbp)
   movl   %esi, -8(%rbp)
   cmpl   $1, -4(%rbp)
   jne   .L72
   cmpl   $65535, -8(%rbp)
   jne   .L72
   movl   $_ZStL8__ioinit, %edi
   call   _ZNSt8ios_base4InitC1Ev
   movl   $__dso_handle, %edx
   movl   $_ZStL8__ioinit, %esi
   movl   $_ZNSt8ios_base4InitD1Ev, %edi
   call   __cxa_atexit
.L72:
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1728:
   .size   _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
   .weak   _ZTSFviE
   .section   .rodata._ZTSFviE,"aG",@progbits,_ZTSFviE,comdat
   .type   _ZTSFviE, @object
   .size   _ZTSFviE, 5
_ZTSFviE:
   .string   "FviE"
   .weak   _ZTIFviE
   .section   .rodata._ZTIFviE,"aG",@progbits,_ZTIFviE,comdat
   .align 16
   .type   _ZTIFviE, @object
   .size   _ZTIFviE, 16
_ZTIFviE:
   .quad   _ZTVN10__cxxabiv120__function_type_infoE+16
   .quad   _ZTSFviE
   .text
   .type   _GLOBAL__sub_I__Z9print_numi, @function
_GLOBAL__sub_I__Z9print_numi:
.LFB1729:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   movl   $65535, %esi
   movl   $1, %edi
   call   _Z41__static_initialization_and_destruction_0ii
   popq   %rbp
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE1729:
   .size   _GLOBAL__sub_I__Z9print_numi, .-_GLOBAL__sub_I__Z9print_numi
   .section   .init_array,"aw"
   .align 8
   .quad   _GLOBAL__sub_I__Z9print_numi
   .hidden   __dso_handle
   .ident   "GCC: (GNU) 4.8.1 20130603 (Red Hat 4.8.1-1)"
   .section   .note.GNU-stack,"",@progbits

With -O2

Code: Select all

   .file   "opttest.cpp"
   .section   .text._ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai,"axG",@progbits,_ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai,comdat
   .p2align 4,,15
   .weak   _ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai
   .type   _ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai, @function
_ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai:
.LFB1682:
   .cfi_startproc
   movq   (%rdi), %rax
   movl   %esi, %edi
   jmp   *%rax
   .cfi_endproc
.LFE1682:
   .size   _ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai, .-_ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai
   .section   .text._ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation,"axG",@progbits,_ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation,comdat
   .p2align 4,,15
   .weak   _ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation
   .type   _ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation, @function
_ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation:
.LFB1683:
   .cfi_startproc
   cmpl   $1, %edx
   je   .L4
   cmpl   $2, %edx
   je   .L5
   testl   %edx, %edx
   je   .L11
.L3:
   xorl   %eax, %eax
   .p2align 4,,4
   ret
   .p2align 4,,10
   .p2align 3
.L11:
   movq   $_ZTIPFviE, (%rdi)
   xorl   %eax, %eax
   ret
   .p2align 4,,10
   .p2align 3
.L5:
   testq   %rdi, %rdi
   movq   (%rsi), %rax
   je   .L3
   movq   %rax, (%rdi)
   xorl   %eax, %eax
   ret
   .p2align 4,,10
   .p2align 3
.L4:
   movq   %rsi, (%rdi)
   xorl   %eax, %eax
   ret
   .cfi_endproc
.LFE1683:
   .size   _ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation, .-_ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation
   .text
   .p2align 4,,15
   .globl   _Z9print_numi
   .type   _Z9print_numi, @function
_Z9print_numi:
.LFB1564:
   .cfi_startproc
   movl   %edi, %esi
   movl   $_ZSt4cout, %edi
   jmp   _ZNSolsEi
   .cfi_endproc
.LFE1564:
   .size   _Z9print_numi, .-_Z9print_numi
   .section   .text.startup,"ax",@progbits
   .p2align 4,,15
   .globl   main
   .type   main, @function
main:
.LFB1565:
   .cfi_startproc
   .cfi_personality 0x3,__gxx_personality_v0
   .cfi_lsda 0x3,.LLSDA1565
   pushq   %rbx
   .cfi_def_cfa_offset 16
   .cfi_offset 3, -16
   movl   $_ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation, %eax
   subq   $32, %rsp
   .cfi_def_cfa_offset 48
   testq   %rax, %rax
   movq   $_Z9print_numi, (%rsp)
   movq   $_ZNSt17_Function_handlerIFviEPS0_E9_M_invokeERKSt9_Any_datai, 24(%rsp)
   movq   $_ZNSt14_Function_base13_Base_managerIPFviEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation, 16(%rsp)
   je   .L27
   movl   $-9, %edi
.LEHB0:
   call   _Z9print_numi
.LEHE0:
   movq   16(%rsp), %rax
   testq   %rax, %rax
   je   .L21
   movl   $3, %edx
   movq   %rsp, %rsi
   movq   %rsp, %rdi
   call   *%rax
.L21:
   addq   $32, %rsp
   .cfi_remember_state
   .cfi_def_cfa_offset 16
   xorl   %eax, %eax
   popq   %rbx
   .cfi_def_cfa_offset 8
   ret
.L27:
   .cfi_restore_state
.LEHB1:
   call   _ZSt25__throw_bad_function_callv
.LEHE1:
.L18:
   movq   16(%rsp), %rcx
   movq   %rax, %rbx
   testq   %rcx, %rcx
   je   .L17
   movl   $3, %edx
   movq   %rsp, %rsi
   movq   %rsp, %rdi
   call   *%rcx
.L17:
   movq   %rbx, %rdi
.LEHB2:
   call   _Unwind_Resume
.LEHE2:
   .cfi_endproc
.LFE1565:
   .globl   __gxx_personality_v0
   .section   .gcc_except_table,"a",@progbits
.LLSDA1565:
   .byte   0xff
   .byte   0xff
   .byte   0x1
   .uleb128 .LLSDACSE1565-.LLSDACSB1565
.LLSDACSB1565:
   .uleb128 .LEHB0-.LFB1565
   .uleb128 .LEHE0-.LEHB0
   .uleb128 .L18-.LFB1565
   .uleb128 0
   .uleb128 .LEHB1-.LFB1565
   .uleb128 .LEHE1-.LEHB1
   .uleb128 .L18-.LFB1565
   .uleb128 0
   .uleb128 .LEHB2-.LFB1565
   .uleb128 .LEHE2-.LEHB2
   .uleb128 0
   .uleb128 0
.LLSDACSE1565:
   .section   .text.startup
   .size   main, .-main
   .p2align 4,,15
   .type   _GLOBAL__sub_I__Z9print_numi, @function
_GLOBAL__sub_I__Z9print_numi:
.LFB1752:
   .cfi_startproc
   subq   $8, %rsp
   .cfi_def_cfa_offset 16
   movl   $_ZStL8__ioinit, %edi
   call   _ZNSt8ios_base4InitC1Ev
   movl   $__dso_handle, %edx
   movl   $_ZStL8__ioinit, %esi
   movl   $_ZNSt8ios_base4InitD1Ev, %edi
   addq   $8, %rsp
   .cfi_def_cfa_offset 8
   jmp   __cxa_atexit
   .cfi_endproc
.LFE1752:
   .size   _GLOBAL__sub_I__Z9print_numi, .-_GLOBAL__sub_I__Z9print_numi
   .section   .init_array,"aw"
   .align 8
   .quad   _GLOBAL__sub_I__Z9print_numi
   .weak   _ZTIFviE
   .section   .rodata._ZTIFviE,"aG",@progbits,_ZTIFviE,comdat
   .align 16
   .type   _ZTIFviE, @object
   .size   _ZTIFviE, 16
_ZTIFviE:
   .quad   _ZTVN10__cxxabiv120__function_type_infoE+16
   .quad   _ZTSFviE
   .weak   _ZTSFviE
   .section   .rodata._ZTSFviE,"aG",@progbits,_ZTSFviE,comdat
   .type   _ZTSFviE, @object
   .size   _ZTSFviE, 5
_ZTSFviE:
   .string   "FviE"
   .weak   _ZTIPFviE
   .section   .rodata._ZTIPFviE,"aG",@progbits,_ZTIPFviE,comdat
   .align 32
   .type   _ZTIPFviE, @object
   .size   _ZTIPFviE, 32
_ZTIPFviE:
   .quad   _ZTVN10__cxxabiv119__pointer_type_infoE+16
   .quad   _ZTSPFviE
   .long   0
   .zero   4
   .quad   _ZTIFviE
   .weak   _ZTSPFviE
   .section   .rodata._ZTSPFviE,"aG",@progbits,_ZTSPFviE,comdat
   .type   _ZTSPFviE, @object
   .size   _ZTSPFviE, 6
_ZTSPFviE:
   .string   "PFviE"
   .local   _ZStL8__ioinit
   .comm   _ZStL8__ioinit,1,1
   .hidden   __dso_handle
   .ident   "GCC: (GNU) 4.8.1 20130603 (Red Hat 4.8.1-1)"
   .section   .note.GNU-stack,"",@progbits

Looks like it's kind-of optimizing it to me, but viewing assembly generated by a C++ program is something that I don't normally do, and I do not code in assembly, so it seems new and strange and scary to me.

That said, if that function is in another function, and the std::function object is passed as a parameter, then it can only eliminate the call if that function is inlined, which you can't always guarantee.
Last edited by Thesh on Wed Jun 12, 2013 5:54 am UTC, edited 1 time in total.
Summum ius, summa iniuria.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Wed Jun 12, 2013 5:50 am UTC

Ahhhhh spoiler plz

Thesh wrote:Looks like it's kind-of optimizing it to me, but viewing assembly generated by a C++ program is something that I don't normally do, and I do not code in assembly, so it seems new and strange and scary to me.
I actually can't quite tell either. There's a testq %rax, %rax, which is the nearest flag-setting instruction to the je .L27 (according to here, mov doesn't modify flags). But... that means it's always going to jump, and .L27 seems to lead to some exception function. And then the line before .LEHB0: it loads -9 into %eax and calls print_num, but then what is it doing putting a bunch of crap onto the stack with the previous movs? I'm totally confused.

I tried MSVC 2012, and it also doesn't seem to optimize the function<> version. I also tried the function pointer version, and it did do constant propagation to get a direct call to print_num. However, it did not actually inline the call for some reason, even with __forceinline. I don't know why.

Edit: Intel ICPC 12.1.3 both eliminates the explict std::function and inlines print_num:
Spoiler:

Code: Select all

main:
..B1.1:                         # Preds ..B1.0
..___tag_value_main.1:                                          #10.1                    I don't know what this crap is. Function prelude for a bit...
        pushq     %rbp                                          #10.1
..___tag_value_main.3:                                          #
        movq      %rsp, %rbp                                    #10.1
..___tag_value_main.4:                                          #
        andq      $-128, %rsp                                   #10.1
        subq      $128, %rsp                                    #10.1
        movl      $3, %edi                                      #10.1
..___tag_value_main.6:                                          #10.1
        call      __intel_new_proc_init                         #10.1
..___tag_value_main.7:                                          #
                                # LOE rbx r12 r13 r14 r15
..B1.5:                         # Preds ..B1.1
        stmxcsr   (%rsp)                                        #10.1                    ???
        movl      $_ZSt4cout, %edi                              #12.5                    %edi = this
        movl      $-9, %esi                                     #12.5                    Argument 2 goes into esi
        orl       $32832, (%rsp)                                #10.1
        ldmxcsr   (%rsp)                                        #10.1
..___tag_value_main.8:                                          #12.5
        call      _ZNSolsEi                                     #12.5                    std::ostream::operator<<(int)
..___tag_value_main.9:                                          #
                                # LOE rbx r12 r13 r14 r15
..B1.2:                         # Preds ..B1.5
        xorl      %eax, %eax                                    #13.1
        movq      %rbp, %rsp                                    #13.1
        popq      %rbp                                          #13.1
..___tag_value_main.10:                                         #
        ret                                                     #13.1
        .align    16,0x90
..___tag_value_main.12:                                         #
                                # LOE
# mark_end;
        .type   main,@function
        .size   main,.-main
        .data
# -- End  main
Last edited by EvanED on Wed Jun 12, 2013 6:03 am UTC, edited 3 times in total.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6598
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Wed Jun 12, 2013 5:56 am UTC

EvanED wrote:Ahhhhh spoiler plz


I added the spoiler. For me, the code tags are fixed height with scrollbars.
Summum ius, summa iniuria.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Wed Jun 12, 2013 5:59 am UTC

Thesh wrote:
EvanED wrote:Ahhhhh spoiler plz


I added the spoiler. For me, the code tags are fixed height with scrollbars.

Ah hahaha. OK, that may because I'm an old fogie and have things set to the unsupported subsilver theme. Sorry for complaining then. :-)


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 7 guests