Changeset 269574 in webkit
- Timestamp:
- Nov 8, 2020 9:02:22 PM (21 months ago)
- Location:
- trunk
- Files:
-
- 12 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/test262/expectations.yaml (modified) (3 diffs)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/runtime/ArrayBuffer.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/ArrayBuffer.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/ArrayBufferSharingMode.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/ArrayPrototype.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSArrayBufferPrototype.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/JSGlobalObject.cpp (modified) (8 diffs)
-
Source/JavaScriptCore/runtime/JSGlobalObject.h (modified) (8 diffs)
-
Source/WTF/ChangeLog (modified) (1 diff)
-
Source/WTF/wtf/PlatformEnable.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r269552 r269574 1 2020-11-08 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] Support @@species in ArrayBuffer / SharedArrayBuffer slice 4 https://bugs.webkit.org/show_bug.cgi?id=218697 5 6 Reviewed by Ross Kirsling. 7 8 * test262/expectations.yaml: 9 1 10 2020-11-06 Dmitry Bezhetskov <dbezhetskov@igalia.com> 2 11 -
trunk/JSTests/test262/expectations.yaml
r269531 r269574 604 604 test/annexB/language/global-code/switch-dflt-global-skip-early-err.js: 605 605 default: "SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'f' in strict mode." 606 test/built-ins/ArrayBuffer/prototype/slice/species-constructor-is-not-object.js:607 default: 'Test262Error: `constructor` value is null Expected a TypeError to be thrown but no exception was thrown at all'608 strict mode: 'Test262Error: `constructor` value is null Expected a TypeError to be thrown but no exception was thrown at all'609 test/built-ins/ArrayBuffer/prototype/slice/species-is-not-constructor.js:610 default: 'Test262Error: `constructor[Symbol.species]` value is Object Expected a TypeError to be thrown but no exception was thrown at all'611 strict mode: 'Test262Error: `constructor[Symbol.species]` value is Object Expected a TypeError to be thrown but no exception was thrown at all'612 test/built-ins/ArrayBuffer/prototype/slice/species-is-not-object.js:613 default: 'Test262Error: `constructor[Symbol.species]` value is Boolean Expected a TypeError to be thrown but no exception was thrown at all'614 strict mode: 'Test262Error: `constructor[Symbol.species]` value is Boolean Expected a TypeError to be thrown but no exception was thrown at all'615 test/built-ins/ArrayBuffer/prototype/slice/species-returns-larger-arraybuffer.js:616 default: 'Test262Error: Expected SameValue(«8», «10») to be true'617 strict mode: 'Test262Error: Expected SameValue(«8», «10») to be true'618 test/built-ins/ArrayBuffer/prototype/slice/species-returns-not-arraybuffer.js:619 default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'620 strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'621 test/built-ins/ArrayBuffer/prototype/slice/species-returns-same-arraybuffer.js:622 default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'623 strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'624 test/built-ins/ArrayBuffer/prototype/slice/species-returns-smaller-arraybuffer.js:625 default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'626 strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'627 test/built-ins/ArrayBuffer/prototype/slice/species.js:628 default: 'Test262Error: Expected SameValue(«[object ArrayBuffer]», «undefined») to be true'629 strict mode: 'Test262Error: Expected SameValue(«[object ArrayBuffer]», «undefined») to be true'630 606 test/built-ins/Date/UTC/fp-evaluation-order.js: 631 607 default: 'Test262Error: order of operations / precision in MakeTime Expected SameValue(«NaN», «29312») to be true' … … 848 824 default: 'SyntaxError: Invalid regular expression: number too large in {} quantifier' 849 825 strict mode: 'SyntaxError: Invalid regular expression: number too large in {} quantifier' 850 test/built-ins/SharedArrayBuffer/prototype/slice/species-constructor-is-not-object.js:851 default: 'Test262Error: `constructor` value is null Expected a TypeError to be thrown but no exception was thrown at all'852 strict mode: 'Test262Error: `constructor` value is null Expected a TypeError to be thrown but no exception was thrown at all'853 test/built-ins/SharedArrayBuffer/prototype/slice/species-is-not-constructor.js:854 default: 'Test262Error: `constructor[Symbol.species]` value is Object Expected a TypeError to be thrown but no exception was thrown at all'855 strict mode: 'Test262Error: `constructor[Symbol.species]` value is Object Expected a TypeError to be thrown but no exception was thrown at all'856 test/built-ins/SharedArrayBuffer/prototype/slice/species-is-not-object.js:857 default: 'Test262Error: `constructor[Symbol.species]` value is Boolean Expected a TypeError to be thrown but no exception was thrown at all'858 strict mode: 'Test262Error: `constructor[Symbol.species]` value is Boolean Expected a TypeError to be thrown but no exception was thrown at all'859 test/built-ins/SharedArrayBuffer/prototype/slice/species-returns-larger-arraybuffer.js:860 default: 'Test262Error: Expected SameValue(«8», «10») to be true'861 strict mode: 'Test262Error: Expected SameValue(«8», «10») to be true'862 test/built-ins/SharedArrayBuffer/prototype/slice/species-returns-not-arraybuffer.js:863 default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'864 strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'865 test/built-ins/SharedArrayBuffer/prototype/slice/species-returns-same-arraybuffer.js:866 default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'867 strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'868 test/built-ins/SharedArrayBuffer/prototype/slice/species-returns-smaller-arraybuffer.js:869 default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'870 strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'871 test/built-ins/SharedArrayBuffer/prototype/slice/species.js:872 default: 'Test262Error: Expected SameValue(«[object SharedArrayBuffer]», «undefined») to be true'873 strict mode: 'Test262Error: Expected SameValue(«[object SharedArrayBuffer]», «undefined») to be true'874 826 test/built-ins/TypedArray/prototype/every/callbackfn-detachbuffer.js: 875 827 default: 'Test262Error: Expected a TypeError but got a Test262Error (Testing with Float64Array.)' … … 2746 2698 test/language/statements/class/method/forbidden-ext/b2/cls-decl-meth-forbidden-ext-indirect-access-prop-caller.js: 2747 2699 default: 'TypeError: Function.caller used to retrieve strict caller' 2748 test/language/statements/class/subclass/builtin-objects/ArrayBuffer/regular-subclassing.js:2749 default: 'Test262Error: Expected true but got false'2750 strict mode: 'Test262Error: Expected true but got false'2751 2700 test/language/statements/const/dstr/ary-init-iter-get-err-array-prototype.js: 2752 2701 default: 'TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function' -
trunk/Source/JavaScriptCore/ChangeLog
r269552 r269574 1 2020-11-08 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] Support @@species in ArrayBuffer / SharedArrayBuffer slice 4 https://bugs.webkit.org/show_bug.cgi?id=218697 5 6 Reviewed by Ross Kirsling. 7 8 This patch adds support for @@species in ArrayBuffer/SharedArrayBuffer.prototype.slice. 9 We leverage the mechanism similar to Array's @@species handling: adding fast path with watchpoint. 10 When we found that some of critical properties (e.g. %Prototype%.constructor, %Constructor%[@@species]) 11 are modified, watchpoint is fired and we go to the slow path. Until that, we use fast path that is 12 basically the same to the code before this patch. 13 14 * runtime/ArrayBuffer.cpp: 15 (JSC::ArrayBuffer::slice const): 16 (JSC::ArrayBuffer::sliceWithClampedIndex const): 17 (JSC::ArrayBuffer::sliceImpl const): Deleted. 18 * runtime/ArrayBuffer.h: 19 * runtime/ArrayBufferSharingMode.h: 20 * runtime/ArrayPrototype.cpp: 21 (JSC::speciesWatchpointIsValid): 22 * runtime/JSArrayBufferPrototype.cpp: 23 (JSC::speciesWatchpointIsValid): 24 (JSC::arrayBufferSlice): 25 * runtime/JSGlobalObject.cpp: 26 (JSC::JSGlobalObject::JSGlobalObject): 27 (JSC::JSGlobalObject::init): 28 (JSC::JSGlobalObject::visitChildren): 29 (JSC::JSGlobalObject::tryInstallSpeciesWatchpoint): 30 (JSC::JSGlobalObject::tryInstallArraySpeciesWatchpoint): 31 (JSC::JSGlobalObject::tryInstallArrayBufferSpeciesWatchpoint): 32 * runtime/JSGlobalObject.h: 33 (JSC::JSGlobalObject::arrayBufferSpeciesWatchpointSet): 34 (JSC::JSGlobalObject::arrayBufferPrototype const): 35 (JSC::JSGlobalObject::arrayBufferStructure const): 36 (JSC::JSGlobalObject::arrayBufferConstructor const): 37 1 38 2020-11-06 Dmitry Bezhetskov <dbezhetskov@igalia.com> 2 39 -
trunk/Source/JavaScriptCore/runtime/ArrayBuffer.cpp
r269343 r269574 312 312 RefPtr<ArrayBuffer> ArrayBuffer::slice(double begin, double end) const 313 313 { 314 return slice Impl(clampIndex(begin), clampIndex(end));314 return sliceWithClampedIndex(clampIndex(begin), clampIndex(end)); 315 315 } 316 316 317 317 RefPtr<ArrayBuffer> ArrayBuffer::slice(double begin) const 318 318 { 319 return slice Impl(clampIndex(begin), byteLength());320 } 321 322 RefPtr<ArrayBuffer> ArrayBuffer::slice Impl(unsigned begin, unsigned end) const319 return sliceWithClampedIndex(clampIndex(begin), byteLength()); 320 } 321 322 RefPtr<ArrayBuffer> ArrayBuffer::sliceWithClampedIndex(unsigned begin, unsigned end) const 323 323 { 324 324 unsigned size = begin <= end ? end - begin : 0; -
trunk/Source/JavaScriptCore/runtime/ArrayBuffer.h
r269343 r269574 138 138 JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(double begin, double end) const; 139 139 JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(double begin) const; 140 JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> sliceWithClampedIndex(unsigned begin, unsigned end) const; 140 141 141 142 inline void pin(); … … 165 166 static RefPtr<ArrayBuffer> tryCreate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy); 166 167 ArrayBuffer(ArrayBufferContents&&); 167 RefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const;168 168 inline unsigned clampIndex(double index) const; 169 169 static inline unsigned clampValue(double x, unsigned left, unsigned right); -
trunk/Source/JavaScriptCore/runtime/ArrayBufferSharingMode.h
r233122 r269574 31 31 namespace JSC { 32 32 33 enum class ArrayBufferSharingMode {34 Default ,33 enum class ArrayBufferSharingMode : uint8_t { 34 Default = 0, 35 35 Shared 36 36 }; -
trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
r268990 r269574 187 187 } 188 188 189 ALWAYS_INLINE bool speciesWatchpointIsValid(VM& vm, JSObject* thisObject)189 static ALWAYS_INLINE bool speciesWatchpointIsValid(VM& vm, JSObject* thisObject) 190 190 { 191 191 JSGlobalObject* globalObject = thisObject->globalObject(vm); -
trunk/Source/JavaScriptCore/runtime/JSArrayBufferPrototype.cpp
r269531 r269574 31 31 32 32 namespace JSC { 33 namespace JSArrayBufferPrototypeInternal { 34 static constexpr bool verbose = false; 35 }; 33 36 34 37 static JSC_DECLARE_HOST_FUNCTION(arrayBufferProtoFuncSlice); … … 37 40 static JSC_DECLARE_HOST_FUNCTION(sharedArrayBufferProtoGetterFuncByteLength); 38 41 39 static EncodedJSValue arrayBufferSlice(JSGlobalObject* globalObject, JSValue arrayBufferValue, JSValue startValue, JSValue endValue, ArrayBufferSharingMode mode) 40 { 42 43 static ALWAYS_INLINE bool speciesWatchpointIsValid(VM& vm, JSObject* thisObject, ArrayBufferSharingMode mode) 44 { 45 JSGlobalObject* globalObject = thisObject->globalObject(vm); 46 auto* prototype = globalObject->arrayBufferPrototype(mode); 47 48 if (globalObject->arrayBufferSpeciesWatchpointSet(mode).stateOnJSThread() == ClearWatchpoint) { 49 dataLogLnIf(JSArrayBufferPrototypeInternal::verbose, "Initializing ArrayBuffer species watchpoints for ArrayBuffer.prototype: ", pointerDump(prototype), " with structure: ", pointerDump(prototype->structure(vm)), "\nand ArrayBuffer: ", pointerDump(globalObject->arrayBufferConstructor(mode)), " with structure: ", pointerDump(globalObject->arrayBufferConstructor(mode)->structure(vm))); 50 globalObject->tryInstallArrayBufferSpeciesWatchpoint(mode); 51 ASSERT(globalObject->arrayBufferSpeciesWatchpointSet(mode).stateOnJSThread() != ClearWatchpoint); 52 } 53 54 return !thisObject->hasCustomProperties(vm) 55 && prototype == thisObject->getPrototypeDirect(vm) 56 && globalObject->arrayBufferSpeciesWatchpointSet(mode).stateOnJSThread() == IsWatched; 57 } 58 59 enum class SpeciesConstructResult : uint8_t { 60 FastPath, 61 Exception, 62 CreatedObject 63 }; 64 65 static ALWAYS_INLINE std::pair<SpeciesConstructResult, JSArrayBuffer*> speciesConstructArrayBuffer(JSGlobalObject* globalObject, JSArrayBuffer* thisObject, unsigned length, ArrayBufferSharingMode mode) 66 { 67 // This is optimized way of SpeciesConstruct invoked from {ArrayBuffer,SharedArrayBuffer}.prototype.slice. 68 // https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice 69 // https://tc39.es/ecma262/#sec-sharedarraybuffer.prototype.slice 41 70 VM& vm = globalObject->vm(); 42 71 auto scope = DECLARE_THROW_SCOPE(vm); 43 72 73 auto exceptionResult = [] () { 74 return std::make_pair(SpeciesConstructResult::Exception, nullptr); 75 }; 76 77 // Fast path in the normal case where the user has not set an own constructor and the ArrayBuffer.prototype.constructor is normal. 78 // We need prototype check for subclasses of ArrayBuffer, which are ArrayBuffer objects but have a different prototype by default. 79 bool isValid = speciesWatchpointIsValid(vm, thisObject, mode); 80 scope.assertNoException(); 81 if (LIKELY(isValid)) 82 return std::make_pair(SpeciesConstructResult::FastPath, nullptr); 83 84 JSValue constructor = thisObject->get(globalObject, vm.propertyNames->constructor); 85 RETURN_IF_EXCEPTION(scope, exceptionResult()); 86 if (constructor.isConstructor(vm)) { 87 JSObject* constructorObject = jsCast<JSObject*>(constructor); 88 JSGlobalObject* globalObjectFromConstructor = constructorObject->globalObject(vm); 89 bool isArrayBufferConstructorFromAnotherRealm = globalObject != globalObjectFromConstructor 90 && constructorObject == globalObjectFromConstructor->arrayBufferConstructor(mode); 91 if (isArrayBufferConstructorFromAnotherRealm) 92 return std::make_pair(SpeciesConstructResult::FastPath, nullptr); 93 } 94 if (constructor.isObject()) { 95 constructor = constructor.get(globalObject, vm.propertyNames->speciesSymbol); 96 RETURN_IF_EXCEPTION(scope, exceptionResult()); 97 if (constructor.isNull()) 98 return std::make_pair(SpeciesConstructResult::FastPath, nullptr); 99 } 100 101 if (constructor.isUndefined()) 102 return std::make_pair(SpeciesConstructResult::FastPath, nullptr); 103 104 // 16. Let new be ? Construct(ctor, « 𝔽(newLen) »). 105 MarkedArgumentBuffer args; 106 args.append(jsNumber(length)); 107 ASSERT(!args.hasOverflowed()); 108 JSObject* newObject = construct(globalObject, constructor, args, "Species construction did not get a valid constructor"); 109 RETURN_IF_EXCEPTION(scope, exceptionResult()); 110 111 // 17. Perform ? RequireInternalSlot(new, [[ArrayBufferData]]). 112 JSArrayBuffer* result = jsDynamicCast<JSArrayBuffer*>(vm, newObject); 113 if (UNLIKELY(!result)) { 114 throwTypeError(globalObject, scope, "Species construction does not create ArrayBuffer"_s); 115 return exceptionResult(); 116 } 117 118 if (mode == ArrayBufferSharingMode::Default) { 119 // 18. If IsSharedArrayBuffer(new) is true, throw a TypeError exception. 120 if (result->isShared()) { 121 throwTypeError(globalObject, scope, "ArrayBuffer.prototype.slice creates SharedArrayBuffer"_s); 122 return exceptionResult(); 123 } 124 // 19. If IsDetachedBuffer(new) is true, throw a TypeError exception. 125 if (result->impl()->isDetached()) { 126 throwVMTypeError(globalObject, scope, "Created ArrayBuffer is detached"_s); 127 return exceptionResult(); 128 } 129 } else { 130 // 17. If IsSharedArrayBuffer(new) is false, throw a TypeError exception. 131 if (!result->isShared()) { 132 throwTypeError(globalObject, scope, "SharedArrayBuffer.prototype.slice creates non-shared ArrayBuffer"_s); 133 return exceptionResult(); 134 } 135 } 136 137 // 20. If SameValue(new, O) is true, throw a TypeError exception. 138 if (result == thisObject) { 139 throwVMTypeError(globalObject, scope, "Species construction returns same ArrayBuffer to a receiver"_s); 140 return exceptionResult(); 141 } 142 143 // 21. If new.[[ArrayBufferByteLength]] < newLen, throw a TypeError exception. 144 if (result->impl()->byteLength() < length) { 145 throwVMTypeError(globalObject, scope, "Species construction returns ArrayBuffer which byteLength is less than requested"_s); 146 return exceptionResult(); 147 } 148 149 return std::make_pair(SpeciesConstructResult::CreatedObject, result); 150 } 151 152 153 static EncodedJSValue arrayBufferSlice(JSGlobalObject* globalObject, JSValue arrayBufferValue, JSValue startValue, JSValue endValue, ArrayBufferSharingMode mode) 154 { 155 // https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice 156 // https://tc39.es/ecma262/#sec-sharedarraybuffer.prototype.slice 157 158 VM& vm = globalObject->vm(); 159 auto scope = DECLARE_THROW_SCOPE(vm); 160 161 // 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). 162 // 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception. 44 163 JSArrayBuffer* thisObject = jsDynamicCast<JSArrayBuffer*>(vm, arrayBufferValue); 45 164 if (!thisObject || (mode != thisObject->impl()->sharingMode())) 46 165 return throwVMTypeError(globalObject, scope, makeString("Receiver must be "_s, mode == ArrayBufferSharingMode::Default ? "ArrayBuffer"_s : "SharedArrayBuffer"_s)); 47 166 167 // 4. If IsDetachedBuffer(O) is true, throw a TypeError exception. 48 168 if (mode == ArrayBufferSharingMode::Default && thisObject->impl()->isDetached()) 49 169 return throwVMTypeError(globalObject, scope, "Receiver is detached"_s); 50 170 51 double begin = startValue.toIntegerOrInfinity(globalObject); 171 // 5. Let len be O.[[ArrayBufferByteLength]]. 172 unsigned byteLength = thisObject->impl()->byteLength(); 173 unsigned firstIndex = 0; 174 double relativeStart = startValue.toIntegerOrInfinity(globalObject); 52 175 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 53 54 double end; 176 if (relativeStart < 0) 177 firstIndex = static_cast<unsigned>(std::max<double>(byteLength + relativeStart, 0)); 178 else 179 firstIndex = static_cast<unsigned>(std::min<double>(relativeStart, byteLength)); 180 ASSERT(firstIndex >= 0); 181 ASSERT(firstIndex <= byteLength); 182 183 unsigned finalIndex = 0; 55 184 if (!endValue.isUndefined()) { 56 end = endValue.toIntegerOrInfinity(globalObject);185 double relativeEnd = endValue.toIntegerOrInfinity(globalObject); 57 186 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 187 if (relativeEnd < 0) 188 finalIndex = static_cast<unsigned>(std::max<double>(byteLength + relativeEnd, 0)); 189 else 190 finalIndex = static_cast<unsigned>(std::min<double>(relativeEnd, byteLength)); 58 191 } else 59 end = thisObject->impl()->byteLength(); 192 finalIndex = thisObject->impl()->byteLength(); 193 ASSERT(finalIndex >= 0); 194 ASSERT(finalIndex <= byteLength); 195 196 // 14. Let newLen be max(final - first, 0). 197 unsigned newLength = (finalIndex >= firstIndex) ? finalIndex - firstIndex : 0; 198 199 // 15. Let ctor be ? SpeciesConstructor(O, %ArrayBuffer%). 200 auto speciesResult = speciesConstructArrayBuffer(globalObject, thisObject, newLength, mode); 201 // We can only get an exception if we call some user function. 202 EXCEPTION_ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception)); 203 if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception)) 204 return { }; 60 205 61 206 // 23. If IsDetachedBuffer(O) is true, throw a TypeError exception. 62 // Check detach status again since toIntegerOrInfinity can have side effect.63 207 if (mode == ArrayBufferSharingMode::Default && thisObject->impl()->isDetached()) 64 208 return throwVMTypeError(globalObject, scope, "Receiver is detached"_s); 65 209 66 auto newBuffer = thisObject->impl()->slice(begin, end); 67 if (!newBuffer) 68 return JSValue::encode(throwOutOfMemoryError(globalObject, scope)); 69 70 Structure* structure = globalObject->arrayBufferStructure(newBuffer->sharingMode()); 71 72 JSArrayBuffer* result = JSArrayBuffer::create(vm, structure, WTFMove(newBuffer)); 73 74 return JSValue::encode(result); 210 if (LIKELY(speciesResult.first == SpeciesConstructResult::FastPath)) { 211 ASSERT(!thisObject->impl()->isDetached()); 212 auto newBuffer = thisObject->impl()->sliceWithClampedIndex(firstIndex, finalIndex); 213 if (!newBuffer) 214 return JSValue::encode(throwOutOfMemoryError(globalObject, scope)); 215 Structure* structure = globalObject->arrayBufferStructure(newBuffer->sharingMode()); 216 JSArrayBuffer* result = JSArrayBuffer::create(vm, structure, WTFMove(newBuffer)); 217 return JSValue::encode(result); 218 } 219 220 // 24. Let fromBuf be O.[[ArrayBufferData]]. 221 // 25. Let toBuf be new.[[ArrayBufferData]]. 222 // 26. Perform CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLen). 223 JSArrayBuffer* newObject = speciesResult.second; 224 ASSERT(!thisObject->impl()->isDetached()); 225 ASSERT(!newObject->impl()->isDetached()); 226 ASSERT(newObject->impl()->byteLength() >= newLength); 227 memcpy(newObject->impl()->data(), static_cast<const char*>(thisObject->impl()->data()) + firstIndex, newLength); 228 return JSValue::encode(newObject); 75 229 } 76 230 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r269531 r269574 500 500 , m_mapSetWatchpointSet(IsWatched) 501 501 , m_setAddWatchpointSet(IsWatched) 502 , m_arraySpeciesWatchpointSet(ClearWatchpoint)503 502 , m_arrayJoinWatchpointSet(IsWatched) 504 503 , m_numberToStringWatchpointSet(IsWatched) … … 831 830 }); 832 831 833 #if ENABLE(SHARED_ARRAY_BUFFER)834 832 if (Options::useSharedArrayBuffer()) { 835 m_sharedArrayBufferPrototype.set(vm, this, JSArrayBufferPrototype::create(vm, this, JSArrayBufferPrototype::createStructure(vm, this, m_objectPrototype.get()), ArrayBufferSharingMode::Shared)); 836 m_sharedArrayBufferStructure.set(vm, this, JSArrayBuffer::createStructure(vm, this, m_sharedArrayBufferPrototype.get())); 837 } 838 #endif 833 m_sharedArrayBufferStructure.initLater( 834 [] (LazyClassStructure::Initializer& init) { 835 init.setPrototype(JSArrayBufferPrototype::create(init.vm, init.global, JSArrayBufferPrototype::createStructure(init.vm, init.global, init.global->m_objectPrototype.get()), ArrayBufferSharingMode::Shared)); 836 init.setStructure(JSArrayBuffer::createStructure(init.vm, init.global, init.prototype)); 837 init.setConstructor(JSSharedArrayBufferConstructor::create(init.vm, JSSharedArrayBufferConstructor::createStructure(init.vm, init.global, init.global->m_functionPrototype.get()), jsCast<JSArrayBufferPrototype*>(init.prototype), init.global->m_speciesGetterSetter.get())); 838 }); 839 } 839 840 840 841 m_iteratorPrototype.set(vm, this, IteratorPrototype::create(vm, this, IteratorPrototype::createStructure(vm, this, m_objectPrototype.get()))); … … 901 902 m_regExpGlobalData.cachedResult().record(vm, this, nullptr, jsEmptyString(vm), MatchResult(0, 0)); 902 903 903 #if ENABLE(SHARED_ARRAY_BUFFER)904 JSSharedArrayBufferConstructor* sharedArrayBufferConstructor = nullptr;905 904 AtomicsObject* atomicsObject = nullptr; 906 if (Options::useSharedArrayBuffer()) { 907 sharedArrayBufferConstructor = JSSharedArrayBufferConstructor::create(vm, JSSharedArrayBufferConstructor::createStructure(vm, this, m_functionPrototype.get()), m_sharedArrayBufferPrototype.get(), m_speciesGetterSetter.get()); 908 m_sharedArrayBufferPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, sharedArrayBufferConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); 909 905 if (Options::useSharedArrayBuffer()) 910 906 atomicsObject = AtomicsObject::create(vm, this, AtomicsObject::createStructure(vm, this, m_objectPrototype.get())); 911 }912 #endif913 907 914 908 #define CREATE_CONSTRUCTOR_FOR_SIMPLE_TYPE(capitalName, lowerName, properName, instanceType, jsName, prototypeBase, featureFlag) \ … … 988 982 putDirectWithoutTransition(vm, vm.propertyNames->RegExp, regExpConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); 989 983 990 #if ENABLE(SHARED_ARRAY_BUFFER)991 984 if (Options::useSharedArrayBuffer()) { 992 putDirectWithoutTransition(vm, vm.propertyNames->SharedArrayBuffer, sharedArrayBufferConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));985 putDirectWithoutTransition(vm, vm.propertyNames->SharedArrayBuffer, m_sharedArrayBufferStructure.constructor(this), static_cast<unsigned>(PropertyAttribute::DontEnum)); 993 986 putDirectWithoutTransition(vm, vm.propertyNames->Atomics, atomicsObject, static_cast<unsigned>(PropertyAttribute::DontEnum)); 994 987 } 995 #endif996 988 997 989 #define PUT_CONSTRUCTOR_FOR_SIMPLE_TYPE(capitalName, lowerName, properName, instanceType, jsName, prototypeBase, featureFlag) \ … … 2034 2026 thisObject->m_callableProxyObjectStructure.visit(visitor); 2035 2027 thisObject->m_proxyRevokeStructure.visit(visitor); 2028 thisObject->m_sharedArrayBufferStructure.visit(visitor); 2036 2029 2037 2030 for (auto& property : thisObject->m_linkTimeConstants) 2038 2031 property.visit(visitor); 2039 2040 #if ENABLE(SHARED_ARRAY_BUFFER)2041 visitor.append(thisObject->m_sharedArrayBufferPrototype);2042 visitor.append(thisObject->m_sharedArrayBufferStructure);2043 #endif2044 2032 2045 2033 #define VISIT_SIMPLE_TYPE(CapitalName, lowerName, properName, instanceType, jsName, prototypeBase, featureFlag) if (featureFlag) { \ … … 2137 2125 } 2138 2126 2139 void JSGlobalObject::tryInstall ArraySpeciesWatchpoint()2140 { 2141 RELEASE_ASSERT(! m_arrayPrototypeConstructorWatchpoint);2142 RELEASE_ASSERT(! m_arrayConstructorSpeciesWatchpoint);2127 void JSGlobalObject::tryInstallSpeciesWatchpoint(JSObject* prototype, JSObject* constructor, std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>& constructorWatchpoint, std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>& speciesWatchpoint, InlineWatchpointSet& speciesWatchpointSet) 2128 { 2129 RELEASE_ASSERT(!constructorWatchpoint); 2130 RELEASE_ASSERT(!speciesWatchpoint); 2143 2131 2144 2132 VM& vm = this->vm(); 2145 2133 auto scope = DECLARE_THROW_SCOPE(vm); 2146 2134 2147 // First we need to make sure that the Array.prototype.constructor property points to Array 2148 // and that Array[Symbol.species] is the primordial GetterSetter. 2149 ArrayPrototype* arrayPrototype = this->arrayPrototype(); 2135 // First we need to make sure that the %prototype%.constructor property points to a %constructor% 2136 // and that %constructor%[Symbol.species] is the primordial GetterSetter. 2150 2137 2151 2138 // We only initialize once so flattening the structures does not have any real cost. 2152 Structure* prototypeStructure = arrayPrototype->structure(vm);2139 Structure* prototypeStructure = prototype->structure(vm); 2153 2140 if (prototypeStructure->isDictionary()) 2154 prototypeStructure = prototypeStructure->flattenDictionaryStructure(vm, arrayPrototype);2141 prototypeStructure = prototypeStructure->flattenDictionaryStructure(vm, prototype); 2155 2142 RELEASE_ASSERT(!prototypeStructure->isDictionary()); 2156 2143 2157 ArrayConstructor* arrayConstructor = this->arrayConstructor();2158 2159 2144 auto invalidateWatchpoint = [&] { 2160 m_arraySpeciesWatchpointSet.invalidate(vm, StringFireDetail("Was not able to set up arrayspecies watchpoint."));2145 speciesWatchpointSet.invalidate(vm, StringFireDetail("Was not able to set up species watchpoint.")); 2161 2146 }; 2162 2147 2163 PropertySlot constructorSlot( arrayPrototype, PropertySlot::InternalMethodType::VMInquiry, &vm);2164 arrayPrototype->getOwnPropertySlot(arrayPrototype, this, vm.propertyNames->constructor, constructorSlot);2148 PropertySlot constructorSlot(prototype, PropertySlot::InternalMethodType::VMInquiry, &vm); 2149 prototype->getOwnPropertySlot(prototype, this, vm.propertyNames->constructor, constructorSlot); 2165 2150 scope.assertNoException(); 2166 if (constructorSlot.slotBase() != arrayPrototype2151 if (constructorSlot.slotBase() != prototype 2167 2152 || !constructorSlot.isCacheableValue() 2168 || constructorSlot.getValue(this, vm.propertyNames->constructor) != arrayConstructor) {2153 || constructorSlot.getValue(this, vm.propertyNames->constructor) != constructor) { 2169 2154 invalidateWatchpoint(); 2170 2155 return; 2171 2156 } 2172 2157 2173 Structure* constructorStructure = arrayConstructor->structure(vm);2158 Structure* constructorStructure = constructor->structure(vm); 2174 2159 if (constructorStructure->isDictionary()) 2175 constructorStructure = constructorStructure->flattenDictionaryStructure(vm, arrayConstructor);2176 2177 PropertySlot speciesSlot( arrayConstructor, PropertySlot::InternalMethodType::VMInquiry, &vm);2178 arrayConstructor->getOwnPropertySlot(arrayConstructor, this, vm.propertyNames->speciesSymbol, speciesSlot);2160 constructorStructure = constructorStructure->flattenDictionaryStructure(vm, constructor); 2161 2162 PropertySlot speciesSlot(constructor, PropertySlot::InternalMethodType::VMInquiry, &vm); 2163 constructor->getOwnPropertySlot(constructor, this, vm.propertyNames->speciesSymbol, speciesSlot); 2179 2164 scope.assertNoException(); 2180 if (speciesSlot.slotBase() != arrayConstructor2165 if (speciesSlot.slotBase() != constructor 2181 2166 || !speciesSlot.isCacheableGetter() 2182 2167 || speciesSlot.getterSetter() != speciesGetterSetter()) { … … 2189 2174 constructorStructure->startWatchingPropertyForReplacements(vm, speciesSlot.cachedOffset()); 2190 2175 2191 ObjectPropertyCondition constructorCondition = ObjectPropertyCondition::equivalence(vm, arrayPrototype, arrayPrototype, vm.propertyNames->constructor.impl(), arrayConstructor);2192 ObjectPropertyCondition speciesCondition = ObjectPropertyCondition::equivalence(vm, arrayPrototype, arrayConstructor, vm.propertyNames->speciesSymbol.impl(), speciesGetterSetter());2176 ObjectPropertyCondition constructorCondition = ObjectPropertyCondition::equivalence(vm, prototype, prototype, vm.propertyNames->constructor.impl(), constructor); 2177 ObjectPropertyCondition speciesCondition = ObjectPropertyCondition::equivalence(vm, prototype, constructor, vm.propertyNames->speciesSymbol.impl(), speciesGetterSetter()); 2193 2178 2194 2179 if (!constructorCondition.isWatchable() || !speciesCondition.isWatchable()) { … … 2198 2183 2199 2184 // We only watch this from the DFG, and the DFG makes sure to only start watching if the watchpoint is in the IsWatched state. 2200 RELEASE_ASSERT(!m_arraySpeciesWatchpointSet.isBeingWatched()); 2201 m_arraySpeciesWatchpointSet.touch(vm, "Set up array species watchpoint."); 2202 2203 m_arrayPrototypeConstructorWatchpoint = makeUnique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(this, constructorCondition, m_arraySpeciesWatchpointSet); 2204 m_arrayPrototypeConstructorWatchpoint->install(vm); 2205 2206 m_arrayConstructorSpeciesWatchpoint = makeUnique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(this, speciesCondition, m_arraySpeciesWatchpointSet); 2207 m_arrayConstructorSpeciesWatchpoint->install(vm); 2185 RELEASE_ASSERT(!speciesWatchpointSet.isBeingWatched()); 2186 speciesWatchpointSet.touch(vm, "Set up species watchpoint."); 2187 2188 constructorWatchpoint = makeUnique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(this, constructorCondition, speciesWatchpointSet); 2189 constructorWatchpoint->install(vm); 2190 2191 speciesWatchpoint = makeUnique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(this, speciesCondition, speciesWatchpointSet); 2192 speciesWatchpoint->install(vm); 2193 } 2194 2195 void JSGlobalObject::tryInstallArraySpeciesWatchpoint() 2196 { 2197 RELEASE_ASSERT(!m_arrayPrototypeConstructorWatchpoint); 2198 RELEASE_ASSERT(!m_arrayConstructorSpeciesWatchpoint); 2199 2200 tryInstallSpeciesWatchpoint(arrayPrototype(), arrayConstructor(), m_arrayPrototypeConstructorWatchpoint, m_arrayConstructorSpeciesWatchpoint, m_arraySpeciesWatchpointSet); 2201 } 2202 2203 void JSGlobalObject::tryInstallArrayBufferSpeciesWatchpoint(ArrayBufferSharingMode sharingMode) 2204 { 2205 static_assert(static_cast<unsigned>(ArrayBufferSharingMode::Default) == 0); 2206 static_assert(static_cast<unsigned>(ArrayBufferSharingMode::Shared) == 1); 2207 unsigned index = static_cast<unsigned>(sharingMode); 2208 tryInstallSpeciesWatchpoint(arrayBufferPrototype(sharingMode), arrayBufferConstructor(sharingMode), m_arrayBufferPrototypeConstructorWatchpoints[index], m_arrayBufferConstructorSpeciesWatchpoints[index], arrayBufferSpeciesWatchpointSet(sharingMode)); 2208 2209 } 2209 2210 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r268956 r269574 421 421 LazyProperty<JSGlobalObject, Structure> m_callableProxyObjectStructure; 422 422 LazyProperty<JSGlobalObject, Structure> m_proxyRevokeStructure; 423 #if ENABLE(SHARED_ARRAY_BUFFER) 424 WriteBarrier<JSArrayBufferPrototype> m_sharedArrayBufferPrototype; 425 WriteBarrier<Structure> m_sharedArrayBufferStructure; 426 #endif 423 LazyClassStructure m_sharedArrayBufferStructure; 427 424 428 425 #define DEFINE_STORAGE_FOR_SIMPLE_TYPE(capitalName, lowerName, properName, instanceType, jsName, prototypeBase, featureFlag) \ … … 488 485 InlineWatchpointSet m_mapSetWatchpointSet; 489 486 InlineWatchpointSet m_setAddWatchpointSet; 490 InlineWatchpointSet m_arraySpeciesWatchpointSet ;487 InlineWatchpointSet m_arraySpeciesWatchpointSet { ClearWatchpoint }; 491 488 InlineWatchpointSet m_arrayJoinWatchpointSet; 492 489 InlineWatchpointSet m_numberToStringWatchpointSet; 490 InlineWatchpointSet m_arrayBufferSpeciesWatchpointSet { ClearWatchpoint }; 491 InlineWatchpointSet m_sharedArrayBufferSpeciesWatchpointSet { ClearWatchpoint }; 493 492 std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_arrayConstructorSpeciesWatchpoint; 494 493 std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_arrayPrototypeConstructorWatchpoint; … … 505 504 std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_setPrototypeAddWatchpoint; 506 505 std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_numberPrototypeToStringWatchpoint; 506 std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_arrayBufferConstructorSpeciesWatchpoints[2]; 507 std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_arrayBufferPrototypeConstructorWatchpoints[2]; 507 508 508 509 public: … … 521 522 RELEASE_ASSERT(Options::useJIT()); 522 523 return m_numberToStringWatchpointSet; 524 } 525 InlineWatchpointSet& arrayBufferSpeciesWatchpointSet(ArrayBufferSharingMode sharingMode) 526 { 527 switch (sharingMode) { 528 case ArrayBufferSharingMode::Default: 529 return m_arrayBufferSpeciesWatchpointSet; 530 case ArrayBufferSharingMode::Shared: 531 return m_sharedArrayBufferSpeciesWatchpointSet; 532 } 533 RELEASE_ASSERT_NOT_REACHED(); 534 return m_arrayBufferSpeciesWatchpointSet; 523 535 } 524 536 … … 872 884 static ScriptExecutionStatus scriptExecutionStatus(JSGlobalObject*, JSObject*) { return ScriptExecutionStatus::Running; } 873 885 874 JSObject* arrayBufferConstructor() const { return m_arrayBufferStructure.constructor(this); }875 876 886 JSObject* arrayBufferPrototype(ArrayBufferSharingMode sharingMode) const 877 887 { … … 879 889 case ArrayBufferSharingMode::Default: 880 890 return m_arrayBufferStructure.prototype(this); 881 #if ENABLE(SHARED_ARRAY_BUFFER)882 891 case ArrayBufferSharingMode::Shared: 883 return m_sharedArrayBufferPrototype.get(); 884 #else 885 default: 886 return m_arrayBufferStructure.prototype(this); 887 #endif 892 return m_sharedArrayBufferStructure.prototype(this); 888 893 } 894 RELEASE_ASSERT_NOT_REACHED(); 895 return nullptr; 889 896 } 890 897 Structure* arrayBufferStructure(ArrayBufferSharingMode sharingMode) const … … 893 900 case ArrayBufferSharingMode::Default: 894 901 return m_arrayBufferStructure.get(this); 895 #if ENABLE(SHARED_ARRAY_BUFFER)896 902 case ArrayBufferSharingMode::Shared: 897 return m_sharedArrayBufferStructure.get(); 898 #else 899 default: 900 return m_arrayBufferStructure.get(this); 901 #endif 903 return m_sharedArrayBufferStructure.get(this); 902 904 } 903 905 RELEASE_ASSERT_NOT_REACHED(); 904 906 return nullptr; 905 907 } 908 JSObject* arrayBufferConstructor(ArrayBufferSharingMode sharingMode) const 909 { 910 switch (sharingMode) { 911 case ArrayBufferSharingMode::Default: 912 return m_arrayBufferStructure.constructor(this); 913 case ArrayBufferSharingMode::Shared: 914 return m_sharedArrayBufferStructure.constructor(this); 915 } 916 RELEASE_ASSERT_NOT_REACHED(); 917 return nullptr; 918 } 919 906 920 907 921 #define DEFINE_ACCESSORS_FOR_SIMPLE_TYPE(capitalName, lowerName, properName, instanceType, jsName, prototypeBase, featureFlag) \ … … 1079 1093 void installMapPrototypeWatchpoint(MapPrototype*); 1080 1094 void installSetPrototypeWatchpoint(SetPrototype*); 1095 void tryInstallArrayBufferSpeciesWatchpoint(ArrayBufferSharingMode); 1081 1096 1082 1097 protected: 1098 void tryInstallSpeciesWatchpoint(JSObject* prototype, JSObject* constructor, std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>& constructorWatchpoint, std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>& speciesWatchpoint, InlineWatchpointSet& speciesWatchpointSet); 1099 1083 1100 struct GlobalPropertyInfo { 1084 1101 GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a) -
trunk/Source/WTF/ChangeLog
r269545 r269574 1 2020-11-08 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] Support @@species in ArrayBuffer / SharedArrayBuffer slice 4 https://bugs.webkit.org/show_bug.cgi?id=218697 5 6 Reviewed by Ross Kirsling. 7 8 Remove ENABLE(SHARED_ARRAY_BUFFER) flag. We use Options::useSharedArrayBuffer() runtime flag instead. 9 10 * wtf/PlatformEnable.h: 11 1 12 2020-11-06 Sam Weinig <weinig@apple.com> 2 13 -
trunk/Source/WTF/wtf/PlatformEnable.h
r269531 r269574 830 830 #endif 831 831 832 /* Disable SharedArrayBuffers until Spectre security concerns are mitigated. */833 #define ENABLE_SHARED_ARRAY_BUFFER 1834 835 836 832 #if ((PLATFORM(COCOA) || PLATFORM(PLAYSTATION) || PLATFORM(WPE)) && ENABLE(ASYNC_SCROLLING)) || PLATFORM(GTK) 837 833 #define ENABLE_KINETIC_SCROLLING 1
Note: See TracChangeset
for help on using the changeset viewer.