-
-
Notifications
You must be signed in to change notification settings - Fork 416
Conversation
@yebblies review this pull please. |
The typeinfo refactoring should be independent of adding a compile time hash function so this should be two pull requests. What are the reasons to introduce a compile time hash function in druntime? |
It's possible, but difficult. One part of hash refactoring: moving hash calculation logic into core.util.hash module.
where T different for all TypeInfo. May be possibly to keep pull as is? This is not cyclic dependency. This is an attempt to avoid unnecessary work. However, if you tell me to split this pulls, I'll do it.
First reason is allowing to construct AA literals in CTFE and returning it to calling code. However, this is not the sole reason. this typeinfos has a different addresses and we must to call:
What we can to do?
However, the main goal of this patch is allowing to generate associative array instances an compile time. P.S. Thank you for taking the time to see this pull and sorry for my bad English. |
Ping |
@dawgfoto please, comment this. Do I must split this pull to typeinfo refactoring and hash refactoring? (I've wrote early, why I dont want to do it). Also please comment my reasons for hash CTFE implementation. Thanks. |
Rebased and reverted typeinfo refactoring (I'll create pull request for it later).
If you want to ask, why certainly in druntime, I have an answer.
If I move CTFE implementation of hash function to my library or phobos, I'll need follow druntime hash code. My code will be depended on druntime implementation. See simple example:
this code print not 15 as someone expect, but big strange number. Ok. I can follow this behavior in my ctfehash.d Specified issue is not alone. There are many strange cases and I'll need to follow all of druntime fixes in my ctfehash.d Now all hash-calculation functions concentrated in By a way, Last reason: CTFE hash calculation need for compile-time construction of the associative array instances (now ctfe can not return AA instance to main code and place this instance in static segment). After this pull merge I can add this ability (near 30 rows of D code and some C++ code in DMD will be needed) |
} | ||
else | ||
{ | ||
const(ubyte)[] bytes = cast(const(ubyte)[])cast(const(void)[])((&val)[0..1]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What Types are handled in this fall-through case. I don't think you can access the memory representation in CTFE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is default behaivor. It dont need to support ctfe. computeHash must work for all types, even if it cannot to do it it ctfe. i.e. delegates hash compute in the default branch.
How about the following.
|
I do not understand the first step. hashOf do not allow to compute And computeHash need not only for CTFE hash. It must compute identical hash for ctfe and rune if ctfe hash can be computed. What I must to do now? |
I think this pull has achieved the first two goals. |
Yes, the exact name of the function is not important, but
Not moving, we can create a template function in object that imports and forwards to the internal implementation.
I would like to use that opportunity to clean up and improve some hash computations instead of simply cut&pasting the existing ones. Of course this is not strictly necessary. |
This means, that core.internals.hash must be in public part of druntime. (in import folder)
Opposite, after I moved all hash logic to one place, we can optimize/clear/improve this logic as we wish. Otherwise, when logic divided between 10+ modules, you can not change something, without fear that any break. |
About naming: I'll rename: Ok? |
Is it ok now? What I need to do after renaming? Is it possible to work under this pull without separation to hashOf implementation and TypeInfo.getHash implementation? They are highly dependent on each other. In addition, I have made several changes in the hash computation. (For example, for arrays of structures and classes) Revert getHash changes lead to misalignment. |
cleanup of constraints and added comments for hashOf functions |
My suggestion for improving:
|
Also, I've added tests which cover all if/else branches if all hashOf function, and ensure that hashOf(v) == typeid(typeof(v)).getHash(&v); |
* http://www.boost.org/LICENSE_1_0.txt) | ||
*/ | ||
module core.internals.hash; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably package:
protection would make sense here, so that only core
can access this module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What means "package" did it allow access for all core.* modules, or only for all core.internals.*
(I mean "must means").
Now (http://d.puremagic.com/issues/show_bug.cgi?id=143) package
does protect us from unwarranted access?
Looks much better now. |
Ok. Thank you for your attention. |
@dawgfoto Do you have time to rewiew this pull now? :) Thanks! |
@@ -13,6 +13,8 @@ COPY=\ | |||
$(IMPDIR)\core\time.d \ | |||
$(IMPDIR)\core\vararg.d \ | |||
\ | |||
$(IMPDIR)\core\internals\hash.d \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's named internal
in phobos so we should stick to singular too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't genenerate import file? But how we can access to this module? If we hide this module and provide a proxy function in object.di, we'll be need to access to this internal module. Moreower, I don't know any way to protect internal.hash module (Allow access to it only with object.di), because object
module haven't parent package and package
protection can't help us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, let's scratch the package
protection.
But please rename the packge from core.internals
to core.internal
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
@dawgfoto All test are green. The last unresolwed issue is hash for float/double, yes? Is it good solution - implement CTFE log2 function to calculate exponent and compute ubyte[] representaion of double value like this: http://codepad.org/tWhIDslx (Of course, there are special cases like inf, nan etc)? |
if dlang/dmd#2656 will be merged, I'll be able to implement CTFE double hash properly. |
Not sure, but that was the main remaining issue. Looks good. |
Can we break down the pull request a little further? |
I'm not sure that adding
For struct Anyway this changes are so big and it will require long-term agreements with the community.
I've pushed this changes. Waiting for tests. |
@WalterBright I've strange linkage bug in win64 and ld warning on linux while compiling |
I've created bug report about this bug: http://d.puremagic.com/issues/show_bug.cgi?id=11273 |
@dawgfoto float hash issue is fixed. Is this solution is good? What we need to do next? |
I have some ideas how to perform this change and avoid circular dependence. Do you suggest to start this work now? Current pull request doesn't break public interface, but toHash signature changing will do it. Should we do it if a separate pull request if we want to start this work? |
@dawgfoto
I guess I do not understand you correctly. Do you suggest split this pull request to part?
|
@dawgfoto Ping |
} | ||
else | ||
{ | ||
return ((cast(uint) x[3]) << 24) | ((cast(uint) x[2]) << 16) | ((cast(uint) x[1]) << 8) | (cast(uint) x[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out that neither GCC 4.8 nor LLVM 3.3 implement this optimization. Apparently, nobody ever writes C code like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll rewert cast in non-dmd case. Another trouble: dmd can't inline function with if-else even if condition is trivially evaluatable at compile time like __ctfe
pseudu-variable.
You're right, I misunderstood that part. |
The bad news, it's really good work but there are simply too many orthogonal changes (add hashOf, change hash function, rewire TypeInfo.toHash) in this pull request which even complicates the AA situation.
If this works out we don't need to touch TypeInfo.toHash stuff and avoid complications like the seeded step-by-step array hash. |
@dawgfoto Hmm. Do you suggest to remove
How to compute hash of object without |
If a struct or class defines a
That's the point, these operations don't make sense for every class so we shouldn't define those methods in the root class. The only reason they are part of Object is because we need them for AAs. Replacing the virtual methods with a template functions in object will also allow to use qualifiers. Here are the relevant Bugzilla entries. We might also want to ask @jmdavis for the current status of this. |
In this case, I've understood general idea. My first goal: create PR which implements module |
Yes, it doesn't work because with a moving GC we wouldn't have any sensible data to hash.
This sounds interesting, but i wouldn't mind if object imported core.internel.aa. |
I would like to clarify my question.
BTW: Can we add special rules to toHash definition which can be checked by compiler?
This rule allow to ensure that AA key hash can't be changed but doesn't require that a key has been immutable. |
No, the code is not correct, because I can insert object which aren't comparable. It will take quite some time until we can remove the Object functions and I think this is orthogonal to the AA issue. |
@dawgfoto
I mean that
Yes. I think we can use toHash as is, and when we'll start removing toHash from Object, we'll fix hashOf class part. About
This code unable to implement as D user type (without ugly temporary proxy objects) because opIndex implementation don't know about next opIndexAssign. |
True, but you'd need to express this different because
I think we should try to go with a fully generic AA. module object;
//...
template AA(Key, Value)
{
import core.internal.aaimpl;
alias AA = AAImpl!(Key, Value);
} |
About toHash: I think it should be more restrictive then is. Hash value of object shouldn't be changed during object lifetime. Otherwice it can be chenged when object placed in associative array, and break this array.
Can you help me with this stage? I think it be a good idea to create special template object.AssociativeArrayLiteral(T...) and cast all aa literals to it. AssociativeArrayLiteral should allow different types of keys/values (like [1:2.0, "val":[1,2,3]]) because it can be used in different user containers like JSONValue. Same for simple array literal. But I don't know how to do it. |
I'll have a look at this, but it'll take 1 or 2 weeks until I have time. For now we can continue without this, it means that calling
That might be a good idea, but I'm not sure we can make this compatible with the current runtime AA.
That's an interesting idea, but it's a heavy language change. So we should file it as further enhancement. |
This is part of #477 pull.
My motivations for this refactoring:
Ergo: all hash functions must be placed into single module (and this module must be allowed to end-user).