/ bytecode / ComplexGetStatus.h
ComplexGetStatus.h
  1  /*
  2   * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
  3   *
  4   * Redistribution and use in source and binary forms, with or without
  5   * modification, are permitted provided that the following conditions
  6   * are met:
  7   * 1. Redistributions of source code must retain the above copyright
  8   *    notice, this list of conditions and the following disclaimer.
  9   * 2. Redistributions in binary form must reproduce the above copyright
 10   *    notice, this list of conditions and the following disclaimer in the
 11   *    documentation and/or other materials provided with the distribution.
 12   *
 13   * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 17   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21   * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 24   */
 25  
 26  #pragma once
 27  
 28  #include "ObjectPropertyConditionSet.h"
 29  #include "PropertyOffset.h"
 30  
 31  namespace JSC {
 32  
 33  class CodeBlock;
 34  class StructureChain;
 35  
 36  // This class is useful for figuring out how to inline a cached get-like access. We
 37  // say "get-like" because this is appropriate for loading the GetterSetter object in
 38  // a put_by_id that hits a setter. Notably, this doesn't figure out how to call
 39  // accessors, or even whether they should be called. What it gives us, is a way of
 40  // determining how to load the value from the requested property (identified by a
 41  // StringImpl* uid) from an object of the given structure in the given CodeBlock,
 42  // assuming that such an access had already been cached by Repatch (and so Repatch had
 43  // already done a bunch of safety checks). This doesn't reexecute any checks that
 44  // Repatch would have executed, and for prototype chain accesses, it doesn't ask the
 45  // objects in the prototype chain whether their getOwnPropertySlot would attempt to
 46  // intercept the access - so this really is only appropriate if you already know that
 47  // one of the JITOperations had OK'd this for caching and that Repatch concurred.
 48  //
 49  // The typical use pattern is something like:
 50  //
 51  //     ComplexGetStatus status = ComplexGetStatus::computeFor(...);
 52  //     switch (status.kind()) {
 53  //     case ComplexGetStatus::ShouldSkip:
 54  //         // Handle the case where this kind of access is possibly safe but wouldn't
 55  //         // pass the required safety checks. For example, if an IC gives us a list of
 56  //         // accesses and one of them is ShouldSkip, then we should pretend as if it
 57  //         // wasn't even there.
 58  //         break;
 59  //     case ComplexGetStatus::TakesSlowPath:
 60  //         // This kind of access is not safe to inline. Bail out of any attempst to
 61  //         // inline.
 62  //         break;
 63  //     case ComplexGetStatus::Inlineable:
 64  //         // The good stuff goes here. If it's Inlineable then the other properties of
 65  //         // the 'status' object will tell you everything you need to know about how
 66  //         // to execute the get-like operation.
 67  //         break;
 68  //     }
 69  
 70  class ComplexGetStatus final {
 71  public:
 72      enum Kind {
 73          ShouldSkip,
 74          TakesSlowPath,
 75          Inlineable
 76      };
 77      
 78      ComplexGetStatus()
 79          : m_kind(ShouldSkip)
 80          , m_offset(invalidOffset)
 81      {
 82      }
 83      
 84      static ComplexGetStatus skip()
 85      {
 86          return ComplexGetStatus();
 87      }
 88      
 89      static ComplexGetStatus takesSlowPath()
 90      {
 91          ComplexGetStatus result;
 92          result.m_kind = TakesSlowPath;
 93          return result;
 94      }
 95      
 96      static ComplexGetStatus computeFor(
 97          Structure* headStructure, const ObjectPropertyConditionSet&, UniquedStringImpl* uid);
 98      
 99      Kind kind() const { return m_kind; }
100      PropertyOffset offset() const { return m_offset; }
101      const ObjectPropertyConditionSet& conditionSet() const { return m_conditionSet; }
102      
103  private:
104      Kind m_kind;
105      PropertyOffset m_offset;
106      ObjectPropertyConditionSet m_conditionSet;
107  };
108  
109  } // namespace JSC