summaryrefslogtreecommitdiffstats
path: root/compiler/image_writer.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/image_writer.h')
-rw-r--r--compiler/image_writer.h210
1 files changed, 210 insertions, 0 deletions
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
new file mode 100644
index 000000000..9b0d67160
--- /dev/null
+++ b/compiler/image_writer.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_IMAGE_WRITER_H_
+#define ART_SRC_IMAGE_WRITER_H_
+
+#include <stdint.h>
+
+#include <cstddef>
+#include <set>
+#include <string>
+
+#include "driver/compiler_driver.h"
+#include "mem_map.h"
+#include "oat_file.h"
+#include "mirror/dex_cache.h"
+#include "os.h"
+#include "safe_map.h"
+#include "gc/space/space.h"
+#include "UniquePtr.h"
+
+namespace art {
+
+// Write a Space built during compilation for use during execution.
+class ImageWriter {
+ public:
+ explicit ImageWriter(const CompilerDriver& compiler_driver)
+ : compiler_driver_(compiler_driver), oat_file_(NULL), image_end_(0), image_begin_(NULL),
+ oat_data_begin_(NULL), interpreter_to_interpreter_entry_offset_(0),
+ interpreter_to_quick_entry_offset_(0), portable_resolution_trampoline_offset_(0),
+ quick_resolution_trampoline_offset_(0) {}
+
+ ~ImageWriter() {}
+
+ bool Write(const std::string& image_filename,
+ uintptr_t image_begin,
+ const std::string& oat_filename,
+ const std::string& oat_location)
+ LOCKS_EXCLUDED(Locks::mutator_lock_);
+
+ uintptr_t GetOatDataBegin() {
+ return reinterpret_cast<uintptr_t>(oat_data_begin_);
+ }
+
+ private:
+ bool AllocMemory();
+
+ // we use the lock word to store the offset of the object in the image
+ void AssignImageOffset(mirror::Object* object)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(object != NULL);
+ SetImageOffset(object, image_end_);
+ image_end_ += RoundUp(object->SizeOf(), 8); // 64-bit alignment
+ DCHECK_LT(image_end_, image_->Size());
+ }
+
+ void SetImageOffset(mirror::Object* object, size_t offset) {
+ DCHECK(object != NULL);
+ DCHECK_NE(offset, 0U);
+ DCHECK(!IsImageOffsetAssigned(object));
+ offsets_.Put(object, offset);
+ }
+
+ size_t IsImageOffsetAssigned(const mirror::Object* object) const {
+ DCHECK(object != NULL);
+ return offsets_.find(object) != offsets_.end();
+ }
+
+ size_t GetImageOffset(const mirror::Object* object) const {
+ DCHECK(object != NULL);
+ DCHECK(IsImageOffsetAssigned(object));
+ return offsets_.find(object)->second;
+ }
+
+ mirror::Object* GetImageAddress(const mirror::Object* object) const {
+ if (object == NULL) {
+ return NULL;
+ }
+ return reinterpret_cast<mirror::Object*>(image_begin_ + GetImageOffset(object));
+ }
+
+ mirror::Object* GetLocalAddress(const mirror::Object* object) const {
+ size_t offset = GetImageOffset(object);
+ byte* dst = image_->Begin() + offset;
+ return reinterpret_cast<mirror::Object*>(dst);
+ }
+
+ const byte* GetOatAddress(uint32_t offset) const {
+#if !defined(ART_USE_PORTABLE_COMPILER)
+ // With Quick, code is within the OatFile, as there are all in one
+ // .o ELF object. However with Portable, the code is always in
+ // different .o ELF objects.
+ DCHECK_LT(offset, oat_file_->Size());
+#endif
+ if (offset == 0) {
+ return NULL;
+ }
+ return oat_data_begin_ + offset;
+ }
+
+ // Returns true if the class was in the original requested image classes list.
+ bool IsImageClass(const mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Debug aid that list of requested image classes.
+ void DumpImageClasses();
+
+ // Preinitializes some otherwise lazy fields (such as Class name) to avoid runtime image dirtying.
+ void ComputeLazyFieldsForImageClasses()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static bool ComputeLazyFieldsForClassesVisitor(mirror::Class* klass, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Wire dex cache resolved strings to strings in the image to avoid runtime resolution.
+ void ComputeEagerResolvedStrings();
+ static void ComputeEagerResolvedStringsCallback(mirror::Object* obj, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Remove unwanted classes from various roots.
+ void PruneNonImageClasses() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static bool NonImageClassesVisitor(mirror::Class* c, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Verify unwanted classes removed.
+ void CheckNonImageClassesRemoved();
+ static void CheckNonImageClassesRemovedCallback(mirror::Object* obj, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Lays out where the image objects will be at runtime.
+ void CalculateNewObjectOffsets(size_t oat_loaded_size, size_t oat_data_offset)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ mirror::ObjectArray<mirror::Object>* CreateImageRoots() const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static void CalculateNewObjectOffsetsCallback(mirror::Object* obj, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Creates the contiguous image in memory and adjusts pointers.
+ void CopyAndFixupObjects();
+ static void CopyAndFixupObjectsCallback(mirror::Object* obj, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void FixupClass(const mirror::Class* orig, mirror::Class* copy)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void FixupMethod(const mirror::AbstractMethod* orig, mirror::AbstractMethod* copy)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void FixupObject(const mirror::Object* orig, mirror::Object* copy)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void FixupObjectArray(const mirror::ObjectArray<mirror::Object>* orig,
+ mirror::ObjectArray<mirror::Object>* copy)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void FixupInstanceFields(const mirror::Object* orig, mirror::Object* copy)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void FixupStaticFields(const mirror::Class* orig, mirror::Class* copy)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void FixupFields(const mirror::Object* orig, mirror::Object* copy, uint32_t ref_offsets,
+ bool is_static)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Patches references in OatFile to expect runtime addresses.
+ void PatchOatCodeAndMethods()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetPatchLocation(const CompilerDriver::PatchInformation* patch, uint32_t value)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+
+ const CompilerDriver& compiler_driver_;
+
+ // Map of Object to where it will be at runtime.
+ SafeMap<const mirror::Object*, size_t> offsets_;
+
+ // oat file with code for this image
+ OatFile* oat_file_;
+
+ // Memory mapped for generating the image.
+ UniquePtr<MemMap> image_;
+
+ // Offset to the free space in image_.
+ size_t image_end_;
+
+ // Beginning target image address for the output image.
+ byte* image_begin_;
+
+ // Beginning target oat address for the pointers from the output image to its oat file.
+ const byte* oat_data_begin_;
+
+ // Offset from oat_data_begin_ to the stubs.
+ uint32_t interpreter_to_interpreter_entry_offset_;
+ uint32_t interpreter_to_quick_entry_offset_;
+ uint32_t portable_resolution_trampoline_offset_;
+ uint32_t quick_resolution_trampoline_offset_;
+
+ // DexCaches seen while scanning for fixing up CodeAndDirectMethods
+ typedef std::set<mirror::DexCache*> Set;
+ Set dex_caches_;
+};
+
+} // namespace art
+
+#endif // ART_SRC_IMAGE_WRITER_H_