summaryrefslogtreecommitdiffstats
path: root/js/src/jit/IonAnalysis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/IonAnalysis.cpp')
-rw-r--r--js/src/jit/IonAnalysis.cpp268
1 files changed, 0 insertions, 268 deletions
diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp
index 8bad8ba9c..a78ef232c 100644
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -1975,274 +1975,6 @@ jit::ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph)
return true;
}
-// Check if `def` is only the N-th operand of `useDef`.
-static inline size_t
-IsExclusiveNthOperand(MDefinition* useDef, size_t n, MDefinition* def)
-{
- uint32_t num = useDef->numOperands();
- if (n >= num || useDef->getOperand(n) != def)
- return false;
-
- for (uint32_t i = 0; i < num; i++) {
- if (i == n)
- continue;
- if (useDef->getOperand(i) == def)
- return false;
- }
-
- return true;
-}
-
-static size_t
-IsExclusiveThisArg(MCall* call, MDefinition* def)
-{
- return IsExclusiveNthOperand(call, MCall::IndexOfThis(), def);
-}
-
-static size_t
-IsExclusiveFirstArg(MCall* call, MDefinition* def)
-{
- return IsExclusiveNthOperand(call, MCall::IndexOfArgument(0), def);
-}
-
-static bool
-IsRegExpHoistableCall(MCall* call, MDefinition* def)
-{
- if (call->isConstructing())
- return false;
-
- JSAtom* name;
- if (WrappedFunction* fun = call->getSingleTarget()) {
- if (!fun->isSelfHostedBuiltin())
- return false;
- name = GetSelfHostedFunctionName(fun->rawJSFunction());
- } else {
- MDefinition* funDef = call->getFunction();
- if (funDef->isDebugCheckSelfHosted())
- funDef = funDef->toDebugCheckSelfHosted()->input();
- if (funDef->isTypeBarrier())
- funDef = funDef->toTypeBarrier()->input();
-
- if (!funDef->isCallGetIntrinsicValue())
- return false;
- name = funDef->toCallGetIntrinsicValue()->name();
- }
-
- // Hoistable only if the RegExp is the first argument of RegExpBuiltinExec.
- CompileRuntime* runtime = GetJitContext()->runtime;
- if (name == runtime->names().RegExpBuiltinExec ||
- name == runtime->names().UnwrapAndCallRegExpBuiltinExec ||
- name == runtime->names().RegExpMatcher ||
- name == runtime->names().RegExpTester ||
- name == runtime->names().RegExpSearcher)
- {
- return IsExclusiveFirstArg(call, def);
- }
-
- if (name == runtime->names().RegExp_prototype_Exec)
- return IsExclusiveThisArg(call, def);
-
- return false;
-}
-
-static bool
-CanCompareRegExp(MCompare* compare, MDefinition* def)
-{
- MDefinition* value;
- if (compare->lhs() == def) {
- value = compare->rhs();
- } else {
- MOZ_ASSERT(compare->rhs() == def);
- value = compare->lhs();
- }
-
- // Comparing two regexp that weren't cloned will give different result
- // than if they were cloned.
- if (value->mightBeType(MIRType::Object))
- return false;
-
- // Make sure @@toPrimitive is not called which could notice
- // the difference between a not cloned/cloned regexp.
-
- JSOp op = compare->jsop();
- // Strict equality comparison won't invoke @@toPrimitive.
- if (op == JSOP_STRICTEQ || op == JSOP_STRICTNE)
- return true;
-
- if (op != JSOP_EQ && op != JSOP_NE) {
- // Relational comparison always invoke @@toPrimitive.
- MOZ_ASSERT(op == JSOP_GT || op == JSOP_GE || op == JSOP_LT || op == JSOP_LE);
- return false;
- }
-
- // Loose equality comparison can invoke @@toPrimitive.
- if (value->mightBeType(MIRType::Boolean) || value->mightBeType(MIRType::String) ||
- value->mightBeType(MIRType::Int32) ||
- value->mightBeType(MIRType::Double) || value->mightBeType(MIRType::Float32) ||
- value->mightBeType(MIRType::Symbol))
- {
- return false;
- }
-
- return true;
-}
-
-static inline void
-SetNotInWorklist(MDefinitionVector& worklist)
-{
- for (size_t i = 0; i < worklist.length(); i++)
- worklist[i]->setNotInWorklist();
-}
-
-static bool
-IsRegExpHoistable(MIRGenerator* mir, MDefinition* regexp, MDefinitionVector& worklist,
- bool* hoistable)
-{
- MOZ_ASSERT(worklist.length() == 0);
-
- if (!worklist.append(regexp))
- return false;
- regexp->setInWorklist();
-
- for (size_t i = 0; i < worklist.length(); i++) {
- MDefinition* def = worklist[i];
- if (mir->shouldCancel("IsRegExpHoistable outer loop"))
- return false;
-
- for (MUseIterator use = def->usesBegin(); use != def->usesEnd(); use++) {
- if (mir->shouldCancel("IsRegExpHoistable inner loop"))
- return false;
-
- // Ignore resume points. At this point all uses are listed.
- // No DCE or GVN or something has happened.
- if (use->consumer()->isResumePoint())
- continue;
-
- MDefinition* useDef = use->consumer()->toDefinition();
-
- // Step through a few white-listed ops.
- if (useDef->isPhi() || useDef->isFilterTypeSet() || useDef->isGuardShape()) {
- if (useDef->isInWorklist())
- continue;
-
- if (!worklist.append(useDef))
- return false;
- useDef->setInWorklist();
- continue;
- }
-
- // Instructions that doesn't invoke unknown code that may modify
- // RegExp instance or pass it to elsewhere.
- if (useDef->isRegExpMatcher() || useDef->isRegExpTester() ||
- useDef->isRegExpSearcher())
- {
- if (IsExclusiveNthOperand(useDef, 0, def))
- continue;
- } else if (useDef->isLoadFixedSlot() || useDef->isTypeOf()) {
- continue;
- } else if (useDef->isCompare()) {
- if (CanCompareRegExp(useDef->toCompare(), def))
- continue;
- }
- // Instructions that modifies `lastIndex` property.
- else if (useDef->isStoreFixedSlot()) {
- if (IsExclusiveNthOperand(useDef, 0, def)) {
- MStoreFixedSlot* store = useDef->toStoreFixedSlot();
- if (store->slot() == RegExpObject::lastIndexSlot())
- continue;
- }
- } else if (useDef->isSetPropertyCache()) {
- if (IsExclusiveNthOperand(useDef, 0, def)) {
- MSetPropertyCache* setProp = useDef->toSetPropertyCache();
- if (setProp->idval()->isConstant()) {
- Value propIdVal = setProp->idval()->toConstant()->toJSValue();
- if (propIdVal.isString()) {
- CompileRuntime* runtime = GetJitContext()->runtime;
- if (propIdVal.toString() == runtime->names().lastIndex)
- continue;
- }
- }
- }
- }
- // MCall is safe only for some known safe functions.
- else if (useDef->isCall()) {
- if (IsRegExpHoistableCall(useDef->toCall(), def))
- continue;
- }
-
- // Everything else is unsafe.
- SetNotInWorklist(worklist);
- worklist.clear();
- *hoistable = false;
-
- return true;
- }
- }
-
- SetNotInWorklist(worklist);
- worklist.clear();
- *hoistable = true;
- return true;
-}
-
-bool
-jit::MakeMRegExpHoistable(MIRGenerator* mir, MIRGraph& graph)
-{
- // If we are compiling try blocks, regular expressions may be observable
- // from catch blocks (which Ion does not compile). For now just disable the
- // pass in this case.
- if (graph.hasTryBlock())
- return true;
-
- MDefinitionVector worklist(graph.alloc());
-
- for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
- if (mir->shouldCancel("MakeMRegExpHoistable outer loop"))
- return false;
-
- for (MDefinitionIterator iter(*block); iter; iter++) {
- if (!*iter)
- MOZ_CRASH("confirm bug 1263794.");
-
- if (mir->shouldCancel("MakeMRegExpHoistable inner loop"))
- return false;
-
- if (!iter->isRegExp())
- continue;
-
- MRegExp* regexp = iter->toRegExp();
-
- bool hoistable = false;
- if (!IsRegExpHoistable(mir, regexp, worklist, &hoistable))
- return false;
-
- if (!hoistable)
- continue;
-
- // Make MRegExp hoistable
- regexp->setMovable();
- regexp->setDoNotClone();
-
- // That would be incorrect for global/sticky, because lastIndex
- // could be wrong. Therefore setting the lastIndex to 0. That is
- // faster than a not movable regexp.
- RegExpObject* source = regexp->source();
- if (source->sticky() || source->global()) {
- if (!graph.alloc().ensureBallast())
- return false;
- MConstant* zero = MConstant::New(graph.alloc(), Int32Value(0));
- regexp->block()->insertAfter(regexp, zero);
-
- MStoreFixedSlot* lastIndex =
- MStoreFixedSlot::New(graph.alloc(), regexp, RegExpObject::lastIndexSlot(), zero);
- regexp->block()->insertAfter(zero, lastIndex);
- }
- }
- }
-
- return true;
-}
-
void
jit::RenumberBlocks(MIRGraph& graph)
{