Skip to content

Alloc-free dev#1

Open
CapZTr wants to merge 41 commits intodevelopmentfrom
alloc-free-dev
Open

Alloc-free dev#1
CapZTr wants to merge 41 commits intodevelopmentfrom
alloc-free-dev

Conversation

@CapZTr
Copy link
Owner

@CapZTr CapZTr commented May 14, 2025

No description provided.

natgavrilenko and others added 11 commits May 13, 2025 14:26
* init alias analysis for alloc

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* add MemFree events to the test

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* add first test for alias analysis

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* add second test for alias analysis

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* improve field insensitive for alloc

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* add third test for alias analysis

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* add alias analysis for free events

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* use alias analysis for alloc and free in relation analysis

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* change native relation analysis

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* change logic of mustAlias

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* Using stack pointer in alloc tests

* change exception type

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* Add full alias analysis

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* Add object alias for alloc -> memory event

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

* Add alloc and free to alias graph

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>

---------

Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Co-authored-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Co-authored-by: Natalia Gavrilenko <natgavrilenko@gmail.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
.withConfig(configuration)
.withTarget(target);
Program program = new ProgramParser().parse(new File(getTestResourcePath("alloc/" + name + ".ll")));
Wmm mcm = new ParserCat().parse(new File(getRootPath("cat/vmm.cat")));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add tests for all the three models: vmm, rc11, and c11. I think expected results should be different for all of them, so, instead of listing all variations explicitly, we can loop through the models or create a separate unit test for each model.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the tests we have so far have same results for the three models. Do you mean we will have some tests that pass for some models but fail for others?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean that it is very unlikely that we will have tests that should pass for one model and fail for the other, so we can use the same expected results for all models.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.

I think expected results should be different for all of them

It confused me a bit :-)

@@ -0,0 +1,117 @@
package com.dat3m.dartagnan.c;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package is "com.dat3m.dartagnan.llvm"

cat/c11.cat Outdated
flag ~empty (allocmem \ hb) as use-before-alloc
flag ~empty ((allocmem^-1 ; (allocptr & (ALLOC * FREE))) \ hb) as use-after-free

// TODO: Non-monotonic! (see ThreadCreation class)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thread join has been fixed, so this TODO can be removed for all three models

import java.util.HashSet;
import java.util.Set;

// TODO: Consistent naming. Should we rename relation 'Free' into FreeRel?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's align the naming and remove the TODO. Any reasonable naming of your choice should be fine.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed Alloc to MemAlloc

- Side-effectful non-termination requires at least one infix iteration
- Side-effect-free non-termination causes exactly one suffix iteration.
*/
private BooleanFormula encodeInfixSuffixDecomposition() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these methods can be changed back to private

BooleanFormula encoding = (specType == Property.Type.SAFETY) ?
encodePropertyViolations(properties) : encodePropertyWitnesses(properties);
if (!program.getFormat().equals(LLVM) || properties.contains(TERMINATION)) {
// if (!program.getFormat().equals(LLVM) || properties.contains(TERMINATION)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be changed back

import com.dat3m.dartagnan.program.Thread;
import com.dat3m.dartagnan.program.*;
import com.dat3m.dartagnan.program.event.*;
import com.dat3m.dartagnan.program.event.core.Assume;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import

// getOrCreatePredefinedRelation(IDDTRANS),
// addDefinition(product(newRelation(), Tag.MEMORY, Tag.MEMORY))
// );
case DATA -> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works correctly but doesn't look very clean. I think at this point we should consider if:

  1. Alloc and Free events should have Tag.MEMORY
  2. Alloc and Free events should inherit MemoryEvent or MemoryCoreEvent.

I didn't look into this myself yet, but we should definitely check what would be the implications of this. It might be that it will also make alias analysis a bit cleaner and give us ordering via the co relation (if Alloc and Free are a part of the co chain). It might be also that it is not going to work for some reason.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also change Tag.MEMORY to Tag.VISIBLE, and it should include all the necessary events

Tianrui Zheng added 9 commits May 14, 2025 17:05
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
@natgavrilenko
Copy link

Could you change this merge request to use development branch as a base? Otherwise, there are many changes that are not related to alloc-free

@CapZTr CapZTr changed the base branch from master to development July 24, 2025 06:37
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
@@ -1,51 +1,49 @@
; ModuleID = 'dglm.c'
source_filename = "dglm.c"
; ModuleID = 'benchmarks/lfds/dglm.c'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to update .ll files for dglm-CAS-relaxed, ms-CAS-relaxed, and trebier-CAS-relaxed. It should probably be possibly to figure out what exactly was relaxed if you compare the relaxed .ll file with a the original non-relaxed .ll file.

@@ -1,376 +1,307 @@
; ModuleID = '/home/ponce/git/Dat3M/output/clh_mutex.ll'
source_filename = "/home/ponce/git/Dat3M/benchmarks/locks/clh_mutex.c"
; ModuleID = 'benchmarks/locks/clh_mutex.c'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, we should also update the alternative acq2rx files

arr[0] = 0;
arr[1] = 1;

return NULL;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor thing: it looks like the indentation is too large here and in several other places

@@ -0,0 +1,26 @@
#include <stdlib.h>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since all tests here start with 'test1_', we can rename them to just 'test_'

_Atomic(Node *) Tail;
_Atomic(Node *) Head;

#define RETIRE_THRESHOLD 10

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better not to modify the original algorithm with our custom retirement method but do the following:

  1. Keep a 'normal' free and add a comment that it should retire instead
  2. For the VMMLFDSTest which fails, splits it into three tests: one for PROGRAM_SPEC, one for TERMINATION, and one for CAT_SPEC.
  3. For the CAT_SPEC version of the tests, change expected result to 'FAIL' and add a comment that it fails use-after-free because it requires safe memory reclamation.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we need AllocMemGraph and AllocPtrGraph because lack of these two makes testing with only one property PROGRAM_SPEC or TERMINATION impossible.

encoding = bmgr.and(encoding, encodeProgramTermination());
Event termination = program.getThreadEvents(Termination.class).stream().findFirst()
.orElseThrow(() -> new IllegalArgumentException("Malformed program: missing the termination event"));
encoding = bmgr.and(encoding, context.execution(termination));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation

ImmutableSet.Builder<Location> addresses = ImmutableSet.builder();
Collector collector = new Collector(e.getAddress());
addresses.addAll(collector.address());
protected ImmutableSet<Location> getAddressSpace(Event e) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be a private method

}

@Override
// TODO: May and must sets of AllocMem can become very large for some programs.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can also try to fix this. As far as I see, in the alias analysis, the only not thread-safe part is the EqualityAliasAnalysis (assuming that it can be called from different threads only after the initialization stage).

The problem is that EqualityAliasAnalysis computes trueSet and falseSet on demand, and that's why it can have a concurrent modification. If we precompute that sets in the constructor (and actually we will only need the trueSet), then it should be safe to use the lazy relation analysis here. Looks like it is a relatively small change that can solve a potentially huge performance issue.

// );
case DATA -> {
Relation mm = addDefinition(product(newRelation(), Tag.MEMORY, Tag.MEMORY));
Relation am = addDefinition(product(newRelation(), Tag.ALLOC, Tag.MEMORY));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can combine tags in a filter instead of creating a separate relation for each tag, something like this

case DATA -> intersection(r, getOrCreatePredefinedRelation(IDDTRANS),
addDefinition(new CartesianProduct(newRelation(),
Filter.union(Filter.byTag(Tag.MEMORY), Filter.byTag(Tag.ALLOC)),
Filter.byTag(Tag.MEMORY))));

Please also delete the commented out code

.forEach(this::instrumentLoop);
}

program.addTerminationThread();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, we should optimize this and create a a termination thread only when really needed:

  • the original condition when encodeProgramTermination() was called in PropertyEncoder, or
  • if property is CAT_SPEC and there is at least one Alloc event in the program

But I don't immediately see what would be an elegant way to get verification property in a ProgramProcessor. I will try to find a clean solution for this.

Tianrui Zheng added 4 commits August 1, 2025 16:32
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Tianrui Zheng added 15 commits August 7, 2025 10:30
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Signed-off-by: Tianrui Zheng <tianrui.zheng@huawei.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants