PolyProtoAccessChain.h
1 /* 2 * Copyright (C) 2017 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 "StructureIDTable.h" 29 #include "VM.h" 30 #include <wtf/Vector.h> 31 32 namespace JSC { 33 34 class JSCell; 35 class JSGlobalObject; 36 class JSObject; 37 class PropertySlot; 38 class Structure; 39 40 class PolyProtoAccessChain { 41 WTF_MAKE_FAST_ALLOCATED; 42 43 public: 44 PolyProtoAccessChain(PolyProtoAccessChain&) = default; 45 46 // Returns nullptr when invalid. 47 static std::unique_ptr<PolyProtoAccessChain> create(JSGlobalObject*, JSCell* base, const PropertySlot&); 48 static std::unique_ptr<PolyProtoAccessChain> create(JSGlobalObject*, JSCell* base, JSObject* target); 49 50 std::unique_ptr<PolyProtoAccessChain> clone() 51 { 52 return makeUnique<PolyProtoAccessChain>(*this); 53 } 54 55 const Vector<StructureID>& chain() const { return m_chain; } 56 57 void dump(Structure* baseStructure, PrintStream& out) const; 58 59 bool operator==(const PolyProtoAccessChain& other) const; 60 bool operator!=(const PolyProtoAccessChain& other) const 61 { 62 return !(*this == other); 63 } 64 65 bool needImpurePropertyWatchpoint(VM&) const; 66 67 template <typename Func> 68 void forEach(VM& vm, Structure* baseStructure, const Func& func) const 69 { 70 bool atEnd = !m_chain.size(); 71 func(baseStructure, atEnd); 72 for (unsigned i = 0; i < m_chain.size(); ++i) { 73 atEnd = i + 1 == m_chain.size(); 74 func(vm.getStructure(m_chain[i]), atEnd); 75 } 76 } 77 78 Structure* slotBaseStructure(VM& vm, Structure* baseStructure) const 79 { 80 if (m_chain.size()) 81 return vm.getStructure(m_chain.last()); 82 return baseStructure; 83 } 84 85 private: 86 PolyProtoAccessChain() = default; 87 88 // This does not include the base. We rely on AccessCase providing it for us. That said, this data 89 // structure is tied to the base that it was created with. 90 Vector<StructureID> m_chain; 91 }; 92 93 }