1/* 2 * Copyright (C) 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#include "config.h" 27#include "PolymorphicGetByIdList.h" 28 29#if ENABLE(JIT) 30 31#include "CodeBlock.h" 32#include "Heap.h" 33#include "JSCInlines.h" 34#include "StructureStubInfo.h" 35 36namespace JSC { 37 38GetByIdAccess::GetByIdAccess( 39 VM& vm, JSCell* owner, AccessType type, PassRefPtr<JITStubRoutine> stubRoutine, 40 Structure* structure, StructureChain* chain, unsigned chainCount) 41 : m_type(type) 42 , m_chainCount(chainCount) 43 , m_structure(vm, owner, structure) 44 , m_stubRoutine(stubRoutine) 45{ 46 if (chain) 47 m_chain.set(vm, owner, chain); 48} 49 50GetByIdAccess::~GetByIdAccess() 51{ 52} 53 54GetByIdAccess GetByIdAccess::fromStructureStubInfo(StructureStubInfo& stubInfo) 55{ 56 MacroAssemblerCodePtr initialSlowPath = 57 stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToSlowCase); 58 59 GetByIdAccess result; 60 61 switch (stubInfo.accessType) { 62 case access_get_by_id_self: 63 result.m_type = SimpleInline; 64 result.m_structure.copyFrom(stubInfo.u.getByIdSelf.baseObjectStructure); 65 result.m_stubRoutine = JITStubRoutine::createSelfManagedRoutine(initialSlowPath); 66 break; 67 68 case access_get_by_id_chain: 69 result.m_structure.copyFrom(stubInfo.u.getByIdChain.baseObjectStructure); 70 result.m_chain.copyFrom(stubInfo.u.getByIdChain.chain); 71 result.m_chainCount = stubInfo.u.getByIdChain.count; 72 result.m_stubRoutine = stubInfo.stubRoutine; 73 if (stubInfo.u.getByIdChain.isDirect) 74 result.m_type = SimpleStub; 75 else 76 result.m_type = Getter; 77 break; 78 79 default: 80 RELEASE_ASSERT_NOT_REACHED(); 81 } 82 83 return result; 84} 85 86bool GetByIdAccess::visitWeak(RepatchBuffer& repatchBuffer) const 87{ 88 if (m_structure && !Heap::isMarked(m_structure.get())) 89 return false; 90 if (m_chain && !Heap::isMarked(m_chain.get())) 91 return false; 92 if (!m_stubRoutine->visitWeak(repatchBuffer)) 93 return false; 94 return true; 95} 96 97PolymorphicGetByIdList::PolymorphicGetByIdList(StructureStubInfo& stubInfo) 98{ 99 if (stubInfo.accessType == access_unset) 100 return; 101 102 m_list.append(GetByIdAccess::fromStructureStubInfo(stubInfo)); 103} 104 105PolymorphicGetByIdList* PolymorphicGetByIdList::from(StructureStubInfo& stubInfo) 106{ 107 if (stubInfo.accessType == access_get_by_id_list) 108 return stubInfo.u.getByIdList.list; 109 110 ASSERT( 111 stubInfo.accessType == access_get_by_id_self 112 || stubInfo.accessType == access_get_by_id_chain 113 || stubInfo.accessType == access_unset); 114 115 PolymorphicGetByIdList* result = new PolymorphicGetByIdList(stubInfo); 116 117 stubInfo.initGetByIdList(result); 118 119 return result; 120} 121 122PolymorphicGetByIdList::~PolymorphicGetByIdList() { } 123 124MacroAssemblerCodePtr PolymorphicGetByIdList::currentSlowPathTarget( 125 StructureStubInfo& stubInfo) const 126{ 127 if (isEmpty()) 128 return stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToSlowCase); 129 return m_list.last().stubRoutine()->code().code(); 130} 131 132void PolymorphicGetByIdList::addAccess(const GetByIdAccess& access) 133{ 134 ASSERT(!isFull()); 135 // Make sure that the resizing optimizes for space, not time. 136 m_list.resize(m_list.size() + 1); 137 m_list.last() = access; 138} 139 140bool PolymorphicGetByIdList::isFull() const 141{ 142 ASSERT(size() <= POLYMORPHIC_LIST_CACHE_SIZE); 143 return size() == POLYMORPHIC_LIST_CACHE_SIZE; 144} 145 146bool PolymorphicGetByIdList::isAlmostFull() const 147{ 148 ASSERT(size() <= POLYMORPHIC_LIST_CACHE_SIZE); 149 return size() >= POLYMORPHIC_LIST_CACHE_SIZE - 1; 150} 151 152bool PolymorphicGetByIdList::didSelfPatching() const 153{ 154 for (unsigned i = size(); i--;) { 155 if (at(i).type() == GetByIdAccess::SimpleInline) 156 return true; 157 } 158 return false; 159} 160 161bool PolymorphicGetByIdList::visitWeak(RepatchBuffer& repatchBuffer) const 162{ 163 for (unsigned i = size(); i--;) { 164 if (!at(i).visitWeak(repatchBuffer)) 165 return false; 166 } 167 return true; 168} 169 170} // namespace JSC 171 172#endif // ENABLE(JIT) 173 174 175