/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ECMASCRIPT_OBJECT_FACTORY_H #define ECMASCRIPT_OBJECT_FACTORY_H #include "ecmascript/base/error_type.h" #include "ecmascript/ecma_string.h" #include "ecmascript/js_function_kind.h" #include "ecmascript/js_handle.h" #include "ecmascript/js_hclass.h" #include "ecmascript/js_native_pointer.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/chunk_containers.h" #include "ecmascript/mem/heap_region_allocator.h" #include "ecmascript/mem/machine_code.h" #include "ecmascript/mem/native_area_allocator.h" #include "ecmascript/mem/space.h" #include "ecmascript/tagged_array.h" namespace panda::ecmascript { struct JSMethod; class JSObject; class JSArray; class JSAPIPlainArray; class JSSymbol; class JSFunctionBase; class JSFunction; class JSBoundFunction; class JSProxyRevocFunction; class JSAsyncAwaitStatusFunction; class JSPrimitiveRef; class GlobalEnv; class GlobalEnvConstants; class AccessorData; class JSGlobalObject; class LexicalEnv; class JSDate; class JSProxy; class JSRealm; class JSArguments; class TaggedQueue; class JSForInIterator; class JSSet; class JSMap; class JSRegExp; class JSSetIterator; class JSRegExpIterator; class JSMapIterator; class JSArrayIterator; class JSAPIPlainArrayIterator; class JSStringIterator; class JSGeneratorObject; class CompletionRecord; class GeneratorContext; class JSArrayBuffer; class JSDataView; class JSPromise; class JSPromiseReactionsFunction; class JSPromiseExecutorFunction; class JSPromiseAllResolveElementFunction; class JSPromiseAnyRejectElementFunction; class JSPromiseAllSettledElementFunction; class JSPromiseFinallyFunction; class JSPromiseValueThunkOrThrowerFunction; class PromiseReaction; class PromiseCapability; class PromiseIteratorRecord; class JSAsyncFuncObject; class JSAsyncFunction; class PromiseRecord; class JSLocale; class ResolvingFunctionsRecord; class EcmaVM; class Heap; class ConstantPool; class Program; class LayoutInfo; class JSIntlBoundFunction; class FreeObject; class JSNativePointer; class TSObjectType; class TSClassType; class TSUnionType; class TSInterfaceType; class TSTypeTable; class TSClassInstanceType; class TSFunctionType; class TSArrayType; class TSImportType; class TSObjLayoutInfo; class TSModuleTable; class TSFunctionType; class TSArrayType; class JSAPIArrayList; class JSAPIArrayListIterator; class JSAPIDeque; class JSAPIDequeIterator; class JSAPILightWeightMap; class JSAPILightWeightMapIterator; class JSAPILightWeightSet; class JSAPILightWeightSetIterator; class JSAPIQueue; class JSAPIQueueIterator; class JSAPIStack; class JSAPIStackIterator; class JSAPITreeSet; class JSAPITreeMap; class JSAPITreeSetIterator; class JSAPITreeMapIterator; class JSAPIVector; class JSAPIVectorIterator; class JSAPILinkedList; class JSAPIList; class JSAPILinkedListIterator; class JSAPIListIterator; class ModuleNamespace; class ImportEntry; class ExportEntry; class SourceTextModule; class CjsModule; class CjsRequire; class CjsExports; class ResolvedBinding; class BigInt; class CellRecord; namespace job { class MicroJobQueue; class PendingJob; } // namespace job class TransitionHandler; class PrototypeHandler; class PropertyBox; class ProtoChangeMarker; class ProtoChangeDetails; class ProfileTypeInfo; class MachineCode; class ClassInfoExtractor; enum class CompletionRecordType : uint8_t; enum class PrimitiveType : uint8_t; enum class IterationKind : uint8_t; using ErrorType = base::ErrorType; using base::ErrorType; using DeleteEntryPoint = void (*)(void *, void *); enum class RemoveSlots { YES, NO }; enum class MethodIndex : uint8_t { BUILTINS_GLOBAL_CALL_JS_BOUND_FUNCTION = 0, BUILTINS_GLOBAL_CALL_JS_PROXY, BUILTINS_OBJECT_CREATE_DATA_PROPERTY_ON_OBJECT_FUNCTIONS, BUILTINS_COLLATOR_ANONYMOUS_COLLATOR, BUILTINS_DATE_TIME_FORMAT_ANONYMOUS_DATE_TIME_FORMAT, BUILTINS_NUMBER_FORMAT_NUMBER_FORMAT_INTERNAL_FORMAT_NUMBER, BUILTINS_PROXY_INVALIDATE_PROXY_FUNCTION, BUILTINS_PROMISE_HANDLER_ASYNC_AWAIT_FULFILLED, BUILTINS_PROMISE_HANDLER_ASYNC_AWAIT_REJECTED, BUILTINS_PROMISE_HANDLER_RESOLVE_ELEMENT_FUNCTION, BUILTINS_PROMISE_HANDLER_RESOLVE, BUILTINS_PROMISE_HANDLER_REJECT, BUILTINS_PROMISE_HANDLER_EXECUTOR, BUILTINS_PROMISE_HANDLER_ANY_REJECT_ELEMENT_FUNCTION, BUILTINS_PROMISE_HANDLER_ALL_SETTLED_RESOLVE_ELEMENT_FUNCTION, BUILTINS_PROMISE_HANDLER_ALL_SETTLED_REJECT_ELEMENT_FUNCTION, BUILTINS_PROMISE_HANDLER_THEN_FINALLY_FUNCTION, BUILTINS_PROMISE_HANDLER_CATCH_FINALLY_FUNCTION, BUILTINS_PROMISE_HANDLER_VALUE_THUNK_FUNCTION, BUILTINS_PROMISE_HANDLER_THROWER_FUNCTION, METHOD_END }; class ObjectFactory { public: explicit ObjectFactory(JSThread *thread, Heap *heap, Chunk *chunk); ~ObjectFactory(); void GenerateInternalNativeMethods(); JSMethod *GetMethodByIndex(MethodIndex idx); JSMethod *NewMethodForNativeFunction(const void *func); JSMethod *NewMethodForAOTFunction(const void *func, size_t numArgs, const JSPandaFile *pf, uint32_t methodId); JSHandle NewProfileTypeInfo(uint32_t length); JSHandle NewConstantPool(uint32_t capacity); JSHandle NewProgram(); JSHandle GetJSError(const ErrorType &errorType, const char *data = nullptr); JSHandle NewJSError(const ErrorType &errorType, const JSHandle &message); JSHandle NewJSAggregateError(); JSHandle NewTransitionHandler(); JSHandle NewPrototypeHandler(); JSHandle NewEmptyJSObject(); // use for others create, prototype is Function.prototype // use for native function JSHandle NewJSFunction(const JSHandle &env, const void *nativeFunc = nullptr, FunctionKind kind = FunctionKind::NORMAL_FUNCTION); // use for method JSHandle NewJSFunction(const JSHandle &env, JSMethod *method, FunctionKind kind = FunctionKind::NORMAL_FUNCTION); JSHandle NewJSNativeErrorFunction(const JSHandle &env, const void *nativeFunc = nullptr); JSHandle NewSpecificTypedArrayFunction(const JSHandle &env, const void *nativeFunc = nullptr); JSHandle OrdinaryNewJSObjectCreate(const JSHandle &proto); JSHandle CreateNullJSObject(); JSHandle NewAotFunction(uint32_t numArgs, uintptr_t codeEntry); JSHandle NewJSBoundFunction(const JSHandle &target, const JSHandle &boundThis, const JSHandle &args); JSHandle NewJSIntlBoundFunction(MethodIndex idx, int functionLength = 1); JSHandle NewJSProxyRevocFunction(const JSHandle &proxy); JSHandle NewJSAsyncAwaitStatusFunction(MethodIndex idx); JSHandle NewJSGeneratorFunction(JSMethod *method); JSHandle NewAsyncFunction(JSMethod *method); JSHandle NewJSGeneratorObject(JSHandle generatorFunction); JSHandle NewJSAsyncFuncObject(); JSHandle NewJSPrimitiveRef(const JSHandle &function, const JSHandle &object); JSHandle NewJSPrimitiveRef(PrimitiveType type, const JSHandle &object); // get JSHClass for Ecma ClassLinker JSHandle NewGlobalEnv(JSHClass *globalEnvClass); // get JSHClass for Ecma ClassLinker JSHandle NewLexicalEnv(int numSlots); inline LexicalEnv *InlineNewLexicalEnv(int numSlots); JSHandle NewJSSymbol(); JSHandle NewPrivateSymbol(); JSHandle NewPrivateNameSymbol(const JSHandle &name); JSHandle NewWellKnownSymbol(const JSHandle &name); JSHandle NewPublicSymbol(const JSHandle &name); JSHandle NewSymbolWithTable(const JSHandle &name); JSHandle NewPrivateNameSymbolWithChar(const char *description); JSHandle NewWellKnownSymbolWithChar(const char *description); JSHandle NewPublicSymbolWithChar(const char *description); JSHandle NewSymbolWithTableWithChar(const char *description); JSHandle NewAccessorData(); JSHandle NewInternalAccessor(void *setter, void *getter); JSHandle NewPromiseCapability(); JSHandle NewPromiseReaction(); JSHandle NewPromiseRecord(); JSHandle NewResolvingFunctionsRecord(); JSHandle NewPromiseIteratorRecord(const JSHandle &itor, bool done); JSHandle NewMicroJobQueue(); JSHandle NewPendingJob(const JSHandle &func, const JSHandle &argv); JSHandle NewJSArray(); JSHandle NewJSProxy(const JSHandle &target, const JSHandle &handler); JSHandle NewJSRealm(); JSHandle NewJSArguments(); JSHandle NewJSString(const JSHandle &str); JSHandle NewTaggedArray(uint32_t length, JSTaggedValue initVal = JSTaggedValue::Hole()); JSHandle NewTaggedArray(uint32_t length, JSTaggedValue initVal, bool nonMovable); JSHandle NewTaggedArray(uint32_t length, JSTaggedValue initVal, MemSpaceType spaceType); JSHandle NewDictionaryArray(uint32_t length); JSHandle NewJSForinIterator(const JSHandle &obj); JSHandle NewPropertyBox(const JSHandle &name); JSHandle NewProtoChangeMarker(); JSHandle NewProtoChangeDetails(); JSHandle NewBigInt(uint32_t length); // use for copy properties keys's array to another array JSHandle ExtendArray(const JSHandle &old, uint32_t length, JSTaggedValue initVal = JSTaggedValue::Hole()); JSHandle CopyPartArray(const JSHandle &old, uint32_t start, uint32_t end); JSHandle CopyArray(const JSHandle &old, uint32_t oldLength, uint32_t newLength, JSTaggedValue initVal = JSTaggedValue::Hole()); JSHandle CloneProperties(const JSHandle &old); JSHandle CloneProperties(const JSHandle &old, const JSHandle &env, const JSHandle &obj, const JSHandle &constpool); JSHandle CreateLayoutInfo(int properties, JSTaggedValue initVal = JSTaggedValue::Hole()); JSHandle ExtendLayoutInfo(const JSHandle &old, int properties, JSTaggedValue initVal = JSTaggedValue::Hole()); JSHandle CopyLayoutInfo(const JSHandle &old); JSHandle CopyAndReSort(const JSHandle &old, int end, int capacity); JSHandle GetEmptyString() const; JSHandle EmptyArray() const; FreeObject *FillFreeObject(uintptr_t address, size_t size, RemoveSlots removeSlots = RemoveSlots::NO); TaggedObject *NewDynObject(const JSHandle &dynclass); TaggedObject *NewNonMovableDynObject(const JSHandle &dynclass, int inobjPropCount = 0); void InitializeExtraProperties(const JSHandle &dynclass, TaggedObject *obj, int inobjPropCount); JSHandle NewTaggedQueue(uint32_t length); JSHandle GetEmptyTaggedQueue() const; JSHandle NewJSSetIterator(const JSHandle &set, IterationKind kind); JSHandle NewJSRegExpIterator(const JSHandle &matcher, const JSHandle &inputStr, bool global, bool fullUnicode); JSHandle NewJSMapIterator(const JSHandle &map, IterationKind kind); JSHandle NewJSArrayIterator(const JSHandle &array, IterationKind kind); JSHandle NewCompletionRecord(CompletionRecordType type, JSHandle value); JSHandle NewGeneratorContext(); JSHandle CreateJSPromiseReactionsFunction(MethodIndex idx); JSHandle CreateJSPromiseExecutorFunction(); JSHandle NewJSPromiseAllResolveElementFunction(); JSHandle NewJSPromiseAnyRejectElementFunction(); JSHandle NewJSPromiseAllSettledResolveElementFunction(); JSHandle NewJSPromiseAllSettledRejectElementFunction(); JSHandle NewJSPromiseThenFinallyFunction(); JSHandle NewJSPromiseCatchFinallyFunction(); JSHandle NewJSPromiseValueThunkFunction(); JSHandle NewJSPromiseThrowerFunction(); JSHandle CloneObjectLiteral(JSHandle object, const JSHandle &env, const JSHandle &constpool, bool canShareHClass = true); JSHandle CloneObjectLiteral(JSHandle object); JSHandle CloneArrayLiteral(JSHandle object); JSHandle CloneJSFuction(JSHandle obj, FunctionKind kind); JSHandle CloneClassCtor(JSHandle ctor, const JSHandle &lexenv, bool canShareHClass); void NewJSArrayBufferData(const JSHandle &array, int32_t length); JSHandle NewJSArrayBuffer(int32_t length); JSHandle NewJSArrayBuffer(void *buffer, int32_t length, const DeleteEntryPoint &deleter, void *data, bool share = false); JSHandle NewJSDataView(JSHandle buffer, uint32_t offset, uint32_t length); void NewJSSharedArrayBufferData(const JSHandle &array, int32_t length); JSHandle NewJSSharedArrayBuffer(int32_t length); JSHandle NewJSSharedArrayBuffer(void *buffer, int32_t length); void NewJSRegExpByteCodeData(const JSHandle ®exp, void *buffer, size_t size); template inline void NewJSIntlIcuData(const JSHandle &obj, const S &icu, const DeleteEntryPoint &callback); EcmaString *InternString(const JSHandle &key); inline JSHandle NewJSNativePointer(void *externalPointer, const DeleteEntryPoint &callBack = nullptr, void *data = nullptr, bool nonMovable = false); JSHandle GetObjectLiteralByHClass(const JSHandle &properties, size_t length); JSHandle SetLayoutInObjHClass(const JSHandle &properties, size_t length, const JSHandle &objClass); JSHandle GetObjectLiteralHClass(const JSHandle &properties, size_t length); // only use for creating Function.prototype and Function JSHandle NewJSFunctionByDynClass(JSMethod *method, const JSHandle &clazz, FunctionKind kind = FunctionKind::NORMAL_FUNCTION); JSHandle NewJSFunctionByDynClass(const void *func, const JSHandle &clazz, FunctionKind kind = FunctionKind::NORMAL_FUNCTION); // used for creating jsobject by constructor JSHandle NewJSObjectByConstructor(const JSHandle &constructor, const JSHandle &newTarget); void InitializeJSObject(const JSHandle &obj, const JSHandle &jshclass); JSHandle NewJSObjectWithInit(const JSHandle &jshclass); uintptr_t NewSpaceBySnapshotAllocator(size_t size); JSHandle NewMachineCodeObject(size_t length, const uint8_t *data); JSHandle NewClassInfoExtractor(JSMethod *ctorMethod); // ----------------------------------- new TSType ---------------------------------------- JSHandle CreateTSObjLayoutInfo(int propNum, JSTaggedValue initVal = JSTaggedValue::Hole()); JSHandle NewTSObjectType(uint32_t numOfKeys); JSHandle NewTSClassType(); JSHandle NewTSUnionType(uint32_t length); JSHandle NewTSInterfaceType(); JSHandle NewTSImportType(); JSHandle NewTSClassInstanceType(); JSHandle NewTSTypeTable(uint32_t length); JSHandle NewTSModuleTable(uint32_t length); JSHandle NewTSFunctionType(uint32_t length); JSHandle NewTSArrayType(); // ----------------------------------- new string ---------------------------------------- JSHandle NewFromASCII(const CString &data); JSHandle NewFromUtf8(const CString &data); JSHandle NewFromStdString(const std::string &data); JSHandle NewFromUtf8(const uint8_t *utf8Data, uint32_t utf8Len); JSHandle NewFromUtf16(const uint16_t *utf16Data, uint32_t utf16Len); JSHandle NewFromUtf16Compress(const uint16_t *utf16Data, uint32_t utf16Len); JSHandle NewFromUtf16NotCompress(const uint16_t *utf16Data, uint32_t utf16Len); JSHandle NewFromUtf8Literal(const uint8_t *utf8Data, uint32_t utf8Len); JSHandle NewFromUtf8LiteralCompress(const uint8_t *utf8Data, uint32_t utf8Len); JSHandle NewFromUtf16Literal(const uint16_t *utf16Data, uint32_t utf16Len); JSHandle NewFromUtf16LiteralCompress(const uint16_t *utf16Data, uint32_t utf16Len); JSHandle NewFromUtf16LiteralNotCompress(const uint16_t *utf16Data, uint32_t utf16Len); JSHandle ConcatFromString(const JSHandle &firstString, const JSHandle &secondString); // used for creating Function JSHandle NewJSObject(const JSHandle &jshclass); // used for creating jshclass in Builtins, Function, Class_Linker JSHandle NewEcmaDynClass(uint32_t size, JSType type, const JSHandle &prototype); // It is used to provide iterators for non ECMA standard jsapi containers. JSHandle NewJSAPIPlainArray(uint32_t capacity); JSHandle NewJSAPIPlainArrayIterator(const JSHandle &plainarray, IterationKind kind); JSHandle NewJSAPIArrayList(uint32_t capacity); JSHandle NewJSAPILightWeightMapIterator(const JSHandle &obj, IterationKind kind); JSHandle NewJSAPILightWeightSetIterator(const JSHandle &obj, IterationKind kind); JSHandle CopyQueue(const JSHandle &old, uint32_t newLength, uint32_t front, uint32_t tail); JSHandle NewJSAPIQueueIterator(const JSHandle &queue); JSHandle CopyDeque(const JSHandle &old, uint32_t newLength, uint32_t oldLength, uint32_t first, uint32_t last); JSHandle NewJSAPIDequeIterator(const JSHandle &deque); JSHandle NewJSAPIArrayListIterator(const JSHandle &arrayList); JSHandle NewJSAPIList(); JSHandle NewJSAPILinkedList(); JSHandle NewJSAPILinkedListIterator(const JSHandle &linkedList); JSHandle NewJSAPIListIterator(const JSHandle &list); JSHandle NewJSAPITreeMapIterator(const JSHandle &map, IterationKind kind); JSHandle NewJSAPITreeSetIterator(const JSHandle &set, IterationKind kind); JSHandle NewJSAPIStackIterator(const JSHandle &stack); JSHandle NewJSAPIVector(uint32_t capacity); JSHandle NewJSAPIVectorIterator(const JSHandle &vector); // --------------------------------------module-------------------------------------------- JSHandle NewModuleNamespace(); JSHandle NewImportEntry(); JSHandle NewImportEntry(const JSHandle &moduleRequest, const JSHandle &importName, const JSHandle &localName); JSHandle NewExportEntry(); JSHandle NewExportEntry(const JSHandle &exportName, const JSHandle &moduleRequest, const JSHandle &importName, const JSHandle &localName); JSHandle NewSourceTextModule(); JSHandle NewResolvedBindingRecord(); JSHandle NewResolvedBindingRecord(const JSHandle &module, const JSHandle &bindingName); JSHandle NewCellRecord(); // --------------------------------------require-------------------------------------------- JSHandle NewCjsModule(); JSHandle NewCjsExports(); JSHandle NewCjsRequire(); private: friend class GlobalEnv; friend class GlobalEnvConstants; friend class EcmaString; friend class SnapshotProcessor; void ClearNativeMethodsData(); JSHandle NewJSFunctionImpl(JSMethod *method); static void * InternalMethodTable[static_cast(MethodIndex::METHOD_END)]; void InitObjectFields(const TaggedObject *object); JSThread *thread_ {nullptr}; bool isTriggerGc_ {false}; bool triggerSemiGC_ {false}; EcmaVM *vm_ {nullptr}; Heap *heap_ {nullptr}; ChunkVector nativeMethods_; ChunkVector internalNativeMethods_; NO_COPY_SEMANTIC(ObjectFactory); NO_MOVE_SEMANTIC(ObjectFactory); void NewObjectHook() const; // used for creating jshclass in Builtins, Function, Class_Linker JSHandle NewEcmaDynClass(uint32_t size, JSType type, uint32_t inlinedProps = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); // used for creating jshclass in GlobalEnv, EcmaVM JSHandle NewEcmaDynClassClass(JSHClass *hclass, uint32_t size, JSType type); JSHandle NewEcmaDynClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); JSHandle NewEcmaReadOnlyDynClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); JSHandle InitClassClass(); // used to create nonmovable js_object JSHandle NewNonMovableJSObject(const JSHandle &jshclass); // used to create nonmovable utf8 string at global constants JSHandle NewFromASCIINonMovable(const CString &data); // used for creating Function JSHandle NewJSFunction(const JSHandle &env, const JSHandle &dynKlass); JSHandle CreateObjectClass(const JSHandle &keys, const JSHandle &values); JSHandle CreateObjectClass(const JSHandle &properties, size_t length); JSHandle CreateFunctionClass(FunctionKind kind, uint32_t size, JSType type, const JSHandle &prototype); // used for creating ref.prototype in buildins, such as Number.prototype JSHandle NewJSPrimitiveRef(const JSHandle &dynKlass, const JSHandle &object); JSHandle GetStringFromStringTable(const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress) const; JSHandle GetStringFromStringTableNonMovable(const uint8_t *utf8Data, uint32_t utf8Len) const; // For MUtf-8 string data EcmaString *GetRawStringFromStringTable(const uint8_t *mutf8Data, uint32_t utf16Len, bool canBeCompressed) const; JSHandle GetStringFromStringTable(const uint16_t *utf16Data, uint32_t utf16Len, bool canBeCompress) const; JSHandle GetStringFromStringTable(EcmaString *string) const; JSHandle GetStringFromStringTable(const JSHandle &firstString, const JSHandle &secondString); inline EcmaString *AllocStringObject(size_t size); inline EcmaString *AllocNonMovableStringObject(size_t size); JSHandle NewEmptyArray(); // only used for EcmaVM. JSHandle CreateJSArguments(); JSHandle CreateJSArrayInstanceClass(JSHandle proto); JSHandle CreateJSRegExpInstanceClass(JSHandle proto); friend class Builtins; // create builtins object need dynclass friend class JSFunction; // create prototype_or_dynclass need dynclass friend class JSHClass; // HC transition need dynclass friend class EcmaVM; // hold the factory instance friend class JsVerificationTest; friend class PandaFileTranslator; friend class LiteralDataExtractor; friend class RuntimeStubs; friend class ClassInfoExtractor; friend class TSObjectType; friend class ModuleDataExtractor; }; class ClassLinkerFactory { private: friend class GlobalEnv; // root class in class_linker need dynclass friend class EcmaVM; // root class in class_linker need dynclass }; } // namespace panda::ecmascript #endif // ECMASCRIPT_OBJECT_FACTORY_H