diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index a11ce6bcef03d2cd98ac9130ed8240eca780ba04..3828b14ec58cb9ebd24f4f0379d956f46bdcc2a2 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -101,7 +101,6 @@ set(ECMASCRIPT_SOURCES ${ECMA_SRC_DIR}/ecma_exceptions.cpp ${ECMA_SRC_DIR}/ecma_language_context.cpp ${ECMA_SRC_DIR}/ecma_module.cpp - ${ECMA_SRC_DIR}/ecma_profiling.cpp ${ECMA_SRC_DIR}/ecma_string.cpp ${ECMA_SRC_DIR}/ecma_string_table.cpp ${ECMA_SRC_DIR}/ecma_vm.cpp diff --git a/runtime/ecma_profiling.cpp b/runtime/ecma_profiling.cpp deleted file mode 100644 index df626318d62ebd1bf7574e515cf0b0819a1efc9c..0000000000000000000000000000000000000000 --- a/runtime/ecma_profiling.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2022 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. - */ - -#include "ecma_profiling.h" -#include "plugins/ecmascript/runtime/js_hclass.h" -#include "plugins/ecmascript/runtime/mem/tagged_object-inl.h" -#include "plugins/ecmascript/runtime/js_function.h" - -namespace panda::ecmascript { -ProfilingIndexedAccessBits::Type GetObjectTypeFromValue(JSTaggedValue value) -{ - if (!value.IsHeapObject()) { - return ProfilingIndexedAccessBits::NOT_HEAP_OBJECT_ACCESS; - } - auto *hclass = value.GetTaggedObject()->GetClass(); - JSType js_type = hclass->GetObjectType(); - - if (js_type > JSType::JS_ARRAY || hclass->IsDictionaryElement()) { - return ProfilingIndexedAccessBits::OBJECT_ACCESS; - } - return ProfilingIndexedAccessBits::OBJECT_ARRAY_ACCESS; -} -} // namespace panda::ecmascript \ No newline at end of file diff --git a/runtime/ecma_profiling.h b/runtime/ecma_profiling.h index ac13ed73debe34521f073769e9b6d2a003186f81..1124d174dbedeac49dea90d88c4c475f704a348d 100644 --- a/runtime/ecma_profiling.h +++ b/runtime/ecma_profiling.h @@ -244,9 +244,9 @@ public: return ProfilingIndexedAccess(GetOperandType()); } - static void Update(Base::ValueType *data, JSTaggedValue value) + static void Update(void *data, ProfilingIndexedAccessBits::Type access_type) { - *data |= OperandType::Encode(GetObjectTypeFromValue(value)); + *(reinterpret_cast(data)) |= OperandType::Encode(access_type); } protected: diff --git a/runtime/interpreter/ecma-interpreter-inl.h b/runtime/interpreter/ecma-interpreter-inl.h index 30f32cee99fdde6981eaab72120ce2a521281be9..a6f2a7b7f4c93950ebda9b1d0c478f1cb867c663 100644 --- a/runtime/interpreter/ecma-interpreter-inl.h +++ b/runtime/interpreter/ecma-interpreter-inl.h @@ -82,14 +82,6 @@ namespace panda::ecmascript { UNUSED_VAR(rhs); \ } -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define UPDATE_OBJ_BY_INDEX_PROFILE(lhs) \ - if constexpr (IS_PROFILE_ENABLED) { \ - UpdateObjByIndexProfile(lhs); \ - } else { \ - UNUSED_VAR(lhs); \ - } - // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define UPDATE_CALL_PROFILE(func) \ if constexpr (IS_PROFILE_ENABLED) { \ @@ -98,6 +90,14 @@ namespace panda::ecmascript { UNUSED_VAR(func); \ } +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define GET_PROFILE_ADDRESS(addr) \ + if constexpr (IS_PROFILE_ENABLED) { \ + addr = GetProfileAddress(); \ + } else { \ + addr = nullptr; \ + } + template class JSFrameHelper { public: @@ -2172,9 +2172,9 @@ public: << " imm" << idx; uint64_t obj = GetAccAsTaggedValue().GetRawData(); - UPDATE_OBJ_BY_INDEX_PROFILE(obj); - - INTRINSIC_CALL_CHECK_SETACC(intrinsics::LdObjByIndex(this->GetJSThread(), idx, obj)); + void *prof_address; + GET_PROFILE_ADDRESS(prof_address); + INTRINSIC_CALL_CHECK_SETACC(intrinsics::LdObjByIndex(this->GetJSThread(), idx, obj, prof_address)); this->template MoveToNextInst(); } @@ -2188,10 +2188,10 @@ public: uint64_t obj = GetRegAsTaggedValue(v0).GetRawData(); uint64_t value = GetAccAsTaggedValue().GetRawData(); - UPDATE_OBJ_BY_INDEX_PROFILE(obj); - + void *prof_address; + GET_PROFILE_ADDRESS(prof_address); SaveAccToFrame(); - INTRINSIC_CALL_CHECK(intrinsics::StObjByIndex(this->GetJSThread(), idx, obj, value)); + INTRINSIC_CALL_CHECK(intrinsics::StObjByIndex(this->GetJSThread(), idx, obj, value, prof_address)); RestoreAccFromFrame(); this->template MoveToNextInst(); } @@ -2791,12 +2791,12 @@ public: return JSThread::Cast(this->GetThread()); } - void UpdateObjByIndexProfile(coretypes::TaggedType value) + void *GetProfileAddress() { auto method = static_cast(this->GetFrame()->GetMethod()); // Profiling is not initialized if (method->GetProfileSize() == 0) { - return; + return nullptr; } auto prof_data = method->GetProfilingVector(); auto prof_id = this->GetInst().GetProfileId(); @@ -2804,7 +2804,8 @@ public: // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) auto prof_value = reinterpret_cast(&prof_data[prof_id]); ASSERT(method->GetProfileSize() > helpers::ToUnsigned(prof_id)); - ObjByIndexOperationProfile::Update(prof_value, JSTaggedValue(value)); + + return prof_value; } void UpdateUnaryArithProfile(coretypes::TaggedType value) diff --git a/runtime/interpreter/fast_runtime_stub-inl.h b/runtime/interpreter/fast_runtime_stub-inl.h index b83c0c384805709adf2f79a20182c4324d072724..191a58a89ead1855808bba41fb1a8b20914d1c71 100644 --- a/runtime/interpreter/fast_runtime_stub-inl.h +++ b/runtime/interpreter/fast_runtime_stub-inl.h @@ -18,6 +18,7 @@ #include "plugins/ecmascript/runtime/interpreter/fast_runtime_stub.h" +#include "plugins/ecmascript/runtime/ecma_profiling.h" #include "plugins/ecmascript/runtime/global_dictionary-inl.h" #include "plugins/ecmascript/runtime/global_env.h" #include "plugins/ecmascript/runtime/internal_call_params.h" @@ -33,6 +34,13 @@ #include "plugins/ecmascript/runtime/vmstat/runtime_stat.h" namespace panda::ecmascript { + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define SET_PROFILING_ACCESS(access) \ + if (prof != nullptr) { \ + ObjByIndexOperationProfile::Update(prof, access); \ + } + JSTaggedValue FastRuntimeStub::FastAdd(JSTaggedValue left, JSTaggedValue right) { if (left.IsNumber() && right.IsNumber()) { @@ -308,7 +316,7 @@ JSTaggedValue FastRuntimeStub::AddPropertyByIndex(JSThread *thread, JSTaggedValu } template -JSTaggedValue FastRuntimeStub::GetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index) +JSTaggedValue FastRuntimeStub::GetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index, void *prof) { INTERPRETER_TRACE(thread, GetPropertyByIndex); [[maybe_unused]] EcmaHandleScope handle_scope(thread); @@ -317,6 +325,7 @@ JSTaggedValue FastRuntimeStub::GetPropertyByIndex(JSThread *thread, JSTaggedValu auto *hclass = holder.GetTaggedObject()->GetClass(); JSType js_type = hclass->GetObjectType(); if (IsSpecialIndexedObj(js_type)) { + SET_PROFILING_ACCESS(ProfilingIndexedAccessBits::OBJECT_ACCESS); if (IsSpecialContainer(js_type)) { return GetContainerProperty(thread, holder, index, js_type); } @@ -329,12 +338,15 @@ JSTaggedValue FastRuntimeStub::GetPropertyByIndex(JSThread *thread, JSTaggedValu if (index < elements->GetLength()) { JSTaggedValue value = elements->Get(index); if (!value.IsHole()) { + SET_PROFILING_ACCESS(ProfilingIndexedAccessBits::OBJECT_ARRAY_ACCESS); return value; } } else { + SET_PROFILING_ACCESS(ProfilingIndexedAccessBits::OBJECT_ACCESS); return JSTaggedValue::Hole(); } } else { + SET_PROFILING_ACCESS(ProfilingIndexedAccessBits::OBJECT_ACCESS); NumberDictionary *dict = NumberDictionary::Cast(elements); int entry = dict->FindEntry(JSTaggedValue(static_cast(index))); if (entry != -1) { @@ -352,7 +364,7 @@ JSTaggedValue FastRuntimeStub::GetPropertyByIndex(JSThread *thread, JSTaggedValu } holder = JSObject::Cast(holder)->GetJSHClass()->GetPrototype(); } while (holder.IsHeapObject()); - + SET_PROFILING_ACCESS(ProfilingIndexedAccessBits::OBJECT_ACCESS); // not found return JSTaggedValue::Undefined(); } @@ -522,7 +534,7 @@ JSTaggedValue FastRuntimeStub::SetPropertyByName(JSThread *thread, JSTaggedValue template JSTaggedValue FastRuntimeStub::SetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index, - JSTaggedValue value) + JSTaggedValue value, void *prof) { INTERPRETER_TRACE(thread, SetPropertyByIndex); JSTaggedValue holder = receiver; @@ -530,6 +542,8 @@ JSTaggedValue FastRuntimeStub::SetPropertyByIndex(JSThread *thread, JSTaggedValu auto *hclass = holder.GetTaggedObject()->GetClass(); JSType js_type = hclass->GetObjectType(); if (IsSpecialIndexedObj(js_type)) { + SET_PROFILING_ACCESS(ProfilingIndexedAccessBits::OBJECT_ACCESS); + if (IsSpecialContainer(js_type)) { return SetContainerProperty(thread, holder, index, value, js_type); } @@ -544,10 +558,12 @@ JSTaggedValue FastRuntimeStub::SetPropertyByIndex(JSThread *thread, JSTaggedValu if (index < elements->GetLength()) { if (!elements->Get(index).IsHole()) { elements->Set(thread, index, value); + SET_PROFILING_ACCESS(ProfilingIndexedAccessBits::OBJECT_ARRAY_ACCESS); return JSTaggedValue::Undefined(); } } } else { + SET_PROFILING_ACCESS(ProfilingIndexedAccessBits::OBJECT_ACCESS); return JSTaggedValue::Hole(); } if (USE_OWN) { @@ -556,6 +572,7 @@ JSTaggedValue FastRuntimeStub::SetPropertyByIndex(JSThread *thread, JSTaggedValu holder = JSObject::Cast(holder)->GetJSHClass()->GetPrototype(); } while (holder.IsHeapObject()); + SET_PROFILING_ACCESS(ProfilingIndexedAccessBits::OBJECT_ACCESS); return AddPropertyByIndex(thread, receiver, index, value); } diff --git a/runtime/interpreter/fast_runtime_stub.h b/runtime/interpreter/fast_runtime_stub.h index 7548d54d2126a245869861fa9066a660969fe602..64f48d3a7974cd5ea8f16660f494dc0c43c2573c 100644 --- a/runtime/interpreter/fast_runtime_stub.h +++ b/runtime/interpreter/fast_runtime_stub.h @@ -76,7 +76,8 @@ public: static inline JSTaggedValue GetPropertyByValue(JSThread *thread, JSHandle receiver, JSHandle key); template - static inline JSTaggedValue GetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index); + static inline JSTaggedValue GetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index, + void *prof = nullptr); template static inline JSTaggedValue SetPropertyByName(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key, JSTaggedValue value); @@ -85,7 +86,7 @@ public: JSHandle key, JSHandle value); template static inline JSTaggedValue SetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index, - JSTaggedValue value); + JSTaggedValue value, void *prof = nullptr); static inline bool FastSetPropertyByValue(JSThread *thread, JSHandle receiver, JSHandle key, JSHandle value); diff --git a/runtime/intrinsics-inl.h b/runtime/intrinsics-inl.h index e8900cb441cbd057ebe8e518d0fd779d0ca879c6..5556ccc741c62cedea062213140ad83dca5e4193 100644 --- a/runtime/intrinsics-inl.h +++ b/runtime/intrinsics-inl.h @@ -1123,12 +1123,12 @@ INLINE_ECMA_INTRINSICS uint64_t StObjByName(JSThread *thread, uint32_t string_id } // NOLINTNEXTLINE(misc-definitions-in-headers) -INLINE_ECMA_INTRINSICS uint64_t LdObjByIndex(JSThread *thread, uint32_t idx, uint64_t uobj) +INLINE_ECMA_INTRINSICS uint64_t LdObjByIndex(JSThread *thread, uint32_t idx, uint64_t uobj, void *prof = nullptr) { // fast path [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter(); if (LIKELY(JSTaggedValue(uobj).IsHeapObject())) { - JSTaggedValue res = FastRuntimeStub::GetPropertyByIndex(thread, JSTaggedValue(uobj), idx); + JSTaggedValue res = FastRuntimeStub::GetPropertyByIndex(thread, JSTaggedValue(uobj), idx, prof); if (!res.IsHole()) { return res.GetRawData(); } @@ -1141,12 +1141,14 @@ INLINE_ECMA_INTRINSICS uint64_t LdObjByIndex(JSThread *thread, uint32_t idx, uin } // NOLINTNEXTLINE(misc-definitions-in-headers) -INLINE_ECMA_INTRINSICS uint64_t StObjByIndex(JSThread *thread, uint32_t idx, uint64_t uobj, uint64_t uval) +INLINE_ECMA_INTRINSICS uint64_t StObjByIndex(JSThread *thread, uint32_t idx, uint64_t uobj, uint64_t uval, + void *prof = nullptr) { // fast path [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter(); if (JSTaggedValue(uobj).IsHeapObject()) { - JSTaggedValue res = FastRuntimeStub::SetPropertyByIndex(thread, JSTaggedValue(uobj), idx, JSTaggedValue(uval)); + JSTaggedValue res = + FastRuntimeStub::SetPropertyByIndex(thread, JSTaggedValue(uobj), idx, JSTaggedValue(uval), prof); if (!res.IsHole()) { return res.GetRawData(); } diff --git a/subproject_sources.gn b/subproject_sources.gn index 5cc102be3e6f1ba2f0c0b8e6b346917447a0f22b..96121b6ff190825359601e054c651f697145be8a 100644 --- a/subproject_sources.gn +++ b/subproject_sources.gn @@ -130,7 +130,6 @@ srcs_runtime = [ "runtime/ecma_exceptions.cpp", "runtime/ecma_language_context.cpp", "runtime/ecma_module.cpp", - "runtime/ecma_profiling.cpp", "runtime/ecma_string.cpp", "runtime/ecma_string_table.cpp", "runtime/ecma_vm.cpp",