diff --git a/compiler/GHC/StgToJS/Prim.hs b/compiler/GHC/StgToJS/Prim.hs index dcd360b0d4988d2e0606949190f9d304a27e3723..414b7251acf3931b7b3ae8dd768a7ad0cc38d3c5 100644 --- a/compiler/GHC/StgToJS/Prim.hs +++ b/compiler/GHC/StgToJS/Prim.hs @@ -1348,23 +1348,27 @@ write_boff_addr a i r o = mconcat read_stableptr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat read_stableptr a i r o = mconcat - [ r |= var "h$stablePtrBuf" -- stable pointers are always in this array - , o |= read_i32 a i + [ o |= read_i32 a i + , ifS (o .===. zero_) + (r |= null_) + (r |= var "h$stablePtrBuf") ] read_boff_stableptr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat read_boff_stableptr a i r o = mconcat - [ r |= var "h$stablePtrBuf" -- stable pointers are always in this array - , o |= read_boff_i32 a i + [ o |= read_boff_i32 a i + , ifS (o .===. zero_) + (r |= null_) + (r |= var "h$stablePtrBuf") ] write_stableptr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat write_stableptr a i _r o = write_i32 a i o - -- don't store "r" as it must be h$stablePtrBuf + -- don't store "r" as it must be h$stablePtrBuf or null write_boff_stableptr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat write_boff_stableptr a i _r o = write_boff_i32 a i o - -- don't store "r" as it must be h$stablePtrBuf + -- don't store "r" as it must be h$stablePtrBuf or null write_u8 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgStat write_u8 a i v = idx_u8 a i |= v diff --git a/rts/js/stableptr.js b/rts/js/stableptr.js index 82fc2d336c8ba52fc761cb6a05646d27204431f2..7912137ef0aded69bbaf50d24b58aa5f0f1ed05d 100644 --- a/rts/js/stableptr.js +++ b/rts/js/stableptr.js @@ -18,6 +18,13 @@ var h$stablePtrData = [null]; var h$stablePtrBuf = h$newByteArray(8); var h$stablePtrN = 1; var h$stablePtrFree = []; +// Slot 0 isn't used as offset 0 is reserved for the null pointer. In +// particular, when we store a StablePtr in an array, we don't store the array +// part. When we read it back, we only have the offset. Some codes initialize +// these stored StablePtr with NULL (hence offset 0) and if we were creating a +// StablePtr from it (i.e. [$stablePtrBuf,0]) then we can't compare them to +// nullPtr (castStablePtrToPtr [$stablePtrBuf,0] /= [null,0]). +// This happens in direct-sqlite package for example. function h$makeStablePtr(v) { TRACE_STABLEPTR("makeStablePtr")