/* * Copyright (C) 2013-2020 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. */ #pragma once #if ENABLE(DFG_JIT) #include "DFGNodeFlags.h" #include "SpeculatedType.h" #include namespace JSC { namespace DFG { enum UseKind { // The DFG has 3 representations of values used: // 1. The JSValue representation for a JSValue that must be stored in a GP // register (or a GP register pair), and follows rules for boxing and unboxing // that allow the JSValue to be stored as either fully boxed JSValues, or // unboxed Int32, Booleans, Cells, etc. in 32-bit as appropriate. UntypedUse, // UntypedUse must come first (value 0). Int32Use, KnownInt32Use, AnyIntUse, NumberUse, RealNumberUse, BooleanUse, KnownBooleanUse, CellUse, KnownCellUse, CellOrOtherUse, ObjectUse, ArrayUse, FunctionUse, FinalObjectUse, PromiseObjectUse, RegExpObjectUse, ProxyObjectUse, DerivedArrayUse, ObjectOrOtherUse, StringIdentUse, StringUse, StringOrOtherUse, KnownStringUse, KnownPrimitiveUse, // This bizarre type arises for op_strcat, which has a bytecode guarantee that it will only see primitives (i.e. not objects). SymbolUse, AnyBigIntUse, HeapBigIntUse, BigInt32Use, DateObjectUse, MapObjectUse, SetObjectUse, WeakMapObjectUse, WeakSetObjectUse, DataViewObjectUse, StringObjectUse, StringOrStringObjectUse, NotStringVarUse, NotSymbolUse, NotCellUse, NotCellNorBigIntUse, KnownOtherUse, OtherUse, MiscUse, // 2. The Double representation for an unboxed double value that must be stored // in an FP register. DoubleRepUse, DoubleRepRealUse, DoubleRepAnyIntUse, // 3. The Int52 representation for an unboxed integer value that must be stored // in a GP register. Int52RepUse, LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements. }; inline SpeculatedType typeFilterFor(UseKind useKind) { switch (useKind) { case UntypedUse: return SpecBytecodeTop; case Int32Use: case KnownInt32Use: return SpecInt32Only; case Int52RepUse: return SpecInt52Any; case AnyIntUse: return SpecInt32Only | SpecAnyIntAsDouble; case NumberUse: return SpecBytecodeNumber; case RealNumberUse: return SpecBytecodeRealNumber; case DoubleRepUse: return SpecFullDouble; case DoubleRepRealUse: return SpecDoubleReal; case DoubleRepAnyIntUse: return SpecAnyIntAsDouble; case BooleanUse: case KnownBooleanUse: return SpecBoolean; case CellUse: case KnownCellUse: return SpecCellCheck; case CellOrOtherUse: return SpecCellCheck | SpecOther; case ObjectUse: return SpecObject; case ArrayUse: return SpecArray; case FunctionUse: return SpecFunction; case FinalObjectUse: return SpecFinalObject; case RegExpObjectUse: return SpecRegExpObject; case ProxyObjectUse: return SpecProxyObject; case DerivedArrayUse: return SpecDerivedArray; case ObjectOrOtherUse: return SpecObject | SpecOther; case StringIdentUse: return SpecStringIdent; case StringUse: case KnownStringUse: return SpecString; case StringOrOtherUse: return SpecString | SpecOther; case KnownPrimitiveUse: return SpecHeapTop & ~SpecObject; case SymbolUse: return SpecSymbol; case AnyBigIntUse: return SpecBigInt; case HeapBigIntUse: return SpecHeapBigInt; case BigInt32Use: return SpecBigInt32; case PromiseObjectUse: return SpecPromiseObject; case DateObjectUse: return SpecDateObject; case MapObjectUse: return SpecMapObject; case SetObjectUse: return SpecSetObject; case WeakMapObjectUse: return SpecWeakMapObject; case WeakSetObjectUse: return SpecWeakSetObject; case DataViewObjectUse: return SpecDataViewObject; case StringObjectUse: return SpecStringObject; case StringOrStringObjectUse: return SpecString | SpecStringObject; case NotStringVarUse: return ~SpecStringVar; case NotSymbolUse: return ~SpecSymbol; case NotCellUse: return ~SpecCellCheck; case NotCellNorBigIntUse: return ~SpecCellCheck & ~SpecBigInt; case KnownOtherUse: case OtherUse: return SpecOther; case MiscUse: return SpecMisc; default: RELEASE_ASSERT_NOT_REACHED(); return SpecFullTop; } } inline bool shouldNotHaveTypeCheck(UseKind kind) { switch (kind) { case UntypedUse: case KnownInt32Use: case KnownCellUse: case KnownStringUse: case KnownPrimitiveUse: case KnownBooleanUse: case KnownOtherUse: case Int52RepUse: case DoubleRepUse: return true; default: return false; } } inline bool mayHaveTypeCheck(UseKind kind) { return !shouldNotHaveTypeCheck(kind); } inline bool isDouble(UseKind kind) { switch (kind) { case DoubleRepUse: case DoubleRepRealUse: case DoubleRepAnyIntUse: return true; default: return false; } } // Returns true if the use kind only admits cells, and is therefore appropriate for // SpeculateCellOperand in the DFG or lowCell() in the FTL. inline bool isCell(UseKind kind) { switch (kind) { case CellUse: case KnownCellUse: case ObjectUse: case ArrayUse: case FunctionUse: case FinalObjectUse: case RegExpObjectUse: case PromiseObjectUse: case ProxyObjectUse: case DerivedArrayUse: case StringIdentUse: case StringUse: case KnownStringUse: case SymbolUse: case HeapBigIntUse: case StringObjectUse: case StringOrStringObjectUse: case DateObjectUse: case MapObjectUse: case SetObjectUse: case WeakMapObjectUse: case WeakSetObjectUse: case DataViewObjectUse: return true; default: return false; } } // Returns true if we've already guaranteed the type inline bool alreadyChecked(UseKind kind, SpeculatedType type) { return !(type & ~typeFilterFor(kind)); } inline UseKind useKindForResult(NodeFlags result) { ASSERT(!(result & ~NodeResultMask)); switch (result) { case NodeResultInt52: return Int52RepUse; case NodeResultDouble: return DoubleRepUse; default: return UntypedUse; } } inline bool checkMayCrashIfInputIsEmpty(UseKind kind) { #if USE(JSVALUE64) switch (kind) { case UntypedUse: case Int32Use: case KnownInt32Use: case AnyIntUse: case NumberUse: case BooleanUse: case KnownBooleanUse: case CellUse: case KnownCellUse: case CellOrOtherUse: case KnownOtherUse: case OtherUse: case MiscUse: case NotCellUse: case NotCellNorBigIntUse: return false; default: return true; } #else UNUSED_PARAM(kind); return true; #endif } } } // namespace JSC::DFG namespace WTF { void printInternal(PrintStream&, JSC::DFG::UseKind); } // namespace WTF #endif // ENABLE(DFG_JIT)