summaryrefslogtreecommitdiffstats
path: root/js/src/jit/EagerSimdUnbox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/EagerSimdUnbox.cpp')
-rw-r--r--js/src/jit/EagerSimdUnbox.cpp128
1 files changed, 128 insertions, 0 deletions
diff --git a/js/src/jit/EagerSimdUnbox.cpp b/js/src/jit/EagerSimdUnbox.cpp
new file mode 100644
index 000000000..0b93d145d
--- /dev/null
+++ b/js/src/jit/EagerSimdUnbox.cpp
@@ -0,0 +1,128 @@
+/* -*- 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/EagerSimdUnbox.h"
+
+#include "jit/MIR.h"
+#include "jit/MIRGenerator.h"
+#include "jit/MIRGraph.h"
+
+namespace js {
+namespace jit {
+
+// Do not optimize any Phi instruction which has conflicting Unbox operations,
+// as this might imply some intended polymorphism.
+static bool
+CanUnboxSimdPhi(const JitCompartment* jitCompartment, MPhi* phi, SimdType unboxType)
+{
+ MOZ_ASSERT(phi->type() == MIRType::Object);
+
+ // If we are unboxing, we are more than likely to have boxed this SIMD type
+ // once in baseline, otherwise, we cannot create a MSimdBox as we have no
+ // template object to use.
+ if (!jitCompartment->maybeGetSimdTemplateObjectFor(unboxType))
+ return false;
+
+ MResumePoint* entry = phi->block()->entryResumePoint();
+ MIRType mirType = SimdTypeToMIRType(unboxType);
+ for (MUseIterator i(phi->usesBegin()), e(phi->usesEnd()); i != e; i++) {
+ // If we cannot recover the Simd object at the entry of the basic block,
+ // then we would have to box the content anyways.
+ if ((*i)->consumer() == entry && !entry->isRecoverableOperand(*i))
+ return false;
+
+ if (!(*i)->consumer()->isDefinition())
+ continue;
+
+ MDefinition* def = (*i)->consumer()->toDefinition();
+ if (def->isSimdUnbox() && def->toSimdUnbox()->type() != mirType)
+ return false;
+ }
+
+ return true;
+}
+
+static void
+UnboxSimdPhi(const JitCompartment* jitCompartment, MIRGraph& graph, MPhi* phi, SimdType unboxType)
+{
+ TempAllocator& alloc = graph.alloc();
+
+ // Unbox and replace all operands.
+ for (size_t i = 0, e = phi->numOperands(); i < e; i++) {
+ MDefinition* op = phi->getOperand(i);
+ MSimdUnbox* unbox = MSimdUnbox::New(alloc, op, unboxType);
+ op->block()->insertAtEnd(unbox);
+ phi->replaceOperand(i, unbox);
+ }
+
+ // Change the MIRType of the Phi.
+ MIRType mirType = SimdTypeToMIRType(unboxType);
+ phi->setResultType(mirType);
+
+ MBasicBlock* phiBlock = phi->block();
+ MInstruction* atRecover = phiBlock->safeInsertTop(nullptr, MBasicBlock::IgnoreRecover);
+ MInstruction* at = phiBlock->safeInsertTop(atRecover);
+
+ // Note, we capture the uses-list now, as new instructions are not visited.
+ MUseIterator i(phi->usesBegin()), e(phi->usesEnd());
+
+ // Add a MSimdBox, and replace all the Phi uses with it.
+ JSObject* templateObject = jitCompartment->maybeGetSimdTemplateObjectFor(unboxType);
+ InlineTypedObject* inlineTypedObject = &templateObject->as<InlineTypedObject>();
+ MSimdBox* recoverBox = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, unboxType, gc::DefaultHeap);
+ recoverBox->setRecoveredOnBailout();
+ phiBlock->insertBefore(atRecover, recoverBox);
+
+ MSimdBox* box = nullptr;
+ while (i != e) {
+ MUse* use = *i++;
+ MNode* ins = use->consumer();
+
+ if ((ins->isDefinition() && ins->toDefinition()->isRecoveredOnBailout()) ||
+ (ins->isResumePoint() && ins->toResumePoint()->isRecoverableOperand(use)))
+ {
+ use->replaceProducer(recoverBox);
+ continue;
+ }
+
+ if (!box) {
+ box = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, unboxType, gc::DefaultHeap);
+ phiBlock->insertBefore(at, box);
+ }
+
+ use->replaceProducer(box);
+ }
+}
+
+bool
+EagerSimdUnbox(MIRGenerator* mir, MIRGraph& graph)
+{
+ const JitCompartment* jitCompartment = GetJitContext()->compartment->jitCompartment();
+ for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) {
+ if (mir->shouldCancel("Eager Simd Unbox"))
+ return false;
+
+ for (MInstructionReverseIterator ins = block->rbegin(); ins != block->rend(); ins++) {
+ if (!ins->isSimdUnbox())
+ continue;
+
+ MSimdUnbox* unbox = ins->toSimdUnbox();
+ if (!unbox->input()->isPhi())
+ continue;
+
+ MPhi* phi = unbox->input()->toPhi();
+ if (!CanUnboxSimdPhi(jitCompartment, phi, unbox->simdType()))
+ continue;
+
+ UnboxSimdPhi(jitCompartment, graph, phi, unbox->simdType());
+ }
+ }
+
+ return true;
+}
+
+} /* namespace jit */
+} /* namespace js */