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