text: /*
   * Copyright (C) 2014, 2015 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. 
   */
  
  #ifndef ComplexGetStatus_h
  #define ComplexGetStatus_h
  
  #include "JSCJSValue.h"
  #include "ObjectPropertyConditionSet.h"
  #include "PropertyOffset.h"
  
  namespace JSC {
  
  class CodeBlock;
  class StructureChain;
  
  // This class is useful for figuring out how to inline a cached get-like access. We
  // say "get-like" because this is appropriate for loading the GetterSetter object in
  // a put_by_id that hits a setter. Notably, this doesn't figure out how to call
  // accessors, or even whether they should be called. What it gives us, is a way of
  // determining how to load the value from the requested property (identified by a
  // StringImpl* uid) from an object of the given structure in the given CodeBlock,
  // assuming that such an access had already been cached by Repatch (and so Repatch had
  // already done a bunch of safety checks). This doesn't reexecute any checks that
  // Repatch would have executed, and for prototype chain accesses, it doesn't ask the
  // objects in the prototype chain whether their getOwnPropertySlot would attempt to
  // intercept the access - so this really is only appropriate if you already know that
  // one of the JITOperations had OK'd this for caching and that Repatch concurred.
  //
  // The typical use pattern is something like:
  //
  //     ComplexGetStatus status = ComplexGetStatus::computeFor(...);
  //     switch (status.kind()) {
  //     case ComplexGetStatus::ShouldSkip:
  //         // Handle the case where this kind of access is possibly safe but wouldn't
  //         // pass the required safety checks. For example, if an IC gives us a list of
  //         // accesses and one of them is ShouldSkip, then we should pretend as if it
  //         // wasn't even there.
  //         break;
  //     case ComplexGetStatus::TakesSlowPath:
  //         // This kind of access is not safe to inline. Bail out of any attempst to
  //         // inline.
  //         break;
  //     case ComplexGetStatus::Inlineable:
  //         // The good stuff goes here. If it's Inlineable then the other properties of
  //         // the 'status' object will tell you everything you need to know about how
  //         // to execute the get-like operation.
  //         break;
  //     }
  
  class ComplexGetStatus {
  public:
      enum Kind {
          ShouldSkip,
          TakesSlowPath,
          Inlineable
      };
      
      ComplexGetStatus()
          : m_kind(ShouldSkip)
          , m_offset(invalidOffset)
      {
      }
      
      static ComplexGetStatus skip()
      {
          return ComplexGetStatus();
      }
      
      static ComplexGetStatus takesSlowPath()
      {
          ComplexGetStatus result;
          result.m_kind = TakesSlowPath;
          return result;
      }
      
      static ComplexGetStatus computeFor(
          Structure* headStructure, const ObjectPropertyConditionSet&, UniquedStringImpl* uid);
      
      Kind kind() const { return m_kind; }
      PropertyOffset offset() const { return m_offset; }
      const ObjectPropertyConditionSet& conditionSet() const { return m_conditionSet; }
      
  private:
      Kind m_kind;
      PropertyOffset m_offset;
      ObjectPropertyConditionSet m_conditionSet;
  };
  
  } // namespace JSC
  
  #endif // ComplexGetStatus_h
  
  