February 17
On 16/02/2024 11:23 PM, Kagamin wrote:
> On Friday, 16 February 2024 at 09:56:50 UTC, Richard (Rikki) Andrew Cattermole wrote:
>> That covers immutable, but not immutable that has become const.
> 
> That's fine, const can't be restrict qualified unconditionally, but immutable can.
It is not fine.

Immutable objects can be in read only memory, since nothing is allowed to modify the contents process wide.

Write to it, and see how the program segfaults.

Just to prove a point of what immutable enables a compiler to do:

```d
import std.stdio;
import core.sys.posix.sys.mman;
import core.sys.posix.unistd : sysconf, _SC_PAGESIZE;
import core.sys.posix.stdlib;

void main() {
    auto pagesize = sysconf(_SC_PAGESIZE);
    int* temp;
    posix_memalign(cast(void**)&temp, pagesize, 4 * pagesize);
    data = temp[0 .. pagesize];

    data[0 .. 2] = [1, 2];
    mprotect(data.ptr, int.sizeof * data.length, PROT_READ);
    writeln(data[0 .. 2]);

    data[0 .. 2] = [3, 4];
    writeln(data[0 .. 2]);
}

static int[] data;
```

```
[1, 2]
Error: program killed by signal 11
```

Read only memory like this is useful to kernels, it enables them to map the same ram ranges to multiple processes.

It provides a very strong guarantee, well beyond const and right now that guarantee isn't honored in the language and needs to be fixed (otherwise why have it at all?).
February 16
On Friday, 16 February 2024 at 11:10:13 UTC, Richard (Rikki) Andrew Cattermole wrote:
> Immutable objects can be in read only memory, since nothing is allowed to modify the contents process wide.

Then you won't be able to create a monitor for them.
February 17
On 17/02/2024 4:12 AM, Kagamin wrote:
> On Friday, 16 February 2024 at 11:10:13 UTC, Richard (Rikki) Andrew Cattermole wrote:
>> Immutable objects can be in read only memory, since nothing is allowed to modify the contents process wide.
> 
> Then you won't be able to create a monitor for them.

Code will still call into the null monitor.

Or we could have a way to disable it at runtime instead by setting a field to change behavior to cover all use cases (which is what I proposed ;) ).
February 18
On Friday, 16 February 2024 at 15:12:58 UTC, Kagamin wrote:
> On Friday, 16 February 2024 at 11:10:13 UTC, Richard (Rikki) Andrew Cattermole wrote:
>> Immutable objects can be in read only memory, since nothing is allowed to modify the contents process wide.
>
> Then you won't be able to create a monitor for them.

I don't get this point. The monitor field can just be the single pointer that is not transitively immutable? I mean. The compiler knows *exactly* when you access the monitor field. It's never accessed manually! This is a pointer access that can be generated at exactly line of code in the compiler. Just drop immutable there.
February 18
On Wednesday, 14 February 2024 at 04:49:28 UTC, Walter Bright wrote:
> On 2/12/2024 7:31 PM, Richard (Rikki) Andrew Cattermole wrote:
>> dmd having bad codegen here isn't a surprise, that is to be expected.
>
> I'm used to people saying that DMD doesn't do data flow analysis. It does. In fact, it is based on my OptimumC, which was the first C compiler on DOS to do DFA back in the 1980s.
>
> This isn't a case of buggy DFA. It's a case of doing DFA correctly.
>
> The issue is pointer aliasing. A pointer can point to anything, including const data. Therefore, storing through a pointer can alter any value that is reachable via a pointer. Therefore, storing through a pointer invalidates any cached value already read.
>
> This is what you're seeing.
>
> C99 tried to address this with __restrict, but few people use it or understand it. D didn't bother with it because people will inevitably misuse __restrict and get their data mysteriously corrupted.


It's probably true that not many can rattle off the legalese that defines restrict semantics correctly (I know I can't, although have to say I've never been bitten by it), but within a roughly C-like programming model its where a lot of performance comes from when at the bleeding edge so I don't know if not including it at all is particularly good either.

Thinking about it, it's actually probably mainly an issue for library users rather than the author who actually wrote restrict to begin with - I have wondered in the past whether some kind of `isolated` style type qualifier could actually help here i.e. one could provide the compiler good information and make it very obvious to the programmer.
February 18

On Sunday, 18 February 2024 at 13:41:42 UTC, FeepingCreature wrote:

>

On Friday, 16 February 2024 at 15:12:58 UTC, Kagamin wrote:

>

On Friday, 16 February 2024 at 11:10:13 UTC, Richard (Rikki) Andrew Cattermole wrote:

>

Immutable objects can be in read only memory, since nothing is allowed to modify the contents process wide.

Then you won't be able to create a monitor for them.

I don't get this point. The monitor field can just be the single pointer that is not transitively immutable? I mean. The compiler knows exactly when you access the monitor field. It's never accessed manually! This is a pointer access that can be generated at exactly line of code in the compiler. Just drop immutable there.

>

I hope someone can find the link to some DConf talk (me or Andrei) or forum post where I talk about why LDC assumes that immutable(uint*) points to mutable (nota bene) data. The reason is the mutable thread synchronization field in immutable class variable storage (__monitor), combined with casting an immutable class to an array of immutable bytes.

Okay I think I overread this, probably because it's absurd. Why is this idiom worth protecting? You're hardcasting anyways, it's forbidden in @safe anyways, just cast __monitor to uint* instead of immutable(uint*). If you're interacting with classes at such a deep level, asking you to remember that there's a mutable field in there even in immutable classes doesn't seem like a big ask.

February 19
On 19/02/2024 2:58 AM, max haughton wrote:
> Thinking about it, it's actually probably mainly an issue for library users rather than the author who actually wrote restrict to begin with - I have wondered in the past whether some kind of |isolated| style type qualifier could actually help here i.e. one could provide the compiler good information and make it very obvious to the programmer.

A couple of days ago I had a read of Joe Duffy's blog.

I was very impressed with what he had to say, enough to immediately want to buy his concurrency book and start adding his blog articles as references to my existing proposals.

He was one of the developers Midori and had a lot to say about exception mechanisms and concurrency. Turns out we both have some similar conclusions, only he gained his about 15 years prior to me (which may or may not have contributed to my impression).

The concept of isolated was one such concept that he talked about in regards to concurrency and its safety. I had not thought about it, that it would be a useful tool for making memory ownership safe in this context.

But it also applies here consider:

```d
isolated(int[]) a, b;
func(a, b);

void func(scope int[] c, scope int[] d) @safe {}
```

Should that be callable with a and b? Yes. The graph doesn't matter, it doesn't escape.

Now what about the case where it does?

```d
int[] func(return scope int[] c, scope int[] d) @safe {
	return c;
}
```

Again yes. Only one parameter contributes to return, the return would therefore be part of ``a``'s graph.

Another interesting possibility is that if one parameter is isolated, that means the second parameter ``d`` is not in ``c``'s graph, because isolated is a form of transfer of ownership, except because ``c`` is scope, the transfer doesn't occur from the outside.

As a result both ``c`` and ``d`` would have ``@restrict`` added.

This is on my todo list to research, of course how exactly it plays out with DIP1000 and the this pointer is unknown to me at this stage.
1 2 3 4
Next ›   Last »