@@ -480,25 +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
- auto *startAddr = reinterpret_cast <char *>(this ) + sizeof (FutureFragment);
486
- uintptr_t startAddrVal = (uintptr_t )startAddr;
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 );
487
493
uintptr_t alignment = resultType->vw_alignment ();
488
- startAddrVal = (startAddrVal + alignment -1 ) & ~(alignment -1 );
489
- return reinterpret_cast <OpaqueValue *>(
490
- reinterpret_cast <char *>(startAddrVal));
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);
491
504
}
492
505
493
506
// / Retrieve the error.
494
507
SwiftError *&getError () { return error; }
495
508
496
- // / Determine the size of the future fragment given a particular future
497
- // / result type.
498
- static size_t fragmentSize (size_t initialOffset, const Metadata *resultType) {
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 );
499
514
size_t alignment = resultType->vw_alignment ();
500
- size_t padding = alignment - ((sizeof (FutureFragment) + initialOffset) % alignment);
501
- return sizeof (FutureFragment) + padding + 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);
502
519
}
503
520
};
504
521
0 commit comments