dispatch_once calls on every load from it
Performance improvements, as reported by the perf testing buildbot:
Histogram -18.81%
TwoSum -17.42%
RGBHistogram -9.65%
Regressions:
InsertionSort 5.59%
ArrayOfRef 3.99%
SwiftStructuresInsertionSort 5.29%
PrimeNum 6.09%
These regressions are bogus. The tests that "regressed" don't do any
hashing at all.
Swift SVN r23995
We were using std::function that allocated memory. Unfortunately c++ lambdas
don't have a type so I had to make the function findOrAdd templated on the
type of the callback. This is not a big deal since the class is already
templated and there is a single call site.
Swift SVN r23919
Fixes a crash when some programs were run in JIT mode; they instantiated a JITed class before the ObjC subclass was realized. Send a message to super to realize the class before we try to readClassPair it. Fixes rdar://problem/19170232.
Swift SVN r23825
Using the intrinsics is obnoxious because I needed them
to return Builtin.NativeObject?, but there's no reasonable
way to safely generate optional types from Builtins.cpp.
Ugh.
Dave and I also decided that there's no need for
swift_tryPin to allow a null object.
Swift SVN r23824
Pinning an object prevents it from being deallocated,
just like retaining it, but only one client can own the
pin at once. Sensible "sharing" of the pin can occur
if attempts are perfectly nested. It is efficient to
simultaneously query the pin state of an object in
conjunction with its strong reference count.
This combination of traits makes pinning suitable for
use in tracking whether a data structure backed by
an object is undergoing a non-structural modification:
- A structural change would require unique ownership
of the object, but two non-structural changes (to
different parts of the object) can occur at once
without harm. So a non-structural change can check
for either uniqueness or a pin and then, if necessary,
assert the pin for the duration of the change.
Meanwhile, this act of asserting the pin prevents
simultaneous structural changes.
- A very simple code-generation discipline leads to
changes being perfectly nested as long as they're
all performed by a single thread (or synchronously).
Asynchrony can introduce imperfect nesting, but it's
easy to write that off as a race condition and hence
undefined behavior.
See Accessors.rst for more on both of these points.
Swift SVN r23761
Metatypes have no user-visible structure, but can at least summarize as their type names. This gives us reasonable ad-hoc Printable behavior (thought debugPrint is still wrong, since a type name isn't parsable without being .self'ed).
Swift SVN r23745
Use the recursive demangled name generation I implemented in _typeName for metatypes in _stdlib_getDemangledType as well, so that we get fully-qualified generic names and other goodness.
Swift SVN r23743
Before the change we were spending ~35% of the time of getGenericMetadata in hashing the inputs. I measured the following speedups:
SwiftStructuresQueue 1.11x
Havlak 1.11x
CaptureProp 1.11x
SwiftStructuresStack 1.12x
Life 1.15x
NestedLoop 1.16x
RangeAssignment 1.24x
Swift SVN r23708
Fixes a crash when KVO-observed objects were reflect()ed, and the magic mirror tried to peep the artificial subclass's nonexistent nominal type descriptor. rdar://problem/19060227
Swift SVN r23628
swift_retain and objc_retain both handle nil already, so we can bypass the generic Optional value witnesses when instantiating Optional on a class type, which happens kind of a lot.
Swift SVN r23613
If, after layout, we recognize that a generic struct or enum instance is POD, we can replace the generic value witnesses in the image with POD ones.
Swift SVN r23609
References to functions that take inout parameters crash the compiler
because InOutType isn't a "real" type in itself and has no special type
metadata to emit. It merely further qualifies the function's input
types.
For example, we would like to have a unique entry in the cache for:
var f: (T, T) -> ()
and
var f2: (inout T, T) -> ()
For each argument type metadata pointer in the function's input, take
advantage of pointer alignment and mark the lowest bit if it is inout.
Since the metadata cache uses pointers to create the key, this creates a
unique entry while still being able to extract the actual pointer.
This fixes <rdar://problem/17655125>, and a couple of other similar
crashes.
Swift SVN r23557
This works by loading the protocols from a specially named symbol,
which is generated by the linker through the help of a linker script
that merges all of the protocol conformance blocks into one section
with its size at the start of it and points a global symbol at
the section.
We do all this because unlike MachO, section information does not
survive to be loaded into memory with ELF binaries. Instead,
the mappings that survive are 'segments', which contain one or
more sections. Information about how these relate to their original
sections is difficult, if not impossible, to obtain at runtime.
Swift SVN r23518
This works by loading the protocols from a specially named symbol,
which is generated by the linker through the help of a linker script
that merges all of the protocol conformance blocks into one section
with its size at the start of it and points a global symbol at
the section.
We do all this because unlike MachO, section information does not
survive to be loaded into memory with ELF binaries. Instead,
the mappings that survive are 'segments', which contain one or
more sections. Information about how these relate to their original
sections is difficult, if not impossible, to obtain at runtime.
Swift SVN r23475
Previously we weren't accounting for the fact that
heap_object_abi::SwiftSpareBitsMask includes all the tagged pointer
demarcation bits in heap_object_abi::ObjCReservedBitsMask.
Swift SVN r23459
Making the type of nodes in the concurrent map a concurrent list will get rid
of the problem of the map itself allocating the node type, which may have a
side effect.
Swift SVN r23443
When we search for metadata we usually search for the same value over and
over again. Instead of searching the value in the binary tree we can save
the value that we found and use it again the next time we search. This
commit adds a cache value. The invariant is that the LastSearch variable
always points to a valid node and the access to the pointer itself is atomic.
This is a major performance win for the current use of getGenericMetadata.
Swift SVN r23434
Naturally, the fast path for things like Array<Int> has to be that no
masking is required to get at the buffer. Therefore, the state with no
spare bits set needs to be reserved for native objects. After the
change, an ObjC non-tagged pointer is stored with all spare bits set, and
native objects are stored with 0..<N bits set, where N is the number of
spare bits. ObjC tagged pointers are still stored verbatim.
Swift SVN r23430
In debug builds getGenericMetadata takes about 10% of the execution time.
Most of this time is spent in searching the binary tree. This commit splits
the search into cold path and hot path, where the less likely checks are
done after the mode likely checks. This reduces the overall runtime of the
test suite in -Onone by ~1%.
Swift SVN r23419