text: /*
   * Copyright (C) 2012-2018 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
  
  #include "CacheableIdentifier.h"
  #include "ClassInfo.h"
  #include "CodeLocation.h"
  #include "IndexingType.h"
  #include "JITStubRoutine.h"
  #include "Structure.h"
  
  namespace JSC {
  
  class Symbol;
  
  #if ENABLE(JIT)
  
  class ArrayProfile;
  class StructureStubInfo;
  
  enum JITArrayMode : uint8_t {
      JITInt32,
      JITDouble,
      JITContiguous,
      JITArrayStorage,
      JITDirectArguments,
      JITScopedArguments,
      JITInt8Array,
      JITInt16Array,
      JITInt32Array,
      JITUint8Array,
      JITUint8ClampedArray,
      JITUint16Array,
      JITUint32Array,
      JITFloat32Array,
      JITFloat64Array
  };
  
  inline bool isOptimizableIndexingType(IndexingType indexingType)
  {
      switch (indexingType) {
      case ALL_INT32_INDEXING_TYPES:
      case ALL_DOUBLE_INDEXING_TYPES:
      case ALL_CONTIGUOUS_INDEXING_TYPES:
      case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES:
          return true;
      default:
          return false;
      }
  }
  
  inline bool hasOptimizableIndexingForJSType(JSType type)
  {
      switch (type) {
      case DirectArgumentsType:
      case ScopedArgumentsType:
          return true;
      default:
          return false;
      }
  }
  
  inline bool hasOptimizableIndexingForClassInfo(const ClassInfo* classInfo)
  {
      return isTypedView(classInfo->typedArrayStorageType);
  }
  
  inline bool hasOptimizableIndexing(Structure* structure)
  {
      return isOptimizableIndexingType(structure->indexingType())
          || hasOptimizableIndexingForJSType(structure->typeInfo().type())
          || hasOptimizableIndexingForClassInfo(structure->classInfo());
  }
  
  inline JITArrayMode jitArrayModeForIndexingType(IndexingType indexingType)
  {
      switch (indexingType) {
      case ALL_INT32_INDEXING_TYPES:
          return JITInt32;
      case ALL_DOUBLE_INDEXING_TYPES:
          return JITDouble;
      case ALL_CONTIGUOUS_INDEXING_TYPES:
          return JITContiguous;
      case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES:
          return JITArrayStorage;
      default:
          CRASH();
          return JITContiguous;
      }
  }
  
  inline JITArrayMode jitArrayModeForJSType(JSType type)
  {
      switch (type) {
      case DirectArgumentsType:
          return JITDirectArguments;
      case ScopedArgumentsType:
          return JITScopedArguments;
      default:
          RELEASE_ASSERT_NOT_REACHED();
          return JITContiguous;
      }
  }
  
  inline JITArrayMode jitArrayModeForClassInfo(const ClassInfo* classInfo)
  {
      switch (classInfo->typedArrayStorageType) {
      case TypeInt8:
          return JITInt8Array;
      case TypeInt16:
          return JITInt16Array;
      case TypeInt32:
          return JITInt32Array;
      case TypeUint8:
          return JITUint8Array;
      case TypeUint8Clamped:
          return JITUint8ClampedArray;
      case TypeUint16:
          return JITUint16Array;
      case TypeUint32:
          return JITUint32Array;
      case TypeFloat32:
          return JITFloat32Array;
      case TypeFloat64:
          return JITFloat64Array;
      default:
          CRASH();
          return JITContiguous;
      }
  }
  
  inline bool jitArrayModePermitsPut(JITArrayMode mode)
  {
      switch (mode) {
      case JITDirectArguments:
      case JITScopedArguments:
          // We could support put_by_val on these at some point, but it's just not that profitable
          // at the moment.
          return false;
      default:
          return true;
      }
  }
  
  inline bool jitArrayModePermitsPutDirect(JITArrayMode mode)
  {
      // We don't allow typed array putDirect here since putDirect has
      // defineOwnProperty({configurable: true, writable:true, enumerable:true})
      // semantics. Typed array indexed properties are non-configurable by
      // default, so we can't simply store to a typed array for putDirect.
      //
      // We could model putDirect on ScopedArguments and DirectArguments, but we
      // haven't found any performance incentive to do it yet.
      switch (mode) {
      case JITInt32:
      case JITDouble:
      case JITContiguous:
      case JITArrayStorage:
          return true;
      default:
          return false;
      }
  }
  
  inline TypedArrayType typedArrayTypeForJITArrayMode(JITArrayMode mode)
  {
      switch (mode) {
      case JITInt8Array:
          return TypeInt8;
      case JITInt16Array:
          return TypeInt16;
      case JITInt32Array:
          return TypeInt32;
      case JITUint8Array:
          return TypeUint8;
      case JITUint8ClampedArray:
          return TypeUint8Clamped;
      case JITUint16Array:
          return TypeUint16;
      case JITUint32Array:
          return TypeUint32;
      case JITFloat32Array:
          return TypeFloat32;
      case JITFloat64Array:
          return TypeFloat64;
      default:
          CRASH();
          return NotTypedArray;
      }
  }
  
  inline JITArrayMode jitArrayModeForStructure(Structure* structure)
  {
      if (isOptimizableIndexingType(structure->indexingType()))
          return jitArrayModeForIndexingType(structure->indexingType());
      
      if (hasOptimizableIndexingForJSType(structure->typeInfo().type()))
          return jitArrayModeForJSType(structure->typeInfo().type());
      
      ASSERT(hasOptimizableIndexingForClassInfo(structure->classInfo()));
      return jitArrayModeForClassInfo(structure->classInfo());
  }
  
  struct ByValInfo {
      ByValInfo() { }
  
      ByValInfo(BytecodeIndex bytecodeIndex, CodeLocationJump<JSInternalPtrTag> notIndexJump, CodeLocationJump<JSInternalPtrTag> badTypeJump, CodeLocationLabel<ExceptionHandlerPtrTag> exceptionHandler, JITArrayMode arrayMode, ArrayProfile* arrayProfile, CodeLocationLabel<JSInternalPtrTag> doneTarget, CodeLocationLabel<JSInternalPtrTag> badTypeNextHotPathTarget, CodeLocationLabel<JSInternalPtrTag> slowPathTarget)
          : notIndexJump(notIndexJump)
          , badTypeJump(badTypeJump)
          , exceptionHandler(exceptionHandler)
          , doneTarget(doneTarget)
          , badTypeNextHotPathTarget(badTypeNextHotPathTarget)
          , slowPathTarget(slowPathTarget)
          , arrayProfile(arrayProfile)
          , bytecodeIndex(bytecodeIndex)
          , slowPathCount(0)
          , stubInfo(nullptr)
          , arrayMode(arrayMode)
          , tookSlowPath(false)
          , seen(false)
      {
      }
  
      void visitAggregate(SlotVisitor&);
  
      CodeLocationJump<JSInternalPtrTag> notIndexJump;
      CodeLocationJump<JSInternalPtrTag> badTypeJump;
      CodeLocationLabel<ExceptionHandlerPtrTag> exceptionHandler;
      CodeLocationLabel<JSInternalPtrTag> doneTarget;
      CodeLocationLabel<JSInternalPtrTag> badTypeNextHotPathTarget;
      CodeLocationLabel<JSInternalPtrTag> slowPathTarget;
      ArrayProfile* arrayProfile;
      BytecodeIndex bytecodeIndex;
      unsigned slowPathCount;
      RefPtr<JITStubRoutine> stubRoutine;
      CacheableIdentifier cachedId; // Once we set cachedId, we must not change the value. JIT code relies on that configured cachedId is marked and retained by CodeBlock through ByValInfo.
      StructureStubInfo* stubInfo;
      JITArrayMode arrayMode; // The array mode that was baked into the inline JIT code.
      bool tookSlowPath : 1;
      bool seen : 1;
  };
  
  inline BytecodeIndex getByValInfoBytecodeIndex(ByValInfo* info)
  {
      return info->bytecodeIndex;
  }
  
  #endif // ENABLE(JIT)
  
  } // namespace JSC
  