Skip to content

Commit 7f96c94

Browse files
committed
[GR-28428] [GR-28429] Mmap uses PosixSupportLibrary abstraction.
PullRequest: graalpython/1641
2 parents 87aeb8a + eb26140 commit 7f96c94

File tree

20 files changed

+1380
-594
lines changed

20 files changed

+1380
-594
lines changed

graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/ArgumentClinic.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@
6666

6767
/**
6868
* The string should contain valid Java constant value expression, for example, {@code true}, or
69-
* {@code \"some string\"}. You may have to update the annotation processor to include import of
70-
* necessary packages or use fully qualified names.
69+
* {@code \"some string\"}. Another supported value is an identifier of a static field inside
70+
* the annotated class. For anything else, you may have to update the annotation processor to
71+
* include import of necessary packages or use fully qualified names.
7172
*/
7273
String defaultValue() default "";
7374

@@ -122,10 +123,21 @@ enum ClinicConversion {
122123
*/
123124
Int,
124125
/**
125-
* Corresponds to CPython's {@code Py_ssize_t} converter. Supports {@link #defaultValue()},
126-
* and {@link #useDefaultForNone()}.
126+
* Corresponds to CPython's {@code long} converter ("L"/"l" for old style conversions).
127+
* Supports {@link #defaultValue()}, and {@link #useDefaultForNone()}.
128+
*/
129+
Long,
130+
/**
131+
* Corresponds to CPython's {@code Py_ssize_t} converter, except that it converts the result
132+
* into Java integer. Supports {@link #defaultValue()}, and {@link #useDefaultForNone()}.
127133
*/
128134
Index,
135+
/**
136+
* Roughly corresponds to CPython's legacy "n" converter: calls the __index__ and then
137+
* converts it to Java long. Supports {@link #defaultValue()}, and
138+
* {@link #useDefaultForNone()}.
139+
*/
140+
LongIndex,
129141
/**
130142
* Corresponds to CPython's {@code slice_index} converter. Supports {@link #defaultValue()},
131143
* and {@link #useDefaultForNone()}.

graalpython/com.oracle.graal.python.cext/posix/posix.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#include <sys/utsname.h>
6363
#include <sys/wait.h>
6464
#include <sys/file.h>
65+
#include <sys/mman.h>
6566
#include <unistd.h>
6667

6768

@@ -505,6 +506,33 @@ int32_t call_system(const char *pathname) {
505506
return system(pathname);
506507
}
507508

509+
void *call_mmap(int64_t length, int32_t prot, int32_t flags, int32_t fd, int64_t offset) {
510+
void *result = mmap(NULL, length, prot, flags, fd, offset);
511+
return result == MAP_FAILED ? NULL : result;
512+
}
513+
514+
int32_t call_munmap(void* address, int64_t length) {
515+
return munmap(address, length);
516+
}
517+
518+
void call_msync(void* address, int64_t offset, int64_t length) {
519+
// TODO: can be generalized to also accept different flags,
520+
// but MS_SYNC and such seem to be defined to different values across systems
521+
msync(address + offset, length, MS_SYNC);
522+
}
523+
524+
int8_t read_byte(int8_t *address, int64_t index) {
525+
return address[index];
526+
}
527+
528+
void write_bytes(int8_t *address, int8_t* buffer, int64_t index, int32_t length) {
529+
memcpy(address + index, buffer, length);
530+
}
531+
532+
void read_bytes(int8_t *address, int8_t* buffer, int64_t index, int32_t length) {
533+
memcpy(buffer, address + index, length);
534+
}
535+
508536
int32_t get_errno() {
509537
return errno;
510538
}

graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/ArgumentClinicModel.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,13 @@
4444
import java.util.Collections;
4545
import java.util.HashSet;
4646
import java.util.List;
47+
import java.util.Optional;
4748
import java.util.Set;
4849
import java.util.function.Predicate;
50+
import java.util.stream.Stream;
4951

52+
import javax.lang.model.element.Element;
53+
import javax.lang.model.element.ElementKind;
5054
import javax.lang.model.element.TypeElement;
5155

5256
import com.oracle.graal.python.annotations.ArgumentClinic;
@@ -173,7 +177,15 @@ public static ArgumentClinicData create(ArgumentClinic annotation, TypeElement t
173177
// factory method
174178
continue factoryLoop;
175179
}
176-
args[i] = annotation.defaultValue();
180+
String defaultValue = annotation.defaultValue();
181+
Stream<? extends Element> eclosedElements = type.getEnclosedElements().stream();
182+
eclosedElements = eclosedElements.filter(x -> x.getKind() == ElementKind.FIELD && x.getSimpleName().toString().equals(defaultValue));
183+
Optional<? extends Element> typeElement = eclosedElements.findFirst();
184+
if (typeElement.isPresent()) {
185+
args[i] = type.getQualifiedName() + "." + typeElement.get().getSimpleName();
186+
} else {
187+
args[i] = defaultValue;
188+
}
177189
break;
178190
case UseDefaultForNone:
179191
args[i] = String.valueOf(annotation.useDefaultForNone());

graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/ConverterFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,11 @@ public enum Param {
9494
private static ConverterFactory[] BuiltinString;
9595
private static ConverterFactory[] BuiltinStringWithDefaultValue;
9696
private static ConverterFactory[] BuiltinInt;
97+
private static ConverterFactory[] BuiltinLong;
9798
private static ConverterFactory[] BuiltinCodePoint;
9899
private static ConverterFactory[] BuiltinBuffer;
99100
private static ConverterFactory[] BuiltinIndex;
101+
private static ConverterFactory[] BuiltinLongIndex;
100102
private static ConverterFactory[] BuiltinSliceIndex;
101103
private static ConverterFactory[] BuiltinNone;
102104
private static ConverterFactory[] BuiltinDouble;
@@ -127,6 +129,8 @@ public static ConverterFactory[] getBuiltin(ArgumentClinic annotation) {
127129
return annotation.defaultValue().isEmpty() ? BuiltinString : BuiltinStringWithDefaultValue;
128130
case Int:
129131
return BuiltinInt;
132+
case Long:
133+
return BuiltinLong;
130134
case Double:
131135
return BuiltinDouble;
132136
case CodePoint:
@@ -135,6 +139,8 @@ public static ConverterFactory[] getBuiltin(ArgumentClinic annotation) {
135139
return BuiltinBuffer;
136140
case Index:
137141
return BuiltinIndex;
142+
case LongIndex:
143+
return BuiltinLongIndex;
138144
case SliceIndex:
139145
return BuiltinSliceIndex;
140146
case None:
@@ -209,10 +215,12 @@ public static void initBuiltins(Elements elementUtils) throws ProcessingError {
209215
BuiltinString = forBuiltin(elementUtils, "JavaStringConverterNode");
210216
BuiltinStringWithDefaultValue = forBuiltin(elementUtils, "JavaStringConverterWithDefaultValueNode");
211217
BuiltinInt = forBuiltin(elementUtils, "JavaIntConversionNode");
218+
BuiltinLong = forBuiltin(elementUtils, "JavaLongConversionNode");
212219
BuiltinDouble = forBuiltin(elementUtils, "JavaDoubleConversionNode");
213220
BuiltinCodePoint = forBuiltin(elementUtils, "CodePointConversionNode");
214221
BuiltinBuffer = forBuiltin(elementUtils, "BufferConversionNode");
215222
BuiltinIndex = forBuiltin(elementUtils, "IndexConversionNode");
223+
BuiltinLongIndex = forBuiltin(elementUtils, "LongIndexConverterNode");
216224
BuiltinSliceIndex = forBuiltin(elementUtils, "SliceIndexConversionNode");
217225
BuiltinNone = forBuiltin(elementUtils, "DefaultValueNode");
218226
}

graalpython/com.oracle.graal.python.test/src/tests/test_mmap.py

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,10 @@
22
# Copyright (C) 1996-2017 Python Software Foundation
33
#
44
# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
5-
from test.support import (TESTFN, run_unittest, import_module, unlink,
6-
requires, _2G, _4G, gc_collect, cpython_only)
7-
import unittest
85
import os
96
import re
10-
import itertools
11-
import socket
12-
import sys
13-
import weakref
7+
import unittest
8+
from test.support import (TESTFN, run_unittest, import_module)
149

1510
# Skip test if we can't import mmap.
1611
mmap = import_module('mmap')
@@ -179,6 +174,53 @@ def test_context_manager_exception(self):
179174
self.assertTrue(m.closed, "context manager failed")
180175

181176

177+
FIND_BUFFER_SIZE = 1024 # keep in sync with FindNode#BUFFER_SIZE
178+
def test_find():
179+
cases = [
180+
# (size, needle_pos)
181+
(FIND_BUFFER_SIZE * 3 + 1, FIND_BUFFER_SIZE * 3 - 2),
182+
(FIND_BUFFER_SIZE * 3 + 3, FIND_BUFFER_SIZE * 3),
183+
(FIND_BUFFER_SIZE * 2, FIND_BUFFER_SIZE),
184+
(FIND_BUFFER_SIZE * 2, FIND_BUFFER_SIZE - 1),
185+
(11, 1),
186+
]
187+
for (size, needle_pos) in cases:
188+
m = mmap.mmap(-1, size)
189+
m[needle_pos] = b'a'[0]
190+
m[needle_pos + 1] = b'b'[0]
191+
m[needle_pos + 2] = b'c'[0]
192+
assert m.find(b'abc') == needle_pos
193+
assert m.find(b'abc', 0, needle_pos) == -1
194+
assert m.find(b'abc', 0, needle_pos+2) == -1
195+
assert m.find(b'abc', 0, needle_pos+3) == needle_pos
196+
assert m.find(b'abc', needle_pos) == needle_pos
197+
assert m.find(b'abc', needle_pos+1) == -1
198+
assert m.find(b'abc', needle_pos-1) == needle_pos
199+
m.close()
200+
201+
202+
def test_getitem():
203+
m = mmap.mmap(-1, 12)
204+
for i in range(0, 12):
205+
m[i] = i
206+
assert m[slice(-10, 100)] == b'\x02\x03\x04\x05\x06\x07\x08\t\n\x0b'
207+
208+
209+
def test_readline():
210+
m = mmap.mmap(-1, 9)
211+
for i in range(0, 9):
212+
m[i] = i
213+
m[4] = b'\n'[0]
214+
assert m.readline() == b'\x00\x01\x02\x03\n'
215+
assert m.readline() == b'\x05\x06\x07\x08'
216+
217+
m = mmap.mmap(-1, 1024 + 3)
218+
m[1024] = b'\n'[0]
219+
m[1025] = b'a'[0]
220+
m[1026] = b'b'[0]
221+
assert m.readline() == (b'\x00' * 1024) + b'\n'
222+
assert m.readline() == b'ab'
223+
182224

183225
def test_main():
184226
#run_unittest(MmapTests, LargeMmapTests)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
*graalpython.lib-python.3.test.test_mmap.LargeMmapTests.test_around_2GB
22
*graalpython.lib-python.3.test.test_mmap.LargeMmapTests.test_around_4GB
3+
*graalpython.lib-python.3.test.test_mmap.LargeMmapTests.test_large_offset
34
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_anonymous
45
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_bad_file_desc
6+
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_basic
57
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_concat_repeat_exception
68
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_context_manager
79
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_context_manager_exception
810
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_crasher_on_windows
911
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_double_close
12+
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_empty_file
1013
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_entire_file
1114
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_find_end
1215
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_invalid_descriptor
16+
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_length_0_large_offset
17+
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_length_0_offset
1318
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_madvise
19+
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_prot_readonly
1420
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_read_all
1521
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_read_invalid_arg
22+
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_resize_past_pos
1623
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_sizeof
1724
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_subclass
1825
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_tagname
26+
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_tougher_find
1927
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_weakref
2028
*graalpython.lib-python.3.test.test_mmap.MmapTests.test_write_returning_the_number_of_bytes_written

0 commit comments

Comments
 (0)