2 * Copyright (C) 2008, 2014-2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "StructureStubInfo.h"
30 #include "PolymorphicAccess.h"
36 StructureStubInfo::StructureStubInfo(AccessType accessType)
37 : callSiteIndex(UINT_MAX)
38 , accessType(accessType)
39 , cacheType(CacheType::Unset)
40 , countdown(1) // For a totally clear stub, we'll patch it after the first execution.
42 , numberOfCoolDowns(0)
45 , everConsidered(false)
49 StructureStubInfo::~StructureStubInfo()
53 void StructureStubInfo::initGetByIdSelf(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset)
55 cacheType = CacheType::GetByIdSelf;
57 u.byIdSelf.baseObjectStructure.set(
58 *codeBlock->vm(), codeBlock, baseObjectStructure);
59 u.byIdSelf.offset = offset;
62 void StructureStubInfo::initPutByIdReplace(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset)
64 cacheType = CacheType::PutByIdReplace;
66 u.byIdSelf.baseObjectStructure.set(
67 *codeBlock->vm(), codeBlock, baseObjectStructure);
68 u.byIdSelf.offset = offset;
71 void StructureStubInfo::initStub(CodeBlock*, std::unique_ptr<PolymorphicAccess> stub)
73 cacheType = CacheType::Stub;
74 u.stub = stub.release();
77 void StructureStubInfo::deref()
83 case CacheType::Unset:
84 case CacheType::GetByIdSelf:
85 case CacheType::PutByIdReplace:
89 RELEASE_ASSERT_NOT_REACHED();
92 void StructureStubInfo::aboutToDie()
98 case CacheType::Unset:
99 case CacheType::GetByIdSelf:
100 case CacheType::PutByIdReplace:
104 RELEASE_ASSERT_NOT_REACHED();
107 AccessGenerationResult StructureStubInfo::addAccessCase(
108 CodeBlock* codeBlock, const Identifier& ident, std::unique_ptr<AccessCase> accessCase)
110 VM& vm = *codeBlock->vm();
113 return AccessGenerationResult::MadeNoChanges;
115 if (cacheType == CacheType::Stub)
116 return u.stub->regenerateWithCase(vm, codeBlock, *this, ident, WTFMove(accessCase));
118 std::unique_ptr<PolymorphicAccess> access = std::make_unique<PolymorphicAccess>();
120 Vector<std::unique_ptr<AccessCase>> accessCases;
122 std::unique_ptr<AccessCase> previousCase =
123 AccessCase::fromStructureStubInfo(vm, codeBlock, *this);
125 accessCases.append(WTFMove(previousCase));
127 accessCases.append(WTFMove(accessCase));
129 AccessGenerationResult result =
130 access->regenerateWithCases(vm, codeBlock, *this, ident, WTFMove(accessCases));
132 if (!result.generatedNewCode())
135 initStub(codeBlock, WTFMove(access));
139 void StructureStubInfo::reset(CodeBlock* codeBlock)
141 if (cacheType == CacheType::Unset)
144 if (Options::verboseOSR()) {
145 // This can be called from GC destructor calls, so we don't try to do a full dump
147 dataLog("Clearing structure cache (kind ", static_cast<int>(accessType), ") in ", RawPointer(codeBlock), ".\n");
150 switch (accessType) {
151 case AccessType::Get:
152 resetGetByID(codeBlock, *this);
154 case AccessType::Put:
155 resetPutByID(codeBlock, *this);
158 resetIn(codeBlock, *this);
163 cacheType = CacheType::Unset;
166 void StructureStubInfo::visitWeakReferences(CodeBlock* codeBlock)
168 VM& vm = *codeBlock->vm();
171 case CacheType::GetByIdSelf:
172 case CacheType::PutByIdReplace:
173 if (Heap::isMarked(u.byIdSelf.baseObjectStructure.get()))
176 case CacheType::Stub:
177 if (u.stub->visitWeak(vm))
188 bool StructureStubInfo::containsPC(void* pc) const
190 if (cacheType != CacheType::Stub)
192 return u.stub->containsPC(pc);