博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Chakra TypedArray代码实现笔记
阅读量:5047 次
发布时间:2019-06-12

本文共 44114 字,大约阅读时间需要 147 分钟。

ArrayBuffer.cpp阅读

对象继承关系

JavascriptArrayBuffer:ArrayBuffer:ArrayBufferBase:DynamicObject:RecyclableObject:FinalizableObject
template<> TypedArray
TypedArrayTypedArrayBaseArrayBufferParentArrayObjectDynamicObjectRecyclableObjectFinalizableObject

FinalizableObject类

抽象类FinalizableObject,所有Object类的基类

class FinalizableObject{public:    virtual void Finalize(bool isShutdown) = 0;    virtual void Dispose(bool isShutdown) = 0;    virtual void Mark(Recycler * recycler) = 0;    virtual void OnMark() {}};

RecyclableObject类

//TO DO

RecyclableObject类涉及到内存管理相关的操作

class RecyclableObject : public FinalizableObject    {                friend class JavascriptOperators;    protected:        Field(Type *) type;        DEFINE_VTABLE_CTOR_NOBASE(RecyclableObject);        virtual RecyclableObject* GetPrototypeSpecial();    public:        static bool Is(Var aValue);//static方法,传入地址判断是否为RecyclableObject对象        static RecyclableObject* FromVar(Var varValue);//static方法,传入地址返回对象        RecyclableObject(Type * type);//构造函数        ScriptContext* GetScriptContext() const;//返回ScriptContext        TypeId GetTypeId() const;//返回TypeId        RecyclableObject* GetPrototype() const;//return prototype;        JavascriptMethod GetEntryPoint() const;//return entryPoint;        JavascriptLibrary* GetLibrary() const;// return javascriptLibrary;        Recycler* GetRecycler() const;// return recycler;        void SetIsPrototype();        // Is this object known to have only writable data properties        // (i.e. no accessors or non-writable properties)?        bool HasOnlyWritableDataProperties();//查询访问属性        void ClearWritableDataOnlyDetectionBit();//删除只读属性  propertyTypes &= ~PropertyTypesWritableDataOnlyDetection;        bool IsWritableDataOnlyDetectionBitSet();        inline Type * GetType() const { return type; }        // In order to avoid a branch, every object has an entry point if it gets called like a        // function - however, if it can't be called like a function, it's set to DefaultEntryPoint        // which will emit an error.        static Var DefaultEntryPoint(RecyclableObject* function, CallInfo callInfo, ...);        BOOL HasItem(uint32 index);        BOOL HasProperty(PropertyId propertyId);        BOOL GetProperty(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);        BOOL GetProperty(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);        BOOL GetPropertyReference(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);        BOOL GetItem(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext);        BOOL GetItemReference(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext);        virtual PropertyId GetPropertyId(PropertyIndex index) { return Constants::NoProperty; }        virtual PropertyId GetPropertyId(BigPropertyIndex index) { return Constants::NoProperty; }        virtual PropertyIndex GetPropertyIndex(PropertyId propertyId) { return Constants::NoSlot; }        virtual int GetPropertyCount() { return 0; }        virtual PropertyQueryFlags HasPropertyQuery(PropertyId propertyId);        virtual BOOL HasOwnProperty( PropertyId propertyId);        virtual BOOL HasOwnPropertyNoHostObject( PropertyId propertyId);        virtual BOOL HasOwnPropertyCheckNoRedecl( PropertyId propertyId) { Assert(FALSE); return FALSE; }        virtual BOOL UseDynamicObjectForNoHostObjectAccess() { return FALSE; }        virtual DescriptorFlags GetSetter(PropertyId propertyId, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext) { return None; }        virtual DescriptorFlags GetSetter(JavascriptString* propertyNameString, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext) { return None; }        virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);        virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);        virtual BOOL GetInternalProperty(Var instance, PropertyId internalPropertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);        virtual BOOL GetAccessors(PropertyId propertyId, Var* getter, Var* setter, ScriptContext * requestContext);        virtual PropertyQueryFlags GetPropertyReferenceQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);        virtual BOOL SetProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info);        virtual BOOL SetProperty(JavascriptString* propertyNameString, Var value, PropertyOperationFlags flags, PropertyValueInfo* info);        virtual BOOL SetInternalProperty(PropertyId internalPropertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info);        virtual BOOL InitProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags = PropertyOperation_None, PropertyValueInfo* info = NULL);        virtual BOOL EnsureProperty(PropertyId propertyId);        virtual BOOL EnsureNoRedeclProperty(PropertyId propertyId);        virtual BOOL SetPropertyWithAttributes(PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any);        virtual BOOL InitPropertyScoped(PropertyId propertyId, Var value);        virtual BOOL InitFuncScoped(PropertyId propertyId, Var value);        virtual BOOL DeleteProperty(PropertyId propertyId, PropertyOperationFlags flags);        virtual BOOL DeleteProperty(JavascriptString *propertyNameString, PropertyOperationFlags flags);        virtual BOOL IsFixedProperty(PropertyId propertyId);        virtual PropertyQueryFlags HasItemQuery(uint32 index);        virtual BOOL HasOwnItem(uint32 index);        virtual PropertyQueryFlags GetItemQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext);        virtual PropertyQueryFlags GetItemReferenceQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext);        virtual DescriptorFlags GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext) { return None; }        virtual BOOL SetItem(uint32 index, Var value, PropertyOperationFlags flags);        virtual BOOL DeleteItem(uint32 index, PropertyOperationFlags flags);        virtual BOOL GetEnumerator(JavascriptStaticEnumerator * enumerator, EnumeratorFlags flags, ScriptContext* requestContext, ForInCache * forInCache = nullptr);        virtual BOOL ToPrimitive(JavascriptHint hint, Var* value, ScriptContext * requestContext);        virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags = PropertyOperation_None);        virtual BOOL Equals(__in Var other, __out BOOL* value, ScriptContext* requestContext);        virtual BOOL StrictEquals(__in Var other, __out BOOL* value, ScriptContext* requestContext);        virtual BOOL IsWritable(PropertyId propertyId) { return false; }        virtual BOOL IsConfigurable(PropertyId propertyId) { return false; }        virtual BOOL IsEnumerable(PropertyId propertyId) { return false; }        virtual BOOL IsExtensible() { return false; }        virtual BOOL IsProtoImmutable() const { return false; }        virtual BOOL PreventExtensions() { return false; };     // Sets [[Extensible]] flag of instance to false        virtual void ThrowIfCannotDefineProperty(PropertyId propId, const PropertyDescriptor& descriptor);        virtual void ThrowIfCannotGetOwnPropertyDescriptor(PropertyId propId) {}        virtual BOOL GetDefaultPropertyDescriptor(PropertyDescriptor& descriptor);        virtual BOOL Seal() { return false; }                   // Seals the instance, no additional property can be added or deleted        virtual BOOL Freeze() { return false; }                 // Freezes the instance, no additional property can be added or deleted or written        virtual BOOL IsSealed() { return false; }        virtual BOOL IsFrozen() { return false; }        virtual BOOL SetWritable(PropertyId propertyId, BOOL value) { return false; }        virtual BOOL SetConfigurable(PropertyId propertyId, BOOL value) { return false; }        virtual BOOL SetEnumerable(PropertyId propertyId, BOOL value) { return false; }        virtual BOOL SetAttributes(PropertyId propertyId, PropertyAttributes attributes) { return false; }        virtual BOOL GetSpecialPropertyName(uint32 index, JavascriptString ** propertyName, ScriptContext * requestContext) { return false; }        virtual uint GetSpecialPropertyCount() const { return 0; }        virtual PropertyId const * GetSpecialPropertyIds() const { return nullptr; }        virtual RecyclableObject* GetThisObjectOrUnWrap(); // Due to the withScope object there are times we need to unwrap        virtual BOOL HasInstance(Var instance, ScriptContext* scriptContext, IsInstInlineCache* inlineCache = NULL);        BOOL SkipsPrototype() const;        BOOL CanHaveInterceptors() const;        BOOL IsExternal() const;        // Used only in JsVarToExtension where it may be during dispose and the type is not available        virtual BOOL IsExternalVirtual() const { return FALSE; }        virtual RecyclableObject* GetConfigurablePrototype(ScriptContext * requestContext) { return GetPrototype(); }        virtual Js::JavascriptString* GetClassName(ScriptContext * requestContext);        virtual RecyclableObject* GetProxiedObjectForHeapEnum();        virtual void RemoveFromPrototype(ScriptContext * requestContext) { AssertMsg(false, "Shouldn't call this implementation."); }        virtual void AddToPrototype(ScriptContext * requestContext) { AssertMsg(false, "Shouldn't call this implementation."); }        virtual void SetPrototype(RecyclableObject* newPrototype) { AssertMsg(false, "Shouldn't call this implementation."); }        virtual BOOL ToString(Js::Var* value, Js::ScriptContext* scriptContext) { AssertMsg(FALSE, "Do not use this function."); return false; }        // don't need cross-site: in HostDispatch it's IDispatchEx based; in CustomExternalObject we have marshalling code explicitly.        virtual Var GetNamespaceParent(Js::Var aChild) { return nullptr; }        virtual HRESULT QueryObjectInterface(REFIID riid, void **ppvObj);        virtual BOOL GetDiagValueString(StringBuilder
* stringBuilder, ScriptContext* requestContext); virtual BOOL GetDiagTypeString(StringBuilder
* stringBuilder, ScriptContext* requestContext); virtual RecyclableObject* ToObject(ScriptContext * requestContext); virtual Var GetTypeOfString(ScriptContext* requestContext); // don't need cross-site: only supported in HostDispatch. virtual Var InvokePut(Arguments args); virtual BOOL GetRemoteTypeId(TypeId* typeId); // Only implemented by the HostDispatch object for cross-thread support // Only supports a subset of entry points to be called remotely. // For a list of supported entry points see the BuiltInOperation enum defined in JscriptInfo.idl virtual BOOL InvokeBuiltInOperationRemotely(JavascriptMethod entryPoint, Arguments args, Var* result) { return FALSE; }; // don't need cross-site: only supported in HostDispatch. virtual DynamicObject* GetRemoteObject(); // don't need cross-site: get the HostDispatch for global object/module root. don't need marshalling. virtual Var GetHostDispatchVar(); virtual RecyclableObject * CloneToScriptContext(ScriptContext* requestContext); // If dtor is called, that means that OOM happened (mostly), then the vtable might not be initialized // to the base class', so we can't assert. virtual void Finalize(bool isShutdown) override { } virtual void Dispose(bool isShutdown) override { } virtual void Mark(Recycler *recycler) override { AssertMsg(false, "Mark called on object that isn't TrackableObject"); } static uint32 GetOffsetOfType() { return offsetof(RecyclableObject, type); } virtual void InvalidateCachedScope() { return; } virtual BOOL HasDeferredTypeHandler() const { return false; } private: bool dtorCalled;#endif friend class LowererMD; friend class LowererMDArch; friend struct InlineCache; private: UINT m_heapEnumValidationCookie; public: void SetHeapEnumValidationCookie(int cookie ) { m_heapEnumValidationCookie = cookie; } int GetHeapEnumValidationCookie() { return m_heapEnumValidationCookie; }#endif };

ArrayBufferBase类

ArrayBufferBase类包含一系列关于ArrayBuffer的重要操作,但是这是个抽象类,方法并未实现。

GetByteLength //获取buffer size
GetBuffer //获取buffer地址
IsArrayBuffer //判断类型
IsSharedArrayBuffer //判断类型

比较重要的是提供了static方法AllocWrapper,负责分配VirtualBuffer内存

class ArrayBufferBase : public DynamicObject    {    protected:        #define MAX_ASMJS_ARRAYBUFFER_LENGTH 0x100000000 // 4GB               //这个static函数会以函数指针作为参数传递,与malloc做选择        template
static void* __cdecl AllocWrapper(DECLSPEC_GUARD_OVERFLOW size_t length); //VirtualFree static void FreeMemAlloc(Var ptr); public: virtual void MarshalToScriptContext(Js::ScriptContext * scriptContext) = 0;//pure virtual //构造函数,设置isDetached=0 ArrayBufferBase(DynamicType *type) : DynamicObject(type), isDetached(false) { } bool IsDetached() { return isDetached; } virtual bool IsArrayBuffer() = 0;//pure virtual virtual bool IsSharedArrayBuffer() = 0;//pure virtual virtual bool IsWebAssemblyArrayBuffer() { return false; } virtual ArrayBuffer * GetAsArrayBuffer() = 0;//pure virtual virtual SharedArrayBuffer * GetAsSharedArrayBuffer() { return nullptr; } virtual void AddParent(ArrayBufferParent* parent) { }//not defined virtual uint32 GetByteLength() const = 0;//pure virtual virtual BYTE* GetBuffer() const = 0;//pure virtual virtual bool IsValidVirtualBufferLength(uint length) const { return false; };//说明Base类是基类,不可直接使用 //通用的static接口 static bool Is(Var value);//static 判断类型 static ArrayBufferBase* FromVar(Var value);//static 类型转换 // #define offsetof(s,m) ((size_t)&reinterpret_cast
((((s*)0)->m))) static int GetIsDetachedOffset() { return offsetof(ArrayBufferBase, isDetached); } protected: Field(bool) isDetached; };

ArrayBufferBase内存结构,此对象只有一个isDetached成员

Js::ArrayBufferBase{    Js::DynamicObject    isDetached bool}

ArrayBuffer类

ArrayBuffer类是直接对应于javascript中ArrayBuffer对象

ArrayBuffer方法ArrayBuffer.isView(arg)    如果参数是ArrayBuffer的视图实例就返回true,例如 typed array objects 或 DataView。否则返回false。ArrayBuffer.transfer(oldBuffer [, newByteLength])    返回一个新的ArrayBuffer,其内容取自oldBuffer的数据,并且根据 newByteLength 的大小来对数据进行截取或者以0扩展。ArrayBuffer.prototype.slice()    返回一个新的 ArrayBuffer ,它的内容是这个 ArrayBuffer 的字节副本,从begin(包括),到end(不包括)。如果begin或end是负数,则指的是从数组末尾开始的索引,而不是从头开始。ArrayBuffer.slice()    和 ArrayBuffer.prototype.slice()功能一样    ArrayBuffer属性    ArrayBuffer.length    ArrayBuffer构造函数的length属性,它的值是1ArrayBuffer.prototype.constructor    指定函数,它创建一个对象的原型。其初始值是标准ArrayBuffer内置构造函数。ArrayBuffer.prototype.byteLength 只读    数组的字节大小。在数组创建时确定,并且不可变更。只读
内存结构可以看到对于ArrayBuffer来说,重要的结构在ArrayBuffer对象中都已给出Js::ArrayBuffer{    Js::ArrayBufferBase Js::ArrayBufferBase    primaryParent   Recycler*    otherParents    OtherParents*    buffer          byte*    bufferLength    uint32}
class ArrayBuffer : public ArrayBufferBase    {    public:        // we need to install cross-site thunk on the nested array buffer when marshaling        // typed array.        DEFINE_VTABLE_CTOR_ABSTRACT(ArrayBuffer, ArrayBufferBase);    private:        void DetachBufferFromParent(ArrayBufferParent* parent);    public:            template 
class ArrayBufferDetachedState : public ArrayBufferDetachedStateBase { public: FreeFN* freeFunction; ArrayBufferDetachedState(BYTE* buffer, uint32 bufferLength, FreeFN* freeFunction, ArrayBufferAllocationType allocationType) : ArrayBufferDetachedStateBase(TypeIds_ArrayBuffer, buffer, bufferLength, allocationType), freeFunction(freeFunction) {} virtual void ClearSelfOnly() override { HeapDelete(this); } virtual void DiscardState() override { if (this->buffer != nullptr) { freeFunction(this->buffer); this->buffer = nullptr; } this->bufferLength = 0; } virtual void Discard() override { ClearSelfOnly(); } }; class EntryInfo { public: static FunctionInfo NewInstance; static FunctionInfo Slice; static FunctionInfo IsView; static FunctionInfo GetterByteLength; static FunctionInfo GetterSymbolSpecies; static FunctionInfo Transfer; }; //newArr = scriptContext->GetLibrary()->CreateArrayBuffer(byteLength); static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...); //ArrayBuffer.prototype.slice() static Var EntrySlice(RecyclableObject* function, CallInfo callInfo, ...); //ArrayBuffer.isView() //https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/isView static Var EntryIsView(RecyclableObject* function, CallInfo callInfo, ...); //ArrayBuffer.prototype.byteLength //https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/byteLength static Var EntryGetterByteLength(RecyclableObject* function, CallInfo callInfo, ...); static Var EntryGetterSymbolSpecies(RecyclableObject* function, CallInfo callInfo, ...); //ArrayBuffer.transfer() //https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/transfer static Var EntryTransfer(RecyclableObject* function, CallInfo callInfo, ...); //判定类型 static bool Is(Var aValue); // static ArrayBuffer* NewFromDetachedState(DetachedStateBase* state, JavascriptLibrary *library); //类型转换 static ArrayBuffer* FromVar(Var aValue); //Detach virtual ArrayBufferDetachedStateBase* DetachAndGetState(); virtual uint32 GetByteLength() const override { return bufferLength; } virtual BYTE* GetBuffer() const override { return buffer; } static int GetByteLengthOffset() { return offsetof(ArrayBuffer, bufferLength); }//ArrayBuffer中bufferLength的offset static int GetBufferOffset() { return offsetof(ArrayBuffer, buffer); }//ArrayBuffer中buffer的offset //设定parent virtual void AddParent(ArrayBufferParent* parent) override; //maximum 2G -1 for amd64 static const uint32 MaxArrayBufferLength = 0x7FFFFFFF; static const uint32 ParentsCleanupThreshold = 1000; virtual bool IsValidAsmJsBufferLength(uint length, bool forceCheck = false) { return false; } virtual bool IsArrayBuffer() override { return true; } virtual bool IsSharedArrayBuffer() override { return false; } virtual ArrayBuffer * GetAsArrayBuffer() override { return ArrayBuffer::FromVar(this); } static uint32 ToIndex(Var value, int32 errorCode, ScriptContext *scriptContext, uint32 MaxAllowedLength, bool checkSameValueZero = true); virtual ArrayBuffer * TransferInternal(DECLSPEC_GUARD_OVERFLOW uint32 newBufferLength) = 0; protected: typedef void __cdecl FreeFn(void* ptr); virtual ArrayBufferDetachedStateBase* CreateDetachedState(BYTE* buffer, DECLSPEC_GUARD_OVERFLOW uint32 bufferLength) = 0; static uint32 GetIndexFromVar(Js::Var arg, uint32 length, ScriptContext* scriptContext); //In most cases, the ArrayBuffer will only have one parent Field(RecyclerWeakReference
*) primaryParent; struct OtherParents :public SList
*, Recycler> { OtherParents(Recycler* recycler) :SList
*, Recycler>(recycler), increasedCount(0) { } Field(uint) increasedCount; }; Field(OtherParents*) otherParents; FieldNoBarrier(BYTE*) buffer; // Points to a heap allocated RGBA buffer, can be null Field(uint32) bufferLength; // Number of bytes allocated };

TypedArrayBase

对于TypedArray的常见操作都已经给出,但是是纯虚函数

class TypedArrayBase : public ArrayBufferParent    {        friend ArrayBuffer;        friend ArrayBufferBase;    public:        static Var GetDefaultConstructor(Var object, ScriptContext* scriptContext);        class EntryInfo        {        public:            static FunctionInfo NewInstance;            static FunctionInfo Set;            static FunctionInfo Subarray;            static FunctionInfo From;            static FunctionInfo Of;            static FunctionInfo CopyWithin;            static FunctionInfo Entries;            static FunctionInfo Every;            static FunctionInfo Fill;            static FunctionInfo Filter;            static FunctionInfo Find;            static FunctionInfo FindIndex;            static FunctionInfo ForEach;            static FunctionInfo IndexOf;            static FunctionInfo Includes;            static FunctionInfo Join;            static FunctionInfo Keys;            static FunctionInfo LastIndexOf;            static FunctionInfo Map;            static FunctionInfo Reduce;            static FunctionInfo ReduceRight;            static FunctionInfo Reverse;            static FunctionInfo Slice;            static FunctionInfo Some;            static FunctionInfo Sort;            static FunctionInfo Values;            static FunctionInfo GetterBuffer;            static FunctionInfo GetterByteLength;            static FunctionInfo GetterByteOffset;            static FunctionInfo GetterLength;            static FunctionInfo GetterSymbolToStringTag;            static FunctionInfo GetterSymbolSpecies;        };        TypedArrayBase(ArrayBufferBase* arrayBuffer, uint byteOffset, uint mappedLength, uint elementSize, DynamicType* type);                //创建函数        static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntrySet(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntrySubarray(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryFrom(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryOf(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryCopyWithin(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryEntries(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryEvery(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryFill(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryFilter(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryFind(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryFindIndex(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryForEach(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryIndexOf(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryIncludes(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryJoin(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryKeys(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryLastIndexOf(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryMap(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryReduce(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryReduceRight(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryReverse(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntrySlice(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntrySome(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntrySort(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryValues(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryGetterBuffer(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryGetterByteLength(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryGetterByteOffset(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryGetterLength(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryGetterSymbolToStringTag(RecyclableObject* function, CallInfo callInfo, ...);        static Var EntryGetterSymbolSpecies(RecyclableObject* function, CallInfo callInfo, ...);        virtual DescriptorFlags GetSetter(PropertyId propertyId, Var *setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;        virtual DescriptorFlags GetSetter(JavascriptString* propertyNameString, Var *setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;        virtual DescriptorFlags GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext) override;        virtual PropertyQueryFlags HasPropertyQuery(Js::PropertyId propertyId) override;        virtual BOOL HasOwnProperty(Js::PropertyId propertyId) override;        virtual PropertyQueryFlags GetPropertyQuery(Js::Var originalInstance, Js::PropertyId propertyId, Js::Var* value, Js::PropertyValueInfo* info, Js::ScriptContext* requestContext) override;        virtual PropertyQueryFlags GetPropertyQuery(Js::Var originalInstance, Js::JavascriptString* propertyNameString, Js::Var* value, Js::PropertyValueInfo* info, Js::ScriptContext* requestContext) override;        virtual PropertyQueryFlags GetPropertyReferenceQuery(Js::Var originalInstance, Js::PropertyId propertyId, Js::Var* value, Js::PropertyValueInfo* info, Js::ScriptContext* requestContext) override;        virtual PropertyQueryFlags HasItemQuery(uint32 index) override;        virtual BOOL DeleteItem(uint32 index, Js::PropertyOperationFlags flags) override { return false; }        virtual PropertyQueryFlags GetItemQuery(Js::Var originalInstance, uint32 index, Js::Var* value, Js::ScriptContext * requestContext) override;        virtual BOOL SetItem(uint32 index, Js::Var value, Js::PropertyOperationFlags flags = PropertyOperation_None) override;        virtual BOOL SetProperty(Js::PropertyId propertyId, Js::Var value, Js::PropertyOperationFlags flags, Js::PropertyValueInfo* info) override;        virtual BOOL SetProperty(Js::JavascriptString* propertyNameString, Js::Var value, Js::PropertyOperationFlags flags, Js::PropertyValueInfo* info) override;        virtual BOOL DeleteProperty(Js::PropertyId propertyId, Js::PropertyOperationFlags flags) override;        virtual BOOL DeleteProperty(JavascriptString *propertyNameString, Js::PropertyOperationFlags flags) override;        virtual PropertyQueryFlags GetItemReferenceQuery(Js::Var originalInstance, uint32 index, Js::Var* value, Js::ScriptContext * requestContext) override;        virtual BOOL GetEnumerator(JavascriptStaticEnumerator * enumerator, EnumeratorFlags flags, ScriptContext* requestContext, ForInCache * forInCache = nullptr) override;        virtual JavascriptEnumerator * GetIndexEnumerator(EnumeratorFlags flags, ScriptContext * requestContext) override;        virtual BOOL IsEnumerable(PropertyId propertyId)  override;        virtual BOOL IsConfigurable(PropertyId propertyId)  override;        virtual BOOL IsWritable(PropertyId propertyId)  override;        virtual BOOL SetEnumerable(PropertyId propertyId, BOOL value) override;        virtual BOOL SetWritable(PropertyId propertyId, BOOL value) override;        virtual BOOL SetConfigurable(PropertyId propertyId, BOOL value) override;        virtual BOOL SetAttributes(PropertyId propertyId, PropertyAttributes attributes) override;        virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags) override;        virtual BOOL InitProperty(Js::PropertyId propertyId, Js::Var value, PropertyOperationFlags flags = PropertyOperation_None, Js::PropertyValueInfo* info = NULL) override;        virtual BOOL SetPropertyWithAttributes(PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any) override;        static BOOL Is(Var aValue);        static BOOL Is(TypeId typeId);        static TypedArrayBase* FromVar(Var aValue);        // Returns false if this is not a TypedArray or it's not detached        static BOOL IsDetachedTypedArray(Var aValue);        static HRESULT GetBuffer(Var aValue, ArrayBuffer** outBuffer, uint32* outOffset, uint32* outLength);        static TypedArrayBase * ValidateTypedArray(Var aValue, ScriptContext *scriptContext, LPCWSTR apiName);        static TypedArrayBase * ValidateTypedArray(Arguments &args, ScriptContext *scriptContext, LPCWSTR apiName);        static Var TypedArrayCreate(Var constructor, Arguments *args, uint32 length, ScriptContext *scriptContext);        //写入操作 pure virtual        virtual BOOL DirectSetItem(__in uint32 index, __in Js::Var value) = 0;        virtual BOOL DirectSetItemNoSet(__in uint32 index, __in Js::Var value) = 0;        virtual Var  DirectGetItem(__in uint32 index) = 0;        virtual BOOL DirectSetItemNoDetachCheck(__in uint32 index, __in Js::Var value) = 0;        virtual Var  DirectGetItemNoDetachCheck(__in uint32 index) = 0;        virtual Var TypedAdd(__in uint32 index, Var second) = 0;        virtual Var TypedAnd(__in uint32 index, Var second) = 0;        virtual Var TypedLoad(__in uint32 index) = 0;        virtual Var TypedOr(__in uint32 index, Var second) = 0;        virtual Var TypedStore(__in uint32 index, Var second) = 0;        virtual Var TypedSub(__in uint32 index, Var second) = 0;        virtual Var TypedXor(__in uint32 index, Var second) = 0;        virtual Var TypedExchange(__in uint32 index, Var second) = 0;        virtual Var TypedCompareExchange(__in uint32 index, Var comparand, Var replacementValue) = 0;                //TypedArray.prototype.byteLength        uint32 GetByteLength() const { return length * BYTES_PER_ELEMENT; }        //TypedArray.prototype.byteOffset        uint32 GetByteOffset() const { return byteOffset; }        uint32 GetBytesPerElement() const { return BYTES_PER_ELEMENT; }        //TypedArray.prototype.buffer        byte*  GetByteBuffer() const { return buffer; };                bool IsDetachedBuffer() const { return this->GetArrayBuffer()->IsDetached(); }        void ClearLengthAndBufferOnDetach();        static Var CommonSet(Arguments& args);        static Var CommonSubarray(Arguments& args);        void SetObject(RecyclableObject* arraySource, uint32 targetLength, uint32 offset = 0);        void SetObjectNoDetachCheck(RecyclableObject* arraySource, uint32 targetLength, uint32 offset = 0);        void Set(TypedArrayBase* typedArraySource, uint32 offset = 0);        virtual BOOL GetDiagValueString(StringBuilder
* stringBuilder, ScriptContext* requestContext) override; virtual BOOL GetDiagTypeString(StringBuilder
* stringBuilder, ScriptContext* requestContext) override; static bool TryGetLengthForOptimizedTypedArray(const Var var, uint32 *const lengthRef, TypeId *const typeIdRef); BOOL ValidateIndexAndDirectSetItem(__in Js::Var index, __in Js::Var value, __out bool * isNumericIndex); uint32 ValidateAndReturnIndex(__in Js::Var index, __out bool * skipOperation, __out bool * isNumericIndex); // objectArray support virtual BOOL SetItemWithAttributes(uint32 index, Var value, PropertyAttributes attributes) override; Var FindMinOrMax(Js::ScriptContext * scriptContext, TypeId typeId, bool findMax); template
Var FindMinOrMax(Js::ScriptContext * scriptContext, bool findMax); static Var GetKeysEntriesValuesHelper(Arguments& args, ScriptContext *scriptContext, LPCWSTR apiName, JavascriptArrayIteratorKind kind); static uint32 GetFromIndex(Var arg, uint32 length, ScriptContext *scriptContext); private: uint32 GetSourceLength(RecyclableObject* arraySource, uint32 targetLength, uint32 offset); protected: static Var CreateNewInstanceFromIterator(RecyclableObject *iterator, ScriptContext *scriptContext, uint32 elementSize, PFNCreateTypedArray pfnCreateTypedArray); static Var CreateNewInstance(Arguments& args, ScriptContext* scriptContext, uint32 elementSize, PFNCreateTypedArray pfnCreateTypedArray ); static bool ArrayIteratorPrototypeHasUserDefinedNext(ScriptContext *scriptContext); static BOOL CanonicalNumericIndexString(PropertyId propertyId, ScriptContext *scriptContext); static BOOL CanonicalNumericIndexString(JavascriptString *propertyString, ScriptContext *scriptContext); typedef int(__cdecl* CompareElementsFunction)(void*, const void*, const void*); virtual CompareElementsFunction GetCompareElementsFunction() = 0; virtual Var Subarray(uint32 begin, uint32 end) = 0; Field(int32) BYTES_PER_ELEMENT; Field(uint32) byteOffset; FieldNoBarrier(BYTE*) buffer; // beginning of mapped array. public: static uint32 GetOffsetOfBuffer() { return offsetof(TypedArrayBase, buffer); } static uint32 GetOffsetOfLength() { return offsetof(TypedArrayBase, length); } };

TypedArray

内存结构

Js::TypedArray{    Js::TypedArrayBase    {        Js::ArrayBufferParent        {            Js::ArrayObject            arrayBuffer         Js::JavascriptArrayBuffer*        }        BYTES_PER_ELEMENT       int        byteOffset      unsigned int        buffer          unsigned char *    }}

TypedArray类复写实现了虚函数和实际的操作方法

并不存在单独的TypedArray类型的类,都是针对模版进行的特例化

template 
class TypedArray : public TypedArrayBase { protected: DEFINE_VTABLE_CTOR(TypedArray, TypedArrayBase); virtual void MarshalToScriptContext(Js::ScriptContext * scriptContext) { Assert(this->GetScriptContext() != scriptContext); AssertMsg(VirtualTableInfo
::HasVirtualTable(this), "Derived class need to define marshal to script context"); VirtualTableInfo
>>::SetVirtualTable(this); ArrayBufferBase* arrayBuffer = this->GetArrayBuffer(); if (arrayBuffer && !arrayBuffer->IsCrossSiteObject()) { arrayBuffer->MarshalToScriptContext(scriptContext); } } TypedArray(DynamicType *type): TypedArrayBase(nullptr, 0, 0, sizeof(TypeName), type) { buffer = nullptr; } public: class EntryInfo { public: static FunctionInfo NewInstance; static FunctionInfo Set; }; TypedArray(ArrayBufferBase* arrayBuffer, uint32 byteOffset, uint32 mappedLength, DynamicType* type); static Var Create(ArrayBufferBase* arrayBuffer, uint32 byteOffSet, uint32 mappedLength, JavascriptLibrary* javascriptLibrary); static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...); static Var EntrySet(RecyclableObject* function, CallInfo callInfo, ...); Var Subarray(uint32 begin, uint32 end); static BOOL Is(Var aValue); static TypedArray
* FromVar(Var aValue); inline Var BaseTypedDirectGetItem(__in uint32 index) { if (this->IsDetachedBuffer()) // 9.4.5.8 IntegerIndexedElementGet { JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray); } if (index < GetLength()) { Assert((index + 1)* sizeof(TypeName)+GetByteOffset() <= GetArrayBuffer()->GetByteLength()); TypeName* typedBuffer = (TypeName*)buffer; return JavascriptNumber::ToVar(typedBuffer[index], GetScriptContext()); } return GetLibrary()->GetUndefined(); } inline Var TypedDirectGetItemWithCheck(__in uint32 index) { if (this->IsDetachedBuffer()) // 9.4.5.8 IntegerIndexedElementGet { JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray); } if (index < GetLength()) { Assert((index + 1)* sizeof(TypeName)+GetByteOffset() <= GetArrayBuffer()->GetByteLength()); TypeName* typedBuffer = (TypeName*)buffer; return JavascriptNumber::ToVarWithCheck(typedBuffer[index], GetScriptContext()); } return GetLibrary()->GetUndefined(); } inline Var BaseTypedDirectGetItemNoDetachCheck(__in uint32 index) { Assert(!IsDetachedBuffer()); Assert(index < GetLength()); Assert((index + 1)* sizeof(TypeName) + GetByteOffset() <= GetArrayBuffer()->GetByteLength()); TypeName* typedBuffer = (TypeName*)buffer; return JavascriptNumber::ToVar(typedBuffer[index], GetScriptContext()); } inline Var DirectGetItemVarCheckNoDetachCheck(__in uint32 index) { Assert(!IsDetachedBuffer()); Assert(index < GetLength()); Assert((index + 1)* sizeof(TypeName) + GetByteOffset() <= GetArrayBuffer()->GetByteLength()); TypeName* typedBuffer = (TypeName*)buffer; return JavascriptNumber::ToVarWithCheck(typedBuffer[index], GetScriptContext()); } inline BOOL DirectSetItemAtRange(TypedArray *fromArray, __in int32 iSrcStart, __in int32 iDstStart, __in uint32 length, TypeName(*convFunc)(Var value, ScriptContext* scriptContext)) { TypeName* dstBuffer = (TypeName*)buffer; TypeName* srcBuffer = (TypeName*)fromArray->buffer; Assert(srcBuffer && dstBuffer); Assert(length <= ArrayBuffer::MaxArrayBufferLength / sizeof(TypeName)); // caller checks that src and dst index are the same Assert(iSrcStart == iDstStart); if (this->IsDetachedBuffer() || fromArray->IsDetachedBuffer()) { JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray); } // Fixup destination start in case it's negative uint32 start = iDstStart; if (iDstStart < 0) { if ((int64)(length) + iDstStart < 0) { // nothing to do, all index are no-op return true; } length += iDstStart; start = 0; } uint32 dstLength = UInt32Math::Add(start, length) < GetLength() ? length : GetLength() > start ? GetLength() - start : 0; uint32 srcLength = start + length < fromArray->GetLength() ? length : (fromArray->GetLength() > start ? fromArray->GetLength() - start : 0); // length is the minimum of length, srcLength and dstLength length = length < srcLength ? (length < dstLength ? length : dstLength) : (srcLength < dstLength ? srcLength : dstLength); const size_t byteSize = sizeof(TypeName) * length; Assert(byteSize >= length); // check for overflow js_memcpy_s(dstBuffer + start, dstLength * sizeof(TypeName), srcBuffer + start, byteSize); if (dstLength > length) { TypeName undefinedValue = convFunc(GetLibrary()->GetUndefined(), GetScriptContext()); for (uint32 i = length; i < dstLength; i++) { dstBuffer[i] = undefinedValue; } } return true; } inline BOOL DirectSetItemAtRange(__in int32 start, __in uint32 length, __in Js::Var value, TypeName(*convFunc)(Var value, ScriptContext* scriptContext)) { if (CrossSite::IsCrossSiteObjectTyped(this)) { return false; } TypeName typedValue = convFunc(value, GetScriptContext()); if (this->IsDetachedBuffer()) // 9.4.5.9 IntegerIndexedElementSet { JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray); } uint32 newStart = start, newLength = length; if (start < 0) { if ((int64)(length) + start < 0) { // nothing to do, all index are no-op return true; } newStart = 0; // fixup the length with the change newLength += start; } if (newStart >= GetLength()) { // If we want to start copying past the length of the array, all index are no-op return true; } if (UInt32Math::Add(newStart, newLength) > GetLength()) { newLength = GetLength() - newStart; } TypeName* typedBuffer = (TypeName*)buffer; if (typedValue == 0 || sizeof(TypeName) == 1) { const size_t byteSize = sizeof(TypeName) * newLength; Assert(byteSize >= newLength); // check for overflow memset(typedBuffer + newStart, (int)typedValue, byteSize); } else { for (uint32 i = 0; i < newLength; i++) { typedBuffer[newStart + i] = typedValue; } } return TRUE; } inline BOOL BaseTypedDirectSetItem(__in uint32 index, __in Js::Var value, TypeName (*convFunc)(Var value, ScriptContext* scriptContext)) { // This call can potentially invoke user code, and may end up detaching the underlying array (this). // Therefore it was brought out and above the IsDetached check TypeName typedValue = convFunc(value, GetScriptContext()); if (this->IsDetachedBuffer()) // 9.4.5.9 IntegerIndexedElementSet { JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray); } if (index >= GetLength()) { return FALSE; } AssertMsg(index < GetLength(), "Trying to set out of bound index for typed array."); Assert((index + 1)* sizeof(TypeName) + GetByteOffset() <= GetArrayBuffer()->GetByteLength()); TypeName* typedBuffer = (TypeName*)buffer; typedBuffer[index] = typedValue; return TRUE; } inline BOOL BaseTypedDirectSetItemNoSet(__in uint32 index, __in Js::Var value, TypeName (*convFunc)(Var value, ScriptContext* scriptContext)) { // This call can potentially invoke user code, and may end up detaching the underlying array (this). // Therefore it was brought out and above the IsDetached check convFunc(value, GetScriptContext()); if (this->IsDetachedBuffer()) // 9.4.5.9 IntegerIndexedElementSet { JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_DetachedTypedArray); } return FALSE; } inline BOOL BaseTypedDirectSetItemNoDetachCheck(__in uint32 index, __in Js::Var value, TypeName(*convFunc)(Var value, ScriptContext* scriptContext)) { TypeName typedValue = convFunc(value, GetScriptContext()); // The caller of the function made sure that no IsDetached check required. // The caller of the function also made sure that no length check required. Assert(!IsDetachedBuffer()); AssertMsg(index < GetLength(), "Trying to set out of bound index for typed array."); Assert((index + 1)* sizeof(TypeName) + GetByteOffset() <= GetArrayBuffer()->GetByteLength()); TypeName* typedBuffer = (TypeName*)buffer; typedBuffer[index] = typedValue; return TRUE; } virtual BOOL DirectSetItem(__in uint32 index, __in Js::Var value) override sealed; virtual BOOL DirectSetItemNoSet(__in uint32 index, __in Js::Var value) override sealed; virtual Var DirectGetItem(__in uint32 index) override sealed; virtual BOOL DirectSetItemNoDetachCheck(__in uint32 index, __in Js::Var value) override sealed; virtual Var DirectGetItemNoDetachCheck(__in uint32 index) override sealed; virtual Var TypedAdd(__in uint32 index, Var second) override; virtual Var TypedAnd(__in uint32 index, Var second) override; virtual Var TypedLoad(__in uint32 index) override; virtual Var TypedOr(__in uint32 index, Var second) override; virtual Var TypedStore(__in uint32 index, Var second) override; virtual Var TypedSub(__in uint32 index, Var second) override; virtual Var TypedXor(__in uint32 index, Var second) override; virtual Var TypedExchange(__in uint32 index, Var second) override; virtual Var TypedCompareExchange(__in uint32 index, Var comparand, Var replacementValue) override; static BOOL DirectSetItem(__in TypedArray* arr, __in uint32 index, __in Js::Var value) { AssertMsg(arr != nullptr, "Array shouldn't be nullptr."); return arr->DirectSetItem(index, value); } protected: CompareElementsFunction GetCompareElementsFunction() { return &TypedArrayCompareElementsHelper
; } public: virtual VTableValue DummyVirtualFunctionToHinderLinkerICF(); };

转载于:https://www.cnblogs.com/Ox9A82/p/7308337.html

你可能感兴趣的文章
luogu4849 寻找宝藏 (cdq分治+dp)
查看>>
Spring Cloud微服务笔记(五)Feign
查看>>
C语言键盘按键列表
查看>>
Codeforces Round #374 (Div. 2)
查看>>
oracle数据类型
查看>>
socket
查看>>
Vue中使用key的作用
查看>>
二叉索引树 树状数组
查看>>
日志框架--(一)基础篇
查看>>
Java设计模式之原型模式
查看>>
Spring学习(四)-----Spring Bean引用同xml和不同xml bean的例子
查看>>
哲理故事与管理之道(20)-用危机激励下属
查看>>
关于源程序到可运行程序的过程
查看>>
wepy的使用
查看>>
转载:mysql数据库密码忘记找回方法
查看>>
scratch少儿编程第一季——06、人在江湖混,没有背景怎么行。
查看>>
面向对象1
查看>>
在ns2.35中添加myevalvid框架
查看>>
【贪心+DFS】D. Field expansion
查看>>
为什么要使用href=”javascript:void(0);”
查看>>