Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reuse ELF image from code_memory #2064

Closed

Conversation

yurydelendik
Copy link
Contributor

Optimization for #2020

Changes:

  • Places entire ELF image into code_memory
  • Use code_memory data as a source for wasm_module_serialize instead keeping pristine copy in memory
  • Use code_memory data as GDB JIT image
  • Sanitizes serialized image from current address information
  • Moves ELF patching logic into the wasmtime-obj crate, also refactored for adding other platforms.

Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I've left a few comments here and there, but I think I may be missing something as well? I can see the entire ELF image being copied into the code memory, but I'm having trouble figuring out the end goal ofthis PR. Is the intention that the Object isn't kept around which duplicates resident memory by having code twice? This isn't related to minimizing the number of copies, right?

(sorry I'm somewhat familiar with all these paths but not intimately familiar)

}

trait ElfObject {
fn e_ident(&self) -> &Ident;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like some of these reader methods are already on a predefined trait, could that be used instead?

(it looks like setters aren't found there though)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is the main reason for code duplication -- I can add a comment about setters.

@@ -400,11 +402,9 @@ fn build_code_memory(
),
String,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you're here, mind going ahead and changing this to an anyhow::Result to avoid using String as an error?


// Make all code compiled thus far executable.
// TODO publish only .text section of ELF object.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'll probably want to resolve this before landing

continue;
}
};
let body = unsafe { obj_data.as_ptr().add(body_offset) } as *const VMFunctionBody;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the unsafe be avoided here by reading the second data directly from the section from the iterator?

continue;
}
};
let body = unsafe { obj_data.as_ptr().add(body_offset) } as *const VMFunctionBody;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(similar comment about unsafety as above)

Additionally this look looks basically the same as the one above, so could that be factored out? Something like a function that applies all relocations and uses a closure to calculate the reloc value.

let mut file = match parse_elf_object_mut(bytes) {
Ok(file) => file,
Err(_) => {
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it's a bit of a scary error to omit, could we return an error here instead and use error messages to guide fixing this later?

unwind_info,
})
}

/// Extracts `CompilationArtifacts` from the compiled module.
pub fn to_compilation_artifacts(&self) -> CompilationArtifacts {
// Get ELF image bytes and sanitize that.
let mut obj = Vec::from(unsafe {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to not add unsafe here? Could the code bytes be read from a safe method?

std::slice::from_raw_parts(range.start as *const u8, range.len())
});
drop(unlink_module(&mut obj));
drop(sanitize_loadable_file(&mut obj));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come these errors are ignored?

@@ -202,11 +209,12 @@ impl CompiledModule {

// Register GDB JIT images; initialize profiler and load the wasm module.
let dbg_jit_registration = if debug_info {
let bytes = create_dbg_image(obj.to_vec(), code_range, &module, &finished_functions)?;
let bytes = unsafe { std::slice::from_raw_parts(image_range.0, image_range.1) };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the unsafety here be encapsulated in a safe method?

@yurydelendik
Copy link
Contributor Author

I can see the entire ELF image being copied into the code memory, but I'm having trouble figuring out the end goal ofthis PR. Is the intention that the Object isn't kept around which duplicates resident memory by having code twice? This isn't related to minimizing the number of copies, right?

The end goal not only remove copy operations but also reduce amount of data copies as well. Currently, we are keeping pristine ELF image copy along with code_memory, which only needed for Module::serialize (so almost never). This PR tries to remove this data from memory.

It is low priority for this optimization. Though it will probably be needed when we will emit ELF image directly into the code_memory.

@alexcrichton
Copy link
Member

Ah ok I see, so it's removing some duplicates we store next to each other. Ok that makes sense to me! I'd be happy landing this since it at least improves along those lines and will be needed for future refactorings anyway.

@alexcrichton
Copy link
Member

I'm going through some old PRs and this one's pretty old at this point. Enough points have changed that I don't think this is quite as applicable any more and I think much of this ended up getting landed in main anyway over time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants