Commit f8947063 authored by jgruber's avatar jgruber Committed by Commit Bot

[snapshot] Flush icache and allocate with code alignment

This fixes two issues related to Code object allocation: Code objects
need to be aligned to kCodeAlignment (= 32), and the instruction cache
needs to be flushed after deserialization.

Both bugs combined manifested as a crash at a basically arbitrary point
in the code after the Runtime::kDeserializeLazy call:

0x286bc8dc:  blx     r12     // Call to Runtime::kDeserializeLazy,
                             // generated through
                             // GenerateTailCallToReturnedCode.
0x286bc8e0:  mov     r2, r0  // This seemingly innocent register move
                             // crashes hard.

Bug: v8:6624,v8:6796
Change-Id: I88c7eaf57ac851745fb7e800c92b0f5978b33466
Reviewed-on: https://chromium-review.googlesource.com/660119Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47947}
parent 07f93aff
......@@ -1807,6 +1807,10 @@ Handle<Code> Factory::NewCode(const CodeDesc& desc, Code::Flags flags,
return code;
}
Handle<Code> Factory::NewCodeForDeserialization(uint32_t size) {
const bool kNotImmovable = false;
return NewCodeRaw(size, kNotImmovable);
}
Handle<Code> Factory::CopyCode(Handle<Code> code) {
CALL_HEAP_FUNCTION(isolate(),
......
......@@ -659,6 +659,10 @@ class V8_EXPORT_PRIVATE Factory final {
Handle<Code> NewCode(const CodeDesc& desc, Code::Flags flags,
Handle<Object> self_reference, bool immovable = false);
// Allocates a new, empty code object for use by builtin deserialization. The
// given {size} argument specifies the size of the entire code object.
Handle<Code> NewCodeForDeserialization(uint32_t size);
Handle<Code> CopyCode(Handle<Code> code);
Handle<BytecodeArray> CopyBytecodeArray(Handle<BytecodeArray>);
......@@ -820,7 +824,7 @@ class V8_EXPORT_PRIVATE Factory final {
PretenureFlag pretenure);
// Creates a code object that is not yet fully initialized yet.
inline Handle<Code> NewCodeRaw(int object_size, bool immovable);
Handle<Code> NewCodeRaw(int object_size, bool immovable);
// Attempt to find the number in a small cache. If we finds it, return
// the string representation of the number. Otherwise return undefined.
......
......@@ -4,6 +4,7 @@
#include "src/snapshot/builtin-deserializer.h"
#include "src/assembler-inl.h"
#include "src/objects-inl.h"
#include "src/snapshot/snapshot.h"
......@@ -85,7 +86,12 @@ Code* BuiltinDeserializer::DeserializeBuiltin(int builtin_id) {
// Rewind.
source()->set_position(initial_position);
return Code::cast(o);
// Flush the instruction cache.
Code* code = Code::cast(o);
Assembler::FlushICache(isolate(), code->instruction_start(),
code->instruction_size());
return code;
}
void BuiltinDeserializer::SetPositionToBuiltin(int builtin_id) {
......@@ -213,7 +219,7 @@ void BuiltinDeserializer::ReserveAndInitializeBuiltinsTableForBuiltin(
DCHECK_LE(builtin_size, MemoryAllocator::PageAreaSize(CODE_SPACE));
Handle<HeapObject> o =
isolate()->factory()->NewFillerObject(builtin_size, false, CODE_SPACE);
isolate()->factory()->NewCodeForDeserialization(builtin_size);
// Note: After this point and until deserialization finishes, heap allocation
// is disallowed. We currently can't safely assert this since we'd need to
......
......@@ -22,6 +22,9 @@ class BuiltinDeserializer final : public Deserializer {
// startup blob. In particular, we need to ensure that no GC can occur
// between startup- and builtins deserialization, as all builtins have been
// pre-allocated and their pointers may not be invalidated.
//
// After this, the instruction cache must be flushed by the caller (we don't
// do it ourselves since the startup serializer batch-flushes all code pages).
void DeserializeEagerBuiltins();
// Deserializes the single given builtin. Assumes that reservations have
......
......@@ -40,11 +40,15 @@ void StartupDeserializer::DeserializeInto(Isolate* isolate) {
isolate->heap()->RepairFreeListsAfterDeserialization();
isolate->heap()->IterateWeakRoots(this, VISIT_ALL);
DeserializeDeferredObjects();
FlushICacheForNewIsolate();
RestoreExternalReferenceRedirectors(accessor_infos());
// Deserialize eager builtins from the builtin snapshot.
// Deserialize eager builtins from the builtin snapshot. Note that deferred
// objects must have been deserialized prior to this.
builtin_deserializer.DeserializeEagerBuiltins();
// Flush the instruction cache for the entire code-space. Must happen after
// builtins deserialization.
FlushICacheForNewIsolate();
}
isolate->heap()->set_native_contexts_list(isolate->heap()->undefined_value());
......
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