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#include "config.h" 27#include "PolymorphicPutByIdList.h" 28 29#if ENABLE(JIT) 30 31#include "StructureStubInfo.h" 32 33namespace JSC { 34 35PutByIdAccess PutByIdAccess::fromStructureStubInfo(StructureStubInfo& stubInfo) 36{ 37 MacroAssemblerCodePtr initialSlowPath = 38 stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToSlowCase); 39 40 PutByIdAccess result; 41 42 switch (stubInfo.accessType) { 43 case access_put_by_id_replace: 44 result.m_type = Replace; 45 result.m_oldStructure.copyFrom(stubInfo.u.putByIdReplace.baseObjectStructure); 46 result.m_stubRoutine = JITStubRoutine::createSelfManagedRoutine(initialSlowPath); 47 break; 48 49 case access_put_by_id_transition_direct: 50 case access_put_by_id_transition_normal: 51 result.m_type = Transition; 52 result.m_oldStructure.copyFrom(stubInfo.u.putByIdTransition.previousStructure); 53 result.m_newStructure.copyFrom(stubInfo.u.putByIdTransition.structure); 54 result.m_chain.copyFrom(stubInfo.u.putByIdTransition.chain); 55 result.m_stubRoutine = stubInfo.stubRoutine; 56 break; 57 58 default: 59 RELEASE_ASSERT_NOT_REACHED(); 60 } 61 62 return result; 63} 64 65bool PutByIdAccess::visitWeak(RepatchBuffer& repatchBuffer) const 66{ 67 switch (m_type) { 68 case Replace: 69 if (!Heap::isMarked(m_oldStructure.get())) 70 return false; 71 break; 72 case Transition: 73 if (!Heap::isMarked(m_oldStructure.get())) 74 return false; 75 if (!Heap::isMarked(m_newStructure.get())) 76 return false; 77 if (!Heap::isMarked(m_chain.get())) 78 return false; 79 break; 80 case Setter: 81 case CustomSetter: 82 if (!Heap::isMarked(m_oldStructure.get())) 83 return false; 84 if (m_chain && !Heap::isMarked(m_chain.get())) 85 return false; 86 break; 87 default: 88 RELEASE_ASSERT_NOT_REACHED(); 89 return false; 90 } 91 if (!m_stubRoutine->visitWeak(repatchBuffer)) 92 return false; 93 return true; 94} 95 96PolymorphicPutByIdList::PolymorphicPutByIdList( 97 PutKind putKind, StructureStubInfo& stubInfo) 98 : m_kind(putKind) 99{ 100 if (stubInfo.accessType != access_unset) 101 m_list.append(PutByIdAccess::fromStructureStubInfo(stubInfo)); 102} 103 104PolymorphicPutByIdList* PolymorphicPutByIdList::from( 105 PutKind putKind, StructureStubInfo& stubInfo) 106{ 107 if (stubInfo.accessType == access_put_by_id_list) 108 return stubInfo.u.putByIdList.list; 109 110 ASSERT(stubInfo.accessType == access_put_by_id_replace 111 || stubInfo.accessType == access_put_by_id_transition_normal 112 || stubInfo.accessType == access_put_by_id_transition_direct 113 || stubInfo.accessType == access_unset); 114 115 PolymorphicPutByIdList* result = 116 new PolymorphicPutByIdList(putKind, stubInfo); 117 118 stubInfo.initPutByIdList(result); 119 120 return result; 121} 122 123PolymorphicPutByIdList::~PolymorphicPutByIdList() { } 124 125bool PolymorphicPutByIdList::isFull() const 126{ 127 ASSERT(size() <= POLYMORPHIC_LIST_CACHE_SIZE); 128 return size() == POLYMORPHIC_LIST_CACHE_SIZE; 129} 130 131bool PolymorphicPutByIdList::isAlmostFull() const 132{ 133 ASSERT(size() <= POLYMORPHIC_LIST_CACHE_SIZE); 134 return size() >= POLYMORPHIC_LIST_CACHE_SIZE - 1; 135} 136 137void PolymorphicPutByIdList::addAccess(const PutByIdAccess& putByIdAccess) 138{ 139 ASSERT(!isFull()); 140 // Make sure that the resizing optimizes for space, not time. 141 m_list.resize(m_list.size() + 1); 142 m_list.last() = putByIdAccess; 143} 144 145bool PolymorphicPutByIdList::visitWeak(RepatchBuffer& repatchBuffer) const 146{ 147 for (unsigned i = 0; i < size(); ++i) { 148 if (!at(i).visitWeak(repatchBuffer)) 149 return false; 150 } 151 return true; 152} 153 154} // namespace JSC 155 156#endif // ENABLE(JIT) 157