Commit c924a942 authored by Yang Guo's avatar Yang Guo Committed by Commit Bot

[snapshot] initialize padding space.

This is to ensure the snapshot is deterministic.


R=mstarzinger@chromium.org

Bug: v8:4886, v8:3645
Change-Id: I79c8e54ba6b4810f005bc1ece61890790c815cea
Reviewed-on: https://chromium-review.googlesource.com/595740
Commit-Queue: Yang Guo <yangguo@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47082}
parent 062bb7d4
......@@ -1807,6 +1807,8 @@ Handle<Code> Factory::NewCode(const CodeDesc& desc,
// through the self_reference parameter.
code->CopyFrom(desc);
code->clear_padding();
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) code->ObjectVerify();
#endif
......@@ -2563,6 +2565,8 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
share->set_preparsed_scope_data(*null_value());
share->clear_padding();
// Link into the list.
Handle<Object> new_noscript_list =
WeakFixedArray::Add(noscript_shared_function_infos(), share);
......
......@@ -3263,6 +3263,7 @@ AllocationResult Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
result->set_map_after_allocation(byte_array_map(), SKIP_WRITE_BARRIER);
ByteArray::cast(result)->set_length(length);
ByteArray::cast(result)->clear_padding();
return result;
}
......@@ -3297,6 +3298,7 @@ AllocationResult Heap::AllocateBytecodeArray(int length,
instance->set_handler_table(empty_fixed_array());
instance->set_source_position_table(empty_byte_array());
CopyBytes(instance->GetFirstBytecodeAddress(), raw_bytecodes, length);
instance->clear_padding();
return result;
}
......
......@@ -2774,6 +2774,11 @@ void ByteArray::set_uint32(int index, uint32_t value) {
WRITE_UINT32_FIELD(this, kHeaderSize + index * kUInt32Size, value);
}
void ByteArray::clear_padding() {
int data_size = length() + kHeaderSize;
memset(address() + data_size, 0, Size() - data_size);
}
ByteArray* ByteArray::FromDataStartAddress(Address address) {
DCHECK_TAG_ALIGNED(address);
return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
......@@ -2867,6 +2872,11 @@ ACCESSORS(BytecodeArray, handler_table, FixedArray, kHandlerTableOffset)
ACCESSORS(BytecodeArray, source_position_table, Object,
kSourcePositionTableOffset)
void BytecodeArray::clear_padding() {
int data_size = kHeaderSize + length();
memset(address() + data_size, 0, SizeFor(length()) - data_size);
}
Address BytecodeArray::GetFirstBytecodeAddress() {
return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
}
......@@ -4962,6 +4972,13 @@ void Code::WipeOutHeader() {
WRITE_FIELD(this, kNextCodeLinkOffset, nullptr);
}
void Code::clear_padding() {
memset(address() + kHeaderPaddingStart, 0, kHeaderSize - kHeaderPaddingStart);
Address data_end =
has_unwinding_info() ? unwinding_info_end() : instruction_end();
memset(data_end, 0, CodeSize() - (data_end - address()));
}
Object* Code::type_feedback_info() const {
DCHECK(kind() == FUNCTION);
return raw_type_feedback_info();
......
......@@ -12038,6 +12038,15 @@ Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
return string;
}
void SeqOneByteString::clear_padding() {
int data_size = SeqString::kHeaderSize + length() * kOneByteSize;
memset(address() + data_size, 0, SizeFor(length()) - data_size);
}
void SeqTwoByteString::clear_padding() {
int data_size = SeqString::kHeaderSize + length() * kUC16Size;
memset(address() + data_size, 0, SizeFor(length()) - data_size);
}
uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
// For array indexes mix the length into the hash as an array index could
......
......@@ -3194,6 +3194,10 @@ class ByteArray: public FixedArrayBase {
inline uint32_t get_uint32(int index) const;
inline void set_uint32(int index, uint32_t value);
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
inline void clear_padding();
static int SizeFor(int length) {
return OBJECT_POINTER_ALIGN(kHeaderSize + length);
}
......@@ -3350,6 +3354,10 @@ class BytecodeArray : public FixedArrayBase {
bool IsOld() const;
void MakeOlder();
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
inline void clear_padding();
// Layout description.
static const int kConstantPoolOffset = FixedArrayBase::kHeaderSize;
static const int kHandlerTableOffset = kConstantPoolOffset + kPointerSize;
......@@ -3898,6 +3906,10 @@ class Code: public HeapObject {
// out the to-be-overwritten header data for reproducible snapshots.
inline void WipeOutHeader();
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
inline void clear_padding();
// Flags operations.
static inline Flags ComputeFlags(
Kind kind, ExtraICState extra_ic_state = kNoExtraICState);
......
......@@ -165,6 +165,10 @@ void SharedFunctionInfo::set_function_map_index(int index) {
set_compiler_hints(FunctionMapIndexBits::update(compiler_hints(), index));
}
void SharedFunctionInfo::clear_padding() {
memset(this->address() + kSize, 0, kAlignedSize - kSize);
}
void SharedFunctionInfo::UpdateFunctionMapIndex() {
int map_index = Context::FunctionMapIndex(
language_mode(), kind(), has_shared_name(), needs_home_object());
......
......@@ -315,6 +315,10 @@ class SharedFunctionInfo : public HeapObject {
// this shared function info.
DECL_INT_ACCESSORS(function_map_index)
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
inline void clear_padding();
// Recalculates the |map_index| value after modifications of this shared info.
inline void UpdateFunctionMapIndex();
......
......@@ -496,6 +496,10 @@ class SeqOneByteString : public SeqString {
inline uint8_t* GetChars();
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
void clear_padding();
DECL_CAST(SeqOneByteString)
// Garbage collection support. This method is called by the
......@@ -535,6 +539,10 @@ class SeqTwoByteString : public SeqString {
inline uc16* GetChars();
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
void clear_padding();
// For regexp code.
const uint16_t* SeqTwoByteStringGetData(unsigned start);
......
......@@ -35,10 +35,6 @@ class SnapshotWriter {
// we end up with a corrupted snapshot file. The build step would succeed,
// but the build target is unusable. Ideally we would write out temporary
// files and only move them to the final destination as last step.
// Tell MSan to ignore uninitialized padding in the blob.
MSAN_MEMORY_IS_INITIALIZED(blob.data, blob.raw_size);
i::Vector<const i::byte> blob_vector(
reinterpret_cast<const i::byte*>(blob.data), blob.raw_size);
MaybeWriteSnapshotFile(blob_vector);
......
......@@ -528,6 +528,12 @@ void Serializer::ObjectSerializer::Serialize() {
if (object_->IsExternalString()) {
SerializeExternalString();
return;
} else if (object_->IsSeqOneByteString()) {
// Clear padding bytes at the end. Done here to avoid having to do this
// at allocation sites in generated code.
SeqOneByteString::cast(object_)->clear_padding();
} else if (object_->IsSeqTwoByteString()) {
SeqTwoByteString::cast(object_)->clear_padding();
}
// We cannot serialize typed array objects correctly.
......@@ -788,6 +794,10 @@ int Serializer::ObjectSerializer::OutputRawData(
if (is_code_object) object_start = PrepareCode();
const char* description = is_code_object ? "Code" : "Byte";
#ifdef MEMORY_SANITIZER
// Check that we do not serialize uninitialized memory.
__msan_check_mem_is_initialized(object_start + base, bytes_to_output);
#endif // MEMORY_SANITIZER
sink_->PutRaw(object_start + base, bytes_to_output, description);
}
if (to_skip != 0 && return_skip == kIgnoringReturn) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment