Merge "Free unneeded obsolete maps" into oc-dev
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk
index 1876efc..1ae79ac 100644
--- a/build/Android.common_test.mk
+++ b/build/Android.common_test.mk
@@ -66,6 +66,9 @@
 # Do you want to test the optimizing compiler with graph coloring register allocation?
 ART_TEST_OPTIMIZING_GRAPH_COLOR ?= $(ART_TEST_FULL)
 
+# Do you want to do run-tests with profiles?
+ART_TEST_SPEED_PROFILE ?= $(ART_TEST_FULL)
+
 # Do we want to test PIC-compiled tests ("apps")?
 ART_TEST_PIC_TEST ?= $(ART_TEST_FULL)
 
diff --git a/profman/profile_assistant_test.cc b/profman/profile_assistant_test.cc
index 44cc33f..38254e2 100644
--- a/profman/profile_assistant_test.cc
+++ b/profman/profile_assistant_test.cc
@@ -147,6 +147,18 @@
     return ExecAndReturnCode(argv_str, &error);
   }
 
+  bool GenerateTestProfileWithInputDex(const std::string& filename) {
+    std::string profman_cmd = GetProfmanCmd();
+    std::vector<std::string> argv_str;
+    argv_str.push_back(profman_cmd);
+    argv_str.push_back("--generate-test-profile=" + filename);
+    argv_str.push_back("--generate-test-profile-seed=0");
+    argv_str.push_back("--apk=" + GetLibCoreDexFileNames()[0]);
+    argv_str.push_back("--dex-location=" + GetLibCoreDexFileNames()[0]);
+    std::string error;
+    return ExecAndReturnCode(argv_str, &error);
+  }
+
   bool CreateProfile(std::string profile_file_contents,
                      const std::string& filename,
                      const std::string& dex_location) {
@@ -473,6 +485,17 @@
   ASSERT_TRUE(info.Load(GetFd(profile)));
 }
 
+TEST_F(ProfileAssistantTest, TestProfileGenerationWithIndexDex) {
+  ScratchFile profile;
+  // Generate a test profile passing in a dex file as reference.
+  GenerateTestProfileWithInputDex(profile.GetFilename());
+
+  // Verify that the generated profile is valid and can be loaded.
+  ASSERT_TRUE(profile.GetFile()->ResetOffset());
+  ProfileCompilationInfo info;
+  ASSERT_TRUE(info.Load(GetFd(profile)));
+}
+
 TEST_F(ProfileAssistantTest, TestProfileCreationAllMatch) {
   // Class names put here need to be in sorted order.
   std::vector<std::string> class_names = {
diff --git a/profman/profman.cc b/profman/profman.cc
index c1bdb4f..cf1ffe1 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -118,6 +118,8 @@
   UsageError("      number of methods that should be generated. Defaults to 5.");
   UsageError("  --generate-test-profile-class-ratio=<number>: the percentage from the maximum");
   UsageError("      number of classes that should be generated. Defaults to 5.");
+  UsageError("  --generate-test-profile-seed=<number>: seed for random number generator used when");
+  UsageError("      generating random test profiles. Defaults to using NanoTime.");
   UsageError("");
   UsageError("  --create-profile-from=<filename>: creates a profile from a list of classes and");
   UsageError("      methods.");
@@ -158,6 +160,7 @@
       test_profile_num_dex_(kDefaultTestProfileNumDex),
       test_profile_method_ratio_(kDefaultTestProfileMethodRatio),
       test_profile_class_ratio_(kDefaultTestProfileClassRatio),
+      test_profile_seed_(NanoTime()),
       start_ns_(NanoTime()) {}
 
   ~ProfMan() {
@@ -223,6 +226,8 @@
                         "--generate-test-profile-class-ratio",
                         &test_profile_class_ratio_,
                         Usage);
+      } else if (option.starts_with("--generate-test-profile-seed=")) {
+        ParseUintOption(option, "--generate-test-profile-seed", &test_profile_seed_, Usage);
       } else {
         Usage("Unknown argument '%s'", option.data());
       }
@@ -827,17 +832,39 @@
     if (test_profile_class_ratio_ > 100) {
       Usage("Invalid ratio for --generate-test-profile-class-ratio");
     }
+    // If given APK files or DEX locations, check that they're ok.
+    if (!apk_files_.empty() || !apks_fd_.empty() || !dex_locations_.empty()) {
+      if (apk_files_.empty() && apks_fd_.empty()) {
+        Usage("APK files must be specified when passing DEX locations to --generate-test-profile");
+      }
+      if (dex_locations_.empty()) {
+        Usage("DEX locations must be specified when passing APK files to --generate-test-profile");
+      }
+    }
     // ShouldGenerateTestProfile confirms !test_profile_.empty().
     int profile_test_fd = open(test_profile_.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
     if (profile_test_fd < 0) {
       LOG(ERROR) << "Cannot open " << test_profile_ << strerror(errno);
       return -1;
     }
-
-    bool result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
-                                                              test_profile_num_dex_,
-                                                              test_profile_method_ratio_,
-                                                              test_profile_class_ratio_);
+    bool result;
+    if (apk_files_.empty() && apks_fd_.empty() && dex_locations_.empty()) {
+      result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
+                                                           test_profile_num_dex_,
+                                                           test_profile_method_ratio_,
+                                                           test_profile_class_ratio_,
+                                                           test_profile_seed_);
+    } else {
+      // Initialize MemMap for ZipArchive::OpenFromFd.
+      MemMap::Init();
+      // Open the dex files to look up classes and methods.
+      std::vector<std::unique_ptr<const DexFile>> dex_files;
+      OpenApkFilesFromLocations(&dex_files);
+      // Create a random profile file based on the set of dex files.
+      result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
+                                                           dex_files,
+                                                           test_profile_seed_);
+    }
     close(profile_test_fd);  // ignore close result.
     return result ? 0 : -1;
   }
@@ -886,6 +913,7 @@
   uint16_t test_profile_num_dex_;
   uint16_t test_profile_method_ratio_;
   uint16_t test_profile_class_ratio_;
+  uint32_t test_profile_seed_;
   uint64_t start_ns_;
 };
 
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index 6fcf971..2d1601e 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -1139,7 +1139,8 @@
 bool ProfileCompilationInfo::GenerateTestProfile(int fd,
                                                  uint16_t number_of_dex_files,
                                                  uint16_t method_ratio,
-                                                 uint16_t class_ratio) {
+                                                 uint16_t class_ratio,
+                                                 uint32_t random_seed) {
   const std::string base_dex_location = "base.apk";
   ProfileCompilationInfo info;
   // The limits are defined by the dex specification.
@@ -1148,7 +1149,7 @@
   uint16_t number_of_methods = max_method * method_ratio / 100;
   uint16_t number_of_classes = max_classes * class_ratio / 100;
 
-  srand(MicroTime());
+  std::srand(random_seed);
 
   // Make sure we generate more samples with a low index value.
   // This makes it more likely to hit valid method/class indices in small apps.
@@ -1178,6 +1179,32 @@
   return info.Save(fd);
 }
 
+// Naive implementation to generate a random profile file suitable for testing.
+bool ProfileCompilationInfo::GenerateTestProfile(
+    int fd,
+    std::vector<std::unique_ptr<const DexFile>>& dex_files,
+    uint32_t random_seed) {
+  std::srand(random_seed);
+  ProfileCompilationInfo info;
+  for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
+    const std::string& location = dex_file->GetLocation();
+    uint32_t checksum = dex_file->GetLocationChecksum();
+    for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
+      // Randomly add a class from the dex file (with 50% chance).
+      if (std::rand() % 2 != 0) {
+        info.AddClassIndex(location, checksum, dex::TypeIndex(dex_file->GetClassDef(i).class_idx_));
+      }
+    }
+    for (uint32_t i = 0; i < dex_file->NumMethodIds(); ++i) {
+      // Randomly add a method from the dex file (with 50% chance).
+      if (std::rand() % 2 != 0) {
+        info.AddMethodIndex(location, checksum, i);
+      }
+    }
+  }
+  return info.Save(fd);
+}
+
 bool ProfileCompilationInfo::OfflineProfileMethodInfo::operator==(
       const OfflineProfileMethodInfo& other) const {
   if (inline_caches.size() != other.inline_caches.size()) {
diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h
index b8442ea..f68ed5d 100644
--- a/runtime/jit/profile_compilation_info.h
+++ b/runtime/jit/profile_compilation_info.h
@@ -262,7 +262,14 @@
   static bool GenerateTestProfile(int fd,
                                   uint16_t number_of_dex_files,
                                   uint16_t method_ratio,
-                                  uint16_t class_ratio);
+                                  uint16_t class_ratio,
+                                  uint32_t random_seed);
+
+  // Generate a test profile which will randomly contain classes and methods from
+  // the provided list of dex files.
+  static bool GenerateTestProfile(int fd,
+                                  std::vector<std::unique_ptr<const DexFile>>& dex_files,
+                                  uint32_t random_seed);
 
   // Check that the given profile method info contain the same data.
   static bool Equals(const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi1,
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index cc015b0..187b383 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -208,7 +208,7 @@
 endef
 
 TARGET_TYPES := host target
-COMPILER_TYPES := jit interpreter optimizing regalloc_gc jit interp-ac
+COMPILER_TYPES := jit interpreter optimizing regalloc_gc jit interp-ac speed-profile
 IMAGE_TYPES := picimage no-image multipicimage
 ALL_ADDRESS_SIZES := 64 32
 
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 808e58a..f1b6132 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -64,6 +64,7 @@
 APP_IMAGE="y"
 VDEX_FILTER=""
 PROFILE="n"
+RANDOM_PROFILE="n"
 
 # if "y", run 'sync' before dalvikvm to make sure all files from
 # build step (e.g. dex2oat) were finished writing.
@@ -273,6 +274,9 @@
     elif [ "x$1" = "x--profile" ]; then
         PROFILE="y"
         shift
+    elif [ "x$1" = "x--random-profile" ]; then
+        RANDOM_PROFILE="y"
+        shift
     elif expr "x$1" : "x--" >/dev/null 2>&1; then
         echo "unknown $0 option: $1" 1>&2
         exit 1
@@ -506,17 +510,23 @@
 strip_cmdline="true"
 sync_cmdline="true"
 
-if [ "$PROFILE" = "y" ]; then
+# PROFILE takes precedence over RANDOM_PROFILE, since PROFILE tests require a
+# specific profile to run properly.
+if [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then
   profman_cmdline="${ANDROID_ROOT}/bin/profman  \
     --apk=$DEX_LOCATION/$TEST_NAME.jar \
-    --dex-location=$DEX_LOCATION/$TEST_NAME.jar \
-    --create-profile-from=$DEX_LOCATION/profile \
-    --reference-profile-file=$DEX_LOCATION/$TEST_NAME.prof"
+    --dex-location=$DEX_LOCATION/$TEST_NAME.jar"
   COMPILE_FLAGS="${COMPILE_FLAGS} --profile-file=$DEX_LOCATION/$TEST_NAME.prof"
   FLAGS="${FLAGS} -Xcompiler-option --profile-file=$DEX_LOCATION/$TEST_NAME.prof"
+  if [ "$PROFILE" = "y" ]; then
+    profman_cmdline="${profman_cmdline} --create-profile-from=$DEX_LOCATION/profile \
+        --reference-profile-file=$DEX_LOCATION/$TEST_NAME.prof"
+  else
+    profman_cmdline="${profman_cmdline} --generate-test-profile=$DEX_LOCATION/$TEST_NAME.prof \
+        --generate-test-profile-seed=0"
+  fi
 fi
 
-
 if [ "$PREBUILD" = "y" ]; then
   mkdir_locations="${mkdir_locations} ${DEX_LOCATION}/oat/$ISA"
   if [ "$APP_IMAGE" = "y" ]; then
@@ -603,7 +613,7 @@
       adb shell mkdir -p $DEX_LOCATION
       adb push $TEST_NAME.jar $DEX_LOCATION
       adb push $TEST_NAME-ex.jar $DEX_LOCATION
-      if [ "$PROFILE" = "y" ]; then
+      if [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then
         adb push profile $DEX_LOCATION
       fi
     else
@@ -611,7 +621,7 @@
       adb shell mkdir -p $DEX_LOCATION >/dev/null 2>&1
       adb push $TEST_NAME.jar $DEX_LOCATION >/dev/null 2>&1
       adb push $TEST_NAME-ex.jar $DEX_LOCATION >/dev/null 2>&1
-      if [ "$PROFILE" = "y" ]; then
+      if [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then
         adb push profile $DEX_LOCATION >/dev/null 2>&1
       fi
 
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 3f722c7..1738acf 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -259,7 +259,7 @@
                   "602-deoptimizeable"],
         "description": ["Tests that should fail when the optimizing compiler ",
                         "compiles them non-debuggable."],
-        "variant": "optimizing &  ndebuggable | regalloc_gc & ndebuggable"
+        "variant": "optimizing & ndebuggable | regalloc_gc & ndebuggable | speed-profile & ndebuggable"
     },
     {
         "tests": "596-app-images",
diff --git a/test/run-all-tests b/test/run-all-tests
index 402c299..a0d2f23 100755
--- a/test/run-all-tests
+++ b/test/run-all-tests
@@ -155,6 +155,9 @@
     elif [ "x$1" = "x--strace" ]; then
         run_args="${run_args} --strace"
         shift
+    elif [ "x$1" = "x--random-profile" ]; then
+        run_args="${run_args} --random-profile"
+        shift
     elif expr "x$1" : "x--" >/dev/null 2>&1; then
         echo "unknown $0 option: $1" 1>&2
         usage="yes"
diff --git a/test/run-test b/test/run-test
index a6903ff..91ffdfa 100755
--- a/test/run-test
+++ b/test/run-test
@@ -382,6 +382,9 @@
         filter=$1
         run_args="${run_args} --vdex-filter $filter"
         shift
+    elif [ "x$1" = "x--random-profile" ]; then
+        run_args="${run_args} --random-profile"
+        shift
     elif expr "x$1" : "x--" >/dev/null 2>&1; then
         echo "unknown $0 option: $1" 1>&2
         usage="yes"
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index e93fb3a..46244a4 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -105,6 +105,9 @@
 # Do you want to test the optimizing compiler with graph coloring register allocation?
 ART_TEST_OPTIMIZING_GRAPH_COLOR = getEnvBoolean('ART_TEST_OPTIMIZING_GRAPH_COLOR', ART_TEST_FULL)
 
+# Do you want to do run-tests with profiles?
+ART_TEST_SPEED_PROFILE = getEnvBoolean('ART_TEST_SPEED_PROFILE', ART_TEST_FULL)
+
 # Do we want to test PIC-compiled tests ("apps")?
 ART_TEST_PIC_TEST = getEnvBoolean('ART_TEST_PIC_TEST', ART_TEST_FULL)
 # Do you want tracing tests run?
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 149578d..49dc657 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -147,7 +147,7 @@
   VARIANT_TYPE_DICT['jni'] = {'jni', 'forcecopy', 'checkjni'}
   VARIANT_TYPE_DICT['address_sizes'] = {'64', '32'}
   VARIANT_TYPE_DICT['compiler'] = {'interp-ac', 'interpreter', 'jit', 'optimizing',
-                              'regalloc_gc'}
+                              'regalloc_gc', 'speed-profile'}
 
   for v_type in VARIANT_TYPE_DICT:
     TOTAL_VARIANTS_SET = TOTAL_VARIANTS_SET.union(VARIANT_TYPE_DICT.get(v_type))
@@ -192,6 +192,8 @@
   if env.ART_TEST_OPTIMIZING:
     COMPILER_TYPES.add('optimizing')
     OPTIMIZING_COMPILER_TYPES.add('optimizing')
+  if env.ART_TEST_SPEED_PROFILE:
+    COMPILER_TYPES.add('speed-profile')
 
   # By default we run all 'compiler' variants.
   if not COMPILER_TYPES:
@@ -199,6 +201,7 @@
     COMPILER_TYPES.add('jit')
     COMPILER_TYPES.add('interpreter')
     COMPILER_TYPES.add('interp-ac')
+    COMPILER_TYPES.add('speed-profile')
     OPTIMIZING_COMPILER_TYPES.add('optimizing')
 
   if env.ART_TEST_RUN_TEST_RELOCATE:
@@ -389,6 +392,8 @@
         options_test += ' --interpreter --verify-soft-fail'
       elif compiler == 'jit':
         options_test += ' --jit'
+      elif compiler == 'speed-profile':
+        options_test += ' --random-profile'
 
       if relocate == 'relocate':
         options_test += ' --relocate'
@@ -881,6 +886,8 @@
     IMAGE_TYPES.add('no-image')
   if options['optimizing']:
     COMPILER_TYPES.add('optimizing')
+  if options['speed_profile']:
+    COMPILER_TYPES.add('speed-profile')
   if options['trace']:
     TRACE_TYPES.add('trace')
   if options['gcstress']: