-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Runtime/ABI] Replace emitTypeFieldAccessor
with a single runtime method
#13926
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@DougGregor @jckarter @slavapestov Can you please take a look if this is a a correct initial direction? |
@@ -1222,6 +1222,14 @@ FUNCTION(RegisterTypeMetadataRecords, | |||
ARGS(TypeMetadataRecordPtrTy, TypeMetadataRecordPtrTy), | |||
ATTRS(NoUnwind)) | |||
|
|||
// void swift_registerTypeFields(const FieldDescriptor *begin, | |||
// const FieldDescriptor *end) | |||
FUNCTION(RegisterTypeFields, |
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 file is only used for functions called from IRGen, so I don't think this is necessary.
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.
Gotcha! Will remove.
|
||
struct TypeFieldMetadataState { | ||
ConcurrentMap<DescriptorCacheEntry<FieldDescriptor>> FieldCache; | ||
std::vector<FieldMetadataSection> SectionsToScan; |
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.
Are we allowed to use std::vector from the runtime?
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.
That's what the rest of the caches in this file are doing too - protocols and type metadata, is that incorrect?
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.
std::vector
is okay in the runtime.
This looks like a good start, I'm looking forward to this coming together! |
I've started using Also I've noticed that reflection field record doesn't have "weak" in flags, is that intentional? |
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.
Definitely looks like the right approach!
auto type = field.getMangledTypeName(0); | ||
|
||
auto *typeMetadata = swift_getTypeByMangledName(type.data(), type.length(), | ||
0, nullptr, nullptr); |
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.
Until we're able to provide the substitutions to swift_getTypeByMangledName
, this won't work for generic types. There's no good way to get all of those substitutions correctly now (the information isn't there in the nominal type descriptors), but you should be able to handle non-nested generics with no requirements by using TargetMetadata::getGenericArgs()
. That would at least be enough to see basic substitutions working.
Fully supporting substitutions here will require @jckarter to land #13468
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.
Good to know, thanks, @DougGregor ! In a state I have it right now, would it be able to find non-generic types? Also, all of the methods in Field{Descriptor, Record}
require Offset
as an argument, I looked at how swift-reflection-dump
gets it, but I don't think it's possible to do the same in ImageInspection{ELF, MachO}
because we there is no SectionRef
, is there some other way to get it without using object file interface?
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.
Talked to @jckarter offline and it looks like I don't need to worry about offset
I mentioned in my previous comment. So the only thing which remains is to get some information from given type
to supply generic env to the swift_getTypeByMangledName
call and wait for other changes to be landed.
|
||
auto *typeMetadata = | ||
swift_getTypeByMangledName(type.data(), type.length(), numberOfLevels, | ||
paramsPerLevel, base->getGenericArgs()); |
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.
@DougGregor Is this the correct way of using getGenericArgs
? I've also modified interface a bit to use a callback instead of trying to return std::pair
, WDYT?
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.
Since you're using a callback, you might also be able to make the callback use StringRef
instead of std::string
, since it could have access to memory from swift_getFieldAt
's stack frame.
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.
Done!
@swift-ci please smoke test |
Ok, I'm getting closer, only 9 stdlib tests now fail locally and I think they all related to generics, I'll continue tomorrow. |
@DougGregor @jckarter I got this to the point where only failing tests are related to unimplemented things in |
Only remaining problems in tests are related to REPL, so I'm trying to figure out how to register new types there. It seems like newly defined types are not picked up automatically via image inspection callbacks. |
@xedin Awesome! In JIT mode, we need to manually emit a call that registers the data from the newly-generated code since there's no "image" per se. Look at |
@DougGregor dynamic registration now works! I'm waiting for #14038 to go in before all of the tests are green (I think), because it fails to demangle some imported types in function counter tests. |
Ok I verified that we can't produce metadata for 'Builtin.RawPointer' and other 'Builtin' types right now, that's why function counter tests are failing. |
This is looking good! Don't forget to remove the old mechanism, too. |
Thanks, @slavapestov! Will remove the old code once tests are all green! :) |
In my local build the biggest difference is |
Ok, looks like I have to rebase changes to type context descriptors and re-run everything again :) |
Use information from reflection section of the binary to lookup type field info such as name and it's type and return it using new `swift_getFieldAt` method based on nominal type and field index.
One of my previous commits did that, but since we have Builtins reflection section we don't really want to generate reflection field metadata for opaque structs/enums. This reverts to the previous behavior.
…therNominalTypes when demangling bound generic types.
Since Mirrors are using swift_getFieldAt we need built-in type metadata present in JIT/REPL mode as well, otherwise some of the types are going to become unprintable.
What I really meant is 😭 |
All of their usages have been replaced with new runtime `swift_getFieldAt` method.
All of the information contained by this field (list of property names) is already encoded as part of the field reflection metadata and is accessible via `swift_getFieldAt` runtime method.
@swift-ci please test |
@swift-ci please test source compatibility |
@swift-ci please smoke test compiler performance |
@swift-ci please smoke test compiler performance |
Looks like we save about half a megabyte with this changes |
getFieldAt(*Value->getDescription()); | ||
return; | ||
} | ||
*/ |
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.
Do you want to try turning the cache on before committing, or do that in a followup?
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.
I think it could be done in the follow up, I'm still trying to figure out what is safe to cache and what is not...
Looks good! It's probably a good idea to land this and then improve the layout, enable the cache, etc. in follow-up commits. |
@jckarter Thanks! I'll land it and do couple of improvements later then! |
I just came here to say: THIS IS SUPERB. |
Emitting individual accessors per field for each nominal type is inefficient from code size
and general code reusability perspective, because that duplicates data which already
exists in reflection section of the binary. This PR is a series of changes to get rid of
special lazy accessors and replace them with a single runtime method to request type field
metadata.
Resolves: rdar://problem/26060144