1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
|
From 99641aa4446dc9df04dcfeede8b49ff03abcac42 Mon Sep 17 00:00:00 2001
From: Jan de Mooij <jdemooij@mozilla.com>
Date: Thu, 28 May 2015 10:16:24 +0200
Subject: [PATCH] Bug 1160884 - Add KeepAlive instructions after elements/slots
uses. r=nbp, a=abillings
---
js/src/jit/CodeGenerator.cpp | 7 ++
js/src/jit/CodeGenerator.h | 1 +
js/src/jit/Ion.cpp | 7 ++
js/src/jit/IonAnalysis.cpp | 112 ++++++++++++++++++++++++++++++++
js/src/jit/IonAnalysis.h | 3 +
js/src/jit/LIR-Common.h | 14 ++++
js/src/jit/LOpcodes.h | 1 +
js/src/jit/Lowering.cpp | 9 +++
js/src/jit/Lowering.h | 1 +
js/src/jit/MIR.h | 26 ++++++++
js/src/jit/MOpcodes.h | 1 +
js/src/jit/ParallelSafetyAnalysis.cpp | 1 +
js/src/jit/shared/Lowering-shared-inl.h | 8 ++-
js/src/jit/shared/Lowering-shared.h | 1 +
js/src/vm/TraceLogging.h | 3 +-
15 files changed, 193 insertions(+), 2 deletions(-)
diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index 5dff9df..7364178 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1476,6 +1476,13 @@ CodeGenerator::visitPointer(LPointer* lir)
}
bool
+CodeGenerator::visitKeepAliveObject(LKeepAliveObject* lir)
+{
+ // No-op.
+ return true;
+}
+
+bool
CodeGenerator::visitSlots(LSlots* lir)
{
Address slots(ToRegister(lir->object()), JSObject::offsetOfSlots());
diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h
index 95fb33b..e3b4fd7 100644
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -106,6 +106,7 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitLambdaForSingleton(LLambdaForSingleton* lir);
bool visitLambdaPar(LLambdaPar* lir);
bool visitPointer(LPointer* lir);
+ bool visitKeepAliveObject(LKeepAliveObject* lir);
bool visitSlots(LSlots* lir);
bool visitStoreSlotV(LStoreSlotV* store);
bool visitElements(LElements* lir);
diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp
index 015d387..1551a80 100644
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -1536,6 +1536,13 @@ OptimizeMIR(MIRGenerator* mir)
AssertGraphCoherency(graph);
}
+ if (!mir->compilingAsmJS()) {
+ AutoTraceLog log(logger, TraceLogger::AddKeepAliveInstructions);
+ AddKeepAliveInstructions(graph);
+ IonSpewPass("Add KeepAlive Instructions");
+ AssertGraphCoherency(graph);
+ }
+
return true;
}
diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp
index 8965724..af58aae 100644
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -1971,6 +1971,118 @@ jit::UnsplitEdges(LIRGraph* lir)
return true;
}
+static bool
+NeedsKeepAlive(MInstruction* slotsOrElements, MInstruction* use)
+{
+ MOZ_ASSERT(slotsOrElements->type() == MIRType_Elements ||
+ slotsOrElements->type() == MIRType_Slots);
+
+ if (slotsOrElements->block() != use->block())
+ return true;
+
+ MBasicBlock* block = use->block();
+ MInstructionIterator iter(block->begin(slotsOrElements));
+ MOZ_ASSERT(*iter == slotsOrElements);
+ ++iter;
+
+ while (true) {
+ if (*iter == use)
+ return false;
+
+ switch (iter->op()) {
+ case MDefinition::Op_Nop:
+ case MDefinition::Op_Constant:
+ case MDefinition::Op_KeepAliveObject:
+ case MDefinition::Op_Unbox:
+ case MDefinition::Op_LoadSlot:
+ case MDefinition::Op_StoreSlot:
+ case MDefinition::Op_LoadFixedSlot:
+ case MDefinition::Op_StoreFixedSlot:
+ case MDefinition::Op_LoadElement:
+ case MDefinition::Op_StoreElement:
+ case MDefinition::Op_InitializedLength:
+ case MDefinition::Op_ArrayLength:
+ case MDefinition::Op_BoundsCheck:
+ iter++;
+ break;
+ default:
+ return true;
+ }
+ }
+
+ MOZ_CRASH("Unreachable");
+}
+
+void
+jit::AddKeepAliveInstructions(MIRGraph& graph)
+{
+ for (MBasicBlockIterator i(graph.begin()); i != graph.end(); i++) {
+ MBasicBlock* block = *i;
+
+ for (MInstructionIterator insIter(block->begin()); insIter != block->end(); insIter++) {
+ MInstruction* ins = *insIter;
+ if (ins->type() != MIRType_Elements && ins->type() != MIRType_Slots)
+ continue;
+
+ MDefinition* ownerObject;
+ switch (ins->op()) {
+ case MDefinition::Op_ConstantElements:
+ case MDefinition::Op_NewSlots:
+ continue;
+ case MDefinition::Op_ConvertElementsToDoubles:
+ // EliminateRedundantChecks should have replaced all uses.
+ MOZ_ASSERT(!ins->hasUses());
+ continue;
+ case MDefinition::Op_Elements:
+ case MDefinition::Op_TypedArrayElements:
+ case MDefinition::Op_TypedObjectElements:
+ MOZ_ASSERT(ins->numOperands() == 1);
+ ownerObject = ins->getOperand(0);
+ break;
+ case MDefinition::Op_Slots:
+ ownerObject = ins->toSlots()->object();
+ break;
+ default:
+ MOZ_CRASH("Unexpected op");
+ }
+
+ MOZ_ASSERT(ownerObject->type() == MIRType_Object);
+
+ if (ownerObject->isConstant()) {
+ // Constants are kept alive by other pointers, for instance
+ // ImmGCPtr in JIT code.
+ continue;
+ }
+
+ for (MUseDefIterator uses(ins); uses; uses++) {
+ MInstruction* use = uses.def()->toInstruction();
+
+ if (use->isStoreElementHole()) {
+ // StoreElementHole has an explicit object operand. If GVN
+ // is disabled, we can get different unbox instructions with
+ // the same object as input, so we check for that case.
+ MOZ_ASSERT_IF(!use->toStoreElementHole()->object()->isUnbox() && !ownerObject->isUnbox(),
+ use->toStoreElementHole()->object() == ownerObject);
+ continue;
+ }
+
+ if (use->isInArray()) {
+ // See StoreElementHole case above.
+ MOZ_ASSERT_IF(!use->toInArray()->object()->isUnbox() && !ownerObject->isUnbox(),
+ use->toInArray()->object() == ownerObject);
+ continue;
+ }
+
+ if (!NeedsKeepAlive(ins, use))
+ continue;
+
+ MKeepAliveObject* keepAlive = MKeepAliveObject::New(graph.alloc(), ownerObject);
+ use->block()->insertAfter(use, keepAlive);
+ }
+ }
+ }
+}
+
bool
LinearSum::multiply(int32_t scale)
{
diff --git a/js/src/jit/IonAnalysis.h b/js/src/jit/IonAnalysis.h
index aabf835..a320418 100644
--- a/js/src/jit/IonAnalysis.h
+++ b/js/src/jit/IonAnalysis.h
@@ -64,6 +64,9 @@ AssertExtendedGraphCoherency(MIRGraph& graph);
bool
EliminateRedundantChecks(MIRGraph& graph);
+void
+AddKeepAliveInstructions(MIRGraph& graph);
+
bool
UnsplitEdges(LIRGraph* lir);
diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h
index 5fe0ee9..6b03a42 100644
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -3591,6 +3591,20 @@ class LImplicitThis : public LInstructionHelper<BOX_PIECES, 1, 0>
}
};
+class LKeepAliveObject : public LInstructionHelper<0, 1, 0>
+{
+ public:
+ LIR_HEADER(KeepAliveObject)
+
+ explicit LKeepAliveObject(const LAllocation& object) {
+ setOperand(0, object);
+ }
+
+ const LAllocation* object() {
+ return getOperand(0);
+ }
+};
+
// Load the "slots" member out of a JSObject.
// Input: JSObject pointer
// Output: slots pointer
diff --git a/js/src/jit/LOpcodes.h b/js/src/jit/LOpcodes.h
index cd7eef8..424b22c 100644
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -166,6 +166,7 @@
_(LambdaForSingleton) \
_(LambdaPar) \
_(ImplicitThis) \
+ _(KeepAliveObject) \
_(Slots) \
_(Elements) \
_(ConvertElementsToDoubles) \
diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp
index d671fd4..c0d434e 100644
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2110,6 +2110,15 @@ LIRGenerator::visitImplicitThis(MImplicitThis* ins)
}
bool
+LIRGenerator::visitKeepAliveObject(MKeepAliveObject* ins)
+{
+ MDefinition* obj = ins->object();
+ MOZ_ASSERT(obj->type() == MIRType_Object);
+
+ return add(new(alloc()) LKeepAliveObject(useKeepalive(obj)), ins);
+}
+
+bool
LIRGenerator::visitSlots(MSlots* ins)
{
return define(new(alloc()) LSlots(useRegisterAtStart(ins->object())), ins);
diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h
index ea50cab..a60dc30 100644
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -160,6 +160,7 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitLambdaArrow(MLambdaArrow* ins);
bool visitLambdaPar(MLambdaPar* ins);
bool visitImplicitThis(MImplicitThis* ins);
+ bool visitKeepAliveObject(MKeepAliveObject* ins);
bool visitSlots(MSlots* ins);
bool visitElements(MElements* ins);
bool visitConstantElements(MConstantElements* ins);
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index 48e1dfb..a6060a2 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -5790,6 +5790,32 @@ class MSetTypedObjectOffset
}
};
+class MKeepAliveObject
+ : public MUnaryInstruction,
+ public SingleObjectPolicy
+{
+ explicit MKeepAliveObject(MDefinition* object)
+ : MUnaryInstruction(object)
+ {
+ setResultType(MIRType_None);
+ setGuard();
+ }
+
+ public:
+ INSTRUCTION_HEADER(KeepAliveObject)
+
+ static MKeepAliveObject* New(TempAllocator& alloc, MDefinition* object) {
+ return new(alloc) MKeepAliveObject(object);
+ }
+
+ MDefinition* object() const {
+ return getOperand(0);
+ }
+ TypePolicy* typePolicy() {
+ return this;
+ }
+};
+
// Perform !-operation
class MNot
: public MUnaryInstruction,
diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h
index 83b9e63..cfc3895 100644
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -110,6 +110,7 @@ namespace jit {
_(Lambda) \
_(LambdaArrow) \
_(ImplicitThis) \
+ _(KeepAliveObject) \
_(Slots) \
_(Elements) \
_(ConstantElements) \
diff --git a/js/src/jit/ParallelSafetyAnalysis.cpp b/js/src/jit/ParallelSafetyAnalysis.cpp
index a6a1202..13c577b 100644
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -199,6 +199,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
CUSTOM_OP(Lambda)
UNSAFE_OP(LambdaArrow)
UNSAFE_OP(ImplicitThis)
+ SAFE_OP(KeepAliveObject)
SAFE_OP(Slots)
SAFE_OP(Elements)
SAFE_OP(ConstantElements)
diff --git a/js/src/jit/shared/Lowering-shared-inl.h b/js/src/jit/shared/Lowering-shared-inl.h
index 17bb74a..832cc61 100644
--- a/js/src/jit/shared/Lowering-shared-inl.h
+++ b/js/src/jit/shared/Lowering-shared-inl.h
@@ -372,11 +372,17 @@ LIRGeneratorShared::useStorableAtStart(MDefinition* mir)
#endif
LAllocation
+LIRGeneratorShared::useKeepalive(MDefinition* mir)
+{
+ return use(mir, LUse(LUse::KEEPALIVE));
+}
+
+LAllocation
LIRGeneratorShared::useKeepaliveOrConstant(MDefinition* mir)
{
if (mir->isConstant())
return LAllocation(mir->toConstant()->vp());
- return use(mir, LUse(LUse::KEEPALIVE));
+ return useKeepalive(mir);
}
LUse
diff --git a/js/src/jit/shared/Lowering-shared.h b/js/src/jit/shared/Lowering-shared.h
index 4bd13b0..b23d20e 100644
--- a/js/src/jit/shared/Lowering-shared.h
+++ b/js/src/jit/shared/Lowering-shared.h
@@ -85,6 +85,7 @@ class LIRGeneratorShared : public MInstructionVisitorWithDefaults
// this is a generic "things we can expect to write into memory in 1 instruction"
inline LAllocation useStorable(MDefinition* mir);
inline LAllocation useStorableAtStart(MDefinition* mir);
+ inline LAllocation useKeepalive(MDefinition* mir);
inline LAllocation useKeepaliveOrConstant(MDefinition* mir);
inline LAllocation useRegisterOrConstant(MDefinition* mir);
inline LAllocation useRegisterOrConstantAtStart(MDefinition* mir);
diff --git a/js/src/vm/TraceLogging.h b/js/src/vm/TraceLogging.h
index 4c2ebfe..8447679 100644
--- a/js/src/vm/TraceLogging.h
+++ b/js/src/vm/TraceLogging.h
@@ -145,7 +145,8 @@ namespace jit {
_(EffectiveAddressAnalysis) \
_(EliminateDeadCode) \
_(EdgeCaseAnalysis) \
- _(EliminateRedundantChecks)
+ _(EliminateRedundantChecks) \
+ _(AddKeepAliveInstructions)
class AutoTraceLog;
--
2.4.3
|