@@ -480,27 +480,42 @@ class AsyncTask : public Job {
480
480
return resultType;
481
481
}
482
482
483
- // / Retrieve a pointer to the storage of result.
483
+ // / Retrieve a pointer to the storage of the result.
484
484
OpaqueValue *getStoragePtr () {
485
- return reinterpret_cast <OpaqueValue *>(
486
- reinterpret_cast <char *>(this ) + storageOffset (resultType));
485
+ // The result storage starts at the first aligned offset following
486
+ // the fragment header. This offset will agree with the abstract
487
+ // calculation for `resultOffset` in the fragmentSize function below
488
+ // because the entire task is aligned to at least the target
489
+ // alignment (because it's aligned to MaxAlignment), which means
490
+ // `this` must have the same value modulo that alignment as
491
+ // `fragmentOffset` has in that function.
492
+ char *fragmentAddr = reinterpret_cast <char *>(this );
493
+ uintptr_t alignment = resultType->vw_alignment ();
494
+ char *resultAddr = fragmentAddr + sizeof (FutureFragment);
495
+ uintptr_t unalignedResultAddrInt =
496
+ reinterpret_cast <uintptr_t >(resultAddr);
497
+ uintptr_t alignedResultAddrInt =
498
+ (unalignedResultAddrInt + alignment - 1 ) & ~(alignment - 1 );
499
+ // We could just cast alignedResultAddrInt back to a pointer, but
500
+ // doing pointer arithmetic is more strictly conformant and less
501
+ // likely to annoy the optimizer.
502
+ resultAddr += (alignedResultAddrInt - unalignedResultAddrInt);
503
+ return reinterpret_cast <OpaqueValue *>(resultAddr);
487
504
}
488
505
489
506
// / Retrieve the error.
490
507
SwiftError *&getError () { return error; }
491
508
492
- // / Compute the offset of the storage from the base of the future
493
- // / fragment.
494
- static size_t storageOffset (const Metadata *resultType) {
495
- size_t offset = sizeof (FutureFragment);
509
+ // / Determine the size of the future fragment given the result type
510
+ // / of the future.
511
+ static size_t fragmentSize (size_t fragmentOffset,
512
+ const Metadata *resultType) {
513
+ assert ((fragmentOffset & (alignof (FutureFragment) - 1 )) == 0 );
496
514
size_t alignment = resultType->vw_alignment ();
497
- return (offset + alignment - 1 ) & ~(alignment - 1 );
498
- }
499
-
500
- // / Determine the size of the future fragment given a particular future
501
- // / result type.
502
- static size_t fragmentSize (const Metadata *resultType) {
503
- return storageOffset (resultType) + resultType->vw_size ();
515
+ size_t resultOffset = fragmentOffset + sizeof (FutureFragment);
516
+ resultOffset = (resultOffset + alignment - 1 ) & ~(alignment - 1 );
517
+ size_t endOffset = resultOffset + resultType->vw_size ();
518
+ return (endOffset - fragmentOffset);
504
519
}
505
520
};
506
521
0 commit comments