/ bytecode / PolyProtoAccessChain.cpp
PolyProtoAccessChain.cpp
  1  /*
  2   * Copyright (C) 2017-2019 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  #include "config.h"
 27  #include "PolyProtoAccessChain.h"
 28  
 29  #include "JSCInlines.h"
 30  
 31  namespace JSC {
 32  
 33  std::unique_ptr<PolyProtoAccessChain> PolyProtoAccessChain::create(JSGlobalObject* globalObject, JSCell* base, const PropertySlot& slot)
 34  {
 35      JSObject* target = slot.isUnset() ? nullptr : slot.slotBase();
 36      return create(globalObject, base, target);
 37  }
 38  
 39  std::unique_ptr<PolyProtoAccessChain> PolyProtoAccessChain::create(JSGlobalObject* globalObject, JSCell* base, JSObject* target)
 40  {
 41      JSCell* current = base;
 42      VM& vm = base->vm();
 43  
 44      bool found = false;
 45  
 46      std::unique_ptr<PolyProtoAccessChain> result(new PolyProtoAccessChain());
 47  
 48      for (unsigned iterationNumber = 0; true; ++iterationNumber) {
 49          Structure* structure = current->structure(vm);
 50  
 51          if (structure->isDictionary())
 52              return nullptr;
 53  
 54          if (!structure->propertyAccessesAreCacheable())
 55              return nullptr;
 56  
 57          if (structure->isProxy())
 58              return nullptr;
 59  
 60          // To save memory, we don't include the base in the chain. We let
 61          // AccessCase provide the base to us as needed.
 62          if (iterationNumber)
 63              result->m_chain.append(structure->id());
 64          else
 65              RELEASE_ASSERT(current == base);
 66  
 67          if (current == target) {
 68              found = true;
 69              break;
 70          }
 71  
 72          JSValue prototype = structure->prototypeForLookup(globalObject, current);
 73          if (prototype.isNull())
 74              break;
 75          current = asObject(prototype);
 76      }
 77  
 78      if (!found && !!target)
 79          return nullptr;
 80  
 81      result->m_chain.shrinkToFit();
 82      return result;
 83  }
 84  
 85  bool PolyProtoAccessChain::needImpurePropertyWatchpoint(VM& vm) const
 86  {
 87      for (StructureID structureID : m_chain) {
 88          if (vm.getStructure(structureID)->needImpurePropertyWatchpoint())
 89              return true;
 90      }
 91      return false;
 92  }
 93  
 94  bool PolyProtoAccessChain::operator==(const PolyProtoAccessChain& other) const
 95  {
 96      return m_chain == other.m_chain;
 97  }
 98  
 99  void PolyProtoAccessChain::dump(Structure* baseStructure, PrintStream& out) const
100  {
101      out.print("PolyPolyProtoAccessChain: [\n");
102      forEach(baseStructure->vm(), baseStructure, [&] (Structure* structure, bool) {
103          out.print("\t");
104          structure->dump(out);
105          out.print("\n");
106      });
107  }
108  
109  }