Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/profman/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 10 kB image not shown  

Quelle  boot_image_profile.cc

  Sprache: C
 

/*
 * Copyright (C) 2017 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.
 */


#include "boot_image_profile.h"

#include <memory>
#include <set>

#include "android-base/file.h"
#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/method_reference.h"
#include "dex/type_reference.h"
#include "profile/profile_compilation_info.h"
#include "inline_cache_format_util.h"

namespace art {

using Hotness = ProfileCompilationInfo::MethodHotness;

static const std::string kMethodSep = "->";  // NOLINT [runtime/string] [4]
static const std::string kPackageUseDelim = "@";  // NOLINT [runtime/string] [4]
static constexpr char kMethodFlagStringHot = 'H';
static constexpr char kMethodFlagStringStartup = 'S';
static constexpr char kMethodFlagStringPostStartup = 'P';

// Returns the type descriptor of the given reference.
static std::string_view GetTypeDescriptorView(const TypeReference& ref) {
  const dex::TypeId& type_id = ref.dex_file->GetTypeId(ref.TypeIndex());
  return ref.dex_file->GetTypeDescriptorView(type_id);
}

// Returns the method representation used in the text format of the boot image profile.
static std::string BootImageRepresentation(const MethodReference& ref) {
  const DexFile* dex_file = ref.dex_file;
  const dex::MethodId& id = ref.GetMethodId();
  std::string signature_string(dex_file->GetMethodSignature(id).ToString());
  std::string type_string(dex_file->GetTypeDescriptorView(dex_file->GetTypeId(id.class_idx_)));
  std::string method_name(dex_file->GetMethodNameView(id));
  return type_string +
        kMethodSep +
        method_name +
        signature_string;
}

// Returns the class representation used in the text format of the boot image profile.
static std::string BootImageRepresentation(const TypeReference& ref) {
  return std::string(GetTypeDescriptorView(ref));
}

// Returns the class representation used in preloaded classes.
static std::string PreloadedClassesRepresentation(const TypeReference& ref) {
  std::string_view descriptor = GetTypeDescriptorView(ref);
  return DescriptorToDot(descriptor);
}

// Formats the list of packages from the item metadata as a debug string.
static std::string GetPackageUseString(const FlattenProfileData::ItemMetadata& metadata) {
  std::string result;
  for (const auto& it : metadata.GetAnnotations()) {
    result += it.GetOriginPackageName() + ",";
  }

  return metadata.GetAnnotations().empty()
      ? result
      : result.substr(0, result.size() - 1);
}

// Converts a method representation to its final profile format.
static std::string MethodToProfileFormat(
    const std::string& method,
    const FlattenProfileData::ItemMetadata& metadata,
    bool output_package_use) {
  std::string flags_string;
  if (metadata.HasFlagSet(Hotness::kFlagHot)) {
    flags_string += kMethodFlagStringHot;
  }
  if (metadata.HasFlagSet(Hotness::kFlagStartup)) {
    flags_string += kMethodFlagStringStartup;
  }
  if (metadata.HasFlagSet(Hotness::kFlagPostStartup)) {
    flags_string += kMethodFlagStringPostStartup;
  }
  std::string extra;
  if (output_package_use) {
    extra = kPackageUseDelim + GetPackageUseString(metadata);
  }

  std::string inline_cache_string = GetInlineCacheLine(metadata.GetInlineCache());
  return flags_string + method + extra + inline_cache_string;
}

// Converts a class representation to its final profile or preloaded classes format.
static std::string ClassToProfileFormat(
    const std::string& classString,
    const FlattenProfileData::ItemMetadata& metadata,
    bool output_package_use) {
  std::string extra;
  if (output_package_use) {
    extra = kPackageUseDelim + GetPackageUseString(metadata);
  }

  return classString + extra;
}

// Tries to asses if the given type reference is a clean class.
static bool MaybeIsClassClean(const TypeReference& ref) {
  const dex::ClassDef* class_def = ref.dex_file->FindClassDef(ref.TypeIndex());
  if (class_def == nullptr) {
    return false;
  }

  ClassAccessor accessor(*ref.dex_file, *class_def);
  for (auto& it : accessor.GetStaticFields()) {
    if (!it.IsFinal()) {
      // Not final static field will probably dirty the class.
      return false;
    }
  }
  for (auto& it : accessor.GetMethods()) {
    uint32_t flags = it.GetAccessFlags();
    if ((flags & kAccNative) != 0) {
      // Native method will get dirtied.
      return false;
    }
    if ((flags & kAccConstructor) != 0 && (flags & kAccStatic) != 0) {
      // Class initializer, may get dirtied (not sure).
      return false;
    }
  }

  return true;
}

// Returns true iff the item should be included in the profile.
// (i.e. it passes the given aggregation thresholds)
static bool IncludeItemInProfile(uint32_t max_aggregation_count,
                                 uint32_t item_threshold,
                                 const FlattenProfileData::ItemMetadata& metadata,
                                 const BootImageOptions& options) {
  CHECK_NE(max_aggregation_count, 0u);
  float item_percent = metadata.GetAnnotations().size() / static_cast<float>(max_aggregation_count);
  for (const auto& annotIt : metadata.GetAnnotations()) {
    const auto&thresholdIt =
        options.special_packages_thresholds.find(annotIt.GetOriginPackageName());
    if (thresholdIt != options.special_packages_thresholds.end()) {
      if (item_percent >= (thresholdIt->second / 100.f)) {
        return true;
      }
    }
  }
  return item_percent >= (item_threshold / 100.f);
}

// Returns true iff a method with the given metada should be included in the profile.
static bool IncludeMethodInProfile(uint32_t max_aggregation_count,
                                   const FlattenProfileData::ItemMetadata& metadata,
                                   const BootImageOptions& options) {
  return IncludeItemInProfile(max_aggregation_count, options.method_threshold, metadata, options);
}

// Returns true iff a class with the given metada should be included in the profile.
static bool IncludeClassInProfile(const TypeReference& type_ref,
                                  uint32_t max_aggregation_count,
                                  const FlattenProfileData::ItemMetadata& metadata,
                                  const BootImageOptions& options) {
  uint32_t threshold = MaybeIsClassClean(type_ref)
      ? options.image_class_clean_threshold
      : options.image_class_threshold;
  return IncludeItemInProfile(max_aggregation_count, threshold, metadata, options);
}

// Returns true iff a class with the given metada should be included in the list of
// prelaoded classes.
static bool IncludeInPreloadedClasses(const std::string& class_name,
                                      uint32_t max_aggregation_count,
                                      const FlattenProfileData::ItemMetadata& metadata,
                                      const BootImageOptions& options) {
  bool denylisted = options.preloaded_classes_denylist.find(class_name) !=
      options.preloaded_classes_denylist.end();
  return !denylisted && IncludeItemInProfile(
      max_aggregation_count, options.preloaded_class_threshold, metadata, options);
}

bool GenerateBootImageProfile(
    const std::vector<std::unique_ptr<const DexFile>>& dex_files,
    const std::vector<std::string>& profile_files,
    const BootImageOptions& options,
    const std::string& boot_profile_out_path,
    const std::string& preloaded_classes_out_path) {
  if (boot_profile_out_path.empty()) {
    LOG(ERROR) << "No output file specified";
    return false;
  }

  bool generate_preloaded_classes = !preloaded_classes_out_path.empty();

  std::unique_ptr<FlattenProfileData> flattend_data(new FlattenProfileData());
  for (const std::string& profile_file : profile_files) {
    ProfileCompilationInfo profile(/*for_boot_image=*/ true);
    if (!profile.Load(profile_file, /*clear_if_invalid=*/ false)) {
      LOG(ERROR) << "Profile is not a valid: " << profile_file;
      return false;
    }
    std::unique_ptr<FlattenProfileData> currentData = profile.ExtractProfileData(dex_files);
    flattend_data->MergeData(*currentData);
  }

  // We want the output sorted by the method/class name.
  // So we use an intermediate map for that.
  // There's no attempt to optimize this as it's not part of any critical path,
  // and mostly executed on hosts.
  SafeMap<std::string, FlattenProfileData::ItemMetadata> profile_methods;
  SafeMap<std::string, FlattenProfileData::ItemMetadata> profile_classes;
  SafeMap<std::string, FlattenProfileData::ItemMetadata> preloaded_classes;

  for (const auto& it : flattend_data->GetMethodData()) {
    if (IncludeMethodInProfile(flattend_data->GetMaxAggregationForMethods(), it.second, options)) {
      FlattenProfileData::ItemMetadata metadata(it.second);
      if (options.upgrade_startup_to_hot
          && ((metadata.GetFlags() & Hotness::Flag::kFlagStartup) != 0)) {
        metadata.AddFlag(Hotness::Flag::kFlagHot);
      }
      profile_methods.Put(BootImageRepresentation(it.first), metadata);
    }
  }

  for (const auto& it : flattend_data->GetClassData()) {
    const TypeReference& type_ref = it.first;
    const FlattenProfileData::ItemMetadata& metadata = it.second;
    if (IncludeClassInProfile(type_ref,
            flattend_data->GetMaxAggregationForClasses(),
            metadata,
            options)) {
      profile_classes.Put(BootImageRepresentation(it.first), it.second);
    }
    std::string preloaded_class_representation = PreloadedClassesRepresentation(it.first);
    if (generate_preloaded_classes && IncludeInPreloadedClasses(
            preloaded_class_representation,
            flattend_data->GetMaxAggregationForClasses(),
            metadata,
            options)) {
      preloaded_classes.Put(preloaded_class_representation, it.second);
    }
  }

  // Create the output content
  std::string profile_content;
  std::string preloaded_content;
  for (const auto& it : profile_classes) {
    profile_content += ClassToProfileFormat(it.first, it.second, options.append_package_use_list)
        + "\n";
  }
  for (const auto& it : profile_methods) {
    profile_content += MethodToProfileFormat(it.first, it.second, options.append_package_use_list)
        + "\n";
  }

  if (generate_preloaded_classes) {
    for (const auto& it : preloaded_classes) {
      preloaded_content +=
          ClassToProfileFormat(it.first, it.second, options.append_package_use_list) + "\n";
    }
  }

  return android::base::WriteStringToFile(profile_content, boot_profile_out_path)
      && (!generate_preloaded_classes
          || android::base::WriteStringToFile(preloaded_content, preloaded_classes_out_path));
}

}  // namespace art

Messung V0.5 in Prozent
C=91 H=92 G=91

¤ Dauer der Verarbeitung: 0.9 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.