blob: 2bb3fe84a8db76151db14cb7fbd981b0405e1a80 [file] [log] [blame]
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +00001/*
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00002 * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +00003 *
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 "PutByIdStatus.h"
28
29#include "CodeBlock.h"
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +000030#include "ComplexGetStatus.h"
commit-queue@webkit.orgeebad5d2012-08-31 23:25:28 +000031#include "LLIntData.h"
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000032#include "LowLevelInterpreter.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000033#include "JSCInlines.h"
fpizlo@apple.comb26b5242015-09-10 19:49:36 +000034#include "PolymorphicAccess.h"
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +000035#include "Structure.h"
36#include "StructureChain.h"
fpizlo@apple.com43219522014-02-25 02:02:50 +000037#include <wtf/ListDump.h>
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +000038
39namespace JSC {
40
fpizlo@apple.com57399572014-03-05 22:01:57 +000041bool PutByIdStatus::appendVariant(const PutByIdVariant& variant)
42{
43 for (unsigned i = 0; i < m_variants.size(); ++i) {
fpizlo@apple.com3378c482014-07-27 23:14:40 +000044 if (m_variants[i].attemptToMerge(variant))
45 return true;
46 }
47 for (unsigned i = 0; i < m_variants.size(); ++i) {
48 if (m_variants[i].oldStructure().overlaps(variant.oldStructure()))
fpizlo@apple.com57399572014-03-05 22:01:57 +000049 return false;
50 }
51 m_variants.append(variant);
52 return true;
53}
54
commit-queue@webkit.orge9754872014-02-15 08:30:54 +000055#if ENABLE(DFG_JIT)
fpizlo@apple.comc1f69d72015-06-02 05:39:11 +000056bool PutByIdStatus::hasExitSite(const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, unsigned bytecodeIndex)
msaboff@apple.com95894332014-01-29 19:18:54 +000057{
fpizlo@apple.comc1f69d72015-06-02 05:39:11 +000058 return profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache))
59 || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadConstantCache));
msaboff@apple.com95894332014-01-29 19:18:54 +000060
61}
62#endif
63
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +000064PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, UniquedStringImpl* uid)
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000065{
66 UNUSED_PARAM(profiledBlock);
67 UNUSED_PARAM(bytecodeIndex);
oliver@apple.com02039462013-07-25 03:59:29 +000068 UNUSED_PARAM(uid);
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +000069
70 VM& vm = *profiledBlock->vm();
71
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000072 Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
73
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +000074 StructureID structureID = instruction[4].u.structureID;
75 if (!structureID)
fpizlo@apple.com43219522014-02-25 02:02:50 +000076 return PutByIdStatus(NoInformation);
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000077
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +000078 Structure* structure = vm.heap.structureIDTable().get(structureID);
79
80 StructureID newStructureID = instruction[6].u.structureID;
81 if (!newStructureID) {
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +000082 PropertyOffset offset = structure->getConcurrently(uid);
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +000083 if (!isValidOffset(offset))
fpizlo@apple.com43219522014-02-25 02:02:50 +000084 return PutByIdStatus(NoInformation);
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000085
fpizlo@apple.com12835772015-09-21 20:49:04 +000086 return PutByIdVariant::replace(structure, offset, structure->inferredTypeDescriptorFor(uid));
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000087 }
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +000088
89 Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000090
fpizlo@apple.com04e41152012-06-15 22:14:53 +000091 ASSERT(structure->transitionWatchpointSetHasBeenInvalidated());
92
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +000093 PropertyOffset offset = newStructure->getConcurrently(uid);
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +000094 if (!isValidOffset(offset))
fpizlo@apple.com43219522014-02-25 02:02:50 +000095 return PutByIdStatus(NoInformation);
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000096
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +000097 ObjectPropertyConditionSet conditionSet;
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +000098 if (!(instruction[8].u.putByIdFlags & PutByIdIsDirect)) {
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +000099 conditionSet =
100 generateConditionsForPropertySetterMissConcurrently(
101 *profiledBlock->vm(), profiledBlock->globalObject(), structure, uid);
102 if (!conditionSet.isValid())
103 return PutByIdStatus(NoInformation);
104 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000105
fpizlo@apple.com12835772015-09-21 20:49:04 +0000106 return PutByIdVariant::transition(
107 structure, newStructure, conditionSet, offset, newStructure->inferredTypeDescriptorFor(uid));
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000108}
109
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000110PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& map, unsigned bytecodeIndex, UniquedStringImpl* uid)
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +0000111{
oliver@apple.comd2056662013-07-25 04:00:37 +0000112 ConcurrentJITLocker locker(profiledBlock->m_lock);
oliver@apple.com0c1b13e2013-07-25 03:58:43 +0000113
fpizlo@apple.com246741b2012-01-22 09:11:49 +0000114 UNUSED_PARAM(profiledBlock);
115 UNUSED_PARAM(bytecodeIndex);
oliver@apple.com02039462013-07-25 03:59:29 +0000116 UNUSED_PARAM(uid);
commit-queue@webkit.orge9754872014-02-15 08:30:54 +0000117#if ENABLE(DFG_JIT)
fpizlo@apple.com4d04f3c2015-06-03 20:04:00 +0000118 if (hasExitSite(locker, profiledBlock, bytecodeIndex))
fpizlo@apple.com43219522014-02-25 02:02:50 +0000119 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +0000120
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000121 StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex));
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000122 PutByIdStatus result = computeForStubInfo(
123 locker, profiledBlock, stubInfo, uid,
124 CallLinkStatus::computeExitSiteData(locker, profiledBlock, bytecodeIndex));
msaboff@apple.com95894332014-01-29 19:18:54 +0000125 if (!result)
oliver@apple.com02039462013-07-25 03:59:29 +0000126 return computeFromLLInt(profiledBlock, bytecodeIndex, uid);
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +0000127
msaboff@apple.com95894332014-01-29 19:18:54 +0000128 return result;
129#else // ENABLE(JIT)
130 UNUSED_PARAM(map);
fpizlo@apple.com43219522014-02-25 02:02:50 +0000131 return PutByIdStatus(NoInformation);
msaboff@apple.com95894332014-01-29 19:18:54 +0000132#endif // ENABLE(JIT)
133}
134
135#if ENABLE(JIT)
utatane.tea@gmail.comcb7ea562015-08-20 20:18:45 +0000136PutByIdStatus PutByIdStatus::computeForStubInfo(const ConcurrentJITLocker& locker, CodeBlock* baselineBlock, StructureStubInfo* stubInfo, CodeOrigin codeOrigin, UniquedStringImpl* uid)
137{
138 return computeForStubInfo(
139 locker, baselineBlock, stubInfo, uid,
140 CallLinkStatus::computeExitSiteData(locker, baselineBlock, codeOrigin.bytecodeIndex));
141}
142
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000143PutByIdStatus PutByIdStatus::computeForStubInfo(
144 const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo,
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000145 UniquedStringImpl* uid, CallLinkStatus::ExitSiteData callExitSiteData)
msaboff@apple.com95894332014-01-29 19:18:54 +0000146{
fpizlo@apple.com5566f232015-10-05 17:05:24 +0000147 if (!stubInfo || !stubInfo->everConsidered)
fpizlo@apple.com4d04f3c2015-06-03 20:04:00 +0000148 return PutByIdStatus();
149
150 if (stubInfo->tookSlowPath)
151 return PutByIdStatus(TakesSlowPath);
152
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000153 switch (stubInfo->cacheType) {
154 case CacheType::Unset:
fpizlo@apple.com5566f232015-10-05 17:05:24 +0000155 // This means that we attempted to cache but failed for some reason.
fpizlo@apple.com43219522014-02-25 02:02:50 +0000156 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +0000157
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000158 case CacheType::PutByIdReplace: {
oliver@apple.comb3956442013-07-25 03:58:27 +0000159 PropertyOffset offset =
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000160 stubInfo->u.byIdSelf.baseObjectStructure->getConcurrently(uid);
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000161 if (isValidOffset(offset)) {
fpizlo@apple.com43219522014-02-25 02:02:50 +0000162 return PutByIdVariant::replace(
fpizlo@apple.com12835772015-09-21 20:49:04 +0000163 stubInfo->u.byIdSelf.baseObjectStructure.get(), offset, InferredType::Top);
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +0000164 }
fpizlo@apple.com43219522014-02-25 02:02:50 +0000165 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +0000166 }
167
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000168 case CacheType::Stub: {
169 PolymorphicAccess* list = stubInfo->u.stub;
fpizlo@apple.com43219522014-02-25 02:02:50 +0000170
171 PutByIdStatus result;
172 result.m_state = Simple;
173
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000174 State slowPathState = TakesSlowPath;
fpizlo@apple.com43219522014-02-25 02:02:50 +0000175 for (unsigned i = 0; i < list->size(); ++i) {
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000176 const AccessCase& access = list->at(i);
177 if (access.doesCalls())
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000178 slowPathState = MakesCalls;
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000179 }
180
181 for (unsigned i = 0; i < list->size(); ++i) {
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000182 const AccessCase& access = list->at(i);
183 if (access.viaProxy())
184 return PutByIdStatus(slowPathState);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000185
186 PutByIdVariant variant;
187
188 switch (access.type()) {
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000189 case AccessCase::Replace: {
fpizlo@apple.com43219522014-02-25 02:02:50 +0000190 Structure* structure = access.structure();
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000191 PropertyOffset offset = structure->getConcurrently(uid);
fpizlo@apple.com43219522014-02-25 02:02:50 +0000192 if (!isValidOffset(offset))
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000193 return PutByIdStatus(slowPathState);
fpizlo@apple.com12835772015-09-21 20:49:04 +0000194 variant = PutByIdVariant::replace(
195 structure, offset, structure->inferredTypeDescriptorFor(uid));
fpizlo@apple.com43219522014-02-25 02:02:50 +0000196 break;
197 }
198
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000199 case AccessCase::Transition: {
fpizlo@apple.com43219522014-02-25 02:02:50 +0000200 PropertyOffset offset =
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000201 access.newStructure()->getConcurrently(uid);
fpizlo@apple.com43219522014-02-25 02:02:50 +0000202 if (!isValidOffset(offset))
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000203 return PutByIdStatus(slowPathState);
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000204 ObjectPropertyConditionSet conditionSet = access.conditionSet();
205 if (!conditionSet.structuresEnsureValidity())
206 return PutByIdStatus(slowPathState);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000207 variant = PutByIdVariant::transition(
fpizlo@apple.com12835772015-09-21 20:49:04 +0000208 access.structure(), access.newStructure(), conditionSet, offset,
209 access.newStructure()->inferredTypeDescriptorFor(uid));
fpizlo@apple.com43219522014-02-25 02:02:50 +0000210 break;
211 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000212
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000213 case AccessCase::Setter: {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000214 Structure* structure = access.structure();
215
216 ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor(
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000217 structure, access.conditionSet(), uid);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000218
219 switch (complexGetStatus.kind()) {
220 case ComplexGetStatus::ShouldSkip:
221 continue;
222
223 case ComplexGetStatus::TakesSlowPath:
224 return PutByIdStatus(slowPathState);
225
226 case ComplexGetStatus::Inlineable: {
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000227 CallLinkInfo* callLinkInfo = access.callLinkInfo();
228 ASSERT(callLinkInfo);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000229 std::unique_ptr<CallLinkStatus> callLinkStatus =
230 std::make_unique<CallLinkStatus>(
231 CallLinkStatus::computeFor(
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000232 locker, profiledBlock, *callLinkInfo, callExitSiteData));
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000233
234 variant = PutByIdVariant::setter(
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000235 structure, complexGetStatus.offset(), complexGetStatus.conditionSet(),
gyuyoung.kim@samsung.com23dff192014-10-17 09:54:14 +0000236 WTF::move(callLinkStatus));
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000237 } }
238 break;
239 }
240
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000241 case AccessCase::CustomSetter:
oliver@apple.com11ce5ff2014-03-06 21:27:13 +0000242 return PutByIdStatus(MakesCalls);
fpizlo@apple.com43219522014-02-25 02:02:50 +0000243
244 default:
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000245 return PutByIdStatus(slowPathState);
fpizlo@apple.com43219522014-02-25 02:02:50 +0000246 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000247
248 if (!result.appendVariant(variant))
249 return PutByIdStatus(slowPathState);
fpizlo@apple.com43219522014-02-25 02:02:50 +0000250 }
251
252 return result;
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +0000253 }
254
255 default:
fpizlo@apple.com43219522014-02-25 02:02:50 +0000256 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +0000257 }
msaboff@apple.com95894332014-01-29 19:18:54 +0000258}
259#endif
260
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000261PutByIdStatus PutByIdStatus::computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin codeOrigin, UniquedStringImpl* uid)
msaboff@apple.com95894332014-01-29 19:18:54 +0000262{
commit-queue@webkit.orge9754872014-02-15 08:30:54 +0000263#if ENABLE(DFG_JIT)
msaboff@apple.com95894332014-01-29 19:18:54 +0000264 if (dfgBlock) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000265 CallLinkStatus::ExitSiteData exitSiteData;
msaboff@apple.com95894332014-01-29 19:18:54 +0000266 {
267 ConcurrentJITLocker locker(baselineBlock->m_lock);
fpizlo@apple.comc1f69d72015-06-02 05:39:11 +0000268 if (hasExitSite(locker, baselineBlock, codeOrigin.bytecodeIndex))
msaboff@apple.com95894332014-01-29 19:18:54 +0000269 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000270 exitSiteData = CallLinkStatus::computeExitSiteData(
fpizlo@apple.comc1f69d72015-06-02 05:39:11 +0000271 locker, baselineBlock, codeOrigin.bytecodeIndex);
msaboff@apple.com95894332014-01-29 19:18:54 +0000272 }
273
274 PutByIdStatus result;
275 {
276 ConcurrentJITLocker locker(dfgBlock->m_lock);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000277 result = computeForStubInfo(
278 locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData);
msaboff@apple.com95894332014-01-29 19:18:54 +0000279 }
280
fpizlo@apple.coma502abe2014-03-30 18:43:41 +0000281 // We use TakesSlowPath in some cases where the stub was unset. That's weird and
282 // it would be better not to do that. But it means that we have to defend
283 // ourselves here.
284 if (result.isSimple())
msaboff@apple.com95894332014-01-29 19:18:54 +0000285 return result;
286 }
287#else
288 UNUSED_PARAM(dfgBlock);
289 UNUSED_PARAM(dfgMap);
290#endif
291
292 return computeFor(baselineBlock, baselineMap, codeOrigin.bytecodeIndex, uid);
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +0000293}
294
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000295PutByIdStatus PutByIdStatus::computeFor(JSGlobalObject* globalObject, const StructureSet& set, UniquedStringImpl* uid, bool isDirect)
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000296{
utatane.tea@gmail.comc7c203c2015-04-06 12:40:33 +0000297 if (parseIndex(*uid))
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000298 return PutByIdStatus(TakesSlowPath);
oliver@apple.com58c86752013-07-25 04:02:40 +0000299
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000300 if (set.isEmpty())
301 return PutByIdStatus();
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000302
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000303 PutByIdStatus result;
304 result.m_state = Simple;
305 for (unsigned i = 0; i < set.size(); ++i) {
306 Structure* structure = set[i];
307
308 if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
309 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000310
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000311 if (!structure->propertyAccessesAreCacheable())
312 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000313
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000314 unsigned attributes;
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000315 PropertyOffset offset = structure->getConcurrently(uid, attributes);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000316 if (isValidOffset(offset)) {
317 if (attributes & CustomAccessor)
318 return PutByIdStatus(MakesCalls);
oliver@apple.com11ce5ff2014-03-06 21:27:13 +0000319
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000320 if (attributes & (Accessor | ReadOnly))
321 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000322
323 WatchpointSet* replaceSet = structure->propertyReplacementWatchpointSet(offset);
324 if (!replaceSet || replaceSet->isStillValid()) {
325 // When this executes, it'll create, and fire, this replacement watchpoint set.
326 // That means that this has probably never executed or that something fishy is
327 // going on. Also, we cannot create or fire the watchpoint set from the concurrent
328 // JIT thread, so even if we wanted to do this, we'd need to have a lazy thingy.
329 // So, better leave this alone and take slow path.
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000330 return PutByIdStatus(TakesSlowPath);
331 }
fpizlo@apple.com12835772015-09-21 20:49:04 +0000332
333 PutByIdVariant variant =
334 PutByIdVariant::replace(structure, offset, structure->inferredTypeDescriptorFor(uid));
335 if (!result.appendVariant(variant))
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000336 return PutByIdStatus(TakesSlowPath);
337 continue;
fpizlo@apple.comfd016b12013-03-22 20:51:24 +0000338 }
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000339
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000340 // Our hypothesis is that we're doing a transition. Before we prove that this is really
341 // true, we want to do some sanity checks.
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000342
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000343 // Don't cache put transitions on dictionaries.
344 if (structure->isDictionary())
345 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000346
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000347 // If the structure corresponds to something that isn't an object, then give up, since
348 // we don't want to be adding properties to strings.
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +0000349 if (!structure->typeInfo().isObject())
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000350 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000351
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000352 ObjectPropertyConditionSet conditionSet;
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000353 if (!isDirect) {
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +0000354 conditionSet = generateConditionsForPropertySetterMissConcurrently(
355 globalObject->vm(), globalObject, structure, uid);
356 if (!conditionSet.isValid())
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000357 return PutByIdStatus(TakesSlowPath);
358 }
359
360 // We only optimize if there is already a structure that the transition is cached to.
fpizlo@apple.com12835772015-09-21 20:49:04 +0000361 Structure* transition =
362 Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000363 if (!transition)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000364 return PutByIdStatus(TakesSlowPath);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000365 ASSERT(isValidOffset(offset));
366
367 bool didAppend = result.appendVariant(
fpizlo@apple.com12835772015-09-21 20:49:04 +0000368 PutByIdVariant::transition(
369 structure, transition, conditionSet, offset,
370 transition->inferredTypeDescriptorFor(uid)));
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000371 if (!didAppend)
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000372 return PutByIdStatus(TakesSlowPath);
373 }
374
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000375 return result;
fpizlo@apple.com43219522014-02-25 02:02:50 +0000376}
377
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000378bool PutByIdStatus::makesCalls() const
379{
380 if (m_state == MakesCalls)
381 return true;
382
383 if (m_state != Simple)
384 return false;
385
386 for (unsigned i = m_variants.size(); i--;) {
387 if (m_variants[i].makesCalls())
388 return true;
389 }
390
391 return false;
392}
393
fpizlo@apple.com43219522014-02-25 02:02:50 +0000394void PutByIdStatus::dump(PrintStream& out) const
395{
396 switch (m_state) {
397 case NoInformation:
398 out.print("(NoInformation)");
399 return;
400
401 case Simple:
402 out.print("(", listDump(m_variants), ")");
403 return;
404
405 case TakesSlowPath:
406 out.print("(TakesSlowPath)");
407 return;
oliver@apple.com11ce5ff2014-03-06 21:27:13 +0000408 case MakesCalls:
409 out.print("(MakesCalls)");
410 return;
fpizlo@apple.com43219522014-02-25 02:02:50 +0000411 }
412
413 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000414}
415
fpizlo@apple.com1f8917f2012-01-22 01:36:23 +0000416} // namespace JSC
417