Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hint AllocConstantSize #106

Closed
wants to merge 19 commits into from
Closed

Hint AllocConstantSize #106

wants to merge 19 commits into from

Conversation

jkktom
Copy link
Contributor

@jkktom jkktom commented Oct 10, 2023

implementing AllocConstantSize hint.
And corresponding test code for that.

Accordingly below follow-up was implemented
memory.go - AllocateEmptySegmentOfSize function
memory_test.go - TestAllocateEmptySegmentOfSize

@rodrigo-pino
Copy link
Contributor

I am not sure what exactly is AllocConstantSize hints does. Does it creates a fix-sized, ungrowable segment? Or it is something else. Could you investigate?

@jkktom
Copy link
Contributor Author

jkktom commented Oct 12, 2023

Hi @rodrigo-pino
Yes, it creates a fixed-sized segment. But if the data surpasses the size of a single segment, the system will use multiple contiguous segments to store it.
Fixed-sized segments :When data is stored using the AllocConstantSize hint, it allocates memory segments based on the specified size. This means that the allocated memory segment has a fixed size.
Dynamic Memory Consumption: While each segment is of a fixed size, the mechanism can use multiple contiguous segments to accommodate larger data structures. For example, if a data structure is larger than a single segment, it will occupy multiple contiguous memory slots or segments to fit that data.

below is from the Cairo Mono Repo

CoreHint::AllocConstantSize { size, dst } => {
                formatdoc!(
                    

                        if '__boxed_segment' not in globals():
                            __boxed_segment = segments.add()
                        memory{dst} = __boxed_segment
                        __boxed_segment += {}
                   
                    ResOperandAsIntegerFormatter(size)
                )
            }

and the __boxed_segment seems to handle the memory segment
see below for using 1 boxed segment


//! > casm
%{
if '__boxed_segment' not in globals():
    __boxed_segment = segments.add()
memory[ap + 0] = __boxed_segment
__boxed_segment += 1
%}
[fp + -3] = [[ap + 0] + 0], ap++;
ret;

or using two segments


//! > casm
%{
if '__boxed_segment' not in globals():
    __boxed_segment = segments.add()
memory[ap + 0] = __boxed_segment
__boxed_segment += 2
%}
[fp + -4] = [[ap + 0] + 0], ap++;
[fp + -3] = [[ap + -1] + 1];
ret;

@jkktom
Copy link
Contributor Author

jkktom commented Oct 12, 2023

Python VM investigating furthermore, in the Cairo-lang project,
Each memory segment has a predetermined size that is calculated using the compute_effective_sizes function. This function determines the used size for each segment.

The relocate_segments function then uses this size information to move segments while preserving their respective sizes, reinforcing the fixed-size behavior of each segment. it assigns each memory segment a new address in memory, making sure that each segment retains its allocated size

def compute_effective_sizes(self, allow_tmp_segments: bool = False):
    ""
    Computes the current used size of the segments, and caches it.
    ""
    if self._segment_used_sizes is not None:
        # segment_sizes is already cached.
        return

    assert self.memory.is_frozen(), "Memory has to be frozen before calculating effective size."

    first_segment_index = -self.n_temp_segments if allow_tmp_segments else 0
    self._segment_used_sizes = {
        index: 0 for index in range(first_segment_index, self.n_segments)
    }
    for addr in self.memory:
        if not isinstance(addr, RelocatableValue):
            raise SecurityError(
                f"Expected memory address to be relocatable value. Found: {addr}."
            )

        previous_max_size = self._segment_used_sizes[addr.segment_index]
        self._segment_used_sizes[addr.segment_index] = max(previous_max_size, addr.offset + 1)

def relocate_segments(self) -> Dict[int, int]:
    current_addr = FIRST_MEMORY_ADDR
    res = {}

    assert (
        self._segment_used_sizes is not None
    ), "compute_effective_sizes must be called before relocate_segments."

    for segment_index, used_size in self._segment_used_sizes.items():
        res[segment_index] = current_addr
        size = self.get_segment_size(segment_index=segment_index)
        assert size >= used_size, f"Segment {segment_index} exceeded its allocated size."
        current_addr += size
    return res

go.mod Outdated Show resolved Hide resolved
@jkktom jkktom closed this Oct 24, 2023
@jkktom
Copy link
Contributor Author

jkktom commented Oct 24, 2023

Closed. This issue will be handled with different PR

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