2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef DFGClobberize_h
27 #define DFGClobberize_h
31 #include "DFGAbstractHeap.h"
32 #include "DFGEdgeUsesStructure.h"
35 namespace JSC
{ namespace DFG
{
37 template<typename ReadFunctor
, typename WriteFunctor
>
38 void clobberizeForAllocation(ReadFunctor
& read
, WriteFunctor
& write
)
46 template<typename ReadFunctor
, typename WriteFunctor
>
47 void clobberize(Graph
& graph
, Node
* node
, ReadFunctor
& read
, WriteFunctor
& write
)
51 // - We cannot hoist, or sink, anything that has effects. This means that the
52 // easiest way of indicating that something cannot be hoisted is to claim
53 // that it side-effects some miscellaneous thing.
55 // - We cannot hoist forward-exiting nodes without some additional effort. I
56 // believe that what it comes down to is that forward-exiting generally have
57 // their NodeExitsForward cleared upon hoist, except for forward-exiting
58 // nodes that take bogus state as their input. Those are substantially
59 // harder. We disable it for now. In the future we could enable it by having
60 // versions of those nodes that backward-exit instead, but I'm not convinced
63 // - Some nodes lie, and claim that they do not read the JSCell_structureID, JSCell_typeInfoFlags, etc.
64 // These are nodes that use the structure in a way that does not depend on
65 // things that change under structure transitions.
67 // - It's implicitly understood that OSR exits read the world. This is why we
68 // generally don't move or eliminate stores. Every node can exit, so the
69 // read set does not reflect things that would be read if we exited.
70 // Instead, the read set reflects what the node will have to read if it
73 // - Broadly, we don't say that we're reading something if that something is
76 // - We try to make this work even prior to type inference, just so that we
77 // can use it for IR dumps. No promises on whether the answers are sound
78 // prior to type inference - though they probably could be if we did some
81 if (edgesUseStructure(graph
, node
))
82 read(JSCell_structureID
);
116 case StringCharCodeAt
:
117 case StringFromCharCode
:
118 case CompareEqConstant
:
119 case CompareStrictEq
:
125 case ExtractOSREntryLocal
:
127 case ConstantStoragePointer
:
134 case BooleanToNumber
:
145 case PhantomArguments
:
153 case CheckTierUpInLoop
:
154 case CheckTierUpAtReturn
:
155 case CheckTierUpAndOSREnter
:
157 case InvalidationPoint
:
159 case ProfileWillCall
:
164 case VariableWatchpoint
:
165 case TypedArrayWatchpoint
:
166 read(Watchpoint_fire
);
171 write(Watchpoint_fire
);
175 case CreateActivation
:
176 case CreateArguments
:
177 clobberizeForAllocation(read
, write
);
179 write(Watchpoint_fire
);
182 case FunctionReentryWatchpoint
:
183 read(Watchpoint_fire
);
189 clobberizeForAllocation(read
, write
);
192 case VarInjectionWatchpoint
:
193 case AllocationProfileWatchpoint
:
211 case GetMyArgumentsLengthSafe
:
212 case GetMyArgumentByValSafe
:
219 read(AbstractHeap(Variables
, JSStack::Callee
));
224 read(AbstractHeap(Variables
, node
->local()));
228 write(AbstractHeap(Variables
, node
->local()));
231 case GetLocalUnlinked
:
232 read(AbstractHeap(Variables
, node
->unlinkedLocal()));
236 ArrayMode mode
= node
->arrayMode();
237 switch (mode
.type()) {
238 case Array::SelectUsingPredictions
:
239 case Array::Unprofiled
:
240 case Array::Undecided
:
241 // Assume the worst since we don't have profiling yet.
246 case Array::ForceExit
:
256 if (mode
.isOutOfBounds()) {
261 // This appears to read nothing because it's only reading immutable data.
264 case Array::Arguments
:
265 read(Arguments_registers
);
270 if (mode
.isInBounds()) {
271 read(Butterfly_publicLength
);
272 read(Butterfly_vectorLength
);
273 read(IndexedInt32Properties
);
281 if (mode
.isInBounds()) {
282 read(Butterfly_publicLength
);
283 read(Butterfly_vectorLength
);
284 read(IndexedDoubleProperties
);
291 case Array::Contiguous
:
292 if (mode
.isInBounds()) {
293 read(Butterfly_publicLength
);
294 read(Butterfly_vectorLength
);
295 read(IndexedContiguousProperties
);
302 case Array::ArrayStorage
:
303 case Array::SlowPutArrayStorage
:
304 // Give up on life for now.
309 case Array::Int8Array
:
310 case Array::Int16Array
:
311 case Array::Int32Array
:
312 case Array::Uint8Array
:
313 case Array::Uint8ClampedArray
:
314 case Array::Uint16Array
:
315 case Array::Uint32Array
:
316 case Array::Float32Array
:
317 case Array::Float64Array
:
318 read(TypedArrayProperties
);
319 read(JSArrayBufferView_vector
);
320 read(JSArrayBufferView_length
);
323 RELEASE_ASSERT_NOT_REACHED();
329 case PutByValAlias
: {
330 ArrayMode mode
= node
->arrayMode();
331 switch (mode
.modeForPut().type()) {
332 case Array::SelectUsingPredictions
:
333 case Array::Unprofiled
:
334 case Array::Undecided
:
336 // Assume the worst since we don't have profiling yet.
341 case Array::ForceExit
:
350 case Array::Arguments
:
351 read(Arguments_registers
);
352 read(Arguments_numArguments
);
353 read(Arguments_slowArguments
);
358 if (node
->arrayMode().isOutOfBounds()) {
363 read(Butterfly_publicLength
);
364 read(Butterfly_vectorLength
);
365 read(IndexedInt32Properties
);
366 write(IndexedInt32Properties
);
370 if (node
->arrayMode().isOutOfBounds()) {
375 read(Butterfly_publicLength
);
376 read(Butterfly_vectorLength
);
377 read(IndexedDoubleProperties
);
378 write(IndexedDoubleProperties
);
381 case Array::Contiguous
:
382 if (node
->arrayMode().isOutOfBounds()) {
387 read(Butterfly_publicLength
);
388 read(Butterfly_vectorLength
);
389 read(IndexedContiguousProperties
);
390 write(IndexedContiguousProperties
);
393 case Array::ArrayStorage
:
394 case Array::SlowPutArrayStorage
:
395 // Give up on life for now.
400 case Array::Int8Array
:
401 case Array::Int16Array
:
402 case Array::Int32Array
:
403 case Array::Uint8Array
:
404 case Array::Uint8ClampedArray
:
405 case Array::Uint16Array
:
406 case Array::Uint32Array
:
407 case Array::Float32Array
:
408 case Array::Float64Array
:
409 read(JSArrayBufferView_vector
);
410 read(JSArrayBufferView_length
);
411 write(TypedArrayProperties
);
414 RELEASE_ASSERT_NOT_REACHED();
419 case StructureTransitionWatchpoint
:
421 read(JSCell_structureID
);
425 read(JSCell_indexingType
);
426 read(JSCell_typeInfoType
);
427 read(JSCell_structureID
);
430 case CheckHasInstance
:
431 read(JSCell_typeInfoFlags
);
434 case CheckExecutable
:
435 read(JSFunction_executable
);
439 case PhantomPutStructure
:
440 write(JSCell_structureID
);
441 write(JSCell_typeInfoType
);
442 write(JSCell_typeInfoFlags
);
443 write(JSCell_indexingType
);
446 case AllocatePropertyStorage
:
447 write(JSObject_butterfly
);
448 clobberizeForAllocation(read
, write
);
451 case ReallocatePropertyStorage
:
452 read(JSObject_butterfly
);
453 write(JSObject_butterfly
);
454 clobberizeForAllocation(read
, write
);
458 read(JSObject_butterfly
);
462 case ArrayifyToStructure
:
463 read(JSCell_structureID
);
464 read(JSCell_indexingType
);
465 read(JSObject_butterfly
);
466 write(JSCell_structureID
);
467 write(JSCell_indexingType
);
468 write(JSObject_butterfly
);
469 write(Watchpoint_fire
);
470 clobberizeForAllocation(read
, write
);
473 case GetIndexedPropertyStorage
:
474 if (node
->arrayMode().type() == Array::String
)
476 read(JSArrayBufferView_vector
);
479 case GetTypedArrayByteOffset
:
480 read(JSArrayBufferView_vector
);
481 read(JSArrayBufferView_mode
);
482 read(Butterfly_arrayBuffer
);
483 read(ArrayBuffer_data
);
487 read(AbstractHeap(NamedProperties
, graph
.m_storageAccessData
[node
->storageAccessDataIndex()].identifierNumber
));
490 case MultiGetByOffset
:
491 read(JSCell_structureID
);
492 read(JSObject_butterfly
);
493 read(AbstractHeap(NamedProperties
, node
->multiGetByOffsetData().identifierNumber
));
496 case MultiPutByOffset
:
497 read(JSCell_structureID
);
498 read(JSObject_butterfly
);
499 write(AbstractHeap(NamedProperties
, node
->multiPutByOffsetData().identifierNumber
));
500 if (node
->multiPutByOffsetData().writesStructures())
501 write(JSCell_structureID
);
502 if (node
->multiPutByOffsetData().reallocatesStorage()) {
503 write(JSObject_butterfly
);
504 clobberizeForAllocation(read
, write
);
509 write(AbstractHeap(NamedProperties
, graph
.m_storageAccessData
[node
->storageAccessDataIndex()].identifierNumber
));
512 case GetArrayLength
: {
513 ArrayMode mode
= node
->arrayMode();
514 switch (mode
.type()) {
517 case Array::Contiguous
:
518 case Array::ArrayStorage
:
519 case Array::SlowPutArrayStorage
:
520 read(Butterfly_publicLength
);
526 case Array::Arguments
:
527 read(Arguments_overrideLength
);
528 read(Arguments_numArguments
);
532 read(JSArrayBufferView_length
);
538 read(AbstractHeap(Variables
, JSStack::ScopeChain
));
542 read(AbstractHeap(Variables
, graph
.activationRegister()));
545 case GetClosureRegisters
:
546 read(JSVariableObject_registers
);
550 read(AbstractHeap(Variables
, node
->varNumber()));
554 write(AbstractHeap(Variables
, node
->varNumber()));
558 read(AbstractHeap(Absolute
, node
->registerPointer()));
562 write(AbstractHeap(Absolute
, node
->registerPointer()));
567 case NewArrayWithSize
:
570 case NewStringObject
:
572 case NewFunctionNoCheck
:
574 case NewFunctionExpression
:
575 clobberizeForAllocation(read
, write
);
579 clobberizeForAllocation(read
, write
);
580 switch (node
->child1().useKind()) {
588 RELEASE_ASSERT_NOT_REACHED();
599 if (node
->arrayMode().isOutOfBounds()) {
610 case CompareGreaterEq
:
611 if (!node
->isBinaryUseKind(UntypedUse
))
618 switch (node
->child1().useKind()) {
619 case StringObjectUse
:
620 case StringOrStringObjectUse
:
630 RELEASE_ASSERT_NOT_REACHED();
634 case TearOffActivation
:
635 write(JSVariableObject_registers
);
638 case TearOffArguments
:
639 write(Arguments_registers
);
642 case GetMyArgumentsLength
:
643 read(AbstractHeap(Variables
, graph
.argumentsRegisterFor(node
->origin
.semantic
)));
644 read(AbstractHeap(Variables
, JSStack::ArgumentCount
));
647 case GetMyArgumentByVal
:
651 case CheckArgumentsNotCreated
:
652 read(AbstractHeap(Variables
, graph
.argumentsRegisterFor(node
->origin
.semantic
)));
655 case ThrowReferenceError
:
657 clobberizeForAllocation(read
, write
);
661 case CheckWatchdogTimer
:
663 write(InternalState
);
667 case StoreBarrierWithNullCheck
:
673 RELEASE_ASSERT_NOT_REACHED();
677 RELEASE_ASSERT_NOT_REACHED();
680 class NoOpClobberize
{
683 void operator()(AbstractHeap
) { }
686 class CheckClobberize
{
693 void operator()(AbstractHeap
) { m_result
= true; }
695 bool result() const { return m_result
; }
701 bool doesWrites(Graph
&, Node
*);
703 class AbstractHeapOverlaps
{
705 AbstractHeapOverlaps(AbstractHeap heap
)
711 void operator()(AbstractHeap otherHeap
)
715 m_result
= m_heap
.overlaps(otherHeap
);
718 bool result() const { return m_result
; }
725 bool writesOverlap(Graph
&, Node
*, AbstractHeap
);
727 } } // namespace JSC::DFG
729 #endif // ENABLE(DFG_JIT)
731 #endif // DFGClobberize_h