Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
halo
art
Commits
41be588f
Commit
41be588f
authored
8 years ago
by
TreeHugger Robot
Committed by
Android (Google) Code Review
8 years ago
Browse files
Options
Download
Plain Diff
Merge "Make image test multi image" into nyc-mr1-dev
parents
894f3fd2
25adcfb7
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
282 additions
and
179 deletions
+282
-179
compiler/image_test.cc
compiler/image_test.cc
+197
-122
dex2oat/dex2oat.cc
dex2oat/dex2oat.cc
+4
-44
runtime/common_runtime_test.cc
runtime/common_runtime_test.cc
+16
-3
runtime/common_runtime_test.h
runtime/common_runtime_test.h
+6
-0
runtime/gc/heap.cc
runtime/gc/heap.cc
+3
-3
runtime/gc/space/image_space.cc
runtime/gc/space/image_space.cc
+48
-3
runtime/gc/space/image_space.h
runtime/gc/space/image_space.h
+5
-1
runtime/runtime.cc
runtime/runtime.cc
+3
-3
No files found.
compiler/image_test.cc
View file @
41be588f
...
...
@@ -56,33 +56,63 @@ void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) {
compiler_options_
->
SetInlineMaxCodeUnits
(
CompilerOptions
::
kDefaultInlineMaxCodeUnits
);
ClassLinker
*
class_linker
=
Runtime
::
Current
()
->
GetClassLinker
();
const
std
::
vector
<
const
DexFile
*>&
boot_class_path
=
class_linker
->
GetBootClassPath
();
const
size_t
num_images
=
boot_class_path
.
size
();
// Enable write for dex2dex.
for
(
const
DexFile
*
dex_file
:
class_linker
->
GetB
oot
C
lass
P
ath
()
)
{
for
(
const
DexFile
*
dex_file
:
b
oot
_c
lass
_p
ath
)
{
dex_file
->
EnableWrite
();
}
// Create a generic location tmp file, to be the base of the .art and .oat temporary files.
ScratchFile
location
;
ScratchFile
image_location
(
location
,
".art"
);
std
::
string
image_filename
(
GetSystemImageFilename
(
image_location
.
GetFilename
().
c_str
(),
kRuntimeISA
));
size_t
pos
=
image_filename
.
rfind
(
'/'
);
CHECK_NE
(
pos
,
std
::
string
::
npos
)
<<
image_filename
;
std
::
string
image_dir
(
image_filename
,
0
,
pos
);
int
mkdir_result
=
mkdir
(
image_dir
.
c_str
(),
0700
);
CHECK_EQ
(
0
,
mkdir_result
)
<<
image_dir
;
ScratchFile
image_file
(
OS
::
CreateEmptyFile
(
image_filename
.
c_str
()));
std
::
string
oat_filename
(
image_filename
,
0
,
image_filename
.
size
()
-
3
);
oat_filename
+=
"oat"
;
ScratchFile
oat_file
(
OS
::
CreateEmptyFile
(
oat_filename
.
c_str
()));
std
::
vector
<
ScratchFile
>
image_locations
;
{
ScratchFile
location
;
for
(
int
i
=
0
;
i
<
static_cast
<
int
>
(
num_images
);
++
i
)
{
std
::
string
cur_location
(
StringPrintf
(
"%s-%d.art"
,
location
.
GetFilename
().
c_str
(),
i
));
image_locations
.
push_back
(
ScratchFile
(
cur_location
));
}
}
std
::
vector
<
std
::
string
>
image_filenames
;
std
::
vector
<
ScratchFile
>
image_files
;
std
::
string
image_dir
;
for
(
ScratchFile
&
file
:
image_locations
)
{
std
::
string
image_filename
(
GetSystemImageFilename
(
file
.
GetFilename
().
c_str
(),
kRuntimeISA
));
image_filenames
.
push_back
(
image_filename
);
size_t
pos
=
image_filename
.
rfind
(
'/'
);
CHECK_NE
(
pos
,
std
::
string
::
npos
)
<<
image_filename
;
if
(
image_dir
.
empty
())
{
image_dir
=
image_filename
.
substr
(
0
,
pos
);
int
mkdir_result
=
mkdir
(
image_dir
.
c_str
(),
0700
);
CHECK_EQ
(
0
,
mkdir_result
)
<<
image_dir
;
}
image_files
.
push_back
(
ScratchFile
(
OS
::
CreateEmptyFile
(
image_filename
.
c_str
())));
}
std
::
vector
<
std
::
string
>
oat_filenames
;
std
::
vector
<
ScratchFile
>
oat_files
;
for
(
const
std
::
string
&
image_filename
:
image_filenames
)
{
std
::
string
oat_filename
(
image_filename
.
substr
(
0
,
image_filename
.
size
()
-
strlen
(
"art"
))
+
"oat"
);
oat_files
.
push_back
(
ScratchFile
(
OS
::
CreateEmptyFile
(
oat_filename
.
c_str
())));
oat_filenames
.
push_back
(
oat_filename
);
}
const
uintptr_t
requested_image_base
=
ART_BASE_ADDRESS
;
std
::
unordered_map
<
const
DexFile
*
,
size_t
>
dex_file_to_oat_index_map
;
std
::
vector
<
const
char
*>
oat_filename_vector
(
1
,
oat_filename
.
c_str
());
for
(
const
DexFile
*
dex_file
:
class_linker
->
GetBootClassPath
())
{
dex_file_to_oat_index_map
.
emplace
(
dex_file
,
0
);
std
::
vector
<
const
char
*>
oat_filename_vector
;
for
(
const
std
::
string
&
file
:
oat_filenames
)
{
oat_filename_vector
.
push_back
(
file
.
c_str
());
}
std
::
vector
<
const
char
*>
image_filename_vector
;
for
(
const
std
::
string
&
file
:
image_filenames
)
{
image_filename_vector
.
push_back
(
file
.
c_str
());
}
size_t
image_idx
=
0
;
for
(
const
DexFile
*
dex_file
:
boot_class_path
)
{
dex_file_to_oat_index_map
.
emplace
(
dex_file
,
image_idx
);
++
image_idx
;
}
// TODO: compile_pic should be a test argument.
std
::
unique_ptr
<
ImageWriter
>
writer
(
new
ImageWriter
(
*
compiler_driver_
,
requested_image_base
,
/*compile_pic*/
false
,
...
...
@@ -90,7 +120,6 @@ void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) {
storage_mode
,
oat_filename_vector
,
dex_file_to_oat_index_map
));
// TODO: compile_pic should be a test argument.
{
{
jobject
class_loader
=
nullptr
;
...
...
@@ -101,94 +130,129 @@ void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) {
t
.
NewTiming
(
"WriteElf"
);
SafeMap
<
std
::
string
,
std
::
string
>
key_value_store
;
std
::
vector
<
const
char
*>
dex_filename_vector
;
for
(
size_t
i
=
0
;
i
<
boot_class_path
.
size
();
++
i
)
{
dex_filename_vector
.
push_back
(
""
);
}
key_value_store
.
Put
(
OatHeader
::
kBootClassPathKey
,
gc
::
space
::
ImageSpace
::
GetMultiImageBootClassPath
(
dex_filename_vector
,
oat_filename_vector
,
image_filename_vector
));
const
std
::
vector
<
const
DexFile
*>&
dex_files
=
class_linker
->
GetBootClassPath
();
std
::
unique_ptr
<
ElfWriter
>
elf_writer
=
CreateElfWriterQuick
(
compiler_driver_
->
GetInstructionSet
(),
compiler_driver_
->
GetInstructionSetFeatures
(),
&
compiler_driver_
->
GetCompilerOptions
(),
oat_file
.
GetFile
());
elf_writer
->
Start
();
OatWriter
oat_writer
(
/*compiling_boot_image*/
true
,
&
timings
);
OutputStream
*
rodata
=
elf_writer
->
StartRoData
();
for
(
const
DexFile
*
dex_file
:
dex_files
)
{
std
::
vector
<
std
::
unique_ptr
<
ElfWriter
>>
elf_writers
;
std
::
vector
<
std
::
unique_ptr
<
OatWriter
>>
oat_writers
;
for
(
ScratchFile
&
oat_file
:
oat_files
)
{
elf_writers
.
emplace_back
(
CreateElfWriterQuick
(
compiler_driver_
->
GetInstructionSet
(),
compiler_driver_
->
GetInstructionSetFeatures
(),
&
compiler_driver_
->
GetCompilerOptions
(),
oat_file
.
GetFile
()));
elf_writers
.
back
()
->
Start
();
oat_writers
.
emplace_back
(
new
OatWriter
(
/*compiling_boot_image*/
true
,
&
timings
));
}
std
::
vector
<
OutputStream
*>
rodata
;
std
::
vector
<
std
::
unique_ptr
<
MemMap
>>
opened_dex_files_map
;
std
::
vector
<
std
::
unique_ptr
<
const
DexFile
>>
opened_dex_files
;
// Now that we have finalized key_value_store_, start writing the oat file.
for
(
size_t
i
=
0
,
size
=
oat_writers
.
size
();
i
!=
size
;
++
i
)
{
const
DexFile
*
dex_file
=
dex_files
[
i
];
rodata
.
push_back
(
elf_writers
[
i
]
->
StartRoData
());
ArrayRef
<
const
uint8_t
>
raw_dex_file
(
reinterpret_cast
<
const
uint8_t
*>
(
&
dex_file
->
GetHeader
()),
dex_file
->
GetHeader
().
file_size_
);
oat_writer
.
AddRawDexFileSource
(
raw_dex_file
,
dex_file
->
GetLocation
().
c_str
(),
dex_file
->
GetLocationChecksum
());
oat_writers
[
i
]
->
AddRawDexFileSource
(
raw_dex_file
,
dex_file
->
GetLocation
().
c_str
(),
dex_file
->
GetLocationChecksum
());
std
::
unique_ptr
<
MemMap
>
cur_opened_dex_files_map
;
std
::
vector
<
std
::
unique_ptr
<
const
DexFile
>>
cur_opened_dex_files
;
bool
dex_files_ok
=
oat_writers
[
i
]
->
WriteAndOpenDexFiles
(
rodata
.
back
(),
oat_files
[
i
].
GetFile
(),
compiler_driver_
->
GetInstructionSet
(),
compiler_driver_
->
GetInstructionSetFeatures
(),
&
key_value_store
,
/* verify */
false
,
// Dex files may be dex-to-dex-ed, don't verify.
&
cur_opened_dex_files_map
,
&
cur_opened_dex_files
);
ASSERT_TRUE
(
dex_files_ok
);
if
(
cur_opened_dex_files_map
!=
nullptr
)
{
opened_dex_files_map
.
push_back
(
std
::
move
(
cur_opened_dex_files_map
));
for
(
std
::
unique_ptr
<
const
DexFile
>&
cur_dex_file
:
cur_opened_dex_files
)
{
// dex_file_oat_index_map_.emplace(dex_file.get(), i);
opened_dex_files
.
push_back
(
std
::
move
(
cur_dex_file
));
}
}
else
{
ASSERT_TRUE
(
cur_opened_dex_files
.
empty
());
}
}
std
::
unique_ptr
<
MemMap
>
opened_dex_files_map
;
std
::
vector
<
std
::
unique_ptr
<
const
DexFile
>>
opened_dex_files
;
bool
dex_files_ok
=
oat_writer
.
WriteAndOpenDexFiles
(
rodata
,
oat_file
.
GetFile
(),
compiler_driver_
->
GetInstructionSet
(),
compiler_driver_
->
GetInstructionSetFeatures
(),
&
key_value_store
,
/* verify */
false
,
// Dex files may be dex-to-dex-ed, don't verify.
&
opened_dex_files_map
,
&
opened_dex_files
);
ASSERT_TRUE
(
dex_files_ok
);
bool
image_space_ok
=
writer
->
PrepareImageAddressSpace
();
ASSERT_TRUE
(
image_space_ok
);
linker
::
MultiOatRelativePatcher
patcher
(
compiler_driver_
->
GetInstructionSet
(),
instruction_set_features_
.
get
());
oat_writer
.
PrepareLayout
(
compiler_driver_
.
get
(),
writer
.
get
(),
dex_files
,
&
patcher
);
size_t
rodata_size
=
oat_writer
.
GetOatHeader
().
GetExecutableOffset
();
size_t
text_size
=
oat_writer
.
GetSize
()
-
rodata_size
;
elf_writer
->
SetLoadedSectionSizes
(
rodata_size
,
text_size
,
oat_writer
.
GetBssSize
());
writer
->
UpdateOatFileLayout
(
/* oat_index */
0u
,
elf_writer
->
GetLoadedSize
(),
oat_writer
.
GetOatDataOffset
(),
oat_writer
.
GetSize
());
bool
rodata_ok
=
oat_writer
.
WriteRodata
(
rodata
);
ASSERT_TRUE
(
rodata_ok
);
elf_writer
->
EndRoData
(
rodata
);
OutputStream
*
text
=
elf_writer
->
StartText
();
bool
text_ok
=
oat_writer
.
WriteCode
(
text
);
ASSERT_TRUE
(
text_ok
);
elf_writer
->
EndText
(
text
);
bool
header_ok
=
oat_writer
.
WriteHeader
(
elf_writer
->
GetStream
(),
0u
,
0u
,
0u
);
ASSERT_TRUE
(
header_ok
);
writer
->
UpdateOatFileHeader
(
/* oat_index */
0u
,
oat_writer
.
GetOatHeader
());
elf_writer
->
WriteDynamicSection
();
elf_writer
->
WriteDebugInfo
(
oat_writer
.
GetMethodDebugInfo
());
elf_writer
->
WritePatchLocations
(
oat_writer
.
GetAbsolutePatchLocations
());
bool
success
=
elf_writer
->
End
();
ASSERT_TRUE
(
success
);
for
(
size_t
i
=
0
,
size
=
oat_files
.
size
();
i
!=
size
;
++
i
)
{
linker
::
MultiOatRelativePatcher
patcher
(
compiler_driver_
->
GetInstructionSet
(),
instruction_set_features_
.
get
());
OatWriter
*
const
oat_writer
=
oat_writers
[
i
].
get
();
ElfWriter
*
const
elf_writer
=
elf_writers
[
i
].
get
();
std
::
vector
<
const
DexFile
*>
cur_dex_files
(
1u
,
dex_files
[
i
]);
oat_writer
->
PrepareLayout
(
compiler_driver_
.
get
(),
writer
.
get
(),
cur_dex_files
,
&
patcher
);
size_t
rodata_size
=
oat_writer
->
GetOatHeader
().
GetExecutableOffset
();
size_t
text_size
=
oat_writer
->
GetSize
()
-
rodata_size
;
elf_writer
->
SetLoadedSectionSizes
(
rodata_size
,
text_size
,
oat_writer
->
GetBssSize
());
writer
->
UpdateOatFileLayout
(
i
,
elf_writer
->
GetLoadedSize
(),
oat_writer
->
GetOatDataOffset
(),
oat_writer
->
GetSize
());
bool
rodata_ok
=
oat_writer
->
WriteRodata
(
rodata
[
i
]);
ASSERT_TRUE
(
rodata_ok
);
elf_writer
->
EndRoData
(
rodata
[
i
]);
OutputStream
*
text
=
elf_writer
->
StartText
();
bool
text_ok
=
oat_writer
->
WriteCode
(
text
);
ASSERT_TRUE
(
text_ok
);
elf_writer
->
EndText
(
text
);
bool
header_ok
=
oat_writer
->
WriteHeader
(
elf_writer
->
GetStream
(),
0u
,
0u
,
0u
);
ASSERT_TRUE
(
header_ok
);
writer
->
UpdateOatFileHeader
(
i
,
oat_writer
->
GetOatHeader
());
elf_writer
->
WriteDynamicSection
();
elf_writer
->
WriteDebugInfo
(
oat_writer
->
GetMethodDebugInfo
());
elf_writer
->
WritePatchLocations
(
oat_writer
->
GetAbsolutePatchLocations
());
bool
success
=
elf_writer
->
End
();
ASSERT_TRUE
(
success
);
}
}
}
// Workound bug that mcld::Linker::emit closes oat_file by reopening as dup_oat.
std
::
unique_ptr
<
File
>
dup_oat
(
OS
::
OpenFileReadWrite
(
oat_file
.
GetFilename
().
c_str
()));
ASSERT_TRUE
(
dup_oat
.
get
()
!=
nullptr
);
{
std
::
vector
<
const
char
*>
dup_oat_filename
(
1
,
dup_oat
->
GetPath
().
c_str
());
std
::
vector
<
const
char
*>
dup_image_filename
(
1
,
image_file
.
GetFilename
().
c_str
());
bool
success_image
=
writer
->
Write
(
kInvalidFd
,
dup_
image_filename
,
dup_
oat_filename
);
image_filename
_vector
,
oat_filename
_vector
);
ASSERT_TRUE
(
success_image
);
bool
success_fixup
=
ElfWriter
::
Fixup
(
dup_oat
.
get
(),
writer
->
GetOatDataBegin
(
0
));
ASSERT_TRUE
(
success_fixup
);
ASSERT_EQ
(
dup_oat
->
FlushCloseOrErase
(),
0
)
<<
"Could not flush and close oat file "
<<
oat_file
.
GetFilename
();
for
(
size_t
i
=
0
,
size
=
oat_filenames
.
size
();
i
!=
size
;
++
i
)
{
const
char
*
oat_filename
=
oat_filenames
[
i
].
c_str
();
std
::
unique_ptr
<
File
>
oat_file
(
OS
::
OpenFileReadWrite
(
oat_filename
));
ASSERT_TRUE
(
oat_file
!=
nullptr
);
bool
success_fixup
=
ElfWriter
::
Fixup
(
oat_file
.
get
(),
writer
->
GetOatDataBegin
(
i
));
ASSERT_TRUE
(
success_fixup
);
ASSERT_EQ
(
oat_file
->
FlushCloseOrErase
(),
0
)
<<
"Could not flush and close oat file "
<<
oat_filename
;
}
}
uint64_t
image_file_size
;
{
std
::
vector
<
uint64_t
>
image_file_size
s
;
for
(
ScratchFile
&
image_file
:
image_files
)
{
std
::
unique_ptr
<
File
>
file
(
OS
::
OpenFileForReading
(
image_file
.
GetFilename
().
c_str
()));
ASSERT_TRUE
(
file
.
get
()
!=
nullptr
);
ImageHeader
image_header
;
...
...
@@ -205,7 +269,7 @@ void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) {
ASSERT_TRUE
(
space
!=
nullptr
);
ASSERT_TRUE
(
space
->
IsMallocSpace
());
image_file_size
=
file
->
GetLength
();
image_file_size
s
.
push_back
(
file
->
GetLength
()
)
;
}
ASSERT_TRUE
(
compiler_driver_
->
GetImageClasses
()
!=
nullptr
);
...
...
@@ -225,11 +289,10 @@ void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) {
java_lang_dex_file_
=
nullptr
;
MemMap
::
Init
();
std
::
unique_ptr
<
const
DexFile
>
dex
(
LoadExpectSingleDexFile
(
GetLibCoreDexFileNames
()[
0
].
c_str
()));
RuntimeOptions
options
;
std
::
string
image
(
"-Ximage:"
);
image
.
append
(
image_location
.
GetFilename
());
image
.
append
(
image_location
s
[
0
]
.
GetFilename
());
options
.
push_back
(
std
::
make_pair
(
image
.
c_str
(),
static_cast
<
void
*>
(
nullptr
)));
// By default the compiler this creates will not include patch information.
options
.
push_back
(
std
::
make_pair
(
"-Xnorelocate"
,
nullptr
));
...
...
@@ -251,38 +314,51 @@ void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) {
ASSERT_TRUE
(
heap
->
GetNonMovingSpace
()
->
IsMallocSpace
());
// We loaded the runtime with an explicit image, so it must exist.
gc
::
space
::
ImageSpace
*
image_space
=
heap
->
GetBootImageSpaces
()[
0
];
ASSERT_TRUE
(
image_space
!=
nullptr
);
if
(
storage_mode
==
ImageHeader
::
kStorageModeUncompressed
)
{
// Uncompressed, image should be smaller than file.
ASSERT_LE
(
image_space
->
Size
(),
image_file_size
);
}
else
{
// Compressed, file should be smaller than image.
ASSERT_LE
(
image_file_size
,
image_space
->
Size
());
}
image_space
->
VerifyImageAllocations
();
uint8_t
*
image_begin
=
image_space
->
Begin
();
uint8_t
*
image_end
=
image_space
->
End
();
CHECK_EQ
(
requested_image_base
,
reinterpret_cast
<
uintptr_t
>
(
image_begin
));
for
(
size_t
i
=
0
;
i
<
dex
->
NumClassDefs
();
++
i
)
{
const
DexFile
::
ClassDef
&
class_def
=
dex
->
GetClassDef
(
i
);
const
char
*
descriptor
=
dex
->
GetClassDescriptor
(
class_def
);
mirror
::
Class
*
klass
=
class_linker_
->
FindSystemClass
(
soa
.
Self
(),
descriptor
);
EXPECT_TRUE
(
klass
!=
nullptr
)
<<
descriptor
;
if
(
image_classes
.
find
(
descriptor
)
!=
image_classes
.
end
())
{
// Image classes should be located inside the image.
EXPECT_LT
(
image_begin
,
reinterpret_cast
<
uint8_t
*>
(
klass
))
<<
descriptor
;
EXPECT_LT
(
reinterpret_cast
<
uint8_t
*>
(
klass
),
image_end
)
<<
descriptor
;
ASSERT_EQ
(
heap
->
GetBootImageSpaces
().
size
(),
image_file_sizes
.
size
());
for
(
size_t
i
=
0
;
i
<
image_file_sizes
.
size
();
++
i
)
{
std
::
unique_ptr
<
const
DexFile
>
dex
(
LoadExpectSingleDexFile
(
GetLibCoreDexFileNames
()[
i
].
c_str
()));
uint64_t
image_file_size
=
image_file_sizes
[
i
];
gc
::
space
::
ImageSpace
*
image_space
=
heap
->
GetBootImageSpaces
()[
i
];
ASSERT_TRUE
(
image_space
!=
nullptr
);
if
(
storage_mode
==
ImageHeader
::
kStorageModeUncompressed
)
{
// Uncompressed, image should be smaller than file.
ASSERT_LE
(
image_space
->
GetImageHeader
().
GetImageSize
(),
image_file_size
);
}
else
{
EXPECT_TRUE
(
reinterpret_cast
<
uint8_t
*>
(
klass
)
>=
image_end
||
reinterpret_cast
<
uint8_t
*>
(
klass
)
<
image_begin
)
<<
descriptor
;
// Compressed, file should be smaller than image.
ASSERT_LE
(
image_file_size
,
image_space
->
GetImageHeader
().
GetImageSize
());
}
image_space
->
VerifyImageAllocations
();
uint8_t
*
image_begin
=
image_space
->
Begin
();
uint8_t
*
image_end
=
image_space
->
End
();
if
(
i
==
0
)
{
// This check is only valid for image 0.
CHECK_EQ
(
requested_image_base
,
reinterpret_cast
<
uintptr_t
>
(
image_begin
));
}
for
(
size_t
j
=
0
;
j
<
dex
->
NumClassDefs
();
++
j
)
{
const
DexFile
::
ClassDef
&
class_def
=
dex
->
GetClassDef
(
j
);
const
char
*
descriptor
=
dex
->
GetClassDescriptor
(
class_def
);
mirror
::
Class
*
klass
=
class_linker_
->
FindSystemClass
(
soa
.
Self
(),
descriptor
);
EXPECT_TRUE
(
klass
!=
nullptr
)
<<
descriptor
;
if
(
image_classes
.
find
(
descriptor
)
==
image_classes
.
end
())
{
EXPECT_TRUE
(
reinterpret_cast
<
uint8_t
*>
(
klass
)
>=
image_end
||
reinterpret_cast
<
uint8_t
*>
(
klass
)
<
image_begin
)
<<
descriptor
;
}
else
{
// Image classes should be located inside the image.
EXPECT_LT
(
image_begin
,
reinterpret_cast
<
uint8_t
*>
(
klass
))
<<
descriptor
;
EXPECT_LT
(
reinterpret_cast
<
uint8_t
*>
(
klass
),
image_end
)
<<
descriptor
;
}
EXPECT_TRUE
(
Monitor
::
IsValidLockWord
(
klass
->
GetLockWord
(
false
)));
}
EXPECT_TRUE
(
Monitor
::
IsValidLockWord
(
klass
->
GetLockWord
(
false
)));
}
image_file
.
Unlink
();
oat_file
.
Unlink
();
for
(
ScratchFile
&
image_file
:
image_files
)
{
image_file
.
Unlink
();
}
for
(
ScratchFile
&
oat_file
:
oat_files
)
{
oat_file
.
Unlink
();
}
int
rmdir_result
=
rmdir
(
image_dir
.
c_str
());
CHECK_EQ
(
0
,
rmdir_result
);
}
...
...
@@ -299,7 +375,6 @@ TEST_F(ImageTest, WriteReadLZ4HC) {
TestWriteRead
(
ImageHeader
::
kStorageModeLZ4HC
);
}
TEST_F
(
ImageTest
,
ImageHeaderIsValid
)
{
uint32_t
image_begin
=
ART_BASE_ADDRESS
;
uint32_t
image_size_
=
16
*
KB
;
...
...
This diff is collapsed.
Click to expand it.
dex2oat/dex2oat.cc
View file @
41be588f
...
...
@@ -1329,7 +1329,10 @@ class Dex2Oat FINAL {
if
(
IsBootImage
()
&&
image_filenames_
.
size
()
>
1
)
{
// If we're compiling the boot image, store the boot classpath into the Key-Value store.
// We need this for the multi-image case.
key_value_store_
->
Put
(
OatHeader
::
kBootClassPathKey
,
GetMultiImageBootClassPath
());
key_value_store_
->
Put
(
OatHeader
::
kBootClassPathKey
,
gc
::
space
::
ImageSpace
::
GetMultiImageBootClassPath
(
dex_locations_
,
oat_filenames_
,
image_filenames_
));
}
if
(
!
IsBootImage
())
{
...
...
@@ -1960,49 +1963,6 @@ class Dex2Oat FINAL {
return
result
;
}
std
::
string
GetMultiImageBootClassPath
()
{
DCHECK
(
IsBootImage
());
DCHECK_GT
(
oat_filenames_
.
size
(),
1u
);
// If the image filename was adapted (e.g., for our tests), we need to change this here,
// too, but need to strip all path components (they will be re-established when loading).
std
::
ostringstream
bootcp_oss
;
bool
first_bootcp
=
true
;
for
(
size_t
i
=
0
;
i
<
dex_locations_
.
size
();
++
i
)
{
if
(
!
first_bootcp
)
{
bootcp_oss
<<
":"
;
}
std
::
string
dex_loc
=
dex_locations_
[
i
];
std
::
string
image_filename
=
image_filenames_
[
i
];
// Use the dex_loc path, but the image_filename name (without path elements).
size_t
dex_last_slash
=
dex_loc
.
rfind
(
'/'
);
// npos is max(size_t). That makes this a bit ugly.
size_t
image_last_slash
=
image_filename
.
rfind
(
'/'
);
size_t
image_last_at
=
image_filename
.
rfind
(
'@'
);
size_t
image_last_sep
=
(
image_last_slash
==
std
::
string
::
npos
)
?
image_last_at
:
(
image_last_at
==
std
::
string
::
npos
)
?
std
::
string
::
npos
:
std
::
max
(
image_last_slash
,
image_last_at
);
// Note: whenever image_last_sep == npos, +1 overflow means using the full string.
if
(
dex_last_slash
==
std
::
string
::
npos
)
{
dex_loc
=
image_filename
.
substr
(
image_last_sep
+
1
);
}
else
{
dex_loc
=
dex_loc
.
substr
(
0
,
dex_last_slash
+
1
)
+
image_filename
.
substr
(
image_last_sep
+
1
);
}
// Image filenames already end with .art, no need to replace.
bootcp_oss
<<
dex_loc
;
first_bootcp
=
false
;
}
return
bootcp_oss
.
str
();
}
std
::
vector
<
std
::
string
>
GetClassPathLocations
(
const
std
::
string
&
class_path
)
{
// This function is used only for apps and for an app we have exactly one oat file.
DCHECK
(
!
IsBootImage
());
...
...
This diff is collapsed.
Click to expand it.
runtime/common_runtime_test.cc
View file @
41be588f
...
...
@@ -76,9 +76,10 @@ ScratchFile::ScratchFile() {
file_
.
reset
(
new
File
(
fd
,
GetFilename
(),
true
));
}
ScratchFile
::
ScratchFile
(
const
ScratchFile
&
other
,
const
char
*
suffix
)
{
filename_
=
other
.
GetFilename
();
filename_
+=
suffix
;
ScratchFile
::
ScratchFile
(
const
ScratchFile
&
other
,
const
char
*
suffix
)
:
ScratchFile
(
other
.
GetFilename
()
+
suffix
)
{}
ScratchFile
::
ScratchFile
(
const
std
::
string
&
filename
)
:
filename_
(
filename
)
{
int
fd
=
open
(
filename_
.
c_str
(),
O_RDWR
|
O_CREAT
,
0666
);
CHECK_NE
(
-
1
,
fd
);
file_
.
reset
(
new
File
(
fd
,
GetFilename
(),
true
));
...
...
@@ -90,6 +91,18 @@ ScratchFile::ScratchFile(File* file) {
file_
.
reset
(
file
);
}
ScratchFile
::
ScratchFile
(
ScratchFile
&&
other
)
{
*
this
=
std
::
move
(
other
);
}
ScratchFile
&
ScratchFile
::
operator
=
(
ScratchFile
&&
other
)
{
if
(
GetFile
()
!=
other
.
GetFile
())
{
std
::
swap
(
filename_
,
other
.
filename_
);
std
::
swap
(
file_
,
other
.
file_
);
}
return
*
this
;
}
ScratchFile
::~
ScratchFile
()
{
Unlink
();
}
...
...
This diff is collapsed.
Click to expand it.
runtime/common_runtime_test.h
View file @
41be588f
...
...
@@ -40,8 +40,14 @@ class ScratchFile {
public:
ScratchFile
();
explicit
ScratchFile
(
const
std
::
string
&
filename
);
ScratchFile
(
const
ScratchFile
&
other
,
const
char
*
suffix
);
explicit
ScratchFile
(
ScratchFile
&&
other
);
ScratchFile
&
operator
=
(
ScratchFile
&&
other
);
explicit
ScratchFile
(
File
*
file
);
~
ScratchFile
();
...
...
This diff is collapsed.
Click to expand it.
runtime/gc/heap.cc
View file @
41be588f
...
...
@@ -316,9 +316,9 @@ Heap::Heap(size_t initial_size,
continue
;
}
space
::
ImageSpace
::
Create
MultiImageLocations
(
image_file_name
,
boot_classpath
,
&
image_file_names
);
space
::
ImageSpace
::
Extract
MultiImageLocations
(
image_file_name
,
boot_classpath
,
&
image_file_names
);
}
}
else
{
LOG
(
ERROR
)
<<
"Could not create image space with image file '"
<<
image_file_name
<<
"'. "
...
...
This diff is collapsed.
Click to expand it.
runtime/gc/space/image_space.cc
View file @
41be588f
...
...
@@ -1508,9 +1508,54 @@ void ImageSpace::Dump(std::ostream& os) const {
<<
",name=
\"
"
<<
GetName
()
<<
"
\"
]"
;
}
void
ImageSpace
::
CreateMultiImageLocations
(
const
std
::
string
&
input_image_file_name
,
const
std
::
string
&
boot_classpath
,
std
::
vector
<
std
::
string
>*
image_file_names
)
{
std
::
string
ImageSpace
::
GetMultiImageBootClassPath
(
const
std
::
vector
<
const
char
*>&
dex_locations
,
const
std
::
vector
<
const
char
*>&
oat_filenames
,
const
std
::
vector
<
const
char
*>&
image_filenames
)
{
DCHECK_GT
(
oat_filenames
.
size
(),
1u
);
// If the image filename was adapted (e.g., for our tests), we need to change this here,
// too, but need to strip all path components (they will be re-established when loading).
std
::
ostringstream
bootcp_oss
;
bool
first_bootcp
=
true
;
for
(
size_t
i
=
0
;
i
<
dex_locations
.
size
();
++
i
)
{
if
(
!
first_bootcp
)
{
bootcp_oss
<<
":"
;
}
std
::
string
dex_loc
=
dex_locations
[
i
];
std
::
string
image_filename
=
image_filenames
[
i
];
// Use the dex_loc path, but the image_filename name (without path elements).
size_t
dex_last_slash
=
dex_loc
.
rfind
(
'/'
);
// npos is max(size_t). That makes this a bit ugly.
size_t
image_last_slash
=
image_filename
.
rfind
(
'/'
);
size_t
image_last_at
=
image_filename
.
rfind
(
'@'
);
size_t
image_last_sep
=
(
image_last_slash
==
std
::
string
::
npos
)
?
image_last_at
:
(
image_last_at
==
std
::
string
::
npos
)
?
std
::
string
::
npos
:
std
::
max
(
image_last_slash
,
image_last_at
);
// Note: whenever image_last_sep == npos, +1 overflow means using the full string.
if
(
dex_last_slash
==
std
::
string
::
npos
)
{
dex_loc
=
image_filename
.
substr
(
image_last_sep
+
1
);
}
else
{
dex_loc
=
dex_loc
.
substr
(
0
,
dex_last_slash
+
1
)
+
image_filename
.
substr
(
image_last_sep
+
1
);
}
// Image filenames already end with .art, no need to replace.
bootcp_oss
<<
dex_loc
;
first_bootcp
=
false
;
}
return
bootcp_oss
.
str
();
}
void
ImageSpace
::
ExtractMultiImageLocations
(
const
std
::
string
&
input_image_file_name
,
const
std
::
string
&
boot_classpath
,
std
::
vector
<
std
::
string
>*
image_file_names
)
{
DCHECK
(
image_file_names
!=
nullptr
);
std
::
vector
<
std
::
string
>
images
;
...
...
This diff is collapsed.
Click to expand it.
runtime/gc/space/image_space.h
View file @
41be588f
...
...
@@ -130,10 +130,14 @@ class ImageSpace : public MemMapSpace {
// Use the input image filename to adapt the names in the given boot classpath to establish
// complete locations for secondary images.
static
void
Create
MultiImageLocations
(
const
std
::
string
&
input_image_file_name
,
static
void
Extract
MultiImageLocations
(
const
std
::
string
&
input_image_file_name
,
const
std
::
string
&
boot_classpath
,
std
::
vector
<
std
::
string
>*
image_filenames
);
static
std
::
string
GetMultiImageBootClassPath
(
const
std
::
vector
<
const
char
*>&
dex_locations
,
const
std
::
vector
<
const
char
*>&
oat_filenames
,
const
std
::
vector
<
const
char
*>&
image_filenames
);
// Return the end of the image which includes non-heap objects such as ArtMethods and ArtFields.
uint8_t
*
GetImageEnd
()
const
{
return
Begin
()
+
GetImageHeader
().
GetImageSize
();
...
...
This diff is collapsed.
Click to expand it.
runtime/runtime.cc
View file @
41be588f
...
...
@@ -878,9 +878,9 @@ static bool OpenDexFilesFromImage(const std::string& image_location,
const
OatHeader
&
boot_oat_header
=
oat_file
->
GetOatHeader
();
const
char
*
boot_cp
=
boot_oat_header
.
GetStoreValueByKey
(
OatHeader
::
kBootClassPathKey
);
if
(
boot_cp
!=
nullptr
)
{
gc
::
space
::
ImageSpace
::
Create
MultiImageLocations
(
image_locations
[
0
],
boot_cp
,
&
image_locations
);
gc
::
space
::
ImageSpace
::
Extract
MultiImageLocations
(
image_locations
[
0
],
boot_cp
,
&
image_locations
);
}
}
...
...
This diff is collapsed.
Click to expand it.
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