Line data Source code
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/EagerSimdUnbox.h"
8 :
9 : #include "jit/MIR.h"
10 : #include "jit/MIRGenerator.h"
11 : #include "jit/MIRGraph.h"
12 :
13 : namespace js {
14 : namespace jit {
15 :
16 : // Do not optimize any Phi instruction which has conflicting Unbox operations,
17 : // as this might imply some intended polymorphism.
18 : static bool
19 0 : CanUnboxSimdPhi(const JitCompartment* jitCompartment, MPhi* phi, SimdType unboxType)
20 : {
21 0 : MOZ_ASSERT(phi->type() == MIRType::Object);
22 :
23 : // If we are unboxing, we are more than likely to have boxed this SIMD type
24 : // once in baseline, otherwise, we cannot create a MSimdBox as we have no
25 : // template object to use.
26 0 : if (!jitCompartment->maybeGetSimdTemplateObjectFor(unboxType))
27 0 : return false;
28 :
29 0 : MResumePoint* entry = phi->block()->entryResumePoint();
30 0 : MIRType mirType = SimdTypeToMIRType(unboxType);
31 0 : for (MUseIterator i(phi->usesBegin()), e(phi->usesEnd()); i != e; i++) {
32 : // If we cannot recover the Simd object at the entry of the basic block,
33 : // then we would have to box the content anyways.
34 0 : if ((*i)->consumer() == entry && !entry->isRecoverableOperand(*i))
35 0 : return false;
36 :
37 0 : if (!(*i)->consumer()->isDefinition())
38 0 : continue;
39 :
40 0 : MDefinition* def = (*i)->consumer()->toDefinition();
41 0 : if (def->isSimdUnbox() && def->toSimdUnbox()->type() != mirType)
42 0 : return false;
43 : }
44 :
45 0 : return true;
46 : }
47 :
48 : static void
49 0 : UnboxSimdPhi(const JitCompartment* jitCompartment, MIRGraph& graph, MPhi* phi, SimdType unboxType)
50 : {
51 0 : TempAllocator& alloc = graph.alloc();
52 :
53 : // Unbox and replace all operands.
54 0 : for (size_t i = 0, e = phi->numOperands(); i < e; i++) {
55 0 : MDefinition* op = phi->getOperand(i);
56 0 : MSimdUnbox* unbox = MSimdUnbox::New(alloc, op, unboxType);
57 0 : op->block()->insertAtEnd(unbox);
58 0 : phi->replaceOperand(i, unbox);
59 : }
60 :
61 : // Change the MIRType of the Phi.
62 0 : MIRType mirType = SimdTypeToMIRType(unboxType);
63 0 : phi->setResultType(mirType);
64 :
65 0 : MBasicBlock* phiBlock = phi->block();
66 0 : MInstruction* atRecover = phiBlock->safeInsertTop(nullptr, MBasicBlock::IgnoreRecover);
67 0 : MInstruction* at = phiBlock->safeInsertTop(atRecover);
68 :
69 : // Note, we capture the uses-list now, as new instructions are not visited.
70 0 : MUseIterator i(phi->usesBegin()), e(phi->usesEnd());
71 :
72 : // Add a MSimdBox, and replace all the Phi uses with it.
73 0 : JSObject* templateObject = jitCompartment->maybeGetSimdTemplateObjectFor(unboxType);
74 0 : InlineTypedObject* inlineTypedObject = &templateObject->as<InlineTypedObject>();
75 0 : MSimdBox* recoverBox = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, unboxType, gc::DefaultHeap);
76 0 : recoverBox->setRecoveredOnBailout();
77 0 : phiBlock->insertBefore(atRecover, recoverBox);
78 :
79 0 : MSimdBox* box = nullptr;
80 0 : while (i != e) {
81 0 : MUse* use = *i++;
82 0 : MNode* ins = use->consumer();
83 :
84 0 : if ((ins->isDefinition() && ins->toDefinition()->isRecoveredOnBailout()) ||
85 0 : (ins->isResumePoint() && ins->toResumePoint()->isRecoverableOperand(use)))
86 : {
87 0 : use->replaceProducer(recoverBox);
88 0 : continue;
89 : }
90 :
91 0 : if (!box) {
92 0 : box = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, unboxType, gc::DefaultHeap);
93 0 : phiBlock->insertBefore(at, box);
94 : }
95 :
96 0 : use->replaceProducer(box);
97 : }
98 0 : }
99 :
100 : bool
101 8 : EagerSimdUnbox(MIRGenerator* mir, MIRGraph& graph)
102 : {
103 8 : const JitCompartment* jitCompartment = GetJitContext()->compartment->jitCompartment();
104 461 : for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) {
105 453 : if (mir->shouldCancel("Eager Simd Unbox"))
106 0 : return false;
107 :
108 2987 : for (MInstructionReverseIterator ins = block->rbegin(); ins != block->rend(); ins++) {
109 2534 : if (!ins->isSimdUnbox())
110 2534 : continue;
111 :
112 0 : MSimdUnbox* unbox = ins->toSimdUnbox();
113 0 : if (!unbox->input()->isPhi())
114 0 : continue;
115 :
116 0 : MPhi* phi = unbox->input()->toPhi();
117 0 : if (!CanUnboxSimdPhi(jitCompartment, phi, unbox->simdType()))
118 0 : continue;
119 :
120 0 : UnboxSimdPhi(jitCompartment, graph, phi, unbox->simdType());
121 : }
122 : }
123 :
124 8 : return true;
125 : }
126 :
127 : } /* namespace jit */
128 : } /* namespace js */
|