2 * Copyright (C) 2011-2013, 2015-2016 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
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.
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.
30 #include "SpeculatedType.h"
32 #include "DirectArguments.h"
34 #include "JSFunction.h"
35 #include "JSCInlines.h"
36 #include "ScopedArguments.h"
37 #include "StringObject.h"
38 #include "ValueProfile.h"
39 #include <wtf/StringPrintStream.h>
43 void dumpSpeculation(PrintStream& out, SpeculatedType value)
45 if (value == SpecNone) {
50 StringPrintStream myOut;
54 if ((value & SpecCell) == SpecCell)
57 if ((value & SpecObject) == SpecObject)
58 myOut.print("Object");
60 if (value & SpecCellOther)
61 myOut.print("Othercell");
65 if (value & SpecObjectOther)
66 myOut.print("Otherobj");
70 if (value & SpecFinalObject)
75 if (value & SpecArray)
80 if (value & SpecInt8Array)
81 myOut.print("Int8array");
85 if (value & SpecInt16Array)
86 myOut.print("Int16array");
90 if (value & SpecInt32Array)
91 myOut.print("Int32array");
95 if (value & SpecUint8Array)
96 myOut.print("Uint8array");
100 if (value & SpecUint8ClampedArray)
101 myOut.print("Uint8clampedarray");
105 if (value & SpecUint16Array)
106 myOut.print("Uint16array");
110 if (value & SpecUint32Array)
111 myOut.print("Uint32array");
115 if (value & SpecFloat32Array)
116 myOut.print("Float32array");
120 if (value & SpecFloat64Array)
121 myOut.print("Float64array");
125 if (value & SpecFunction)
126 myOut.print("Function");
130 if (value & SpecDirectArguments)
131 myOut.print("Directarguments");
135 if (value & SpecScopedArguments)
136 myOut.print("Scopedarguments");
140 if (value & SpecStringObject)
141 myOut.print("Stringobject");
145 if (value & SpecRegExpObject)
146 myOut.print("Regexpobject");
151 if ((value & SpecString) == SpecString)
152 myOut.print("String");
154 if (value & SpecStringIdent)
155 myOut.print("Stringident");
159 if (value & SpecStringVar)
160 myOut.print("Stringvar");
165 if (value & SpecSymbol)
166 myOut.print("Symbol");
171 if (value == SpecInt32Only)
172 myOut.print("Int32");
174 if (value & SpecBoolInt32)
175 myOut.print("Boolint32");
179 if (value & SpecNonBoolInt32)
180 myOut.print("Nonboolint32");
185 if (value & SpecInt52Only)
186 myOut.print("Int52");
188 if ((value & SpecBytecodeDouble) == SpecBytecodeDouble)
189 myOut.print("Bytecodedouble");
191 if (value & SpecAnyIntAsDouble)
192 myOut.print("AnyIntAsDouble");
196 if (value & SpecNonIntAsDouble)
197 myOut.print("Nonintasdouble");
201 if (value & SpecDoublePureNaN)
202 myOut.print("Doublepurenan");
207 if (value & SpecDoubleImpureNaN)
208 out.print("Doubleimpurenan");
210 if (value & SpecBoolean)
215 if (value & SpecOther)
216 myOut.print("Other");
223 out.print(myOut.toCString());
225 if (value & SpecEmpty)
229 // We don't expose this because we don't want anyone relying on the fact that this method currently
230 // just returns string constants.
231 static const char* speculationToAbbreviatedString(SpeculatedType prediction)
233 if (isFinalObjectSpeculation(prediction))
235 if (isArraySpeculation(prediction))
237 if (isStringIdentSpeculation(prediction))
238 return "<StringIdent>";
239 if (isStringSpeculation(prediction))
241 if (isFunctionSpeculation(prediction))
243 if (isInt8ArraySpeculation(prediction))
244 return "<Int8array>";
245 if (isInt16ArraySpeculation(prediction))
246 return "<Int16array>";
247 if (isInt32ArraySpeculation(prediction))
248 return "<Int32array>";
249 if (isUint8ArraySpeculation(prediction))
250 return "<Uint8array>";
251 if (isUint16ArraySpeculation(prediction))
252 return "<Uint16array>";
253 if (isUint32ArraySpeculation(prediction))
254 return "<Uint32array>";
255 if (isFloat32ArraySpeculation(prediction))
256 return "<Float32array>";
257 if (isFloat64ArraySpeculation(prediction))
258 return "<Float64array>";
259 if (isDirectArgumentsSpeculation(prediction))
260 return "<DirectArguments>";
261 if (isScopedArgumentsSpeculation(prediction))
262 return "<ScopedArguments>";
263 if (isStringObjectSpeculation(prediction))
264 return "<StringObject>";
265 if (isRegExpObjectSpeculation(prediction))
266 return "<RegExpObject>";
267 if (isStringOrStringObjectSpeculation(prediction))
268 return "<StringOrStringObject>";
269 if (isObjectSpeculation(prediction))
271 if (isCellSpeculation(prediction))
273 if (isBoolInt32Speculation(prediction))
274 return "<BoolInt32>";
275 if (isInt32Speculation(prediction))
277 if (isAnyIntAsDoubleSpeculation(prediction))
278 return "<AnyIntAsDouble>";
279 if (isInt52Speculation(prediction))
281 if (isAnyIntSpeculation(prediction))
283 if (isDoubleSpeculation(prediction))
285 if (isFullNumberSpeculation(prediction))
287 if (isBooleanSpeculation(prediction))
289 if (isOtherSpeculation(prediction))
291 if (isMiscSpeculation(prediction))
296 void dumpSpeculationAbbreviated(PrintStream& out, SpeculatedType value)
298 out.print(speculationToAbbreviatedString(value));
301 SpeculatedType speculationFromTypedArrayType(TypedArrayType type)
305 return SpecInt8Array;
307 return SpecInt16Array;
309 return SpecInt32Array;
311 return SpecUint8Array;
312 case TypeUint8Clamped:
313 return SpecUint8ClampedArray;
315 return SpecUint16Array;
317 return SpecUint32Array;
319 return SpecFloat32Array;
321 return SpecFloat64Array;
326 RELEASE_ASSERT_NOT_REACHED();
330 SpeculatedType speculationFromClassInfo(const ClassInfo* classInfo)
332 if (classInfo == JSFinalObject::info())
333 return SpecFinalObject;
335 if (classInfo == JSArray::info())
338 if (classInfo == DirectArguments::info())
339 return SpecDirectArguments;
341 if (classInfo == ScopedArguments::info())
342 return SpecScopedArguments;
344 if (classInfo == StringObject::info())
345 return SpecStringObject;
347 if (classInfo == RegExpObject::info())
348 return SpecRegExpObject;
350 if (classInfo->isSubClassOf(JSFunction::info()))
353 if (isTypedView(classInfo->typedArrayStorageType))
354 return speculationFromTypedArrayType(classInfo->typedArrayStorageType);
356 if (classInfo->isSubClassOf(JSObject::info()))
357 return SpecObjectOther;
359 return SpecCellOther;
362 SpeculatedType speculationFromStructure(Structure* structure)
364 if (structure->typeInfo().type() == StringType)
366 if (structure->typeInfo().type() == SymbolType)
368 return speculationFromClassInfo(structure->classInfo());
371 SpeculatedType speculationFromCell(JSCell* cell)
373 if (JSString* string = jsDynamicCast<JSString*>(cell)) {
374 if (const StringImpl* impl = string->tryGetValueImpl()) {
375 if (impl->isAtomic())
376 return SpecStringIdent;
378 return SpecStringVar;
380 return speculationFromStructure(cell->structure());
383 SpeculatedType speculationFromValue(JSValue value)
387 if (value.isInt32()) {
388 if (value.asInt32() & ~1)
389 return SpecNonBoolInt32;
390 return SpecBoolInt32;
392 if (value.isDouble()) {
393 double number = value.asNumber();
394 if (number != number)
395 return SpecDoublePureNaN;
396 if (value.isAnyInt())
397 return SpecAnyIntAsDouble;
398 return SpecNonIntAsDouble;
401 return speculationFromCell(value.asCell());
402 if (value.isBoolean())
404 ASSERT(value.isUndefinedOrNull());
408 TypedArrayType typedArrayTypeFromSpeculation(SpeculatedType type)
410 if (isInt8ArraySpeculation(type))
413 if (isInt16ArraySpeculation(type))
416 if (isInt32ArraySpeculation(type))
419 if (isUint8ArraySpeculation(type))
422 if (isUint8ClampedArraySpeculation(type))
423 return TypeUint8Clamped;
425 if (isUint16ArraySpeculation(type))
428 if (isUint32ArraySpeculation(type))
431 if (isFloat32ArraySpeculation(type))
434 if (isFloat64ArraySpeculation(type))
437 return NotTypedArray;
440 SpeculatedType leastUpperBoundOfStrictlyEquivalentSpeculations(SpeculatedType type)
442 if (type & (SpecAnyInt | SpecAnyIntAsDouble))
443 type |= (SpecAnyInt | SpecAnyIntAsDouble);
444 if (type & SpecString)
449 bool valuesCouldBeEqual(SpeculatedType a, SpeculatedType b)
451 a = leastUpperBoundOfStrictlyEquivalentSpeculations(a);
452 b = leastUpperBoundOfStrictlyEquivalentSpeculations(b);
454 // Anything could be equal to a string.
460 // If both sides are definitely only objects, then equality is fairly sane.
461 if (isObjectSpeculation(a) && isObjectSpeculation(b))
464 // If either side could be an object or not, then we could call toString or
465 // valueOf, which could return anything.
471 // Neither side is an object or string, so the world is relatively sane.
475 SpeculatedType typeOfDoubleSum(SpeculatedType a, SpeculatedType b)
477 SpeculatedType result = a | b;
478 // Impure NaN could become pure NaN during addition because addition may clear bits.
479 if (result & SpecDoubleImpureNaN)
480 result |= SpecDoublePureNaN;
481 // Values could overflow, or fractions could become integers.
482 if (result & SpecDoubleReal)
483 result |= SpecDoubleReal;
487 SpeculatedType typeOfDoubleDifference(SpeculatedType a, SpeculatedType b)
489 return typeOfDoubleSum(a, b);
492 SpeculatedType typeOfDoubleProduct(SpeculatedType a, SpeculatedType b)
494 return typeOfDoubleSum(a, b);
497 static SpeculatedType polluteDouble(SpeculatedType value)
499 // Impure NaN could become pure NaN because the operation could clear some bits.
500 if (value & SpecDoubleImpureNaN)
501 value |= SpecDoubleNaN;
502 // Values could overflow, fractions could become integers, or an error could produce
504 if (value & SpecDoubleReal)
505 value |= SpecDoubleReal | SpecDoublePureNaN;
509 SpeculatedType typeOfDoubleQuotient(SpeculatedType a, SpeculatedType b)
511 return polluteDouble(a | b);
514 SpeculatedType typeOfDoubleMinMax(SpeculatedType a, SpeculatedType b)
516 SpeculatedType result = a | b;
517 // Impure NaN could become pure NaN during addition because addition may clear bits.
518 if (result & SpecDoubleImpureNaN)
519 result |= SpecDoublePureNaN;
523 SpeculatedType typeOfDoubleNegation(SpeculatedType value)
525 // Changing bits can make pure NaN impure and vice versa:
526 // 0xefff000000000000 (pure) - 0xffff000000000000 (impure)
527 if (value & SpecDoubleNaN)
528 value |= SpecDoubleNaN;
529 // We could get negative zero, which mixes SpecAnyIntAsDouble and SpecNotIntAsDouble.
530 // We could also overflow a large negative int into something that is no longer
531 // representable as an int.
532 if (value & SpecDoubleReal)
533 value |= SpecDoubleReal;
537 SpeculatedType typeOfDoubleAbs(SpeculatedType value)
539 return typeOfDoubleNegation(value);
542 SpeculatedType typeOfDoubleRounding(SpeculatedType value)
544 // Double Pure NaN can becomes impure when converted back from Float.
546 if (value & SpecDoubleNaN)
547 value |= SpecDoubleNaN;
548 // We might lose bits, which leads to a value becoming integer-representable.
549 if (value & SpecNonIntAsDouble)
550 value |= SpecAnyIntAsDouble;
554 SpeculatedType typeOfDoublePow(SpeculatedType xValue, SpeculatedType yValue)
556 // Math.pow() always return NaN if the exponent is NaN, unlike std::pow().
557 // We always set a pure NaN in that case.
558 if (yValue & SpecDoubleNaN)
559 xValue |= SpecDoublePureNaN;
560 return polluteDouble(xValue);
563 SpeculatedType typeOfDoubleBinaryOp(SpeculatedType a, SpeculatedType b)
565 return polluteDouble(a | b);
568 SpeculatedType typeOfDoubleUnaryOp(SpeculatedType value)
570 return polluteDouble(value);