Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ghc/ghc
  • bgamari/ghc
  • syd/ghc
  • ggreif/ghc
  • watashi/ghc
  • RolandSenn/ghc
  • mpickering/ghc
  • DavidEichmann/ghc
  • carter/ghc
  • harpocrates/ghc
  • ethercrow/ghc
  • mijicd/ghc
  • adamse/ghc
  • alexbiehl/ghc
  • gridaphobe/ghc
  • trofi/ghc
  • supersven/ghc
  • ppk/ghc
  • ulysses4ever/ghc
  • AndreasK/ghc
  • ghuntley/ghc
  • shayne-fletcher-da/ghc
  • fgaz/ghc
  • yav/ghc
  • osa1/ghc
  • mbbx6spp/ghc
  • JulianLeviston/ghc
  • reactormonk/ghc
  • rae/ghc
  • takenobu-hs/ghc
  • michalt/ghc
  • andrewthad/ghc
  • hsyl20/ghc
  • scottgw/ghc
  • sjakobi/ghc
  • angerman/ghc
  • RyanGlScott/ghc
  • hvr/ghc
  • howtonotwin/ghc
  • chessai/ghc
  • m-renaud/ghc
  • brprice/ghc
  • stevehartdata/ghc
  • sighingnow/ghc
  • kgardas/ghc
  • ckoparkar/ghc
  • alp/ghc
  • smaeul/ghc
  • kakkun61/ghc
  • sykloid/ghc
  • newhoggy/ghc
  • toonn/ghc
  • nineonine/ghc
  • Phyx/ghc
  • ezyang/ghc
  • tweag/ghc
  • langston/ghc
  • ndmitchell/ghc
  • rockbmb/ghc
  • artempyanykh/ghc
  • mniip/ghc
  • mynguyenbmc/ghc
  • alexfmpe/ghc
  • crockeea/ghc
  • nh2/ghc
  • vaibhavsagar/ghc
  • phadej/ghc
  • Haskell-mouse/ghc
  • lolotp/ghc
  • spacekitteh/ghc
  • michaelpj/ghc
  • mgsloan/ghc
  • HPCohen/ghc
  • tmobile/ghc
  • radrow/ghc
  • simonmar/ghc
  • _deepfire/ghc
  • Ericson2314/ghc
  • leitao/ghc
  • fumieval/ghc
  • trac-isovector/ghc
  • cblp/ghc
  • xich/ghc
  • ciil/ghc
  • erthalion/ghc
  • xldenis/ghc
  • autotaker/ghc
  • haskell-wasm/ghc
  • kcsongor/ghc
  • agander/ghc
  • Baranowski/ghc
  • trac-dredozubov/ghc
  • 23Skidoo/ghc
  • iustin/ghc
  • ningning/ghc
  • josefs/ghc
  • kabuhr/ghc
  • gallais/ghc
  • dten/ghc
  • expipiplus1/ghc
  • Pluralia/ghc
  • rohanjr/ghc
  • intricate/ghc
  • kirelagin/ghc
  • Javran/ghc
  • DanielG/ghc
  • trac-mizunashi_mana/ghc
  • pparkkin/ghc
  • bollu/ghc
  • ntc2/ghc
  • jaspervdj/ghc
  • JoshMeredith/ghc
  • wz1000/ghc
  • zkourouma/ghc
  • code5hot/ghc
  • jdprice/ghc
  • tdammers/ghc
  • J-mie6/ghc
  • trac-lantti/ghc
  • ch1bo/ghc
  • cgohla/ghc
  • lucamolteni/ghc
  • acairncross/ghc
  • amerocu/ghc
  • chreekat/ghc
  • txsmith/ghc
  • trupill/ghc
  • typetetris/ghc
  • sergv/ghc
  • fryguybob/ghc
  • erikd/ghc
  • trac-roland/ghc
  • setupminimal/ghc
  • Friede80/ghc
  • SkyWriter/ghc
  • xplorld/ghc
  • abrar/ghc
  • obsidiansystems/ghc
  • Icelandjack/ghc
  • adinapoli/ghc
  • trac-matthewbauer/ghc
  • heatsink/ghc
  • dwijnand/ghc
  • Cmdv/ghc
  • alinab/ghc
  • pepeiborra/ghc
  • fommil/ghc
  • luochen1990/ghc
  • rlupton20/ghc
  • applePrincess/ghc
  • lehins/ghc
  • ronmrdechai/ghc
  • leeadam/ghc
  • harendra/ghc
  • mightymosquito1991/ghc
  • trac-gershomb/ghc
  • lucajulian/ghc
  • Rizary/ghc
  • VictorCMiraldo/ghc
  • jamesbrock/ghc
  • andrewdmeier/ghc
  • luke/ghc
  • pranaysashank/ghc
  • cocreature/ghc
  • hithroc/ghc
  • obreitwi/ghc
  • slrtbtfs/ghc
  • kaol/ghc
  • yairchu/ghc
  • Mathemagician98/ghc
  • trac-taylorfausak/ghc
  • leungbk/ghc
  • MichaWiedenmann/ghc
  • chris-martin/ghc
  • TDecki/ghc
  • adithyaov/ghc
  • trac-gelisam/ghc
  • Lysxia/ghc
  • complyue/ghc
  • bwignall/ghc
  • sternmull/ghc
  • sonika/ghc
  • leif/ghc
  • broadwaylamb/ghc
  • myszon/ghc
  • danbroooks/ghc
  • Mechachleopteryx/ghc
  • zardyh/ghc
  • trac-vdukhovni/ghc
  • OmarKhaledAbdo/ghc
  • arrowd/ghc
  • Bodigrim/ghc
  • matheus23/ghc
  • cardenaso11/ghc
  • trac-Athas/ghc
  • mb720/ghc
  • DylanZA/ghc
  • liff/ghc
  • typedrat/ghc
  • trac-claude/ghc
  • jbm/ghc
  • Gertjan423/ghc
  • PHO/ghc
  • JKTKops/ghc
  • kockahonza/ghc
  • msakai/ghc
  • Sir4ur0n/ghc
  • barambani/ghc
  • vishnu.c/ghc
  • dcoutts/ghc
  • trac-runeks/ghc
  • trac-MaxGabriel/ghc
  • lexi.lambda/ghc
  • strake/ghc
  • spavikevik/ghc
  • JakobBruenker/ghc
  • rmanne/ghc
  • gdziadkiewicz/ghc
  • ani/ghc
  • iliastsi/ghc
  • smunix/ghc
  • judah/ghc
  • blackgnezdo/ghc
  • emilypi/ghc
  • trac-bpfoley/ghc
  • muesli4/ghc
  • trac-gkaracha/ghc
  • Kleidukos/ghc
  • nek0/ghc
  • TristanCacqueray/ghc
  • dwulive/ghc
  • mbakke/ghc
  • arybczak/ghc
  • Yang123321/ghc
  • maksbotan/ghc
  • QuietMisdreavus/ghc
  • trac-olshanskydr/ghc
  • emekoi/ghc
  • samuela/ghc
  • josephcsible/ghc
  • dramforever/ghc
  • lpsmith/ghc
  • DenisFrezzato/ghc
  • michivi/ghc
  • jneira/ghc
  • jeffhappily/ghc
  • Ivan-Yudin/ghc
  • nakaji-dayo/ghc
  • gdevanla/ghc
  • galen/ghc
  • fendor/ghc
  • yaitskov/ghc
  • rcythr/ghc
  • awpr/ghc
  • jeremyschlatter/ghc
  • Aver1y/ghc
  • mitchellvitez/ghc
  • merijn/ghc
  • tomjaguarpaw1/ghc
  • trac-NoidedSuper/ghc
  • erewok/ghc
  • trac-junji.hashimoto/ghc
  • adamwespiser/ghc
  • bjaress/ghc
  • jhrcek/ghc
  • leonschoorl/ghc
  • lukasz-golebiewski/ghc
  • sheaf/ghc
  • last-g/ghc
  • carassius1014/ghc
  • eschwartz/ghc
  • dwincort/ghc
  • felixwiemuth/ghc
  • TimWSpence/ghc
  • marcusmonteirodesouza/ghc
  • WJWH/ghc
  • vtols/ghc
  • theobat/ghc
  • BinderDavid/ghc
  • ckoparkar0/ghc
  • alexander-kjeldaas/ghc
  • dme2/ghc
  • philderbeast/ghc
  • aaronallen8455/ghc
  • rayshih/ghc
  • benkard/ghc
  • mpardalos/ghc
  • saidelman/ghc
  • leiftw/ghc
  • ca333/ghc
  • bwroga/ghc
  • nmichael44/ghc
  • trac-crobbins/ghc
  • felixonmars/ghc
  • adityagupta1089/ghc
  • hgsipiere/ghc
  • treeowl/ghc
  • alexpeits/ghc
  • CraigFe/ghc
  • dnlkrgr/ghc
  • kerckhove_ts/ghc
  • cptwunderlich/ghc
  • eiais/ghc
  • hahohihu/ghc
  • sanchayan/ghc
  • lemmih/ghc
  • sehqlr/ghc
  • trac-dbeacham/ghc
  • luite/ghc
  • trac-f-a/ghc
  • vados/ghc
  • luntain/ghc
  • fatho/ghc
  • alexbiehl-gc/ghc
  • dcbdan/ghc
  • tvh/ghc
  • liam-ly/ghc
  • timbobbarnes/ghc
  • GovanifY/ghc
  • shanth2600/ghc
  • gliboc/ghc
  • duog/ghc
  • moxonsghost/ghc
  • zander/ghc
  • masaeedu/ghc
  • georgefst/ghc
  • guibou/ghc
  • nicuveo/ghc
  • mdebruijne/ghc
  • stjordanis/ghc
  • emiflake/ghc
  • wygulmage/ghc
  • frasertweedale/ghc
  • coot/ghc
  • aratamizuki/ghc
  • tsandstr/ghc
  • mrBliss/ghc
  • Anton-Latukha/ghc
  • tadfisher/ghc
  • vapourismo/ghc
  • Sorokin-Anton/ghc
  • basile-henry/ghc
  • trac-mightybyte/ghc
  • AbsoluteNikola/ghc
  • cobrien99/ghc
  • songzh/ghc
  • blamario/ghc
  • aj4ayushjain/ghc
  • trac-utdemir/ghc
  • tangcl/ghc
  • hdgarrood/ghc
  • maerwald/ghc
  • arjun/ghc
  • ratherforky/ghc
  • haskieLambda/ghc
  • EmilGedda/ghc
  • Bogicevic/ghc
  • eddiejessup/ghc
  • kozross/ghc
  • AlistairB/ghc
  • 3Rafal/ghc
  • christiaanb/ghc
  • trac-bit/ghc
  • matsumonkie/ghc
  • trac-parsonsmatt/ghc
  • chisui/ghc
  • jaro/ghc
  • trac-kmiyazato/ghc
  • davidsd/ghc
  • Tritlo/ghc
  • I-B-3/ghc
  • lykahb/ghc
  • AriFordsham/ghc
  • turion1/ghc
  • berberman/ghc
  • christiantakle/ghc
  • zyklotomic/ghc
  • trac-ocramz/ghc
  • CSEdd/ghc
  • doyougnu/ghc
  • mmhat/ghc
  • why-not-try-calmer/ghc
  • plutotulp/ghc
  • kjekac/ghc
  • Manvi07/ghc
  • teo/ghc
  • cactus/ghc
  • CarrieMY/ghc
  • abel/ghc
  • yihming/ghc
  • tsakki/ghc
  • jessicah/ghc
  • oliverbunting/ghc
  • meld/ghc
  • friedbrice/ghc
  • Joald/ghc
  • abarbu/ghc
  • DigitalBrains1/ghc
  • sterni/ghc
  • alexDarcy/ghc
  • hexchain/ghc
  • minimario/ghc
  • zliu41/ghc
  • tommd/ghc
  • jazcarate/ghc
  • peterbecich/ghc
  • alirezaghey/ghc
  • solomon/ghc
  • mikael.urankar/ghc
  • davjam/ghc
  • int-index/ghc
  • MorrowM/ghc
  • nrnrnr/ghc
  • Sonfamm/ghc-test-only
  • afzt1/ghc
  • nguyenhaibinh-tpc/ghc
  • trac-lierdakil/ghc
  • MichaWiedenmann1/ghc
  • jmorag/ghc
  • Ziharrk/ghc
  • trac-MitchellSalad/ghc
  • juampe/ghc
  • jwaldmann/ghc
  • snowleopard/ghc
  • juhp/ghc
  • normalcoder/ghc
  • ksqsf/ghc
  • trac-jberryman/ghc
  • roberth/ghc
  • 1ntEgr8/ghc
  • epworth/ghc
  • MrAdityaAlok/ghc
  • JunmingZhao42/ghc
  • jappeace/ghc
  • trac-Gabriel439/ghc
  • alt-romes/ghc
  • HugoPeters1024/ghc
  • 10ne1/ghc-fork
  • agentultra/ghc
  • Garfield1002/ghc
  • ChickenProp/ghc
  • clyring/ghc
  • MaxHearnden/ghc
  • jumper149/ghc
  • vem/ghc
  • ketzacoatl/ghc
  • Rosuavio/ghc
  • jackohughes/ghc
  • p4l1ly/ghc
  • konsumlamm/ghc
  • shlevy/ghc
  • torsten.schmits/ghc
  • andremarianiello/ghc
  • amesgen/ghc
  • googleson78/ghc
  • InfiniteVerma/ghc
  • uhbif19/ghc
  • yiyunliu/ghc
  • raehik/ghc
  • mrkun/ghc
  • telser/ghc
  • 1Jajen1/ghc
  • slotThe/ghc
  • WinstonHartnett/ghc
  • mpilgrem/ghc
  • dreamsmasher/ghc
  • schuelermine/ghc
  • trac-Viwor/ghc
  • undergroundquizscene/ghc
  • evertedsphere/ghc
  • coltenwebb/ghc
  • oberblastmeister/ghc
  • agrue/ghc
  • lf-/ghc
  • zacwood9/ghc
  • steshaw/ghc
  • high-cloud/ghc
  • SkamDart/ghc
  • PiDelport/ghc
  • maoif/ghc
  • RossPaterson/ghc
  • CharlesTaylor7/ghc
  • ribosomerocker/ghc
  • trac-ramirez7/ghc
  • daig/ghc
  • NicolasT/ghc
  • FinleyMcIlwaine/ghc
  • lawtonnichols/ghc
  • jmtd/ghc
  • ozkutuk/ghc
  • wildsebastian/ghc
  • nikshalark/ghc
  • lrzlin/ghc
  • tobias/ghc
  • fw/ghc
  • hawkinsw/ghc
  • type-dance/ghc
  • rui314/ghc
  • ocharles/ghc
  • wavewave/ghc
  • TheKK/ghc
  • nomeata/ghc
  • trac-csabahruska/ghc
  • jonathanjameswatson/ghc
  • L-as/ghc
  • Axman6/ghc
  • barracuda156/ghc
  • trac-jship/ghc
  • jake-87/ghc
  • meooow/ghc
  • rebeccat/ghc
  • hamana55/ghc
  • Enigmage/ghc
  • kokobd/ghc
  • agevelt/ghc
  • gshen42/ghc
  • chrismwendt/ghc
  • MangoIV/ghc
  • teto/ghc
  • Sookr1/ghc
  • trac-thomasjm/ghc
  • barci2/ghc-dev
  • trac-m4dc4p/ghc
  • dixonary/ghc
  • breakerzirconia/ghc
  • alexsio27444/ghc
  • glocq/ghc
  • sourabhxyz/ghc
  • ryantrinkle/ghc
  • Jade/ghc
  • scedfaliako/ghc
  • martijnbastiaan/ghc
  • trac-george.colpitts/ghc
  • ammarbinfaisal/ghc
  • mimi.vx/ghc
  • lortabac/ghc
  • trac-zyla/ghc
  • benbellick/ghc
  • aadaa-fgtaa/ghc
  • jvanbruegge/ghc
  • archbung/ghc
  • gilmi/ghc
  • mfonism/ghc
  • alex-mckenna/ghc
  • Ei30metry/ghc
  • DiegoDiverio/ghc
  • jorgecunhamendes/ghc
  • liesnikov/ghc
  • akrmn/ghc
  • trac-simplifierticks/ghc
  • jacco/ghc
  • rhendric/ghc
  • damhiya/ghc
  • ryndubei/ghc
  • DaveBarton/ghc
  • trac-Profpatsch/ghc
  • GZGavinZhao/ghc
  • ncfavier/ghc
  • jameshaydon/ghc
  • ajccosta/ghc
  • dschrempf/ghc
  • cydparser/ghc
  • LinuxUserGD/ghc
  • elodielander/ghc
  • facundominguez/ghc
  • psilospore/ghc
  • lachrimae/ghc
  • dylan-thinnes/ghc-type-errors-plugin
  • hamishmack/ghc
  • Leary/ghc
  • lzszt/ghc
  • lyokha/ghc
  • trac-glaubitz/ghc
  • Rewbert/ghc
  • andreabedini/ghc
  • Jasagredo/ghc
  • sol/ghc
  • OlegAlexander/ghc
  • trac-sthibaul/ghc
  • avdv/ghc
  • Wendaolee/ghc
  • ur4t/ghc
  • daylily/ghc
  • boltzmannrain/ghc
  • mmzk1526/ghc
  • trac-fizzixnerd/ghc
  • soulomoon/ghc
  • rwmjones/ghc
  • j14i/ghc
  • tracsis/ghc
  • gesh/ghc
  • flip101/ghc
  • eldritch-cookie/ghc
  • LemonjamesD/ghc
  • pgujjula/ghc
  • skeuchel/ghc
  • noteed/ghc
  • gulin.serge/ghc
  • Torrekie/ghc
  • jlwoodwa/ghc
  • ayanamists/ghc
  • husong998/ghc
  • trac-edmundnoble/ghc
  • josephf/ghc
  • contrun/ghc
  • baulig/ghc
  • edsko/ghc
  • mzschr/ghc-issue-24732
  • ulidtko/ghc
  • Arsen/ghc
  • trac-sjoerd_visscher/ghc
  • crumbtoo/ghc
  • L0neGamer/ghc
  • DrewFenwick/ghc
  • benz0li/ghc
  • MaciejWas/ghc
  • jordanrule/ghc
  • trac-qqwy/ghc
  • LiamGoodacre/ghc
  • isomorpheme/ghc
  • trac-danidiaz/ghc
  • Kariim/ghc
  • MTaimoorZaeem/ghc
  • hololeap/ghc
  • ticat-fp/ghc
  • meritamen/ghc
  • criskell/ghc
  • trac-kraai/ghc
  • aergus/ghc
  • jdral/ghc
  • SamB/ghc
  • Tristian/ghc
  • ywgrit/ghc
  • KatsuPatrick/ghc
  • OsePedro/ghc
  • mpscholten/ghc
  • fp/ghc
  • zaquest/ghc
  • fangyi-zhou/ghc
  • augyg/ghc
640 results
Show changes
Commits on Source (13)
  • Marten Wijnja's avatar
    edfe6140
  • Cheng Shao's avatar
    rts: cleanup inlining logic · 35a64220
    Cheng Shao authored and Marge Bot's avatar Marge Bot committed
    This patch removes pre-C11 legacy code paths related to
    INLINE_HEADER/STATIC_INLINE/EXTERN_INLINE macros, ensure EXTERN_INLINE
    is treated as static inline in most cases (fixes #24945), and also
    corrects the comments accordingly.
    35a64220
  • Bodigrim's avatar
    CODEOWNERS: add @core-libraries to track base interface changes · 9ea90ed2
    Bodigrim authored and Marge Bot's avatar Marge Bot committed
    A low-tech tactical solution for #24919
    9ea90ed2
  • Duncan Coutts's avatar
    Permit ARR_WORDS closures outside HEAP_ALLOCED space · 75d5a448
    Duncan Coutts authored
    In the GC, evacuate() is prepared to deal with some heap objects that
    are not in the HEAP_ALLOCED() memory space. These are mainly the heap
    objects that GHC puts into the data sections of object files.
    
    It is also useful however to allow ByteArray# and MutableByteArray#
    heap objects to appear outside of the HEAP_ALLOCED() memory space. These
    have the ARR_WORDS closure type and contain no pointer should be easy to
    deal with. Indeed evacuate() already deals with closure types for
    constructors containing no pointers by doing nothing.
    
    So we just tack the ARR_WORDS case into this group of closure types that
    are permitted outside the HEAP_ALLOCED area but otherwise ignored.
    75d5a448
  • Duncan Coutts's avatar
    Add new primop placeByteArray# · 55b0eb1e
    Duncan Coutts authored
    It places a byte array heap object header at the given address, which
    must be outside the heap. It also sets the byte array size.
    55b0eb1e
  • Duncan Coutts's avatar
    Define HEAP_ALLOCED for CMM code · 3ef54581
    Duncan Coutts authored
    Allow rts/sm/HeapAlloc.h to be #included by CMM code and have it provide
    a suitable implementation of HEAP_ALLOCED.
    
    The HEAP_ALLOCED system has three implementations, the large address
    space case, two fallbakc impls, one for 32bit and one for 64bit. The
    first two are simple enough that we can provide a HEAP_ALLOCED macro
    that can be used in a CMM expression context.
    
    The 64bit fallback case is rather more tricky. We provide a different
    interface to HEAP_ALLOCED for this case, which has to be called in a
    statement/"callish" style.
    3ef54581
  • Duncan Coutts's avatar
    Fix isByteArrayPinned# for the !HEAP_ALLOCATED case · f8cfafc5
    Duncan Coutts authored
    The isByteArrayPinned# primop works by looking up the block descriptor
    for the byte array to see if it lives in a pinned area or not. This of
    course cannot work for byte arrays that are not HEAP_ALLOCATED since
    they don't have block descriptors.
    
    The solution is to check if it is HEAP_ALLOCATED first. Since this is
    done in CMM code we make use of the new HEAP_ALLOCATED support for CMM.
    It is a bit awkward since it does not have a uniform interface.
    f8cfafc5
  • Duncan Coutts's avatar
    Add test T17747 · 9798a26f
    Duncan Coutts authored
    Closes issue #17747
    
    Test that we can allocate ByteArray#s outside of the HEAP_ALLOCED()
    address space without upsetting the GC. To be extra sure we attach weak
    pointers with C finalizers to the ByteArray#s. We keep them alive and
    run a major GC so that the GC has to trace the live ByteArray#s.
    
    Prior to the first patch in this series, doing this would upset the GC
    because the GC does not expect heap objects with closure type ARR_WORDS
    to exist outside the GC heap.
    
    > internal error: evacuate(static): strange closure type 42
    
    Finally we allow everything to be GC'd again, and check that the C
    finalizers did run.
    
    This feature also required a change to the isByteArrayPinned# which
    itself required a CMM implementation of the HEAP_ALLOCED system. So we
    also add a check that the CMM and C implementations of HEAP_ALLOCED
    agree with each other.
    9798a26f
  • Duncan Coutts's avatar
    Update user guide for byte arrays outside of the heap · fd54a5b9
    Duncan Coutts authored
    Add a sub-subsection in the chapter on GHC extensions to the FFI, under
    the existing Memory Allocation subsection.
    
    Explain that it's permitted to have {Mutable}ByteArray# outside the heap
    and the tricky associated constraints. Mention the new primop
    placeByteArray#.
    fd54a5b9
  • Duncan Coutts's avatar
    058a823c
  • Duncan Coutts's avatar
    Add Note [Byte arrays outside of the HEAP_ALLOCED space] · 98563fe0
    Duncan Coutts authored
    And refer to it from the various places involved in the scheme.
    98563fe0
  • Duncan Coutts's avatar
    b311afd6
  • davide's avatar
    63e3f5bc
Showing
with 426 additions and 70 deletions
......@@ -60,6 +60,7 @@
/libraries/base/ @hvr
/libraries/ghci/ @simonmar
/libraries/template-haskell/ @rae
/testsuite/tests/interface-stability/ @core-libraries
[Internal utilities and libraries]
/utils/iserv-proxy/ @angerman @simonmar
......
......@@ -1852,6 +1852,70 @@ section "Byte Arrays"
------------------------------------------------------------------------
-- Note [Byte arrays outside of the HEAP_ALLOCED space]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
-- It is useful to be able to allocate byte arrays outside of the heap,
-- i.e. outside of the memory space covered by the HEAP_ALLOCED() test.
--
-- There are two major use cases (see issue #17747):
--
-- 1. Having foreign memory appear as a normal GHC byte array. This
-- are use cases similar to the use of a ForeignPtr, but where it
-- is useful to have the representation be a byte array type, for
-- easier interoperability with existing libraries.
--
-- 2. Static byte arrays in object files for constant values.
--
-- The second is not yet available as it requires additional support
-- from the code gen.
--
-- An example of the first category can be seen in GHC test T17747.
-- A concrete use-case is to memory map a file
-- but have it appear as a ByteArray# rather than a ForeignPtr. Doing
-- so of course requires that space is reserved immediately before the
-- file data for the byte array heap object header. See the
-- placeByteArray# primop documentation below and the FFI section of
-- the user guide for more details.
--
-- To have the first use-case work requires a few things:
--
-- * For the GC to not fail when it encounters byte arrays outside of
-- the HEAP_ALLOCED space. This is straightforward because the GC
-- has support for a number of different closure types to appear
-- outside the heap (primarily for statically allocated values), and
-- byte arrays are easy because they contain no heap pointers. See
-- the reference back to this note in `evacuate(StgClosure **p)` in
-- `rts/sm/Evac.c`
--
-- * For all other byte array primops (e.g. shrinkMutableByteArray#,
-- sameMutableByteArray#, isByteArrayPinned#, etc.) to not fail when
-- encountering byte arrays outside of the heap. Specifically
-- isByteArrayPinned# requires special support. This is currently the
-- only primop that needs special support.
-- See Note [isByteArrayPinned# support for off heap byte arrays].
--
-- * A mechanism to set up the heap object header for a byte array at
-- an address outside of the HEAP_ALLOCED space. This is needed to
-- make the foreign allocated memory look like a byte array. This is
-- provided by the placeByteArray# primop.
--
-- Note [isByteArrayPinned# support for off heap byte arrays]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- The isByteArrayPinned# primop is implemented by reading block descriptor
-- flags. Since off heap byte arrays don't have block descriptors,
-- isByteArrayPinned# must explicitly check if the byte array is HEAP_ALLOCED
-- or not. If not HEAP_ALLOCED then it is certainly pinned. This requires CMM
-- support for the HEAP_ALLOCED test, which is otherwise only called from C
-- code in the RTS. The current design is to provide full CMM
-- implementations of HEAP_ALLOCED enabled in `rts/storage/HeapAlloc.h` with the
-- CMINUSMINUS cpp flag. This includes HEAP_ALLOCED_CALLISH which essentially
-- duplicates what is already a complex C implementation. This is fast
-- but an alternative would be to use a CMM C call to a C function that use
-- the existing C implementation of HEAP_ALLOCED.
primtype ByteArray#
{
A boxed, unlifted datatype representing a region of raw memory in the garbage-collected heap,
......@@ -1902,6 +1966,20 @@ primop NewByteArrayOp_Char "newByteArray#" GenPrimOp
with out_of_line = True
effect = ReadWriteEffect
-- See [Byte arrays outside of the HEAP_ALLOCED space]
primop PlaceByteArrayOp_Char "placeByteArray#" GenPrimOp
Addr# -> Int# -> State# s -> (# State# s, MutableByteArray# s #)
{Place a new byte array header at the specified address outside of the heap,
for the specified payload size (in bytes), in the specified state thread. In
C code with `#include "Rts.h"`, use `sizeOf(StgArrBytes)` or
`sizeOfW(StgArrBytes)` to get the size of a byte array header in bytes or
words respectively. The caller must ensure `sizeof(StgArrBytes) + n` bytes of
space is allocated at the give address for the heap object header followed by
n bytes of payload. See the FFI section of the user guide for more details
on how to use this primop.}
with out_of_line = True
effect = ReadWriteEffect
primop NewPinnedByteArrayOp_Char "newPinnedByteArray#" GenPrimOp
Int# -> State# s -> (# State# s, MutableByteArray# s #)
{Like 'newByteArray#' but GC guarantees not to move it.}
......
......@@ -1665,6 +1665,7 @@ emitPrimOp cfg primop =
CasArrayOp -> alwaysExternal
UnsafeThawSmallArrayOp -> alwaysExternal
CasSmallArrayOp -> alwaysExternal
PlaceByteArrayOp_Char -> alwaysExternal
NewPinnedByteArrayOp_Char -> alwaysExternal
NewAlignedPinnedByteArrayOp_Char -> alwaysExternal
MutableByteArrayIsPinnedOp -> alwaysExternal
......
......@@ -1198,6 +1198,10 @@ genPrim prof bound ty op = case op of
VecReadScalarOffAddrOp _ _ _ -> unhandledPrimop op
VecWriteScalarOffAddrOp _ _ _ -> unhandledPrimop op
-- This primop can be used to create a ByteArray# header outside the managed heap.
-- This operation is not supported in the Javascript backend.
PlaceByteArrayOp_Char -> unhandledPrimop op
PrefetchByteArrayOp3 -> noOp
PrefetchMutableByteArrayOp3 -> noOp
PrefetchAddrOp3 -> noOp
......
......@@ -811,6 +811,37 @@ the different kinds of allocation perform with GHC.
allocation than using one of the other forms of allocation. They are
backed by the RTS internal arena instead of ``malloc/free``.
Foreign allocation of native byte arrays
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
GHC allows ``ByteArray#`` and ``MutableByteArray#`` to be allocated
outside of the GHC heap. This enables manually allocated data to be
represented as these native types. It is also possible to attach weak
pointers with finalisers to these byte array types. For example, in
principle it is possible to arrange for a memory mapped file to be
presented as a byte array, including a weak pointer finaliser to unmap
the file after it is no longer referenced. This can be useful because
these native types are used directly or indirectly by many libraries.
It does however require some care and attention.
The in-memory representation of ``ByteArray#`` and ``MutableByteArray#``
are exactly the same whether inside or outside the heap. In particular
they use a few prefix words for the object header and array size field.
Note that the object header size is different for normal and profiling
builds. When allocating in foreign memory, space must be made available
for this in the memory layout immediately before the data payload.
In C code, ``#include "Rts.h"`` and use ``sizeOf(StgArrBytes)`` or
``sizeOfW(StgArrBytes)`` to get the size of a byte array heap object
header in bytes or words respectively. This is the space that must be
reserved at the memory location immediately before the intended payload.
Then use the primop ``placeByteArray#`` to place the heap object header
at the intended location with the appropriate payload size in bytes.
To add a finaliser, use GHC's weak pointer support. If appropriate make
use of the ability to use C functions for finalisers.
.. _ffi-threads:
Multi-threading and the FFI
......
......@@ -79,7 +79,7 @@ import GHC.Internal.Exception.Type
-- WARNING: You may want to use 'throwIO' instead so that your pure code
-- stays exception-free.
throw :: forall (r :: RuntimeRep). forall (a :: TYPE r). forall e.
(?callStack :: CallStack, Exception e) => e -> a
(HasCallStack, Exception e) => e -> a
throw e =
let !se = unsafePerformIO (toExceptionWithBacktrace e)
in raise# se
......
// all functions declared with EXTERN_INLINE in the header files get
// compiled for real here, just in case the definition was not inlined
// at some call site:
// All functions declared with EXTERN_INLINE in the header files get
// compiled for real here. Some of them are called by Cmm (e.g.
// recordClosureMutated) and therefore the real thing needs to reside
// in Inlines.o for Cmm ccall to work.
#define KEEP_INLINES
#include "rts/PosixSource.h"
#include "Rts.h"
......@@ -8,3 +9,4 @@
#include "Capability.h"
#include "WSDeque.h"
#include "SMPClosureOps.h"
#include "rts/storage/HeapAlloc.h"
......@@ -24,6 +24,7 @@
#include "Cmm.h"
#include "MachDeps.h"
#include "SMPClosureOps.h"
#include "rts/storage/HeapAlloc.h" /* for HEAP_ALLOCED() */
#if defined(__PIC__)
import pthread_mutex_lock;
......@@ -133,9 +134,22 @@ stg_newByteArrayzh ( W_ n )
return (p);
}
stg_placeByteArrayzh ( W_ addr, W_ n )
// Addr# -> Int# -> MutableByteArray# {
{
/* Place an ARR_WORDS object header at the given address outside the heap.
The caller must arrange for space for the heap object header. */
gcptr p;
p = addr;
SET_HDR(p, stg_ARR_WORDS_info, CCCS);
StgArrBytes_bytes(p) = n;
return (p);
}
#define BA_ALIGN 16
#define BA_MASK (BA_ALIGN-1)
// See Note [Byte arrays outside of the HEAP_ALLOCED space]
stg_newPinnedByteArrayzh ( W_ n )
{
W_ words, bytes, payload_words;
......@@ -203,16 +217,29 @@ stg_isByteArrayPinnedzh ( gcptr ba )
// ByteArray# s -> Int#
{
W_ bd, flags;
bd = Bdescr(ba);
// Pinned byte arrays live in blocks with the BF_PINNED flag set.
// We also consider BF_LARGE objects to be immovable. See #13894.
// See the comment in Storage.c:allocatePinned.
// We also consider BF_COMPACT objects to be immovable. See #14900.
flags = TO_W_(bdescr_flags(bd));
// We used to also consider BF_LARGE pinned, but stopped doing so
// because it interacted badly with compact regions. See #22255
return (flags & BF_PINNED != 0);
// See Note [Byte arrays outside of the HEAP_ALLOCED space]
#if defined(HEAP_ALLOCED)
if (HEAP_ALLOCED(ba)) {
#else
W_ result;
HEAP_ALLOCED_CALLISH(result, ba)
if (result == 1) {
#endif
// Safe to look up the block descriptor when the object is in the heap.
bd = Bdescr(ba);
// Pinned byte arrays live in blocks with the BF_PINNED flag set.
// See the comment in Storage.c:allocatePinned.
// We used to also considered BF_LARGE & BF_COMPACT pinned. See #13894 & 14900.
// We stopped doing so because it interacted badly with compact regions. See #22255.
flags = TO_W_(bdescr_flags(bd));
return (flags & BF_PINNED != 0);
} else {
// If it's not in the heap at all then we GC will not move it, so we
// can report to application code that it is pinned.
return (1);
}
}
stg_isMutableByteArrayPinnedzh ( gcptr mba )
......@@ -2975,4 +3002,3 @@ stg_castFloatToWord32zh(F_ f)
return (w);
}
......@@ -637,6 +637,7 @@ extern char **environ;
SymI_HasDataProto(stg_copyArray_barrier) \
SymI_HasDataProto(stg_newBCOzh) \
SymI_HasDataProto(stg_newByteArrayzh) \
SymI_HasDataProto(stg_placeByteArrayzh) \
SymI_HasDataProto(stg_casIntArrayzh) \
SymI_HasDataProto(stg_casInt8Arrayzh) \
SymI_HasDataProto(stg_casInt16Arrayzh) \
......
......@@ -114,57 +114,19 @@
* 'Portable' inlining:
* INLINE_HEADER is for inline functions in header files (macros)
* STATIC_INLINE is for inline functions in source files
* EXTERN_INLINE is for functions that we want to inline sometimes
* (we also compile a static version of the function; see Inlines.c)
* EXTERN_INLINE is for functions that may be called in Cmm
* (we also compile a static version of an EXTERN_INLINE function; see Inlines.c)
*/
// We generally assume C99 semantics albeit these two definitions work fine even
// when gnu90 semantics are active (i.e. when __GNUC_GNU_INLINE__ is defined or
// when a GCC older than 4.2 is used)
//
// The problem, however, is with 'extern inline' whose semantics significantly
// differs between gnu90 and C99
#define INLINE_HEADER static inline
#define STATIC_INLINE static inline
// Figure out whether `__attributes__((gnu_inline))` is needed
// to force gnu90-style 'external inline' semantics.
#if defined(FORCE_GNU_INLINE)
// disable auto-detection since HAVE_GNU_INLINE has been defined externally
#elif defined(__GNUC_GNU_INLINE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2
// GCC 4.2.x didn't properly support C99 inline semantics (GCC 4.3 was the first
// release to properly support C99 inline semantics), and therefore warned when
// using 'extern inline' while in C99 mode unless `__attributes__((gnu_inline))`
// was explicitly set.
# define FORCE_GNU_INLINE 1
#endif
#if defined(FORCE_GNU_INLINE)
// Force compiler into gnu90 semantics
# if defined(KEEP_INLINES)
# define EXTERN_INLINE inline __attribute__((gnu_inline))
# else
# define EXTERN_INLINE extern inline __attribute__((gnu_inline))
# endif
#elif defined(__GNUC_GNU_INLINE__)
// we're currently in gnu90 inline mode by default and
// __attribute__((gnu_inline)) may not be supported, so better leave it off
# if defined(KEEP_INLINES)
# define EXTERN_INLINE inline
# else
# define EXTERN_INLINE extern inline
# endif
#else
// Assume C99 semantics (yes, this curiously results in swapped definitions!)
// This is the preferred branch, and at some point we may drop support for
// compilers not supporting C99 semantics altogether.
// See comment in rts/Inlines.c for explanation.
# if defined(KEEP_INLINES)
# define EXTERN_INLINE extern inline
# else
# define EXTERN_INLINE inline
# define EXTERN_INLINE static inline
# endif
#endif
/*
* GCC attributes
......
......@@ -8,6 +8,8 @@
#pragma once
#if !defined(CMINUSMINUS)
#if defined(THREADED_RTS)
// needed for HEAP_ALLOCED below
extern SpinLock gc_alloc_block_sync;
......@@ -16,6 +18,8 @@ extern SpinLock gc_alloc_block_sync;
#define ACQUIRE_ALLOC_BLOCK_SPIN_LOCK() ACQUIRE_SPIN_LOCK(&gc_alloc_block_sync)
#define RELEASE_ALLOC_BLOCK_SPIN_LOCK() RELEASE_SPIN_LOCK(&gc_alloc_block_sync)
#endif // !defined(CMINUSMINUS)
/* -----------------------------------------------------------------------------
The HEAP_ALLOCED() test.
......@@ -56,6 +60,9 @@ extern SpinLock gc_alloc_block_sync;
#if defined(USE_LARGE_ADDRESS_SPACE)
#if !defined(CMINUSMINUS)
// If this struct is changed, the CMM macro below must be adjusted to match.
struct mblock_address_range {
W_ begin, end;
W_ padding[6]; // ensure nothing else inhabits this cache line
......@@ -66,7 +73,21 @@ extern struct mblock_address_range mblock_address_space;
(W_)(p) < (mblock_address_space.end))
# define HEAP_ALLOCED_GC(p) HEAP_ALLOCED(p)
#else /* defined(CMINUSMINUS) */
/* See Note [Byte arrays outside of the HEAP_ALLOCED space] */
import mblock_address_space;
# define HEAP_ALLOCED(p) ((p) >= W_[mblock_address_space + WDS(0)] && \
(p) < W_[mblock_address_space + WDS(1)])
#endif
#elif SIZEOF_VOID_P == 4
#if !defined(CMINUSMINUS)
extern StgWord8 mblock_map[];
# define MBLOCK_MAP_SIZE (1 << (32 - MBLOCK_SHIFT))
......@@ -74,6 +95,17 @@ extern StgWord8 mblock_map[];
# define HEAP_ALLOCED(p) mblock_map[MBLOCK_MAP_ENTRY(p)]
# define HEAP_ALLOCED_GC(p) HEAP_ALLOCED(p)
#else /* defined(CMINUSMINUS) */
/* See Note [Byte arrays outside of the HEAP_ALLOCED space] */
import mblock_map;
# define MBLOCK_MAP_ENTRY(p) ((p) >> MBLOCK_SHIFT)
# define HEAP_ALLOCED(p) (TO_W_(I8[mblock_map + MBLOCK_MAP_ENTRY(p)]) != 0)
#endif
/* -----------------------------------------------------------------------------
HEAP_ALLOCED for 64-bit machines (without LARGE_ADDRESS_SPACE).
......@@ -130,11 +162,13 @@ extern StgWord8 mblock_map[];
---------------------------------------------------------------------------- */
#elif SIZEOF_VOID_P == 8
#elif SIZEOF_VOID_P == 8 /* && !defined(USE_LARGE_ADDRESS_SPACE) */
#define MBC_LINE_BITS 0
#define MBC_TAG_BITS 15
#if !defined(CMINUSMINUS)
#if defined(x86_64_HOST_ARCH)
// 32bits are enough for 'entry' as modern amd64 boxes have
// only 48bit sized virtual address.
......@@ -168,7 +202,7 @@ extern W_ mpc_misses;
StgBool HEAP_ALLOCED_miss(StgWord mblock, const void *p);
INLINE_HEADER
EXTERN_INLINE
StgBool HEAP_ALLOCED(const void *p)
{
StgWord mblock;
......@@ -222,6 +256,21 @@ StgBool HEAP_ALLOCED_GC(const void *p)
}
}
#else /* defined(CMINUSMINUS) */
/* See Note [Byte arrays outside of the HEAP_ALLOCED space] */
// This is a call to HEAP_ALLOCED C function defined above. That function is reified via the
// Inlines.c file. Since the implementation that can't use USE_LARGE_ADDRESS_SPACE is big and
// complicated we prevent duplicating it's logic. We define the interface to be used in a statement
// "callish op" style.
#define HEAP_ALLOCED_CALLISH(result, p) \
CInt r; \
(r) = ccall HEAP_ALLOCED(p "ptr"); \
result = TO_W_(r); \
#endif
#else
# error HEAP_ALLOCED not defined
#endif
......@@ -450,6 +450,7 @@ RTS_FUN_DECL(stg_decodeDoublezuInt64zh);
RTS_FUN_DECL(stg_unsafeThawArrayzh);
RTS_FUN_DECL(stg_casArrayzh);
RTS_FUN_DECL(stg_newByteArrayzh);
RTS_FUN_DECL(stg_placeByteArrayzh);
RTS_FUN_DECL(stg_newPinnedByteArrayzh);
RTS_FUN_DECL(stg_newAlignedPinnedByteArrayzh);
RTS_FUN_DECL(stg_isByteArrayPinnedzh);
......
......@@ -741,6 +741,8 @@ loop:
case CONSTR_0_1:
case CONSTR_0_2:
case CONSTR_NOCAF:
/* See Note [Byte arrays outside of the HEAP_ALLOCED space] */
case ARR_WORDS:
/* no need to put these on the static linked list, they don't need
* to be scavenged.
*/
......
......@@ -292,7 +292,7 @@ module Control.Exception where
mask_ :: forall a. GHC.Types.IO a -> GHC.Types.IO a
onException :: forall a b. GHC.Types.IO a -> GHC.Types.IO b -> GHC.Types.IO a
someExceptionContext :: SomeException -> GHC.Internal.Exception.Context.ExceptionContext
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::GHC.Internal.Stack.Types.CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
throwIO :: forall e a. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> GHC.Types.IO a
throwTo :: forall e. Exception e => GHC.Internal.Conc.Sync.ThreadId -> e -> GHC.Types.IO ()
try :: forall e a. Exception e => GHC.Types.IO a -> GHC.Types.IO (GHC.Internal.Data.Either.Either e a)
......@@ -407,7 +407,7 @@ module Control.Exception.Base where
patError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
recConError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
recSelError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::GHC.Internal.Stack.Types.CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
throwIO :: forall e a. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> GHC.Types.IO a
throwTo :: forall e. Exception e => GHC.Internal.Conc.Sync.ThreadId -> e -> GHC.Types.IO ()
try :: forall e a. Exception e => GHC.Types.IO a -> GHC.Types.IO (GHC.Internal.Data.Either.Either e a)
......@@ -5319,7 +5319,7 @@ module GHC.Exception where
prettySrcLoc :: SrcLoc -> GHC.Internal.Base.String
ratioZeroDenomException :: SomeException
showCCSStack :: [GHC.Internal.Base.String] -> [GHC.Internal.Base.String]
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
underflowException :: SomeException
 
module GHC.Exception.Type where
......
......@@ -292,7 +292,7 @@ module Control.Exception where
mask_ :: forall a. GHC.Types.IO a -> GHC.Types.IO a
onException :: forall a b. GHC.Types.IO a -> GHC.Types.IO b -> GHC.Types.IO a
someExceptionContext :: SomeException -> GHC.Internal.Exception.Context.ExceptionContext
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::GHC.Internal.Stack.Types.CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
throwIO :: forall e a. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> GHC.Types.IO a
throwTo :: forall e. Exception e => GHC.Internal.Conc.Sync.ThreadId -> e -> GHC.Types.IO ()
try :: forall e a. Exception e => GHC.Types.IO a -> GHC.Types.IO (GHC.Internal.Data.Either.Either e a)
......@@ -407,7 +407,7 @@ module Control.Exception.Base where
patError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
recConError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
recSelError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::GHC.Internal.Stack.Types.CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
throwIO :: forall e a. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> GHC.Types.IO a
throwTo :: forall e. Exception e => GHC.Internal.Conc.Sync.ThreadId -> e -> GHC.Types.IO ()
try :: forall e a. Exception e => GHC.Types.IO a -> GHC.Types.IO (GHC.Internal.Data.Either.Either e a)
......@@ -5288,7 +5288,7 @@ module GHC.Exception where
prettySrcLoc :: SrcLoc -> GHC.Internal.Base.String
ratioZeroDenomException :: SomeException
showCCSStack :: [GHC.Internal.Base.String] -> [GHC.Internal.Base.String]
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
underflowException :: SomeException
 
module GHC.Exception.Type where
......@@ -292,7 +292,7 @@ module Control.Exception where
mask_ :: forall a. GHC.Types.IO a -> GHC.Types.IO a
onException :: forall a b. GHC.Types.IO a -> GHC.Types.IO b -> GHC.Types.IO a
someExceptionContext :: SomeException -> GHC.Internal.Exception.Context.ExceptionContext
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::GHC.Internal.Stack.Types.CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
throwIO :: forall e a. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> GHC.Types.IO a
throwTo :: forall e. Exception e => GHC.Internal.Conc.Sync.ThreadId -> e -> GHC.Types.IO ()
try :: forall e a. Exception e => GHC.Types.IO a -> GHC.Types.IO (GHC.Internal.Data.Either.Either e a)
......@@ -407,7 +407,7 @@ module Control.Exception.Base where
patError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
recConError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
recSelError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::GHC.Internal.Stack.Types.CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
throwIO :: forall e a. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> GHC.Types.IO a
throwTo :: forall e. Exception e => GHC.Internal.Conc.Sync.ThreadId -> e -> GHC.Types.IO ()
try :: forall e a. Exception e => GHC.Types.IO a -> GHC.Types.IO (GHC.Internal.Data.Either.Either e a)
......@@ -5465,7 +5465,7 @@ module GHC.Exception where
prettySrcLoc :: SrcLoc -> GHC.Internal.Base.String
ratioZeroDenomException :: SomeException
showCCSStack :: [GHC.Internal.Base.String] -> [GHC.Internal.Base.String]
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
underflowException :: SomeException
 
module GHC.Exception.Type where
......
......@@ -292,7 +292,7 @@ module Control.Exception where
mask_ :: forall a. GHC.Types.IO a -> GHC.Types.IO a
onException :: forall a b. GHC.Types.IO a -> GHC.Types.IO b -> GHC.Types.IO a
someExceptionContext :: SomeException -> GHC.Internal.Exception.Context.ExceptionContext
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::GHC.Internal.Stack.Types.CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
throwIO :: forall e a. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> GHC.Types.IO a
throwTo :: forall e. Exception e => GHC.Internal.Conc.Sync.ThreadId -> e -> GHC.Types.IO ()
try :: forall e a. Exception e => GHC.Types.IO a -> GHC.Types.IO (GHC.Internal.Data.Either.Either e a)
......@@ -407,7 +407,7 @@ module Control.Exception.Base where
patError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
recConError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
recSelError :: forall (q :: GHC.Types.RuntimeRep) (a :: TYPE q). GHC.Prim.Addr# -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::GHC.Internal.Stack.Types.CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
throwIO :: forall e a. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> GHC.Types.IO a
throwTo :: forall e. Exception e => GHC.Internal.Conc.Sync.ThreadId -> e -> GHC.Types.IO ()
try :: forall e a. Exception e => GHC.Types.IO a -> GHC.Types.IO (GHC.Internal.Data.Either.Either e a)
......@@ -5319,7 +5319,7 @@ module GHC.Exception where
prettySrcLoc :: SrcLoc -> GHC.Internal.Base.String
ratioZeroDenomException :: SomeException
showCCSStack :: [GHC.Internal.Base.String] -> [GHC.Internal.Base.String]
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (?callStack::CallStack, Exception e) => e -> a
throw :: forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r) e. (GHC.Internal.Stack.Types.HasCallStack, Exception e) => e -> a
underflowException :: SomeException
 
module GHC.Exception.Type where
......
......@@ -126,6 +126,12 @@ EventlogOutput2:
./EventlogOutput +RTS -l
ls EventlogOutput.eventlog >/dev/null
.PHONY: T17747
T17747:
$(RM) T17747_c.o T17747.o T17747.hi
'$(TEST_HC)' $(TEST_HC_OPTS) -v0 --make T17747 T17747_c.c T17747_cmm.cmm -I$(TOP)/../rts
./T17747
.PHONY: EventlogOutputNull
EventlogOutputNull:
"$(TEST_HC)" -rtsopts -v0 EventlogOutput.hs
......
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE UnliftedFFITypes #-}
{-# LANGUAGE GHCForeignImportPrim #-}
module Main (main) where
import Foreign.C
import Foreign.Ptr
import Foreign.Storable
import System.Mem (performMajorGC)
import GHC.Exts
import GHC.Base (IO(IO))
-- | Test that we can allocate 'ByteArray#'s outside of the @HEAP_ALLOCED()@ address space without
-- upsetting the GC. To be extra sure we attach weak pointers with C finalizers to the
-- 'ByteArray#'s. We keep them alive and run a major GC so that the GC has to trace the live
-- 'ByteArray#'s.
--
-- On older GHC versions this upsets the GC because it does not expect heap objects with closure
-- type @ARR_WORDS@ to exist outside the heap.
--
-- > internal error: evacuate(static): strange closure type 42
--
-- Finally we free the backing memory with `unsafeFreeByteArray`. Then we rerun the GC'd again.
-- Note: When connecting finalizers they seem to fire on shutdown of the RTS not on a major GC
-- invocation.
--
main :: IO ()
main = do
heapallocedTest
bytearrayTest
-- | This checks that the CMM impl of HEAP_ALLOCED matches the behaviour of
-- the C version. This test lives here since the CMM HEAP_ALLOCED is used by
-- the isByteArrayPinned# primop now that it supports byte arrays that are
-- not themselves HEAP_ALLOCED.
--
heapallocedTest :: IO ()
heapallocedTest = do
let same = and [ c_HEAP_ALLOCED ptr == cmm_HEAP_ALLOCED ptr
| addr <- addrs
, let ptr = plusPtr nullPtr addr ]
putStrLn ("HEAP_ALLOCED = " ++ show same
++ "\t(c_HEAP_ALLOCED ptr == cmm_HEAP_ALLOCED ptr)")
where
-- For values selected here see OSMem.c
heapLowerbound = 8 * (2^30) -- 8GB lower bound starting index of the heap
heapDefaultStart = 0x4200000000 -- > 32GB default starting address of the heap
heapSizes = [0 -- Check the heap lower starting bound
, 2^40, 2^38] -- Check the heap upper bounds at both 1TB and 1/4TB of virtual memory
addrs
-- Addresses around the start of the heap
= [heapStart + heapSize + offset
| heapStart <- [heapLowerbound, heapDefaultStart]
, heapSize <- heapSizes
, offset <- [-1000..1000]] -- Area of the bounds check
-- 2k address probes, appropriate to the address space
++ case sizeOf (nullPtr :: Ptr ()) of
4 -> [0, 2^21 .. 2^32-1] -- 0 to 4Gb-1 in 2Mb jumps
8 -> [0, 2^30 .. 2^41-1] -- 0 to 2Tb-1 in 1Gb jumps
_ -> error "sizeOf ptr not 4 or 8"
bytearrayTest :: IO ()
bytearrayTest = do
printMallocCount "initial"
let byteLengths = [0..99]
-- malloc() a bunch of ByteArray#s on the C heap
(foreignPtrs, foreignBAs) <- unzip <$> mapM newForeignHeapByteArray byteLengths
printMallocCount "alloced"
-- allocate a bunch of ByteArray#s on the GHC heap
nativeBAs <- mapM newNativeHeapByteArray byteLengths
-- as a sanity check compare them to each other
let same = and (zipWith equalByteArrays foreignBAs nativeBAs)
putStrLn ("arrays equal = " ++ show same
++ "\t(and (zipWith equalByteArrays foreignBAs nativeBAs))")
-- and test the isByteArrayPinned# primop on them foreign byte arrays
let pinnedForeign = all isByteArrayPinned foreignBAs
putStrLn ("arrays pinned = " ++ show pinnedForeign
++ "\t(all isByteArrayPinned foreignBAs)")
-- and test the isByteArrayPinned# primop on them native byte arrays
let pinnedNative = all isByteArrayPinned nativeBAs
putStrLn ("arrays pinned = " ++ show pinnedNative
++ "\t(all isByteArrayPinned nativeBAs)")
-- while they're still live, have the GC inspect them all
performMajorGC
printMallocCount "alive"
mapM_ touchByteArray foreignBAs
-- after they have been freed, have another GC run
mapM_ unsafeFreeByteArray foreignPtrs
-- WARNING: DO NOT USE `foreignPtrs` OR `foreignBAs` AFTER THIS POINT
-- We have released the memory backing the byte arrays
performMajorGC
printMallocCount "final"
printMallocCount :: String -> IO ()
printMallocCount phase = do
n <- getMallocByteArrayCount
putStrLn ("malloc_count = " ++ show n ++ "\t" ++ phase)
data ByteArray = ByteArray ByteArray#
data MutableByteArray = MutableByteArray (MutableByteArray# RealWorld)
newNativeHeapByteArray :: Int -> IO ByteArray
newNativeHeapByteArray n = do
mba <- newByteArray n
fillAndFreezeByteArray mba n
newForeignHeapByteArray :: Int -> IO (Ptr a, ByteArray)
newForeignHeapByteArray n = do
-- mallocByteArray also allocates memory for the header of a ByteArray#
ptr <- mallocByteArray (fromIntegral n)
-- placeByteArray# writes the ByteArray# header in this additionally allocated memory
mba <- placeByteArray ptr n
ba <- fillAndFreezeByteArray mba n
pure (ptr, ba)
newByteArray :: Int -> IO MutableByteArray
newByteArray (I# n#) =
IO $ \s0 ->
case newByteArray# n# s0 of
(# s1, mba# #) -> (# s1, MutableByteArray mba# #)
placeByteArray :: Ptr a -> Int -> IO MutableByteArray
placeByteArray (Ptr addr#) (I# n#) =
IO $ \s0 ->
case placeByteArray# addr# n# s0 of
(# s1, mba# #) -> (# s1, MutableByteArray mba# #)
fillAndFreezeByteArray :: MutableByteArray -> Int -> IO ByteArray
fillAndFreezeByteArray (MutableByteArray mba#) (I# n#) =
IO $ \s0 ->
case setByteArray# mba# 0# n# n# s0 of
s1 ->
case unsafeFreezeByteArray# mba# s1 of
(# s2, ba# #) -> (# s2, ByteArray ba# #)
touchByteArray :: ByteArray -> IO ()
touchByteArray (ByteArray ba#) =
IO $ \s0 ->
case touch# ba# s0 of
s1 -> (# s1, () #)
equalByteArrays :: ByteArray -> ByteArray -> Bool
equalByteArrays (ByteArray ba1#) (ByteArray ba2#)
| let ba1len = I# (sizeofByteArray# ba1#)
ba2len = I# (sizeofByteArray# ba2#)
I# balen# = ba1len
, ba1len == ba2len
= isTrue# (0# ==# compareByteArrays# ba1# 0# ba2# 0# balen#)
isByteArrayPinned :: ByteArray -> Bool
isByteArrayPinned (ByteArray ba#) = isTrue# (isByteArrayPinned# ba#)
cmm_HEAP_ALLOCED :: Ptr a -> Int
cmm_HEAP_ALLOCED (Ptr addr#) = I# (cmm_HEAP_ALLOCED# addr#)
foreign import ccall unsafe "mallocByteArray"
mallocByteArray :: CInt -> IO (Ptr a)
foreign import ccall unsafe "unsafeFreeByteArray"
unsafeFreeByteArray :: Ptr a -> IO ()
foreign import ccall unsafe "getMallocByteArrayCount"
getMallocByteArrayCount :: IO CInt
foreign import ccall unsafe "c_HEAP_ALLOCED"
c_HEAP_ALLOCED :: Ptr a -> Int
foreign import prim "cmm_HEAP_ALLOCED"
cmm_HEAP_ALLOCED# :: Addr# -> Int#
HEAP_ALLOCED = True (c_HEAP_ALLOCED ptr == cmm_HEAP_ALLOCED ptr)
malloc_count = 0 initial
malloc_count = 100 alloced
arrays equal = True (and (zipWith equalByteArrays foreignBAs nativeBAs))
arrays pinned = True (all isByteArrayPinned foreignBAs)
arrays pinned = False (all isByteArrayPinned nativeBAs)
malloc_count = 100 alive
malloc_count = 0 final