Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
f60f6788
Commit
f60f6788
authored
Sep 13, 2016
by
Dong-hee Na
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Change section memory manager to fix performance problem in long-running SectionMemoryManagers
parent
75562e57
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
78 additions
and
26 deletions
+78
-26
src/codegen/memmgr.cpp
src/codegen/memmgr.cpp
+78
-26
No files found.
src/codegen/memmgr.cpp
View file @
f60f6788
...
...
@@ -19,6 +19,7 @@
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/Process.h"
#include "codegen/irgen/util.h"
#include "codegen/unwinding.h"
...
...
@@ -49,9 +50,14 @@ public:
private:
void
invalidateInstructionCache
();
struct
FreeMemBlock
{
sys
::
MemoryBlock
Free
;
unsigned
PendingPrefixIndex
;
};
struct
MemoryGroup
{
SmallVector
<
sys
::
MemoryBlock
,
16
>
PendingMem
;
SmallVector
<
sys
::
MemoryBlock
,
16
>
AllocatedMem
;
SmallVector
<
sys
::
Memory
Block
,
16
>
FreeMem
;
SmallVector
<
FreeMem
Block
,
16
>
FreeMem
;
sys
::
MemoryBlock
Near
;
};
...
...
@@ -91,21 +97,33 @@ uint8_t* PystonMemoryManager::allocateSection(MemoryGroup& MemGroup, uintptr_t S
uintptr_t
RequiredSize
=
Alignment
*
((
Size
+
Alignment
-
1
)
/
Alignment
+
1
);
uintptr_t
Addr
=
0
;
//
Look in the list of free memory regions and use a block there if one
//
is available
.
for
(
int
i
=
0
,
e
=
MemGroup
.
FreeMem
.
size
();
i
!=
e
;
++
i
)
{
sys
::
MemoryBlock
&
MB
=
MemGroup
.
FreeMem
[
i
];
if
(
MB
.
size
()
>=
RequiredSize
)
{
Addr
=
(
uintptr_t
)
MB
.
base
();
uintptr_t
EndOfBlock
=
Addr
+
MB
.
size
();
//
Note that all sections get allocated as read-write. The permissions will
//
be updated later based on memory group
.
//
for
(
FreeMemBlock
&
FreeMB
:
MemGroup
.
FreeMem
)
{
if
(
FreeMB
.
Free
.
size
()
>=
RequiredSize
)
{
Addr
=
(
uintptr_t
)
FreeMB
.
Free
.
base
();
uintptr_t
EndOfBlock
=
Addr
+
FreeMB
.
Free
.
size
();
// Align the address.
Addr
=
(
Addr
+
Alignment
-
1
)
&
~
(
uintptr_t
)(
Alignment
-
1
);
// Store cutted free memory block.
MemGroup
.
FreeMem
[
i
]
=
sys
::
MemoryBlock
((
void
*
)(
Addr
+
Size
),
EndOfBlock
-
Addr
-
Size
);
if
(
FreeMB
.
PendingPrefixIndex
==
(
unsigned
)
-
1
)
{
// The part of the block we're giving out to the user is now pending
MemGroup
.
PendingMem
.
push_back
(
sys
::
MemoryBlock
((
void
*
)
Addr
,
Size
));
// Remember this pending block, such that future allocations can just
// modify it rather than creating a new one
FreeMB
.
PendingPrefixIndex
=
MemGroup
.
PendingMem
.
size
()
-
1
;
}
else
{
sys
::
MemoryBlock
&
PendingMB
=
MemGroup
.
PendingMem
[
FreeMB
.
PendingPrefixIndex
];
PendingMB
=
sys
::
MemoryBlock
(
PendingMB
.
base
(),
Addr
+
Size
-
(
uintptr_t
)
PendingMB
.
base
());
}
// Remember how much free space is now left in this block
FreeMB
.
Free
=
sys
::
MemoryBlock
((
void
*
)(
Addr
+
Size
),
EndOfBlock
-
Addr
-
Size
);
return
(
uint8_t
*
)
Addr
;
}
}
// No pre-allocated free block was large enough. Allocate a new memory region.
// Note that all sections get allocated as read-write. The permissions will
// be updated later based on memory group.
...
...
@@ -120,7 +138,7 @@ uint8_t* PystonMemoryManager::allocateSection(MemoryGroup& MemGroup, uintptr_t S
sys
::
Memory
::
MF_READ
|
sys
::
Memory
::
MF_WRITE
,
ec
);
if
(
ec
)
{
// FIXME: Add error propogation to the interface.
return
NULL
;
return
nullptr
;
}
std
::
string
stat_name
=
"mem_section_"
+
std
::
string
(
SectionName
);
...
...
@@ -136,13 +154,17 @@ uint8_t* PystonMemoryManager::allocateSection(MemoryGroup& MemGroup, uintptr_t S
// Align the address.
Addr
=
(
Addr
+
Alignment
-
1
)
&
~
(
uintptr_t
)(
Alignment
-
1
);
MemGroup
.
PendingMem
.
push_back
(
sys
::
MemoryBlock
((
void
*
)
Addr
,
Size
));
// The allocateMappedMemory may allocate much more memory than we need. In
// this case, we store the unused memory as a free memory block.
unsigned
FreeSize
=
EndOfBlock
-
Addr
-
Size
;
if
(
FreeSize
>
16
)
MemGroup
.
FreeMem
.
push_back
(
sys
::
MemoryBlock
((
void
*
)(
Addr
+
Size
),
FreeSize
));
// Return aligned address
if
(
FreeSize
>
16
)
{
FreeMemBlock
FreeMB
;
FreeMB
.
Free
=
sys
::
MemoryBlock
((
void
*
)(
Addr
+
Size
),
FreeSize
);
FreeMB
.
PendingPrefixIndex
=
(
unsigned
)
-
1
;
MemGroup
.
FreeMem
.
push_back
(
FreeMB
);
}
return
(
uint8_t
*
)
Addr
;
}
...
...
@@ -185,15 +207,47 @@ bool PystonMemoryManager::finalizeMemory(std::string* ErrMsg) {
return
false
;
}
static
sys
::
MemoryBlock
trimBlockToPageSize
(
sys
::
MemoryBlock
M
)
{
static
const
size_t
PageSize
=
sys
::
Process
::
getPageSize
();
size_t
StartOverlap
=
(
PageSize
-
((
uintptr_t
)
M
.
base
()
%
PageSize
))
%
PageSize
;
size_t
TrimmedSize
=
M
.
size
();
TrimmedSize
-=
StartOverlap
;
TrimmedSize
-=
TrimmedSize
%
PageSize
;
sys
::
MemoryBlock
Trimmed
((
void
*
)((
uintptr_t
)
M
.
base
()
+
StartOverlap
),
TrimmedSize
);
assert
(((
uintptr_t
)
Trimmed
.
base
()
%
PageSize
)
==
0
);
assert
((
Trimmed
.
size
()
%
PageSize
)
==
0
);
assert
(
M
.
base
()
<=
Trimmed
.
base
()
&&
Trimmed
.
size
()
<=
M
.
size
());
return
Trimmed
;
}
llvm_error_code
PystonMemoryManager
::
applyMemoryGroupPermissions
(
MemoryGroup
&
MemGroup
,
unsigned
Permissions
)
{
for
(
int
i
=
0
,
e
=
MemGroup
.
AllocatedMem
.
size
();
i
!=
e
;
++
i
)
{
for
(
sys
::
MemoryBlock
&
MB
:
MemGroup
.
PendingMem
)
{
llvm_error_code
ec
;
ec
=
sys
::
Memory
::
protectMappedMemory
(
M
emGroup
.
AllocatedMem
[
i
]
,
Permissions
);
ec
=
sys
::
Memory
::
protectMappedMemory
(
M
B
,
Permissions
);
if
(
ec
)
{
return
ec
;
}
}
MemGroup
.
PendingMem
.
clear
();
// Now go through free blocks and trim any of them that don't span the entire
// page because one of the pending blocks may have overlapped it.
for
(
FreeMemBlock
&
FreeMB
:
MemGroup
.
FreeMem
)
{
FreeMB
.
Free
=
trimBlockToPageSize
(
FreeMB
.
Free
);
// We cleared the PendingMem list, so all these pointers are now invalid
FreeMB
.
PendingPrefixIndex
=
(
unsigned
)
-
1
;
}
// Remove all blocks which are now empty
MemGroup
.
FreeMem
.
erase
(
std
::
remove_if
(
MemGroup
.
FreeMem
.
begin
(),
MemGroup
.
FreeMem
.
end
(),
[](
FreeMemBlock
&
FreeMB
)
{
return
FreeMB
.
Free
.
size
()
==
0
;
}),
MemGroup
.
FreeMem
.
end
());
#if LLVMREV < 209952
return
llvm_error_code
::
success
();
...
...
@@ -203,8 +257,8 @@ llvm_error_code PystonMemoryManager::applyMemoryGroupPermissions(MemoryGroup& Me
}
void
PystonMemoryManager
::
invalidateInstructionCache
()
{
for
(
int
i
=
0
,
e
=
CodeMem
.
AllocatedMem
.
size
();
i
!=
e
;
++
i
)
sys
::
Memory
::
InvalidateInstructionCache
(
CodeMem
.
AllocatedMem
[
i
].
base
(),
CodeMem
.
AllocatedMem
[
i
]
.
size
());
for
(
sys
::
MemoryBlock
&
Block
:
CodeMem
.
PendingMem
)
sys
::
Memory
::
InvalidateInstructionCache
(
Block
.
base
(),
Block
.
size
());
}
uint64_t
PystonMemoryManager
::
getSymbolAddress
(
const
std
::
string
&
name
)
{
...
...
@@ -230,12 +284,10 @@ uint64_t PystonMemoryManager::getSymbolAddress(const std::string& name) {
}
PystonMemoryManager
::~
PystonMemoryManager
()
{
for
(
unsigned
i
=
0
,
e
=
CodeMem
.
AllocatedMem
.
size
();
i
!=
e
;
++
i
)
sys
::
Memory
::
releaseMappedMemory
(
CodeMem
.
AllocatedMem
[
i
]);
for
(
unsigned
i
=
0
,
e
=
RWDataMem
.
AllocatedMem
.
size
();
i
!=
e
;
++
i
)
sys
::
Memory
::
releaseMappedMemory
(
RWDataMem
.
AllocatedMem
[
i
]);
for
(
unsigned
i
=
0
,
e
=
RODataMem
.
AllocatedMem
.
size
();
i
!=
e
;
++
i
)
sys
::
Memory
::
releaseMappedMemory
(
RODataMem
.
AllocatedMem
[
i
]);
for
(
MemoryGroup
*
Group
:
{
&
CodeMem
,
&
RWDataMem
,
&
RODataMem
})
{
for
(
sys
::
MemoryBlock
&
Block
:
Group
->
AllocatedMem
)
sys
::
Memory
::
releaseMappedMemory
(
Block
);
}
}
std
::
unique_ptr
<
llvm
::
RTDyldMemoryManager
>
createMemoryManager
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment