diff --git a/include/hermes/VM/JSObject.h b/include/hermes/VM/JSObject.h index 83e38bf77eb..47da56ec06a 100644 --- a/include/hermes/VM/JSObject.h +++ b/include/hermes/VM/JSObject.h @@ -699,8 +699,19 @@ class JSObject : public GCCell { /// named storage or indexed storage depending on the presence of the /// "Indexed" flag. This does not call the getter, and can be used to /// retrieve the accessor directly. - static HermesValue getComputedSlotValue( - JSObject *self, + static CallResult> getComputedSlotValue( + PseudoHandle self, + Runtime *runtime, + MutableHandle &tmpSymbolStorage, + ComputedPropertyDescriptor desc); + + /// Load a value using a computed descriptor. Read the value either from + /// named storage or indexed storage depending on the presence of the + /// "Indexed" flag. This does not call the getter, and can be used to + /// retrieve the accessor directly. + /// \pre The property must not be on a Proxy or HostObject. + static HermesValue getComputedSlotValueUnsafe( + PseudoHandle self, Runtime *runtime, ComputedPropertyDescriptor desc); @@ -709,7 +720,20 @@ class JSObject : public GCCell { /// "Indexed" flag. This does not call the setter, and can be used to /// set the accessor directly. The \p gc parameter is necessary for write /// barriers. - LLVM_NODISCARD static ExecutionStatus setComputedSlotValue( + LLVM_NODISCARD static CallResult setComputedSlotValue( + Handle selfHandle, + Runtime *runtime, + MutableHandle &tmpSymbolStorage, + ComputedPropertyDescriptor desc, + Handle<> value); + + /// Store a value using a computed descriptor. Store the value either to + /// named storage or indexed storage depending on the presence of the + /// "Indexed" flag. This does not call the setter, and can be used to + /// set the accessor directly. The \p gc parameter is necessary for write + /// barriers. + /// \pre The property must not be on a Proxy or HostObject. + LLVM_NODISCARD static ExecutionStatus setComputedSlotValueUnsafe( Handle selfHandle, Runtime *runtime, ComputedPropertyDescriptor desc, @@ -723,7 +747,8 @@ class JSObject : public GCCell { /// \param propObj the object where the property was found (it could be /// anywhere along the prototype chain). /// \param desc the property descriptor. - static CallResult> getComputedPropertyValue_RJS( + /// \pre The property must not be on a Proxy or HostObject. + static CallResult> getComputedPropertyValueInternal_RJS( Handle selfHandle, Runtime *runtime, Handle propObj, @@ -740,6 +765,7 @@ class JSObject : public GCCell { Handle selfHandle, Runtime *runtime, Handle propObj, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor desc, Handle<> nameValHandle); @@ -789,6 +815,7 @@ class JSObject : public GCCell { Runtime *runtime, Handle<> nameValHandle, IgnoreProxy ignoreProxy, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc); /// Provides the functionality of ES9 [[GetOwnProperty]] on selfHandle. It @@ -802,6 +829,7 @@ class JSObject : public GCCell { Handle selfHandle, Runtime *runtime, Handle<> nameValHandle, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc); /// Like the other overload, except valueOrAccessor will be set to a value or @@ -810,6 +838,7 @@ class JSObject : public GCCell { Handle selfHandle, Runtime *runtime, Handle<> nameValHandle, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc, MutableHandle<> &valueOrAccessor); @@ -863,6 +892,10 @@ class JSObject : public GCCell { /// Extract a descriptor \p desc of a named property \p name in this object /// or along the prototype chain. /// \param nameValHandle the name of the property. It must be a primitive. + /// \param tmpSymbolStorage a temporary handle sometimes used internally + /// to store SymbolIDs in order to make sure they aren't collected. + /// Must not be modified or read by the caller for the lifetime of \p desc, + /// the function makes no guarantees regarding whether it is used. /// \param[out] propObj it is set to the object in the prototype chain /// containing the property, or \c null if we didn't find the property. /// \param[out] desc if the property was found, set to the property @@ -872,6 +905,7 @@ class JSObject : public GCCell { Runtime *runtime, Handle<> nameValHandle, MutableHandle &propObj, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc); /// A wrapper to getComputedPrimitiveDescriptor() in the case when @@ -881,6 +915,10 @@ class JSObject : public GCCell { /// The values of the output parameters are not defined if the call terminates /// with an exception. /// \param nameValHandle the name of the property. + /// \param tmpSymbolStorage a temporary handle sometimes used internally + /// to store SymbolIDs in order to make sure they aren't collected. + /// Must not be modified or read by the caller for the lifetime of \p desc, + /// the function makes no guarantees regarding whether it is used. /// \param[out] propObj if the method terminates without an exception, it is /// set to the object in the prototype chain containing the property, or /// \c null if we didn't find the property. @@ -891,6 +929,7 @@ class JSObject : public GCCell { Runtime *runtime, Handle<> nameValHandle, MutableHandle &propObj, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc); /// The following three methods implement ES5.1 8.12.3. @@ -1741,29 +1780,80 @@ inline void JSObject::setNamedSlotValueUnsafe( index - DIRECT_PROPERTY_SLOTS, value, &runtime->getHeap()); } -inline HermesValue JSObject::getComputedSlotValue( - JSObject *self, +inline CallResult> JSObject::getComputedSlotValue( + PseudoHandle self, Runtime *runtime, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor desc) { - assert(!self->flags_.proxyObject && "getComputedSlotValue called on a Proxy"); if (LLVM_LIKELY(desc.flags.indexed)) { assert( self->flags_.indexedStorage && "indexed flag set but no indexed storage"); - return getOwnIndexed(self, runtime, desc.slot); + return createPseudoHandle(getOwnIndexed(self.get(), runtime, desc.slot)); + } + if (LLVM_UNLIKELY(desc.flags.proxyObject) || + LLVM_UNLIKELY(desc.flags.hostObject)) { + SymbolID name = SymbolID::unsafeCreate(desc.slot); + assert(name.isValid() && "invalid SymbolID in descriptor"); + return getComputed_RJS( + runtime->makeHandle(std::move(self)), + runtime, + runtime->makeHandle(HermesValue::encodeSymbolValue(name))); + } + return createPseudoHandle(getNamedSlotValueUnsafe( + self.get(), runtime, desc.castToNamedPropertyDescriptorRef())); +} + +inline HermesValue JSObject::getComputedSlotValueUnsafe( + PseudoHandle self, + Runtime *runtime, + ComputedPropertyDescriptor desc) { + if (LLVM_LIKELY(desc.flags.indexed)) { + assert( + self->flags_.indexedStorage && + "indexed flag set but no indexed storage"); + return getOwnIndexed(self.get(), runtime, desc.slot); } // Call is valid because this function cannot be called with a Proxy. return getNamedSlotValueUnsafe( - self, runtime, desc.castToNamedPropertyDescriptorRef()); + self.get(), runtime, desc.castToNamedPropertyDescriptorRef()); } -inline ExecutionStatus JSObject::setComputedSlotValue( +inline CallResult JSObject::setComputedSlotValue( + Handle selfHandle, + Runtime *runtime, + MutableHandle &tmpSymbolStorage, + ComputedPropertyDescriptor desc, + Handle<> value) { + if (LLVM_LIKELY(desc.flags.indexed)) { + assert( + selfHandle->flags_.indexedStorage && + "indexed flag set but no indexed storage"); + return setOwnIndexed(selfHandle, runtime, desc.slot, value); + } + if (LLVM_UNLIKELY(desc.flags.proxyObject) || + LLVM_UNLIKELY(desc.flags.hostObject)) { + SymbolID name = SymbolID::unsafeCreate(desc.slot); + assert(name.isValid() && "invalid SymbolID in descriptor"); + return putComputed_RJS( + selfHandle, + runtime, + runtime->makeHandle(HermesValue::encodeSymbolValue(name)), + value); + } + setNamedSlotValueUnsafe( + selfHandle.get(), + runtime, + desc.castToNamedPropertyDescriptorRef(), + value.get()); + return true; +} + +inline ExecutionStatus JSObject::setComputedSlotValueUnsafe( Handle selfHandle, Runtime *runtime, ComputedPropertyDescriptor desc, Handle<> value) { - assert( - !selfHandle->isProxyObject() && "setComputedSlotValue called on a Proxy"); if (LLVM_LIKELY(desc.flags.indexed)) { assert( selfHandle->flags_.indexedStorage && diff --git a/lib/VM/Interpreter.cpp b/lib/VM/Interpreter.cpp index e1837dc7bf3..2eb10e03345 100644 --- a/lib/VM/Interpreter.cpp +++ b/lib/VM/Interpreter.cpp @@ -235,9 +235,10 @@ CallResult> Interpreter::getArgumentsPropByValSlowPath_RJS( // somewhere up in the prototype chain. Since we want to avoid reifying, // check which it is: MutableHandle inObject{runtime}; + MutableHandle inNameTmpStorage{runtime}; ComputedPropertyDescriptor desc; JSObject::getComputedPrimitiveDescriptor( - objectPrototype, runtime, strPrim, inObject, desc); + objectPrototype, runtime, strPrim, inObject, inNameTmpStorage, desc); // If we couldn't find the property, just return 'undefined'. if (!inObject) @@ -246,8 +247,11 @@ CallResult> Interpreter::getArgumentsPropByValSlowPath_RJS( // If the property isn't an accessor, we can just return it without // reifying. if (!desc.flags.accessor) { - return createPseudoHandle( - JSObject::getComputedSlotValue(inObject.get(), runtime, desc)); + return JSObject::getComputedSlotValue( + createPseudoHandle(inObject.get()), + runtime, + inNameTmpStorage, + desc); } } @@ -2668,12 +2672,23 @@ CallResult Interpreter::interpretFunction( uint32_t idx = O4REG(GetNextPName).getNumber(); uint32_t size = O5REG(GetNextPName).getNumber(); MutableHandle propObj{runtime}; + MutableHandle tmpPropNameStorage{runtime}; // Loop until we find a property which is present. while (idx < size) { tmpHandle = arr->at(idx); ComputedPropertyDescriptor desc; - CAPTURE_IP(JSObject::getComputedPrimitiveDescriptor( - obj, runtime, tmpHandle, propObj, desc)); + CAPTURE_IP_ASSIGN( + ExecutionStatus status, + JSObject::getComputedPrimitiveDescriptor( + obj, + runtime, + tmpHandle, + propObj, + tmpPropNameStorage, + desc)); + if (LLVM_UNLIKELY(status == ExecutionStatus::EXCEPTION)) { + goto exception; + } if (LLVM_LIKELY(propObj)) break; ++idx; diff --git a/lib/VM/JIT/ExternalCalls.cpp b/lib/VM/JIT/ExternalCalls.cpp index 272376cf525..4da346373fd 100644 --- a/lib/VM/JIT/ExternalCalls.cpp +++ b/lib/VM/JIT/ExternalCalls.cpp @@ -776,7 +776,7 @@ CallResult slowPathNegate( return HermesValue::encodeNumberValue(-res->getNumber()); } -HermesValue externGetNextPName( +CallResult externGetNextPName( Runtime *runtime, PinnedHermesValue *arrReg, PinnedHermesValue *objReg, @@ -792,13 +792,22 @@ HermesValue externGetNextPName( uint32_t size = sizeReg->getNumber(); PinnedHermesValue *scratch = &runtime->getCurrentFrame().getScratchRef(); MutableHandle propObj{runtime}; + MutableHandle tmpPropNameStorage{runtime}; // Loop until we find a property which is present. while (idx < size) { *scratch = arr->at(idx); ComputedPropertyDescriptor desc; - JSObject::getComputedPrimitiveDescriptor( - obj, runtime, Handle<>(scratch), propObj, desc); + if (LLVM_UNLIKELY( + JSObject::getComputedPrimitiveDescriptor( + obj, + runtime, + Handle<>(scratch), + tmpPropNameStorage, + propObj, + desc) == ExecutionStatus::EXCEPTION)) { + return ExecutionStatus::EXCEPTION; + } if (LLVM_LIKELY(propObj)) break; ++idx; diff --git a/lib/VM/JIT/ExternalCalls.h b/lib/VM/JIT/ExternalCalls.h index 913214a7e48..628de1c56d7 100644 --- a/lib/VM/JIT/ExternalCalls.h +++ b/lib/VM/JIT/ExternalCalls.h @@ -345,7 +345,7 @@ CallResult slowPathNegate( /// \param iterReg the iterating index, it will be incremented by 1 every time /// GetNextPName is called. /// \param sizeReg the size of property list. -HermesValue externGetNextPName( +CallResult externGetNextPName( Runtime *runtime, PinnedHermesValue *arrReg, PinnedHermesValue *objReg, diff --git a/lib/VM/JSLib/Array.cpp b/lib/VM/JSLib/Array.cpp index 8f882eb59ff..ed97e5c1c76 100644 --- a/lib/VM/JSLib/Array.cpp +++ b/lib/VM/JSLib/Array.cpp @@ -599,6 +599,7 @@ arrayPrototypeConcat(void *, Runtime *runtime, NativeArgs args) { MutableHandle<> tmpHandle{runtime}; // Used to find the object in the prototype chain that has index as property. MutableHandle propObj{runtime}; + MutableHandle tmpPropNameStorage{runtime}; auto marker = gcScope.createMarker(); ComputedPropertyDescriptor desc; @@ -671,10 +672,15 @@ arrayPrototypeConcat(void *, Runtime *runtime, NativeArgs args) { // may exist anywhere in the prototype chain. kHandle = HermesValue::encodeDoubleValue(k); JSObject::getComputedPrimitiveDescriptor( - objHandle, runtime, kHandle, propObj, desc); + objHandle, runtime, kHandle, propObj, tmpPropNameStorage, desc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - objHandle, runtime, propObj, desc, kHandle); + objHandle, + runtime, + propObj, + tmpPropNameStorage, + desc, + kHandle); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -956,6 +962,10 @@ class StandardSortModel : public SortModel { /// Object to sort elements [0, length). Handle obj_; + /// Temporary handles for property name. + MutableHandle aTmpNameStorage_; + MutableHandle bTmpNameStorage_; + /// Preallocate handles in the current GCScope so that we don't have to make /// new handles in every method call. @@ -984,6 +994,8 @@ class StandardSortModel : public SortModel { gcScope_(runtime), compareFn_(compareFn), obj_(obj), + aTmpNameStorage_(runtime), + bTmpNameStorage_(runtime), aHandle_(runtime), bHandle_(runtime), aValue_(runtime), @@ -1002,16 +1014,21 @@ class StandardSortModel : public SortModel { ComputedPropertyDescriptor aDesc; JSObject::getComputedPrimitiveDescriptor( - obj_, runtime_, aHandle_, aDescObjHandle_, aDesc); + obj_, runtime_, aHandle_, aDescObjHandle_, aTmpNameStorage_, aDesc); ComputedPropertyDescriptor bDesc; JSObject::getComputedPrimitiveDescriptor( - obj_, runtime_, bHandle_, bDescObjHandle_, bDesc); + obj_, runtime_, bHandle_, bDescObjHandle_, bTmpNameStorage_, bDesc); if (aDescObjHandle_) { if (LLVM_LIKELY(!aDesc.flags.proxyObject)) { auto res = JSObject::getComputedPropertyValue_RJS( - obj_, runtime_, aDescObjHandle_, aDesc, aDescObjHandle_); + obj_, + runtime_, + aDescObjHandle_, + aTmpNameStorage_, + aDesc, + aDescObjHandle_); if (res == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } @@ -1044,7 +1061,12 @@ class StandardSortModel : public SortModel { if (bDescObjHandle_) { if (LLVM_LIKELY(!bDesc.flags.proxyObject)) { auto res = JSObject::getComputedPropertyValue_RJS( - obj_, runtime_, bDescObjHandle_, bDesc, bDescObjHandle_); + obj_, + runtime_, + bDescObjHandle_, + bTmpNameStorage_, + bDesc, + bDescObjHandle_); if (res == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } @@ -1129,9 +1151,9 @@ class StandardSortModel : public SortModel { ComputedPropertyDescriptor aDesc; JSObject::getComputedPrimitiveDescriptor( - obj_, runtime_, aHandle_, aDescObjHandle_, aDesc); + obj_, runtime_, aHandle_, aDescObjHandle_, aTmpNameStorage_, aDesc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - obj_, runtime_, aDescObjHandle_, aDesc, aHandle_); + obj_, runtime_, aDescObjHandle_, aTmpNameStorage_, aDesc, aHandle_); if (propRes == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } @@ -1144,10 +1166,14 @@ class StandardSortModel : public SortModel { ComputedPropertyDescriptor bDesc; JSObject::getComputedPrimitiveDescriptor( - obj_, runtime_, bHandle_, bDescObjHandle_, bDesc); + obj_, runtime_, bHandle_, bDescObjHandle_, bTmpNameStorage_, bDesc); if ((propRes = JSObject::getComputedPropertyValue_RJS( - obj_, runtime_, bDescObjHandle_, bDesc, bHandle_)) == - ExecutionStatus::EXCEPTION) { + obj_, + runtime_, + bDescObjHandle_, + bTmpNameStorage_, + bDesc, + bHandle_)) == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } if ((*propRes)->isEmpty()) { @@ -1390,6 +1416,7 @@ arrayPrototypeForEach(void *, Runtime *runtime, NativeArgs args) { MutableHandle<> k{runtime, HermesValue::encodeDoubleValue(0)}; MutableHandle descObjHandle{runtime}; + MutableHandle tmpPropNameStorage{runtime}; // Loop through and execute the callback on all existing values. // TODO: Implement a fast path for actual arrays. @@ -1399,9 +1426,9 @@ arrayPrototypeForEach(void *, Runtime *runtime, NativeArgs args) { ComputedPropertyDescriptor desc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, k, descObjHandle, desc); + O, runtime, k, descObjHandle, tmpPropNameStorage, desc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, descObjHandle, desc, k); + O, runtime, descObjHandle, tmpPropNameStorage, desc, k); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -1456,6 +1483,7 @@ static CallResult flattenIntoArray( // Temporary storage for sourceIndex and targetIndex. MutableHandle<> indexHandle{runtime}; + MutableHandle tmpPropNameStorage{runtime}; MutableHandle propObj{runtime}; MutableHandle<> element{runtime}; MutableHandle<> lenResHandle{runtime}; @@ -1472,15 +1500,19 @@ static CallResult flattenIntoArray( indexHandle = HermesValue::encodeNumberValue(sourceIndex); if (LLVM_UNLIKELY( JSObject::getComputedDescriptor( - source, runtime, indexHandle, propObj, desc) == - ExecutionStatus::EXCEPTION)) { + source, + runtime, + indexHandle, + propObj, + tmpPropNameStorage, + desc) == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } // c. If exists is true, then // i. Let element be ? Get(source, P). CallResult> elementRes = JSObject::getComputedPropertyValue_RJS( - source, runtime, propObj, desc, indexHandle); + source, runtime, propObj, tmpPropNameStorage, desc, indexHandle); if (LLVM_UNLIKELY(elementRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -1767,6 +1799,7 @@ arrayPrototypeSlice(void *, Runtime *runtime, NativeArgs args) { uint32_t n = 0; MutableHandle descObjHandle{runtime}; + MutableHandle tmpPropNameStorage{runtime}; MutableHandle<> kValue{runtime}; auto marker = gcScope.createMarker(); @@ -1775,9 +1808,9 @@ arrayPrototypeSlice(void *, Runtime *runtime, NativeArgs args) { while (k->getNumber() < fin) { ComputedPropertyDescriptor desc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, k, descObjHandle, desc); + O, runtime, k, descObjHandle, tmpPropNameStorage, desc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, descObjHandle, desc, k); + O, runtime, descObjHandle, tmpPropNameStorage, desc, k); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -1879,6 +1912,7 @@ arrayPrototypeSplice(void *, Runtime *runtime, NativeArgs args) { MutableHandle<> to{runtime}; // Value storage used for copying values. + MutableHandle tmpPropNameStorage{runtime}; MutableHandle fromDescObjHandle{runtime}; MutableHandle<> fromValue{runtime}; @@ -1895,10 +1929,15 @@ arrayPrototypeSplice(void *, Runtime *runtime, NativeArgs args) { ComputedPropertyDescriptor fromDesc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, from, fromDescObjHandle, fromDesc); + O, runtime, from, fromDescObjHandle, tmpPropNameStorage, fromDesc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, fromDescObjHandle, fromDesc, from); + O, + runtime, + fromDescObjHandle, + tmpPropNameStorage, + fromDesc, + from); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -1943,10 +1982,15 @@ arrayPrototypeSplice(void *, Runtime *runtime, NativeArgs args) { to = HermesValue::encodeDoubleValue(j + itemCount); ComputedPropertyDescriptor fromDesc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, from, fromDescObjHandle, fromDesc); + O, runtime, from, fromDescObjHandle, tmpPropNameStorage, fromDesc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, fromDescObjHandle, fromDesc, from); + O, + runtime, + fromDescObjHandle, + tmpPropNameStorage, + fromDesc, + from); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -2001,10 +2045,15 @@ arrayPrototypeSplice(void *, Runtime *runtime, NativeArgs args) { ComputedPropertyDescriptor fromDesc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, from, fromDescObjHandle, fromDesc); + O, runtime, from, fromDescObjHandle, tmpPropNameStorage, fromDesc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, fromDescObjHandle, fromDesc, from); + O, + runtime, + fromDescObjHandle, + tmpPropNameStorage, + fromDesc, + from); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -2163,6 +2212,7 @@ arrayPrototypeCopyWithin(void *, Runtime *runtime, NativeArgs args) { MutableHandle<> fromHandle{runtime, HermesValue::encodeNumberValue(from)}; MutableHandle<> toHandle{runtime, HermesValue::encodeNumberValue(to)}; + MutableHandle fromNameTmpStorage{runtime}; MutableHandle fromObj{runtime}; MutableHandle<> fromVal{runtime}; @@ -2177,13 +2227,17 @@ arrayPrototypeCopyWithin(void *, Runtime *runtime, NativeArgs args) { ComputedPropertyDescriptor fromDesc; if (LLVM_UNLIKELY( JSObject::getComputedDescriptor( - O, runtime, fromHandle, fromObj, fromDesc) == - ExecutionStatus::EXCEPTION)) { + O, + runtime, + fromHandle, + fromObj, + fromNameTmpStorage, + fromDesc) == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } CallResult> fromValRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, fromObj, fromDesc, fromHandle); + O, runtime, fromObj, fromNameTmpStorage, fromDesc, fromHandle); if (LLVM_UNLIKELY(fromValRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -2332,6 +2386,7 @@ arrayPrototypeShift(void *, Runtime *runtime, NativeArgs args) { MutableHandle<> from{runtime, HermesValue::encodeDoubleValue(1)}; MutableHandle<> to{runtime}; + MutableHandle fromNameTmpStorage{runtime}; MutableHandle fromDescObjHandle{runtime}; MutableHandle<> fromVal{runtime}; @@ -2345,9 +2400,9 @@ arrayPrototypeShift(void *, Runtime *runtime, NativeArgs args) { ComputedPropertyDescriptor fromDesc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, from, fromDescObjHandle, fromDesc); + O, runtime, from, fromDescObjHandle, fromNameTmpStorage, fromDesc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, fromDescObjHandle, fromDesc, from); + O, runtime, fromDescObjHandle, fromNameTmpStorage, fromDesc, from); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -2452,6 +2507,7 @@ indexOfHelper(Runtime *runtime, NativeArgs args, const bool reverse) { } } + MutableHandle tmpPropNameStorage{runtime}; MutableHandle descObjHandle{runtime}; // Search for the element. @@ -2471,9 +2527,9 @@ indexOfHelper(Runtime *runtime, NativeArgs args, const bool reverse) { } ComputedPropertyDescriptor desc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, k, descObjHandle, desc); + O, runtime, k, descObjHandle, tmpPropNameStorage, desc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, descObjHandle, desc, k); + O, runtime, descObjHandle, tmpPropNameStorage, desc, k); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -2527,6 +2583,7 @@ arrayPrototypeUnshift(void *, Runtime *runtime, NativeArgs args) { MutableHandle<> to{runtime}; // Value that is being copied. + MutableHandle fromNameTmpStorage{runtime}; MutableHandle fromDescObjHandle{runtime}; MutableHandle<> fromValue{runtime}; @@ -2540,10 +2597,15 @@ arrayPrototypeUnshift(void *, Runtime *runtime, NativeArgs args) { ComputedPropertyDescriptor fromDesc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, from, fromDescObjHandle, fromDesc); + O, runtime, from, fromDescObjHandle, fromNameTmpStorage, fromDesc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, fromDescObjHandle, fromDesc, from); + O, + runtime, + fromDescObjHandle, + fromNameTmpStorage, + fromDesc, + from); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -2640,6 +2702,7 @@ everySomeHelper(Runtime *runtime, NativeArgs args, const bool every) { MutableHandle<> k{runtime, HermesValue::encodeDoubleValue(0)}; // Value at index k; + MutableHandle tmpPropNameStorage{runtime}; MutableHandle descObjHandle{runtime}; MutableHandle<> kValue{runtime}; @@ -2650,9 +2713,9 @@ everySomeHelper(Runtime *runtime, NativeArgs args, const bool every) { ComputedPropertyDescriptor desc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, k, descObjHandle, desc); + O, runtime, k, descObjHandle, tmpPropNameStorage, desc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, descObjHandle, desc, k); + O, runtime, descObjHandle, tmpPropNameStorage, desc, k); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -2740,6 +2803,7 @@ arrayPrototypeMap(void *, Runtime *runtime, NativeArgs args) { // Current index to execute callback on. MutableHandle<> k{runtime, HermesValue::encodeDoubleValue(0)}; + MutableHandle tmpPropNameStorage{runtime}; MutableHandle descObjHandle{runtime}; // Main loop to execute callback and store the results in A. @@ -2750,9 +2814,9 @@ arrayPrototypeMap(void *, Runtime *runtime, NativeArgs args) { ComputedPropertyDescriptor desc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, k, descObjHandle, desc); + O, runtime, k, descObjHandle, tmpPropNameStorage, desc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, descObjHandle, desc, k); + O, runtime, descObjHandle, tmpPropNameStorage, desc, k); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -2820,6 +2884,7 @@ arrayPrototypeFilter(void *, Runtime *runtime, NativeArgs args) { uint32_t to = 0; // Value at index k. + MutableHandle tmpPropNameStorage{runtime}; MutableHandle descObjHandle{runtime}; MutableHandle<> kValue{runtime}; @@ -2829,9 +2894,9 @@ arrayPrototypeFilter(void *, Runtime *runtime, NativeArgs args) { ComputedPropertyDescriptor desc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, k, descObjHandle, desc); + O, runtime, k, descObjHandle, tmpPropNameStorage, desc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, descObjHandle, desc, k); + O, runtime, descObjHandle, tmpPropNameStorage, desc, k); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -3029,6 +3094,7 @@ reduceHelper(Runtime *runtime, NativeArgs args, const bool reverse) { // Current index in the reduction iteration. MutableHandle<> k{ runtime, HermesValue::encodeDoubleValue(reverse ? len - 1 : 0)}; + MutableHandle kNameTmpStorage{runtime}; MutableHandle kDescObjHandle{runtime}; MutableHandle<> accumulator{runtime}; @@ -3057,10 +3123,10 @@ reduceHelper(Runtime *runtime, NativeArgs args, const bool reverse) { } ComputedPropertyDescriptor kDesc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, k, kDescObjHandle, kDesc); + O, runtime, k, kDescObjHandle, kNameTmpStorage, kDesc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, kDescObjHandle, kDesc, k); + O, runtime, kDescObjHandle, kNameTmpStorage, kDesc, k); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -3091,9 +3157,9 @@ reduceHelper(Runtime *runtime, NativeArgs args, const bool reverse) { ComputedPropertyDescriptor kDesc; JSObject::getComputedPrimitiveDescriptor( - O, runtime, k, kDescObjHandle, kDesc); + O, runtime, k, kDescObjHandle, kNameTmpStorage, kDesc); CallResult> propRes = JSObject::getComputedPropertyValue_RJS( - O, runtime, kDescObjHandle, kDesc, k); + O, runtime, kDescObjHandle, kNameTmpStorage, kDesc, k); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } diff --git a/lib/VM/JSLib/HermesBuiltin.cpp b/lib/VM/JSLib/HermesBuiltin.cpp index 171cca2c915..ad877ae0701 100644 --- a/lib/VM/JSLib/HermesBuiltin.cpp +++ b/lib/VM/JSLib/HermesBuiltin.cpp @@ -268,6 +268,7 @@ CallResult copyDataPropertiesSlowPath_RJS( MutableHandle<> nextKeyHandle{runtime}; MutableHandle<> propValueHandle{runtime}; + MutableHandle tmpSymbolStorage{runtime}; GCScopeMarkerRAII marker{runtime}; // 6. For each element nextKey of keys in List order, do for (uint32_t nextKeyIdx = 0, endIdx = keys->getEndIndex(); @@ -297,6 +298,7 @@ CallResult copyDataPropertiesSlowPath_RJS( runtime, nextKeyHandle, JSObject::IgnoreProxy::Yes, + tmpSymbolStorage, desc); if (LLVM_UNLIKELY(cr == ExecutionStatus::EXCEPTION)) return ExecutionStatus::EXCEPTION; @@ -383,13 +385,19 @@ hermesBuiltinCopyDataProperties(void *, Runtime *runtime, NativeArgs args) { MutableHandle<> nameHandle{runtime}; MutableHandle<> valueHandle{runtime}; + MutableHandle tmpSymbolStorage{runtime}; // Process all named properties/symbols. bool success = JSObject::forEachOwnPropertyWhile( source, runtime, // indexedCB. - [&source, &target, &excludedItems, &nameHandle, &valueHandle]( + [&source, + &target, + &excludedItems, + &nameHandle, + &valueHandle, + &tmpSymbolStorage]( Runtime *runtime, uint32_t index, ComputedPropertyDescriptor desc) { if (!desc.flags.enumerable) return true; @@ -406,6 +414,7 @@ hermesBuiltinCopyDataProperties(void *, Runtime *runtime, NativeArgs args) { runtime, nameHandle, JSObject::IgnoreProxy::Yes, + tmpSymbolStorage, xdesc); if (LLVM_UNLIKELY(cr == ExecutionStatus::EXCEPTION)) return false; diff --git a/lib/VM/JSLib/Object.cpp b/lib/VM/JSLib/Object.cpp index 63d43a20861..3df58c41be4 100644 --- a/lib/VM/JSLib/Object.cpp +++ b/lib/VM/JSLib/Object.cpp @@ -334,9 +334,10 @@ CallResult getOwnPropertyDescriptor( Handle<> key) { ComputedPropertyDescriptor desc; MutableHandle<> valueOrAccessor{runtime}; + MutableHandle tmpPropNameStorage{runtime}; { auto result = JSObject::getOwnComputedDescriptor( - object, runtime, key, desc, valueOrAccessor); + object, runtime, key, tmpPropNameStorage, desc, valueOrAccessor); if (result == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } @@ -605,12 +606,13 @@ objectDefinePropertiesInternal(Runtime *runtime, Handle<> obj, Handle<> props) { // We store each property name here. This is hoisted out of the loop // to avoid allocating a handle per property. MutableHandle<> propName{runtime}; + MutableHandle tmpPropNameStorage{runtime}; for (unsigned i = 0, e = propNames->getEndIndex(); i < e; ++i) { propName = propNames->at(runtime, i); ComputedPropertyDescriptor desc; CallResult descRes = JSObject::getOwnComputedDescriptor( - propsHandle, runtime, propName, desc); + propsHandle, runtime, propName, tmpPropNameStorage, desc); if (LLVM_UNLIKELY(descRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -619,7 +621,7 @@ objectDefinePropertiesInternal(Runtime *runtime, Handle<> obj, Handle<> props) { } CallResult> propRes = propsHandle->isProxyObject() ? JSObject::getComputed_RJS(propsHandle, runtime, propName) - : JSObject::getComputedPropertyValue_RJS( + : JSObject::getComputedPropertyValueInternal_RJS( propsHandle, runtime, propsHandle, desc); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; @@ -813,6 +815,7 @@ CallResult enumerableOwnProperties_RJS( MutableHandle name{runtime}; MutableHandle<> value{runtime}; MutableHandle<> entry{runtime}; + MutableHandle tmpPropNameStorage{runtime}; uint32_t targetIdx = 0; @@ -828,7 +831,12 @@ CallResult enumerableOwnProperties_RJS( // By calling getString, name is guaranteed to be primitive. ComputedPropertyDescriptor desc; CallResult descRes = JSObject::getOwnComputedPrimitiveDescriptor( - objHandle, runtime, name, JSObject::IgnoreProxy::Yes, desc); + objHandle, + runtime, + name, + JSObject::IgnoreProxy::Yes, + tmpPropNameStorage, + desc); if (LLVM_UNLIKELY(descRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -836,7 +844,8 @@ CallResult enumerableOwnProperties_RJS( // Ensure that the property is still there and that it is enumerable, // as descriptors can be modified by a getter at any point. - auto valueRes = JSObject::getComputedPropertyValue_RJS( + // Safe to call the Internal version here because we ignored Proxy above. + auto valueRes = JSObject::getComputedPropertyValueInternal_RJS( objHandle, runtime, objHandle, desc); if (LLVM_UNLIKELY(valueRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; @@ -1000,6 +1009,8 @@ objectAssign(void *, Runtime *runtime, NativeArgs args) { MutableHandle<> nextKeyHandle{runtime}; // Handle for the property value being copied. MutableHandle<> propValueHandle{runtime}; + // Handle for the property value being copied. + MutableHandle tmpPropNameStorage{runtime}; for (uint32_t argIdx = 1; argIdx < args.getArgCount(); argIdx++) { GCScopeMarkerRAII markerOuter(gcScope); @@ -1042,7 +1053,7 @@ objectAssign(void *, Runtime *runtime, NativeArgs args) { // 5.c.i. Let desc be from.[[GetOwnProperty]](nextKey). auto descCr = JSObject::getOwnComputedDescriptor( - fromHandle, runtime, nextKeyHandle, desc); + fromHandle, runtime, nextKeyHandle, tmpPropNameStorage, desc); if (LLVM_UNLIKELY(descCr == ExecutionStatus::EXCEPTION)) { // 5.c.ii. ReturnIfAbrupt(desc). return ExecutionStatus::EXCEPTION; @@ -1061,7 +1072,12 @@ objectAssign(void *, Runtime *runtime, NativeArgs args) { CallResult> propRes = fromHandle->isProxyObject() ? JSObject::getComputed_RJS(fromHandle, runtime, nextKeyHandle) : JSObject::getComputedPropertyValue_RJS( - fromHandle, runtime, fromHandle, desc); + fromHandle, + runtime, + fromHandle, + tmpPropNameStorage, + desc, + nextKeyHandle); if (LLVM_UNLIKELY(propRes == ExecutionStatus::EXCEPTION)) { // 5.c.iii.2. ReturnIfAbrupt(propValue). return ExecutionStatus::EXCEPTION; @@ -1266,8 +1282,9 @@ objectPrototypeHasOwnProperty(void *, Runtime *runtime, NativeArgs args) { /// 3. Return ? HasOwnProperty(O, P). ComputedPropertyDescriptor desc; - CallResult hasProp = - JSObject::getOwnComputedDescriptor(O, runtime, P, desc); + MutableHandle tmpPropNameStorage{runtime}; + CallResult hasProp = JSObject::getOwnComputedDescriptor( + O, runtime, P, tmpPropNameStorage, desc); if (LLVM_UNLIKELY(hasProp == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -1322,6 +1339,7 @@ objectPrototypeIsPrototypeOf(void *, Runtime *runtime, NativeArgs args) { CallResult objectPrototypePropertyIsEnumerable(void *, Runtime *runtime, NativeArgs args) { + MutableHandle tmpPropNameStorage{runtime}; auto res = toObject(runtime, args.getThisHandle()); if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; @@ -1331,6 +1349,7 @@ objectPrototypePropertyIsEnumerable(void *, Runtime *runtime, NativeArgs args) { runtime->makeHandle(res.getValue()), runtime, args.getArgHandle(0), + tmpPropNameStorage, desc); if (LLVM_UNLIKELY(status == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; @@ -1480,10 +1499,11 @@ CallResult lookupAccessor( runtime->makeMutableHandle(vmcast(*res)); Handle<> key = args.getArgHandle(0); MutableHandle<> valueOrAccessor{runtime}; + MutableHandle tmpPropNameStorage{runtime}; do { ComputedPropertyDescriptor desc; CallResult definedRes = JSObject::getOwnComputedDescriptor( - O, runtime, key, desc, valueOrAccessor); + O, runtime, key, tmpPropNameStorage, desc, valueOrAccessor); if (LLVM_UNLIKELY(definedRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } diff --git a/lib/VM/JSObject.cpp b/lib/VM/JSObject.cpp index 15a22f6a685..3a3525857d9 100644 --- a/lib/VM/JSObject.cpp +++ b/lib/VM/JSObject.cpp @@ -327,7 +327,7 @@ CallResult> JSObject::getNamedPropertyValue_RJS( runtime->makeHandle(accessor->getter), runtime, selfHandle); } -CallResult> JSObject::getComputedPropertyValue_RJS( +CallResult> JSObject::getComputedPropertyValueInternal_RJS( Handle selfHandle, Runtime *runtime, Handle propObj, @@ -337,11 +337,11 @@ CallResult> JSObject::getComputedPropertyValue_RJS( "getComputedPropertyValue_RJS cannot be used with proxy objects"); if (LLVM_LIKELY(!desc.flags.accessor)) - return createPseudoHandle( - getComputedSlotValue(propObj.get(), runtime, desc)); + return createPseudoHandle(getComputedSlotValueUnsafe( + createPseudoHandle(propObj.get()), runtime, desc)); - auto *accessor = vmcast( - getComputedSlotValue(propObj.get(), runtime, desc)); + auto *accessor = vmcast(getComputedSlotValueUnsafe( + createPseudoHandle(propObj.get()), runtime, desc)); if (!accessor->getter) return createPseudoHandle(HermesValue::encodeUndefinedValue()); @@ -354,6 +354,7 @@ CallResult> JSObject::getComputedPropertyValue_RJS( Handle selfHandle, Runtime *runtime, Handle propObj, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor desc, Handle<> nameValHandle) { if (!propObj) { @@ -361,7 +362,7 @@ CallResult> JSObject::getComputedPropertyValue_RJS( } if (LLVM_LIKELY(!desc.flags.proxyObject)) { - return JSObject::getComputedPropertyValue_RJS( + return JSObject::getComputedPropertyValueInternal_RJS( selfHandle, runtime, propObj, desc); } @@ -725,6 +726,7 @@ CallResult getOwnComputedPrimitiveDescriptorImpl( Handle<> nameValHandle, JSObject::IgnoreProxy ignoreProxy, SymbolID &id, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc) { assert( !nameValHandle->isObject() && @@ -805,7 +807,12 @@ CallResult getOwnComputedPrimitiveDescriptorImpl( if (selfHandle->isLazy()) { JSObject::initializeLazyObject(runtime, selfHandle); return JSObject::getOwnComputedPrimitiveDescriptor( - selfHandle, runtime, nameValHandle, ignoreProxy, desc); + selfHandle, + runtime, + nameValHandle, + ignoreProxy, + tmpSymbolStorage, + desc); } assert(selfHandle->isProxyObject() && "descriptor flags are impossible"); @@ -823,30 +830,39 @@ CallResult JSObject::getOwnComputedPrimitiveDescriptor( Runtime *runtime, Handle<> nameValHandle, JSObject::IgnoreProxy ignoreProxy, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc) { SymbolID id{}; return getOwnComputedPrimitiveDescriptorImpl( - selfHandle, runtime, nameValHandle, ignoreProxy, id, desc); + selfHandle, + runtime, + nameValHandle, + ignoreProxy, + id, + tmpSymbolStorage, + desc); } CallResult JSObject::getOwnComputedDescriptor( Handle selfHandle, Runtime *runtime, Handle<> nameValHandle, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc) { auto converted = toPropertyKeyIfObject(runtime, nameValHandle); if (LLVM_UNLIKELY(converted == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } return JSObject::getOwnComputedPrimitiveDescriptor( - selfHandle, runtime, *converted, IgnoreProxy::No, desc); + selfHandle, runtime, *converted, IgnoreProxy::No, tmpSymbolStorage, desc); } CallResult JSObject::getOwnComputedDescriptor( Handle selfHandle, Runtime *runtime, Handle<> nameValHandle, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc, MutableHandle<> &valueOrAccessor) { auto converted = toPropertyKeyIfObject(runtime, nameValHandle); @@ -858,12 +874,20 @@ CallResult JSObject::getOwnComputedDescriptor( // getOwnComputedPrimitiveDescriptor doesn't pass back the // valueOrAccessor. CallResult res = JSObject::getOwnComputedPrimitiveDescriptor( - selfHandle, runtime, *converted, IgnoreProxy::Yes, desc); + selfHandle, + runtime, + *converted, + IgnoreProxy::Yes, + tmpSymbolStorage, + desc); if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } if (*res) { - valueOrAccessor = getComputedSlotValue(selfHandle.get(), runtime, desc); + // This is safe because we passed IgnoreProxy::Yes above, + // meaning that this will return false in proxy cases. + valueOrAccessor = getComputedSlotValueUnsafe( + createPseudoHandle(selfHandle.get()), runtime, desc); return true; } if (LLVM_UNLIKELY(selfHandle->isProxyObject())) { @@ -962,6 +986,7 @@ ExecutionStatus JSObject::getComputedPrimitiveDescriptor( Runtime *runtime, Handle<> nameValHandle, MutableHandle &propObj, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc) { assert( !nameValHandle->isObject() && @@ -981,7 +1006,13 @@ ExecutionStatus JSObject::getComputedPrimitiveDescriptor( Handle loopHandle = propObj; CallResult res = getOwnComputedPrimitiveDescriptorImpl( - loopHandle, runtime, nameValHandle, IgnoreProxy::Yes, id, desc); + loopHandle, + runtime, + nameValHandle, + IgnoreProxy::Yes, + id, + tmpSymbolStorage, + desc); if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -992,10 +1023,14 @@ ExecutionStatus JSObject::getComputedPrimitiveDescriptor( if (LLVM_UNLIKELY(propObj->flags_.hostObject)) { desc.flags.hostObject = true; desc.flags.writable = true; + desc.slot = id.unsafeGetRaw(); + tmpSymbolStorage = id; return ExecutionStatus::RETURNED; } if (LLVM_UNLIKELY(propObj->flags_.proxyObject)) { desc.flags.proxyObject = true; + desc.slot = id.unsafeGetRaw(); + tmpSymbolStorage = id; return ExecutionStatus::RETURNED; } // This isn't a proxy, so use the faster getParent() instead of @@ -1013,13 +1048,14 @@ ExecutionStatus JSObject::getComputedDescriptor( Runtime *runtime, Handle<> nameValHandle, MutableHandle &propObj, + MutableHandle &tmpSymbolStorage, ComputedPropertyDescriptor &desc) { auto converted = toPropertyKeyIfObject(runtime, nameValHandle); if (LLVM_UNLIKELY(converted == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } return getComputedPrimitiveDescriptor( - selfHandle, runtime, *converted, propObj, desc); + selfHandle, runtime, *converted, propObj, tmpSymbolStorage, desc); } CallResult> JSObject::getNamedWithReceiver_RJS( @@ -1129,10 +1165,15 @@ CallResult> JSObject::getComputedWithReceiver_RJS( // Locate the descriptor. propObj contains the object which may be anywhere // along the prototype chain. MutableHandle propObj{runtime}; + MutableHandle tmpPropNameStorage{runtime}; if (LLVM_UNLIKELY( getComputedPrimitiveDescriptor( - selfHandle, runtime, nameValPrimitiveHandle, propObj, desc) == - ExecutionStatus::EXCEPTION)) { + selfHandle, + runtime, + nameValPrimitiveHandle, + propObj, + tmpPropNameStorage, + desc) == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -1142,13 +1183,13 @@ CallResult> JSObject::getComputedWithReceiver_RJS( if (LLVM_LIKELY( !desc.flags.accessor && !desc.flags.hostObject && !desc.flags.proxyObject)) { - return createPseudoHandle( - getComputedSlotValue(propObj.get(), runtime, desc)); + return createPseudoHandle(getComputedSlotValueUnsafe( + createPseudoHandle(propObj.get()), runtime, desc)); } if (desc.flags.accessor) { - auto *accessor = vmcast( - getComputedSlotValue(propObj.get(), runtime, desc)); + auto *accessor = vmcast(getComputedSlotValueUnsafe( + createPseudoHandle(propObj.get()), runtime, desc)); if (!accessor->getter) return createPseudoHandle(HermesValue::encodeUndefinedValue()); @@ -1233,10 +1274,15 @@ CallResult JSObject::hasComputed( auto nameValPrimitiveHandle = *converted; ComputedPropertyDescriptor desc; + MutableHandle tmpPropNameStorage{runtime}; MutableHandle propObj{runtime}; if (getComputedPrimitiveDescriptor( - selfHandle, runtime, nameValPrimitiveHandle, propObj, desc) == - ExecutionStatus::EXCEPTION) { + selfHandle, + runtime, + nameValPrimitiveHandle, + propObj, + tmpPropNameStorage, + desc) == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } if (!propObj) { @@ -1408,6 +1454,7 @@ CallResult JSObject::putNamedWithReceiver_RJS( // this object. MutableHandle receiverHandle{runtime, *selfHandle}; + MutableHandle tmpSymbolStorage{runtime}; if (selfHandle.getHermesValue().getRaw() != receiver->getRaw() || receiverHandle->isHostObject() || receiverHandle->isProxyObject()) { if (selfHandle.getHermesValue().getRaw() != receiver->getRaw()) { @@ -1444,7 +1491,12 @@ CallResult JSObject::putNamedWithReceiver_RJS( ComputedPropertyDescriptor desc; Handle<> nameValHandle = runtime->makeHandle(name); CallResult descDefinedRes = getOwnComputedPrimitiveDescriptor( - receiverHandle, runtime, nameValHandle, IgnoreProxy::No, desc); + receiverHandle, + runtime, + nameValHandle, + IgnoreProxy::No, + tmpSymbolStorage, + desc); if (LLVM_UNLIKELY(descDefinedRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -1551,10 +1603,15 @@ CallResult JSObject::putComputedWithReceiver_RJS( // Look for the property in this object or along the prototype chain. MutableHandle propObj{runtime}; + MutableHandle tmpSymbolStorage{runtime}; if (LLVM_UNLIKELY( getComputedPrimitiveDescriptor( - selfHandle, runtime, nameValPrimitiveHandle, propObj, desc) == - ExecutionStatus::EXCEPTION)) { + selfHandle, + runtime, + nameValPrimitiveHandle, + propObj, + tmpSymbolStorage, + desc) == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -1574,7 +1631,8 @@ CallResult JSObject::putComputedWithReceiver_RJS( !desc.flags.hostObject && !desc.flags.proxyObject && desc.flags.writable)) { if (LLVM_UNLIKELY( - setComputedSlotValue(selfHandle, runtime, desc, valueHandle) == + setComputedSlotValueUnsafe( + selfHandle, runtime, desc, valueHandle) == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } @@ -1584,7 +1642,7 @@ CallResult JSObject::putComputedWithReceiver_RJS( // Is it an accessor? if (LLVM_UNLIKELY(desc.flags.accessor)) { auto *accessor = vmcast( - getComputedSlotValue(propObj.get(), runtime, desc)); + getComputedSlotValueUnsafe(propObj, runtime, desc)); // If it is a read-only accessor, fail. if (!accessor->setter) { @@ -1673,6 +1731,7 @@ CallResult JSObject::putComputedWithReceiver_RJS( runtime, nameValPrimitiveHandle, IgnoreProxy::No, + tmpSymbolStorage, existingDesc); if (LLVM_UNLIKELY(descDefinedRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; @@ -1689,7 +1748,7 @@ CallResult JSObject::putComputedWithReceiver_RJS( !receiverHandle->isHostObject() && !receiverHandle->isProxyObject())) { if (LLVM_UNLIKELY( - setComputedSlotValue( + setComputedSlotValueUnsafe( receiverHandle, runtime, existingDesc, valueHandle) == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; diff --git a/lib/VM/JSProxy.cpp b/lib/VM/JSProxy.cpp index d084edc4e1e..7f34da6a113 100644 --- a/lib/VM/JSProxy.cpp +++ b/lib/VM/JSProxy.cpp @@ -501,14 +501,20 @@ CallResult JSProxy::getOwnProperty( if (trapRes == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } + MutableHandle tmpPropNameStorage{runtime}; // 7. If trap is undefined, then if (!*trapRes) { // a. Return ? target.[[GetOwnProperty]](P). return valueOrAccessor ? JSObject::getOwnComputedDescriptor( - target, runtime, nameValHandle, desc, *valueOrAccessor) + target, + runtime, + nameValHandle, + tmpPropNameStorage, + desc, + *valueOrAccessor) : JSObject::getOwnComputedDescriptor( - target, runtime, nameValHandle, desc); + target, runtime, nameValHandle, tmpPropNameStorage, desc); } // 8. Let trapResultObj be ? Call(trap, handler, « target, P »). // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a @@ -527,7 +533,12 @@ CallResult JSProxy::getOwnProperty( ComputedPropertyDescriptor targetDesc; MutableHandle<> targetValueOrAccessor{runtime}; CallResult targetDescRes = JSObject::getOwnComputedDescriptor( - target, runtime, nameValHandle, targetDesc, targetValueOrAccessor); + target, + runtime, + nameValHandle, + tmpPropNameStorage, + targetDesc, + targetValueOrAccessor); if (targetDescRes == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } @@ -693,8 +704,14 @@ CallResult JSProxy::defineOwnProperty( // 11. Let targetDesc be ? target.[[GetOwnProperty]](P). ComputedPropertyDescriptor targetDesc; MutableHandle<> targetDescValueOrAccessor{runtime}; + MutableHandle tmpPropNameStorage{runtime}; CallResult targetDescRes = JSObject::getOwnComputedDescriptor( - target, runtime, nameValHandle, targetDesc, targetDescValueOrAccessor); + target, + runtime, + nameValHandle, + tmpPropNameStorage, + targetDesc, + targetDescValueOrAccessor); if (targetDescRes == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } @@ -771,8 +788,9 @@ CallResult hasWithTrap( if (!trapResult) { // a. Let targetDesc be ? target.[[GetOwnProperty]](P). ComputedPropertyDescriptor targetDesc; + MutableHandle tmpPropNameStorage{runtime}; CallResult targetDescRes = JSObject::getOwnComputedDescriptor( - target, runtime, nameValHandle, targetDesc); + target, runtime, nameValHandle, tmpPropNameStorage, targetDesc); if (targetDescRes == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } @@ -888,8 +906,14 @@ CallResult> getWithTrap( // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). ComputedPropertyDescriptor targetDesc; MutableHandle<> targetValueOrAccessor{runtime}; + MutableHandle tmpPropNameStorage{runtime}; CallResult targetDescRes = JSObject::getOwnComputedDescriptor( - target, runtime, nameValHandle, targetDesc, targetValueOrAccessor); + target, + runtime, + nameValHandle, + tmpPropNameStorage, + targetDesc, + targetValueOrAccessor); if (targetDescRes == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } @@ -1021,8 +1045,14 @@ CallResult setWithTrap( // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). ComputedPropertyDescriptor targetDesc; MutableHandle<> targetValueOrAccessor{runtime}; + MutableHandle tmpPropNameStorage{runtime}; CallResult targetDescRes = JSObject::getOwnComputedDescriptor( - target, runtime, nameValHandle, targetDesc, targetValueOrAccessor); + target, + runtime, + nameValHandle, + tmpPropNameStorage, + targetDesc, + targetValueOrAccessor); if (targetDescRes == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } @@ -1158,8 +1188,14 @@ CallResult deleteWithTrap( // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). ComputedPropertyDescriptor targetDesc; MutableHandle<> targetValueOrAccessor{runtime}; + MutableHandle tmpPropNameStorage{runtime}; CallResult targetDescRes = JSObject::getOwnComputedDescriptor( - target, runtime, nameValHandle, targetDesc, targetValueOrAccessor); + target, + runtime, + nameValHandle, + tmpPropNameStorage, + targetDesc, + targetValueOrAccessor); if (targetDescRes == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } @@ -1442,13 +1478,18 @@ CallResult> JSProxy::ownPropertyKeys( // 14. Let targetConfigurableKeys be a new empty List. // 15. Let targetNonconfigurableKeys be a new empty List. llvh::SmallSet nonConfigurable; + MutableHandle tmpPropNameStorage{runtime}; // 16. For each element key of targetKeys, do auto marker2 = runtime->getTopGCScope()->createMarker(); for (uint32_t i = 0, len = JSArray::getLength(*targetKeys); i < len; ++i) { // a. Let desc be ? target.[[GetOwnProperty]](key). ComputedPropertyDescriptor desc; CallResult descRes = JSObject::getOwnComputedDescriptor( - target, runtime, runtime->makeHandle(targetKeys->at(runtime, i)), desc); + target, + runtime, + runtime->makeHandle(targetKeys->at(runtime, i)), + tmpPropNameStorage, + desc); if (descRes == ExecutionStatus::EXCEPTION) { return ExecutionStatus::EXCEPTION; } diff --git a/test/hermes/arguments-proxy.js b/test/hermes/arguments-proxy.js new file mode 100644 index 00000000000..f6a5d85c5d2 --- /dev/null +++ b/test/hermes/arguments-proxy.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// RUN: %hermes -Xes6-proxy %s | %FileCheck --match-full-lines %s + +// Put a proxy in the prototype chain of the arguments array +({}).__proto__.__proto__ = new Proxy({},{}); + +function innerFunc() { + // Trigger getArgumentsPropByValSlowPath_RJS. + print(arguments[1]); +} + +innerFunc(4, 2); +// CHECK: 2 diff --git a/unittests/VMRuntime/ArrayTest.cpp b/unittests/VMRuntime/ArrayTest.cpp index cff7136dcc5..97f8e6718d7 100644 --- a/unittests/VMRuntime/ArrayTest.cpp +++ b/unittests/VMRuntime/ArrayTest.cpp @@ -32,31 +32,40 @@ TEST_F(ArrayTest, CppAPITest) { // Call haveOwnIndexed() and getOwnIndexed() on a element not in the array. ComputedPropertyDescriptor desc; + MutableHandle tmpSymbolStorage{runtime}; ASSERT_FALSE(*array->getOwnComputedPrimitiveDescriptor( array, runtime, runtime->makeHandle(100.0_hd), JSObject::IgnoreProxy::No, + tmpSymbolStorage, desc)); EXPECT_CALLRESULT_UNDEFINED( array->getComputed_RJS(array, runtime, runtime->makeHandle(100.0_hd))); // Obtain the value a couple of different ways and check its value. -#define EXPECT_INDEX_VALUE(value, array, index) \ - EXPECT_EQ(value, array->at(runtime, index)); \ - ASSERT_TRUE(*array->getOwnComputedDescriptor( \ - array, \ - runtime, \ - runtime->makeHandle(HermesValue::encodeDoubleValue(index)), \ - desc)); \ - EXPECT_CALLRESULT_VALUE( \ - value, \ - JSArray::getComputedPropertyValue_RJS(array, runtime, array, desc)); \ - EXPECT_CALLRESULT_VALUE( \ - value, \ - array->getComputed_RJS( \ - array, \ - runtime, \ +#define EXPECT_INDEX_VALUE(value, array, index) \ + EXPECT_EQ(value, array->at(runtime, index)); \ + ASSERT_TRUE(*array->getOwnComputedDescriptor( \ + array, \ + runtime, \ + runtime->makeHandle(HermesValue::encodeDoubleValue(index)), \ + tmpSymbolStorage, \ + desc)); \ + EXPECT_CALLRESULT_VALUE( \ + value, \ + JSArray::getComputedPropertyValue_RJS( \ + array, \ + runtime, \ + array, \ + tmpSymbolStorage, \ + desc, \ + runtime->makeHandle(HermesValue::encodeDoubleValue(index)))); \ + EXPECT_CALLRESULT_VALUE( \ + value, \ + array->getComputed_RJS( \ + array, \ + runtime, \ runtime->makeHandle(HermesValue::encodeDoubleValue(index)))); // array[100] = 50. This will case a reallocation. @@ -106,6 +115,7 @@ TEST_F(ArrayTest, CppAPITest) { runtime, runtime->makeHandle(106.0_hd), JSObject::IgnoreProxy::No, + tmpSymbolStorage, desc)); EXPECT_CALLRESULT_UNDEFINED( array->getComputed_RJS(array, runtime, runtime->makeHandle(106.0_hd))); @@ -121,6 +131,7 @@ TEST_F(ArrayTest, CppAPITest) { runtime, runtime->makeHandle(106.0_hd), JSObject::IgnoreProxy::No, + tmpSymbolStorage, desc)); EXPECT_CALLRESULT_UNDEFINED( array->getComputed_RJS(array, runtime, runtime->makeHandle(106.0_hd))); diff --git a/unittests/VMRuntime/ObjectModelTest.cpp b/unittests/VMRuntime/ObjectModelTest.cpp index 90e6c1589e9..7f85598a06c 100644 --- a/unittests/VMRuntime/ObjectModelTest.cpp +++ b/unittests/VMRuntime/ObjectModelTest.cpp @@ -617,20 +617,23 @@ TEST_F(ObjectModelTest, NonArrayComputedTest) { // descriptors. ComputedPropertyDescriptor cdesc; MutableHandle propObjHandle{runtime}; + MutableHandle tmpPropNameStorage{runtime}; JSObject::getComputedPrimitiveDescriptor( - obj1, runtime, index5, propObjHandle, cdesc); + obj1, runtime, index5, propObjHandle, tmpPropNameStorage, cdesc); ASSERT_TRUE(propObjHandle); ASSERT_FALSE(cdesc.flags.indexed); ASSERT_EQ( value10.get(), - JSObject::getComputedSlotValue(obj1.get(), runtime, cdesc)); + JSObject::getComputedSlotValue(obj1, runtime, tmpPropNameStorage, cdesc) + ->get()); JSObject::getComputedPrimitiveDescriptor( - obj1, runtime, prop1Name, propObjHandle, cdesc); + obj1, runtime, prop1Name, propObjHandle, tmpPropNameStorage, cdesc); ASSERT_TRUE(propObjHandle); ASSERT_FALSE(cdesc.flags.indexed); ASSERT_EQ( value11.get(), - JSObject::getComputedSlotValue(obj1.get(), runtime, cdesc)); + JSObject::getComputedSlotValue(obj1, runtime, tmpPropNameStorage, cdesc) + ->get()); // Use getComputed() to obtain the values. EXPECT_CALLRESULT_VALUE( @@ -649,10 +652,10 @@ TEST_F(ObjectModelTest, NonArrayComputedTest) { // Try to get missing properties. JSObject::getComputedPrimitiveDescriptor( - obj1, runtime, index6, propObjHandle, cdesc); + obj1, runtime, index6, propObjHandle, tmpPropNameStorage, cdesc); ASSERT_FALSE(propObjHandle); JSObject::getComputedPrimitiveDescriptor( - obj1, runtime, prop2Name, propObjHandle, cdesc); + obj1, runtime, prop2Name, propObjHandle, tmpPropNameStorage, cdesc); ASSERT_FALSE(propObjHandle); // Delete a missing property. @@ -662,11 +665,11 @@ TEST_F(ObjectModelTest, NonArrayComputedTest) { // Delete existing properties. ASSERT_TRUE(*JSObject::deleteComputed(obj1, runtime, index5)); JSObject::getComputedPrimitiveDescriptor( - obj1, runtime, index5, propObjHandle, cdesc); + obj1, runtime, index5, propObjHandle, tmpPropNameStorage, cdesc); ASSERT_FALSE(propObjHandle); ASSERT_TRUE(*JSObject::deleteComputed(obj1, runtime, prop1Name)); JSObject::getComputedPrimitiveDescriptor( - obj1, runtime, prop1Name, propObjHandle, cdesc); + obj1, runtime, prop1Name, propObjHandle, tmpPropNameStorage, cdesc); ASSERT_FALSE(propObjHandle); }