Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
5edd93e
Reduce temporary bytearray allocations in PPickler
msimacek Sep 24, 2026
34df922
Lazily initialize fastMemo table
msimacek Sep 25, 2026
58067cb
Simplify pickling builtins
msimacek Sep 24, 2026
ce1f410
Profile version and fast mode when pickling
msimacek Sep 25, 2026
964bd5e
Add a recursion limit to PPickler
msimacek Sep 25, 2026
1011631
Add more profiling to PPickler
msimacek Sep 25, 2026
f1044d3
Add fast path for pickling sequences of primitives
msimacek Sep 25, 2026
ba662f2
Add more pickler optimizations
msimacek Sep 29, 2026
b60b36c
Push down helper nodes into PPickler.SaveNode
msimacek Sep 29, 2026
afc6dd2
Make pickler write helpers static
msimacek Sep 29, 2026
a9f6108
Avoid graph size explosion
msimacek Sep 30, 2026
ad38971
Get rid of MemoIterator
msimacek Sep 30, 2026
d867056
Profile buffer bypass
msimacek Sep 30, 2026
c31f65d
Keep size estimates for buffer and memo table
msimacek Sep 30, 2026
bc0e552
Use more specific nodes when working with collections
msimacek Sep 30, 2026
2d7de94
Fix emitting OPCODE_BYTEARRAY8
msimacek Sep 30, 2026
2600c46
Reintroduce BasePickleNode again
msimacek Oct 1, 2026
c275c1d
Organize SaveNode fields
msimacek Oct 1, 2026
7848db8
Move write helpers to PPickler
msimacek Oct 1, 2026
7bfa0b6
Get rid of PPickler.maxOutputLen
msimacek Oct 1, 2026
5f78bd2
Get rid of ByteArrayView
msimacek Oct 1, 2026
eb14674
Add unpickler fast path for decoding UTF-8
msimacek Oct 1, 2026
9e2d6e5
Add profiling for seen unpickler opcodes
msimacek Oct 1, 2026
2102b34
Pre-size dictionaries when unpickling
msimacek Oct 1, 2026
2212a83
Add a few branch probabilities
msimacek Oct 1, 2026
16e83bf
Avoid copying buffer in pickle.loads
msimacek Oct 1, 2026
1a5c650
Profile file reads in unpickle
msimacek Oct 1, 2026
3047bf5
Add fast paths for pickling/unpickling large longs
msimacek Oct 1, 2026
538816c
Avoid boundary in getDottedPath
msimacek Oct 1, 2026
d0c6a40
Cache unpickled names
msimacek Oct 1, 2026
2934d6d
Use ImportName in unpickler
msimacek Oct 1, 2026
427c4fb
Push members down from BasePickleNode
msimacek Oct 1, 2026
a75550e
Use the same import mechanism in pickler and unpickler
msimacek Oct 2, 2026
29988e9
Improve pickler graph size
msimacek Oct 2, 2026
90dc553
Use separate recursive SaveNodes
msimacek Oct 2, 2026
dff33e7
Report loop counts in pickle code
msimacek Oct 8, 2026
c99ab1c
Avoid out-of-bounds access on list mutation in pickler
msimacek Oct 12, 2026
50ce7ee
Downsize oversized output bytes
msimacek Oct 13, 2026
a1b186e
Cap the max pickle buffer/memo size estimate at 15 MiB
msimacek Oct 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -42,6 +42,8 @@

import static com.oracle.graal.python.runtime.exception.PythonErrorType.PicklingError;

import java.util.Arrays;

import com.oracle.graal.python.nodes.ErrorMessages;
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.util.PythonUtils;
Expand All @@ -50,50 +52,22 @@

public final class MemoTable {

private static final int INITIAL_CAPACITY = 8;
static final int INITIAL_CAPACITY = 8;
private static final int OCCUPANCY_EXPONENT = 1; // 2^X relation between capacity and size
private static final int CAPACITY_INC_EXPONENT = 2; // 2^X increase in capacity when resizing

public static final class MemoIterator {

private int index;
private final Object[] keys;
private final int[] values;

public MemoIterator(MemoTable table) {
this.keys = table.keys;
this.values = table.values;
this.index = -1;
}

public boolean advance() {
while (true) {
index++;
if (index >= keys.length) {
return false;
}
if (keys[index] != null) {
return true;
}
}
}

public Object key() {
return keys[index];
}

public int value() {
return values[index];
}
}

private Object[] keys;
private int[] values;
private int mask;
private int size;

public MemoTable() {
initArrays(INITIAL_CAPACITY);
this(INITIAL_CAPACITY);
}

public MemoTable(int initialCapacity) {
assert initialCapacity >= INITIAL_CAPACITY && Integer.bitCount(initialCapacity) == 1;
initArrays(initialCapacity);
}

private MemoTable(MemoTable map) {
Expand All @@ -112,7 +86,8 @@ public int size() {
}

public void clear() {
initArrays(INITIAL_CAPACITY);
Arrays.fill(keys, null);
Arrays.fill(values, 0);
this.size = 0;
}

Expand Down Expand Up @@ -176,11 +151,20 @@ private void resize() {
throw PRaiseNode.raiseStatic(null, PicklingError, ErrorMessages.STRUCT_SIZE_TOO_LONG);
}

MemoIterator iterator = iterator(); // captures the current contents
Object[] oldKeys = keys;
int[] oldValues = values;
initArrays(newLength);

while (iterator.advance()) {
setInternal(iterator.key(), iterator.value());
for (int i = 0; i < oldKeys.length; i++) {
Object key = oldKeys[i];
if (key != null) {
int index = getIndex(key);
while (keys[index] != null) {
index = (index + 1) & mask;
}
keys[index] = key;
values[index] = oldValues[i];
}
}
}

Expand All @@ -192,7 +176,15 @@ public void set(Object key, int value) {
}
}

public MemoIterator iterator() {
return new MemoIterator(this);
int capacity() {
return keys.length;
}

Object getKeyAt(int index) {
return keys[index];
}

int getValueAt(int index) {
return values[index];
}
}
Loading
Loading