Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a034c2a authored by Calin Juravle's avatar Calin Juravle Committed by Android (Google) Code Review
Browse files

Merge "Add profile guided compilation hooks in installd"

parents eecb2d20 60a794dc
Loading
Loading
Loading
Loading
+149 −12
Original line number Diff line number Diff line
@@ -600,7 +600,8 @@ static bool check_boolean_property(const char* property_name, bool default_value

static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
    const char* output_file_name, int swap_fd, const char *instruction_set,
    bool vm_safe_mode, bool debuggable, bool post_bootcomplete, bool use_jit)
    bool vm_safe_mode, bool debuggable, bool post_bootcomplete, bool use_jit,
    const std::vector<int>& profile_files_fd, const std::vector<int>& reference_profile_files_fd)
{
    static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;

@@ -610,6 +611,12 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
        return;
    }

    if (profile_files_fd.size() != reference_profile_files_fd.size()) {
        ALOGE("Invalid configuration of profile files: pf_size (%zu) != rpf_size (%zu)",
              profile_files_fd.size(), reference_profile_files_fd.size());
        return;
    }

    char dex2oat_Xms_flag[kPropertyValueMax];
    bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;

@@ -720,6 +727,17 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
                (get_property("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
                (prop_buf[0] == '1');
    }
    std::vector<std::string> profile_file_args(profile_files_fd.size());
    std::vector<std::string> reference_profile_file_args(profile_files_fd.size());
    // "reference-profile-file-fd" is longer than "profile-file-fd" so we can
    // use it to set the max length.
    char profile_buf[strlen("--reference-profile-file-fd=") + MAX_INT_LEN];
    for (size_t k = 0; k < profile_files_fd.size(); k++) {
        sprintf(profile_buf, "--profile-file-fd=%d", profile_files_fd[k]);
        profile_file_args[k].assign(profile_buf);
        sprintf(profile_buf, "--reference-profile-file-fd=%d", reference_profile_files_fd[k]);
        reference_profile_file_args[k].assign(profile_buf);
    }

    ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);

@@ -734,7 +752,9 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
                     + (have_dex2oat_relocation_skip_flag ? 2 : 0)
                     + (generate_debug_info ? 1 : 0)
                     + (debuggable ? 1 : 0)
                     + dex2oat_flags_count];
                     + dex2oat_flags_count
                     + profile_files_fd.size()
                     + reference_profile_files_fd.size()];
    int i = 0;
    argv[i++] = DEX2OAT_BIN;
    argv[i++] = zip_fd_arg;
@@ -778,6 +798,10 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
        argv[i++] = RUNTIME_ARG;
        argv[i++] = dex2oat_norelocation;
    }
    for (size_t k = 0; k < profile_file_args.size(); k++) {
        argv[i++] = profile_file_args[k].c_str();
        argv[i++] = reference_profile_file_args[k].c_str();
    }
    // Do not add after dex2oat_flags, they should override others for debugging.
    argv[i] = NULL;

@@ -844,8 +868,108 @@ static void SetDex2OatAndPatchOatScheduling(bool set_to_bg) {
    }
}

constexpr const char* PROFILE_FILE_EXTENSION = ".prof";
constexpr const char* REFERENCE_PROFILE_FILE_EXTENSION = ".prof.ref";

static void close_all_fds(const std::vector<int>& fds, const char* description) {
    for (size_t i = 0; i < fds.size(); i++) {
        if (close(fds[i]) != 0) {
            PLOG(WARNING) << "Failed to close fd for " << description << " at index " << i;
        }
    }
}

static int open_code_cache_for_user(userid_t user, const char* volume_uuid, const char* pkgname) {
    std::string code_cache_path =
        create_data_user_package_path(volume_uuid, user, pkgname) + CODE_CACHE_DIR_POSTFIX;

    struct stat buffer;
    // Check that the code cache exists. If not, return and don't log an error.
    if (TEMP_FAILURE_RETRY(lstat(code_cache_path.c_str(), &buffer)) == -1) {
        if (errno != ENOENT) {
            PLOG(ERROR) << "Failed to lstat code_cache: " << code_cache_path;
            return -1;
        }
    }

    int code_cache_fd = open(code_cache_path.c_str(),
            O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW);
    if (code_cache_fd < 0) {
        PLOG(ERROR) << "Failed to open code_cache: " << code_cache_path;
    }
    return code_cache_fd;
}

// Keep profile paths in sync with ActivityThread.
static void open_profile_files_for_user(uid_t uid, const char* pkgname, int code_cache_fd,
            /*out*/ int* profile_fd, /*out*/ int* reference_profile_fd) {
    *profile_fd = -1;
    *reference_profile_fd = -1;
    std::string profile_file(pkgname);
    profile_file += PROFILE_FILE_EXTENSION;

    // Check if the profile exists. If not, early return and don't log an error.
    struct stat buffer;
    if (TEMP_FAILURE_RETRY(fstatat(
            code_cache_fd, profile_file.c_str(), &buffer, AT_SYMLINK_NOFOLLOW)) == -1) {
        if (errno != ENOENT) {
            PLOG(ERROR) << "Failed to fstatat profile file: " << profile_file;
            return;
        }
    }

    // Open in read-write to allow transfer of information from the current profile
    // to the reference profile.
    *profile_fd = openat(code_cache_fd, profile_file.c_str(), O_RDWR | O_NOFOLLOW);
    if (*profile_fd < 0) {
        PLOG(ERROR) << "Failed to open profile file: " << profile_file;
        return;
    }

    std::string reference_profile(pkgname);
    reference_profile += REFERENCE_PROFILE_FILE_EXTENSION;
    // Give read-write permissions just for the user (changed with fchown after opening).
    // We need write permission because dex2oat will update the reference profile files
    // with the content of the corresponding current profile files.
    *reference_profile_fd = openat(code_cache_fd, reference_profile.c_str(),
            O_CREAT | O_RDWR | O_NOFOLLOW, S_IWUSR | S_IRUSR);
    if (*reference_profile_fd < 0) {
        close(*profile_fd);
        return;
    }
    if (fchown(*reference_profile_fd, uid, uid) < 0) {
        PLOG(ERROR) << "Cannot change reference profile file owner: " << reference_profile;
        close(*profile_fd);
        *profile_fd = -1;
        *reference_profile_fd = -1;
    }
}

static void open_profile_files(const char* volume_uuid, uid_t uid, const char* pkgname,
            std::vector<int>* profile_fds, std::vector<int>* reference_profile_fds) {
    std::vector<userid_t> users = get_known_users(volume_uuid);
    for (auto user : users) {
        int code_cache_fd  = open_code_cache_for_user(user, volume_uuid, pkgname);
        if (code_cache_fd < 0) {
            continue;
        }
        int profile_fd = -1;
        int reference_profile_fd = -1;
        open_profile_files_for_user(
            uid, pkgname, code_cache_fd, &profile_fd, &reference_profile_fd);
        close(code_cache_fd);

        // Add to the lists only if both fds are valid.
        if ((profile_fd >= 0) && (reference_profile_fd >= 0)) {
            profile_fds->push_back(profile_fd);
            reference_profile_fds->push_back(reference_profile_fd);
        }
    }
}

int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* instruction_set,
           int dexopt_needed, const char* oat_dir, int dexopt_flags)
           int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* volume_uuid,
           bool use_profiles)
{
    struct utimbuf ut;
    struct stat input_stat;
@@ -859,6 +983,16 @@ int dexopt(const char *apk_path, uid_t uid, const char *pkgname, const char *ins
    bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
    bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
    bool use_jit = (dexopt_flags & DEXOPT_USEJIT) != 0;
    std::vector<int> profile_files_fd;
    std::vector<int> reference_profile_files_fd;
    if (use_profiles) {
        open_profile_files(volume_uuid, uid, pkgname,
                &profile_files_fd, &reference_profile_files_fd);
        if (profile_files_fd.empty()) {
            // Skip profile guided compilation because no profiles were found.
            return 0;
        }
    }

    if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
        LOG_FATAL("dexopt flags contains unknown fields\n");
@@ -990,14 +1124,9 @@ int dexopt(const char *apk_path, uid_t uid, const char *pkgname, const char *ins
            || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
            run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
        } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) {
            const char *input_file_name = strrchr(input_file, '/');
            if (input_file_name == NULL) {
                input_file_name = input_file;
            } else {
                input_file_name++;
            }
            run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd,
                        instruction_set, vm_safe_mode, debuggable, boot_complete, use_jit);
            run_dex2oat(input_fd, out_fd, input_file, out_path, swap_fd,
                        instruction_set, vm_safe_mode, debuggable, boot_complete, use_jit,
                        profile_files_fd, reference_profile_files_fd);
        } else {
            ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
            exit(73);
@@ -1022,6 +1151,10 @@ int dexopt(const char *apk_path, uid_t uid, const char *pkgname, const char *ins
    if (swap_fd != -1) {
        close(swap_fd);
    }
    if (use_profiles != 0) {
        close_all_fds(profile_files_fd, "profile_files_fd");
        close_all_fds(reference_profile_files_fd, "reference_profile_files_fd");
    }
    return 0;

fail:
@@ -1032,6 +1165,10 @@ fail:
    if (input_fd >= 0) {
        close(input_fd);
    }
    if (use_profiles != 0) {
        close_all_fds(profile_files_fd, "profile_files_fd");
        close_all_fds(reference_profile_files_fd, "reference_profile_files_fd");
    }
    return -1;
}

+2 −1
Original line number Diff line number Diff line
@@ -48,7 +48,8 @@ int delete_user(const char *uuid, userid_t userid);
int rm_dex(const char *path, const char *instruction_set);
int free_cache(const char *uuid, int64_t free_size);
int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
           int dexopt_needed, const char* oat_dir, int dexopt_flags);
           int dexopt_needed, const char* oat_dir, int dexopt_flags,
           const char* volume_uuid, bool use_profiles);
int mark_boot_complete(const char *instruction_set);
int movefiles();
int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
+4 −3
Original line number Diff line number Diff line
@@ -213,9 +213,10 @@ static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSE

static int do_dexopt(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
    /* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags */
    /* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags, volume_uuid,
            use_profiles */
    return dexopt(arg[0], atoi(arg[1]), arg[2], arg[3], atoi(arg[4]),
                  arg[5], atoi(arg[6]));
                  arg[5], atoi(arg[6]), parse_null(arg[7]), (atoi(arg[8]) == 0 ? false : true));
}

static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
@@ -322,7 +323,7 @@ struct cmdinfo cmds[] = {
    { "move_complete_app",    7, do_move_complete_app },
    { "get_app_size",         9, do_get_app_size },

    { "dexopt",               7, do_dexopt },
    { "dexopt",               9, do_dexopt },
    { "markbootcomplete",     1, do_mark_boot_complete },
    { "rmdex",                2, do_rm_dex },
    { "freecache",            2, do_free_cache },