GitHub Viewer
/*
* Copyright (C) 2011-2025 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "LLIntData.h"
#include "InPlaceInterpreter.h"
#include "JSCConfig.h"
#include "LLIntCLoop.h"
#include "LLIntEntrypoint.h"
#include "LLIntSlowPaths.h"
#include "LLIntThunks.h"
#include "Opcode.h"
#if PLATFORM(COCOA)
#include
#include
#endif
WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN
namespace JSC {
namespace LLInt {
#if !HAVE(OS_SCRIPT_CONFIG_SPI)
#if COMPILER(CLANG)
// The purpose of applying this attribute is to move the os_script_config_storage away from other
// global variables, and allow the linker to pack them in more efficiently. Without this, the
// linker currently leaves multiple KBs of unused padding before this page though there are many
// other variables that come afterwards that would have fit in there. Adding this attribute was
// shown to resolve a memory regression on our small memory footprint benchmark.
#define LLINT_OPCODE_CONFIG_SECTION __attribute__((used, section("__DATA,__jsc_opcodes")))
#else
#define LLINT_OPCODE_CONFIG_SECTION
#endif
alignas(CeilingOnPageSize) uint8_t LLINT_OPCODE_CONFIG_SECTION os_script_config_storage[OpcodeConfigSizeToProtect];
#endif
static_assert(sizeof(OpcodeConfig) = 256, "nextInstruction() relies on this for bounding the dispatch");
#if CPU(ARM64E)
RELEASE_ASSERT(!g_jscConfig.llint.gateMap[static_cast(Gate::vmEntryToJavaScript)]);
JSC::Opcode tempOpcodeMap[numOpcodeIDs];
JSC::Opcode tempOpcodeMapWide16[numOpcodeIDs];
JSC::Opcode tempOpcodeMapWide32[numOpcodeIDs];
JSC::Opcode* opcodeMap = tempOpcodeMap;
JSC::Opcode* opcodeMapWide16 = tempOpcodeMapWide16;
JSC::Opcode* opcodeMapWide32 = tempOpcodeMapWide32;
#else
JSC::Opcode* opcodeMap = g_opcodeMap;
JSC::Opcode* opcodeMapWide16 = g_opcodeMapWide16;
JSC::Opcode* opcodeMapWide32 = g_opcodeMapWide32;
#endif
// Step 1: fill in opcodeMaps.
llint_entry(opcodeMap, opcodeMapWide16, opcodeMapWide32);
#if ENABLE(WEBASSEMBLY)
if (Options::useWasm())
IPInt::initialize();
#endif
#if CPU(ARM64E)
for (size_t i = 0; i < numOpcodeIDs; ++i) {
g_opcodeMap[i] = removeCodePtrTag(opcodeMap[i]);
g_opcodeMapWide16[i] = removeCodePtrTag(opcodeMapWide16[i]);
g_opcodeMapWide32[i] = removeCodePtrTag(opcodeMapWide32[i]);
}
#endif
// Step 2: freeze opcodeMaps.
WTF::compilerFence();
WTF::permanentlyFreezePages(&os_script_config_storage, OpcodeConfigSizeToProtect, WTF::FreezePagePermission::ReadOnly);
WTF::compilerFence();
// Step 3: verify that the opcodeMap is expected after freezing.
#if CPU(ARM64E)
for (size_t i = 0; i < numOpcodeIDs; ++i) {
uintptr_t tag = (static_cast(BytecodePtrTag)