author | Ted Campbell <tcampbell@mozilla.com> |
Tue, 28 Apr 2020 07:59:04 +0000 | |
changeset 526469 | 6158f69d21c7e5cdba5d2d6847aba2d4074fa7c1 |
parent 526468 | b73154f817cdcc7a9f88228abdbfccb4aff96139 |
child 526470 | 5d3704bf89d5abe274c7587afbacf59d92439723 |
push id | 37357 |
push user | opoprus@mozilla.com |
push date | Tue, 28 Apr 2020 21:47:47 +0000 |
treeherder | mozilla-central@a34695d9b99d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 1633425 |
milestone | 77.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/jit/Ion.cpp | file | annotate | diff | comparison | revisions | |
js/src/jit/IonCode.h | file | annotate | diff | comparison | revisions |
--- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -1,16 +1,17 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "jit/Ion.h" +#include "mozilla/CheckedInt.h" #include "mozilla/DebugOnly.h" #include "mozilla/IntegerPrintfMacros.h" #include "mozilla/MemoryReporting.h" #include "mozilla/ThreadLocal.h" #include "mozilla/Unused.h" #include "gc/FreeOp.h" #include "gc/Marking.h" @@ -605,96 +606,95 @@ IonScript* IonScript::New(JSContext* cx, uint32_t frameSlots, uint32_t argumentSlots, uint32_t frameSize, size_t snapshotsListSize, size_t snapshotsRVATableSize, size_t recoversSize, size_t bailoutEntries, size_t constants, size_t safepointIndices, size_t osiIndices, size_t icEntries, size_t runtimeSize, size_t safepointsSize, OptimizationLevel optimizationLevel) { - constexpr size_t DataAlignment = sizeof(void*); - if (snapshotsListSize >= MAX_BUFFER_SIZE || (bailoutEntries >= MAX_BUFFER_SIZE / sizeof(uint32_t))) { ReportOutOfMemory(cx); return nullptr; } - // This should not overflow on x86, because the memory is already allocated - // *somewhere* and if their total overflowed there would be no memory left - // at all. - size_t paddedSnapshotsSize = - AlignBytes(snapshotsListSize + snapshotsRVATableSize, DataAlignment); - size_t paddedRecoversSize = AlignBytes(recoversSize, DataAlignment); - size_t paddedBailoutSize = - AlignBytes(bailoutEntries * sizeof(uint32_t), DataAlignment); - size_t paddedConstantsSize = - AlignBytes(constants * sizeof(Value), DataAlignment); - size_t paddedSafepointIndicesSize = - AlignBytes(safepointIndices * sizeof(SafepointIndex), DataAlignment); - size_t paddedOsiIndicesSize = - AlignBytes(osiIndices * sizeof(OsiIndex), DataAlignment); - size_t paddedICEntriesSize = - AlignBytes(icEntries * sizeof(uint32_t), DataAlignment); - size_t paddedRuntimeSize = AlignBytes(runtimeSize, DataAlignment); - size_t paddedSafepointSize = AlignBytes(safepointsSize, DataAlignment); - - size_t bytes = paddedRuntimeSize + paddedICEntriesSize + - paddedSafepointIndicesSize + paddedSafepointSize + - paddedBailoutSize + paddedOsiIndicesSize + - paddedSnapshotsSize + paddedRecoversSize + paddedConstantsSize; - - IonScript* script = cx->pod_malloc_with_extra<IonScript, uint8_t>(bytes); - if (!script) { + CheckedInt<Offset> allocSize = sizeof(IonScript); + allocSize += CheckedInt<Offset>(constants) * sizeof(Value); + allocSize += CheckedInt<Offset>(runtimeSize); + allocSize += CheckedInt<Offset>(osiIndices) * sizeof(OsiIndex); + allocSize += CheckedInt<Offset>(safepointIndices) * sizeof(SafepointIndex); + allocSize += CheckedInt<Offset>(bailoutEntries) * sizeof(SnapshotOffset); + allocSize += CheckedInt<Offset>(icEntries) * sizeof(uint32_t); + allocSize += CheckedInt<Offset>(safepointsSize); + allocSize += CheckedInt<Offset>(snapshotsListSize); + allocSize += CheckedInt<Offset>(snapshotsRVATableSize); + allocSize += CheckedInt<Offset>(recoversSize); + + if (!allocSize.isValid()) { + ReportAllocationOverflow(cx); + return nullptr; + } + + void* raw = cx->pod_malloc<uint8_t>(allocSize.value()); + MOZ_ASSERT(uintptr_t(raw) % alignof(IonScript) == 0); + if (!raw) { return nullptr; } - new (script) IonScript(compilationId, frameSlots, argumentSlots, frameSize, - optimizationLevel); - - uint32_t offsetCursor = sizeof(IonScript); - + IonScript* script = new (raw) IonScript( + compilationId, frameSlots, argumentSlots, frameSize, optimizationLevel); + + Offset offsetCursor = sizeof(IonScript); + + MOZ_ASSERT(offsetCursor % alignof(Value) == 0); + script->constantTable_ = offsetCursor; + script->constantEntries_ = constants; + offsetCursor += constants * sizeof(Value); + + MOZ_ASSERT(offsetCursor % alignof(uint64_t) == 0); script->runtimeData_ = offsetCursor; script->runtimeSize_ = runtimeSize; - offsetCursor += paddedRuntimeSize; - + offsetCursor += runtimeSize; + + MOZ_ASSERT(offsetCursor % alignof(OsiIndex) == 0); + script->osiIndexOffset_ = offsetCursor; + script->osiIndexEntries_ = osiIndices; + offsetCursor += osiIndices * sizeof(OsiIndex); + + MOZ_ASSERT(offsetCursor % alignof(SafepointIndex) == 0); + script->safepointIndexOffset_ = offsetCursor; + script->safepointIndexEntries_ = safepointIndices; + offsetCursor += safepointIndices * sizeof(SafepointIndex); + + MOZ_ASSERT(offsetCursor % alignof(SnapshotOffset) == 0); + script->bailoutTable_ = offsetCursor; + script->bailoutEntries_ = bailoutEntries; + offsetCursor += bailoutEntries * sizeof(SnapshotOffset); + + MOZ_ASSERT(offsetCursor % alignof(uint32_t) == 0); script->icIndex_ = offsetCursor; script->icEntries_ = icEntries; - offsetCursor += paddedICEntriesSize; - - script->safepointIndexOffset_ = offsetCursor; - script->safepointIndexEntries_ = safepointIndices; - offsetCursor += paddedSafepointIndicesSize; + offsetCursor += icEntries * sizeof(uint32_t); script->safepointsStart_ = offsetCursor; script->safepointsSize_ = safepointsSize; - offsetCursor += paddedSafepointSize; - - script->bailoutTable_ = offsetCursor; - script->bailoutEntries_ = bailoutEntries; - offsetCursor += paddedBailoutSize; - - script->osiIndexOffset_ = offsetCursor; - script->osiIndexEntries_ = osiIndices; - offsetCursor += paddedOsiIndicesSize; + offsetCursor += safepointsSize; script->snapshots_ = offsetCursor; script->snapshotsListSize_ = snapshotsListSize; script->snapshotsRVATableSize_ = snapshotsRVATableSize; - offsetCursor += paddedSnapshotsSize; + offsetCursor += snapshotsListSize; + offsetCursor += snapshotsRVATableSize; script->recovers_ = offsetCursor; script->recoversSize_ = recoversSize; - offsetCursor += paddedRecoversSize; - - script->constantTable_ = offsetCursor; - script->constantEntries_ = constants; - offsetCursor += paddedConstantsSize; - - script->allocBytes_ = sizeof(IonScript) + bytes; - MOZ_ASSERT(offsetCursor == script->allocBytes_); + offsetCursor += recoversSize; + + script->allocBytes_ = offsetCursor; + MOZ_ASSERT(offsetCursor == allocSize.value()); return script; } void IonScript::trace(JSTracer* trc) { if (method_) { TraceEdge(trc, &method_, "method"); }
--- a/js/src/jit/IonCode.h +++ b/js/src/jit/IonCode.h @@ -12,16 +12,17 @@ #include "jstypes.h" #include "jit/ExecutableAllocator.h" #include "jit/ICStubSpace.h" #include "jit/IonOptimizationLevels.h" #include "jit/IonTypes.h" #include "js/UbiNode.h" +#include "util/TrailingArray.h" #include "vm/TraceLogging.h" namespace js { namespace jit { class IonBuilder; class JitAllocPolicy; class JitCode; @@ -146,18 +147,79 @@ class JitCode : public gc::TenuredCell { class SnapshotWriter; class RecoverWriter; class SafepointWriter; class CodegenSafepointIndex; class SafepointIndex; class OsiIndex; class IonIC; -// An IonScript attaches Ion-generated information to a JSScript. -struct IonScript { +// An IonScript attaches Ion-generated information to a JSScript. The header +// structure is followed by several arrays of data. These trailing arrays have a +// layout based on offsets (bytes from 'this') stored in the IonScript header. +// +// <IonScript itself> +// -- +// PreBarrieredValue[] constantTable() +// uint8_t[] runtimeData() +// OsiIndex[] osiIndex() +// SafepointIndex[] safepointIndex() +// SnapshotOffset[] bailoutTable() +// uint32_t[] icIndex() +// -- +// uint8_t[] safepoints() +// uint8_t[] snapshots() +// uint8_t[] snapshotsRVATable() +// uint8_t[] recovers() +// +// Note: These are arranged in order of descending alignment requirements to +// avoid the need for padding. The `runtimeData` uses uint64_t alignement due to +// its use of mozilla::AlignedStorage2. +struct alignas(8) IonScript final : public TrailingArray { + private: + // Table of constants referenced in snapshots. (JS::Value alignment) + uint32_t constantTable_ = 0; + uint32_t constantEntries_ = 0; + + // IonIC data structures. (uint64_t alignment) + uint32_t runtimeData_ = 0; + uint32_t runtimeSize_ = 0; + + // Map OSI-point displacement to snapshot. + uint32_t osiIndexOffset_ = 0; + uint32_t osiIndexEntries_ = 0; + + // Map code displacement to safepoint / OSI-patch-delta. + uint32_t safepointIndexOffset_ = 0; + uint32_t safepointIndexEntries_ = 0; + + // Table mapping bailout IDs to snapshot offsets. + uint32_t bailoutTable_ = 0; + uint32_t bailoutEntries_ = 0; + + // Offset into `runtimeData` for each (variable-length) IonIC. + uint32_t icIndex_ = 0; + uint32_t icEntries_ = 0; + + // Safepoint table as a CompactBuffer. + uint32_t safepointsStart_ = 0; + uint32_t safepointsSize_ = 0; + + // Snapshot and RValueAllocation tables as CompactBuffers. + uint32_t snapshots_ = 0; + uint32_t snapshotsListSize_ = 0; + uint32_t snapshotsRVATableSize_ = 0; + + // Recover instruction table as a CompactBuffer. + uint32_t recovers_ = 0; + uint32_t recoversSize_ = 0; + + // The size of this allocation. + uint32_t allocBytes_ = 0; + private: // Code pointer containing the actual method. HeapPtrJitCode method_ = nullptr; // Entrypoint for OSR, or nullptr. jsbytecode* osrPc_ = nullptr; // Offset to OSR entrypoint from method_->raw(), or 0. @@ -180,69 +242,26 @@ struct IonScript { uint32_t numBailouts_ = 0; // Flag set if IonScript was compiled with profiling enabled. bool hasProfilingInstrumentation_ = false; // Flag for if this script is getting recompiled. uint32_t recompiling_ = 0; - // Any kind of data needed by the runtime, these can be either cache - // information or profiling info. - uint32_t runtimeData_ = 0; - uint32_t runtimeSize_ = 0; - - // State for polymorphic caches in the compiled code. All caches are stored - // in the runtimeData buffer and indexed by the icIndex which gives a - // relative offset in the runtimeData array. - uint32_t icIndex_ = 0; - uint32_t icEntries_ = 0; - - // Map code displacement to safepoint / OSI-patch-delta. - uint32_t safepointIndexOffset_ = 0; - uint32_t safepointIndexEntries_ = 0; - - // Offset to and length of the safepoint table in bytes. - uint32_t safepointsStart_ = 0; - uint32_t safepointsSize_ = 0; - // Number of bytes this function reserves on the stack. uint32_t frameSlots_ = 0; // Number of bytes used passed in as formal arguments or |this|. uint32_t argumentSlots_ = 0; // Frame size is the value that can be added to the StackPointer along // with the frame prefix to get a valid JitFrameLayout. uint32_t frameSize_ = 0; - // Table mapping bailout IDs to snapshot offsets. - uint32_t bailoutTable_ = 0; - uint32_t bailoutEntries_ = 0; - - // Map OSI-point displacement to snapshot. - uint32_t osiIndexOffset_ = 0; - uint32_t osiIndexEntries_ = 0; - - // Offset from the start of the code buffer to its snapshot buffer. - uint32_t snapshots_ = 0; - uint32_t snapshotsListSize_ = 0; - uint32_t snapshotsRVATableSize_ = 0; - - // List of instructions needed to recover stack frames. - uint32_t recovers_ = 0; - uint32_t recoversSize_ = 0; - - // Constant table for constants stored in snapshots. - uint32_t constantTable_ = 0; - uint32_t constantEntries_ = 0; - - // The size of this allocation. - uint32_t allocBytes_ = 0; - // Number of references from invalidation records. uint32_t invalidationCount_ = 0; // Identifier of the compilation which produced this code. IonCompilationId compilationId_; // The optimization level this script was compiled in. OptimizationLevel optimizationLevel_;