11d54e73444e017d3a65234e0f193846f3e27472bIan Rogers/*
21d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * Copyright (C) 2011 The Android Open Source Project
31d54e73444e017d3a65234e0f193846f3e27472bIan Rogers *
41d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * Licensed under the Apache License, Version 2.0 (the "License");
51d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * you may not use this file except in compliance with the License.
61d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * You may obtain a copy of the License at
71d54e73444e017d3a65234e0f193846f3e27472bIan Rogers *
81d54e73444e017d3a65234e0f193846f3e27472bIan Rogers *      http://www.apache.org/licenses/LICENSE-2.0
91d54e73444e017d3a65234e0f193846f3e27472bIan Rogers *
101d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * Unless required by applicable law or agreed to in writing, software
111d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * distributed under the License is distributed on an "AS IS" BASIS,
121d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * See the License for the specific language governing permissions and
141d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * limitations under the License.
151d54e73444e017d3a65234e0f193846f3e27472bIan Rogers */
161d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
191d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
20a8e8f9c0a8e259a807d7b99a148d14104c24209dMathieu Chartier#include "gc/accounting/space_bitmap.h"
2111d9f06a96a6909905c248ed684366190140095cNarayan Kamath#include "runtime.h"
221d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "space.h"
231d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
241d54e73444e017d3a65234e0f193846f3e27472bIan Rogersnamespace art {
2556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
2656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstromclass OatFile;
2756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
281d54e73444e017d3a65234e0f193846f3e27472bIan Rogersnamespace gc {
291d54e73444e017d3a65234e0f193846f3e27472bIan Rogersnamespace space {
301d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
311d54e73444e017d3a65234e0f193846f3e27472bIan Rogers// An image space is a space backed with a memory mapped image.
321d54e73444e017d3a65234e0f193846f3e27472bIan Rogersclass ImageSpace : public MemMapSpace {
331d54e73444e017d3a65234e0f193846f3e27472bIan Rogers public:
341d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  SpaceType GetType() const {
351d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    return kSpaceTypeImageSpace;
361d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
371d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
38fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  // Create a boot image space from an image file for a specified instruction
3911d9f06a96a6909905c248ed684366190140095cNarayan Kamath  // set. Cannot be used for future allocation or collected.
4056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  //
4156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // Create also opens the OatFile associated with the image file so
4256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // that it be contiguously allocated with the image before the
4356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // creation of the alloc space. The ReleaseOatFile will later be
4456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // used to transfer ownership of the OatFile to the ClassLinker when
4556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // it is initialized.
46fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  static ImageSpace* CreateBootImage(const char* image,
47fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                                     InstructionSet image_isa,
48fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                                     bool secondary_image,
49fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                                     std::string* error_msg)
50fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
51fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier
52fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  // Try to open an existing app image space.
53fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  static ImageSpace* CreateFromAppImage(const char* image,
54fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                                        const OatFile* oat_file,
55fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                                        std::string* error_msg)
5690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
571d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
5852f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath  // Reads the image header from the specified image location for the
5931d8f5295c24730a57cb36cbc41197f0b7e8397cBrian Carlstrom  // instruction set image_isa or dies trying.
6052f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath  static ImageHeader* ReadImageHeaderOrDie(const char* image_location,
612afe49450f2e018f18b5de45428b9174bfd6f196Brian Carlstrom                                           InstructionSet image_isa);
6252f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath
6331d8f5295c24730a57cb36cbc41197f0b7e8397cBrian Carlstrom  // Reads the image header from the specified image location for the
642cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // instruction set image_isa. Returns null on failure, with
6531d8f5295c24730a57cb36cbc41197f0b7e8397cBrian Carlstrom  // reason in error_msg.
6631d8f5295c24730a57cb36cbc41197f0b7e8397cBrian Carlstrom  static ImageHeader* ReadImageHeader(const char* image_location,
6731d8f5295c24730a57cb36cbc41197f0b7e8397cBrian Carlstrom                                      InstructionSet image_isa,
6831d8f5295c24730a57cb36cbc41197f0b7e8397cBrian Carlstrom                                      std::string* error_msg);
6931d8f5295c24730a57cb36cbc41197f0b7e8397cBrian Carlstrom
7022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Give access to the OatFile.
7122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const OatFile* GetOatFile() const;
7222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
7356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // Releases the OatFile from the ImageSpace so it can be transfer to
74f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier  // the caller, presumably the OatFileManager.
75f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier  std::unique_ptr<const OatFile> ReleaseOatFile();
7656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
7731e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  void VerifyImageAllocations()
7890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
7931e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
801d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  const ImageHeader& GetImageHeader() const {
811d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    return *reinterpret_cast<ImageHeader*>(Begin());
821d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
831d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
8452f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath  // Actual filename where image was loaded from.
8552f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath  // For example: /data/dalvik-cache/arm/system@framework@boot.art
861d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  const std::string GetImageFilename() const {
871d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    return GetName();
881d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
891d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
9052f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath  // Symbolic location for image.
9152f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath  // For example: /system/framework/boot.art
9252f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath  const std::string GetImageLocation() const {
9352f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath    return image_location_;
9452f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath  }
9552f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath
96a8e8f9c0a8e259a807d7b99a148d14104c24209dMathieu Chartier  accounting::ContinuousSpaceBitmap* GetLiveBitmap() const OVERRIDE {
971d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    return live_bitmap_.get();
981d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
991d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
100a8e8f9c0a8e259a807d7b99a148d14104c24209dMathieu Chartier  accounting::ContinuousSpaceBitmap* GetMarkBitmap() const OVERRIDE {
1011d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    // ImageSpaces have the same bitmap for both live and marked. This helps reduce the number of
1021d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    // special cases to test against.
1031d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    return live_bitmap_.get();
1041d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
1051d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
1061d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  void Dump(std::ostream& os) const;
1071d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
108a1602f28c0e3127ad511712d4b08db89737ae901Mathieu Chartier  // Sweeping image spaces is a NOP.
109a1602f28c0e3127ad511712d4b08db89737ae901Mathieu Chartier  void Sweep(bool /* swap_bitmaps */, size_t* /* freed_objects */, size_t* /* freed_bytes */) {
110a1602f28c0e3127ad511712d4b08db89737ae901Mathieu Chartier  }
111a1602f28c0e3127ad511712d4b08db89737ae901Mathieu Chartier
11231f441464c0c8f840aba37e236ad133f30308d70Mathieu Chartier  bool CanMoveObjects() const OVERRIDE {
11331f441464c0c8f840aba37e236ad133f30308d70Mathieu Chartier    return false;
11431f441464c0c8f840aba37e236ad133f30308d70Mathieu Chartier  }
11531f441464c0c8f840aba37e236ad133f30308d70Mathieu Chartier
116a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  // Returns the filename of the image corresponding to
117a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  // requested image_location, or the filename where a new image
118a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  // should be written if one doesn't exist. Looks for a generated
119a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  // image in the specified location and then in the dalvik-cache.
120a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  //
121a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  // Returns true if an image was found, false otherwise.
122a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  static bool FindImageFilename(const char* image_location,
123a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light                                InstructionSet image_isa,
124a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light                                std::string* system_location,
125a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light                                bool* has_system,
126a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light                                std::string* data_location,
127a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light                                bool* dalvik_cache_exists,
1283c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe                                bool* has_data,
1293c13a794845e0cf7887e33b2ec20de7e6ba85f8fAndreas Gampe                                bool *is_global_cache);
130a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
1318994a04162a92759f8ec531d18ee8901145dfda0Andreas Gampe  // Use the input image filename to adapt the names in the given boot classpath to establish
1328994a04162a92759f8ec531d18ee8901145dfda0Andreas Gampe  // complete locations for secondary images.
13325adcfb7dc81131add3a0a681ae18bced6f7a0e0Mathieu Chartier  static void ExtractMultiImageLocations(const std::string& input_image_file_name,
1348994a04162a92759f8ec531d18ee8901145dfda0Andreas Gampe                                        const std::string& boot_classpath,
1358994a04162a92759f8ec531d18ee8901145dfda0Andreas Gampe                                        std::vector<std::string>* image_filenames);
1368994a04162a92759f8ec531d18ee8901145dfda0Andreas Gampe
13725adcfb7dc81131add3a0a681ae18bced6f7a0e0Mathieu Chartier  static std::string GetMultiImageBootClassPath(const std::vector<const char*>& dex_locations,
13825adcfb7dc81131add3a0a681ae18bced6f7a0e0Mathieu Chartier                                                const std::vector<const char*>& oat_filenames,
13925adcfb7dc81131add3a0a681ae18bced6f7a0e0Mathieu Chartier                                                const std::vector<const char*>& image_filenames);
14025adcfb7dc81131add3a0a681ae18bced6f7a0e0Mathieu Chartier
141763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  // Return the end of the image which includes non-heap objects such as ArtMethods and ArtFields.
142763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uint8_t* GetImageEnd() const {
143763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    return Begin() + GetImageHeader().GetImageSize();
144763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  }
145763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
146763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  // Return the start of the associated oat file.
147763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uint8_t* GetOatFileBegin() const {
148763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    return GetImageHeader().GetOatFileBegin();
149763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  }
150763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
151763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  // Return the end of the associated oat file.
152763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uint8_t* GetOatFileEnd() const {
153763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    return GetImageHeader().GetOatFileEnd();
154763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  }
155763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
156b33b1dc78d178060ff0f4327d448fd3a89df51deMathieu Chartier  void DumpSections(std::ostream& os) const;
157b33b1dc78d178060ff0f4327d448fd3a89df51deMathieu Chartier
158763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier protected:
159fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  // Tries to initialize an ImageSpace from the given image path, returning null on error.
16056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  //
161fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  // If validate_oat_file is false (for /system), do not verify that image's OatFile is up-to-date
162fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  // relative to its DexFile inputs. Otherwise (for /data), validate the inputs and generate the
163fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  // OatFile in /data/dalvik-cache if necessary. If the oat_file is null, it uses the oat file from
164fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  // the image.
165fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  static ImageSpace* Init(const char* image_filename,
166fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                          const char* image_location,
167fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                          bool validate_oat_file,
168fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                          const OatFile* oat_file,
169fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                          std::string* error_msg)
17090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
17156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
1729583fbcf597eff6d0b3c5359b8e8d5f70ed82c40Nicolas Geoffray  OatFile* OpenOatFile(const char* image, std::string* error_msg) const
17390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
17456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
1758d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  bool ValidateOatFile(std::string* error_msg) const
17690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
17756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
1781d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  friend class Space;
1791d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
180ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  static Atomic<uint32_t> bitmap_index_;
1811d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
182700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<accounting::ContinuousSpaceBitmap> live_bitmap_;
1831d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
184dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao  ImageSpace(const std::string& name,
185dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao             const char* image_location,
186dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao             MemMap* mem_map,
187dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao             accounting::ContinuousSpaceBitmap* live_bitmap,
1882d124ec869430789b51dc624db8ac655971c3a97Mathieu Chartier             uint8_t* end);
1891d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
19056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // The OatFile associated with the image during early startup to
19156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // reserve space contiguous to the image. It is later released to
19256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // the ClassLinker during it's initialization.
193700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<OatFile> oat_file_;
19456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
19588da3b0d2f76b1d6b9749315ac0c5b0367e92262Andreas Gampe  // There are times when we need to find the boot image oat file. As
19688da3b0d2f76b1d6b9749315ac0c5b0367e92262Andreas Gampe  // we release ownership during startup, keep a non-owned reference.
19788da3b0d2f76b1d6b9749315ac0c5b0367e92262Andreas Gampe  const OatFile* oat_file_non_owned_;
19888da3b0d2f76b1d6b9749315ac0c5b0367e92262Andreas Gampe
19952f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath  const std::string image_location_;
20052f84884433f3875f4b1bc5595b8d5a2d6fb3d99Narayan Kamath
201763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier private:
2021d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  DISALLOW_COPY_AND_ASSIGN(ImageSpace);
2031d54e73444e017d3a65234e0f193846f3e27472bIan Rogers};
2041d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
2051d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}  // namespace space
2061d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}  // namespace gc
2071d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}  // namespace art
2081d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
209fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif  // ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_
210