mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-06-24 07:29:44 +00:00
140 lines
4.7 KiB
C++
140 lines
4.7 KiB
C++
/* -*- 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 {
|
|
|
|
static SimdTypeDescr::Type
|
|
MIRTypeToSimdTypeDescr(MIRType type)
|
|
{
|
|
MOZ_ASSERT(IsSimdType(type));
|
|
switch (type) {
|
|
case MIRType_Float32x4: return SimdTypeDescr::Float32x4;
|
|
case MIRType_Int32x4: return SimdTypeDescr::Int32x4;
|
|
default: break;
|
|
}
|
|
MOZ_CRASH("unexpected MIRType");
|
|
}
|
|
|
|
// 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, MIRType 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(MIRTypeToSimdTypeDescr(unboxType)))
|
|
return false;
|
|
|
|
MResumePoint* entry = phi->block()->entryResumePoint();
|
|
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() != unboxType)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static void
|
|
UnboxSimdPhi(const JitCompartment* jitCompartment, MIRGraph& graph, MPhi* phi, MIRType 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.
|
|
phi->setResultType(unboxType);
|
|
|
|
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(MIRTypeToSimdTypeDescr(unboxType));
|
|
InlineTypedObject* inlineTypedObject = &templateObject->as<InlineTypedObject>();
|
|
MSimdBox* recoverBox = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, 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, 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->type()))
|
|
continue;
|
|
|
|
UnboxSimdPhi(jitCompartment, graph, phi, unbox->type());
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} /* namespace jit */
|
|
} /* namespace js */
|