Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
7 #include "jit/shared/Lowering-shared-inl.h"
9 #include "jit/LIR.h"
10 #include "jit/MIR.h"
12 using namespace js;
13 using namespace jit;
15 bool
16 LIRGeneratorShared::visitConstant(MConstant *ins)
17 {
18 const Value &v = ins->value();
19 switch (ins->type()) {
20 case MIRType_Boolean:
21 return define(new(alloc()) LInteger(v.toBoolean()), ins);
22 case MIRType_Int32:
23 return define(new(alloc()) LInteger(v.toInt32()), ins);
24 case MIRType_String:
25 return define(new(alloc()) LPointer(v.toString()), ins);
26 case MIRType_Object:
27 return define(new(alloc()) LPointer(&v.toObject()), ins);
28 default:
29 // Constants of special types (undefined, null) should never flow into
30 // here directly. Operations blindly consuming them require a Box.
31 JS_ASSERT(!"unexpected constant type");
32 return false;
33 }
34 }
36 bool
37 LIRGeneratorShared::defineTypedPhi(MPhi *phi, size_t lirIndex)
38 {
39 LPhi *lir = current->getPhi(lirIndex);
41 uint32_t vreg = getVirtualRegister();
42 if (vreg >= MAX_VIRTUAL_REGISTERS)
43 return false;
45 phi->setVirtualRegister(vreg);
46 lir->setDef(0, LDefinition(vreg, LDefinition::TypeFrom(phi->type())));
47 annotate(lir);
48 return true;
49 }
51 void
52 LIRGeneratorShared::lowerTypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex)
53 {
54 MDefinition *operand = phi->getOperand(inputPosition);
55 LPhi *lir = block->getPhi(lirIndex);
56 lir->setOperand(inputPosition, LUse(operand->virtualRegister(), LUse::ANY));
57 }
59 LRecoverInfo *
60 LIRGeneratorShared::getRecoverInfo(MResumePoint *rp)
61 {
62 if (cachedRecoverInfo_ && cachedRecoverInfo_->mir() == rp)
63 return cachedRecoverInfo_;
65 LRecoverInfo *recoverInfo = LRecoverInfo::New(gen, rp);
66 if (!recoverInfo)
67 return nullptr;
69 cachedRecoverInfo_ = recoverInfo;
70 return recoverInfo;
71 }
73 #ifdef JS_NUNBOX32
74 LSnapshot *
75 LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind)
76 {
77 LRecoverInfo *recover = getRecoverInfo(rp);
78 if (!recover)
79 return nullptr;
81 LSnapshot *snapshot = LSnapshot::New(gen, recover, kind);
82 if (!snapshot)
83 return nullptr;
85 size_t i = 0;
86 for (MResumePoint **it = recover->begin(), **end = recover->end(); it != end; ++it) {
87 MResumePoint *mir = *it;
88 for (size_t j = 0, e = mir->numOperands(); j < e; ++i, ++j) {
89 MDefinition *ins = mir->getOperand(j);
91 LAllocation *type = snapshot->typeOfSlot(i);
92 LAllocation *payload = snapshot->payloadOfSlot(i);
94 if (ins->isBox())
95 ins = ins->toBox()->getOperand(0);
97 // Guards should never be eliminated.
98 JS_ASSERT_IF(ins->isUnused(), !ins->isGuard());
100 // Snapshot operands other than constants should never be
101 // emitted-at-uses. Try-catch support depends on there being no
102 // code between an instruction and the LOsiPoint that follows it.
103 JS_ASSERT_IF(!ins->isConstant(), !ins->isEmittedAtUses());
105 // The register allocation will fill these fields in with actual
106 // register/stack assignments. During code generation, we can restore
107 // interpreter state with the given information. Note that for
108 // constants, including known types, we record a dummy placeholder,
109 // since we can recover the same information, much cleaner, from MIR.
110 if (ins->isConstant() || ins->isUnused()) {
111 *type = LConstantIndex::Bogus();
112 *payload = LConstantIndex::Bogus();
113 } else if (ins->type() != MIRType_Value) {
114 *type = LConstantIndex::Bogus();
115 *payload = use(ins, LUse::KEEPALIVE);
116 } else {
117 *type = useType(ins, LUse::KEEPALIVE);
118 *payload = usePayload(ins, LUse::KEEPALIVE);
119 }
120 }
121 }
123 return snapshot;
124 }
126 #elif JS_PUNBOX64
128 LSnapshot *
129 LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind)
130 {
131 LRecoverInfo *recover = getRecoverInfo(rp);
132 if (!recover)
133 return nullptr;
135 LSnapshot *snapshot = LSnapshot::New(gen, recover, kind);
136 if (!snapshot)
137 return nullptr;
139 size_t i = 0;
140 for (MResumePoint **it = recover->begin(), **end = recover->end(); it != end; ++it) {
141 MResumePoint *mir = *it;
142 for (size_t j = 0, e = mir->numOperands(); j < e; ++i, ++j) {
143 MDefinition *def = mir->getOperand(j);
145 if (def->isBox())
146 def = def->toBox()->getOperand(0);
148 // Guards should never be eliminated.
149 JS_ASSERT_IF(def->isUnused(), !def->isGuard());
151 // Snapshot operands other than constants should never be
152 // emitted-at-uses. Try-catch support depends on there being no
153 // code between an instruction and the LOsiPoint that follows it.
154 JS_ASSERT_IF(!def->isConstant(), !def->isEmittedAtUses());
156 LAllocation *a = snapshot->getEntry(i);
158 if (def->isUnused()) {
159 *a = LConstantIndex::Bogus();
160 continue;
161 }
163 *a = useKeepaliveOrConstant(def);
164 }
165 }
167 return snapshot;
168 }
169 #endif
171 bool
172 LIRGeneratorShared::assignSnapshot(LInstruction *ins, BailoutKind kind)
173 {
174 // assignSnapshot must be called before define/add, since
175 // it may add new instructions for emitted-at-use operands.
176 JS_ASSERT(ins->id() == 0);
178 LSnapshot *snapshot = buildSnapshot(ins, lastResumePoint_, kind);
179 if (!snapshot)
180 return false;
182 ins->assignSnapshot(snapshot);
183 return true;
184 }
186 bool
187 LIRGeneratorShared::assignSafepoint(LInstruction *ins, MInstruction *mir)
188 {
189 JS_ASSERT(!osiPoint_);
190 JS_ASSERT(!ins->safepoint());
192 ins->initSafepoint(alloc());
194 MResumePoint *mrp = mir->resumePoint() ? mir->resumePoint() : lastResumePoint_;
195 LSnapshot *postSnapshot = buildSnapshot(ins, mrp, Bailout_Normal);
196 if (!postSnapshot)
197 return false;
199 osiPoint_ = new(alloc()) LOsiPoint(ins->safepoint(), postSnapshot);
201 return lirGraph_.noteNeedsSafepoint(ins);
202 }