Renaming SpecInt32, SpecInt52, MachineInt to SpecInt32Only, SpecInt52Only, AnyInt.
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGAbstractValue.cpp
1 /*
2  * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #include "config.h"
27 #include "DFGAbstractValue.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGGraph.h"
32 #include "JSCInlines.h"
33 #include "TrackedReferences.h"
34
35 namespace JSC { namespace DFG {
36
37 void AbstractValue::observeTransitions(const TransitionVector& vector)
38 {
39     if (m_type & SpecCell) {
40         m_structure.observeTransitions(vector);
41         ArrayModes newModes = 0;
42         for (unsigned i = vector.size(); i--;) {
43             if (m_arrayModes & asArrayModes(vector[i].previous->indexingType()))
44                 newModes |= asArrayModes(vector[i].next->indexingType());
45         }
46         m_arrayModes |= newModes;
47     }
48     checkConsistency();
49 }
50
51 void AbstractValue::set(Graph& graph, const FrozenValue& value, StructureClobberState clobberState)
52 {
53     if (!!value && value.value().isCell()) {
54         Structure* structure = value.structure();
55         if (graph.registerStructure(structure) == StructureRegisteredAndWatched) {
56             m_structure = structure;
57             if (clobberState == StructuresAreClobbered) {
58                 m_arrayModes = ALL_ARRAY_MODES;
59                 m_structure.clobber();
60             } else
61                 m_arrayModes = asArrayModes(structure->indexingType());
62         } else {
63             m_structure.makeTop();
64             m_arrayModes = ALL_ARRAY_MODES;
65         }
66     } else {
67         m_structure.clear();
68         m_arrayModes = 0;
69     }
70     
71     m_type = speculationFromValue(value.value());
72     m_value = value.value();
73     
74     checkConsistency();
75     assertIsRegistered(graph);
76 }
77
78 void AbstractValue::set(Graph& graph, Structure* structure)
79 {
80     m_structure = structure;
81     m_arrayModes = asArrayModes(structure->indexingType());
82     m_type = speculationFromStructure(structure);
83     m_value = JSValue();
84     
85     checkConsistency();
86     assertIsRegistered(graph);
87 }
88
89 void AbstractValue::set(Graph& graph, const StructureSet& set)
90 {
91     m_structure = set;
92     m_arrayModes = set.arrayModesFromStructures();
93     m_type = set.speculationFromStructures();
94     m_value = JSValue();
95     
96     checkConsistency();
97     assertIsRegistered(graph);
98 }
99
100 void AbstractValue::setType(Graph& graph, SpeculatedType type)
101 {
102     SpeculatedType cellType = type & SpecCell;
103     if (cellType) {
104         if (!(cellType & ~SpecString))
105             m_structure = graph.m_vm.stringStructure.get();
106         else if (isSymbolSpeculation(cellType))
107             m_structure = graph.m_vm.symbolStructure.get();
108         else
109             m_structure.makeTop();
110         m_arrayModes = ALL_ARRAY_MODES;
111     } else {
112         m_structure.clear();
113         m_arrayModes = 0;
114     }
115     m_type = type;
116     m_value = JSValue();
117     checkConsistency();
118 }
119
120 void AbstractValue::set(Graph& graph, const InferredType::Descriptor& descriptor)
121 {
122     switch (descriptor.kind()) {
123     case InferredType::Bottom:
124         clear();
125         return;
126     case InferredType::Boolean:
127         setType(SpecBoolean);
128         return;
129     case InferredType::Other:
130         setType(SpecOther);
131         return;
132     case InferredType::Int32:
133         setType(SpecInt32Only);
134         return;
135     case InferredType::Number:
136         setType(SpecBytecodeNumber);
137         return;
138     case InferredType::String:
139         set(graph, graph.m_vm.stringStructure.get());
140         return;
141     case InferredType::Symbol:
142         set(graph, graph.m_vm.symbolStructure.get());
143         return;
144     case InferredType::ObjectWithStructure:
145         set(graph, descriptor.structure());
146         return;
147     case InferredType::ObjectWithStructureOrOther:
148         set(graph, descriptor.structure());
149         merge(SpecOther);
150         return;
151     case InferredType::Object:
152         setType(graph, SpecObject);
153         return;
154     case InferredType::ObjectOrOther:
155         setType(graph, SpecObject | SpecOther);
156         return;
157     case InferredType::Top:
158         makeHeapTop();
159         return;
160     }
161
162     RELEASE_ASSERT_NOT_REACHED();
163 }
164
165 void AbstractValue::set(
166     Graph& graph, const InferredType::Descriptor& descriptor, StructureClobberState clobberState)
167 {
168     set(graph, descriptor);
169     if (clobberState == StructuresAreClobbered)
170         clobberStructures();
171 }
172
173 void AbstractValue::fixTypeForRepresentation(Graph& graph, NodeFlags representation, Node* node)
174 {
175     if (representation == NodeResultDouble) {
176         if (m_value) {
177             ASSERT(m_value.isNumber());
178             if (m_value.isInt32())
179                 m_value = jsDoubleNumber(m_value.asNumber());
180         }
181         if (m_type & SpecAnyInt) {
182             m_type &= ~SpecAnyInt;
183             m_type |= SpecAnyIntAsDouble;
184         }
185         if (m_type & ~SpecFullDouble)
186             DFG_CRASH(graph, node, toCString("Abstract value ", *this, " for double node has type outside SpecFullDouble.\n").data());
187     } else if (representation == NodeResultInt52) {
188         if (m_type & SpecAnyIntAsDouble) {
189             m_type &= ~SpecAnyIntAsDouble;
190             m_type |= SpecInt52Only;
191         }
192         if (m_type & ~SpecAnyInt)
193             DFG_CRASH(graph, node, toCString("Abstract value ", *this, " for int52 node has type outside SpecAnyInt.\n").data());
194     } else {
195         if (m_type & SpecInt52Only) {
196             m_type &= ~SpecInt52Only;
197             m_type |= SpecAnyIntAsDouble;
198         }
199         if (m_type & ~SpecBytecodeTop)
200             DFG_CRASH(graph, node, toCString("Abstract value ", *this, " for value node has type outside SpecBytecodeTop.\n").data());
201     }
202     
203     checkConsistency();
204 }
205
206 void AbstractValue::fixTypeForRepresentation(Graph& graph, Node* node)
207 {
208     fixTypeForRepresentation(graph, node->result(), node);
209 }
210
211 bool AbstractValue::mergeOSREntryValue(Graph& graph, JSValue value)
212 {
213     AbstractValue oldMe = *this;
214     
215     if (isClear()) {
216         FrozenValue* frozenValue = graph.freeze(value);
217         if (frozenValue->pointsToHeap()) {
218             m_structure = frozenValue->structure();
219             m_arrayModes = asArrayModes(frozenValue->structure()->indexingType());
220         } else {
221             m_structure.clear();
222             m_arrayModes = 0;
223         }
224         
225         m_type = speculationFromValue(value);
226         m_value = value;
227     } else {
228         mergeSpeculation(m_type, speculationFromValue(value));
229         if (!!value && value.isCell()) {
230             Structure* structure = value.asCell()->structure();
231             graph.registerStructure(structure);
232             mergeArrayModes(m_arrayModes, asArrayModes(structure->indexingType()));
233             m_structure.merge(StructureSet(structure));
234         }
235         if (m_value != value)
236             m_value = JSValue();
237     }
238     
239     checkConsistency();
240     assertIsRegistered(graph);
241     
242     return oldMe != *this;
243 }
244
245 bool AbstractValue::isType(Graph& graph, const InferredType::Descriptor& inferredType) const
246 {
247     AbstractValue typeValue;
248     typeValue.set(graph, inferredType);
249
250     AbstractValue mergedValue = *this;
251     mergedValue.merge(typeValue);
252
253     return mergedValue == typeValue;
254 }
255
256 FiltrationResult AbstractValue::filter(
257     Graph& graph, const StructureSet& other, SpeculatedType admittedTypes)
258 {
259     ASSERT(!(admittedTypes & SpecCell));
260     
261     if (isClear())
262         return FiltrationOK;
263     
264     // FIXME: This could be optimized for the common case of m_type not
265     // having structures, array modes, or a specific value.
266     // https://bugs.webkit.org/show_bug.cgi?id=109663
267     
268     m_type &= other.speculationFromStructures() | admittedTypes;
269     m_arrayModes &= other.arrayModesFromStructures();
270     m_structure.filter(other);
271     
272     // It's possible that prior to the above two statements we had (Foo, TOP), where
273     // Foo is a SpeculatedType that is disjoint with the passed StructureSet. In that
274     // case, we will now have (None, [someStructure]). In general, we need to make
275     // sure that new information gleaned from the SpeculatedType needs to be fed back
276     // into the information gleaned from the StructureSet.
277     m_structure.filter(m_type);
278     
279     filterArrayModesByType();
280     filterValueByType();
281     return normalizeClarity(graph);
282 }
283
284 FiltrationResult AbstractValue::changeStructure(Graph& graph, const StructureSet& other)
285 {
286     m_type &= other.speculationFromStructures();
287     m_arrayModes = other.arrayModesFromStructures();
288     m_structure = other;
289     
290     filterValueByType();
291     
292     return normalizeClarity(graph);
293 }
294
295 FiltrationResult AbstractValue::filterArrayModes(ArrayModes arrayModes)
296 {
297     ASSERT(arrayModes);
298     
299     if (isClear())
300         return FiltrationOK;
301     
302     m_type &= SpecCell;
303     m_arrayModes &= arrayModes;
304     return normalizeClarity();
305 }
306
307 FiltrationResult AbstractValue::filter(SpeculatedType type)
308 {
309     if ((m_type & type) == m_type)
310         return FiltrationOK;
311     
312     // Fast path for the case that we don't even have a cell.
313     if (!(m_type & SpecCell)) {
314         m_type &= type;
315         FiltrationResult result;
316         if (m_type == SpecNone) {
317             clear();
318             result = Contradiction;
319         } else
320             result = FiltrationOK;
321         checkConsistency();
322         return result;
323     }
324     
325     m_type &= type;
326     
327     // It's possible that prior to this filter() call we had, say, (Final, TOP), and
328     // the passed type is Array. At this point we'll have (None, TOP). The best way
329     // to ensure that the structure filtering does the right thing is to filter on
330     // the new type (None) rather than the one passed (Array).
331     m_structure.filter(m_type);
332     filterArrayModesByType();
333     filterValueByType();
334     return normalizeClarity();
335 }
336
337 FiltrationResult AbstractValue::filterByValue(const FrozenValue& value)
338 {
339     FiltrationResult result = filter(speculationFromValue(value.value()));
340     if (m_type)
341         m_value = value.value();
342     return result;
343 }
344
345 bool AbstractValue::contains(Structure* structure) const
346 {
347     return couldBeType(speculationFromStructure(structure))
348         && (m_arrayModes & arrayModeFromStructure(structure))
349         && m_structure.contains(structure);
350 }
351
352 FiltrationResult AbstractValue::filter(const AbstractValue& other)
353 {
354     m_type &= other.m_type;
355     m_structure.filter(other.m_structure);
356     m_arrayModes &= other.m_arrayModes;
357
358     m_structure.filter(m_type);
359     filterArrayModesByType();
360     filterValueByType();
361     
362     if (normalizeClarity() == Contradiction)
363         return Contradiction;
364     
365     if (m_value == other.m_value)
366         return FiltrationOK;
367     
368     // Neither of us are BOTTOM, so an empty value means TOP.
369     if (!m_value) {
370         // We previously didn't prove a value but now we have done so.
371         m_value = other.m_value; 
372         return FiltrationOK;
373     }
374     
375     if (!other.m_value) {
376         // We had proved a value but the other guy hadn't, so keep our proof.
377         return FiltrationOK;
378     }
379     
380     // We both proved there to be a specific value but they are different.
381     clear();
382     return Contradiction;
383 }
384
385 FiltrationResult AbstractValue::filter(Graph& graph, const InferredType::Descriptor& descriptor)
386 {
387     AbstractValue filterValue;
388     filterValue.set(graph, descriptor);
389     return filter(filterValue);
390 }
391
392 void AbstractValue::filterValueByType()
393 {
394     // We could go further, and ensure that if the futurePossibleStructure contravenes
395     // the value, then we could clear both of those things. But that's unlikely to help
396     // in any realistic scenario, so we don't do it. Simpler is better.
397
398     if (!!m_type) {
399         // The type is still non-empty. It may be that the new type renders
400         // the value empty because it contravenes the constant value we had.
401         if (m_value && !validateType(m_value))
402             clear();
403         return;
404     }
405     
406     // The type has been rendered empty. That means that the value must now be invalid,
407     // as well.
408     ASSERT(!m_value || !validateType(m_value));
409     m_value = JSValue();
410 }
411
412 void AbstractValue::filterArrayModesByType()
413 {
414     if (!(m_type & SpecCell))
415         m_arrayModes = 0;
416     else if (!(m_type & ~SpecArray))
417         m_arrayModes &= ALL_ARRAY_ARRAY_MODES;
418     
419     // NOTE: If m_type doesn't have SpecArray set, that doesn't mean that the
420     // array modes have to be a subset of ALL_NON_ARRAY_ARRAY_MODES, since
421     // in the speculated type type-system, RegExpMatchesArry and ArrayPrototype
422     // are Otherobj (since they are not *exactly* JSArray) but in the ArrayModes
423     // type system they are arrays (since they expose the magical length
424     // property and are otherwise allocated using array allocation). Hence the
425     // following would be wrong:
426     //
427     // if (!(m_type & SpecArray))
428     //    m_arrayModes &= ALL_NON_ARRAY_ARRAY_MODES;
429 }
430
431 bool AbstractValue::shouldBeClear() const
432 {
433     if (m_type == SpecNone)
434         return true;
435     
436     if (!(m_type & ~SpecCell)
437         && (!m_arrayModes || m_structure.isClear()))
438         return true;
439     
440     return false;
441 }
442
443 FiltrationResult AbstractValue::normalizeClarity()
444 {
445     // It's useful to be able to quickly check if an abstract value is clear.
446     // This normalizes everything to make that easy.
447     
448     FiltrationResult result;
449     
450     if (shouldBeClear()) {
451         clear();
452         result = Contradiction;
453     } else
454         result = FiltrationOK;
455
456     checkConsistency();
457     
458     return result;
459 }
460
461 FiltrationResult AbstractValue::normalizeClarity(Graph& graph)
462 {
463     FiltrationResult result = normalizeClarity();
464     assertIsRegistered(graph);
465     return result;
466 }
467
468 #if !ASSERT_DISABLED
469 void AbstractValue::checkConsistency() const
470 {
471     if (!(m_type & SpecCell)) {
472         ASSERT(m_structure.isClear());
473         ASSERT(!m_arrayModes);
474     }
475     
476     if (isClear())
477         ASSERT(!m_value);
478     
479     if (!!m_value) {
480         SpeculatedType type = m_type;
481         // This relaxes the assertion below a bit, since we don't know the representation of the
482         // node.
483         if (type & SpecInt52Only)
484             type |= SpecAnyIntAsDouble;
485         ASSERT(mergeSpeculations(type, speculationFromValue(m_value)) == type);
486     }
487     
488     // Note that it's possible for a prediction like (Final, []). This really means that
489     // the value is bottom and that any code that uses the value is unreachable. But
490     // we don't want to get pedantic about this as it would only increase the computational
491     // complexity of the code.
492 }
493
494 void AbstractValue::assertIsRegistered(Graph& graph) const
495 {
496     m_structure.assertIsRegistered(graph);
497 }
498 #endif
499
500 ResultType AbstractValue::resultType() const
501 {
502     ASSERT(isType(SpecBytecodeTop));
503     if (isType(SpecBoolean))
504         return ResultType::booleanType();
505     if (isType(SpecInt32Only))
506         return ResultType::numberTypeIsInt32();
507     if (isType(SpecBytecodeNumber))
508         return ResultType::numberType();
509     if (isType(SpecString))
510         return ResultType::stringType();
511     if (isType(SpecString | SpecBytecodeNumber))
512         return ResultType::stringOrNumberType();
513     return ResultType::unknownType();
514 }
515
516 void AbstractValue::dump(PrintStream& out) const
517 {
518     dumpInContext(out, 0);
519 }
520
521 void AbstractValue::dumpInContext(PrintStream& out, DumpContext* context) const
522 {
523     out.print("(", SpeculationDump(m_type));
524     if (m_type & SpecCell) {
525         out.print(
526             ", ", ArrayModesDump(m_arrayModes), ", ",
527             inContext(m_structure, context));
528     }
529     if (!!m_value)
530         out.print(", ", inContext(m_value, context));
531     out.print(")");
532 }
533
534 void AbstractValue::validateReferences(const TrackedReferences& trackedReferences)
535 {
536     trackedReferences.check(m_value);
537     m_structure.validateReferences(trackedReferences);
538 }
539
540 } } // namespace JSC::DFG
541
542 #endif // ENABLE(DFG_JIT)
543