/* -*- 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/VMFunctions.h" #include "mozilla/CheckedInt.h" #include "mozilla/FloatingPoint.h" #include "builtin/String.h" #include "frontend/BytecodeCompiler.h" #include "jit/arm/Simulator-arm.h" #include "jit/AtomicOperations.h" #include "jit/BaselineIC.h" #include "jit/CalleeToken.h" #include "jit/Invalidation.h" #include "jit/JitFrames.h" #include "jit/JitRuntime.h" #include "jit/mips32/Simulator-mips32.h" #include "jit/mips64/Simulator-mips64.h" #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* #include "js/friend/StackLimits.h" // js::CheckRecursionLimitWithExtra #include "js/friend/WindowProxy.h" // js::IsWindow #include "js/Printf.h" #include "vm/ArrayObject.h" #include "vm/Interpreter.h" #include "vm/PlainObject.h" // js::PlainObject #include "vm/SelfHosting.h" #include "vm/TraceLogging.h" #include "vm/TypedArrayObject.h" #include "wasm/TypedObject.h" #include "debugger/DebugAPI-inl.h" #include "jit/BaselineFrame-inl.h" #include "jit/VMFunctionList-inl.h" #include "vm/Interpreter-inl.h" #include "vm/JSScript-inl.h" #include "vm/NativeObject-inl.h" #include "vm/PlainObject-inl.h" // js::CreateThis #include "vm/StringObject-inl.h" using namespace js; using namespace js::jit; namespace js { class ArgumentsObject; class NamedLambdaObject; class AsyncFunctionGeneratorObject; class RegExpObject; namespace jit { struct IonOsrTempData; struct PopValues { uint8_t numValues; explicit constexpr PopValues(uint8_t numValues) : numValues(numValues) {} }; template struct TypeToDataType { /* Unexpected return type for a VMFunction. */ }; template <> struct TypeToDataType { static const DataType result = Type_Void; }; template <> struct TypeToDataType { static const DataType result = Type_Bool; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Handle; }; template <> struct TypeToDataType { static const DataType result = Type_Handle; }; template <> struct TypeToDataType { static const DataType result = Type_Handle; }; template <> struct TypeToDataType { static const DataType result = Type_Handle; }; template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; template <> struct TypeToDataType { static const DataType result = Type_Handle; }; template <> struct TypeToDataType { static const DataType result = Type_Handle; }; template <> struct TypeToDataType { static const DataType result = Type_Handle; }; template <> struct TypeToDataType { static const DataType result = Type_Handle; }; template <> struct TypeToDataType { static const DataType result = Type_Handle; }; // Convert argument types to properties of the argument known by the jit. template struct TypeToArgProperties { static const uint32_t result = (sizeof(T) <= sizeof(void*) ? VMFunctionData::Word : VMFunctionData::Double); }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties > { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties > { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties > { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties > { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties > { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties > { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties > { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties > { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties > { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties > { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; template <> struct TypeToArgProperties { static const uint32_t result = TypeToArgProperties::result | VMFunctionData::ByRef; }; // Convert argument type to whether or not it should be passed in a float // register on platforms that have them, like x64. template struct TypeToPassInFloatReg { static const uint32_t result = 0; }; template <> struct TypeToPassInFloatReg { static const uint32_t result = 1; }; // Convert argument types to root types used by the gc, see MarkJitExitFrame. template struct TypeToRootType { static const uint32_t result = VMFunctionData::RootNone; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootObject; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootString; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootString; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootFunction; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootValue; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootValue; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootId; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootCell; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootCell; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootCell; }; template <> struct TypeToRootType > { static const uint32_t result = VMFunctionData::RootObject; }; template <> struct TypeToRootType > { static const uint32_t result = VMFunctionData::RootObject; }; template <> struct TypeToRootType > { static const uint32_t result = VMFunctionData::RootObject; }; template <> struct TypeToRootType > { static const uint32_t result = VMFunctionData::RootObject; }; template <> struct TypeToRootType > { static const uint32_t result = VMFunctionData::RootObject; }; template <> struct TypeToRootType > { static const uint32_t result = VMFunctionData::RootObject; }; template <> struct TypeToRootType > { static const uint32_t result = VMFunctionData::RootObject; }; template <> struct TypeToRootType > { static const uint32_t result = VMFunctionData::RootCell; }; template <> struct TypeToRootType > { static const uint32_t result = VMFunctionData::RootCell; }; template <> struct TypeToRootType > { static const uint32_t result = VMFunctionData::RootCell; }; template <> struct TypeToRootType { static const uint32_t result = VMFunctionData::RootBigInt; }; template struct TypeToRootType > { // Fail for Handle types that aren't specialized above. }; template struct OutParamToDataType { static const DataType result = Type_Void; }; template <> struct OutParamToDataType { static const DataType result = Type_Value; }; template <> struct OutParamToDataType { static const DataType result = Type_Int32; }; template <> struct OutParamToDataType { static const DataType result = Type_Int32; }; template <> struct OutParamToDataType { static const DataType result = Type_Pointer; }; template <> struct OutParamToDataType { static const DataType result = Type_Pointer; }; template <> struct OutParamToDataType { static const DataType result = Type_Bool; }; template <> struct OutParamToDataType { static const DataType result = Type_Double; }; template <> struct OutParamToDataType { static const DataType result = Type_Handle; }; template <> struct OutParamToDataType { static const DataType result = Type_Handle; }; template <> struct OutParamToDataType { static const DataType result = Type_Handle; }; template <> struct OutParamToDataType { static const DataType result = Type_Handle; }; template struct OutParamToRootType { static const VMFunctionData::RootType result = VMFunctionData::RootNone; }; template <> struct OutParamToRootType { static const VMFunctionData::RootType result = VMFunctionData::RootValue; }; template <> struct OutParamToRootType { static const VMFunctionData::RootType result = VMFunctionData::RootObject; }; template <> struct OutParamToRootType { static const VMFunctionData::RootType result = VMFunctionData::RootString; }; template <> struct OutParamToRootType { static const VMFunctionData::RootType result = VMFunctionData::RootBigInt; }; // Construct a bit mask from a list of types. The mask is constructed as an OR // of the mask produced for each argument. The result of each argument is // shifted by its index, such that the result of the first argument is on the // low bits of the mask, and the result of the last argument in part of the // high bits of the mask. template