diff --git a/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp index 81ce3b244e876fe0fc9a3625b3602aed54bd3c44..e67136aa3073dfbf46dc6f76b21109d633010ac4 100644 --- a/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp @@ -16,12 +16,13 @@ #include "ecmascript/compiler/builtins/builtins_array_stub_builder.h" #include "ecmascript/builtins/builtins_string.h" +#include "ecmascript/compiler/access_object_stub_builder.h" #include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h" #include "ecmascript/compiler/call_stub_builder.h" #include "ecmascript/compiler/new_object_stub_builder.h" #include "ecmascript/js_array_iterator.h" #include "ecmascript/js_iterator.h" -#include "ecmascript/compiler/access_object_stub_builder.h" +#include "ecmascript/platform/dfx_hisys_event.h" namespace panda::ecmascript::kungfu { @@ -5218,6 +5219,7 @@ void BuiltinsArrayStubBuilder::FlatMap(GateRef glue, GateRef thisValue, GateRef DEFVARIABLE(i, VariableType::INT64(), Int64(0)); DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); DEFVARIABLE(newArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); + DEFVARIABLE(flag, VariableType::BOOL(), Boolean(false)); GateRef mappedArray = NewArray(glue, *thisArrLen); GateRef mappedElements = GetElementsArray(glue, mappedArray); // fast path for stable array @@ -5417,7 +5419,16 @@ void BuiltinsArrayStubBuilder::FlatMap(GateRef glue, GateRef thisValue, GateRef BRANCH_NO_WEIGHT(TaggedIsHeapObject(retValue), &retValueIsHeapObject, &retValueIsNotJsArray); Bind(&retValueIsHeapObject); { - BRANCH_NO_WEIGHT(IsJsArray(glue, retValue), &retValueIsJsArray, &retValueIsNotJsArray); + Label checkProxy(env); + Label isProxy(env); + BRANCH_NO_WEIGHT(IsJsArray(glue, retValue), &retValueIsJsArray, &checkProxy); + Bind(&checkProxy); + BRANCH_UNLIKELY(IsJsProxy(glue, retValue), &isProxy, &retValueIsNotJsArray); + Bind(&isProxy); + { + flag = Boolean(true); + Jump(&retValueIsNotJsArray); + } Bind(&retValueIsJsArray); { Label retValueIsStableArray(env); @@ -5473,6 +5484,16 @@ void BuiltinsArrayStubBuilder::FlatMap(GateRef glue, GateRef thisValue, GateRef i = Int64Add(*i, Int64(1)); LoopEnd(&loopHead2); Bind(&loopExit2); + Label reportHiEvent(env); + Label next(env); + BRANCH_UNLIKELY(*flag, &reportHiEvent, &next); + Bind(&reportHiEvent); + { + CallRuntime(glue, RTSTUB_ID(ReportHiEvents), { + Int32(static_cast(DFXHiSysEvent::IncompatibleType::ARRAY_FLATMAP))}); + Jump(&next); + } + Bind(&next); Label trim(env); Label noTrim(env); BRANCH(Int32GreaterThan(*newArrLen, *j), &trim, &noTrim); diff --git a/ecmascript/platform/dfx_hisys_event.h b/ecmascript/platform/dfx_hisys_event.h index ad8642960c48c57c32566a9a6e7a69be004486f5..a0c19a448127f9d31bf25bf6b91f7b2c89630da9 100644 --- a/ecmascript/platform/dfx_hisys_event.h +++ b/ecmascript/platform/dfx_hisys_event.h @@ -16,6 +16,7 @@ #ifndef ECMASCRIPT_PLATFORM_DFX_HISYS_EVENT_H #define ECMASCRIPT_PLATFORM_DFX_HISYS_EVENT_H +#include "ecmascript/js_thread.h" #include "ecmascript/mem/long_gc_stats.h" #include "ecmascript/mem/mem_common.h" @@ -23,8 +24,16 @@ namespace panda::ecmascript { class DFXHiSysEvent { public: + enum class IncompatibleType : uint8_t { + ARRAY_FLATMAP = 0, + }; + + static constexpr int32_t MAX_REPORT_COUNT = 5; + static void SendLongGCEvent(LongGCStats *longGCStats); + static void SendRuntimeIncompatibleEvent(JSThread *thread, IncompatibleType type); + static bool IsEnableDFXHiSysEvent(); static double GetCpuUsage(); diff --git a/ecmascript/platform/unix/linux/dfx_hisys_event.cpp b/ecmascript/platform/unix/linux/dfx_hisys_event.cpp index 1af67d5c945b41b21436be9c81e3d7a5551f2695..0ccb420dbfc542756bbedf26fbf9fb17353b28b0 100644 --- a/ecmascript/platform/unix/linux/dfx_hisys_event.cpp +++ b/ecmascript/platform/unix/linux/dfx_hisys_event.cpp @@ -25,6 +25,12 @@ void DFXHiSysEvent::SendLongGCEvent([[maybe_unused]]LongGCStats *longGCStats) LOG_GC(FATAL) << "Send LongGCEvent is not support in linux."; } +void DFXHiSysEvent::SendRuntimeIncompatibleEvent([[maybe_unused]] JSThread *thread, + [[maybe_unused]] IncompatibleType type) +{ + LOG_ECMA(WARN) << "Send RuntimeIncompatibleEvent is not support in linux."; +} + bool DFXHiSysEvent::IsEnableDFXHiSysEvent() { return false; diff --git a/ecmascript/platform/unix/mac/dfx_hisys_event.cpp b/ecmascript/platform/unix/mac/dfx_hisys_event.cpp index 55ec7fe7abc6b063e1a65ea3596daf5d43112dfd..ce57066fb49bcd90c10e2b8f0595d0054a528d8a 100644 --- a/ecmascript/platform/unix/mac/dfx_hisys_event.cpp +++ b/ecmascript/platform/unix/mac/dfx_hisys_event.cpp @@ -25,6 +25,12 @@ void DFXHiSysEvent::SendLongGCEvent([[maybe_unused]]LongGCStats *longGCStats) LOG_GC(FATAL) << "Send LongGCEvent is not support in macos/ios."; } +void DFXHiSysEvent::SendRuntimeIncompatibleEvent([[maybe_unused]] JSThread *thread, + [[maybe_unused]] IncompatibleType type) +{ + LOG_ECMA(WARN) << "Send RuntimeIncompatibleEvent is not support in macos/ios."; +} + bool DFXHiSysEvent::IsEnableDFXHiSysEvent() { return false; diff --git a/ecmascript/platform/unix/ohos/dfx_hisys_event.cpp b/ecmascript/platform/unix/ohos/dfx_hisys_event.cpp index 8a71d899e165dea763a135f25bc48b98f5956c34..36fe946915403f7fc2dbe9d496723adca9eb2cc3 100644 --- a/ecmascript/platform/unix/ohos/dfx_hisys_event.cpp +++ b/ecmascript/platform/unix/ohos/dfx_hisys_event.cpp @@ -14,6 +14,7 @@ */ #include "ecmascript/platform/dfx_hisys_event.h" +#include "ecmascript/dfx/stackinfo/js_stackinfo.h" #ifdef ENABLE_HISYSEVENT #include "hisysevent.h" #endif @@ -22,6 +23,7 @@ #endif #include "ecmascript/pgo_profiler/pgo_profiler_manager.h" #include "ecmascript/log_wrapper.h" +#include "ecmascript/runtime.h" namespace panda::ecmascript { using PGOProfilerManager = pgo::PGOProfilerManager; @@ -79,6 +81,38 @@ void DFXHiSysEvent::SendLongGCEvent([[maybe_unused]] LongGCStats *longGCStats) #endif } +void DFXHiSysEvent::SendRuntimeIncompatibleEvent([[maybe_unused]] JSThread *thread, + [[maybe_unused]] IncompatibleType type) +{ +#ifdef ENABLE_HISYSEVENT + std::string functionName; + switch (type) { + case IncompatibleType::ARRAY_FLATMAP: + functionName = "Array.prototype.flatMap"; + break; + default: + LOG_ECMA(FATAL) << "this branch is unreachable, type:" << static_cast(type); + break; + } + LOG_ECMA(DEBUG) << "SendRuntimeIncompatibleEvent: functionName" << functionName; + uint32_t eventCount = Runtime::GetInstance()->AddIncompatibleEvent(type); + if (eventCount > MAX_REPORT_COUNT) { + LOG_ECMA(DEBUG) << functionName << " has report more than " << DFXHiSysEvent::MAX_REPORT_COUNT; + return ; + } + std::string stack = JsStackInfo::BuildJsStackTrace(thread, true, false, 1); + std::string bundleName = ConvertToStdString(thread->GetEcmaVM()->GetBundleName()); + int32_t ret = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::ARKTS_RUNTIME, + "ARK_RUNTIME_INCOMPATIBLE", OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR, + "FUNCTIONNAME", functionName, + "STACK", stack, + "BUNDLENAME", bundleName); + if (ret != 0) { + LOG_ECMA(ERROR) << "HiSysEventWrite RuntimeIncompatibleEvent Failed! ret = " << ret; + } +#endif +} + bool DFXHiSysEvent::IsEnableDFXHiSysEvent() { return true; diff --git a/ecmascript/platform/windows/dfx_hisys_event.cpp b/ecmascript/platform/windows/dfx_hisys_event.cpp index 24392d46f905ff8e6e28b4412ba4cfb5df8d7225..242ca83b494a5bd007246c07329aee3f8159bda4 100644 --- a/ecmascript/platform/windows/dfx_hisys_event.cpp +++ b/ecmascript/platform/windows/dfx_hisys_event.cpp @@ -25,6 +25,12 @@ void DFXHiSysEvent::SendLongGCEvent([[maybe_unused]]LongGCStats *longGCStats) LOG_GC(FATAL) << "Send LongGCEvent is not support in windows."; } +void DFXHiSysEvent::SendRuntimeIncompatibleEvent([[maybe_unused]] JSThread *thread, + [[maybe_unused]] IncompatibleType type) +{ + LOG_ECMA(WARN) << "Send RuntimeIncompatibleEvent is not support in windows."; +} + bool DFXHiSysEvent::IsEnableDFXHiSysEvent() { return false; diff --git a/ecmascript/runtime.h b/ecmascript/runtime.h index 1878fc9d85be848a416c268cc15cfb124a4158c5..c72d58fa8bbb0d20873d2e4ff8a99d467f13416d 100644 --- a/ecmascript/runtime.h +++ b/ecmascript/runtime.h @@ -25,6 +25,7 @@ #include "ecmascript/mem/visitor.h" #include "ecmascript/module/js_shared_module_manager.h" #include "ecmascript/mutator_lock.h" +#include "ecmascript/platform/dfx_hisys_event.h" #include "ecmascript/platform/mutex.h" #include "ecmascript/serializer/serialize_chunk.h" @@ -307,6 +308,12 @@ public: { isHybridVm_ = isHybridVm; } + + uint32_t AddIncompatibleEvent(DFXHiSysEvent::IncompatibleType type) + { + WriteLockHolder lock(incompatibleEventLock_); + return ++incompatibleEventMap_[type]; + } private: static constexpr int32_t WORKER_DESTRUCTION_COUNT = 3; @@ -375,6 +382,9 @@ private: std::set freeSharedConstpoolIndex_ {}; // reuse shared constpool index. bool postForked_ {false}; + CMap incompatibleEventMap_; + RWLock incompatibleEventLock_; + // Runtime instance and VMs creation. static int32_t vmCount_; static int32_t destroyCount_; diff --git a/ecmascript/stubs/runtime_stub_list.h b/ecmascript/stubs/runtime_stub_list.h index f9dcd9c4f06b3c5bc5c9b67061685cdd4bbf862a..f45061e802737ddffa741399f071b997f7029ef5 100644 --- a/ecmascript/stubs/runtime_stub_list.h +++ b/ecmascript/stubs/runtime_stub_list.h @@ -424,7 +424,8 @@ namespace panda::ecmascript { V(FunctionPrototypeBind) \ V(FunctionPrototypeCall) \ V(SuperCallForwardAllArgs) \ - V(OptSuperCallForwardAllArgs) + V(OptSuperCallForwardAllArgs) \ + V(ReportHiEvents) // When ASM enters C++ via CallRuntime, if the C++ process requires GetGlobalEnv(), // the current globalenv in ASM must be set to glue before CallRuntime! diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index a4b7e002afaf4a91ba3ffe6666b8469d6bfe23e2..34ee4fe851ba7d32e78b0cfa272fb2bbe04db5bc 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -50,6 +50,7 @@ #include "ecmascript/module/module_path_helper.h" #include "common_components/heap/allocator/region_desc.h" #include "common_components/mutator/mutator.h" +#include "ecmascript/platform/dfx_hisys_event.h" #ifdef ARK_SUPPORT_INTL #include "ecmascript/js_collator.h" #include "ecmascript/js_locale.h" @@ -1129,6 +1130,15 @@ DEF_RUNTIME_STUBS(OptSuperCallForwardAllArgs) return RuntimeSuperCallForwardAllArgs(thread, sp, superFunc, newTarget, restNumArgs, startIdx).GetRawData(); } +DEF_RUNTIME_STUBS(ReportHiEvents) +{ + RUNTIME_STUBS_HEADER(ReportHiEvents); + DFXHiSysEvent::IncompatibleType type = static_cast( + GetHArg(argv, argc, 0)->GetInt()); + DFXHiSysEvent::SendRuntimeIncompatibleEvent(thread, type); + return JSTaggedValue(true).GetRawData(); +} + DEF_RUNTIME_STUBS(GetCallSpreadArgs) { RUNTIME_STUBS_HEADER(GetCallSpreadArgs); diff --git a/hisysevent.yaml b/hisysevent.yaml index 0fae0a86561ffc568b6d4775d85cbbc98b3f9a96..67d27552517f2a202df93e66d2d14ab86ac6c8da 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -104,4 +104,10 @@ ARK_BLOCKUI_JIT: JIT_TYPE: {type: STRING, desc: Triggered jit type} JIT_FUNCTION_NAME: {type: STRING, desc: JIT compiled function name} TIME_ON_MAIN_THREAD: {type: INT32, desc: The time occupied by JIT on the main thread} - TIME_ON_JIT_THREAD: {type: INT32, desc: The time occupied on JIT thread} \ No newline at end of file + TIME_ON_JIT_THREAD: {type: INT32, desc: The time occupied on JIT thread} + +ARK_RUNTIME_INCOMPATIBLE: + __BASE: {type: STATISTIC, level: MINOR, desc: ARKTSRUNTIME INCOMPATIBLE EVENT, preserve: true} + FUNCTIONNAME: {type: STRING, desc: Name of the incompatible function} + STACK: {type: STRING, desc: Function call stack} + BUNDLE_NAME: {type: STRING, desc: Application bundle name}