1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "jit/AliasAnalysisShared.h"
8
9 #include "jit/MIR.h"
10
11 namespace js {
12 namespace jit {
13
14 void
spewDependencyList()15 AliasAnalysisShared::spewDependencyList()
16 {
17 #ifdef JS_JITSPEW
18 if (JitSpewEnabled(JitSpew_AliasSummaries)) {
19 Fprinter &print = JitSpewPrinter();
20 JitSpewHeader(JitSpew_AliasSummaries);
21 print.printf("Dependency list for other passes:\n");
22
23 for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) {
24 for (MInstructionIterator def(block->begin()), end(block->begin(block->lastIns()));
25 def != end;
26 ++def)
27 {
28 if (!def->dependency())
29 continue;
30 if (!def->getAliasSet().isLoad())
31 continue;
32
33 JitSpewHeader(JitSpew_AliasSummaries);
34 print.printf(" ");
35 MDefinition::PrintOpcodeName(print, def->op());
36 print.printf("%d marked depending on ", def->id());
37 MDefinition::PrintOpcodeName(print, def->dependency()->op());
38 print.printf("%d\n", def->dependency()->id());
39 }
40 }
41 }
42 #endif
43 }
44
45 // Unwrap any slot or element to its corresponding object.
46 static inline const MDefinition*
MaybeUnwrap(const MDefinition * object)47 MaybeUnwrap(const MDefinition* object)
48 {
49
50 while (object->isSlots() || object->isElements() || object->isConvertElementsToDoubles()) {
51 MOZ_ASSERT(object->numOperands() == 1);
52 object = object->getOperand(0);
53 }
54
55 if (object->isTypedArrayElements())
56 return nullptr;
57 if (object->isTypedObjectElements())
58 return nullptr;
59 if (object->isConstantElements())
60 return nullptr;
61
62 return object;
63 }
64
65 // Get the object of any load/store. Returns nullptr if not tied to
66 // an object.
67 static inline const MDefinition*
GetObject(const MDefinition * ins)68 GetObject(const MDefinition* ins)
69 {
70 if (!ins->getAliasSet().isStore() && !ins->getAliasSet().isLoad())
71 return nullptr;
72
73 // Note: only return the object if that objects owns that property.
74 // I.e. the poperty isn't on the prototype chain.
75 const MDefinition* object = nullptr;
76 switch (ins->op()) {
77 case MDefinition::Op_InitializedLength:
78 case MDefinition::Op_LoadElement:
79 case MDefinition::Op_LoadUnboxedScalar:
80 case MDefinition::Op_LoadUnboxedObjectOrNull:
81 case MDefinition::Op_LoadUnboxedString:
82 case MDefinition::Op_StoreElement:
83 case MDefinition::Op_StoreUnboxedObjectOrNull:
84 case MDefinition::Op_StoreUnboxedString:
85 case MDefinition::Op_StoreUnboxedScalar:
86 case MDefinition::Op_SetInitializedLength:
87 case MDefinition::Op_ArrayLength:
88 case MDefinition::Op_SetArrayLength:
89 case MDefinition::Op_StoreElementHole:
90 case MDefinition::Op_FallibleStoreElement:
91 case MDefinition::Op_TypedObjectDescr:
92 case MDefinition::Op_Slots:
93 case MDefinition::Op_Elements:
94 case MDefinition::Op_MaybeCopyElementsForWrite:
95 case MDefinition::Op_MaybeToDoubleElement:
96 case MDefinition::Op_UnboxedArrayLength:
97 case MDefinition::Op_UnboxedArrayInitializedLength:
98 case MDefinition::Op_IncrementUnboxedArrayInitializedLength:
99 case MDefinition::Op_SetUnboxedArrayInitializedLength:
100 case MDefinition::Op_TypedArrayLength:
101 case MDefinition::Op_SetTypedObjectOffset:
102 case MDefinition::Op_SetDisjointTypedElements:
103 case MDefinition::Op_ArrayPopShift:
104 case MDefinition::Op_ArrayPush:
105 case MDefinition::Op_ArraySlice:
106 case MDefinition::Op_LoadTypedArrayElementHole:
107 case MDefinition::Op_StoreTypedArrayElementHole:
108 case MDefinition::Op_LoadFixedSlot:
109 case MDefinition::Op_LoadFixedSlotAndUnbox:
110 case MDefinition::Op_StoreFixedSlot:
111 case MDefinition::Op_GetPropertyPolymorphic:
112 case MDefinition::Op_SetPropertyPolymorphic:
113 case MDefinition::Op_GuardShape:
114 case MDefinition::Op_GuardReceiverPolymorphic:
115 case MDefinition::Op_GuardObjectGroup:
116 case MDefinition::Op_GuardObjectIdentity:
117 case MDefinition::Op_GuardClass:
118 case MDefinition::Op_GuardUnboxedExpando:
119 case MDefinition::Op_LoadUnboxedExpando:
120 case MDefinition::Op_LoadSlot:
121 case MDefinition::Op_StoreSlot:
122 case MDefinition::Op_InArray:
123 case MDefinition::Op_LoadElementHole:
124 case MDefinition::Op_TypedArrayElements:
125 case MDefinition::Op_TypedObjectElements:
126 object = ins->getOperand(0);
127 break;
128 case MDefinition::Op_GetPropertyCache:
129 case MDefinition::Op_LoadTypedArrayElementStatic:
130 case MDefinition::Op_StoreTypedArrayElementStatic:
131 case MDefinition::Op_GetDOMProperty:
132 case MDefinition::Op_GetDOMMember:
133 case MDefinition::Op_Call:
134 case MDefinition::Op_Compare:
135 case MDefinition::Op_GetArgumentsObjectArg:
136 case MDefinition::Op_SetArgumentsObjectArg:
137 case MDefinition::Op_GetFrameArgument:
138 case MDefinition::Op_SetFrameArgument:
139 case MDefinition::Op_CompareExchangeTypedArrayElement:
140 case MDefinition::Op_AtomicExchangeTypedArrayElement:
141 case MDefinition::Op_AtomicTypedArrayElementBinop:
142 case MDefinition::Op_AsmJSLoadHeap:
143 case MDefinition::Op_AsmJSStoreHeap:
144 case MDefinition::Op_WasmLoad:
145 case MDefinition::Op_WasmStore:
146 case MDefinition::Op_AsmJSCompareExchangeHeap:
147 case MDefinition::Op_AsmJSAtomicBinopHeap:
148 case MDefinition::Op_WasmLoadGlobalVar:
149 case MDefinition::Op_WasmStoreGlobalVar:
150 case MDefinition::Op_ArrayJoin:
151 return nullptr;
152 default:
153 #ifdef DEBUG
154 // Crash when the default aliasSet is overriden, but when not added in the list above.
155 if (!ins->getAliasSet().isStore() || ins->getAliasSet().flags() != AliasSet::Flag::Any)
156 MOZ_CRASH("Overridden getAliasSet without updating AliasAnalysisShared GetObject");
157 #endif
158
159 return nullptr;
160 }
161
162 MOZ_ASSERT(!ins->getAliasSet().isStore() || ins->getAliasSet().flags() != AliasSet::Flag::Any);
163 object = MaybeUnwrap(object);
164 MOZ_ASSERT_IF(object, object->type() == MIRType::Object);
165 return object;
166 }
167
168 // Generic comparing if a load aliases a store using TI information.
169 MDefinition::AliasType
genericMightAlias(const MDefinition * load,const MDefinition * store)170 AliasAnalysisShared::genericMightAlias(const MDefinition* load, const MDefinition* store)
171 {
172 const MDefinition* loadObject = GetObject(load);
173 const MDefinition* storeObject = GetObject(store);
174 if (!loadObject || !storeObject)
175 return MDefinition::AliasType::MayAlias;
176
177 if (!loadObject->resultTypeSet() || !storeObject->resultTypeSet())
178 return MDefinition::AliasType::MayAlias;
179
180 if (loadObject->resultTypeSet()->objectsIntersect(storeObject->resultTypeSet()))
181 return MDefinition::AliasType::MayAlias;
182
183 return MDefinition::AliasType::NoAlias;
184 }
185
186
187 } // namespace jit
188 } // namespace js
189