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, ...@@ -1807,6 +1807,8 @@ Handle<Code> Factory::NewCode(const CodeDesc& desc,
// through the self_reference parameter. // through the self_reference parameter.
code->CopyFrom(desc); code->CopyFrom(desc);
code->clear_padding();
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
if (FLAG_verify_heap) code->ObjectVerify(); if (FLAG_verify_heap) code->ObjectVerify();
#endif #endif
...@@ -2563,6 +2565,8 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo( ...@@ -2563,6 +2565,8 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
share->set_preparsed_scope_data(*null_value()); share->set_preparsed_scope_data(*null_value());
share->clear_padding();
// Link into the list. // Link into the list.
Handle<Object> new_noscript_list = Handle<Object> new_noscript_list =
WeakFixedArray::Add(noscript_shared_function_infos(), share); WeakFixedArray::Add(noscript_shared_function_infos(), share);
......
...@@ -3263,6 +3263,7 @@ AllocationResult Heap::AllocateByteArray(int length, PretenureFlag pretenure) { ...@@ -3263,6 +3263,7 @@ AllocationResult Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
result->set_map_after_allocation(byte_array_map(), SKIP_WRITE_BARRIER); result->set_map_after_allocation(byte_array_map(), SKIP_WRITE_BARRIER);
ByteArray::cast(result)->set_length(length); ByteArray::cast(result)->set_length(length);
ByteArray::cast(result)->clear_padding();
return result; return result;
} }
...@@ -3297,6 +3298,7 @@ AllocationResult Heap::AllocateBytecodeArray(int length, ...@@ -3297,6 +3298,7 @@ AllocationResult Heap::AllocateBytecodeArray(int length,
instance->set_handler_table(empty_fixed_array()); instance->set_handler_table(empty_fixed_array());
instance->set_source_position_table(empty_byte_array()); instance->set_source_position_table(empty_byte_array());
CopyBytes(instance->GetFirstBytecodeAddress(), raw_bytecodes, length); CopyBytes(instance->GetFirstBytecodeAddress(), raw_bytecodes, length);
instance->clear_padding();
return result; return result;
} }
......
...@@ -2774,6 +2774,11 @@ void ByteArray::set_uint32(int index, uint32_t value) { ...@@ -2774,6 +2774,11 @@ void ByteArray::set_uint32(int index, uint32_t value) {
WRITE_UINT32_FIELD(this, kHeaderSize + index * kUInt32Size, 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) { ByteArray* ByteArray::FromDataStartAddress(Address address) {
DCHECK_TAG_ALIGNED(address); DCHECK_TAG_ALIGNED(address);
return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag); return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
...@@ -2867,6 +2872,11 @@ ACCESSORS(BytecodeArray, handler_table, FixedArray, kHandlerTableOffset) ...@@ -2867,6 +2872,11 @@ ACCESSORS(BytecodeArray, handler_table, FixedArray, kHandlerTableOffset)
ACCESSORS(BytecodeArray, source_position_table, Object, ACCESSORS(BytecodeArray, source_position_table, Object,
kSourcePositionTableOffset) kSourcePositionTableOffset)
void BytecodeArray::clear_padding() {
int data_size = kHeaderSize + length();
memset(address() + data_size, 0, SizeFor(length()) - data_size);
}
Address BytecodeArray::GetFirstBytecodeAddress() { Address BytecodeArray::GetFirstBytecodeAddress() {
return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize; return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
} }
...@@ -4962,6 +4972,13 @@ void Code::WipeOutHeader() { ...@@ -4962,6 +4972,13 @@ void Code::WipeOutHeader() {
WRITE_FIELD(this, kNextCodeLinkOffset, nullptr); 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 { Object* Code::type_feedback_info() const {
DCHECK(kind() == FUNCTION); DCHECK(kind() == FUNCTION);
return raw_type_feedback_info(); return raw_type_feedback_info();
......
...@@ -12038,6 +12038,15 @@ Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) { ...@@ -12038,6 +12038,15 @@ Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
return string; 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) { uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
// For array indexes mix the length into the hash as an array index could // For array indexes mix the length into the hash as an array index could
......
...@@ -3194,6 +3194,10 @@ class ByteArray: public FixedArrayBase { ...@@ -3194,6 +3194,10 @@ class ByteArray: public FixedArrayBase {
inline uint32_t get_uint32(int index) const; inline uint32_t get_uint32(int index) const;
inline void set_uint32(int index, uint32_t value); 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) { static int SizeFor(int length) {
return OBJECT_POINTER_ALIGN(kHeaderSize + length); return OBJECT_POINTER_ALIGN(kHeaderSize + length);
} }
...@@ -3350,6 +3354,10 @@ class BytecodeArray : public FixedArrayBase { ...@@ -3350,6 +3354,10 @@ class BytecodeArray : public FixedArrayBase {
bool IsOld() const; bool IsOld() const;
void MakeOlder(); void MakeOlder();
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
inline void clear_padding();
// Layout description. // Layout description.
static const int kConstantPoolOffset = FixedArrayBase::kHeaderSize; static const int kConstantPoolOffset = FixedArrayBase::kHeaderSize;
static const int kHandlerTableOffset = kConstantPoolOffset + kPointerSize; static const int kHandlerTableOffset = kConstantPoolOffset + kPointerSize;
...@@ -3898,6 +3906,10 @@ class Code: public HeapObject { ...@@ -3898,6 +3906,10 @@ class Code: public HeapObject {
// out the to-be-overwritten header data for reproducible snapshots. // out the to-be-overwritten header data for reproducible snapshots.
inline void WipeOutHeader(); inline void WipeOutHeader();
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
inline void clear_padding();
// Flags operations. // Flags operations.
static inline Flags ComputeFlags( static inline Flags ComputeFlags(
Kind kind, ExtraICState extra_ic_state = kNoExtraICState); Kind kind, ExtraICState extra_ic_state = kNoExtraICState);
......
...@@ -165,6 +165,10 @@ void SharedFunctionInfo::set_function_map_index(int index) { ...@@ -165,6 +165,10 @@ void SharedFunctionInfo::set_function_map_index(int index) {
set_compiler_hints(FunctionMapIndexBits::update(compiler_hints(), index)); set_compiler_hints(FunctionMapIndexBits::update(compiler_hints(), index));
} }
void SharedFunctionInfo::clear_padding() {
memset(this->address() + kSize, 0, kAlignedSize - kSize);
}
void SharedFunctionInfo::UpdateFunctionMapIndex() { void SharedFunctionInfo::UpdateFunctionMapIndex() {
int map_index = Context::FunctionMapIndex( int map_index = Context::FunctionMapIndex(
language_mode(), kind(), has_shared_name(), needs_home_object()); language_mode(), kind(), has_shared_name(), needs_home_object());
......
...@@ -315,6 +315,10 @@ class SharedFunctionInfo : public HeapObject { ...@@ -315,6 +315,10 @@ class SharedFunctionInfo : public HeapObject {
// this shared function info. // this shared function info.
DECL_INT_ACCESSORS(function_map_index) 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. // Recalculates the |map_index| value after modifications of this shared info.
inline void UpdateFunctionMapIndex(); inline void UpdateFunctionMapIndex();
......
...@@ -496,6 +496,10 @@ class SeqOneByteString : public SeqString { ...@@ -496,6 +496,10 @@ class SeqOneByteString : public SeqString {
inline uint8_t* GetChars(); inline uint8_t* GetChars();
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
void clear_padding();
DECL_CAST(SeqOneByteString) DECL_CAST(SeqOneByteString)
// Garbage collection support. This method is called by the // Garbage collection support. This method is called by the
...@@ -535,6 +539,10 @@ class SeqTwoByteString : public SeqString { ...@@ -535,6 +539,10 @@ class SeqTwoByteString : public SeqString {
inline uc16* GetChars(); inline uc16* GetChars();
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
void clear_padding();
// For regexp code. // For regexp code.
const uint16_t* SeqTwoByteStringGetData(unsigned start); const uint16_t* SeqTwoByteStringGetData(unsigned start);
......
...@@ -35,10 +35,6 @@ class SnapshotWriter { ...@@ -35,10 +35,6 @@ class SnapshotWriter {
// we end up with a corrupted snapshot file. The build step would succeed, // 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 // but the build target is unusable. Ideally we would write out temporary
// files and only move them to the final destination as last step. // 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( i::Vector<const i::byte> blob_vector(
reinterpret_cast<const i::byte*>(blob.data), blob.raw_size); reinterpret_cast<const i::byte*>(blob.data), blob.raw_size);
MaybeWriteSnapshotFile(blob_vector); MaybeWriteSnapshotFile(blob_vector);
......
...@@ -528,6 +528,12 @@ void Serializer::ObjectSerializer::Serialize() { ...@@ -528,6 +528,12 @@ void Serializer::ObjectSerializer::Serialize() {
if (object_->IsExternalString()) { if (object_->IsExternalString()) {
SerializeExternalString(); SerializeExternalString();
return; 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. // We cannot serialize typed array objects correctly.
...@@ -788,6 +794,10 @@ int Serializer::ObjectSerializer::OutputRawData( ...@@ -788,6 +794,10 @@ int Serializer::ObjectSerializer::OutputRawData(
if (is_code_object) object_start = PrepareCode(); if (is_code_object) object_start = PrepareCode();
const char* description = is_code_object ? "Code" : "Byte"; 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); sink_->PutRaw(object_start + base, bytes_to_output, description);
} }
if (to_skip != 0 && return_skip == kIgnoringReturn) { 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