From 005fda4f7fbf1570c6935e1f6589e9a8af6c1a1c Mon Sep 17 00:00:00 2001 From: linxiang Date: Fri, 8 Oct 2021 16:02:23 +0800 Subject: [PATCH] debug mode: 1. disable ic 2. disable parallel gc 3. enable gc logi 4. enable mem zap 5. switch to compress gc 6. enable cast checkwq 7. enable heap verify Signed-off-by: linxiang --- BUILD.gn | 2 +- ecmascript/base/config.h | 32 ++++++++++++- ecmascript/ecma_macros.h | 52 ++++++++++++++++++++- ecmascript/ecma_vm.cpp | 3 +- ecmascript/js_arguments.h | 5 +-- ecmascript/js_array.h | 6 +-- ecmascript/js_array_iterator.h | 7 +-- ecmascript/js_arraybuffer.h | 6 +-- ecmascript/js_async_function.h | 6 +-- ecmascript/js_collator.h | 6 +-- ecmascript/js_dataview.h | 6 +-- ecmascript/js_date.h | 6 +-- ecmascript/js_date_time_format.h | 6 +-- ecmascript/js_for_in_iterator.h | 5 +-- ecmascript/js_function.h | 60 ++++--------------------- ecmascript/js_generator_object.h | 18 ++------ ecmascript/js_hclass.h | 5 +++ ecmascript/js_map.h | 6 +-- ecmascript/js_number_format.h | 6 +-- ecmascript/js_object-inl.h | 6 --- ecmascript/js_object.h | 16 ++----- ecmascript/js_plural_rules.h | 6 +-- ecmascript/js_primitive_ref.h | 6 +-- ecmascript/js_promise.h | 38 ++++------------ ecmascript/js_proxy.h | 10 +---- ecmascript/js_regexp.h | 6 +-- ecmascript/js_relative_time_format.h | 6 +-- ecmascript/js_set.h | 5 +-- ecmascript/js_set_iterator.h | 6 +-- ecmascript/js_string_iterator.h | 6 +-- ecmascript/js_symbol.h | 6 +-- ecmascript/js_tagged_value-inl.h | 6 +++ ecmascript/js_tagged_value.h | 1 + ecmascript/js_thread.cpp | 10 +++++ ecmascript/js_typed_array.h | 6 +++ ecmascript/mem/caddress_allocator.h | 1 - ecmascript/mem/clock_scope.h | 4 +- ecmascript/mem/compress_collector.cpp | 1 + ecmascript/mem/compress_gc_marker-inl.h | 5 ++- ecmascript/mem/ecma_heap_manager-inl.h | 10 ++--- ecmascript/mem/gc_stats.cpp | 16 +++---- ecmascript/mem/heap.cpp | 49 +++++++++++++------- ecmascript/mem/heap.h | 2 +- ecmascript/mem/mem.h | 2 - ecmascript/mem/old_space_collector.cpp | 1 + ecmascript/mem/region_factory.cpp | 27 +++++++++-- ecmascript/mem/semi_space_collector.cpp | 1 + ecmascript/mem/semi_space_collector.h | 6 +++ ecmascript/mem/semi_space_marker.cpp | 9 ++-- ecmascript/mem/space.cpp | 22 +++++++-- ecmascript/mem/verification.cpp | 8 ++-- ecmascript/mem/verification.h | 24 +++++----- 52 files changed, 286 insertions(+), 285 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index bea20a7536..49a8fcc0c0 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -65,7 +65,7 @@ group("ark_js_host_unittest") { deps += [ "//ark/js_runtime:libark_jsruntime(${host_toolchain})", "//ark/js_runtime/ecmascript/builtins/tests:host_unittest", - "//ark/js_runtime/ecmascript/hprof/tests:host_unittest", + #"//ark/js_runtime/ecmascript/hprof/tests:host_unittest", "//ark/js_runtime/ecmascript/js_vm:ark_js_vm(${host_toolchain})", "//ark/js_runtime/ecmascript/napi/test:host_unittest", "//ark/js_runtime/ecmascript/regexp/tests:host_unittest", diff --git a/ecmascript/base/config.h b/ecmascript/base/config.h index 229c2eba8c..72f60cb077 100644 --- a/ecmascript/base/config.h +++ b/ecmascript/base/config.h @@ -20,9 +20,37 @@ namespace panda::ecmascript { #define ARK_INLINE __attribute__((always_inline)) #define ARK_NOINLINE __attribute__((noinline)) +#define ECMASCRIPT_ENABLE_DEBUG_MODE 0 #define ECMASCRIPT_ENABLE_RUNTIME_STAT 0 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define ECMASCRIPT_ENABLE_IC 1 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define ECMASCRIPT_ENABLE_THREAD_CHECK 0 + +/*** + * 1. close ic + * 2. close parallel gc + * 3. enable gc logs + * 4. enable handle-scope zap, zap reclaimed regions + * 5. switch gc mode to full gc + * 6. enable Cast() check + * 7. enable verify heap + */ +#if ECMASCRIPT_ENABLE_DEBUG_MODE + #define ECMASCRIPT_ENABLE_IC 0 + #define ECMASCRIPT_DISABLE_PARALLEL_GC 1 + #define ECMASCRIPT_ENABLE_GC_LOG 1 + #define ECMASCRIPT_ENABLE_ZAP_MEM 1 + #define ECMASCRIPT_SWITCH_GC_MODE_TO_COMPRESS_GC 1 + #define ECMASCRIPT_ENABLE_CAST_CHECK 1 + #define ECMASCRIPT_ENABLE_HEAP_VERIFY 1 + #define ECMASCRIPT_ENABLE_THREAD_CHECK 1 +#else + #define ECMASCRIPT_ENABLE_IC 1 + #define ECMASCRIPT_DISABLE_PARALLEL_GC 0 + #define ECMASCRIPT_ENABLE_GC_LOG 0 + #define ECMASCRIPT_ENABLE_ZAP_MEM 0 + #define ECMASCRIPT_SWITCH_GC_MODE_TO_COMPRESS_GC 0 + #define ECMASCRIPT_ENABLE_CAST_CHECK 0 + #define ECMASCRIPT_ENABLE_HEAP_VERIFY 0 + #define ECMASCRIPT_ENABLE_THREAD_CHECK 0 +#endif } // namespace panda::ecmascript #endif // ECMASCRIPT_BASE_CONFIG_H diff --git a/ecmascript/ecma_macros.h b/ecmascript/ecma_macros.h index b13285f0a5..eb749d7327 100644 --- a/ecmascript/ecma_macros.h +++ b/ecmascript/ecma_macros.h @@ -371,14 +371,14 @@ // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DECL_VISIT_OBJECT(BEGIN_OFFSET, SIZE) \ - void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor) \ + void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor) \ { \ visitor(this, ObjectSlot(ToUintPtr(this) + BEGIN_OFFSET), ObjectSlot(ToUintPtr(this) + SIZE)); \ } // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DECL_VISIT_OBJECT_FOR_JS_OBJECT(PARENTCLASS, BEGIN_OFFSET, SIZE) \ - void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor) \ + void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor) \ { \ VisitObjects(visitor); \ /* visit in object fields */ \ @@ -396,4 +396,52 @@ visitor(this, ObjectSlot(ToUintPtr(this) + BEGIN_OFFSET), ObjectSlot(ToUintPtr(this) + SIZE)); \ } +#if ECMASCRIPT_ENABLE_CAST_CHECK + #define CAST_CHECK(CAST_TYPE, CHECK_METHOD) \ + static inline CAST_TYPE *Cast(ObjectHeader *object) \ + { \ + if (!JSTaggedValue(object).CHECK_METHOD()) { \ + std::abort(); \ + } \ + return static_cast(object); \ + } \ + static inline const CAST_TYPE *ConstCast(const ObjectHeader *object) \ + { \ + if (!JSTaggedValue(object).CHECK_METHOD()) { \ + std::abort(); \ + } \ + return static_cast(object); \ + } +# else + #define CAST_CHECK(CAST_TYPE, CHECK_METHOD) \ + static inline CAST_TYPE *Cast(ObjectHeader *object) \ + { \ + ASSERT(JSTaggedValue(object).CHECK_METHOD()); \ + return static_cast(object); \ + } \ + static const inline CAST_TYPE *ConstCast(const ObjectHeader *object) \ + { \ + ASSERT(JSTaggedValue(object).CHECK_METHOD()); \ + return static_cast(object); \ + } +#endif + +#if ECMASCRIPT_ENABLE_CAST_CHECK + #define CAST_CHECK_TAGGEDVALUE(CAST_TYPE, CHECK_METHOD) \ + static inline CAST_TYPE *Cast(JSTaggedValue value) \ + { \ + if (value.IsHeapObject() && value.GetTaggedObject()->GetClass()->CHECK_METHOD()) { \ + return static_cast(value.GetTaggedObject()); \ + } \ + std::abort(); \ + } +# else + #define CAST_CHECK_TAGGEDVALUE(CAST_TYPE, CHECK_METHOD) \ + static inline CAST_TYPE *Cast(JSTaggedValue value) \ + { \ + ASSERT(value.IsHeapObject() && value.GetTaggedObject()->GetClass()->CHECK_METHOD()); \ + return static_cast(value.GetTaggedObject()); \ + } +#endif + #endif // ECMASCRIPT_ECMA_MACROS_H diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index fd4b50b2c7..54cf9ca407 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -242,7 +242,6 @@ EcmaVM::~EcmaVM() ClearBufferData(); if (gcStats_ != nullptr) { - gcStats_->PrintStatisticResult(); chunk_.Delete(gcStats_); gcStats_ = nullptr; } @@ -722,4 +721,4 @@ void EcmaVM::SetupRegExpResultCache() { regexpCache_ = builtins::RegExpExecResultCache::CreateCacheTable(thread_); } -} // namespace panda::ecmascript +} // namespace panda::ecmascript \ No newline at end of file diff --git a/ecmascript/js_arguments.h b/ecmascript/js_arguments.h index ba69c599d5..2c2d0f949e 100644 --- a/ecmascript/js_arguments.h +++ b/ecmascript/js_arguments.h @@ -30,10 +30,7 @@ public: static constexpr int CALLER_INLINE_PROPERTY_INDEX = 2; static constexpr int CALLEE_INLINE_PROPERTY_INDEX = 3; - static JSArguments *Cast(ObjectHeader *object) - { - return static_cast(object); - } + CAST_CHECK(JSArguments, IsArguments); // 9.4.4.1 [[GetOwnProperty]] (P) static bool GetOwnProperty(JSThread *thread, const JSHandle &args, const JSHandle &key, diff --git a/ecmascript/js_array.h b/ecmascript/js_array.h index 9a15eb47a4..16e60f26b2 100644 --- a/ecmascript/js_array.h +++ b/ecmascript/js_array.h @@ -28,11 +28,7 @@ class JSArray : public JSObject { public: static constexpr int LENGTH_INLINE_PROPERTY_INDEX = 0; - static JSArray *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSArray()); - return static_cast(object); - } + CAST_CHECK(JSArray, IsJSArray); static JSHandle ArrayCreate(JSThread *thread, JSTaggedNumber length); static JSHandle ArrayCreate(JSThread *thread, JSTaggedNumber length, diff --git a/ecmascript/js_array_iterator.h b/ecmascript/js_array_iterator.h index 7c8427869b..77e7d84371 100644 --- a/ecmascript/js_array_iterator.h +++ b/ecmascript/js_array_iterator.h @@ -22,11 +22,8 @@ namespace panda::ecmascript { class JSArrayIterator : public JSObject { public: - static JSArrayIterator *Cast(ObjectHeader *obj) - { - ASSERT(JSTaggedValue(obj).IsJSArrayIterator()); - return static_cast(obj); - } + CAST_CHECK(JSArrayIterator, IsJSArrayIterator); + static JSTaggedValue Next(EcmaRuntimeCallInfo *argv); static constexpr size_t ITERATED_ARRAY_OFFSET = JSObject::SIZE; diff --git a/ecmascript/js_arraybuffer.h b/ecmascript/js_arraybuffer.h index 18afaf06c3..7b7c7baf03 100644 --- a/ecmascript/js_arraybuffer.h +++ b/ecmascript/js_arraybuffer.h @@ -21,10 +21,8 @@ namespace panda::ecmascript { class JSArrayBuffer final : public JSObject { public: - static JSArrayBuffer *Cast(ObjectHeader *object) - { - return static_cast(object); - } + CAST_CHECK(JSArrayBuffer, IsArrayBuffer); + // 6.2.6.2 static void CopyDataBlockBytes(JSTaggedValue toBlock, JSTaggedValue fromBlock, int32_t fromIndex, int32_t count); diff --git a/ecmascript/js_async_function.h b/ecmascript/js_async_function.h index a79b7bf136..7e94d15bb9 100644 --- a/ecmascript/js_async_function.h +++ b/ecmascript/js_async_function.h @@ -23,11 +23,7 @@ namespace panda::ecmascript { class JSAsyncAwaitStatusFunction : public JSFunction { public: - static JSAsyncAwaitStatusFunction *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSAsyncAwaitStatusFunction()); - return static_cast(object); - } + CAST_CHECK(JSAsyncAwaitStatusFunction, IsJSAsyncAwaitStatusFunction); static JSHandle AsyncFunctionAwaitFulfilled(JSThread *thread, const JSHandle &func, diff --git a/ecmascript/js_collator.h b/ecmascript/js_collator.h index 77b21885bf..da7fe9614f 100644 --- a/ecmascript/js_collator.h +++ b/ecmascript/js_collator.h @@ -34,11 +34,7 @@ public: static const std::map uColAttributeValueMap; - static JSCollator *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSCollator()); - return reinterpret_cast(object); - } + CAST_CHECK(JSCollator, IsJSCollator); static constexpr size_t ICU_FIELD_OFFSET = JSObject::SIZE; diff --git a/ecmascript/js_dataview.h b/ecmascript/js_dataview.h index 4afef0b855..9d48627096 100644 --- a/ecmascript/js_dataview.h +++ b/ecmascript/js_dataview.h @@ -22,10 +22,8 @@ namespace panda::ecmascript { enum class DataViewType : uint8_t { FLOAT32 = 0, FLOAT64, INT8, INT16, INT32, UINT8, UINT16, UINT32, UINT8_CLAMPED }; class JSDataView : public JSObject { public: - static JSDataView *Cast(ObjectHeader *object) - { - return static_cast(object); - } + CAST_CHECK(JSDataView, IsDataView); + static int32_t GetElementSize(DataViewType type); static constexpr size_t DATA_VIEW_OFFSET = JSObject::SIZE; diff --git a/ecmascript/js_date.h b/ecmascript/js_date.h index c0040e6cdf..a9341fe9e8 100644 --- a/ecmascript/js_date.h +++ b/ecmascript/js_date.h @@ -63,10 +63,8 @@ public: }; class JSDate : public JSObject { public: - static JSDate *Cast(ObjectHeader *object) - { - return static_cast(object); - } + CAST_CHECK(JSDate, IsDate); + static constexpr size_t TIME_VALUE_OFFSET = JSObject::SIZE; ACCESSORS(TimeValue, TIME_VALUE_OFFSET, LOCAL_TIME_OFFSET) ACCESSORS(LocalOffset, LOCAL_TIME_OFFSET, SIZE) // localoffset in min diff --git a/ecmascript/js_date_time_format.h b/ecmascript/js_date_time_format.h index eaedd7f34c..85c9d1126f 100644 --- a/ecmascript/js_date_time_format.h +++ b/ecmascript/js_date_time_format.h @@ -86,11 +86,7 @@ private: class JSDateTimeFormat : public JSObject { public: - static JSDateTimeFormat *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSDateTimeFormat()); - return reinterpret_cast(object); - } + CAST_CHECK(JSDateTimeFormat, IsJSDateTimeFormat); static constexpr size_t LOCALE_OFFSET = JSObject::SIZE; diff --git a/ecmascript/js_for_in_iterator.h b/ecmascript/js_for_in_iterator.h index a33690a249..328c940d5e 100644 --- a/ecmascript/js_for_in_iterator.h +++ b/ecmascript/js_for_in_iterator.h @@ -24,10 +24,7 @@ namespace panda::ecmascript { class JSForInIterator : public JSObject { public: - static JSForInIterator *Cast(ObjectHeader *object) - { - return static_cast(object); - } + CAST_CHECK(JSForInIterator, IsForinIterator); static std::pair NextInternal(JSThread *thread, const JSHandle &it); diff --git a/ecmascript/js_function.h b/ecmascript/js_function.h index 316399e1aa..663ef51a30 100644 --- a/ecmascript/js_function.h +++ b/ecmascript/js_function.h @@ -29,17 +29,7 @@ class JSThread; class JSFunctionBase : public JSObject { public: - static JSFunctionBase *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSFunctionBase()); - return static_cast(object); - } - - static const JSFunctionBase *ConstCast(const ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSFunctionBase()); - return static_cast(object); - } + CAST_CHECK(JSFunctionBase, IsJSFunctionBase); inline void SetConstructor(bool flag) { @@ -71,11 +61,7 @@ public: static constexpr int CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX = 1; /* -------------- Common API Begin, Don't change those interface!!! ----------------- */ - static JSFunction *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSFunction()); - return static_cast(object); - } + CAST_CHECK(JSFunction, IsJSFunction); static void InitializeJSFunction(JSThread *thread, const JSHandle &env, const JSHandle &func, FunctionKind kind = FunctionKind::NORMAL_FUNCTION, bool strict = true); @@ -303,11 +289,7 @@ private: class JSGeneratorFunction : public JSFunction { public: - static JSGeneratorFunction *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsGeneratorFunction()); - return static_cast(object); - } + CAST_CHECK(JSGeneratorFunction, IsGeneratorFunction); static constexpr size_t SIZE = JSFunction::SIZE; @@ -318,11 +300,7 @@ public: class JSBoundFunction : public JSFunctionBase { public: - static JSBoundFunction *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsBoundFunction()); - return static_cast(object); - } + CAST_CHECK(JSBoundFunction, IsBoundFunction); // 9.4.1.1[[Call]](thisArgument, argumentsList) static JSTaggedValue CallInternal(JSThread *thread, const JSHandle &func); @@ -343,11 +321,7 @@ public: class JSProxyRevocFunction : public JSFunction { public: - static JSProxyRevocFunction *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsProxyRevocFunction()); - return static_cast(object); - } + CAST_CHECK(JSProxyRevocFunction, IsProxyRevocFunction); static void ProxyRevocFunctions(const JSThread *thread, const JSHandle &revoker); @@ -362,11 +336,7 @@ public: // ResolveFunction/RejectFunction class JSPromiseReactionsFunction : public JSFunction { public: - static JSPromiseReactionsFunction *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSPromiseReactionFunction()); - return static_cast(object); - } + CAST_CHECK(JSPromiseReactionsFunction, IsJSPromiseReactionFunction); static constexpr size_t PROMISE_OFFSET = JSFunction::SIZE; ACCESSORS(Promise, PROMISE_OFFSET, ALREADY_RESOLVED_OFFSET); @@ -380,11 +350,7 @@ public: // ExecutorFunction class JSPromiseExecutorFunction : public JSFunction { public: - static JSPromiseExecutorFunction *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSPromiseExecutorFunction()); - return static_cast(object); - } + CAST_CHECK(JSPromiseExecutorFunction, IsJSPromiseExecutorFunction); static constexpr size_t CAPABILITY_OFFSET = JSFunction::SIZE; ACCESSORS(Capability, CAPABILITY_OFFSET, SIZE); @@ -396,11 +362,7 @@ public: class JSPromiseAllResolveElementFunction : public JSFunction { public: - static JSPromiseAllResolveElementFunction *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSPromiseAllResolveElementFunction()); - return static_cast(object); - } + CAST_CHECK(JSPromiseAllResolveElementFunction, IsJSPromiseAllResolveElementFunction); static constexpr size_t INDEX_OFFSET = JSFunction::SIZE; ACCESSORS(Index, INDEX_OFFSET, VALUES_OFFSET); @@ -416,11 +378,7 @@ public: class JSIntlBoundFunction : public JSFunction { public: - static JSIntlBoundFunction *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSIntlBoundFunction()); - return static_cast(object); - } + CAST_CHECK(JSIntlBoundFunction, IsJSIntlBoundFunction); static JSTaggedValue IntlNameGetter(JSThread *thread, const JSHandle &self); diff --git a/ecmascript/js_generator_object.h b/ecmascript/js_generator_object.h index faf1796618..4365d6f811 100644 --- a/ecmascript/js_generator_object.h +++ b/ecmascript/js_generator_object.h @@ -30,11 +30,7 @@ enum class JSGeneratorState { class GeneratorContext : TaggedObject { public: - static GeneratorContext *Cast(ObjectHeader *object) - { - ASSERT(!JSTaggedValue(object).IsJSHClass()); - return static_cast(object); - } + CAST_CHECK(GeneratorContext, IsGeneratorContext); static constexpr size_t GENERATOR_REGS_ARRAY_OFFSET = TaggedObjectSize(); ACCESSORS(RegsArray, GENERATOR_REGS_ARRAY_OFFSET, GENERATOR_METHOD_OFFSET) @@ -50,11 +46,7 @@ public: class JSGeneratorObject : public JSObject { public: - static JSGeneratorObject *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsGeneratorObject()); - return static_cast(object); - } + CAST_CHECK(JSGeneratorObject, IsGeneratorObject); static constexpr size_t GENERATOR_STATE_OFFSET = JSObject::SIZE; ACCESSORS(GeneratorState, GENERATOR_STATE_OFFSET, GENERATOR_CONTEXT_OFFSET) @@ -88,11 +80,7 @@ public: class JSAsyncFuncObject : public JSGeneratorObject { public: - static JSAsyncFuncObject *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsAsyncFuncObject()); - return static_cast(object); - } + CAST_CHECK(JSAsyncFuncObject, IsAsyncFuncObject); static constexpr size_t GENERATOR_PROMISE_OFFSET = JSGeneratorObject::SIZE; ACCESSORS(Promise, GENERATOR_PROMISE_OFFSET, SIZE); diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index 7f29a4976a..d9c2a94759 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -722,6 +722,11 @@ public: return jsType == JSType::JS_GENERATOR_OBJECT || jsType == JSType::JS_ASYNC_FUNC_OBJECT; } + inline bool IsGeneratorContext() const + { + return GetObjectType() == JSType::JS_GENERATOR_CONTEXT; + } + inline bool IsAsyncFuncObject() const { return GetObjectType() == JSType::JS_ASYNC_FUNC_OBJECT; diff --git a/ecmascript/js_map.h b/ecmascript/js_map.h index 7b2a90e347..aa0e4ba4b2 100644 --- a/ecmascript/js_map.h +++ b/ecmascript/js_map.h @@ -23,10 +23,8 @@ namespace panda::ecmascript { class JSMap : public JSObject { public: - static JSMap *Cast(ObjectHeader *object) - { - return static_cast(object); - } + CAST_CHECK(JSMap, IsJSMap); + static bool Delete(const JSThread *thread, const JSHandle &map, const JSHandle &key); static void Set(JSThread *thread, const JSHandle &map, const JSHandle &key, diff --git a/ecmascript/js_number_format.h b/ecmascript/js_number_format.h index bf0791b9c8..8f7c97b6da 100644 --- a/ecmascript/js_number_format.h +++ b/ecmascript/js_number_format.h @@ -51,11 +51,7 @@ static const std::set sanctionedUnit({ "acre", "bit", "byte", "cels class JSNumberFormat : public JSObject { public: - static JSNumberFormat *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSNumberFormat()); - return reinterpret_cast(object); - } + CAST_CHECK(JSNumberFormat, IsJSNumberFormat); static constexpr size_t LOCALE_OFFSET = JSObject::SIZE; diff --git a/ecmascript/js_object-inl.h b/ecmascript/js_object-inl.h index fdf6bb49e4..7208fa4581 100644 --- a/ecmascript/js_object-inl.h +++ b/ecmascript/js_object-inl.h @@ -23,12 +23,6 @@ #include "ecmascript/tagged_array-inl.h" namespace panda::ecmascript { -inline ECMAObject *ECMAObject::Cast(ObjectHeader *object) -{ - ASSERT(JSTaggedValue(object).IsECMAObject()); - return static_cast(object); -} - inline void ECMAObject::SetBuiltinsCtorMode() { GetClass()->SetBuiltinsCtor(true); diff --git a/ecmascript/js_object.h b/ecmascript/js_object.h index 9030b10ef6..e9a95dd860 100644 --- a/ecmascript/js_object.h +++ b/ecmascript/js_object.h @@ -327,7 +327,8 @@ private: class ECMAObject : public TaggedObject { public: - static ECMAObject *Cast(ObjectHeader *object); + CAST_CHECK(ECMAObject, IsECMAObject); + void SetBuiltinsCtorMode(); bool IsBuiltinsConstructor() const; void SetCallable(bool flag); @@ -372,17 +373,8 @@ public: static constexpr int MAX_GAP = 1024; static constexpr uint32_t MAX_ELEMENT_INDEX = std::numeric_limits::max(); - static inline JSObject *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsECMAObject()); - return static_cast(object); - } - - static inline JSObject *Cast(JSTaggedValue value) - { - ASSERT(value.IsHeapObject() && value.GetTaggedObject()->GetClass()->IsECMAObject()); - return static_cast(value.GetTaggedObject()); - } + CAST_CHECK(JSObject, IsECMAObject); + CAST_CHECK_TAGGEDVALUE(JSObject, IsECMAObject); // ecma6.0 6.2.4.4 static JSHandle FromPropertyDescriptor(JSThread *thread, const PropertyDescriptor &desc); diff --git a/ecmascript/js_plural_rules.h b/ecmascript/js_plural_rules.h index 1e87fa0287..42b033ff40 100644 --- a/ecmascript/js_plural_rules.h +++ b/ecmascript/js_plural_rules.h @@ -29,11 +29,7 @@ constexpr int MXFD_DEFAULT = 3; class JSPluralRules : public JSObject { public: - static JSPluralRules *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSPluralRules()); - return reinterpret_cast(object); - } + CAST_CHECK(JSPluralRules, IsJSPluralRules); static constexpr size_t LOCALE_OFFSET = JSObject::SIZE; diff --git a/ecmascript/js_primitive_ref.h b/ecmascript/js_primitive_ref.h index 7564629ec5..d6348a65d6 100644 --- a/ecmascript/js_primitive_ref.h +++ b/ecmascript/js_primitive_ref.h @@ -31,11 +31,7 @@ enum class PrimitiveType : uint8_t { class JSPrimitiveRef : public JSObject { public: - static JSPrimitiveRef *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSPrimitiveRef()); - return static_cast(object); - } + CAST_CHECK(JSPrimitiveRef, IsJSPrimitiveRef); JSPrimitiveRef() = delete; diff --git a/ecmascript/js_promise.h b/ecmascript/js_promise.h index f70561f7cb..d66ac3e81d 100644 --- a/ecmascript/js_promise.h +++ b/ecmascript/js_promise.h @@ -30,11 +30,7 @@ enum class PromiseType : uint32_t { RESOLVE = 0, REJECT }; class PromiseReaction final : public Record { public: - static PromiseReaction *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsPromiseReaction()); - return static_cast(object); - } + CAST_CHECK(PromiseReaction, IsPromiseReaction); static constexpr size_t PROMISE_CAPABILITY_OFFSET = Record::SIZE; ACCESSORS(PromiseCapability, PROMISE_CAPABILITY_OFFSET, TYPE_OFFSET); @@ -48,11 +44,7 @@ public: class PromiseCapability final : public Record { public: - static PromiseCapability *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsPromiseCapability()); - return static_cast(object); - } + CAST_CHECK(PromiseCapability, IsPromiseCapability); static constexpr size_t PROMISE_OFFSET = Record::SIZE; ACCESSORS(Promise, PROMISE_OFFSET, RESOLVE_OFFSET); @@ -66,11 +58,7 @@ public: class PromiseIteratorRecord final : public Record { public: - static PromiseIteratorRecord *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsPromiseIteratorRecord()); - return static_cast(object); - } + CAST_CHECK(PromiseIteratorRecord, IsPromiseIteratorRecord); static constexpr size_t ITERATOR_OFFSET = Record::SIZE; ACCESSORS(Iterator, ITERATOR_OFFSET, DONE_OFFSET); @@ -83,11 +71,8 @@ public: class PromiseRecord final : public Record { public: - static PromiseRecord *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsPromiseRecord()); - return static_cast(object); - } + CAST_CHECK(PromiseRecord, IsPromiseRecord); + static constexpr size_t VALUE_OFFSET = Record::SIZE; ACCESSORS(Value, VALUE_OFFSET, SIZE); DECL_DUMP() @@ -97,11 +82,8 @@ public: class ResolvingFunctionsRecord final : public Record { public: - static ResolvingFunctionsRecord *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsResolvingFunctionsRecord()); - return static_cast(object); - } + CAST_CHECK(ResolvingFunctionsRecord, IsResolvingFunctionsRecord); + static constexpr size_t RESOLVE_FUNCTION_OFFSET = Record::SIZE; ACCESSORS(ResolveFunction, RESOLVE_FUNCTION_OFFSET, REJECT_FUNCTION_OFFSET); ACCESSORS(RejectFunction, REJECT_FUNCTION_OFFSET, SIZE); @@ -113,11 +95,7 @@ public: class JSPromise final : public JSObject { public: - static JSPromise *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSPromise()); - return static_cast(object); - } + CAST_CHECK(JSPromise, IsJSPromise); // ES6 25.4.1.3 CreateResolvingFunctions ( promise ) static JSHandle CreateResolvingFunctions(JSThread *thread, diff --git a/ecmascript/js_proxy.h b/ecmascript/js_proxy.h index fd6dfb5ec0..9297a214f1 100644 --- a/ecmascript/js_proxy.h +++ b/ecmascript/js_proxy.h @@ -22,15 +22,7 @@ namespace panda::ecmascript { class JSProxy final : public ECMAObject { public: - static JSProxy *Cast(ObjectHeader *object) - { - return static_cast(object); - } - - static const JSProxy *ConstCast(const TaggedObject *object) - { - return static_cast(object); - } + CAST_CHECK(JSProxy, IsJSProxy); // ES6 9.5.15 ProxyCreate(target, handler) static JSHandle ProxyCreate(JSThread *thread, const JSHandle &target, diff --git a/ecmascript/js_regexp.h b/ecmascript/js_regexp.h index ef8560df12..47fb41a016 100644 --- a/ecmascript/js_regexp.h +++ b/ecmascript/js_regexp.h @@ -24,11 +24,7 @@ namespace panda::ecmascript { class JSRegExp : public JSObject { public: - static JSRegExp *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSRegExp()); - return static_cast(object); - } + CAST_CHECK(JSRegExp, IsJSRegExp); static constexpr size_t LAST_INDEX_OFFSET = JSObject::SIZE; ACCESSORS(LastIndex, LAST_INDEX_OFFSET, REGEXP_BYTE_CODE_OFFSET); diff --git a/ecmascript/js_relative_time_format.h b/ecmascript/js_relative_time_format.h index 2c5fdc2619..029e244bfa 100644 --- a/ecmascript/js_relative_time_format.h +++ b/ecmascript/js_relative_time_format.h @@ -36,11 +36,7 @@ namespace panda::ecmascript { class JSRelativeTimeFormat : public JSObject { public: - static JSRelativeTimeFormat *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsJSRelativeTimeFormat()); - return reinterpret_cast(object); - } + CAST_CHECK(JSRelativeTimeFormat, IsJSRelativeTimeFormat); static constexpr size_t LOCALE_OFFSET = JSObject::SIZE; diff --git a/ecmascript/js_set.h b/ecmascript/js_set.h index 0412ecf9a1..e20e41866d 100644 --- a/ecmascript/js_set.h +++ b/ecmascript/js_set.h @@ -23,10 +23,7 @@ namespace panda::ecmascript { class JSSet : public JSObject { public: - static JSSet *Cast(ObjectHeader *object) - { - return static_cast(object); - } + CAST_CHECK(JSSet, IsJSSet); static bool Delete(const JSThread *thread, const JSHandle &set, const JSHandle &value); diff --git a/ecmascript/js_set_iterator.h b/ecmascript/js_set_iterator.h index 279f5c2021..dec9aa2666 100644 --- a/ecmascript/js_set_iterator.h +++ b/ecmascript/js_set_iterator.h @@ -22,11 +22,7 @@ namespace panda::ecmascript { class JSSetIterator : public JSObject { public: - static JSSetIterator *Cast(ObjectHeader *obj) - { - ASSERT(JSTaggedValue(obj).IsJSSetIterator()); - return static_cast(obj); - } + CAST_CHECK(JSSetIterator, IsJSSetIterator); static JSHandle CreateSetIterator(JSThread *thread, const JSHandle &obj, IterationKind kind); diff --git a/ecmascript/js_string_iterator.h b/ecmascript/js_string_iterator.h index d13304be59..b20e9a554c 100644 --- a/ecmascript/js_string_iterator.h +++ b/ecmascript/js_string_iterator.h @@ -25,11 +25,7 @@ namespace panda { namespace ecmascript { class JSStringIterator : public JSObject { public: - static JSStringIterator *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsStringIterator()); - return static_cast(object); - } + CAST_CHECK(JSStringIterator, IsStringIterator); static JSHandle CreateStringIterator(const JSThread *thread, const JSHandle &string); diff --git a/ecmascript/js_symbol.h b/ecmascript/js_symbol.h index b1f4ecb18e..9fa2f74854 100644 --- a/ecmascript/js_symbol.h +++ b/ecmascript/js_symbol.h @@ -39,11 +39,7 @@ public: static constexpr const uint32_t LINEAR_SEED = 987654321U; public: - static JSSymbol *Cast(ObjectHeader *object) - { - ASSERT(JSTaggedValue(object).IsSymbol()); - return static_cast(object); - } + CAST_CHECK(JSSymbol, IsSymbol); static inline uint32_t ComputeHash() { diff --git a/ecmascript/js_tagged_value-inl.h b/ecmascript/js_tagged_value-inl.h index 27d6f86f29..da452fa1b3 100644 --- a/ecmascript/js_tagged_value-inl.h +++ b/ecmascript/js_tagged_value-inl.h @@ -789,11 +789,17 @@ inline bool JSTaggedValue::IsGeneratorFunction() const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsGeneratorFunction(); } + inline bool JSTaggedValue::IsGeneratorObject() const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsGeneratorObject(); } +inline bool JSTaggedValue::IsGeneratorContext() const +{ + return IsHeapObject() && GetTaggedObject()->GetClass()->IsGeneratorContext(); +} + inline bool JSTaggedValue::IsAsyncFuncObject() const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsAsyncFuncObject(); diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index 1cd220490d..b7773759e8 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -286,6 +286,7 @@ public: bool IsIterator() const; bool IsGeneratorFunction() const; bool IsGeneratorObject() const; + bool IsGeneratorContext() const; bool IsAsyncFuncObject() const; bool IsJSPromise() const; bool IsRecord() const; diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index 5ed583444c..88b1a280e0 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -190,6 +190,16 @@ uintptr_t *JSThread::ExpandHandleStorage() void JSThread::ShrinkHandleStorage(int prevIndex) { currentHandleStorageIndex_ = prevIndex; + +#if ECMASCRIPT_ENABLE_ZAP_MEM + uintptr_t size = ToUintPtr(handleScopeStorageEnd_) - ToUintPtr(handleScopeStorageNext_); + memset_s(handleScopeStorageNext_, size, 0, size); + + int32_t lastIndex = handleStorageNodes_.size() - 1; + for (int32_t i = currentHandleStorageIndex_ + 1; i < lastIndex; i++) { + memset_s(handleStorageNodes_[i], NODE_BLOCK_SIZE * sizeof(JSTaggedType), 0, NODE_BLOCK_SIZE * sizeof(JSTaggedType)); + } +#endif } void JSThread::NotifyStableArrayElementsGuardians(JSHandle receiver) diff --git a/ecmascript/js_typed_array.h b/ecmascript/js_typed_array.h index ab8a36cce6..506f1474f7 100644 --- a/ecmascript/js_typed_array.h +++ b/ecmascript/js_typed_array.h @@ -24,7 +24,13 @@ class JSTypedArray : public JSObject { public: static JSTypedArray *Cast(ObjectHeader *object) { + #if ECMASCRIPT_ENABLE_CAST_CHECK + if (!(JSTaggedValue(object).IsTypedArray() || JSTaggedValue(object).IsJSTypedArray())) { + std::abort(); + } + #else ASSERT(JSTaggedValue(object).IsTypedArray() || JSTaggedValue(object).IsJSTypedArray()); + #endif return static_cast(object); } diff --git a/ecmascript/mem/caddress_allocator.h b/ecmascript/mem/caddress_allocator.h index 3a08b03775..e7eb1e24f1 100644 --- a/ecmascript/mem/caddress_allocator.h +++ b/ecmascript/mem/caddress_allocator.h @@ -155,7 +155,6 @@ public: return; } // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) - os::memory::LockHolder lock(staticResourceLock_); free(mem); } }; diff --git a/ecmascript/mem/clock_scope.h b/ecmascript/mem/clock_scope.h index de76aac310..53e7a6b035 100644 --- a/ecmascript/mem/clock_scope.h +++ b/ecmascript/mem/clock_scope.h @@ -39,8 +39,10 @@ public: ~ClockScope() { end_ = Clock::now(); + # if ECMASCRIPT_ENABLE_GC_LOG auto duration = std::chrono::duration_cast(end_ - start_); - LOG(DEBUG, RUNTIME) << str_ << " spent time: " << (float) duration.count() / MILLION_TIME << "ms"; + LOG(ERROR, RUNTIME) << str_ << " spent time: " << (float) duration.count() / MILLION_TIME << "ms"; + # endif } NO_COPY_SEMANTIC(ClockScope); diff --git a/ecmascript/mem/compress_collector.cpp b/ecmascript/mem/compress_collector.cpp index db3759594c..aa3f8b60fd 100644 --- a/ecmascript/mem/compress_collector.cpp +++ b/ecmascript/mem/compress_collector.cpp @@ -42,6 +42,7 @@ CompressCollector::~CompressCollector() void CompressCollector::RunPhases() { + LOG_GC() << "CompressCollector::RunPhases"; [[maybe_unused]] ecmascript::JSThread *thread = heap_->GetEcmaVM()->GetJSThread(); INTERPRETER_TRACE(thread, CompressCollector_RunPhases); trace::ScopedTrace scoped_trace("CompressCollector::RunPhases"); diff --git a/ecmascript/mem/compress_gc_marker-inl.h b/ecmascript/mem/compress_gc_marker-inl.h index 1f52bfc10f..d631931928 100644 --- a/ecmascript/mem/compress_gc_marker-inl.h +++ b/ecmascript/mem/compress_gc_marker-inl.h @@ -54,7 +54,7 @@ inline void CompressGCMarker::EvacuateObject(uint32_t threadId, TaggedObject *ob auto size = klass->SizeFromJSHClass(jsType, object); uintptr_t forwardAddress = collector_->workList_->GetTlabAllocator(threadId)->Allocate(size, SpaceAlloc::OLD_SPACE); if (UNLIKELY(forwardAddress == 0)) { - LOG_ECMA_MEM(FATAL) << "alloc failed"; + LOG_ECMA_MEM(FATAL) << "CompressGCMarker::EvacuateObject alloc failed: "; UNREACHABLE(); } @@ -81,7 +81,8 @@ inline void CompressGCMarker::CopyObjectWithoutHeader(TaggedObject *object, uint { if (memcpy_s(ToVoidPtr(address + HEAD_SIZE), size - HEAD_SIZE, ToVoidPtr(ToUintPtr(object) + HEAD_SIZE), size - HEAD_SIZE) != EOK) { - LOG_ECMA(FATAL) << "memcpy_s failed"; + LOG_ECMA_MEM(FATAL) << "CompressGCMarker::CopyObjectWithoutHeader memcpy_s failed: " << " dst: " << address + << " src: " << ToUintPtr(object) << " size: " << size; UNREACHABLE(); } } diff --git a/ecmascript/mem/ecma_heap_manager-inl.h b/ecmascript/mem/ecma_heap_manager-inl.h index 4b65d6c337..1b32ed63cb 100644 --- a/ecmascript/mem/ecma_heap_manager-inl.h +++ b/ecmascript/mem/ecma_heap_manager-inl.h @@ -59,7 +59,7 @@ TaggedObject *EcmaHeapManager::AllocateYoungGenerationOrHugeObject(JSHClass *hcl heap_->CollectGarbage(TriggerGCType::OLD_GC); object = reinterpret_cast(newSpaceAllocator_.Allocate(size)); if (UNLIKELY(object == nullptr)) { - heap_->ThrowOutOfMemoryError(size); + heap_->ThrowOutOfMemoryError(size, "AllocateYoungGenerationOrHugeObject"); UNREACHABLE(); } } @@ -96,7 +96,7 @@ TaggedObject *EcmaHeapManager::AllocateNonMovableOrHugeObject(JSHClass *hclass, } object = reinterpret_cast(nonMovableAllocator_.Allocate(size)); if (UNLIKELY(object == nullptr)) { - heap_->ThrowOutOfMemoryError(size); + heap_->ThrowOutOfMemoryError(size, "AllocateNonMovableOrHugeObject"); UNREACHABLE(); } } @@ -153,7 +153,7 @@ TaggedObject *EcmaHeapManager::AllocateOldGenerationOrHugeObject(JSHClass *hclas } object = reinterpret_cast(oldSpaceAllocator_.Allocate(size)); if (UNLIKELY(object == nullptr)) { - heap_->ThrowOutOfMemoryError(size); + heap_->ThrowOutOfMemoryError(size, "AllocateOldGenerationOrHugeObject"); UNREACHABLE(); } } @@ -175,7 +175,7 @@ TaggedObject *EcmaHeapManager::AllocateHugeObject(JSHClass *hclass, size_t size) object = reinterpret_cast( const_cast(heap_->GetHugeObjectSpace())->Allocate(size)); if (UNLIKELY(object == nullptr)) { - heap_->ThrowOutOfMemoryError(size); + heap_->ThrowOutOfMemoryError(size, "AllocateHugeObject"); UNREACHABLE(); } } @@ -193,7 +193,7 @@ TaggedObject *EcmaHeapManager::AllocateMachineCodeSpaceObject(JSHClass *hclass, } object = reinterpret_cast(machineCodeSpaceAllocator_.Allocate(size)); if (UNLIKELY(object == nullptr)) { - heap_->ThrowOutOfMemoryError(size); + heap_->ThrowOutOfMemoryError(size, "AllocateMachineCodeSpaceObject"); return nullptr; } } diff --git a/ecmascript/mem/gc_stats.cpp b/ecmascript/mem/gc_stats.cpp index 811707dd6c..c7ad5e1380 100644 --- a/ecmascript/mem/gc_stats.cpp +++ b/ecmascript/mem/gc_stats.cpp @@ -21,10 +21,10 @@ namespace panda::ecmascript { void GCStats::PrintStatisticResult() { - LOG(DEBUG, RUNTIME) << "GCStats statistic: "; + LOG(ERROR, RUNTIME) << "GCStats statistic: "; if (semiGCCount_ != 0) { - LOG(DEBUG, RUNTIME) << " SemiCollector statistic: total semi gc count " << semiGCCount_; - LOG(DEBUG, RUNTIME) << " MIN pause time: " << PrintTimeMilliseconds(semiGCMinPause_) << "ms" + LOG(ERROR, RUNTIME) << " SemiCollector statistic: total semi gc count " << semiGCCount_; + LOG(ERROR, RUNTIME) << " MIN pause time: " << PrintTimeMilliseconds(semiGCMinPause_) << "ms" << " MAX pause time: " << PrintTimeMilliseconds(semiGCMAXPause_) << "ms" << " total pause time: " << PrintTimeMilliseconds(semiGCTotalPause_) << "ms" << " average pause time: " << PrintTimeMilliseconds(semiGCTotalPause_ / semiGCCount_) @@ -39,8 +39,8 @@ void GCStats::PrintStatisticResult() } if (oldGCCount_ != 0) { - LOG(DEBUG, RUNTIME) << " oldCollector statistic: total old gc count " << oldGCCount_; - LOG(DEBUG, RUNTIME) << " MIN pause time: " << PrintTimeMilliseconds(oldGCMinPause_) << "ms" + LOG(ERROR, RUNTIME) << " oldCollector statistic: total old gc count " << oldGCCount_; + LOG(ERROR, RUNTIME) << " MIN pause time: " << PrintTimeMilliseconds(oldGCMinPause_) << "ms" << " MAX pause time: " << PrintTimeMilliseconds(oldGCMAXPause_) << "ms" << " total pause time: " << PrintTimeMilliseconds(oldGCTotalPause_) << "ms" << " average pause time: " << PrintTimeMilliseconds(oldGCTotalPause_ / oldGCCount_) << "ms" @@ -57,8 +57,8 @@ void GCStats::PrintStatisticResult() } if (compressGCCount_ != 0) { - LOG(DEBUG, RUNTIME) << " compressCollector statistic: total compress gc count " << compressGCCount_; - LOG(DEBUG, RUNTIME) + LOG(ERROR, RUNTIME) << " compressCollector statistic: total compress gc count " << compressGCCount_; + LOG(ERROR, RUNTIME) << " MIN pause time: " << PrintTimeMilliseconds(compressGCMinPause_) << "ms" << " MAX pause time: " << PrintTimeMilliseconds(compressGCMaxPause_) << "ms" << " total pause time: " << PrintTimeMilliseconds(compressGCTotalPause_) << "ms" @@ -79,7 +79,7 @@ void GCStats::PrintStatisticResult() if (heap_ != nullptr) { RegionFactory *regionFactory = const_cast(heap_->GetRegionFactory()); - LOG(DEBUG, RUNTIME) << "pool statistic:: " + LOG(ERROR, RUNTIME) << "pool statistic:: " << "anno memory usage size:" << regionFactory->GetAnnoMemoryUsage() << "anno memory max usage size:" << regionFactory->GetMaxAnnoMemoryUsage() << "native memory usage size:" << regionFactory->GetNativeMemoryUsage() diff --git a/ecmascript/mem/heap.cpp b/ecmascript/mem/heap.cpp index 61aba40a8b..c9e2a18400 100644 --- a/ecmascript/mem/heap.cpp +++ b/ecmascript/mem/heap.cpp @@ -57,6 +57,9 @@ void Heap::Initialize() markStack_ = new MarkStack(this); weakProcessQueue_ = new ProcessQueue(this); bool paralledGc = ecmaVm_->GetOptions().IsEnableParalledYoungGc(); +#if ECMASCRIPT_DISABLE_PARALLEL_GC + paralledGc = false; +#endif if (paralledGc) { int numOfCpuCore = get_nprocs(); int numThread = std::min(numOfCpuCore, THREAD_NUM_FOR_YOUNG_GC); @@ -135,15 +138,21 @@ void Heap::Destroy() void Heap::CollectGarbage(TriggerGCType gcType) { CHECK_NO_GC +#if ECMASCRIPT_ENABLE_HEAP_VERIFY // pre gc heap verify - { - if (ecmaVm_->GetOptions().IsPreGcHeapVerifyEnabled()) { - auto failCount = Verification(this).VerifyAll(); - if (failCount > 0) { - LOG(FATAL, GC) << "Before gc heap corrupted and " << failCount << " corruptions"; - } - } + auto failCount = Verification(this).VerifyAll(); + if (failCount > 0) { + LOG(FATAL, GC) << "Before gc heap corrupted and " << failCount << " corruptions"; + } + // verify need semiGC or fullGC + if (gcType != TriggerGCType::SEMI_GC) { + gcType = TriggerGCType::COMPRESS_FULL_GC; } +#endif + +# if ECMASCRIPT_SWITCH_GC_MODE_TO_COMPRESS_GC + gcType = TriggerGCType::COMPRESS_FULL_GC; +#endif switch (gcType) { case TriggerGCType::SEMI_GC: if (GetMemController()->IsInAppStartup()) { @@ -180,25 +189,33 @@ void Heap::CollectGarbage(TriggerGCType gcType) break; } +# if ECMASCRIPT_ENABLE_GC_LOG + ecmaVm_->GetEcmaGCStats()->PrintStatisticResult(); +#endif + +#if ECMASCRIPT_ENABLE_HEAP_VERIFY // post gc heap verify - { - if (ecmaVm_->GetOptions().IsPreGcHeapVerifyEnabled()) { - auto failCount = Verification(this).VerifyAll(); - if (failCount > 0) { - LOG(FATAL, GC) << "After gc heap corrupted and " << failCount << " corruptions"; - } - } + failCount = Verification(this).VerifyAll(); + if (failCount > 0) { + LOG(FATAL, GC) << "After gc heap corrupted and " << failCount << " corruptions"; } +#endif } -void Heap::ThrowOutOfMemoryError(size_t size) +void Heap::ThrowOutOfMemoryError(size_t size, std::string functionName) { - LOG_ECMA_MEM(FATAL) << "OOM when trying to allocate " << size << " bytes"; + LOG_ECMA_MEM(FATAL) << "OOM when trying to allocate " << size << " bytes" + << " function name: " << functionName.c_str(); } size_t Heap::VerifyHeapObjects() const { size_t failCount = 0; + { + VerifyObjectVisitor verifier(this, &failCount); + toSpace_->IterateOverObjects(verifier); + } + { VerifyObjectVisitor verifier(this, &failCount); oldSpace_->IterateOverObjects(verifier); diff --git a/ecmascript/mem/heap.h b/ecmascript/mem/heap.h index bc112f2f87..112d947be5 100644 --- a/ecmascript/mem/heap.h +++ b/ecmascript/mem/heap.h @@ -155,7 +155,7 @@ public: inline bool FillSnapShotSpace(BumpPointerAllocator *spaceAllocator); inline bool FillMachineCodeSpaceAndTryGC(FreeListAllocator *spaceAllocator, bool allowGc = true); - void ThrowOutOfMemoryError(size_t size); + void ThrowOutOfMemoryError(size_t size, std::string functionName); void SetHeapManager(EcmaHeapManager *heapManager) { diff --git a/ecmascript/mem/mem.h b/ecmascript/mem/mem.h index 83742742ad..2cbd4c08e5 100644 --- a/ecmascript/mem/mem.h +++ b/ecmascript/mem/mem.h @@ -87,8 +87,6 @@ static constexpr size_t MAX_CHUNK_AREA_SIZE = 1 * 1024 * 1024; static constexpr uintptr_t PANDA_32BITS_HEAP_START_ADDRESS_256 = 256_KB; -static os::memory::Mutex staticResourceLock_; - template constexpr inline bool IsAligned(T value, size_t alignment) { diff --git a/ecmascript/mem/old_space_collector.cpp b/ecmascript/mem/old_space_collector.cpp index 3572760030..7e681dae11 100644 --- a/ecmascript/mem/old_space_collector.cpp +++ b/ecmascript/mem/old_space_collector.cpp @@ -31,6 +31,7 @@ OldSpaceCollector::OldSpaceCollector(Heap *heap) : heap_(heap), rootManager_(hea void OldSpaceCollector::RunPhases() { + LOG_GC() << "OldSpaceCollector::RunPhases"; [[maybe_unused]] ecmascript::JSThread *thread = heap_->GetEcmaVM()->GetJSThread(); INTERPRETER_TRACE(thread, OldSpaceCollector_RunPhases); trace::ScopedTrace scoped_trace("OldSpaceCollector::RunPhases"); diff --git a/ecmascript/mem/region_factory.cpp b/ecmascript/mem/region_factory.cpp index 757babbd7f..6d29122d5d 100644 --- a/ecmascript/mem/region_factory.cpp +++ b/ecmascript/mem/region_factory.cpp @@ -37,6 +37,9 @@ Region *RegionFactory::AllocateAlignedRegion(Space *space, size_t capacity) auto pool = PoolManager::GetMmapMemPool()->AllocPool(commitSize, panda::SpaceType::SPACE_TYPE_OBJECT, AllocatorType::RUNSLOTS_ALLOCATOR, nullptr); void *mapMem = pool.GetMem(); +#if ECMASCRIPT_ENABLE_ZAP_MEM + memset_s(mapMem, commitSize, 0, commitSize); +#endif if (mapMem == nullptr) { LOG_ECMA_MEM(FATAL) << "pool is empty"; UNREACHABLE(); @@ -58,6 +61,9 @@ void RegionFactory::FreeRegion(Region *region) { auto size = region->GetCapacity(); DecreaseAnnoMemoryUsage(size); +#if ECMASCRIPT_ENABLE_ZAP_MEM + memset_s(ToVoidPtr(region->GetAllocateBase()), size, 0, size); +#endif PoolManager::GetMmapMemPool()->FreePool(ToVoidPtr(region->GetAllocateBase()), size); } @@ -75,6 +81,9 @@ Area *RegionFactory::AllocateArea(size_t capacity) } // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) void *mem = malloc(capacity); +#if ECMASCRIPT_ENABLE_ZAP_MEM + memset_s(mem, capacity, 0, capacity); +#endif if (mem == nullptr) { LOG_ECMA_MEM(FATAL) << "malloc failed"; UNREACHABLE(); @@ -97,7 +106,9 @@ void RegionFactory::FreeArea(Area *area) } auto size = area->GetSize() + sizeof(Area); DecreaseNativeMemoryUsage(size); - os::memory::LockHolder lock(staticResourceLock_); +#if ECMASCRIPT_ENABLE_ZAP_MEM + memset_s(area, size, 0, size); +#endif // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) free(reinterpret_cast(area)); } @@ -110,6 +121,9 @@ void *RegionFactory::Allocate(size_t size) } // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) void *ptr = malloc(size); +#if ECMASCRIPT_ENABLE_ZAP_MEM + memset_s(ptr, size, 0, size); +#endif if (ptr == nullptr) { LOG_ECMA_MEM(FATAL) << "malloc failed"; UNREACHABLE(); @@ -124,7 +138,9 @@ void RegionFactory::Free(void *mem, size_t size) return; } DecreaseNativeMemoryUsage(size); - os::memory::LockHolder lock(staticResourceLock_); +#if ECMASCRIPT_ENABLE_ZAP_MEM + memset_s(mem, size, 0, size); +#endif // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) free(mem); } @@ -141,6 +157,9 @@ void *RegionFactory::AllocateBuffer(size_t size) LOG_ECMA_MEM(FATAL) << "malloc failed"; UNREACHABLE(); } +#if ECMASCRIPT_ENABLE_ZAP_MEM + memset_s(ptr, size, 0, size); +#endif IncreaseNativeMemoryUsage(size); return ptr; } @@ -151,7 +170,9 @@ void RegionFactory::FreeBuffer(void *mem) return; } DecreaseNativeMemoryUsage(malloc_usable_size(mem)); - os::memory::LockHolder lock(staticResourceLock_); +#if ECMASCRIPT_ENABLE_ZAP_MEM + memset_s(mem, size, 0, size); +#endif // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) free(mem); } diff --git a/ecmascript/mem/semi_space_collector.cpp b/ecmascript/mem/semi_space_collector.cpp index ef6975066f..3f8f3b0657 100644 --- a/ecmascript/mem/semi_space_collector.cpp +++ b/ecmascript/mem/semi_space_collector.cpp @@ -44,6 +44,7 @@ SemiSpaceCollector::~SemiSpaceCollector() void SemiSpaceCollector::RunPhases() { + LOG_GC() << "SemiSpaceCollector::RunPhases"; [[maybe_unused]] ecmascript::JSThread *thread = heap_->GetEcmaVM()->GetJSThread(); INTERPRETER_TRACE(thread, SemiSpaceCollector_RunPhases); trace::ScopedTrace scoped_trace("SemiSpaceCollector::RunPhases"); diff --git a/ecmascript/mem/semi_space_collector.h b/ecmascript/mem/semi_space_collector.h index 6e5a31f624..2b14350c14 100644 --- a/ecmascript/mem/semi_space_collector.h +++ b/ecmascript/mem/semi_space_collector.h @@ -40,6 +40,12 @@ class Heap; class JSHClass; class SemiSpaceWorker; +#if ECMASCRIPT_ENABLE_GC_LOG + #define LOG_GC() LOG(ERROR, RUNTIME) << ": " +#else + #define LOG_GC() LOG(DEBUG, RUNTIME) << ": " +#endif + class GarbageCollector { public: GarbageCollector() = default; diff --git a/ecmascript/mem/semi_space_marker.cpp b/ecmascript/mem/semi_space_marker.cpp index d4ca483813..f367ca0c62 100644 --- a/ecmascript/mem/semi_space_marker.cpp +++ b/ecmascript/mem/semi_space_marker.cpp @@ -61,7 +61,8 @@ SlotStatus SemiSpaceMarker::EvacuateObject(uint32_t threadId, TaggedObject *obje if (UNLIKELY(forwardAddress == 0)) { forwardAddress = collector_->workList_->GetTlabAllocator(threadId)->Allocate(size, SpaceAlloc::YOUNG_SPACE); if (UNLIKELY(forwardAddress == 0)) { - LOG_ECMA_MEM(FATAL) << "alloc failed"; + LOG_ECMA_MEM(FATAL) << "SemiSpaceMarker::EvacuateObject alloc failed: " << " jstype: " + << (uint16_t)jsType << " size: " << size << " obj address: " << ToUintPtr(object); UNREACHABLE(); } isPromoted = false; @@ -71,7 +72,8 @@ SlotStatus SemiSpaceMarker::EvacuateObject(uint32_t threadId, TaggedObject *obje if (UNLIKELY(forwardAddress == 0)) { forwardAddress = collector_->workList_->GetTlabAllocator(threadId)->Allocate(size, SpaceAlloc::OLD_SPACE); if (UNLIKELY(forwardAddress == 0)) { - LOG_ECMA_MEM(FATAL) << "alloc failed"; + LOG_ECMA_MEM(FATAL) << "SemiSpaceMarker::EvacuateObject alloc failed: " << " jstype: " + << (uint16_t)jsType << " size: " << size << " obj address: " << ToUintPtr(object); UNREACHABLE(); } isPromoted = true; @@ -106,7 +108,8 @@ void SemiSpaceMarker::CopyObjectWithoutHeader(TaggedObject *object, uintptr_t ad { if (memcpy_s(ToVoidPtr(address + HEAD_SIZE), size - HEAD_SIZE, ToVoidPtr(ToUintPtr(object) + HEAD_SIZE), size - HEAD_SIZE) != EOK) { - LOG_ECMA(FATAL) << "memcpy_s failed"; + LOG_ECMA_MEM(FATAL) << "SemiSpaceMarker::CopyObjectWithoutHeader memcpy_s failed: " << " dst: " + << address << " src: " << ToUintPtr(object) << " size: " << size; UNREACHABLE(); } } diff --git a/ecmascript/mem/space.cpp b/ecmascript/mem/space.cpp index cb83b9416c..81dddea607 100644 --- a/ecmascript/mem/space.cpp +++ b/ecmascript/mem/space.cpp @@ -131,7 +131,15 @@ bool SemiSpace::ContainObject(TaggedObject *object) const bool SemiSpace::IsLive(TaggedObject *object) const { - return ContainObject(object); + auto region = GetRegionList().GetFirst(); + while (region != nullptr) { + if (region->InRange(ToUintPtr(object))) { + auto freeObject = FreeObject::Cast(ToUintPtr(object)); + return !freeObject->IsFreeObject(); + } + region = region->GetNext(); + } + return false; } void SemiSpace::IterateOverObjects(const std::function &visitor) const @@ -157,8 +165,10 @@ void SemiSpace::IterateOverObjects(const std::functionAvailable(); } - LOG_IF(objSize == 0, FATAL, RUNTIME) << "SemiSpace IterateOverObjects objSize==0 invalid: " << curPtr; curPtr += AlignUp(objSize, sizeof(JSTaggedType)); + LOG_IF(objSize == 0, FATAL, RUNTIME) << "SemiSpace IterateOverObjects objSize==0 invalid: " << curPtr; + LOG_IF(curPtr > endPtr, FATAL, RUNTIME) << "SemiSpace IterateOverObjects size is invalid curPtr: " + << curPtr << " endPtr: " << endPtr; } }); } @@ -221,8 +231,10 @@ void OldSpace::IterateOverObjects(const std::functionAvailable(); } - LOG_IF(objSize == 0, FATAL, RUNTIME) << "OldSpace IterateOverObjects objSize==0 invalid: " << curPtr; curPtr += AlignUp(objSize, sizeof(JSTaggedType)); + LOG_IF(objSize == 0, FATAL, RUNTIME) << "OldSpace IterateOverObjects objSize==0 invalid: " << curPtr; + LOG_IF(curPtr > endPtr, FATAL, RUNTIME) << "OldSpace IterateOverObjects size is invalid curPtr: " + << curPtr << " endPtr: " << endPtr; } }); } @@ -327,8 +339,10 @@ void NonMovableSpace::IterateOverObjects(const std::functionAvailable(); } - LOG_IF(objSize == 0, FATAL, RUNTIME) << "NonMovableSpace IterateOverObjects objSize==0 invalid: " << curPtr; curPtr += AlignUp(objSize, sizeof(JSTaggedType)); + LOG_IF(objSize == 0, FATAL, RUNTIME) << "NonMovableSpace IterateOverObjects objSize==0 invalid: " << curPtr; + LOG_IF(curPtr > endPtr, FATAL, RUNTIME) << "NonMovableSpace IterateOverObjects size is invalid curPtr: " + << curPtr << " endPtr: " << endPtr; } }); } diff --git a/ecmascript/mem/verification.cpp b/ecmascript/mem/verification.cpp index dac8f084b8..6df379906c 100644 --- a/ecmascript/mem/verification.cpp +++ b/ecmascript/mem/verification.cpp @@ -29,14 +29,14 @@ void VerifyObjectVisitor::VisitAllObjects(TaggedObject *obj) for (ObjectSlot slot = start; slot < end; slot++) { JSTaggedValue value(slot.GetTaggedType()); if (value.IsWeak()) { - if (!HEAP->IsLive(value.GetTaggedWeakRef())) { + if (!heap_->IsLive(value.GetTaggedWeakRef())) { LOG(ERROR, RUNTIME) << "Heap verify detected a dead object at " << value.GetTaggedObject(); - ++(*FAIL_COUNT); + ++(*failCount_); } } else if (value.IsHeapObject()) { - if (!HEAP->IsLive(value.GetTaggedObject())) { + if (!heap_->IsLive(value.GetTaggedObject())) { LOG(ERROR, RUNTIME) << "Heap verify detected a dead object at " << value.GetTaggedObject(); - ++(*FAIL_COUNT); + ++(*failCount_); } } } diff --git a/ecmascript/mem/verification.h b/ecmascript/mem/verification.h index 99e6cba7eb..49af334faa 100644 --- a/ecmascript/mem/verification.h +++ b/ecmascript/mem/verification.h @@ -29,7 +29,7 @@ namespace panda::ecmascript { class VerifyObjectVisitor { public: VerifyObjectVisitor(const Heap *heap, size_t *failCount) - : HEAP(heap), FAIL_COUNT(failCount), rootManager_(heap->GetEcmaVM()) + : heap_(heap), failCount_(failCount), rootManager_(heap->GetEcmaVM()) { } ~VerifyObjectVisitor() = default; @@ -41,14 +41,14 @@ public: size_t GetFailedCount() const { - return *FAIL_COUNT; + return *failCount_; } +private: void VisitAllObjects(TaggedObject *obj); -private: - const Heap * const HEAP{nullptr}; - size_t * const FAIL_COUNT{nullptr}; + const Heap * const heap_{nullptr}; + size_t * const failCount_{nullptr}; HeapRootManager rootManager_; }; @@ -57,20 +57,20 @@ public: explicit Verification(const Heap *heap) : heap_(heap), rootManager_(heap->GetEcmaVM()) {} ~Verification() = default; - bool IsHeapAddress(void *addr) const; - size_t VerifyRoot() const; - - size_t VerifyHeap() const; - size_t VerifyAll() const { - return VerifyRoot() + VerifyHeap(); + size_t result = VerifyRoot(); + result += VerifyHeap(); + return result; } + bool IsHeapAddress(void *addr) const; + size_t VerifyRoot() const; + size_t VerifyHeap() const; +private: NO_COPY_SEMANTIC(Verification); NO_MOVE_SEMANTIC(Verification); -private: const Heap *heap_{nullptr}; HeapRootManager rootManager_; }; -- Gitee