Skip to content

Commit ccee39e

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 3941512 + 7880972 commit ccee39e

18 files changed

+244
-74
lines changed

include/swift/Runtime/Concurrency.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,8 +670,11 @@ void swift_task_enqueue(Job *job, ExecutorRef executor);
670670
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
671671
void swift_task_enqueueGlobal(Job *job);
672672

673+
/// A count in nanoseconds.
674+
using JobDelay = unsigned long long;
675+
673676
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
674-
void swift_task_enqueueGlobalWithDelay(unsigned long long delay, Job *job);
677+
void swift_task_enqueueGlobalWithDelay(JobDelay delay, Job *job);
675678

676679
/// Enqueue the given job on the main executor.
677680
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)

lib/ClangImporter/ClangImporter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,6 +2527,10 @@ static bool isVisibleFromModule(const ClangModuleUnit *ModuleFilter,
25272527
auto *Importer = static_cast<ClangImporter *>(Ctx.getClangModuleLoader());
25282528
auto ClangNode = Importer->getEffectiveClangNode(VD);
25292529

2530+
// Decls in the __ObjC bridging header is always visible.
2531+
if (VD->getModuleContext() == Importer->getImportedHeaderModule())
2532+
return true;
2533+
25302534
// Macros can be "redeclared" by putting an equivalent definition in two
25312535
// different modules. (We don't actually check the equivalence.)
25322536
// FIXME: We're also not checking if the redeclaration is in /this/ module.

lib/ClangImporter/ImportDecl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,6 +2467,11 @@ namespace {
24672467
for (auto redecl : decl->redecls())
24682468
Impl.ImportedDecls[{redecl, getVersion()}] = enumDecl;
24692469

2470+
// Because a namespaces's decl context is the bridging header, make sure
2471+
// we add them to the bridging header lookup table.
2472+
addEntryToLookupTable(*Impl.BridgingHeaderLookupTable,
2473+
const_cast<clang::NamespaceDecl *>(decl),
2474+
Impl.getNameImporter());
24702475
return enumDecl;
24712476
}
24722477

lib/ClangImporter/ImporterImpl.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,9 +350,6 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
350350
"<bridging-header-import>";
351351

352352
private:
353-
/// The Swift lookup table for the bridging header.
354-
std::unique_ptr<SwiftLookupTable> BridgingHeaderLookupTable;
355-
356353
/// The Swift lookup tables, per module.
357354
///
358355
/// Annoyingly, we list this table early so that it gets torn down after
@@ -416,6 +413,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
416413
llvm::SmallDenseMap<ModuleDecl *, SourceFile *> ClangSwiftAttrSourceFiles;
417414

418415
public:
416+
/// The Swift lookup table for the bridging header.
417+
std::unique_ptr<SwiftLookupTable> BridgingHeaderLookupTable;
418+
419419
/// Mapping of already-imported declarations.
420420
llvm::DenseMap<std::pair<const clang::Decl *, Version>, Decl *> ImportedDecls;
421421

stdlib/public/Concurrency/CooperativeGlobalExecutor.inc

Lines changed: 113 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -24,44 +24,80 @@
2424

2525
#include <chrono>
2626
#include <thread>
27+
#include "swift/Basic/ListMerger.h"
2728

28-
static Job *JobQueue = nullptr;
29+
namespace {
2930

30-
class DelayedJob {
31-
public:
32-
Job *job;
33-
unsigned long long when;
34-
DelayedJob *next;
31+
struct JobQueueTraits {
32+
static Job *&storage(Job *cur) {
33+
return reinterpret_cast<Job*&>(cur->SchedulerPrivate[0]);
34+
}
3535

36-
DelayedJob(Job *job, unsigned long long when) : job(job), when(when), next(nullptr) {}
36+
static Job *getNext(Job *job) {
37+
return storage(job);
38+
}
39+
static void setNext(Job *job, Job *next) {
40+
storage(job) = next;
41+
}
42+
static int compare(Job *lhs, Job *rhs) {
43+
return descendingPriorityOrder(lhs->getPriority(), rhs->getPriority());
44+
}
3745
};
46+
using JobQueueMerger = ListMerger<Job*, JobQueueTraits>;
3847

39-
static DelayedJob *DelayedJobQueue = nullptr;
48+
using JobDeadline = std::chrono::time_point<std::chrono::steady_clock>;
4049

41-
/// Get the next-in-queue storage slot.
42-
static Job *&nextInQueue(Job *cur) {
43-
return reinterpret_cast<Job*&>(cur->SchedulerPrivate[Job::NextWaitingTaskIndex]);
44-
}
50+
template <bool = (sizeof(JobDeadline) <= sizeof(void*) &&
51+
alignof(JobDeadline) <= alignof(void*))>
52+
struct JobDeadlineStorage;
53+
54+
/// Specialization for when JobDeadline fits in SchedulerPrivate.
55+
template <>
56+
struct JobDeadlineStorage<true> {
57+
static JobDeadline &storage(Job *job) {
58+
return reinterpret_cast<JobDeadline&>(job->SchedulerPrivate[1]);
59+
}
60+
static JobDeadline get(Job *job) {
61+
return storage(job);
62+
}
63+
static void set(Job *job, JobDeadline deadline) {
64+
new(static_cast<void*>(&storage(job))) JobDeadline(deadline);
65+
}
66+
static void destroy(Job *job) {
67+
storage(job).~JobDeadline();
68+
}
69+
};
70+
71+
/// Specialization for when JobDeadline doesn't fit in SchedulerPrivate.
72+
template <>
73+
struct JobDeadlineStorage<false> {
74+
static JobDeadline *&storage(Job *job) {
75+
return reinterpret_cast<JobDeadline*&>(job->SchedulerPrivate[1]);
76+
}
77+
static JobDeadline get(Job *job) {
78+
return *storage(job);
79+
}
80+
static void set(Job *job, JobDeadline deadline) {
81+
storage(job) = new JobDeadline(deadline);
82+
}
83+
static void destroy(Job *job) {
84+
delete storage(job);
85+
}
86+
};
87+
88+
} // end anonymous namespace
89+
90+
static Job *JobQueue = nullptr;
91+
static Job *DelayedJobQueue = nullptr;
4592

4693
/// Insert a job into the cooperative global queue.
4794
SWIFT_CC(swift)
4895
static void swift_task_enqueueGlobalImpl(Job *job) {
4996
assert(job && "no job provided");
5097

51-
Job **position = &JobQueue;
52-
while (auto cur = *position) {
53-
// If we find a job with lower priority, insert here.
54-
if (cur->getPriority() < newJob->getPriority()) {
55-
nextInQueue(newJob) = cur;
56-
*position = newJob;
57-
return;
58-
}
59-
60-
// Otherwise, keep advancing through the queue.
61-
position = &nextInQueue(cur);
62-
}
63-
nextInQueue(newJob) = nullptr;
64-
*position = newJob;
98+
JobQueueMerger merger(JobQueue);
99+
merger.insert(job);
100+
JobQueue = merger.release();
65101
}
66102

67103
/// Enqueues a task on the main executor.
@@ -72,60 +108,80 @@ static void swift_task_enqueueMainExecutorImpl(Job *job) {
72108
swift_task_enqueueGlobalImpl(job);
73109
}
74110

75-
static unsigned long long currentNanos() {
76-
auto now = std::chrono::steady_clock::now();
77-
auto nowNanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(now);
78-
auto value = std::chrono::duration_cast<std::chrono::nanoseconds>(nowNanos.time_since_epoch());
79-
return value.count();
80-
}
81-
82111
/// Insert a job into the cooperative global queue with a delay.
83112
SWIFT_CC(swift)
84-
static void swift_task_enqueueGlobalWithDelayImpl(unsigned long long delay,
85-
Job *job) {
86-
assert(job && "no job provided");
113+
static void swift_task_enqueueGlobalWithDelayImpl(JobDelay delay,
114+
Job *newJob) {
115+
assert(newJob && "no job provided");
87116

88-
DelayedJob **position = &DelayedJobQueue;
89-
DelayedJob *newJob = new DelayedJob(job, currentNanos() + delay);
117+
auto deadline = std::chrono::steady_clock::now()
118+
+ std::chrono::duration_cast<JobDeadline::duration>(
119+
std::chrono::nanoseconds(delay));
120+
JobDeadlineStorage<>::set(newJob, deadline);
90121

122+
Job **position = &DelayedJobQueue;
91123
while (auto cur = *position) {
92-
// If we find a job with lower priority, insert here.
93-
if (cur->when > newJob->when) {
94-
newJob->next = cur;
124+
// If we find a job with a later deadline, insert here.
125+
// Note that we maintain FIFO order.
126+
if (deadline < JobDeadlineStorage<>::get(cur)) {
127+
JobQueueTraits::setNext(newJob, cur);
95128
*position = newJob;
96129
return;
97130
}
98131

99132
// Otherwise, keep advancing through the queue.
100-
position = &cur->next;
133+
position = &JobQueueTraits::storage(cur);
101134
}
135+
JobQueueTraits::setNext(newJob, nullptr);
102136
*position = newJob;
103137
}
104138

139+
/// Recognize jobs in the delayed-jobs queue that are ready to execute
140+
/// and move them to the primary queue.
141+
static void recognizeReadyDelayedJobs() {
142+
// Process all the delayed jobs.
143+
auto nextDelayedJob = DelayedJobQueue;
144+
if (!nextDelayedJob) return;
145+
146+
auto now = std::chrono::steady_clock::now();
147+
JobQueueMerger readyJobs(JobQueue);
148+
149+
// Pull jobs off of the delayed-jobs queue whose deadline has been
150+
// reached, and add them to the ready queue.
151+
while (nextDelayedJob &&
152+
JobDeadlineStorage<>::get(nextDelayedJob) <= now) {
153+
// Destroy the storage of the deadline in the job.
154+
JobDeadlineStorage<>::destroy(nextDelayedJob);
155+
156+
auto next = JobQueueTraits::getNext(nextDelayedJob);
157+
readyJobs.insert(nextDelayedJob);
158+
nextDelayedJob = next;
159+
}
160+
161+
JobQueue = readyJobs.release();
162+
DelayedJobQueue = nextDelayedJob;
163+
}
164+
105165
/// Claim the next job from the cooperative global queue.
106166
static Job *claimNextFromCooperativeGlobalQueue() {
107-
// Check delayed jobs first
108167
while (true) {
109-
if (auto delayedJob = DelayedJobQueue) {
110-
if (delayedJob->when < currentNanos()) {
111-
DelayedJobQueue = delayedJob->next;
112-
auto job = delayedJob->job;
113-
114-
delete delayedJob;
115-
116-
return job;
117-
}
118-
}
168+
// Move any delayed jobs that are now ready into the primary queue.
169+
recognizeReadyDelayedJobs();
170+
171+
// If there's a job in the primary queue, run it.
119172
if (auto job = JobQueue) {
120-
JobQueue = nextInQueue(job);
173+
JobQueue = JobQueueTraits::getNext(job);
121174
return job;
122175
}
123-
// there are only delayed jobs left, but they are not ready,
124-
// so we sleep until the first one is
176+
177+
// If there are only delayed jobs left, sleep until the next deadline.
178+
// TODO: should the donator have some say in this?
125179
if (auto delayedJob = DelayedJobQueue) {
126-
std::this_thread::sleep_for(std::chrono::nanoseconds(delayedJob->when - currentNanos()));
180+
auto deadline = JobDeadlineStorage<>::get(delayedJob);
181+
std::this_thread::sleep_until(deadline);
127182
continue;
128183
}
184+
129185
return nullptr;
130186
}
131187
}

stdlib/public/Concurrency/DispatchGlobalExecutor.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ static void swift_task_enqueueGlobalImpl(Job *job) {
207207

208208

209209
SWIFT_CC(swift)
210-
static void swift_task_enqueueGlobalWithDelayImpl(unsigned long long delay,
210+
static void swift_task_enqueueGlobalWithDelayImpl(JobDelay delay,
211211
Job *job) {
212212
assert(job && "no job provided");
213213

stdlib/public/Concurrency/GlobalExecutor.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void (*swift::swift_task_enqueueGlobal_hook)(
6767

6868
SWIFT_CC(swift)
6969
void (*swift::swift_task_enqueueGlobalWithDelay_hook)(
70-
unsigned long long delay, Job *job,
70+
JobDelay delay, Job *job,
7171
swift_task_enqueueGlobalWithDelay_original original) = nullptr;
7272

7373
SWIFT_CC(swift)
@@ -91,8 +91,7 @@ void swift::swift_task_enqueueGlobal(Job *job) {
9191
swift_task_enqueueGlobalImpl(job);
9292
}
9393

94-
void swift::swift_task_enqueueGlobalWithDelay(unsigned long long delay,
95-
Job *job) {
94+
void swift::swift_task_enqueueGlobalWithDelay(JobDelay delay, Job *job) {
9695
if (swift_task_enqueueGlobalWithDelay_hook)
9796
swift_task_enqueueGlobalWithDelay_hook(
9897
delay, job, swift_task_enqueueGlobalWithDelayImpl);

stdlib/public/Concurrency/NonDispatchGlobalExecutor.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static void swift_task_enqueueGlobalImpl(Job *job) {
3333
}
3434

3535
SWIFT_CC(swift)
36-
static void swift_task_enqueueGlobalWithDelayImpl(unsigned long long delay,
36+
static void swift_task_enqueueGlobalWithDelayImpl(JobDelay delay,
3737
Job *job) {
3838
assert(job && "no job provided");
3939

test/IDE/complete_from_clang_framework.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ func testSwiftCompletions(foo: SwiftStruct) {
122122
// CLANG_BAR-DAG: Decl[GlobalVar]/OtherModule[Bar]: BAR_MACRO_1[#Int32#]{{; name=.+$}}
123123
// CLANG_BAR-DAG: Decl[Struct]/OtherModule[Bar]: SomeItemSet[#SomeItemSet#]
124124
// CLANG_BAR-DAG: Decl[TypeAlias]/OtherModule[Bar]: SomeEnvironment[#SomeItemSet#]
125+
// CLANG_BAR-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: __NSConstantString[#__NSConstantString_tag#]; name=__NSConstantString
126+
// CLANG_BAR-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: __builtin_ms_va_list[#UnsafeMutablePointer<CChar>#]; name=__builtin_ms_va_list
127+
// CLANG_BAR-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: __builtin_va_list[#(__va_list_tag)#]; name=__builtin_va_list
125128
// CLANG_BAR: End completions
126129

127130
// CLANG_BOTH_FOO_BAR: Begin completions
@@ -148,12 +151,15 @@ func testCompleteModuleQualifiedFoo2() {
148151
Foo#^CLANG_QUAL_FOO_2^#
149152
// If the number of results below changes, then you need to add a result to the
150153
// list below.
151-
// CLANG_QUAL_FOO_2: Begin completions, 76 items
154+
// CLANG_QUAL_FOO_2: Begin completions, 82 items
152155
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooClassBase[#FooClassBase#]{{; name=.+$}}
153156
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooClassDerived[#FooClassDerived#]{{; name=.+$}}
154157
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .ClassWithInternalProt[#ClassWithInternalProt#]{{; name=.+$}}
155158
// CLANG_QUAL_FOO_2-DAG: Decl[Struct]/OtherModule[Foo]: ._InternalStruct[#_InternalStruct#]
156159
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooClassPropertyOwnership[#FooClassPropertyOwnership#]{{; name=.+$}}
160+
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__NSConstantString[#__NSConstantString_tag#]; name=__NSConstantString
161+
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__builtin_ms_va_list[#UnsafeMutablePointer<CChar>#]; name=__builtin_ms_va_list
162+
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__builtin_va_list[#(__va_list_tag)#]; name=__builtin_va_list
157163
// CLANG_QUAL_FOO_2-DAG: Decl[FreeFunction]/OtherModule[Foo]: ._internalTopLevelFunc()[#Void#]
158164
// CLANG_QUAL_FOO_2-DAG: Decl[Enum]/OtherModule[Foo]: .FooComparisonResult[#FooComparisonResult#]{{; name=.+$}}
159165
// CLANG_QUAL_FOO_2-DAG: Decl[FreeFunction]/OtherModule[Foo]: .fooFunc1({#(a): Int32#})[#Int32#]{{; name=.+$}}
@@ -217,14 +223,17 @@ func testCompleteModuleQualifiedFoo2() {
217223
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooRepeatedMembers[#FooRepeatedMembers#]{{; name=.+$}}
218224
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooClassWithClassProperties[#FooClassWithClassProperties#];
219225
// CLANG_QUAL_FOO_2-DAG: Decl[Enum]/OtherModule[Foo]: .SCNFilterMode[#SCNFilterMode#];
226+
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__NSConstantString[#__NSConstantString_tag#]; name=__NSConstantString
227+
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__builtin_ms_va_list[#UnsafeMutablePointer<CChar>#]; name=__builtin_ms_va_list
228+
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule[__ObjC]: .__builtin_va_list[#(__va_list_tag)#]; name=__builtin_va_list
220229
// CLANG_QUAL_FOO_2: End completions
221230
}
222231

223232
func testCompleteModuleQualifiedBar1() {
224233
Bar.#^CLANG_QUAL_BAR_1^#
225234
// If the number of results below changes, this is an indication that you need
226235
// to add a result to the appropriate list. Do not just bump the number!
227-
// CLANG_QUAL_BAR_1: Begin completions, 8 items
236+
// CLANG_QUAL_BAR_1: Begin completions, 11 items
228237
}
229238

230239
func testCompleteFunctionCall1() {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef TEST_INTEROP_CXX_MODULES_INPUTS_BRIDGE_HEADER_H
2+
#define TEST_INTEROP_CXX_MODULES_INPUTS_BRIDGE_HEADER_H
3+
4+
struct Parent {
5+
struct Child {};
6+
};
7+
8+
namespace Namespace {
9+
struct InNamespace {};
10+
}
11+
12+
#endif // TEST_INTEROP_CXX_MODULES_INPUTS_BRIDGE_HEADER_H
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Namespace {
2+
header "namespace.h"
3+
requires cplusplus
4+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import Namespace
2+
3+
extension Namespace.Parent {
4+
public static func test() -> Int { 42 }
5+
}
6+
7+
extension Namespace.Parent.Child {
8+
public static func test() -> Int { 52 }
9+
}
10+
11+
extension Namespace.NestedNamespace.NestedStruct {
12+
public func test() -> Int { 62 }
13+
}

0 commit comments

Comments
 (0)