1/* 2 * Copyright (C) 2012, 2014 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#ifndef PolymorphicPutByIdList_h 27#define PolymorphicPutByIdList_h 28 29#if ENABLE(JIT) 30 31#include "CodeOrigin.h" 32#include "MacroAssembler.h" 33#include "Opcode.h" 34#include "PutKind.h" 35#include "PutPropertySlot.h" 36#include "Structure.h" 37#include <wtf/Vector.h> 38 39namespace JSC { 40 41class CodeBlock; 42struct StructureStubInfo; 43 44class PutByIdAccess { 45public: 46 enum AccessType { 47 Invalid, 48 Transition, 49 Replace, 50 Setter, 51 CustomSetter 52 }; 53 54 PutByIdAccess() 55 : m_type(Invalid) 56 { 57 } 58 59 static PutByIdAccess transition( 60 VM& vm, 61 JSCell* owner, 62 Structure* oldStructure, 63 Structure* newStructure, 64 StructureChain* chain, 65 PassRefPtr<JITStubRoutine> stubRoutine) 66 { 67 PutByIdAccess result; 68 result.m_type = Transition; 69 result.m_oldStructure.set(vm, owner, oldStructure); 70 result.m_newStructure.set(vm, owner, newStructure); 71 result.m_chain.set(vm, owner, chain); 72 result.m_customSetter = 0; 73 result.m_stubRoutine = stubRoutine; 74 return result; 75 } 76 77 static PutByIdAccess replace( 78 VM& vm, 79 JSCell* owner, 80 Structure* structure, 81 PassRefPtr<JITStubRoutine> stubRoutine) 82 { 83 PutByIdAccess result; 84 result.m_type = Replace; 85 result.m_oldStructure.set(vm, owner, structure); 86 result.m_customSetter = 0; 87 result.m_stubRoutine = stubRoutine; 88 return result; 89 } 90 91 92 static PutByIdAccess setter( 93 VM& vm, 94 JSCell* owner, 95 AccessType accessType, 96 Structure* structure, 97 StructureChain* chain, 98 PutPropertySlot::PutValueFunc customSetter, 99 PassRefPtr<JITStubRoutine> stubRoutine) 100 { 101 RELEASE_ASSERT(accessType == Setter || accessType == CustomSetter); 102 PutByIdAccess result; 103 result.m_oldStructure.set(vm, owner, structure); 104 result.m_type = accessType; 105 if (chain) 106 result.m_chain.set(vm, owner, chain); 107 result.m_customSetter = customSetter; 108 result.m_stubRoutine = stubRoutine; 109 return result; 110 } 111 112 static PutByIdAccess fromStructureStubInfo(StructureStubInfo&); 113 114 bool isSet() const { return m_type != Invalid; } 115 bool operator!() const { return !isSet(); } 116 117 AccessType type() const { return m_type; } 118 119 bool isTransition() const { return m_type == Transition; } 120 bool isReplace() const { return m_type == Replace; } 121 bool isSetter() const { return m_type == Setter; } 122 bool isCustom() const { return m_type == CustomSetter; } 123 124 Structure* oldStructure() const 125 { 126 // Using this instead of isSet() to make this assertion robust against the possibility 127 // of additional access types being added. 128 ASSERT(isTransition() || isReplace() || isSetter() || isCustom()); 129 130 return m_oldStructure.get(); 131 } 132 133 Structure* structure() const 134 { 135 ASSERT(isReplace()); 136 return m_oldStructure.get(); 137 } 138 139 Structure* newStructure() const 140 { 141 ASSERT(isTransition()); 142 return m_newStructure.get(); 143 } 144 145 StructureChain* chain() const 146 { 147 ASSERT(isTransition() || isSetter() || isCustom()); 148 return m_chain.get(); 149 } 150 151 JITStubRoutine* stubRoutine() const 152 { 153 ASSERT(isTransition() || isReplace() || isSetter() || isCustom()); 154 return m_stubRoutine.get(); 155 } 156 157 PutPropertySlot::PutValueFunc customSetter() const 158 { 159 ASSERT(isCustom()); 160 return m_customSetter; 161 } 162 163 bool visitWeak(RepatchBuffer&) const; 164 165private: 166 friend class CodeBlock; 167 168 AccessType m_type; 169 WriteBarrier<Structure> m_oldStructure; 170 WriteBarrier<Structure> m_newStructure; 171 WriteBarrier<StructureChain> m_chain; 172 PutPropertySlot::PutValueFunc m_customSetter; 173 RefPtr<JITStubRoutine> m_stubRoutine; 174}; 175 176class PolymorphicPutByIdList { 177 WTF_MAKE_FAST_ALLOCATED; 178public: 179 // Either creates a new polymorphic put list, or returns the one that is already 180 // in place. 181 static PolymorphicPutByIdList* from(PutKind, StructureStubInfo&); 182 183 ~PolymorphicPutByIdList(); 184 185 MacroAssemblerCodePtr currentSlowPathTarget() const 186 { 187 return m_list.last().stubRoutine()->code().code(); 188 } 189 190 void addAccess(const PutByIdAccess&); 191 192 bool isEmpty() const { return m_list.isEmpty(); } 193 unsigned size() const { return m_list.size(); } 194 bool isFull() const; 195 bool isAlmostFull() const; // True if adding an element would make isFull() true. 196 const PutByIdAccess& at(unsigned i) const { return m_list[i]; } 197 const PutByIdAccess& operator[](unsigned i) const { return m_list[i]; } 198 199 PutKind kind() const { return m_kind; } 200 201 bool visitWeak(RepatchBuffer&) const; 202 203private: 204 friend class CodeBlock; 205 206 // Initialize from a stub info; this will place one element in the list and it will 207 // be created by converting the stub info's put by id access information into our 208 // PutByIdAccess. 209 PolymorphicPutByIdList(PutKind, StructureStubInfo&); 210 211 Vector<PutByIdAccess, 2> m_list; 212 PutKind m_kind; 213}; 214 215} // namespace JSC 216 217#endif // ENABLE(JIT) 218 219#endif // PolymorphicPutByIdList_h 220 221