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