diff options
Diffstat (limited to 'js/src/jit/AliasAnalysisShared.cpp')
-rw-r--r-- | js/src/jit/AliasAnalysisShared.cpp | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/js/src/jit/AliasAnalysisShared.cpp b/js/src/jit/AliasAnalysisShared.cpp new file mode 100644 index 000000000..ae28327ca --- /dev/null +++ b/js/src/jit/AliasAnalysisShared.cpp @@ -0,0 +1,188 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "jit/AliasAnalysisShared.h" + +#include "jit/MIR.h" + +namespace js { +namespace jit { + +void +AliasAnalysisShared::spewDependencyList() +{ +#ifdef JS_JITSPEW + if (JitSpewEnabled(JitSpew_AliasSummaries)) { + Fprinter &print = JitSpewPrinter(); + JitSpewHeader(JitSpew_AliasSummaries); + print.printf("Dependency list for other passes:\n"); + + for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) { + for (MInstructionIterator def(block->begin()), end(block->begin(block->lastIns())); + def != end; + ++def) + { + if (!def->dependency()) + continue; + if (!def->getAliasSet().isLoad()) + continue; + + JitSpewHeader(JitSpew_AliasSummaries); + print.printf(" "); + MDefinition::PrintOpcodeName(print, def->op()); + print.printf("%d marked depending on ", def->id()); + MDefinition::PrintOpcodeName(print, def->dependency()->op()); + print.printf("%d\n", def->dependency()->id()); + } + } + } +#endif +} + +// Unwrap any slot or element to its corresponding object. +static inline const MDefinition* +MaybeUnwrap(const MDefinition* object) +{ + + while (object->isSlots() || object->isElements() || object->isConvertElementsToDoubles()) { + MOZ_ASSERT(object->numOperands() == 1); + object = object->getOperand(0); + } + + if (object->isTypedArrayElements()) + return nullptr; + if (object->isTypedObjectElements()) + return nullptr; + if (object->isConstantElements()) + return nullptr; + + return object; +} + +// Get the object of any load/store. Returns nullptr if not tied to +// an object. +static inline const MDefinition* +GetObject(const MDefinition* ins) +{ + if (!ins->getAliasSet().isStore() && !ins->getAliasSet().isLoad()) + return nullptr; + + // Note: only return the object if that objects owns that property. + // I.e. the poperty isn't on the prototype chain. + const MDefinition* object = nullptr; + switch (ins->op()) { + case MDefinition::Op_InitializedLength: + case MDefinition::Op_LoadElement: + case MDefinition::Op_LoadUnboxedScalar: + case MDefinition::Op_LoadUnboxedObjectOrNull: + case MDefinition::Op_LoadUnboxedString: + case MDefinition::Op_StoreElement: + case MDefinition::Op_StoreUnboxedObjectOrNull: + case MDefinition::Op_StoreUnboxedString: + case MDefinition::Op_StoreUnboxedScalar: + case MDefinition::Op_SetInitializedLength: + case MDefinition::Op_ArrayLength: + case MDefinition::Op_SetArrayLength: + case MDefinition::Op_StoreElementHole: + case MDefinition::Op_FallibleStoreElement: + case MDefinition::Op_TypedObjectDescr: + case MDefinition::Op_Slots: + case MDefinition::Op_Elements: + case MDefinition::Op_MaybeCopyElementsForWrite: + case MDefinition::Op_MaybeToDoubleElement: + case MDefinition::Op_UnboxedArrayLength: + case MDefinition::Op_UnboxedArrayInitializedLength: + case MDefinition::Op_IncrementUnboxedArrayInitializedLength: + case MDefinition::Op_SetUnboxedArrayInitializedLength: + case MDefinition::Op_TypedArrayLength: + case MDefinition::Op_SetTypedObjectOffset: + case MDefinition::Op_SetDisjointTypedElements: + case MDefinition::Op_ArrayPopShift: + case MDefinition::Op_ArrayPush: + case MDefinition::Op_ArraySlice: + case MDefinition::Op_LoadTypedArrayElementHole: + case MDefinition::Op_StoreTypedArrayElementHole: + case MDefinition::Op_LoadFixedSlot: + case MDefinition::Op_LoadFixedSlotAndUnbox: + case MDefinition::Op_StoreFixedSlot: + case MDefinition::Op_GetPropertyPolymorphic: + case MDefinition::Op_SetPropertyPolymorphic: + case MDefinition::Op_GuardShape: + case MDefinition::Op_GuardReceiverPolymorphic: + case MDefinition::Op_GuardObjectGroup: + case MDefinition::Op_GuardObjectIdentity: + case MDefinition::Op_GuardClass: + case MDefinition::Op_GuardUnboxedExpando: + case MDefinition::Op_LoadUnboxedExpando: + case MDefinition::Op_LoadSlot: + case MDefinition::Op_StoreSlot: + case MDefinition::Op_InArray: + case MDefinition::Op_LoadElementHole: + case MDefinition::Op_TypedArrayElements: + case MDefinition::Op_TypedObjectElements: + object = ins->getOperand(0); + break; + case MDefinition::Op_GetPropertyCache: + case MDefinition::Op_LoadTypedArrayElementStatic: + case MDefinition::Op_StoreTypedArrayElementStatic: + case MDefinition::Op_GetDOMProperty: + case MDefinition::Op_GetDOMMember: + case MDefinition::Op_Call: + case MDefinition::Op_Compare: + case MDefinition::Op_GetArgumentsObjectArg: + case MDefinition::Op_SetArgumentsObjectArg: + case MDefinition::Op_GetFrameArgument: + case MDefinition::Op_SetFrameArgument: + case MDefinition::Op_CompareExchangeTypedArrayElement: + case MDefinition::Op_AtomicExchangeTypedArrayElement: + case MDefinition::Op_AtomicTypedArrayElementBinop: + case MDefinition::Op_AsmJSLoadHeap: + case MDefinition::Op_AsmJSStoreHeap: + case MDefinition::Op_WasmLoad: + case MDefinition::Op_WasmStore: + case MDefinition::Op_AsmJSCompareExchangeHeap: + case MDefinition::Op_AsmJSAtomicBinopHeap: + case MDefinition::Op_WasmLoadGlobalVar: + case MDefinition::Op_WasmStoreGlobalVar: + case MDefinition::Op_ArrayJoin: + return nullptr; + default: +#ifdef DEBUG + // Crash when the default aliasSet is overriden, but when not added in the list above. + if (!ins->getAliasSet().isStore() || ins->getAliasSet().flags() != AliasSet::Flag::Any) + MOZ_CRASH("Overridden getAliasSet without updating AliasAnalysisShared GetObject"); +#endif + + return nullptr; + } + + MOZ_ASSERT(!ins->getAliasSet().isStore() || ins->getAliasSet().flags() != AliasSet::Flag::Any); + object = MaybeUnwrap(object); + MOZ_ASSERT_IF(object, object->type() == MIRType::Object); + return object; +} + +// Generic comparing if a load aliases a store using TI information. +MDefinition::AliasType +AliasAnalysisShared::genericMightAlias(const MDefinition* load, const MDefinition* store) +{ + const MDefinition* loadObject = GetObject(load); + const MDefinition* storeObject = GetObject(store); + if (!loadObject || !storeObject) + return MDefinition::AliasType::MayAlias; + + if (!loadObject->resultTypeSet() || !storeObject->resultTypeSet()) + return MDefinition::AliasType::MayAlias; + + if (loadObject->resultTypeSet()->objectsIntersect(storeObject->resultTypeSet())) + return MDefinition::AliasType::MayAlias; + + return MDefinition::AliasType::NoAlias; +} + + +} // namespace jit +} // namespace js |