From 2aa4a82499d4becd2284cdb482213d541b8804dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 16:29:10 +0200 Subject: Adding upstream version 86.0.1. Signed-off-by: Daniel Baumann --- js/public/Transcoding.h | 190 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 js/public/Transcoding.h (limited to 'js/public/Transcoding.h') diff --git a/js/public/Transcoding.h b/js/public/Transcoding.h new file mode 100644 index 0000000000..c386fc2539 --- /dev/null +++ b/js/public/Transcoding.h @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +/* + * Structures and functions for transcoding compiled scripts and functions to + * and from memory. + */ + +#ifndef js_Transcoding_h +#define js_Transcoding_h + +#include "mozilla/Range.h" // mozilla::Range +#include "mozilla/Vector.h" // mozilla::Vector + +#include // size_t +#include // uint8_t, uint32_t + +#include "js/TypeDecls.h" + +namespace JS { + +class ReadOnlyCompileOptions; + +using TranscodeBuffer = mozilla::Vector; +using TranscodeRange = mozilla::Range; + +struct TranscodeSource final { + TranscodeSource(const TranscodeRange& range_, const char* file, uint32_t line) + : range(range_), filename(file), lineno(line) {} + + const TranscodeRange range; + const char* filename; + const uint32_t lineno; +}; + +using TranscodeSources = mozilla::Vector; + +enum TranscodeResult : uint8_t { + // Successful encoding / decoding. + TranscodeResult_Ok = 0, + + // A warning message, is set to the message out-param. + TranscodeResult_Failure = 0x10, + TranscodeResult_Failure_BadBuildId = TranscodeResult_Failure | 0x1, + TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2, + TranscodeResult_Failure_AsmJSNotSupported = TranscodeResult_Failure | 0x3, + TranscodeResult_Failure_BadDecode = TranscodeResult_Failure | 0x4, + TranscodeResult_Failure_WrongCompileOption = TranscodeResult_Failure | 0x5, + TranscodeResult_Failure_NotInterpretedFun = TranscodeResult_Failure | 0x6, + + // There is a pending exception on the context. + TranscodeResult_Throw = 0x20 +}; + +static constexpr size_t BytecodeOffsetAlignment = 4; +static_assert(BytecodeOffsetAlignment <= alignof(std::max_align_t), + "Alignment condition requires a custom allocator."); + +// Align the bytecode offset for transcoding for the requirement. +inline size_t AlignTranscodingBytecodeOffset(size_t offset) { + size_t extra = offset % BytecodeOffsetAlignment; + if (extra == 0) { + return offset; + } + size_t padding = BytecodeOffsetAlignment - extra; + return offset + padding; +} + +inline bool IsTranscodingBytecodeOffsetAligned(size_t offset) { + return offset % BytecodeOffsetAlignment == 0; +} + +inline bool IsTranscodingBytecodeAligned(void* offset) { + return IsTranscodingBytecodeOffsetAligned(size_t(offset)); +} + +// Encode JSScript into the buffer. +// +// If the `buffer` isn't empty, the start of the `buffer` should meet +// IsTranscodingBytecodeAligned, and the length should meet +// IsTranscodingBytecodeOffsetAligned. +// +// NOTE: As long as IsTranscodingBytecodeOffsetAligned is met, that means +// there's JS::BytecodeOffsetAlignment+extra bytes in the buffer, +// IsTranscodingBytecodeAligned should be guaranteed to meet by +// malloc, used by MallocAllocPolicy in mozilla::Vector. +extern JS_PUBLIC_API TranscodeResult EncodeScript(JSContext* cx, + TranscodeBuffer& buffer, + Handle script); + +// Decode JSScript from the buffer. +// +// The start of `buffer` and `cursorIndex` should meet +// IsTranscodingBytecodeAligned and IsTranscodingBytecodeOffsetAligned. +// (This should be handled while encoding). +extern JS_PUBLIC_API TranscodeResult +DecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options, + TranscodeBuffer& buffer, MutableHandle scriptp, + size_t cursorIndex = 0); + +// Decode JSScript from the range. +// +// The start of `range` should meet IsTranscodingBytecodeAligned and +// IsTranscodingBytecodeOffsetAligned. +// (This should be handled while encoding). +extern JS_PUBLIC_API TranscodeResult +DecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options, + const TranscodeRange& range, MutableHandle scriptp); + +// If js::UseOffThreadParseGlobal is true, decode JSScript from the buffer. +// +// If js::UseOffThreadParseGlobal is false, decode CompilationStencil from the +// buffer and instantiate JSScript from it. +// +// options.useOffThreadParseGlobal should match JS::SetUseOffThreadParseGlobal. +// +// The start of `buffer` and `cursorIndex` should meet +// IsTranscodingBytecodeAligned and IsTranscodingBytecodeOffsetAligned. +// (This should be handled while encoding). +extern JS_PUBLIC_API TranscodeResult DecodeScriptMaybeStencil( + JSContext* cx, const ReadOnlyCompileOptions& options, + TranscodeBuffer& buffer, MutableHandle scriptp, + size_t cursorIndex = 0); + +// If js::UseOffThreadParseGlobal is true, decode JSScript from the buffer. +// +// If js::UseOffThreadParseGlobal is false, decode CompilationStencil from the +// buffer and instantiate JSScript from it. +// +// And then register an encoder on its script source, such that all functions +// can be encoded as they are parsed. This strategy is used to avoid blocking +// the main thread in a non-interruptible way. +// +// See also JS::FinishIncrementalEncoding. +// +// options.useOffThreadParseGlobal should match JS::SetUseOffThreadParseGlobal. +// +// The start of `buffer` and `cursorIndex` should meet +// IsTranscodingBytecodeAligned and IsTranscodingBytecodeOffsetAligned. +// (This should be handled while encoding). +extern JS_PUBLIC_API TranscodeResult DecodeScriptAndStartIncrementalEncoding( + JSContext* cx, const ReadOnlyCompileOptions& options, + TranscodeBuffer& buffer, MutableHandle scriptp, + size_t cursorIndex = 0); + +// Finish incremental encoding started by one of: +// * JS::CompileAndStartIncrementalEncoding +// * JS::FinishOffThreadScriptAndStartIncrementalEncoding +// * JS::DecodeScriptAndStartIncrementalEncoding +// +// The |script| argument of |FinishIncrementalEncoding| should be the top-level +// script returned from one of the above. +// +// The |buffer| argument of |FinishIncrementalEncoding| is used for appending +// the encoded bytecode into the buffer. If any of these functions failed, the +// content of |buffer| would be undefined. +// +// If js::UseOffThreadParseGlobal is true, |buffer| contains encoded JSScript. +// +// If js::UseOffThreadParseGlobal is false, |buffer| contains encoded +// CompilationStencil. +// +// If the `buffer` isn't empty, the start of the `buffer` should meet +// IsTranscodingBytecodeAligned, and the length should meet +// IsTranscodingBytecodeOffsetAligned. +// +// NOTE: As long as IsTranscodingBytecodeOffsetAligned is met, that means +// there's JS::BytecodeOffsetAlignment+extra bytes in the buffer, +// IsTranscodingBytecodeAligned should be guaranteed to meet by +// malloc, used by MallocAllocPolicy in mozilla::Vector. +extern JS_PUBLIC_API bool FinishIncrementalEncoding(JSContext* cx, + Handle script, + TranscodeBuffer& buffer); + +// Check if the compile options and script's flag matches. +// +// JS::DecodeScript* and JS::DecodeOffThreadScript internally check this. +// +// JS::DecodeMultiOffThreadScripts checks some options shared across multiple +// scripts. Caller is responsible for checking each script with this API when +// using the decoded script instead of compiling a new script wiht the given +// options. +extern JS_PUBLIC_API bool CheckCompileOptionsMatch( + const ReadOnlyCompileOptions& options, JSScript* script); + +} // namespace JS + +#endif /* js_Transcoding_h */ -- cgit v1.2.3