1/* 2 * Copyright (C) 2008, 2012, 2013, 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 StructureStubInfo_h 27#define StructureStubInfo_h 28 29#include "CodeOrigin.h" 30#include "Instruction.h" 31#include "JITStubRoutine.h" 32#include "MacroAssembler.h" 33#include "Opcode.h" 34#include "PolymorphicAccessStructureList.h" 35#include "RegisterSet.h" 36#include "SpillRegistersMode.h" 37#include "Structure.h" 38#include "StructureStubClearingWatchpoint.h" 39#include <wtf/OwnPtr.h> 40 41namespace JSC { 42 43#if ENABLE(JIT) 44 45class PolymorphicGetByIdList; 46class PolymorphicPutByIdList; 47 48enum AccessType { 49 access_get_by_id_self, 50 access_get_by_id_chain, 51 access_get_by_id_list, 52 access_put_by_id_transition_normal, 53 access_put_by_id_transition_direct, 54 access_put_by_id_replace, 55 access_put_by_id_list, 56 access_unset, 57 access_in_list 58}; 59 60inline bool isGetByIdAccess(AccessType accessType) 61{ 62 switch (accessType) { 63 case access_get_by_id_self: 64 case access_get_by_id_chain: 65 case access_get_by_id_list: 66 return true; 67 default: 68 return false; 69 } 70} 71 72inline bool isPutByIdAccess(AccessType accessType) 73{ 74 switch (accessType) { 75 case access_put_by_id_transition_normal: 76 case access_put_by_id_transition_direct: 77 case access_put_by_id_replace: 78 case access_put_by_id_list: 79 return true; 80 default: 81 return false; 82 } 83} 84 85inline bool isInAccess(AccessType accessType) 86{ 87 switch (accessType) { 88 case access_in_list: 89 return true; 90 default: 91 return false; 92 } 93} 94 95struct StructureStubInfo { 96 StructureStubInfo() 97 : accessType(access_unset) 98 , seen(false) 99 , resetByGC(false) 100 { 101 } 102 103 void initGetByIdSelf(VM& vm, JSCell* owner, Structure* baseObjectStructure) 104 { 105 accessType = access_get_by_id_self; 106 107 u.getByIdSelf.baseObjectStructure.set(vm, owner, baseObjectStructure); 108 } 109 110 void initGetByIdChain(VM& vm, JSCell* owner, Structure* baseObjectStructure, StructureChain* chain, unsigned count, bool isDirect) 111 { 112 accessType = access_get_by_id_chain; 113 114 u.getByIdChain.baseObjectStructure.set(vm, owner, baseObjectStructure); 115 u.getByIdChain.chain.set(vm, owner, chain); 116 u.getByIdChain.count = count; 117 u.getByIdChain.isDirect = isDirect; 118 } 119 120 void initGetByIdList(PolymorphicGetByIdList* list) 121 { 122 accessType = access_get_by_id_list; 123 u.getByIdList.list = list; 124 } 125 126 // PutById* 127 128 void initPutByIdTransition(VM& vm, JSCell* owner, Structure* previousStructure, Structure* structure, StructureChain* chain, bool isDirect) 129 { 130 if (isDirect) 131 accessType = access_put_by_id_transition_direct; 132 else 133 accessType = access_put_by_id_transition_normal; 134 135 u.putByIdTransition.previousStructure.set(vm, owner, previousStructure); 136 u.putByIdTransition.structure.set(vm, owner, structure); 137 u.putByIdTransition.chain.set(vm, owner, chain); 138 } 139 140 void initPutByIdReplace(VM& vm, JSCell* owner, Structure* baseObjectStructure) 141 { 142 accessType = access_put_by_id_replace; 143 144 u.putByIdReplace.baseObjectStructure.set(vm, owner, baseObjectStructure); 145 } 146 147 void initPutByIdList(PolymorphicPutByIdList* list) 148 { 149 accessType = access_put_by_id_list; 150 u.putByIdList.list = list; 151 } 152 153 void initInList(PolymorphicAccessStructureList* list, int listSize) 154 { 155 accessType = access_in_list; 156 u.inList.structureList = list; 157 u.inList.listSize = listSize; 158 } 159 160 void reset() 161 { 162 deref(); 163 accessType = access_unset; 164 stubRoutine.clear(); 165 watchpoints.clear(); 166 } 167 168 void deref(); 169 170 // Check if the stub has weak references that are dead. If there are dead ones that imply 171 // that the stub should be entirely reset, this should return false. If there are dead ones 172 // that can be handled internally by the stub and don't require a full reset, then this 173 // should reset them and return true. If there are no dead weak references, return true. 174 // If this method returns true it means that it has left the stub in a state where all 175 // outgoing GC pointers are known to point to currently marked objects; this method is 176 // allowed to accomplish this by either clearing those pointers somehow or by proving that 177 // they have already been marked. It is not allowed to mark new objects. 178 bool visitWeakReferences(RepatchBuffer&); 179 180 bool seenOnce() 181 { 182 return seen; 183 } 184 185 void setSeen() 186 { 187 seen = true; 188 } 189 190 StructureStubClearingWatchpoint* addWatchpoint(CodeBlock* codeBlock) 191 { 192 return WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint( 193 watchpoints, codeBlock, this); 194 } 195 196 int8_t accessType; 197 bool seen : 1; 198 bool resetByGC : 1; 199 200 CodeOrigin codeOrigin; 201 202 struct { 203 unsigned spillMode : 8; 204 int8_t baseGPR; 205#if USE(JSVALUE32_64) 206 int8_t valueTagGPR; 207#endif 208 int8_t valueGPR; 209 RegisterSet usedRegisters; 210 int32_t deltaCallToDone; 211 int32_t deltaCallToStorageLoad; 212 int32_t deltaCallToJump; 213 int32_t deltaCallToSlowCase; 214 int32_t deltaCheckImmToCall; 215#if USE(JSVALUE64) 216 int32_t deltaCallToLoadOrStore; 217#else 218 int32_t deltaCallToTagLoadOrStore; 219 int32_t deltaCallToPayloadLoadOrStore; 220#endif 221 } patch; 222 223 union { 224 struct { 225 // It would be unwise to put anything here, as it will surely be overwritten. 226 } unset; 227 struct { 228 WriteBarrierBase<Structure> baseObjectStructure; 229 } getByIdSelf; 230 struct { 231 WriteBarrierBase<Structure> baseObjectStructure; 232 WriteBarrierBase<Structure> prototypeStructure; 233 bool isDirect; 234 } getByIdProto; 235 struct { 236 WriteBarrierBase<Structure> baseObjectStructure; 237 WriteBarrierBase<StructureChain> chain; 238 unsigned count : 31; 239 bool isDirect : 1; 240 } getByIdChain; 241 struct { 242 PolymorphicGetByIdList* list; 243 } getByIdList; 244 struct { 245 WriteBarrierBase<Structure> previousStructure; 246 WriteBarrierBase<Structure> structure; 247 WriteBarrierBase<StructureChain> chain; 248 } putByIdTransition; 249 struct { 250 WriteBarrierBase<Structure> baseObjectStructure; 251 } putByIdReplace; 252 struct { 253 PolymorphicPutByIdList* list; 254 } putByIdList; 255 struct { 256 PolymorphicAccessStructureList* structureList; 257 int listSize; 258 } inList; 259 } u; 260 261 RefPtr<JITStubRoutine> stubRoutine; 262 CodeLocationCall callReturnLocation; 263 RefPtr<WatchpointsOnStructureStubInfo> watchpoints; 264}; 265 266inline CodeOrigin getStructureStubInfoCodeOrigin(StructureStubInfo& structureStubInfo) 267{ 268 return structureStubInfo.codeOrigin; 269} 270 271typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap; 272 273#else 274 275typedef HashMap<int, void*> StubInfoMap; 276 277#endif // ENABLE(JIT) 278 279} // namespace JSC 280 281#endif // StructureStubInfo_h 282