Ignore:
Timestamp:
Jan 14, 2019, 2:31:06 PM (6 years ago)
Author:
[email protected]
Message:

[JSC] Do not use asArrayModes() with Structures because it discards TypedArray information
https://bugs.webkit.org/show_bug.cgi?id=193372

Reviewed by Saam Barati.

JSTests:

  • stress/typed-array-array-modes-profile.js: Added.

(foo):

Source/JavaScriptCore:

When RegisteredStructureSet is filtered with AbstractValue, we use structure, SpeculationType, and ArrayModes.
However, we use asArrayModes() function with IndexingMode to compute the ArrayModes in AbstractValue. This is
wrong since this discards TypedArray ArrayModes. As a result, if RegisteredStructureSet with TypedArrays is
filtered with ArrayModes of AbstractValue populated from TypedArrays, we filter all the structures out since
AbstractValue's ArrayModes become NonArray, which is wrong with the TypedArrays' ArrayModes. This leads to
incorrect FTL code generation with MultiGetByOffset etc. nodes because,

  1. AI think that this MultiGetByOffset never succeeds since all the values of RegisteredStructureSet are filtered out by the AbstractValue.
  2. AI says the state of MultiGetByOffset is invalid since AI think it never succeeds.
  3. So subsequent code becomes FTL crash code since AI think the execution should do OSR exit.
  4. Then, FTL emits the code for MultiGetByOffset, and emits crash after that.
  5. But in reality, the incoming value can match to the one of the RegisteredStructureSet value since (1)'s structures are incorrectly filtered by the incorrect ArrayModes.
  6. Then, the execution goes on, and falls into the FTL crash.

This patch fixes the incorrect ArrayModes calculation by the following changes

  1. Rename asArrayModes to asArrayModesIgnoringTypedArrays.
  2. Fix incorrect asArrayModesIgnoringTypedArrays use in our code. Use arrayModesFromStructure instead.
  3. Fix OSR exit code which stores incorrect ArrayModes to the profiles.
  • bytecode/ArrayProfile.cpp:

(JSC::dumpArrayModes):
(JSC::ArrayProfile::computeUpdatedPrediction):

  • bytecode/ArrayProfile.h:

(JSC::asArrayModesIgnoringTypedArrays):
(JSC::arrayModesFromStructure):
(JSC::arrayModesIncludeIgnoringTypedArrays):
(JSC::shouldUseSlowPutArrayStorage):
(JSC::shouldUseFastArrayStorage):
(JSC::shouldUseContiguous):
(JSC::shouldUseDouble):
(JSC::shouldUseInt32):
(JSC::asArrayModes): Deleted.
(JSC::arrayModeFromStructure): Deleted.
(JSC::arrayModesInclude): Deleted.

  • dfg/DFGAbstractValue.cpp:

(JSC::DFG::AbstractValue::observeTransitions):
(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::mergeOSREntryValue):
(JSC::DFG::AbstractValue::contains const):

  • dfg/DFGAbstractValue.h:

(JSC::DFG::AbstractValue::observeTransition):
(JSC::DFG::AbstractValue::validate const):
(JSC::DFG::AbstractValue::observeIndexingTypeTransition):

  • dfg/DFGArrayMode.cpp:

(JSC::DFG::ArrayMode::fromObserved):
(JSC::DFG::ArrayMode::alreadyChecked const):

  • dfg/DFGArrayMode.h:

(JSC::DFG::ArrayMode::structureWouldPassArrayModeFiltering):
(JSC::DFG::ArrayMode::arrayModesThatPassFiltering const):
(JSC::DFG::ArrayMode::arrayModesWithIndexingShape const):

  • dfg/DFGOSRExit.cpp:

(JSC::DFG::OSRExit::executeOSRExit):
(JSC::DFG::OSRExit::compileExit):

  • dfg/DFGRegisteredStructureSet.cpp:

(JSC::DFG::RegisteredStructureSet::filterArrayModes):
(JSC::DFG::RegisteredStructureSet::arrayModesFromStructures const):

  • ftl/FTLOSRExitCompiler.cpp:

(JSC::FTL::compileStub):

  • jit/JITInlines.h:

(JSC::JIT::chooseArrayMode):
(JSC::arrayProfileSaw): Deleted.

  • runtime/JSType.h:

(JSC::isTypedArrayType):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp

    r234184 r239951  
    4848        Array::Conversion converts;
    4949
    50         RELEASE_ASSERT((observed & (asArrayModes(toIndexingShape(type)) | asArrayModes(toIndexingShape(type) | ArrayClass) | asArrayModes(toIndexingShape(type) | ArrayClass | CopyOnWrite))) == observed);
    51 
    52         if (observed & asArrayModes(toIndexingShape(type))) {
    53             if ((observed & asArrayModes(toIndexingShape(type))) == observed)
     50        RELEASE_ASSERT((observed & (asArrayModesIgnoringTypedArrays(toIndexingShape(type)) | asArrayModesIgnoringTypedArrays(toIndexingShape(type) | ArrayClass) | asArrayModesIgnoringTypedArrays(toIndexingShape(type) | ArrayClass | CopyOnWrite))) == observed);
     51
     52        if (observed & asArrayModesIgnoringTypedArrays(toIndexingShape(type))) {
     53            if ((observed & asArrayModesIgnoringTypedArrays(toIndexingShape(type))) == observed)
    5454                isArray = nonArray;
    5555            else
     
    5858            isArray = Array::Array;
    5959
    60         if (action == Array::Write && (observed & asArrayModes(toIndexingShape(type) | ArrayClass | CopyOnWrite)))
     60        if (action == Array::Write && (observed & asArrayModesIgnoringTypedArrays(toIndexingShape(type) | ArrayClass | CopyOnWrite)))
    6161            converts = Array::Convert;
    6262        else
     
    7070    case 0:
    7171        return ArrayMode(Array::Unprofiled);
    72     case asArrayModes(NonArray):
     72    case asArrayModesIgnoringTypedArrays(NonArray):
    7373        if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
    7474            return ArrayMode(Array::SelectUsingArguments, nonArray, Array::OutOfBounds, Array::Convert, action);
    7575        return ArrayMode(Array::SelectUsingPredictions, nonArray, action).withSpeculationFromProfile(locker, profile, makeSafe);
    7676
    77     case asArrayModes(ArrayWithUndecided):
     77    case asArrayModesIgnoringTypedArrays(ArrayWithUndecided):
    7878        if (action == Array::Write)
    7979            return ArrayMode(Array::SelectUsingArguments, Array::Array, Array::OutOfBounds, Array::Convert, action);
    8080        return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    8181       
    82     case asArrayModes(NonArray) | asArrayModes(ArrayWithUndecided):
     82    case asArrayModesIgnoringTypedArrays(NonArray) | asArrayModesIgnoringTypedArrays(ArrayWithUndecided):
    8383        if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
    8484            return ArrayMode(Array::SelectUsingArguments, Array::PossiblyArray, Array::OutOfBounds, Array::Convert, action);
    8585        return ArrayMode(Array::SelectUsingPredictions, action).withSpeculationFromProfile(locker, profile, makeSafe);
    8686
    87     case asArrayModes(NonArrayWithInt32):
    88     case asArrayModes(ArrayWithInt32):
    89     case asArrayModes(CopyOnWriteArrayWithInt32):
    90     case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32):
    91     case asArrayModes(NonArrayWithInt32) | asArrayModes(CopyOnWriteArrayWithInt32):
    92     case asArrayModes(ArrayWithInt32) | asArrayModes(CopyOnWriteArrayWithInt32):
    93     case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32) | asArrayModes(CopyOnWriteArrayWithInt32):
     87    case asArrayModesIgnoringTypedArrays(NonArrayWithInt32):
     88    case asArrayModesIgnoringTypedArrays(ArrayWithInt32):
     89    case asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithInt32):
     90    case asArrayModesIgnoringTypedArrays(NonArrayWithInt32) | asArrayModesIgnoringTypedArrays(ArrayWithInt32):
     91    case asArrayModesIgnoringTypedArrays(NonArrayWithInt32) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithInt32):
     92    case asArrayModesIgnoringTypedArrays(ArrayWithInt32) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithInt32):
     93    case asArrayModesIgnoringTypedArrays(NonArrayWithInt32) | asArrayModesIgnoringTypedArrays(ArrayWithInt32) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithInt32):
    9494        return handleContiguousModes(Array::Int32, observed);
    9595
    96     case asArrayModes(NonArrayWithDouble):
    97     case asArrayModes(ArrayWithDouble):
    98     case asArrayModes(CopyOnWriteArrayWithDouble):
    99     case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble):
    100     case asArrayModes(NonArrayWithDouble) | asArrayModes(CopyOnWriteArrayWithDouble):
    101     case asArrayModes(ArrayWithDouble) | asArrayModes(CopyOnWriteArrayWithDouble):
    102     case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble) | asArrayModes(CopyOnWriteArrayWithDouble):
     96    case asArrayModesIgnoringTypedArrays(NonArrayWithDouble):
     97    case asArrayModesIgnoringTypedArrays(ArrayWithDouble):
     98    case asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithDouble):
     99    case asArrayModesIgnoringTypedArrays(NonArrayWithDouble) | asArrayModesIgnoringTypedArrays(ArrayWithDouble):
     100    case asArrayModesIgnoringTypedArrays(NonArrayWithDouble) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithDouble):
     101    case asArrayModesIgnoringTypedArrays(ArrayWithDouble) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithDouble):
     102    case asArrayModesIgnoringTypedArrays(NonArrayWithDouble) | asArrayModesIgnoringTypedArrays(ArrayWithDouble) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithDouble):
    103103        return handleContiguousModes(Array::Double, observed);
    104104
    105     case asArrayModes(NonArrayWithContiguous):
    106     case asArrayModes(ArrayWithContiguous):
    107     case asArrayModes(CopyOnWriteArrayWithContiguous):
    108     case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous):
    109     case asArrayModes(NonArrayWithContiguous) | asArrayModes(CopyOnWriteArrayWithContiguous):
    110     case asArrayModes(ArrayWithContiguous) | asArrayModes(CopyOnWriteArrayWithContiguous):
    111     case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous) | asArrayModes(CopyOnWriteArrayWithContiguous):
     105    case asArrayModesIgnoringTypedArrays(NonArrayWithContiguous):
     106    case asArrayModesIgnoringTypedArrays(ArrayWithContiguous):
     107    case asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithContiguous):
     108    case asArrayModesIgnoringTypedArrays(NonArrayWithContiguous) | asArrayModesIgnoringTypedArrays(ArrayWithContiguous):
     109    case asArrayModesIgnoringTypedArrays(NonArrayWithContiguous) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithContiguous):
     110    case asArrayModesIgnoringTypedArrays(ArrayWithContiguous) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithContiguous):
     111    case asArrayModesIgnoringTypedArrays(NonArrayWithContiguous) | asArrayModesIgnoringTypedArrays(ArrayWithContiguous) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithContiguous):
    112112        return handleContiguousModes(Array::Contiguous, observed);
    113113
    114     case asArrayModes(NonArrayWithArrayStorage):
     114    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage):
    115115        return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    116     case asArrayModes(NonArrayWithSlowPutArrayStorage):
    117     case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage):
     116    case asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage):
     117    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage):
    118118        return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    119     case asArrayModes(ArrayWithArrayStorage):
     119    case asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage):
    120120        return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    121     case asArrayModes(ArrayWithSlowPutArrayStorage):
    122     case asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
     121    case asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
     122    case asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
    123123        return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    124     case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage):
     124    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage):
    125125        return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    126     case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
    127     case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
     126    case asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
     127    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
    128128        return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    129129    case Int8ArrayMode:
     
    151151            return ArrayMode(Array::Generic, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    152152
    153         if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
     153        if ((observed & asArrayModesIgnoringTypedArrays(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
    154154            return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe);
    155155       
     
    439439       
    440440    case Array::Array: {
    441         if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray)))
     441        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModesIgnoringTypedArrays(shape | IsArray)))
    442442            return true;
    443443        if (value.m_structure.isTop())
     
    456456       
    457457    default: {
    458         if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray)))
     458        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModesIgnoringTypedArrays(shape) | asArrayModesIgnoringTypedArrays(shape | IsArray)))
    459459            return true;
    460460        if (value.m_structure.isTop())
     
    506506       
    507507        case Array::Array: {
    508             if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
     508            if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage)))
    509509                return true;
    510510            if (value.m_structure.isTop())
     
    521521       
    522522        default: {
    523             if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
     523            if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage)))
    524524                return true;
    525525            if (value.m_structure.isTop())
Note: See TracChangeset for help on using the changeset viewer.