Changeset 231882 in webkit


Ignore:
Timestamp:
May 16, 2018 6:49:24 PM (6 years ago)
Author:
sbarati@apple.com
Message:

Constant fold CheckTypeInfoFlags on ImplementsDefaultHasInstance
https://bugs.webkit.org/show_bug.cgi?id=185670

Reviewed by Yusuke Suzuki.

JSTests:

  • microbenchmarks/constant-fold-check-type-info-flags.js: Added.
  • stress/dont-constant-fold-check-type-info-on-bound-function.js: Added.

Source/JavaScriptCore:

This patch makes it so that we constant fold CheckTypeInfoFlags for
ImplementsDefaultHasInstance inside of AI/constant folding. We constant
fold in three ways:

  • When the incoming value is a constant, we just look at its inline type

flags. Since those flags never change after an object is created, this
is sound.

  • Based on the incoming value having a finite structure set. We just iterate

all structures and ensure they have the bit set.

  • Based on speculated type. To do this, I split up SpecFunction into two

subheaps where one is for functions that have the bit set, and one for
functions that don't have the bit set. The latter is currently only comprised
of JSBoundFunctions. To constant fold, we check that the incoming
value only has the SpecFunction type with ImplementsDefaultHasInstance set.

  • bytecode/SpeculatedType.cpp:

(JSC::speculationFromClassInfo):

  • bytecode/SpeculatedType.h:
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileCheckTypeInfoFlags):

  • dfg/DFGStrengthReductionPhase.cpp:

(JSC::DFG::StrengthReductionPhase::handleNode):

  • runtime/JSFunction.cpp:

(JSC::JSFunction::JSFunction):
(JSC::JSFunction::assertTypeInfoFlagInvariants):

  • runtime/JSFunction.h:

(JSC::JSFunction::assertTypeInfoFlagInvariants):

  • runtime/JSFunctionInlines.h:

(JSC::JSFunction::JSFunction):

Location:
trunk
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r231878 r231882  
     12018-05-16  Saam Barati  <sbarati@apple.com>
     2
     3        Constant fold CheckTypeInfoFlags on ImplementsDefaultHasInstance
     4        https://bugs.webkit.org/show_bug.cgi?id=185670
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        * microbenchmarks/constant-fold-check-type-info-flags.js: Added.
     9        * stress/dont-constant-fold-check-type-info-on-bound-function.js: Added.
     10
    1112018-05-16  Commit Queue  <commit-queue@webkit.org>
    212
  • trunk/Source/JavaScriptCore/ChangeLog

    r231881 r231882  
     12018-05-16  Saam Barati  <sbarati@apple.com>
     2
     3        Constant fold CheckTypeInfoFlags on ImplementsDefaultHasInstance
     4        https://bugs.webkit.org/show_bug.cgi?id=185670
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        This patch makes it so that we constant fold CheckTypeInfoFlags for
     9        ImplementsDefaultHasInstance inside of AI/constant folding. We constant
     10        fold in three ways:
     11        - When the incoming value is a constant, we just look at its inline type
     12        flags. Since those flags never change after an object is created, this
     13        is sound.
     14        - Based on the incoming value having a finite structure set. We just iterate
     15        all structures and ensure they have the bit set.
     16        - Based on speculated type. To do this, I split up SpecFunction into two
     17        subheaps where one is for functions that have the bit set, and one for
     18        functions that don't have the bit set. The latter is currently only comprised
     19        of JSBoundFunctions. To constant fold, we check that the incoming
     20        value only has the SpecFunction type with ImplementsDefaultHasInstance set.
     21
     22        * bytecode/SpeculatedType.cpp:
     23        (JSC::speculationFromClassInfo):
     24        * bytecode/SpeculatedType.h:
     25        * dfg/DFGAbstractInterpreterInlines.h:
     26        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     27        * dfg/DFGConstantFoldingPhase.cpp:
     28        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     29        * dfg/DFGSpeculativeJIT.cpp:
     30        (JSC::DFG::SpeculativeJIT::compileCheckTypeInfoFlags):
     31        * dfg/DFGStrengthReductionPhase.cpp:
     32        (JSC::DFG::StrengthReductionPhase::handleNode):
     33        * runtime/JSFunction.cpp:
     34        (JSC::JSFunction::JSFunction):
     35        (JSC::JSFunction::assertTypeInfoFlagInvariants):
     36        * runtime/JSFunction.h:
     37        (JSC::JSFunction::assertTypeInfoFlagInvariants):
     38        * runtime/JSFunctionInlines.h:
     39        (JSC::JSFunction::JSFunction):
     40
    1412018-05-16  Devin Rousso  <webkit@devinrousso.com>
    242
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp

    r230516 r231882  
    3333#include "JSArray.h"
    3434#include "JSBigInt.h"
     35#include "JSBoundFunction.h"
    3536#include "JSCInlines.h"
    3637#include "JSFunction.h"
     
    433434        return SpecProxyObject;
    434435   
    435     if (classInfo->isSubClassOf(JSFunction::info()))
    436         return SpecFunction;
     436    if (classInfo->isSubClassOf(JSFunction::info())) {
     437        if (classInfo == JSBoundFunction::info())
     438            return SpecFunctionWithNonDefaultHasInstance;
     439        return SpecFunctionWithDefaultHasInstance;
     440    }
    437441   
    438442    if (isTypedView(classInfo->typedArrayStorageType))
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h

    r230516 r231882  
    3939
    4040typedef uint64_t SpeculatedType;
    41 static const SpeculatedType SpecNone               = 0; // We don't know anything yet.
    42 static const SpeculatedType SpecFinalObject        = 1ull << 0; // It's definitely a JSFinalObject.
    43 static const SpeculatedType SpecArray              = 1ull << 1; // It's definitely a JSArray.
    44 static const SpeculatedType SpecFunction           = 1ull << 2; // It's definitely a JSFunction.
    45 static const SpeculatedType SpecInt8Array          = 1ull << 3; // It's definitely an Int8Array or one of its subclasses.
    46 static const SpeculatedType SpecInt16Array         = 1ull << 4; // It's definitely an Int16Array or one of its subclasses.
    47 static const SpeculatedType SpecInt32Array         = 1ull << 5; // It's definitely an Int32Array or one of its subclasses.
    48 static const SpeculatedType SpecUint8Array         = 1ull << 6; // It's definitely an Uint8Array or one of its subclasses.
    49 static const SpeculatedType SpecUint8ClampedArray  = 1ull << 7; // It's definitely an Uint8ClampedArray or one of its subclasses.
    50 static const SpeculatedType SpecUint16Array        = 1ull << 8; // It's definitely an Uint16Array or one of its subclasses.
    51 static const SpeculatedType SpecUint32Array        = 1ull << 9; // It's definitely an Uint32Array or one of its subclasses.
    52 static const SpeculatedType SpecFloat32Array       = 1ull << 10; // It's definitely an Uint16Array or one of its subclasses.
    53 static const SpeculatedType SpecFloat64Array       = 1ull << 11; // It's definitely an Uint16Array or one of its subclasses.
    54 static const SpeculatedType SpecTypedArrayView     = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array;
    55 static const SpeculatedType SpecDirectArguments    = 1ull << 12; // It's definitely a DirectArguments object.
    56 static const SpeculatedType SpecScopedArguments    = 1ull << 13; // It's definitely a ScopedArguments object.
    57 static const SpeculatedType SpecStringObject       = 1ull << 14; // It's definitely a StringObject.
    58 static const SpeculatedType SpecRegExpObject       = 1ull << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject).
    59 static const SpeculatedType SpecMapObject          = 1ull << 16; // It's definitely a Map object or one of its subclasses.
    60 static const SpeculatedType SpecSetObject          = 1ull << 17; // It's definitely a Set object or one of its subclasses.
    61 static const SpeculatedType SpecWeakMapObject      = 1ull << 18; // It's definitely a WeakMap object or one of its subclasses.
    62 static const SpeculatedType SpecWeakSetObject      = 1ull << 19; // It's definitely a WeakSet object or one of its subclasses.
    63 static const SpeculatedType SpecProxyObject        = 1ull << 20; // It's definitely a Proxy object or one of its subclasses.
    64 static const SpeculatedType SpecDerivedArray       = 1ull << 21; // It's definitely a DerivedArray object.
    65 static const SpeculatedType SpecObjectOther        = 1ull << 22; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
    66 static const SpeculatedType SpecObject             = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther; // Bitmask used for testing for any kind of object prediction.
    67 static const SpeculatedType SpecStringIdent        = 1ull << 23; // It's definitely a JSString, and it's an identifier.
    68 static const SpeculatedType SpecStringVar          = 1ull << 24; // It's definitely a JSString, and it's not an identifier.
    69 static const SpeculatedType SpecString             = SpecStringIdent | SpecStringVar; // It's definitely a JSString.
    70 static const SpeculatedType SpecSymbol             = 1ull << 25; // It's definitely a Symbol.
    71 static const SpeculatedType SpecCellOther          = 1ull << 26; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString, BigInt, or Symbol.
    72 static const SpeculatedType SpecBoolInt32          = 1ull << 27; // It's definitely an Int32 with value 0 or 1.
    73 static const SpeculatedType SpecNonBoolInt32       = 1ull << 28; // It's definitely an Int32 with value other than 0 or 1.
    74 static const SpeculatedType SpecInt32Only          = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32.
    75 static const SpeculatedType SpecInt52Only          = 1ull << 29; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.
    76 static const SpeculatedType SpecAnyInt             = SpecInt32Only | SpecInt52Only; // It's something that we can do machine int arithmetic on.
    77 static const SpeculatedType SpecAnyIntAsDouble     = 1ull << 30; // It's definitely an Int52 and it's inside a double.
    78 static const SpeculatedType SpecNonIntAsDouble     = 1ull << 31; // It's definitely not an Int52 but it's a real number and it's a double.
    79 static const SpeculatedType SpecDoubleReal         = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double.
    80 static const SpeculatedType SpecDoublePureNaN      = 1ull << 32; // It's definitely a NaN that is safe to tag (i.e. pure).
    81 static const SpeculatedType SpecDoubleImpureNaN    = 1ull << 33; // It's definitely a NaN that is unsafe to tag (i.e. impure).
    82 static const SpeculatedType SpecDoubleNaN          = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN.
    83 static const SpeculatedType SpecBytecodeDouble     = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN.
    84 static const SpeculatedType SpecFullDouble         = SpecDoubleReal | SpecDoubleNaN; // It's either a non-NaN or a NaN double.
    85 static const SpeculatedType SpecBytecodeRealNumber = SpecInt32Only | SpecDoubleReal; // It's either an Int32 or a DoubleReal.
    86 static const SpeculatedType SpecFullRealNumber     = SpecAnyInt | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or a Int52.
    87 static const SpeculatedType SpecBytecodeNumber     = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
    88 static const SpeculatedType SpecFullNumber         = SpecAnyInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
    89 static const SpeculatedType SpecBoolean            = 1ull << 34; // It's definitely a Boolean.
    90 static const SpeculatedType SpecOther              = 1ull << 35; // It's definitely either Null or Undefined.
    91 static const SpeculatedType SpecMisc               = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined.
    92 static const SpeculatedType SpecEmpty              = 1ull << 36; // It's definitely an empty value marker.
    93 static const SpeculatedType SpecBigInt             = 1ull << 37; // It's definitely a BigInt.
    94 static const SpeculatedType SpecPrimitive          = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue.
    95 static const SpeculatedType SpecCell               = SpecObject | SpecString | SpecSymbol | SpecCellOther | SpecBigInt; // It's definitely a JSCell.
    96 static const SpeculatedType SpecHeapTop            = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
    97 static const 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.
    98 static const SpeculatedType SpecFullTop            = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers.
     41static const SpeculatedType SpecNone                              = 0; // We don't know anything yet.
     42static const SpeculatedType SpecFinalObject                       = 1ull << 0; // It's definitely a JSFinalObject.
     43static const SpeculatedType SpecArray                             = 1ull << 1; // It's definitely a JSArray.
     44static const SpeculatedType SpecFunctionWithDefaultHasInstance    = 1ull << 2; // It's definitely a JSFunction that has its ImplementsDefaultHasInstance type info flags bit set.
     45static const SpeculatedType SpecFunctionWithNonDefaultHasInstance = 1ull << 3; // It's definitely a JSFunction that does not have its ImplementsDefaultHasInstance type info flags bit set.
     46static const SpeculatedType SpecFunction                          = SpecFunctionWithDefaultHasInstance | SpecFunctionWithNonDefaultHasInstance; // It's definitely a JSFunction.
     47static const SpeculatedType SpecInt8Array                         = 1ull << 4; // It's definitely an Int8Array or one of its subclasses.
     48static const SpeculatedType SpecInt16Array                        = 1ull << 5; // It's definitely an Int16Array or one of its subclasses.
     49static const SpeculatedType SpecInt32Array                        = 1ull << 6; // It's definitely an Int32Array or one of its subclasses.
     50static const SpeculatedType SpecUint8Array                        = 1ull << 7; // It's definitely an Uint8Array or one of its subclasses.
     51static const SpeculatedType SpecUint8ClampedArray                 = 1ull << 8; // It's definitely an Uint8ClampedArray or one of its subclasses.
     52static const SpeculatedType SpecUint16Array                       = 1ull << 9; // It's definitely an Uint16Array or one of its subclasses.
     53static const SpeculatedType SpecUint32Array                       = 1ull << 10; // It's definitely an Uint32Array or one of its subclasses.
     54static const SpeculatedType SpecFloat32Array                      = 1ull << 11; // It's definitely an Uint16Array or one of its subclasses.
     55static const SpeculatedType SpecFloat64Array                      = 1ull << 12; // It's definitely an Uint16Array or one of its subclasses.
     56static const SpeculatedType SpecTypedArrayView                    = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array;
     57static const SpeculatedType SpecDirectArguments                   = 1ull << 13; // It's definitely a DirectArguments object.
     58static const SpeculatedType SpecScopedArguments                   = 1ull << 14; // It's definitely a ScopedArguments object.
     59static const SpeculatedType SpecStringObject                      = 1ull << 15; // It's definitely a StringObject.
     60static const SpeculatedType SpecRegExpObject                      = 1ull << 16; // It's definitely a RegExpObject (and not any subclass of RegExpObject).
     61static const SpeculatedType SpecMapObject                         = 1ull << 17; // It's definitely a Map object or one of its subclasses.
     62static const SpeculatedType SpecSetObject                         = 1ull << 18; // It's definitely a Set object or one of its subclasses.
     63static const SpeculatedType SpecWeakMapObject                     = 1ull << 19; // It's definitely a WeakMap object or one of its subclasses.
     64static const SpeculatedType SpecWeakSetObject                     = 1ull << 20; // It's definitely a WeakSet object or one of its subclasses.
     65static const SpeculatedType SpecProxyObject                       = 1ull << 21; // It's definitely a Proxy object or one of its subclasses.
     66static const SpeculatedType SpecDerivedArray                      = 1ull << 22; // It's definitely a DerivedArray object.
     67static const SpeculatedType SpecObjectOther                       = 1ull << 23; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
     68static const SpeculatedType SpecObject                            = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther; // Bitmask used for testing for any kind of object prediction.
     69static const SpeculatedType SpecStringIdent                       = 1ull << 24; // It's definitely a JSString, and it's an identifier.
     70static const SpeculatedType SpecStringVar                         = 1ull << 25; // It's definitely a JSString, and it's not an identifier.
     71static const SpeculatedType SpecString                            = SpecStringIdent | SpecStringVar; // It's definitely a JSString.
     72static const SpeculatedType SpecSymbol                            = 1ull << 26; // It's definitely a Symbol.
     73static const SpeculatedType SpecCellOther                         = 1ull << 27; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString, BigInt, or Symbol.
     74static const SpeculatedType SpecBoolInt32                         = 1ull << 28; // It's definitely an Int32 with value 0 or 1.
     75static const SpeculatedType SpecNonBoolInt32                      = 1ull << 29; // It's definitely an Int32 with value other than 0 or 1.
     76static const SpeculatedType SpecInt32Only                         = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32.
     77static const SpeculatedType SpecInt52Only                         = 1ull << 30; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.
     78static const SpeculatedType SpecAnyInt                            = SpecInt32Only | SpecInt52Only; // It's something that we can do machine int arithmetic on.
     79static const SpeculatedType SpecAnyIntAsDouble                    = 1ull << 31; // It's definitely an Int52 and it's inside a double.
     80static const SpeculatedType SpecNonIntAsDouble                    = 1ull << 32; // It's definitely not an Int52 but it's a real number and it's a double.
     81static const SpeculatedType SpecDoubleReal                        = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double.
     82static const SpeculatedType SpecDoublePureNaN                     = 1ull << 33; // It's definitely a NaN that is safe to tag (i.e. pure).
     83static const SpeculatedType SpecDoubleImpureNaN                   = 1ull << 34; // It's definitely a NaN that is unsafe to tag (i.e. impure).
     84static const SpeculatedType SpecDoubleNaN                         = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN.
     85static const SpeculatedType SpecBytecodeDouble                    = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN.
     86static const SpeculatedType SpecFullDouble                        = SpecDoubleReal | SpecDoubleNaN; // It's either a non-NaN or a NaN double.
     87static const SpeculatedType SpecBytecodeRealNumber                = SpecInt32Only | SpecDoubleReal; // It's either an Int32 or a DoubleReal.
     88static const SpeculatedType SpecFullRealNumber                    = SpecAnyInt | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or a Int52.
     89static const SpeculatedType SpecBytecodeNumber                    = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
     90static const SpeculatedType SpecFullNumber                        = SpecAnyInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
     91static const SpeculatedType SpecBoolean                           = 1ull << 35; // It's definitely a Boolean.
     92static const SpeculatedType SpecOther                             = 1ull << 36; // It's definitely either Null or Undefined.
     93static const SpeculatedType SpecMisc                              = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined.
     94static const SpeculatedType SpecEmpty                             = 1ull << 37; // It's definitely an empty value marker.
     95static const SpeculatedType SpecBigInt                            = 1ull << 38; // It's definitely a BigInt.
     96static const SpeculatedType SpecPrimitive                         = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue.
     97static const SpeculatedType SpecCell                              = SpecObject | SpecString | SpecSymbol | SpecCellOther | SpecBigInt; // It's definitely a JSCell.
     98static const SpeculatedType SpecHeapTop                           = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
     99static const 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.
     100static const SpeculatedType SpecFullTop                           = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers.
    99101
    100102// SpecCellCheck is the type set representing the values that can flow through a cell check.
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r231871 r231882  
    34383438    case CheckTierUpInLoop:
    34393439    case CheckTierUpAtReturn:
    3440     case CheckTypeInfoFlags:
    34413440    case SuperSamplerBegin:
    34423441    case SuperSamplerEnd:
     
    34463445    case ExitOK:
    34473446        break;
     3447
     3448    case CheckTypeInfoFlags: {
     3449        const AbstractValue& abstractValue = forNode(node->child1());
     3450        unsigned bits = node->typeInfoOperand();
     3451        ASSERT(bits);
     3452        if (bits == ImplementsDefaultHasInstance) {
     3453            if (abstractValue.m_type == SpecFunctionWithDefaultHasInstance) {
     3454                m_state.setFoundConstants(true);
     3455                break;
     3456            }
     3457        }
     3458
     3459        if (JSValue value = abstractValue.value()) {
     3460            if (value.isCell()) {
     3461                // This works because if we see a cell here, we know it's fully constructed
     3462                // and we can read its inline type info flags. These flags don't change over the
     3463                // object's lifetime.
     3464                if ((value.asCell()->inlineTypeFlags() & bits) == bits) {
     3465                    m_state.setFoundConstants(true);
     3466                    break;
     3467                }
     3468            }
     3469        }
     3470
     3471        if (abstractValue.m_structure.isFinite()) {
     3472            bool ok = true;
     3473            abstractValue.m_structure.forEach([&] (RegisteredStructure structure) {
     3474                ok &= (structure->typeInfo().inlineTypeFlags() & bits) == bits;
     3475            });
     3476            if (ok) {
     3477                m_state.setFoundConstants(true);
     3478                break;
     3479            }
     3480        }
     3481
     3482        break;
     3483    }
    34483484
    34493485    case ParseInt: {
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r231733 r231882  
    807807                break;
    808808            }
     809
     810            case CheckTypeInfoFlags: {
     811                const AbstractValue& abstractValue = m_state.forNode(node->child1());
     812                unsigned bits = node->typeInfoOperand();
     813                ASSERT(bits);
     814                if (bits == ImplementsDefaultHasInstance) {
     815                    if (abstractValue.m_type == SpecFunctionWithDefaultHasInstance) {
     816                        changed = true;
     817                        node->remove(m_graph);
     818                        break;
     819                    }
     820                }
     821
     822                if (JSValue value = abstractValue.value()) {
     823                    if (value.isCell()) {
     824                        // This works because if we see a cell here, we know it's fully constructed
     825                        // and we can read its inline type info flags. These flags don't change over the
     826                        // object's lifetime.
     827                        if ((value.asCell()->inlineTypeFlags() & bits) == bits) {
     828                            changed = true;
     829                            node->remove(m_graph);
     830                            break;
     831                        }
     832                    }
     833                }
     834
     835                if (abstractValue.m_structure.isFinite()) {
     836                    bool ok = true;
     837                    abstractValue.m_structure.forEach([&] (RegisteredStructure structure) {
     838                        ok &= (structure->typeInfo().inlineTypeFlags() & bits) == bits;
     839                    });
     840                    if (ok) {
     841                        changed = true;
     842                        node->remove(m_graph);
     843                        break;
     844                    }
     845                }
     846
     847                break;
     848            }
    809849               
    810850            case PhantomNewObject:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r231839 r231882  
    33903390    GPRReg baseGPR = base.gpr();
    33913391
     3392    // FIXME: This only works for checking if a single bit is set. If we want to check more
     3393    // than one bit at once, we'll need to fix this:
     3394    // https://bugs.webkit.org/show_bug.cgi?id=185705
    33923395    speculationCheck(BadTypeInfoFlags, JSValueRegs(), 0, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(node->typeInfoOperand())));
    33933396
  • trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp

    r231193 r231882  
    304304        }
    305305
    306         // FIXME: we should probably do this in constant folding but this currently relies on an OSR exit rule.
     306        // FIXME: we should probably do this in constant folding but this currently relies on OSR exit history:
    307307        // https://bugs.webkit.org/show_bug.cgi?id=154832
    308308        case OverridesHasInstance: {
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r230662 r231882  
    101101    , m_executable()
    102102{
     103    assertTypeInfoFlagInvariants();
    103104}
    104105
     
    790791}
    791792
     793#if !ASSERT_DISABLED
     794void JSFunction::assertTypeInfoFlagInvariants()
     795{
     796    // If you change this, you'll need to update speculationFromClassInfo.
     797    const ClassInfo* info = classInfo(*vm());
     798    if (!(inlineTypeFlags() & ImplementsDefaultHasInstance))
     799        RELEASE_ASSERT(info == JSBoundFunction::info());
     800    else
     801        RELEASE_ASSERT(info != JSBoundFunction::info());
     802}
     803#endif
     804
    792805} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSFunction.h

    r231839 r231882  
    209209    PropertyStatus reifyLazyBoundNameIfNeeded(VM&, ExecState*, PropertyName);
    210210
     211#if ASSERT_DISABLED
     212    void assertTypeInfoFlagInvariants() { }
     213#else
     214    void assertTypeInfoFlagInvariants();
     215#endif
     216
    211217    friend class LLIntOffsetsExtractor;
    212218
  • trunk/Source/JavaScriptCore/runtime/JSFunctionInlines.h

    r229547 r231882  
    4444    , m_rareData()
    4545{
     46    assertTypeInfoFlagInvariants();
    4647}
    4748
Note: See TracChangeset for help on using the changeset viewer.