Ignore:
Timestamp:
May 5, 2017, 3:35:31 PM (8 years ago)
Author:
[email protected]
Message:

putDirectIndex does not properly do defineOwnProperty
https://bugs.webkit.org/show_bug.cgi?id=171591
<rdar://problem/31735695>

Reviewed by Geoffrey Garen.

JSTests:

  • stress/array-prototype-splice-making-typed-array.js:

(test):

  • stress/array-species-config-array-constructor.js:

(shouldThrow):
(test):

  • stress/put-direct-index-broken-2.js: Added.

(assert):
(test):
(makeLengthWritable):
(set get restoreOldDesc):

  • stress/put-direct-index-broken.js: Added.

(whatToTest):
(tryRunning):
(tryItOut):

  • stress/put-indexed-getter-setter.js: Added.

(foo.X.prototype.set 7):
(foo.X.prototype.get 7):
(foo.X):
(foo):

Source/JavaScriptCore:

This patch fixes putDirectIndex and its JIT implementations to be
compatible with the ES6 spec. I think our code became out of date
when we implemented ArraySpeciesCreate since ArraySpeciesCreate may
return arbitrary objects. We perform putDirectIndex on that arbitrary
object. The behavior we want is as if we performed defineProperty({configurable:true, enumerable:true, writable:true}).
However, we weren't doing this. putDirectIndex assumed it could just splat
data into any descendent of JSObject's butterfly. For example, this means
we'd just splat into the butterfly of a typed array, even though a typed
array doesn't use its butterfly to store its indexed properties in the usual
way. Also, typed array properties are non-configurable, so this operation
should throw. This also means if we saw a ProxyObject, we'd just splat
into its butterfly, but this is obviously wrong because ProxyObject should
intercept the defineProperty operation.

This patch fixes this issue by adding a whitelist of cell types that can
go down putDirectIndex's fast path. Anything not in that whitelist will
simply call into defineOwnProperty.

  • bytecode/ByValInfo.h:

(JSC::jitArrayModePermitsPutDirect):

  • dfg/DFGArrayMode.cpp:

(JSC::DFG::ArrayMode::refine):

  • jit/JITOperations.cpp:
  • runtime/ArrayPrototype.cpp:

(JSC::arrayProtoFuncSplice):

  • runtime/ClonedArguments.cpp:

(JSC::ClonedArguments::createStructure):

  • runtime/JSGenericTypedArrayViewInlines.h:

(JSC::JSGenericTypedArrayView<Adaptor>::defineOwnProperty):

  • runtime/JSObject.cpp:

(JSC::canDoFastPutDirectIndex):
(JSC::JSObject::defineOwnIndexedProperty):
(JSC::JSObject::putDirectIndexSlowOrBeyondVectorLength):
(JSC::JSObject::putDirectIndexBeyondVectorLength): Deleted.

  • runtime/JSObject.h:

(JSC::JSObject::putDirectIndex):
(JSC::JSObject::canSetIndexQuicklyForPutDirect): Deleted.

  • runtime/JSType.h:
File:
1 edited

Legend:

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

    r215600 r216279  
    187187    // to value profiling, but the array profile tells us something else, then we
    188188    // should just trust the array profile.
     189
     190    auto typedArrayResult = [&] (ArrayMode result) -> ArrayMode {
     191        if (node->op() == PutByValDirect) {
     192            // This is semantically identical to defineOwnProperty({configurable: true, writable:true, enumerable:true}),
     193            // which we can't model as a simple store to the typed array since typed array indexed properties
     194            // are non-configurable.
     195            return ArrayMode(Array::Generic);
     196        }
     197        return result;
     198    };
    189199   
    190200    switch (type()) {
     
    236246    case Array::Float32Array:
    237247    case Array::Float64Array:
    238         switch (node->op()) {
    239         case PutByVal:
     248        if (node->op() == PutByVal) {
    240249            if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds())
    241                 return withSpeculation(Array::OutOfBounds);
    242             return withSpeculation(Array::InBounds);
    243         default:
    244             return withSpeculation(Array::InBounds);
    245         }
    246         return *this;
     250                return typedArrayResult(withSpeculation(Array::OutOfBounds));
     251        }
     252        return typedArrayResult(withSpeculation(Array::InBounds));
    247253    case Array::Unprofiled:
    248254    case Array::SelectUsingPredictions: {
     
    275281            break;
    276282        }
    277        
     283
    278284        if (isInt8ArraySpeculation(base))
    279             return result.withType(Array::Int8Array);
     285            return typedArrayResult(result.withType(Array::Int8Array));
    280286       
    281287        if (isInt16ArraySpeculation(base))
    282             return result.withType(Array::Int16Array);
     288            return typedArrayResult(result.withType(Array::Int16Array));
    283289       
    284290        if (isInt32ArraySpeculation(base))
    285             return result.withType(Array::Int32Array);
     291            return typedArrayResult(result.withType(Array::Int32Array));
    286292       
    287293        if (isUint8ArraySpeculation(base))
    288             return result.withType(Array::Uint8Array);
     294            return typedArrayResult(result.withType(Array::Uint8Array));
    289295       
    290296        if (isUint8ClampedArraySpeculation(base))
    291             return result.withType(Array::Uint8ClampedArray);
     297            return typedArrayResult(result.withType(Array::Uint8ClampedArray));
    292298       
    293299        if (isUint16ArraySpeculation(base))
    294             return result.withType(Array::Uint16Array);
     300            return typedArrayResult(result.withType(Array::Uint16Array));
    295301       
    296302        if (isUint32ArraySpeculation(base))
    297             return result.withType(Array::Uint32Array);
     303            return typedArrayResult(result.withType(Array::Uint32Array));
    298304       
    299305        if (isFloat32ArraySpeculation(base))
    300             return result.withType(Array::Float32Array);
     306            return typedArrayResult(result.withType(Array::Float32Array));
    301307       
    302308        if (isFloat64ArraySpeculation(base))
    303             return result.withType(Array::Float64Array);
     309            return typedArrayResult(result.withType(Array::Float64Array));
    304310
    305311        if (type() == Array::Unprofiled)
Note: See TracChangeset for help on using the changeset viewer.