/ bytecode / SpeculatedType.h
SpeculatedType.h
  1  /*
  2   * Copyright (C) 2011-2020 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   *
  8   * 1.  Redistributions of source code must retain the above copyright
  9   *     notice, this list of conditions and the following disclaimer.
 10   * 2.  Redistributions in binary form must reproduce the above copyright
 11   *     notice, this list of conditions and the following disclaimer in the
 12   *     documentation and/or other materials provided with the distribution.
 13   * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 14   *     its contributors may be used to endorse or promote products derived
 15   *     from this software without specific prior written permission.
 16   *
 17   * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 18   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 20   * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 21   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 22   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 23   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 24   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 26   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27   */
 28  
 29  #pragma once
 30  
 31  #include "CPU.h"
 32  #include "JSCJSValue.h"
 33  #include "TypedArrayType.h"
 34  #include <wtf/PrintStream.h>
 35  
 36  namespace JSC {
 37  
 38  class Structure;
 39  
 40  typedef uint64_t SpeculatedType;
 41  static constexpr SpeculatedType SpecNone                              = 0; // We don't know anything yet.
 42  static constexpr SpeculatedType SpecFinalObject                       = 1ull << 0; // It's definitely a JSFinalObject.
 43  static constexpr SpeculatedType SpecArray                             = 1ull << 1; // It's definitely a JSArray.
 44  static constexpr SpeculatedType SpecFunctionWithDefaultHasInstance    = 1ull << 2; // It's definitely a JSFunction that has its ImplementsDefaultHasInstance type info flags bit set.
 45  static constexpr SpeculatedType SpecFunctionWithNonDefaultHasInstance = 1ull << 3; // It's definitely a JSFunction that does not have its ImplementsDefaultHasInstance type info flags bit set.
 46  static constexpr SpeculatedType SpecFunction                          = SpecFunctionWithDefaultHasInstance | SpecFunctionWithNonDefaultHasInstance; // It's definitely a JSFunction.
 47  static constexpr SpeculatedType SpecInt8Array                         = 1ull << 4; // It's definitely an Int8Array or one of its subclasses.
 48  static constexpr SpeculatedType SpecInt16Array                        = 1ull << 5; // It's definitely an Int16Array or one of its subclasses.
 49  static constexpr SpeculatedType SpecInt32Array                        = 1ull << 6; // It's definitely an Int32Array or one of its subclasses.
 50  static constexpr SpeculatedType SpecUint8Array                        = 1ull << 7; // It's definitely an Uint8Array or one of its subclasses.
 51  static constexpr SpeculatedType SpecUint8ClampedArray                 = 1ull << 8; // It's definitely an Uint8ClampedArray or one of its subclasses.
 52  static constexpr SpeculatedType SpecUint16Array                       = 1ull << 9; // It's definitely an Uint16Array or one of its subclasses.
 53  static constexpr SpeculatedType SpecUint32Array                       = 1ull << 10; // It's definitely an Uint32Array or one of its subclasses.
 54  static constexpr SpeculatedType SpecFloat32Array                      = 1ull << 11; // It's definitely an Uint16Array or one of its subclasses.
 55  static constexpr SpeculatedType SpecFloat64Array                      = 1ull << 12; // It's definitely an Uint16Array or one of its subclasses.
 56  static constexpr SpeculatedType SpecTypedArrayView                    = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array;
 57  static constexpr SpeculatedType SpecDirectArguments                   = 1ull << 13; // It's definitely a DirectArguments object.
 58  static constexpr SpeculatedType SpecScopedArguments                   = 1ull << 14; // It's definitely a ScopedArguments object.
 59  static constexpr SpeculatedType SpecStringObject                      = 1ull << 15; // It's definitely a StringObject.
 60  static constexpr SpeculatedType SpecRegExpObject                      = 1ull << 16; // It's definitely a RegExpObject (and not any subclass of RegExpObject).
 61  static constexpr SpeculatedType SpecDateObject                        = 1ull << 17; // It's definitely a Date object or one of its subclasses.
 62  static constexpr SpeculatedType SpecPromiseObject                     = 1ull << 18; // It's definitely a Promise object or one of its subclasses.
 63  static constexpr SpeculatedType SpecMapObject                         = 1ull << 19; // It's definitely a Map object or one of its subclasses.
 64  static constexpr SpeculatedType SpecSetObject                         = 1ull << 20; // It's definitely a Set object or one of its subclasses.
 65  static constexpr SpeculatedType SpecWeakMapObject                     = 1ull << 21; // It's definitely a WeakMap object or one of its subclasses.
 66  static constexpr SpeculatedType SpecWeakSetObject                     = 1ull << 22; // It's definitely a WeakSet object or one of its subclasses.
 67  static constexpr SpeculatedType SpecProxyObject                       = 1ull << 23; // It's definitely a Proxy object or one of its subclasses.
 68  static constexpr SpeculatedType SpecDerivedArray                      = 1ull << 24; // It's definitely a DerivedArray object.
 69  static constexpr SpeculatedType SpecObjectOther                       = 1ull << 25; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
 70  static constexpr SpeculatedType SpecStringIdent                       = 1ull << 26; // It's definitely a JSString, and it's an identifier.
 71  static constexpr SpeculatedType SpecStringVar                         = 1ull << 27; // It's definitely a JSString, and it's not an identifier.
 72  static constexpr SpeculatedType SpecString                            = SpecStringIdent | SpecStringVar; // It's definitely a JSString.
 73  static constexpr SpeculatedType SpecSymbol                            = 1ull << 28; // It's definitely a Symbol.
 74  static constexpr SpeculatedType SpecCellOther                         = 1ull << 29; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString, BigInt, or Symbol.
 75  static constexpr SpeculatedType SpecBoolInt32                         = 1ull << 30; // It's definitely an Int32 with value 0 or 1.
 76  static constexpr SpeculatedType SpecNonBoolInt32                      = 1ull << 31; // It's definitely an Int32 with value other than 0 or 1.
 77  static constexpr SpeculatedType SpecInt32Only                         = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32.
 78  
 79  static constexpr SpeculatedType SpecInt32AsInt52                      = 1ull << 32; // It's an Int52 and it can fit in an int32.
 80  static constexpr SpeculatedType SpecNonInt32AsInt52                   = 1ull << 33; // It's an Int52 and it can't fit in an int32.
 81  static constexpr SpeculatedType SpecInt52Any                          = SpecInt32AsInt52 | SpecNonInt32AsInt52; // It's any kind of Int52.
 82  
 83  static constexpr SpeculatedType SpecAnyIntAsDouble                    = 1ull << 34; // It's definitely an Int52 and it's inside a double.
 84  static constexpr SpeculatedType SpecNonIntAsDouble                    = 1ull << 35; // It's definitely not an Int52 but it's a real number and it's a double.
 85  static constexpr SpeculatedType SpecDoubleReal                        = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double.
 86  static constexpr SpeculatedType SpecDoublePureNaN                     = 1ull << 36; // It's definitely a NaN that is safe to tag (i.e. pure).
 87  static constexpr SpeculatedType SpecDoubleImpureNaN                   = 1ull << 37; // It's definitely a NaN that is unsafe to tag (i.e. impure).
 88  static constexpr SpeculatedType SpecDoubleNaN                         = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN.
 89  static constexpr SpeculatedType SpecBytecodeDouble                    = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN.
 90  static constexpr SpeculatedType SpecFullDouble                        = SpecDoubleReal | SpecDoubleNaN; // It's either a non-NaN or a NaN double.
 91  static constexpr SpeculatedType SpecBytecodeRealNumber                = SpecInt32Only | SpecDoubleReal; // It's either an Int32 or a DoubleReal.
 92  static constexpr SpeculatedType SpecFullRealNumber                    = SpecInt32Only | SpecInt52Any | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or an Int52.
 93  static constexpr SpeculatedType SpecBytecodeNumber                    = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
 94  static constexpr SpeculatedType SpecIntAnyFormat                      = SpecInt52Any | SpecInt32Only | SpecAnyIntAsDouble;
 95  
 96  static constexpr SpeculatedType SpecFullNumber                        = SpecIntAnyFormat | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
 97  static constexpr SpeculatedType SpecBoolean                           = 1ull << 38; // It's definitely a Boolean.
 98  static constexpr SpeculatedType SpecOther                             = 1ull << 39; // It's definitely either Null or Undefined.
 99  static constexpr SpeculatedType SpecMisc                              = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined.
100  static constexpr SpeculatedType SpecEmpty                             = 1ull << 40; // It's definitely an empty value marker.
101  static constexpr SpeculatedType SpecHeapBigInt                        = 1ull << 41; // It's definitely a BigInt that is allocated on the heap
102  static constexpr SpeculatedType SpecBigInt32                          = 1ull << 42; // It's definitely a small BigInt that is inline the JSValue
103  #if USE(BIGINT32)
104  static constexpr SpeculatedType SpecBigInt                            = SpecBigInt32 | SpecHeapBigInt;
105  #else
106  // We should not include SpecBigInt32. We are using SpecBigInt in various places like prediction. If this includes SpecBigInt32, fixup phase is confused if !USE(BIGINT32) since it is not using AnyBigIntUse.
107  static constexpr SpeculatedType SpecBigInt                            = SpecHeapBigInt;
108  #endif
109  static constexpr SpeculatedType SpecDataViewObject                    = 1ull << 43; // It's definitely a JSDataView.
110  static constexpr SpeculatedType SpecPrimitive                         = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue.
111  static constexpr SpeculatedType SpecObject                            = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecDateObject | SpecPromiseObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther | SpecDataViewObject; // Bitmask used for testing for any kind of object prediction.
112  static constexpr SpeculatedType SpecCell                              = SpecObject | SpecString | SpecSymbol | SpecCellOther | SpecHeapBigInt; // It's definitely a JSCell.
113  static constexpr SpeculatedType SpecHeapTop                           = SpecCell | SpecBigInt32 | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
114  static constexpr SpeculatedType SpecBytecodeTop                       = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local.
115  static constexpr SpeculatedType SpecFullTop                           = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers.
116  
117  // SpecCellCheck is the type set representing the values that can flow through a cell check.
118  // On 64-bit platforms, the empty value passes a cell check. Also, ~SpecCellCheck is the type
119  // set that representing the values that flow through when testing that something is not a cell.
120  static constexpr SpeculatedType SpecCellCheck          = is64Bit() ? (SpecCell | SpecEmpty) : SpecCell;
121  
122  typedef bool (*SpeculatedTypeChecker)(SpeculatedType);
123  
124  // Dummy prediction checker, only useful if someone insists on requiring a prediction checker.
125  inline bool isAnySpeculation(SpeculatedType)
126  {
127      return true;
128  }
129  
130  inline bool isSubtypeSpeculation(SpeculatedType value, SpeculatedType category)
131  {
132      return !(value & ~category) && value;
133  }
134  
135  inline bool speculationContains(SpeculatedType value, SpeculatedType category)
136  {
137      return !!(value & category) && value;
138  }
139  
140  inline bool isCellSpeculation(SpeculatedType value)
141  {
142      return !!(value & SpecCell) && !(value & ~SpecCell);
143  }
144  
145  inline bool isCellOrOtherSpeculation(SpeculatedType value)
146  {
147      return !!value && !(value & ~(SpecCell | SpecOther));
148  }
149  
150  inline bool isNotCellSpeculation(SpeculatedType value)
151  {
152      return !(value & SpecCellCheck) && value;
153  }
154  
155  inline bool isNotCellNorBigIntSpeculation(SpeculatedType value)
156  {
157      return !(value & (SpecCellCheck | SpecBigInt)) && value;
158  }
159  
160  inline bool isObjectSpeculation(SpeculatedType value)
161  {
162      return !!(value & SpecObject) && !(value & ~SpecObject);
163  }
164  
165  inline bool isObjectOrOtherSpeculation(SpeculatedType value)
166  {
167      return !!(value & (SpecObject | SpecOther)) && !(value & ~(SpecObject | SpecOther));
168  }
169  
170  inline bool isFinalObjectSpeculation(SpeculatedType value)
171  {
172      return value == SpecFinalObject;
173  }
174  
175  inline bool isFinalObjectOrOtherSpeculation(SpeculatedType value)
176  {
177      return !!(value & (SpecFinalObject | SpecOther)) && !(value & ~(SpecFinalObject | SpecOther));
178  }
179  
180  inline bool isStringIdentSpeculation(SpeculatedType value)
181  {
182      return value == SpecStringIdent;
183  }
184  
185  inline bool isNotStringVarSpeculation(SpeculatedType value)
186  {
187      return !(value & SpecStringVar);
188  }
189  
190  inline bool isStringSpeculation(SpeculatedType value)
191  {
192      return !!value && (value & SpecString) == value;
193  }
194  
195  inline bool isNotStringSpeculation(SpeculatedType value)
196  {
197      return value && !(value & SpecString);
198  }
199  
200  inline bool isStringOrOtherSpeculation(SpeculatedType value)
201  {
202      return !!value && (value & (SpecString | SpecOther)) == value;
203  }
204  
205  inline bool isSymbolSpeculation(SpeculatedType value)
206  {
207      return value == SpecSymbol;
208  }
209  
210  inline bool isBigInt32Speculation(SpeculatedType value)
211  {
212      return value == SpecBigInt32;
213  }
214  
215  inline bool isHeapBigIntSpeculation(SpeculatedType value)
216  {
217      return value == SpecHeapBigInt;
218  }
219  
220  inline bool isBigIntSpeculation(SpeculatedType value)
221  {
222      return !!value && (value & SpecBigInt) == value;
223  }
224  
225  inline bool isArraySpeculation(SpeculatedType value)
226  {
227      return value == SpecArray;
228  }
229  
230  inline bool isFunctionSpeculation(SpeculatedType value)
231  {
232      return value == SpecFunction;
233  }
234  
235  inline bool isProxyObjectSpeculation(SpeculatedType value)
236  {
237      return value == SpecProxyObject;
238  }
239  
240  inline bool isDerivedArraySpeculation(SpeculatedType value)
241  {
242      return value == SpecDerivedArray;
243  }
244  
245  inline bool isInt8ArraySpeculation(SpeculatedType value)
246  {
247      return value == SpecInt8Array;
248  }
249  
250  inline bool isInt16ArraySpeculation(SpeculatedType value)
251  {
252      return value == SpecInt16Array;
253  }
254  
255  inline bool isInt32ArraySpeculation(SpeculatedType value)
256  {
257      return value == SpecInt32Array;
258  }
259  
260  inline bool isUint8ArraySpeculation(SpeculatedType value)
261  {
262      return value == SpecUint8Array;
263  }
264  
265  inline bool isUint8ClampedArraySpeculation(SpeculatedType value)
266  {
267      return value == SpecUint8ClampedArray;
268  }
269  
270  inline bool isUint16ArraySpeculation(SpeculatedType value)
271  {
272      return value == SpecUint16Array;
273  }
274  
275  inline bool isUint32ArraySpeculation(SpeculatedType value)
276  {
277      return value == SpecUint32Array;
278  }
279  
280  inline bool isFloat32ArraySpeculation(SpeculatedType value)
281  {
282      return value == SpecFloat32Array;
283  }
284  
285  inline bool isFloat64ArraySpeculation(SpeculatedType value)
286  {
287      return value == SpecFloat64Array;
288  }
289  
290  inline bool isDirectArgumentsSpeculation(SpeculatedType value)
291  {
292      return value == SpecDirectArguments;
293  }
294  
295  inline bool isScopedArgumentsSpeculation(SpeculatedType value)
296  {
297      return value == SpecScopedArguments;
298  }
299  
300  inline bool isActionableIntMutableArraySpeculation(SpeculatedType value)
301  {
302      return isInt8ArraySpeculation(value)
303          || isInt16ArraySpeculation(value)
304          || isInt32ArraySpeculation(value)
305          || isUint8ArraySpeculation(value)
306          || isUint8ClampedArraySpeculation(value)
307          || isUint16ArraySpeculation(value)
308          || isUint32ArraySpeculation(value);
309  }
310  
311  inline bool isActionableFloatMutableArraySpeculation(SpeculatedType value)
312  {
313      return isFloat32ArraySpeculation(value)
314          || isFloat64ArraySpeculation(value);
315  }
316  
317  inline bool isActionableTypedMutableArraySpeculation(SpeculatedType value)
318  {
319      return isActionableIntMutableArraySpeculation(value)
320          || isActionableFloatMutableArraySpeculation(value);
321  }
322  
323  inline bool isActionableMutableArraySpeculation(SpeculatedType value)
324  {
325      return isArraySpeculation(value)
326          || isActionableTypedMutableArraySpeculation(value);
327  }
328  
329  inline bool isActionableArraySpeculation(SpeculatedType value)
330  {
331      return isStringSpeculation(value)
332          || isDirectArgumentsSpeculation(value)
333          || isScopedArgumentsSpeculation(value)
334          || isActionableMutableArraySpeculation(value);
335  }
336  
337  inline bool isArrayOrOtherSpeculation(SpeculatedType value)
338  {
339      return !!(value & (SpecArray | SpecOther)) && !(value & ~(SpecArray | SpecOther));
340  }
341  
342  inline bool isStringObjectSpeculation(SpeculatedType value)
343  {
344      return value == SpecStringObject;
345  }
346  
347  inline bool isStringOrStringObjectSpeculation(SpeculatedType value)
348  {
349      return !!value && !(value & ~(SpecString | SpecStringObject));
350  }
351  
352  inline bool isRegExpObjectSpeculation(SpeculatedType value)
353  {
354      return value == SpecRegExpObject;
355  }
356  
357  inline bool isBoolInt32Speculation(SpeculatedType value)
358  {
359      return value == SpecBoolInt32;
360  }
361  
362  inline bool isInt32Speculation(SpeculatedType value)
363  {
364      return value && !(value & ~SpecInt32Only);
365  }
366  
367  inline bool isNotInt32Speculation(SpeculatedType value)
368  {
369      return value && !(value & SpecInt32Only);
370  }
371  
372  inline bool isInt32OrBooleanSpeculation(SpeculatedType value)
373  {
374      return value && !(value & ~(SpecBoolean | SpecInt32Only));
375  }
376  
377  inline bool isInt32SpeculationForArithmetic(SpeculatedType value)
378  {
379      return !(value & (SpecFullDouble | SpecNonInt32AsInt52 | SpecBigInt));
380  }
381  
382  inline bool isInt32OrBooleanSpeculationForArithmetic(SpeculatedType value)
383  {
384      return !(value & (SpecFullDouble | SpecNonInt32AsInt52 | SpecBigInt));
385  }
386  
387  inline bool isInt32OrBooleanSpeculationExpectingDefined(SpeculatedType value)
388  {
389      return isInt32OrBooleanSpeculation(value & ~SpecOther);
390  }
391  
392  inline bool isAnyInt52Speculation(SpeculatedType value)
393  {
394      return !!value && (value & SpecInt52Any) == value;
395  }
396  
397  inline bool isInt32OrInt52Speculation(SpeculatedType value)
398  {
399      return !!value && (value & (SpecInt32Only | SpecInt52Any)) == value;
400  }
401  
402  inline bool isIntAnyFormat(SpeculatedType value)
403  {
404      return !!value && (value & SpecIntAnyFormat) == value;
405  }
406  
407  inline bool isAnyIntAsDoubleSpeculation(SpeculatedType value)
408  {
409      return value == SpecAnyIntAsDouble;
410  }
411  
412  inline bool isDoubleRealSpeculation(SpeculatedType value)
413  {
414      return !!value && (value & SpecDoubleReal) == value;
415  }
416  
417  inline bool isDoubleSpeculation(SpeculatedType value)
418  {
419      return !!value && (value & SpecFullDouble) == value;
420  }
421  
422  inline bool isDoubleSpeculationForArithmetic(SpeculatedType value)
423  {
424      return !!(value & SpecFullDouble);
425  }
426  
427  inline bool isBytecodeRealNumberSpeculation(SpeculatedType value)
428  {
429      return !!(value & SpecBytecodeRealNumber) && !(value & ~SpecBytecodeRealNumber);
430  }
431  
432  inline bool isFullRealNumberSpeculation(SpeculatedType value)
433  {
434      return !!(value & SpecFullRealNumber) && !(value & ~SpecFullRealNumber);
435  }
436  
437  inline bool isBytecodeNumberSpeculation(SpeculatedType value)
438  {
439      return !!(value & SpecBytecodeNumber) && !(value & ~SpecBytecodeNumber);
440  }
441  
442  inline bool isFullNumberSpeculation(SpeculatedType value)
443  {
444      return !!(value & SpecFullNumber) && !(value & ~SpecFullNumber);
445  }
446  
447  inline bool isFullNumberOrBooleanSpeculation(SpeculatedType value)
448  {
449      return value && !(value & ~(SpecFullNumber | SpecBoolean));
450  }
451  
452  inline bool isFullNumberOrBooleanSpeculationExpectingDefined(SpeculatedType value)
453  {
454      return isFullNumberOrBooleanSpeculation(value & ~SpecOther);
455  }
456  
457  inline bool isBooleanSpeculation(SpeculatedType value)
458  {
459      return value == SpecBoolean;
460  }
461  
462  inline bool isNotBooleanSpeculation(SpeculatedType value)
463  {
464      return value && !(value & SpecBoolean);
465  }
466  
467  inline bool isOtherSpeculation(SpeculatedType value)
468  {
469      return value == SpecOther;
470  }
471  
472  inline bool isMiscSpeculation(SpeculatedType value)
473  {
474      return !!value && !(value & ~SpecMisc);
475  }
476  
477  inline bool isOtherOrEmptySpeculation(SpeculatedType value)
478  {
479      return !value || value == SpecOther;
480  }
481  
482  inline bool isEmptySpeculation(SpeculatedType value)
483  {
484      return value == SpecEmpty;
485  }
486  
487  inline bool isUntypedSpeculationForArithmetic(SpeculatedType value)
488  {
489      return !!(value & ~(SpecFullNumber | SpecBoolean));
490  }
491  
492  inline bool isUntypedSpeculationForBitOps(SpeculatedType value)
493  {
494      return !!(value & ~(SpecFullNumber | SpecBoolean | SpecOther));
495  }
496  
497  void dumpSpeculation(PrintStream&, SpeculatedType);
498  void dumpSpeculationAbbreviated(PrintStream&, SpeculatedType);
499  
500  MAKE_PRINT_ADAPTOR(SpeculationDump, SpeculatedType, dumpSpeculation);
501  MAKE_PRINT_ADAPTOR(AbbreviatedSpeculationDump, SpeculatedType, dumpSpeculationAbbreviated);
502  
503  // Merge two predictions. Note that currently this just does left | right. It may
504  // seem tempting to do so directly, but you would be doing so at your own peril,
505  // since the merging protocol SpeculatedType may change at any time (and has already
506  // changed several times in its history).
507  inline SpeculatedType mergeSpeculations(SpeculatedType left, SpeculatedType right)
508  {
509      return left | right;
510  }
511  
512  template<typename T>
513  inline bool mergeSpeculation(T& left, SpeculatedType right)
514  {
515      SpeculatedType newSpeculation = static_cast<T>(mergeSpeculations(static_cast<SpeculatedType>(left), right));
516      bool result = newSpeculation != static_cast<SpeculatedType>(left);
517      left = newSpeculation;
518      return result;
519  }
520  
521  inline bool speculationChecked(SpeculatedType actual, SpeculatedType desired)
522  {
523      return (actual | desired) == desired;
524  }
525  
526  // The SpeculatedType returned by this function for any cell, c, has the following invariant:
527  // ASSERT(!c->inherits(classInfo) || speculationChecked(speculationFromCell(c), speculationFromClassInfoInheritance(classInfo)));
528  SpeculatedType speculationFromClassInfoInheritance(const ClassInfo*);
529  
530  SpeculatedType speculationFromStructure(Structure*);
531  SpeculatedType speculationFromCell(JSCell*);
532  JS_EXPORT_PRIVATE SpeculatedType speculationFromValue(JSValue);
533  // If it's an anyInt(), it'll return speculated types from the Int52 lattice.
534  // Otherwise, it'll return types from the JSValue lattice.
535  JS_EXPORT_PRIVATE SpeculatedType int52AwareSpeculationFromValue(JSValue);
536  Optional<SpeculatedType> speculationFromJSType(JSType);
537  
538  SpeculatedType speculationFromTypedArrayType(TypedArrayType); // only valid for typed views.
539  TypedArrayType typedArrayTypeFromSpeculation(SpeculatedType);
540  
541  SpeculatedType leastUpperBoundOfStrictlyEquivalentSpeculations(SpeculatedType);
542  
543  bool valuesCouldBeEqual(SpeculatedType, SpeculatedType);
544  
545  // Precise computation of the type of the result of a double computation after we
546  // already know that the inputs are doubles and that the result must be a double. Use
547  // the closest one of these that applies.
548  SpeculatedType typeOfDoubleSum(SpeculatedType, SpeculatedType);
549  SpeculatedType typeOfDoubleDifference(SpeculatedType, SpeculatedType);
550  SpeculatedType typeOfDoubleIncOrDec(SpeculatedType);
551  SpeculatedType typeOfDoubleProduct(SpeculatedType, SpeculatedType);
552  SpeculatedType typeOfDoubleQuotient(SpeculatedType, SpeculatedType);
553  SpeculatedType typeOfDoubleMinMax(SpeculatedType, SpeculatedType);
554  SpeculatedType typeOfDoubleNegation(SpeculatedType);
555  SpeculatedType typeOfDoubleAbs(SpeculatedType);
556  SpeculatedType typeOfDoubleRounding(SpeculatedType);
557  SpeculatedType typeOfDoublePow(SpeculatedType, SpeculatedType);
558  
559  // This conservatively models the behavior of arbitrary double operations.
560  SpeculatedType typeOfDoubleBinaryOp(SpeculatedType, SpeculatedType);
561  SpeculatedType typeOfDoubleUnaryOp(SpeculatedType);
562  
563  // This is mostly for debugging so we can fill profiles from strings.
564  SpeculatedType speculationFromString(const char*);
565  
566  } // namespace JSC