From 0b17d30ad1745a817d4d719a406b5bddb1b0fb54 Mon Sep 17 00:00:00 2001 From: dov1s Date: Mon, 21 Oct 2024 16:18:04 +0800 Subject: [PATCH 001/185] Refactoring Inline Cache Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAYLFA Signed-off-by: dov1s Change-Id: I2201d8e765a64e7dbb044268f4515ea02707b835 --- BUILD.gn | 2 - ecmascript/ic/ic_binary_op.h | 381 ------------------ ecmascript/ic/ic_compare_op.cpp | 461 --------------------- ecmascript/ic/ic_compare_op.h | 78 ---- ecmascript/ic/invoke_cache.cpp | 167 -------- ecmascript/ic/invoke_cache.h | 51 --- ecmascript/ic/tests/BUILD.gn | 3 - ecmascript/ic/tests/ic_binaryop_test.cpp | 381 ------------------ ecmascript/ic/tests/ic_compareop_test.cpp | 462 ---------------------- ecmascript/ic/tests/ic_invoke_test.cpp | 129 ------ ecmascript/runtime_call_id.h | 19 - 11 files changed, 2134 deletions(-) delete mode 100644 ecmascript/ic/ic_binary_op.h delete mode 100644 ecmascript/ic/ic_compare_op.cpp delete mode 100644 ecmascript/ic/ic_compare_op.h delete mode 100644 ecmascript/ic/invoke_cache.cpp delete mode 100644 ecmascript/ic/invoke_cache.h delete mode 100644 ecmascript/ic/tests/ic_binaryop_test.cpp delete mode 100644 ecmascript/ic/tests/ic_compareop_test.cpp delete mode 100644 ecmascript/ic/tests/ic_invoke_test.cpp diff --git a/BUILD.gn b/BUILD.gn index 41fbfe93aa..b0e799aee4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -719,8 +719,6 @@ ecma_source = [ "ecmascript/global_env.cpp", "ecmascript/global_env_constants.cpp", "ecmascript/ic/ic_runtime.cpp", - "ecmascript/ic/ic_compare_op.cpp", - "ecmascript/ic/invoke_cache.cpp", "ecmascript/ic/profile_type_info.cpp", "ecmascript/ic/property_box.cpp", "ecmascript/ic/proto_change_details.cpp", diff --git a/ecmascript/ic/ic_binary_op.h b/ecmascript/ic/ic_binary_op.h deleted file mode 100644 index c204659a3a..0000000000 --- a/ecmascript/ic/ic_binary_op.h +++ /dev/null @@ -1,381 +0,0 @@ -/* - * 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_IC_IC_BINARY_OP_H_ -#define ECMASCRIPT_IC_IC_BINARY_OP_H_ - -#include "ecmascript/ic/profile_type_info.h" -#include "ecmascript/interpreter/slow_runtime_stub.h" -#include "ecmascript/js_tagged_value.h" -#include "ecmascript/property_attributes.h" -#include "ecmascript/runtime_call_id.h" - -namespace panda::ecmascript { -enum class BinaryType : uint8_t { - NUMBER, - NUMBER_GEN, - STRING, - STRING_GEN, - GENERIC, -}; - -class ICBinaryOP { -public: - static inline JSTaggedValue AddWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, AddWithTSType); - BinaryType addType = static_cast(argType.GetInt()); - switch (addType) { - // Support cases, such as: int + double, int + int, double + double - case BinaryType::NUMBER: { - double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble(); - double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble(); - double ret = a0Double + a1Double; - return JSTaggedValue(ret); - } - // Support cases, such as: number + null, undefined + null, boolean + number, etc. - case BinaryType::NUMBER_GEN: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - JSHandle primitiveA0(thread, JSTaggedValue::ToPrimitive(thread, leftValue)); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle primitiveA1(thread, JSTaggedValue::ToPrimitive(thread, rightValue)); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - - JSTaggedNumber taggedValueA0 = JSTaggedValue::ToNumber(thread, primitiveA0); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSTaggedNumber taggedValueA1 = JSTaggedValue::ToNumber(thread, primitiveA1); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - double a0Double = taggedValueA0.GetNumber(); - double a1Double = taggedValueA1.GetNumber(); - return JSTaggedValue(a0Double + a1Double); - } - // Support case: string + string. - case BinaryType::STRING: { - JSHandle stringA0 = JSHandle(JSHandle(thread, left)); - JSHandle stringA1 = JSHandle(JSHandle(thread, right)); - EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return JSTaggedValue(ret); - } - // Support cases, such as: string + null, string + object, string + boolean, string + number, etc. - case BinaryType::STRING_GEN: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - if (left.IsString()) { - JSHandle stringA0 = JSHandle(leftValue); - JSHandle stringA1 = JSTaggedValue::ToString(thread, rightValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return JSTaggedValue(ret); - } else { - JSHandle stringA0 = JSTaggedValue::ToString(thread, leftValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle stringA1 = JSHandle(rightValue); - EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return JSTaggedValue(ret); - } - } - // Some special cases, such as: object + undefined, object + boolean, etc. - case BinaryType::GENERIC: { - JSTaggedValue res = SlowRuntimeStub::Add2(thread, left, right); - return res; - } - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - } - - static inline JSTaggedValue SubWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, SubWithTSType); - BinaryType subType = static_cast(argType.GetInt()); - switch (subType) { - // Support int or number - case BinaryType::NUMBER: { - double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble(); - double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble(); - double ret = a0Double - a1Double; - return JSTaggedValue(ret); - } - // Support cases, such as: string like '2333', boolean, null - case BinaryType::GENERIC: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - JSTaggedNumber number0 = JSTaggedValue::ToNumber(thread, leftValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSTaggedNumber number1 = JSTaggedValue::ToNumber(thread, rightValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - auto ret = number0 - number1; - return JSTaggedValue(ret); - } - case BinaryType::NUMBER_GEN: - case BinaryType::STRING: - case BinaryType::STRING_GEN: - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - } - static inline JSTaggedValue MulWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, MulWithTSType); - BinaryType mulType = static_cast(argType.GetInt()); - switch (mulType) { - // Support int or number - case BinaryType::NUMBER: { - return JSTaggedValue(left.GetNumber() * right.GetNumber()); - } - // Support cases, such as: string like '2333', boolean, null - case BinaryType::GENERIC: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - // 6. Let lnum be ToNumber(leftValue). - JSTaggedNumber primitiveA = JSTaggedValue::ToNumber(thread, leftValue); - // 7. ReturnIfAbrupt(lnum). - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - // 8. Let rnum be ToNumber(rightValue). - JSTaggedNumber primitiveB = JSTaggedValue::ToNumber(thread, rightValue); - // 9. ReturnIfAbrupt(rnum). - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - // 12.6.3.1 Applying the * Operator - return primitiveA * primitiveB; - } - case BinaryType::NUMBER_GEN: - case BinaryType::STRING: - case BinaryType::STRING_GEN: - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - } - - static inline JSTaggedValue DivWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, DivWithTSType); - BinaryType divType = static_cast(argType.GetInt()); - switch (divType) { - // Support int or number - case BinaryType::NUMBER: { - double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble(); - double dRight = right.IsInt() ? right.GetInt() : right.GetDouble(); - if (UNLIKELY(dRight == 0.0)) { - if (dLeft == 0.0 || std::isnan(dLeft)) { - return JSTaggedValue(base::NAN_VALUE); - } - uint64_t flagBit = ((base::bit_cast(dLeft)) ^ (base::bit_cast(dRight))) & - base::DOUBLE_SIGN_MASK; - return JSTaggedValue(base::bit_cast( - flagBit ^ (base::bit_cast(base::POSITIVE_INFINITY)))); - } - return JSTaggedValue(dLeft / dRight); - } - // Support special cases, such as: string like '2333', boolean, null - case BinaryType::GENERIC: { - auto res = SlowRuntimeStub::Div2(thread, left, right); - return res; - } - case BinaryType::NUMBER_GEN: - case BinaryType::STRING: - case BinaryType::STRING_GEN: - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - } - - static inline JSTaggedValue ModWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, ModWithTSType); - BinaryType modType = static_cast(argType.GetInt()); - switch (modType) { - // Support int or number - case BinaryType::NUMBER: { - double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble(); - double dRight = right.IsInt() ? right.GetInt() : right.GetDouble(); - if (dRight == 0.0 || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) { - return JSTaggedValue(base::NAN_VALUE); - } - if (dLeft == 0.0 || std::isinf(dRight)) { - return JSTaggedValue(dLeft); - } - return JSTaggedValue(std::fmod(dLeft, dRight)); - } - // Support special cases, such as: string like '2333', boolean, null - case BinaryType::GENERIC: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - JSTaggedNumber leftNumber = JSTaggedValue::ToNumber(thread, leftValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - double dLeft = leftNumber.GetNumber(); - JSTaggedNumber rightNumber = JSTaggedValue::ToNumber(thread, rightValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - double dRight = rightNumber.GetNumber(); - // 12.6.3.3 Applying the % Operator - if ((dRight == 0.0) || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) { - return JSTaggedValue(base::NAN_VALUE); - } - if ((dLeft == 0.0) || std::isinf(dRight)) { - return JSTaggedValue(dLeft); - } - return JSTaggedValue(std::fmod(dLeft, dRight)); - } - case BinaryType::NUMBER_GEN: - case BinaryType::STRING: - case BinaryType::STRING_GEN: - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - } - - static inline void GetBitOPDate(JSThread *thread, JSTaggedValue left, JSTaggedValue right, - int32_t &opNumber0, int32_t &opNumber1, BinaryType opType) - { - INTERPRETER_TRACE(thread, GetBitOPDate); - switch (opType) { - case BinaryType::NUMBER: { - opNumber0 = - left.IsInt() ? left.GetInt() : - base::NumberHelper::DoubleToInt(left.GetDouble(), base::INT32_BITS); - opNumber1 = - right.IsInt() ? right.GetInt() : - base::NumberHelper::DoubleToInt(right.GetDouble(), base::INT32_BITS); - break; - } - // Support special cases, such as: string like '2333', boolean, null - case BinaryType::GENERIC: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - JSTaggedValue taggedNumber0 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, - leftValue.GetTaggedValue()); - JSTaggedValue taggedNumber1 = SlowRuntimeStub::ToJSTaggedValueWithUint32(thread, - rightValue.GetTaggedValue()); - opNumber0 = taggedNumber0.GetInt(); - opNumber1 = taggedNumber1.GetInt(); - break; - } - case BinaryType::NUMBER_GEN: - case BinaryType::STRING: - case BinaryType::STRING_GEN: - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - return; - } - - static inline JSTaggedValue ShlWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, ShlWithTSType); - BinaryType shlType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, shlType); - uint32_t shift = - static_cast(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers) - using unsigned_type = std::make_unsigned_t; - auto ret = - static_cast(static_cast(opNumber0) << shift); // NOLINT(hicpp-signed-bitwise) - return JSTaggedValue(ret); - } - - static inline JSTaggedValue ShrWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, ShrWithTSType); - BinaryType shrType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, shrType); - uint32_t shift = - static_cast(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers) - auto ret = static_cast(opNumber0 >> shift); // NOLINT(hicpp-signed-bitwise) - return JSTaggedValue(ret); - } - - static inline JSTaggedValue AshrWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, AshrWithTSType); - BinaryType ashrType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, ashrType); - uint32_t shift = - static_cast(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers) - using unsigned_type = std::make_unsigned_t; - auto ret = - static_cast(static_cast(opNumber0) >> shift); // NOLINT(hicpp-signed-bitwise) - return JSTaggedValue(ret); - } - - static inline JSTaggedValue AndWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, AndWithTSType); - BinaryType andType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, andType); - // NOLINT(hicpp-signed-bitwise) - auto ret = static_cast(opNumber0) & static_cast(opNumber1); - return JSTaggedValue(ret); - } - - static inline JSTaggedValue OrWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, OrWithTSType); - BinaryType orType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, orType); - // NOLINT(hicpp-signed-bitwise) - auto ret = static_cast(opNumber0) | static_cast(opNumber1); - return JSTaggedValue(ret); - } - - static inline JSTaggedValue XorWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, XorWithTSType); - BinaryType xorType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, xorType); - // NOLINT(hicpp-signed-bitwise) - auto ret = static_cast(opNumber0) ^ static_cast(opNumber1); - return JSTaggedValue(ret); - } -}; -} // namespace panda::ecmascript - -#endif // ECMASCRIPT_IC_IC_BINARY_OP_H_ diff --git a/ecmascript/ic/ic_compare_op.cpp b/ecmascript/ic/ic_compare_op.cpp deleted file mode 100644 index a8a3de5a33..0000000000 --- a/ecmascript/ic/ic_compare_op.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* - * 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. - */ - -#include "ecmascript/ic/ic_compare_op.h" - -#include "ecmascript/runtime_call_id.h" - -namespace panda::ecmascript { -JSTaggedValue CompareOp::EqualWithIC(JSThread* thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, EqualWithIC); - double leftDouble = 0; - double rightDouble = 0; - JSTaggedValue ret = JSTaggedValue::False(); - switch (operationType) { - case CompareOpType::NUMBER_NUMBER: { - leftDouble = left.GetNumber(); - rightDouble = right.GetNumber(); - ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble)); - break; - } - case CompareOpType::STRING_NUMBER: { - JSTaggedValue temp = left; - left = right; - right = temp; - [[fallthrough]]; - } - case CompareOpType::NUMBER_STRING: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - rightDouble = JSTaggedValue::ToNumber(thread, rightHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - leftDouble = leftHandle.GetTaggedValue().GetNumber(); - ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble)); - break; - } - case CompareOpType::BOOLEAN_NUMBER: { - JSTaggedValue temp = left; - left = right; - right = temp; - [[fallthrough]]; - } - case CompareOpType::NUMBER_BOOLEAN: { - leftDouble = left.GetNumber(); - if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble)); - break; - } - case CompareOpType::OBJ_NUMBER: { - JSTaggedValue temp = left; - left = right; - right = temp; - [[fallthrough]]; - } - case CompareOpType::NUMBER_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - if (rightPrimitive->IsNumber()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_NUMBER); - } else if (rightPrimitive->IsString()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING); - } else if (rightPrimitive->IsBoolean()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } - break; - } - case CompareOpType::STRING_STRING: { - bool result = EcmaStringAccessor::StringsAreEqual(static_cast(left.GetTaggedObject()), - static_cast(right.GetTaggedObject())); - ret = result ? JSTaggedValue::True() : JSTaggedValue::False(); - break; - } - case CompareOpType::BOOLEAN_STRING: { - JSTaggedValue temp = left; - left = right; - right = temp; - [[fallthrough]]; - } - case CompareOpType::STRING_BOOLEAN: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - leftDouble = JSTaggedValue::ToNumber(thread, leftHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - if (rightHandle.GetTaggedValue().GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble)); - break; - } - case CompareOpType::OBJ_STRING: { - JSTaggedValue temp = left; - left = right; - right = temp; - [[fallthrough]]; - } - case CompareOpType::STRING_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - if (rightPrimitive->IsNumber()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING); - } else if (rightPrimitive->IsString()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::STRING_STRING); - } else if (rightPrimitive->IsBoolean()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } - break; - } - case CompareOpType::BOOLEAN_BOOLEAN: { - if (left.GetRawData() == JSTaggedValue::VALUE_TRUE) { - leftDouble = 1; - } - if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble)); - break; - } - case CompareOpType::OBJ_BOOLEAN: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - if (leftPrimitive->IsNumber()) { - ret = EqualWithIC(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } else if (leftPrimitive->IsString()) { - ret = EqualWithIC(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } else if (leftPrimitive->IsBoolean()) { - ret = EqualWithIC(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN); - } - break; - } - case CompareOpType::BOOLEAN_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - if (rightPrimitive->IsNumber()) { - ret = EqualWithIC(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } else if (rightPrimitive->IsString()) { - ret = EqualWithIC(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } else if (rightPrimitive->IsBoolean()) { - ret = EqualWithIC(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN); - } - break; - } - case CompareOpType::OBJ_OBJ: { - // if same type, must call Type::StrictEqual() - JSType xType = left.GetTaggedObject()->GetClass()->GetObjectType(); - JSType yType = right.GetTaggedObject()->GetClass()->GetObjectType(); - bool resultObj = false; - if (xType == yType) { - resultObj = JSTaggedValue::StrictEqual(thread, JSHandle(thread, left), - JSHandle(thread, right)); - } - ret = resultObj ? JSTaggedValue::True() : JSTaggedValue::False(); - break; - } - case CompareOpType::SYMBOL_SYMBOL: { - ret = left == right ? JSTaggedValue::True() : JSTaggedValue::False(); - break; - } - case CompareOpType::NULL_NULL: - case CompareOpType::NULL_UNDEFINED: - case CompareOpType::UNDEFINED_UNDEFINED: - case CompareOpType::UNDEFINED_NULL: { - ret = JSTaggedValue::True(); - break; - } - default: - ret = JSTaggedValue::False(); - } - return ret; -} - -JSTaggedValue CompareOp::NotEqualWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, NotEqualWithIC); - JSTaggedValue res = EqualWithIC(thread, left, right, operationType); - return res.IsTrue() ? JSTaggedValue::False() : JSTaggedValue::True(); -} - -ComparisonResult CompareOp::Compare(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, Compare); - double leftDouble = 0; - double rightDouble = 0; - ComparisonResult ret = ComparisonResult::UNDEFINED; - switch (operationType) { - case CompareOpType::NUMBER_NUMBER: { - leftDouble = left.IsInt() ? static_cast(left.GetInt()) : left.GetDouble(); - rightDouble = right.IsInt() ? static_cast(right.GetInt()) : right.GetDouble(); - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - case CompareOpType::NUMBER_STRING: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - - rightDouble = JSTaggedValue::ToNumber(thread, rightHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - leftDouble = leftHandle.GetTaggedValue().GetNumber(); - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - case CompareOpType::NUMBER_BOOLEAN: { - leftDouble = left.GetNumber(); - if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - case CompareOpType::NUMBER_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (rightPrimitive->IsNumber()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_NUMBER); - } else if (rightPrimitive->IsString()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING); - } else if (rightPrimitive->IsBoolean()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } - break; - } - case CompareOpType::STRING_STRING: { - JSHandle xHandle(thread, left); - JSHandle yHandle(thread, right); - int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle); - if (result < 0) { - ret = ComparisonResult::LESS; - } else if (result == 0) { - ret = ComparisonResult::EQUAL; - } else { - ret = ComparisonResult::GREAT; - } - break; - } - case CompareOpType::STRING_NUMBER: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - leftDouble = JSTaggedValue::ToNumber(thread, leftHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - rightDouble = rightHandle.GetTaggedValue().GetNumber(); - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - case CompareOpType::STRING_BOOLEAN: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - leftDouble = JSTaggedValue::ToNumber(thread, leftHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (rightHandle.GetTaggedValue().GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - case CompareOpType::STRING_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (rightPrimitive->IsNumber()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING); - } else if (rightPrimitive->IsString()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::STRING_STRING); - } else if (rightPrimitive->IsBoolean()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } - break; - } - case CompareOpType::BOOLEAN_BOOLEAN: { - if (left.GetRawData() == JSTaggedValue::VALUE_TRUE) { - leftDouble = 1; - } - if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - - case CompareOpType::BOOLEAN_NUMBER: { - if (left.GetRawData() == JSTaggedValue::VALUE_TRUE) { - leftDouble = 1; - } - rightDouble = right.GetNumber(); - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - - case CompareOpType::BOOLEAN_STRING: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - rightDouble = JSTaggedValue::ToNumber(thread, rightHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (leftHandle.GetTaggedValue().GetRawData() == JSTaggedValue::VALUE_TRUE) { - leftDouble = 1; - } - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - - case CompareOpType::BOOLEAN_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (rightPrimitive->IsNumber()) { - ret = Compare(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } else if (rightPrimitive->IsString()) { - ret = Compare(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } else if (rightPrimitive->IsBoolean()) { - ret = Compare(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN); - } - break; - } - case CompareOpType::OBJ_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - ret = JSTaggedValue::Compare(thread, leftHandle, rightHandle); - break; - } - case CompareOpType::OBJ_NUMBER: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (leftPrimitive->IsNumber()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::NUMBER_NUMBER); - } else if (leftPrimitive->IsString()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::STRING_NUMBER); - } else if (leftPrimitive->IsBoolean()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_NUMBER); - } - break; - } - case CompareOpType::OBJ_STRING: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (leftPrimitive->IsNumber()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::NUMBER_STRING); - } else if (leftPrimitive->IsString()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::STRING_STRING); - } else if (leftPrimitive->IsBoolean()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_STRING); - } - break; - } - case CompareOpType::OBJ_BOOLEAN: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (leftPrimitive->IsNumber()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } else if (leftPrimitive->IsString()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } else if (leftPrimitive->IsBoolean()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN); - } - break; - } - default: - ret = ComparisonResult::UNDEFINED; - } - return ret; -} - -JSTaggedValue CompareOp::LessWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, LessWithIC); - bool ret = CompareOp::Compare(thread, left, right, operationType) == ComparisonResult::LESS; - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return (ret ? JSTaggedValue::True() : JSTaggedValue::False()); -} - -JSTaggedValue CompareOp::LessEqWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, LessEqWithIC); - bool ret = CompareOp::Compare(thread, left, right, operationType) <= ComparisonResult::EQUAL; - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return (ret ? JSTaggedValue::True() : JSTaggedValue::False()); -} - -JSTaggedValue CompareOp::GreaterWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, GreaterWithIC); - bool ret = CompareOp::Compare(thread, left, right, operationType) == ComparisonResult::GREAT; - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return (ret ? JSTaggedValue::True() : JSTaggedValue::False()); -} - -JSTaggedValue CompareOp::GreaterEqWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, GreaterEqWithIC); - ComparisonResult comparison = CompareOp::Compare(thread, left, right, operationType); - bool ret = (comparison == ComparisonResult::GREAT) || (comparison == ComparisonResult::EQUAL); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return (ret ? JSTaggedValue::True() : JSTaggedValue::False()); -} -} // namespace panda::ecmascript diff --git a/ecmascript/ic/ic_compare_op.h b/ecmascript/ic/ic_compare_op.h deleted file mode 100644 index aacff9d7f7..0000000000 --- a/ecmascript/ic/ic_compare_op.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2021-2023 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_IC_IC_COMPARE_OP_H -#define ECMASCRIPT_IC_IC_COMPARE_OP_H - -#include "ecmascript/js_function.h" -#include "ecmascript/js_thread.h" -#include "ecmascript/object_factory.h" - -namespace panda::ecmascript { -enum class CompareOpType { - NUMBER_NUMBER, - NUMBER_STRING, - NUMBER_BOOLEAN, - NUMBER_OBJ, - STRING_STRING, - STRING_NUMBER, - STRING_BOOLEAN, - STRING_OBJ, - BOOLEAN_BOOLEAN, - BOOLEAN_NUMBER, - BOOLEAN_STRING, - BOOLEAN_OBJ, - OBJ_OBJ, - OBJ_NUMBER, - OBJ_STRING, - OBJ_BOOLEAN, - SYMBOL_SYMBOL, - NULL_NULL, - NULL_UNDEFINED, - UNDEFINED_UNDEFINED, - UNDEFINED_NULL, - UNDEFINED_BLLEAN, - OTHER, -}; - -class CompareOp { -public: - - CompareOp() = default; - ~CompareOp() = default; - - static JSTaggedValue EqualWithIC(JSThread* thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static JSTaggedValue NotEqualWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static ComparisonResult Compare(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static JSTaggedValue LessWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static JSTaggedValue LessEqWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static JSTaggedValue GreaterWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static JSTaggedValue GreaterEqWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); -}; -} // namespace panda::ecmascript -#endif // ECMASCRIPT_IC_IC_COMPARE_OP_H \ No newline at end of file diff --git a/ecmascript/ic/invoke_cache.cpp b/ecmascript/ic/invoke_cache.cpp deleted file mode 100644 index 990d3b2100..0000000000 --- a/ecmascript/ic/invoke_cache.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2021-2024 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 "ecmascript/ic/invoke_cache.h" -#include "ecmascript/interpreter/frame_handler.h" -#include "ecmascript/interpreter/interpreter.h" - - -namespace panda::ecmascript { -// Build the infrastructure and wait for TS to invoke. -bool InvokeCache::SetMonoConstuctCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - JSTaggedValue newTarget, JSTaggedValue initialHClass) -{ - // only cache class constructor - if (UNLIKELY(!newTarget.IsClassConstructor())) { - return false; - } - - profileTypeInfo->Set(thread, slotId, newTarget); - profileTypeInfo->Set(thread, slotId + 1, initialHClass); - - return true; -} - -bool InvokeCache::SetPolyConstuctCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - uint8_t length, JSTaggedValue newTargetArray, - JSTaggedValue initialHClassArray) -{ - ASSERT(length <= POLY_CASE_NUM && newTargetArray.IsTaggedArray() && initialHClassArray.IsTaggedArray()); - - JSHandle profileTypeInfoArr(thread, profileTypeInfo); - JSHandle newTargetArr(thread, newTargetArray); - JSHandle initialHClassArr(thread, initialHClassArray); - - auto factory = thread->GetEcmaVM()->GetFactory(); - constexpr uint8_t step = 2; - JSHandle newArray = factory->NewTaggedArray(length * step); // 2: newTarget and hclass - - for (uint8_t index = 0; index < length; ++index) { - ASSERT(newTargetArr->Get(index).IsClassConstructor()); - - newArray->Set(thread, index * step, newTargetArr->Get(index)); - newArray->Set(thread, index * step + 1, initialHClassArr->Get(index)); - } - - profileTypeInfoArr->Set(thread, slotId, newArray); - profileTypeInfoArr->Set(thread, slotId + 1, JSTaggedValue::Hole()); - - return true; -} - -JSTaggedValue InvokeCache::CheckPolyInvokeCache(JSTaggedValue cachedArray, JSTaggedValue func) -{ - ASSERT(cachedArray.IsTaggedArray()); - TaggedArray *array = TaggedArray::Cast(cachedArray.GetTaggedObject()); - uint32_t length = array->GetLength(); - for (uint32_t index = 0; index < length; index += 2) { // 2: means one ic, two slot - auto result = array->Get(index); - if (JSFunction::Cast(result.GetTaggedObject())->GetMethod() == - JSFunction::Cast(func.GetTaggedObject())->GetMethod()) { - return array->Get(index + 1); - } - } - - return JSTaggedValue::Hole(); -} - -JSTaggedValue InvokeCache::Construct(JSThread *thread, JSTaggedValue firstValue, JSTaggedValue secondValue, - JSTaggedValue ctor, JSTaggedValue newTarget, uint16_t firstArgIdx, uint16_t length) -{ - // ic miss - if (UNLIKELY(!firstValue.IsHeapObject())) { - return JSTaggedValue::Hole(); - } - - // gc protection - JSHandle constructor(thread, ctor); - JSHandle newTgt(thread, newTarget); - - JSHandle instanceHClass; - // monomorphic - if (LIKELY(firstValue.IsJSFunction() && - newTgt->GetMethod() == JSFunction::Cast(firstValue.GetTaggedObject())->GetMethod())) { - instanceHClass = JSHandle(thread, JSHClass::Cast(secondValue.GetTaggedObject())); - } else { - // polymorphic - ASSERT(firstValue.IsTaggedArray()); - JSTaggedValue polyCache = CheckPolyInvokeCache(firstValue, newTarget); - if (UNLIKELY(polyCache.IsHole())) { - return JSTaggedValue::Hole(); - } - instanceHClass = JSHandle(thread, JSHClass::Cast(polyCache.GetTaggedObject())); - } - - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle obj = factory->NewJSObject(instanceHClass); - EcmaRuntimeCallInfo *info = - EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle(constructor), JSHandle(obj), - JSHandle(newTgt), length); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - FrameHandler frameHandler(thread); - for (size_t i = 0; i < length; i++) { - info->SetCallArg(i, frameHandler.GetVRegValue(firstArgIdx + i)); - } - EcmaInterpreter::Execute(info); - return obj.GetTaggedValue(); -} - -// just identify simple callee case which can be inlined, the implement of inline need wait TS AOT -bool InvokeCache::SetMonoInlineCallCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - JSTaggedValue callee) -{ - ASSERT(callee.IsJSFunction()); - Method *calleeMethod = JSFunction::Cast(callee.GetTaggedObject())->GetCallTarget(); - if (DecideCanBeInlined(calleeMethod)) { - profileTypeInfo->Set(thread, slotId, callee); - return true; - } - - profileTypeInfo->Set(thread, slotId, JSTaggedValue::Hole()); - return false; -} - -bool InvokeCache::SetPolyInlineCallCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - uint8_t length, JSTaggedValue calleeArray) -{ - ASSERT(calleeArray.IsTaggedArray() && length >= MONO_CASE_NUM && length <= POLY_CASE_NUM); - JSHandle calleeArr(thread, calleeArray); - ASSERT(calleeArr->GetLength() == length); - JSHandle profileTypeInfoArr(thread, profileTypeInfo); - - auto factory = thread->GetEcmaVM()->GetFactory(); - JSHandle newArray = factory->NewTaggedArray(length); - - for (uint8_t index = 0; index < length; ++index) { - JSTaggedValue calleeElement = calleeArr->Get(index); - Method *calleeMethod = JSFunction::Cast(calleeElement.GetTaggedObject())->GetCallTarget(); - if (DecideCanBeInlined(calleeMethod)) { - newArray->Set(thread, index, calleeElement); - } else { - newArray->Set(thread, index, JSTaggedValue::Hole()); - } - } - - profileTypeInfoArr->Set(thread, slotId, newArray); - return true; -} - -bool InvokeCache::DecideCanBeInlined(Method *method) -{ - constexpr uint32_t MAX_INLINED_BYTECODE_SIZE = 128; - uint32_t bcSize = method->GetCodeSize(); - return (bcSize > 0 && bcSize < MAX_INLINED_BYTECODE_SIZE); // 0 is invalid -} -} // namespace panda::ecmascript diff --git a/ecmascript/ic/invoke_cache.h b/ecmascript/ic/invoke_cache.h deleted file mode 100644 index e533122ca5..0000000000 --- a/ecmascript/ic/invoke_cache.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2021-2023 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_IC_INVOKE_CACHE_H -#define ECMASCRIPT_IC_INVOKE_CACHE_H - -#include "ecmascript/ic/profile_type_info.h" -#include "ecmascript/js_tagged_value.h" - -namespace panda::ecmascript { -class InvokeCache { -public: - static constexpr size_t MONO_CASE_NUM = 2; - static constexpr size_t POLY_CASE_NUM = 4; - - static bool SetMonoConstuctCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - JSTaggedValue newTarget, JSTaggedValue initialHClass); - - static bool SetPolyConstuctCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - uint8_t length, JSTaggedValue newTargetArray, - JSTaggedValue initialHClassArray); - - static JSTaggedValue CheckPolyInvokeCache(JSTaggedValue cachedArray, JSTaggedValue func); - - static JSTaggedValue Construct(JSThread *thread, JSTaggedValue firstValue, JSTaggedValue secondValue, - JSTaggedValue ctor, JSTaggedValue newTarget, uint16_t firstArgIdx, - uint16_t length); - - static bool SetMonoInlineCallCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - JSTaggedValue callee); - - static bool SetPolyInlineCallCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - uint8_t length, JSTaggedValue calleeArray); - - static bool DecideCanBeInlined(Method *method); -}; -} // namespace panda::ecmascript - -#endif // ECMASCRIPT_IC_INVOKE_CACHE_H diff --git a/ecmascript/ic/tests/BUILD.gn b/ecmascript/ic/tests/BUILD.gn index 8cf901a782..faf41cb319 100644 --- a/ecmascript/ic/tests/BUILD.gn +++ b/ecmascript/ic/tests/BUILD.gn @@ -21,10 +21,7 @@ host_unittest_action("IC_001_Test") { sources = [ # test file - "ic_binaryop_test.cpp", - "ic_compareop_test.cpp", "ic_handler_test.cpp", - "ic_invoke_test.cpp", "ic_runtime_stub_test.cpp", ] diff --git a/ecmascript/ic/tests/ic_binaryop_test.cpp b/ecmascript/ic/tests/ic_binaryop_test.cpp deleted file mode 100644 index dacbc83e4f..0000000000 --- a/ecmascript/ic/tests/ic_binaryop_test.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 2021-2024 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 - -#include "ecmascript/ecma_vm.h" -#include "ecmascript/global_env_constants.h" -#include "ecmascript/global_env_constants-inl.h" -#include "ecmascript/ic/ic_binary_op.h" -#include "ecmascript/interpreter/slow_runtime_stub.h" -#include "ecmascript/object_factory.h" -#include "ecmascript/tests/test_helper.h" - -using namespace panda::ecmascript; -namespace panda::test { -class ICBinaryOPTest : public testing::Test { -public: - static void SetUpTestCase() - { - GTEST_LOG_(INFO) << "SetUpTestCase"; - } - - static void TearDownTestCase() - { - GTEST_LOG_(INFO) << "TearDownCase"; - } - - void SetUp() override - { - TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope); - } - - void TearDown() override - { - TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope); - } - - EcmaHandleScope *scope {nullptr}; - JSThread *thread {nullptr}; - EcmaVM *ecmaVm = nullptr; -}; - -HWTEST_F_L0(ICBinaryOPTest, AddWithTSType) -{ - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("AddTest"); - JSHandle Str2 = factory->NewFromASCII("IC"); - JSHandle arg4 = factory->NewEmptyJSObject(); - JSTaggedValue arg1Value(static_cast(2)); - JSTaggedValue arg2Value(static_cast(3)); - JSTaggedValue arg3Value(static_cast(9.5561)); - JSHandle arg1(thread, arg1Value); - JSHandle arg2(thread, arg2Value); - JSHandle arg3(thread, arg3Value); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Add2(thread, arg1.GetTaggedValue(), - arg2.GetTaggedValue()); - JSHandle slowHandle1(thread, resInSlowPath1); - JSTaggedValue resInICPath1 = ICBinaryOP::AddWithTSType(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle1.GetTaggedValue(), resInICPath1); - - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Add2(thread, arg1.GetTaggedValue(), - arg3.GetTaggedValue()); - JSHandle slowHandle2(thread, resInSlowPath2); - JSTaggedValue resInICPath2 = ICBinaryOP::AddWithTSType(thread, arg1.GetTaggedValue(), arg3.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle2.GetTaggedValue(), resInICPath2); - - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Add2(thread, Str1.GetTaggedValue(), - Str2.GetTaggedValue()); - JSHandle slowHandle3(thread, reinterpret_cast(resInSlowPath3.GetRawData())); - JSTaggedValue resInICPath3 = ICBinaryOP::AddWithTSType(thread, Str1.GetTaggedValue(), Str2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::STRING))); - ASSERT_TRUE(resInICPath3.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle3, JSHandle(thread, resInICPath3)), 0); - - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Add2(thread, JSTaggedValue::Undefined(), - arg2.GetTaggedValue()); - JSHandle slowHandle4(thread, resInSlowPath4); - JSTaggedValue resInICPath4 = ICBinaryOP::AddWithTSType(thread, JSTaggedValue::Undefined(), - arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER_GEN))); - EXPECT_EQ(slowHandle4.GetTaggedValue(), resInICPath4); - - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Add2(thread, arg3.GetTaggedValue(), - Str1.GetTaggedValue()); - JSHandle slowHandle5(thread, reinterpret_cast(resInSlowPath5.GetRawData())); - JSTaggedValue resInICPath5 = ICBinaryOP::AddWithTSType(thread, arg3.GetTaggedValue(), - Str1.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::STRING_GEN))); - ASSERT_TRUE(resInICPath5.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle5, JSHandle(thread, resInICPath5)), 0); - - JSTaggedValue resInSlowPath6 = SlowRuntimeStub::Add2(thread, Str1.GetTaggedValue(), - JSTaggedValue::Null()); - JSHandle slowHandle6(thread, reinterpret_cast(resInSlowPath6.GetRawData())); - JSTaggedValue resInICPath6 = ICBinaryOP::AddWithTSType(thread, Str1.GetTaggedValue(), JSTaggedValue::Null(), - JSTaggedValue(static_cast(BinaryType::STRING_GEN))); - ASSERT_TRUE(resInICPath6.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle6, JSHandle(thread, resInICPath6)), 0); - - JSTaggedValue resInSlowPath7 = SlowRuntimeStub::Add2(thread, arg1.GetTaggedValue(), - JSTaggedValue::True()); - JSHandle slowHandle7(thread, resInSlowPath7); - JSTaggedValue resInICPath7 = ICBinaryOP::AddWithTSType(thread, arg1.GetTaggedValue(), JSTaggedValue::True(), - JSTaggedValue(static_cast(BinaryType::NUMBER_GEN))); - EXPECT_EQ(slowHandle7.GetTaggedValue(), resInICPath7); - - JSTaggedValue resInSlowPath8 = SlowRuntimeStub::Add2(thread, arg4.GetTaggedValue(), - JSTaggedValue::Null()); - JSHandle slowHandle8(thread, reinterpret_cast(resInSlowPath8.GetRawData())); - JSTaggedValue resInICPath8 = ICBinaryOP::AddWithTSType(thread, arg4.GetTaggedValue(), JSTaggedValue::Null(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - ASSERT_TRUE(resInICPath8.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle8, JSHandle(thread, resInICPath8)), 0); -}; - -HWTEST_F_L0(ICBinaryOPTest, SubWithTSType) -{ - JSTaggedValue arg1Value(static_cast(-2)); - JSTaggedValue arg2Value(static_cast(INT32_MAX-1)); - JSTaggedValue arg3Value(static_cast(9.5561)); - JSHandle arg1(thread, arg1Value); - JSHandle arg2(thread, arg2Value); - JSHandle arg3(thread, arg3Value); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Sub2(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle1(thread, resInSlowPath1); - JSTaggedValue resInICPath1 = ICBinaryOP::SubWithTSType(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle1.GetTaggedValue(), resInICPath1); - - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Sub2(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue()); - JSHandle slowHandle2(thread, resInSlowPath2); - JSTaggedValue resInICPath2 = ICBinaryOP::SubWithTSType(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle2.GetTaggedValue(), resInICPath2); - - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Sub2(thread, arg1.GetTaggedValue(), JSTaggedValue::True()); - JSHandle slowHandle3(thread, resInSlowPath3); - JSTaggedValue resInICPath3 = ICBinaryOP::SubWithTSType(thread, arg1.GetTaggedValue(), JSTaggedValue::True(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle3.GetTaggedValue(), resInICPath3); -}; - -HWTEST_F_L0(ICBinaryOPTest, MulWithTSType) -{ - JSTaggedValue arg1Value(static_cast(28.5)); - JSTaggedValue arg2Value(static_cast(354)); - JSTaggedValue arg3Value(static_cast(9.5561)); - JSHandle arg1(thread, arg1Value); - JSHandle arg2(thread, arg2Value); - JSHandle arg3(thread, arg3Value); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Mul2(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle1(thread, resInSlowPath1); - JSTaggedValue resInICPath1 = ICBinaryOP::MulWithTSType(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle1.GetTaggedValue(), resInICPath1); - - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Mul2(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue()); - JSHandle slowHandle2(thread, resInSlowPath2); - JSTaggedValue resInICPath2 = ICBinaryOP::MulWithTSType(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle2.GetTaggedValue(), resInICPath2); - - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Mul2(thread, arg1.GetTaggedValue(), JSTaggedValue::True()); - JSHandle slowHandle3(thread, resInSlowPath3); - JSTaggedValue resInICPath3 = ICBinaryOP::MulWithTSType(thread, arg1.GetTaggedValue(), JSTaggedValue::True(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle3.GetTaggedValue(), resInICPath3); - -}; - -HWTEST_F_L0(ICBinaryOPTest, DivWithTSType) -{ - JSTaggedValue arg1Value(static_cast(2)); - JSTaggedValue arg2Value(static_cast(39884)); - JSTaggedValue arg3Value(static_cast(0)); - JSTaggedValue arg4Value(static_cast(934.5561)); - JSHandle arg1(thread, arg1Value); - JSHandle arg2(thread, arg2Value); - JSHandle arg3(thread, arg3Value); - JSHandle arg4(thread, arg4Value); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Div2(thread, arg3.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle1(thread, resInSlowPath1); - JSTaggedValue resInICPath1 = ICBinaryOP::DivWithTSType(thread, arg3.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle1.GetTaggedValue(), resInICPath1); - - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Div2(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue()); - JSHandle slowHandle2(thread, resInSlowPath2); - JSTaggedValue resInICPath2 = ICBinaryOP::DivWithTSType(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle2.GetTaggedValue(), resInICPath2); - - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Div2(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle3(thread, resInSlowPath3); - JSTaggedValue resInICPath3 = ICBinaryOP::DivWithTSType(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle3.GetTaggedValue(), resInICPath3); - - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Div2(thread, arg2.GetTaggedValue(), JSTaggedValue::True()); - JSHandle slowHandle4(thread, resInSlowPath4); - JSTaggedValue resInICPath4 = ICBinaryOP::DivWithTSType(thread, arg2.GetTaggedValue(), JSTaggedValue::True(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle4.GetTaggedValue(), resInICPath4); - - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Div2(thread, arg4.GetTaggedValue(), JSTaggedValue::False()); - JSHandle slowHandle5(thread, resInSlowPath5); - JSTaggedValue resInICPath5 = ICBinaryOP::DivWithTSType(thread, arg4.GetTaggedValue(), - JSTaggedValue::False(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle5.GetTaggedValue(), resInICPath5); -}; - -HWTEST_F_L0(ICBinaryOPTest, ModWithTSType) -{ - JSTaggedValue arg1Value(static_cast(2)); - JSTaggedValue arg2Value(static_cast(39884)); - JSTaggedValue arg3Value(static_cast(0)); - JSTaggedValue arg4Value(static_cast(934.5561)); - JSHandle arg1(thread, arg1Value); - JSHandle arg2(thread, arg2Value); - JSHandle arg3(thread, arg3Value); - JSHandle arg4(thread, arg4Value); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Mod2(thread, arg3.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle1(thread, resInSlowPath1); - JSTaggedValue resInICPath1 = ICBinaryOP::ModWithTSType(thread, arg3.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle1.GetTaggedValue(), resInICPath1); - - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Mod2(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue()); - JSHandle slowHandle2(thread, resInSlowPath2); - JSTaggedValue resInICPath2 = ICBinaryOP::ModWithTSType(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle2.GetTaggedValue(), resInICPath2); - - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Mod2(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle3(thread, resInSlowPath3); - JSTaggedValue resInICPath3 = ICBinaryOP::ModWithTSType(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle3.GetTaggedValue(), resInICPath3); - - - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Mod2(thread, arg2.GetTaggedValue(), JSTaggedValue::True()); - JSHandle slowHandle4(thread, resInSlowPath4); - JSTaggedValue resInICPath4 = ICBinaryOP::ModWithTSType(thread, arg2.GetTaggedValue(), JSTaggedValue::True(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle4.GetTaggedValue(), resInICPath4); - - - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Mod2(thread, arg4.GetTaggedValue(), JSTaggedValue::False()); - JSHandle slowHandle5(thread, resInSlowPath5); - JSTaggedValue resInICPath5 = ICBinaryOP::ModWithTSType(thread, arg4.GetTaggedValue(), - JSTaggedValue::False(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle5.GetTaggedValue(), resInICPath5); -}; - -HWTEST_F_L0(ICBinaryOPTest, ShlWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg3(static_cast(5)); - - JSTaggedValue resInICPath1 = ICBinaryOP::ShlWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(9152), resInICPath1); - - JSTaggedValue resInICPath2 = ICBinaryOP::ShlWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(7200), resInICPath2); -}; - -HWTEST_F_L0(ICBinaryOPTest, ShrWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg3(static_cast(5)); - - JSTaggedValue resInICPath1 = ICBinaryOP::ShrWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(8), resInICPath1); - - JSTaggedValue resInICPath2 = ICBinaryOP::ShrWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(7), resInICPath2); -}; - -HWTEST_F_L0(ICBinaryOPTest, AshrWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg2(static_cast(-286)); - JSTaggedValue arg3(static_cast(5)); - - JSTaggedValue resInICPath1 = ICBinaryOP::AshrWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(8), resInICPath1); - - JSTaggedValue resInICPath3 = ICBinaryOP::AshrWithTSType(thread, arg2, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(134217719), resInICPath3); - - JSTaggedValue resInICPath2 = ICBinaryOP::AshrWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(7), resInICPath2); - -}; -HWTEST_F_L0(ICBinaryOPTest, AndWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg3(static_cast(541)); - - JSTaggedValue resInICPath1 = ICBinaryOP::AndWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(28), resInICPath1); - - JSTaggedValue resInICPath2 = ICBinaryOP::AndWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(1), resInICPath2); -}; -HWTEST_F_L0(ICBinaryOPTest, OrWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg3(static_cast(523)); - - JSTaggedValue resInICPath1 = ICBinaryOP::OrWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(799), resInICPath1); - - JSTaggedValue resInICPath2 = ICBinaryOP::OrWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(747), resInICPath2); -}; -HWTEST_F_L0(ICBinaryOPTest, XorWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("1225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg3(static_cast(523)); - - JSTaggedValue resInICPath1 = ICBinaryOP::XorWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(789), resInICPath1); - - JSTaggedValue resInICPath2 = ICBinaryOP::XorWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(1730), resInICPath2); -}; -} // namespace panda::test diff --git a/ecmascript/ic/tests/ic_compareop_test.cpp b/ecmascript/ic/tests/ic_compareop_test.cpp deleted file mode 100644 index 29c676800c..0000000000 --- a/ecmascript/ic/tests/ic_compareop_test.cpp +++ /dev/null @@ -1,462 +0,0 @@ -/* - * 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. - */ - -#include - -#include "ecmascript/builtins/builtins_boolean.h" -#include "ecmascript/ecma_runtime_call_info.h" -#include "ecmascript/ecma_string.h" -#include "ecmascript/ecma_vm.h" -#include "ecmascript/global_env.h" -#include "ecmascript/global_env_constants.h" -#include "ecmascript/global_env_constants-inl.h" -#include "ecmascript/ic/ic_compare_op.cpp" -#include "ecmascript/ic/ic_compare_op.h" -#include "ecmascript/interpreter/slow_runtime_stub.h" -#include "ecmascript/js_primitive_ref.h" -#include "ecmascript/js_tagged_value-inl.h" -#include "ecmascript/object_factory.h" -#include "ecmascript/tests/test_helper.h" - -using namespace panda::ecmascript; -namespace panda::test { -class IcCompareOPTest : public testing::Test { -public: - static void SetUpTestCase() - { - GTEST_LOG_(INFO) << "SetUpTestCase"; - } - - static void TearDownTestCase() - { - GTEST_LOG_(INFO) << "TearDownCase"; - } - - void SetUp() override - { - TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope); - } - - void TearDown() override - { - TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope); - } - - EcmaVM *ecmaVm {nullptr}; - EcmaHandleScope *scope {nullptr}; - JSThread *thread {nullptr}; -}; - -HWTEST_F_L0(IcCompareOPTest, EqualWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("1")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(1.0)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(1))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Eq(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Eq(thread, Str1.GetTaggedValue(), arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Eq(thread, Str1.GetTaggedValue(), arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Eq(thread, Str1.GetTaggedValue(), arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Eq(thread, booleanObjHandle.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::Eq(thread, JSTaggedValue::Undefined(), JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::Eq(thread, JSTaggedValue::Undefined(), JSTaggedValue::True()); - - JSTaggedValue resInICPath1 = CompareOp::EqualWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::EqualWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::EqualWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::EqualWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::EqualWithIC(thread, booleanObjHandle.GetTaggedValue(), - arg4Handle.GetTaggedValue(), CompareOpType::OBJ_BOOLEAN); - JSTaggedValue resInICPath9 = CompareOp::EqualWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::EqualWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; - -HWTEST_F_L0(IcCompareOPTest, NotEqualWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("1")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(2.0)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(123))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::NotEq(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::NotEq(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::NotEq(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::NotEq(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::NotEq(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::NotEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::NotEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True()); - - JSTaggedValue resInICPath1 = CompareOp::NotEqualWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), - CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::NotEqualWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::NotEqualWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::NotEqualWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::NotEqualWithIC(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue(), - CompareOpType::NUMBER_OBJ); - JSTaggedValue resInICPath9 = CompareOp::NotEqualWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::NotEqualWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; - - -HWTEST_F_L0(IcCompareOPTest, LessWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("0")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(0.5)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(123))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Less(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Less(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Less(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Less(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Less(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::Less(thread, - JSTaggedValue::Undefined(), JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::Less(thread, - JSTaggedValue::Undefined(), JSTaggedValue::True()); - - JSTaggedValue resInICPath1 = CompareOp::LessWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::LessWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::LessWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::LessWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::LessWithIC(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue(), - CompareOpType::NUMBER_OBJ); - JSTaggedValue resInICPath9 = CompareOp::LessWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::LessWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; - - -HWTEST_F_L0(IcCompareOPTest, LessEqWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("1")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(0.5)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(123))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::LessEq(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::LessEq(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::LessEq(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::LessEq(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::LessEq(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::LessEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::LessEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True()); - JSTaggedValue resInICPath1 = CompareOp::LessEqWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), - CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::LessEqWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), - CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::LessEqWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::LessEqWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::LessEqWithIC(thread, - arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue(), - CompareOpType::NUMBER_OBJ); - JSTaggedValue resInICPath9 = CompareOp::LessEqWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::LessEqWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; - - -HWTEST_F_L0(IcCompareOPTest, GreaterWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("1")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(1.0)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(1))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Greater(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Greater(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Greater(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Greater(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Greater(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::Greater(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::Greater(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True()); - - JSTaggedValue resInICPath1 = CompareOp::GreaterWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), - CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::GreaterWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), - CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::GreaterWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::GreaterWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::GreaterWithIC(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue(), - CompareOpType::NUMBER_OBJ); - JSTaggedValue resInICPath9 = CompareOp::GreaterWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::GreaterWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; - - -HWTEST_F_L0(IcCompareOPTest, GreaterEqWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("1")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(1.0)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(0))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::GreaterEq(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::GreaterEq(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::GreaterEq(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::GreaterEq(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::GreaterEq(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::GreaterEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::GreaterEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True()); - - JSTaggedValue resInICPath1 = CompareOp::GreaterEqWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), - CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::GreaterEqWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), - CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::GreaterEqWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::GreaterEqWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::GreaterEqWithIC(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue(), - CompareOpType::NUMBER_OBJ); - JSTaggedValue resInICPath9 = CompareOp::GreaterEqWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::GreaterEqWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; -} // namespace panda::test diff --git a/ecmascript/ic/tests/ic_invoke_test.cpp b/ecmascript/ic/tests/ic_invoke_test.cpp deleted file mode 100644 index 69793a18d2..0000000000 --- a/ecmascript/ic/tests/ic_invoke_test.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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. - */ - -#include "ecmascript/ecma_vm.h" -#include "ecmascript/ic/invoke_cache.h" -#include "ecmascript/object_factory.h" -#include "ecmascript/tests/test_helper.h" - -using namespace panda::ecmascript; -namespace panda::test { -class ICInvokeTest : public testing::Test { -public: - static void SetUpTestCase() - { - GTEST_LOG_(INFO) << "SetUpTestCase"; - } - - static void TearDownTestCase() - { - GTEST_LOG_(INFO) << "TearDownCase"; - } - - void SetUp() override - { - TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope); - } - - void TearDown() override - { - TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope); - } - - EcmaVM *ecmaVm = nullptr; - EcmaHandleScope *scope {nullptr}; - JSThread *thread {nullptr}; -}; - -HWTEST_F_L0(ICInvokeTest, SetMonoConstuctCacheSlot) -{ - auto globalEnv = ecmaVm->GetGlobalEnv(); - auto factory = ecmaVm->GetFactory(); - JSHandle func = factory->NewJSFunction(globalEnv); - func.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true); - - JSHandle array = factory->NewTaggedArray(10); - uint32_t slotId = 5; - bool setResult = InvokeCache::SetMonoConstuctCacheSlot( - thread, static_cast(*array), slotId, func.GetTaggedValue(), JSTaggedValue(123)); - ASSERT_TRUE(setResult); - ASSERT_EQ(array->Get(thread, slotId), func.GetTaggedValue()); - ASSERT_EQ(array->Get(thread, slotId + 1), JSTaggedValue(123)); -} - -HWTEST_F_L0(ICInvokeTest, SetPolyConstuctCacheSlot) -{ - auto globalEnv = ecmaVm->GetGlobalEnv(); - auto factory = ecmaVm->GetFactory(); - JSHandle array1 = factory->NewTaggedArray(3); - JSHandle array2 = factory->NewTaggedArray(3); - - JSHandle func0 = factory->NewJSFunction(globalEnv); - func0.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true); - array1->Set(thread, 0, func0.GetTaggedValue()); - array2->Set(thread, 0, JSTaggedValue(123)); - JSHandle func1 = factory->NewJSFunction(globalEnv); - func1.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true); - array1->Set(thread, 1, func1.GetTaggedValue()); - array2->Set(thread, 1, JSTaggedValue(456)); - JSHandle func2 = factory->NewJSFunction(globalEnv); - func2.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true); - array1->Set(thread, 2, func2.GetTaggedValue()); - array2->Set(thread, 2, JSTaggedValue(789)); - - JSHandle array = factory->NewTaggedArray(10); - uint32_t slotId = 5; - bool setResult = InvokeCache::SetPolyConstuctCacheSlot( - thread, static_cast(*array), slotId, 3, array1.GetTaggedValue(), array2.GetTaggedValue()); - ASSERT_TRUE(setResult); - JSTaggedValue slot = array->Get(thread, slotId); - ASSERT_TRUE(slot.IsTaggedArray()); - JSHandle slotArray(thread, slot); - ASSERT_EQ(slotArray->Get(thread, 0), func0.GetTaggedValue()); - ASSERT_EQ(slotArray->Get(thread, 1), JSTaggedValue(123)); - ASSERT_EQ(slotArray->Get(thread, 2), func1.GetTaggedValue()); - ASSERT_EQ(slotArray->Get(thread, 3), JSTaggedValue(456)); - ASSERT_EQ(slotArray->Get(thread, 4), func2.GetTaggedValue()); - ASSERT_EQ(slotArray->Get(thread, 5), JSTaggedValue(789)); - ASSERT_EQ(array->Get(thread, slotId + 1), JSTaggedValue::Hole()); -} - -HWTEST_F_L0(ICInvokeTest, CheckPolyInvokeCache) -{ - auto globalEnv = ecmaVm->GetGlobalEnv(); - auto factory = ecmaVm->GetFactory(); - JSHandle array = factory->NewTaggedArray(6); - - JSHandle func0 = factory->NewJSFunction(globalEnv); - JSHandle func1 = factory->NewJSFunction(globalEnv); - JSHandle func2 = factory->NewJSFunction(globalEnv); - JSHandle func3 = factory->NewJSFunction(globalEnv); - array->Set(thread, 0, func0.GetTaggedValue()); - array->Set(thread, 1, JSTaggedValue(123)); - array->Set(thread, 2, func1.GetTaggedValue()); - array->Set(thread, 3, JSTaggedValue(456)); - array->Set(thread, 4, func2.GetTaggedValue()); - array->Set(thread, 5, JSTaggedValue(789)); - - JSTaggedValue testValue0 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func0.GetTaggedValue()); - ASSERT_EQ(testValue0, JSTaggedValue(123)); - JSTaggedValue testValue1 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func1.GetTaggedValue()); - ASSERT_EQ(testValue1, JSTaggedValue(456)); - JSTaggedValue testValue2 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func2.GetTaggedValue()); - ASSERT_EQ(testValue2, JSTaggedValue(789)); - JSTaggedValue testValue3 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func3.GetTaggedValue()); - ASSERT_EQ(testValue3, JSTaggedValue::Hole()); -} -} // namespace panda::test \ No newline at end of file diff --git a/ecmascript/runtime_call_id.h b/ecmascript/runtime_call_id.h index 769a7f4b73..422c708bc0 100644 --- a/ecmascript/runtime_call_id.h +++ b/ecmascript/runtime_call_id.h @@ -212,26 +212,7 @@ namespace panda::ecmascript { V(LdSuperByValue) \ V(StSuperByValue) \ V(ThrowDeleteSuperProperty) \ - V(ModWithTSType) \ - V(MulWithTSType) \ - V(SubWithTSType) \ - V(DivWithTSType) \ - V(AddWithTSType) \ - V(GetBitOPDate) \ - V(ShlWithTSType) \ - V(ShrWithTSType) \ - V(AshrWithTSType) \ - V(AndWithTSType) \ - V(OrWithTSType) \ - V(XorWithTSType) \ - V(EqualWithIC) \ - V(NotEqualWithIC) \ - V(Compare) \ - V(LessWithIC) \ - V(LessEqWithIC) \ - V(GreaterWithIC) \ V(SetPropertyByName) \ - V(GreaterEqWithIC) \ V(LdBigInt) \ V(Tonumeric) \ V(CreateAsyncGeneratorObj) \ -- Gitee From 060be7f4bdf2d1045cbd3edb79f0f0d000291131 Mon Sep 17 00:00:00 2001 From: c00451847 Date: Sat, 12 Oct 2024 09:17:27 +0800 Subject: [PATCH 002/185] opt storebyname code gen skip prototype's storebyname opt for better code generation Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAXDMU Signed-off-by: c00451847 Change-Id: Ic333fd44684f433b23c71fa3338247e802a18fc4 --- ecmascript/compiler/circuit_builder.h | 2 +- ecmascript/compiler/mcr_circuit_builder.cpp | 5 +- ecmascript/compiler/mcr_opcodes.h | 2 +- ecmascript/compiler/type_info_accessors.h | 23 ++++ .../compiler/typed_bytecode_lowering.cpp | 105 ++++++++++-------- ecmascript/compiler/typed_bytecode_lowering.h | 2 + ecmascript/compiler/typed_hcr_lowering.cpp | 31 ++++-- test/aottest/BUILD.gn | 1 + test/aottest/stobjbyname1/BUILD.gn | 22 ++++ test/aottest/stobjbyname1/expect_output.txt | 15 +++ .../stobjbyname1/pgo_expect_output.txt | 14 +++ test/aottest/stobjbyname1/stobjbyname1.ts | 35 ++++++ test/jittest/BUILD.gn | 1 + test/jittest/jit_test_0002/BUILD.gn | 19 ++++ test/jittest/jit_test_0002/expect_output.txt | 14 +++ test/jittest/jit_test_0002/jit_test_0002.ts | 33 ++++++ 16 files changed, 261 insertions(+), 63 deletions(-) create mode 100644 test/aottest/stobjbyname1/BUILD.gn create mode 100644 test/aottest/stobjbyname1/expect_output.txt create mode 100644 test/aottest/stobjbyname1/pgo_expect_output.txt create mode 100644 test/aottest/stobjbyname1/stobjbyname1.ts create mode 100644 test/jittest/jit_test_0002/BUILD.gn create mode 100644 test/jittest/jit_test_0002/expect_output.txt create mode 100644 test/jittest/jit_test_0002/jit_test_0002.ts diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index cdaea456e4..87ea2fbf39 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -664,7 +664,7 @@ public: GateRef MonoStorePropertyLookUpProto(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex, GateRef value); GateRef MonoStoreProperty(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex, - GateRef value, GateRef keyIndex, GateRef frameState); + GateRef value, GateRef keyIndex, GateRef isProto, GateRef frameState); GateRef TypedCreateObjWithBuffer(std::vector &valueIn); template GateRef ConvertJSArrayHoleAsUndefined(GateRef receiver); diff --git a/ecmascript/compiler/mcr_circuit_builder.cpp b/ecmascript/compiler/mcr_circuit_builder.cpp index ade74d7c0f..538026b444 100644 --- a/ecmascript/compiler/mcr_circuit_builder.cpp +++ b/ecmascript/compiler/mcr_circuit_builder.cpp @@ -1658,14 +1658,15 @@ GateRef CircuitBuilder::MonoStorePropertyLookUpProto(GateRef receiver, GateRef p } GateRef CircuitBuilder::MonoStoreProperty(GateRef receiver, GateRef plrGate, GateRef unsharedConstPool, - size_t hclassIndex, GateRef value, GateRef keyIndex, GateRef frameState) + size_t hclassIndex, GateRef value, GateRef keyIndex, GateRef isProto, + GateRef frameState) { auto currentLabel = env_->GetCurrentLabel(); auto currentControl = currentLabel->GetControl(); auto currentDepend = currentLabel->GetDepend(); auto ret = GetCircuit()->NewGate(circuit_->MonoStoreProperty(false), MachineType::I64, {currentControl, currentDepend, receiver, plrGate, Int32(hclassIndex), - unsharedConstPool, value, keyIndex, frameState}, + unsharedConstPool, value, keyIndex, isProto, frameState}, GateType::AnyType()); currentLabel->SetControl(ret); currentLabel->SetDepend(ret); diff --git a/ecmascript/compiler/mcr_opcodes.h b/ecmascript/compiler/mcr_opcodes.h index f35fa6f8a8..a9901e946f 100644 --- a/ecmascript/compiler/mcr_opcodes.h +++ b/ecmascript/compiler/mcr_opcodes.h @@ -209,7 +209,7 @@ namespace panda::ecmascript::kungfu { #define MCR_GATE_META_DATA_LIST_WITH_BOOL(V) \ V(LoadProperty, LOAD_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2) \ V(MonoStorePropertyLookUpProto, MONO_STORE_PROPERTY_LOOK_UP_PROTO, GateFlags::HAS_FRAME_STATE, 1, 1, 5) \ - V(MonoStoreProperty, MONO_STORE_PROPERTY, GateFlags::HAS_FRAME_STATE, 1, 1, 6) + V(MonoStoreProperty, MONO_STORE_PROPERTY, GateFlags::HAS_FRAME_STATE, 1, 1, 7) #define MCR_GATE_META_DATA_LIST_WITH_GATE_TYPE(V) \ V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ diff --git a/ecmascript/compiler/type_info_accessors.h b/ecmascript/compiler/type_info_accessors.h index 4cc33f2aed..703f2647ad 100644 --- a/ecmascript/compiler/type_info_accessors.h +++ b/ecmascript/compiler/type_info_accessors.h @@ -1361,6 +1361,7 @@ public: virtual bool IsHolderEqNewHolder(size_t index) const = 0; virtual void FetchPGORWTypesDual() = 0; virtual bool GenerateObjectAccessInfo() = 0; + virtual bool IsPrototypeHclass(size_t index) const = 0; }; class AotAccessorStrategy : public AccessorStrategy { @@ -1401,6 +1402,17 @@ public: return std::get(parent_.types_[index]) == std::get(parent_.types_[index]); } + + bool IsPrototypeHclass(size_t index) const override + { + ProfileTyper recv = std::get(parent_.types_[index]); + JSTaggedValue hclass = parent_.ptManager_->QueryHClass(recv.first, recv.second); + if (!hclass.IsJSHClass()) { + return false; + } + return JSHClass::Cast(hclass.GetTaggedObject())->IsPrototype(); + } + void FetchPGORWTypesDual() override; bool GenerateObjectAccessInfo() override; @@ -1443,6 +1455,12 @@ public: { return parent_.jitTypes_[index].GetHolderHclass() == parent_.jitTypes_[index].GetHolderTraHclass(); } + + bool IsPrototypeHclass(size_t index) const override + { + return parent_.jitTypes_[index].GetReceiverHclass()->IsPrototype(); + } + void FetchPGORWTypesDual() override; bool GenerateObjectAccessInfo() override; @@ -1484,6 +1502,11 @@ public: return strategy_->IsHolderEqNewHolder(index); } + bool IsPrototypeHclass(size_t index) const + { + return strategy_->IsPrototypeHclass(index); + } + GateRef GetValue() const { return value_; diff --git a/ecmascript/compiler/typed_bytecode_lowering.cpp b/ecmascript/compiler/typed_bytecode_lowering.cpp index 655aa03397..1773e9b195 100644 --- a/ecmascript/compiler/typed_bytecode_lowering.cpp +++ b/ecmascript/compiler/typed_bytecode_lowering.cpp @@ -762,7 +762,8 @@ void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate) value); } else { builder_.MonoStoreProperty(tacc.GetReceiver(), plrGate, unsharedConstPool, holderHClassIndex, value, - builder_.TruncInt64ToInt32(tacc.GetKey()), frameState); + builder_.TruncInt64ToInt32(tacc.GetKey()), + builder_.Boolean(tacc.IsPrototypeHclass(0)), frameState); } } else if (tacc.IsReceiverEqHolder(0)) { BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(), @@ -786,9 +787,10 @@ void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate) } if (tacc.IsReceiverNoEqNewHolder(i)) { builder_.ProtoChangeMarkerCheck(tacc.GetReceiver(), frameState); - auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET); if (tacc.IsHolderEqNewHolder(i)) { // lookup from receiver for holder + auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, + JSHClass::PROTOTYPE_OFFSET); auto holderHC = builder_.GetHClassGateFromIndex(gate, tacc.GetAccessInfo(i).HClassIndex()); DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype); Label loopHead(&builder_); @@ -811,52 +813,7 @@ void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate) tacc.GetAccessInfo(i).Plr()); builder_.Jump(&exit); } else { - // transition happened - Label notProto(&builder_); - Label isProto(&builder_); - auto newHolderHC = builder_.GetHClassGateFromIndex(gate, tacc.GetAccessInfo(i).HClassIndex()); - builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype); - builder_.Branch(builder_.IsProtoTypeHClass(receiverHC), &isProto, ¬Proto, - BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "isProtoTypeHClass"); - builder_.Bind(&isProto); - GateRef propKey = builder_.GetObjectByIndexFromConstPool( - glue_, gate, frameState, builder_.TruncInt64ToInt32(tacc.GetKey()), ConstPoolType::STRING); - builder_.CallRuntime(glue_, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef, - { receiverHC, newHolderHC, propKey }, gate); - builder_.Jump(¬Proto); - builder_.Bind(¬Proto); - MemoryAttribute mAttr = MemoryAttribute::NeedBarrierAndAtomic(); - builder_.StoreConstOffset(VariableType::JS_ANY(), tacc.GetReceiver(), - TaggedObject::HCLASS_OFFSET, newHolderHC, mAttr); - if (!tacc.GetAccessInfo(i).Plr().IsInlinedProps()) { - auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), tacc.GetReceiver(), - JSObject::PROPERTIES_OFFSET); - auto capacity = - builder_.LoadConstOffset(VariableType::INT32(), properties, TaggedArray::LENGTH_OFFSET); - auto index = builder_.Int32(tacc.GetAccessInfo(i).Plr().GetOffset()); - Label needExtend(&builder_); - Label notExtend(&builder_); - BRANCH_CIR(builder_.Int32UnsignedLessThan(index, capacity), ¬Extend, &needExtend); - builder_.Bind(¬Extend); - { - BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(), - tacc.GetValue(), tacc.GetAccessInfo(i).Plr()); - builder_.Jump(&exit); - } - builder_.Bind(&needExtend); - { - builder_.CallRuntime(glue_, - RTSTUB_ID(PropertiesSetValue), - Gate::InvalidGateRef, - { tacc.GetReceiver(), tacc.GetValue(), properties, builder_.Int32ToTaggedInt(capacity), - builder_.Int32ToTaggedInt(index) }, gate); - builder_.Jump(&exit); - } - } else { - BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(), - tacc.GetValue(), tacc.GetAccessInfo(i).Plr()); - builder_.Jump(&exit); - } + TypedStObjByNameTransition(gate, receiverHC, frameState, exit, tacc, i); } } else if (tacc.IsReceiverEqHolder(i)) { // Local @@ -878,6 +835,58 @@ void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate) DeleteConstDataIfNoUser(tacc.GetKey()); } +void TypedBytecodeLowering::TypedStObjByNameTransition(GateRef gate, GateRef receiverHC, GateRef frameState, + Label &exit, StoreObjByNameTypeInfoAccessor &tacc, size_t i) +{ + Label notProto(&builder_); + Label isProto(&builder_); + auto newHolderHC = builder_.GetHClassGateFromIndex(gate, tacc.GetAccessInfo(i).HClassIndex()); + if (compilationEnv_->IsAotCompiler()) { + auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET); + builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype); + } + if (!tacc.IsPrototypeHclass(i)) { + builder_.DeoptCheck(builder_.BoolNot(builder_.IsProtoTypeHClass(receiverHC)), frameState, + DeoptType::PROTOTYPECHANGED2); + } else { + builder_.Branch(builder_.IsProtoTypeHClass(receiverHC), &isProto, ¬Proto, + BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "isProtoTypeHClass"); + builder_.Bind(&isProto); + GateRef propKey = + builder_.GetObjectByIndexFromConstPool(glue_, gate, frameState, + builder_.TruncInt64ToInt32(tacc.GetKey()), ConstPoolType::STRING); + builder_.CallRuntime(glue_, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef, + { receiverHC, newHolderHC, propKey }, gate); + builder_.Jump(¬Proto); + builder_.Bind(¬Proto); + } + MemoryAttribute mAttr = MemoryAttribute::NeedBarrierAndAtomic(); + builder_.StoreConstOffset(VariableType::JS_ANY(), tacc.GetReceiver(), TaggedObject::HCLASS_OFFSET, + newHolderHC, mAttr); + if (!tacc.GetAccessInfo(i).Plr().IsInlinedProps()) { + auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), tacc.GetReceiver(), + JSObject::PROPERTIES_OFFSET); + auto capacity = builder_.LoadConstOffset(VariableType::INT32(), properties, TaggedArray::LENGTH_OFFSET); + auto index = builder_.Int32(tacc.GetAccessInfo(i).Plr().GetOffset()); + Label needExtend(&builder_); + Label notExtend(&builder_); + BRANCH_CIR(builder_.Int32UnsignedLessThan(index, capacity), ¬Extend, &needExtend); + builder_.Bind(¬Extend); + BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(), tacc.GetValue(), + tacc.GetAccessInfo(i).Plr()); + builder_.Jump(&exit); + builder_.Bind(&needExtend); + builder_.CallRuntime(glue_, RTSTUB_ID(PropertiesSetValue), Gate::InvalidGateRef, + { tacc.GetReceiver(), tacc.GetValue(), properties, builder_.Int32ToTaggedInt(capacity), + builder_.Int32ToTaggedInt(index) }, gate); + builder_.Jump(&exit); + } else { + BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(), tacc.GetValue(), + tacc.GetAccessInfo(i).Plr()); + builder_.Jump(&exit); + } +} + void TypedBytecodeLowering::LowerTypedStOwnByName(GateRef gate) { LowerTypedStObjByName(gate); diff --git a/ecmascript/compiler/typed_bytecode_lowering.h b/ecmascript/compiler/typed_bytecode_lowering.h index 0927049a9f..5917cc2932 100644 --- a/ecmascript/compiler/typed_bytecode_lowering.h +++ b/ecmascript/compiler/typed_bytecode_lowering.h @@ -124,6 +124,8 @@ private: void LowerTypedLdPrivateProperty(GateRef gate); void LowerTypedLdObjByName(GateRef gate); void LowerTypedStObjByName(GateRef gate); + void TypedStObjByNameTransition(GateRef gate, GateRef receiverHC, GateRef frameState, + Label &exit, StoreObjByNameTypeInfoAccessor &tacc, size_t i); void LowerTypedStOwnByName(GateRef gate); GateRef BuildNamedPropertyAccess(GateRef hir, GateRef receiver, GateRef holder, PropertyLookupResult plr); GateRef BuildNamedPropertyAccess(GateRef hir, GateRef receiver, GateRef holder, diff --git a/ecmascript/compiler/typed_hcr_lowering.cpp b/ecmascript/compiler/typed_hcr_lowering.cpp index a4a5a243b9..8d9d2be3fe 100644 --- a/ecmascript/compiler/typed_hcr_lowering.cpp +++ b/ecmascript/compiler/typed_hcr_lowering.cpp @@ -3180,25 +3180,34 @@ void TypedHCRLowering::LowerMonoStoreProperty(GateRef gate, GateRef glue) GateRef unsharedConstPool = acc_.GetValueIn(gate, 3); // 3: constPool GateRef value = acc_.GetValueIn(gate, 4); // 4: value GateRef keyIndex = acc_.GetValueIn(gate, 5); // 5: keyIndex + bool isPrototype = acc_.TryGetValue(acc_.GetValueIn(gate, 6)); // 6: proto flag Index PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult)); bool noBarrier = acc_.IsNoBarrier(gate); auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET); - auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET); // transition happened Label exit(&builder_); Label notProto(&builder_); Label isProto(&builder_); auto newHolderHC = builder_.LoadHClassFromConstpool(unsharedConstPool, acc_.GetConstantValue(hclassIndex)); - builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype); - builder_.Branch(builder_.IsProtoTypeHClass(receiverHC), &isProto, ¬Proto, - BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "isProtoTypeHClass"); - builder_.Bind(&isProto); - - GateRef propKey = builder_.GetObjectByIndexFromConstPool(glue, gate, frameState, keyIndex, ConstPoolType::STRING); - builder_.CallRuntime(glue, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef, - { receiverHC, newHolderHC, propKey }, gate); - builder_.Jump(¬Proto); - builder_.Bind(¬Proto); + if (compilationEnv_->IsAotCompiler()) { + auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET); + builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype); + } + if (!isPrototype) { + builder_.DeoptCheck(builder_.BoolNot(builder_.IsProtoTypeHClass(receiverHC)), frameState, + DeoptType::PROTOTYPECHANGED2); + } else { + builder_.Branch(builder_.IsProtoTypeHClass(receiverHC), &isProto, ¬Proto, + BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "isProtoTypeHClass"); + builder_.Bind(&isProto); + + GateRef propKey = + builder_.GetObjectByIndexFromConstPool(glue, gate, frameState, keyIndex, ConstPoolType::STRING); + builder_.CallRuntime(glue, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef, + { receiverHC, newHolderHC, propKey }, gate); + builder_.Jump(¬Proto); + builder_.Bind(¬Proto); + } MemoryAttribute mAttr = MemoryAttribute::NeedBarrierAndAtomic(); builder_.StoreConstOffset(VariableType::JS_ANY(), receiver, TaggedObject::HCLASS_OFFSET, newHolderHC, mAttr); if (!plr.IsInlinedProps()) { diff --git a/test/aottest/BUILD.gn b/test/aottest/BUILD.gn index 791549600a..e92adfd7bf 100644 --- a/test/aottest/BUILD.gn +++ b/test/aottest/BUILD.gn @@ -279,6 +279,7 @@ group("ark_aot_ts_test") { "stlettoglobalrecord", "stobjbyindex", "stobjbyname", + "stobjbyname1", "stobjbyvalue", "stownbyindex", "stownbyname", diff --git a/test/aottest/stobjbyname1/BUILD.gn b/test/aottest/stobjbyname1/BUILD.gn new file mode 100644 index 0000000000..8038061bfb --- /dev/null +++ b/test/aottest/stobjbyname1/BUILD.gn @@ -0,0 +1,22 @@ +# 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. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("stobjbyname1") { + deps = [] + is_only_typed_path = true + is_enable_pgo = true + is_enable_trace_deopt = true + log_option = " --log-info=trace" +} diff --git a/test/aottest/stobjbyname1/expect_output.txt b/test/aottest/stobjbyname1/expect_output.txt new file mode 100644 index 0000000000..875c58cf52 --- /dev/null +++ b/test/aottest/stobjbyname1/expect_output.txt @@ -0,0 +1,15 @@ +# 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. + +true +[trace] Check Type: InconsistentHClass6 diff --git a/test/aottest/stobjbyname1/pgo_expect_output.txt b/test/aottest/stobjbyname1/pgo_expect_output.txt new file mode 100644 index 0000000000..6728f3b86c --- /dev/null +++ b/test/aottest/stobjbyname1/pgo_expect_output.txt @@ -0,0 +1,14 @@ +# 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. + +false diff --git a/test/aottest/stobjbyname1/stobjbyname1.ts b/test/aottest/stobjbyname1/stobjbyname1.ts new file mode 100644 index 0000000000..7bbb79a4ab --- /dev/null +++ b/test/aottest/stobjbyname1/stobjbyname1.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +function A() { + this.a = 0; + this.b = 2; +} + +function test(a) { + a.c = 9 +} + +test(new A()); + +if (ArkTools.isAOTCompiled(test)) { + print(true); + let a = new A(); + function B() {} + B.prototype = a; + test(a); +} else { + print(false); +} diff --git a/test/jittest/BUILD.gn b/test/jittest/BUILD.gn index 703e6796e9..72080341a8 100644 --- a/test/jittest/BUILD.gn +++ b/test/jittest/BUILD.gn @@ -29,6 +29,7 @@ group("ark_jit_ts_test") { "addition_assignment", "catch_with_osr", "jit_test_0001", + "jit_test_0002", "string_length", "ts_inline", "proxy_fast_call", diff --git a/test/jittest/jit_test_0002/BUILD.gn b/test/jittest/jit_test_0002/BUILD.gn new file mode 100644 index 0000000000..9c31b4d9c2 --- /dev/null +++ b/test/jittest/jit_test_0002/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_jit_test_action("jit_test_0002") { + deps = [] + extra_option = " --log-info=trace --compiler-trace-deopt=true " +} diff --git a/test/jittest/jit_test_0002/expect_output.txt b/test/jittest/jit_test_0002/expect_output.txt new file mode 100644 index 0000000000..e7e8963e89 --- /dev/null +++ b/test/jittest/jit_test_0002/expect_output.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2024 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. + +[trace] Check Type: InconsistentHClass6 diff --git a/test/jittest/jit_test_0002/jit_test_0002.ts b/test/jittest/jit_test_0002/jit_test_0002.ts new file mode 100644 index 0000000000..50b2a60d7d --- /dev/null +++ b/test/jittest/jit_test_0002/jit_test_0002.ts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 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. + */ + +function A() { + this.a = 0; + this.b = 2; +} + +function test(a) { + a.c = 9 +} + +test(new A()); + +ArkTools.jitCompileAsync(test); +ArkTools.waitJitCompileFinish(test); + +let a = new A(); +function B() {} +B.prototype = a; +test(a); -- Gitee From 3c890df5220c4c1306c820adec25b9498816826d Mon Sep 17 00:00:00 2001 From: hecunmao Date: Tue, 29 Oct 2024 20:28:10 +0800 Subject: [PATCH 003/185] Regexp.prototype.source get error result Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IB0NG2 Signed-off-by: hecunmao Change-Id: Ia5b4f03e2259596afd189a0db541102bdb3cd04d --- ecmascript/builtins/builtins_regexp.cpp | 16 +++-- test/moduletest/regexp/expect_output.txt | 16 +++++ test/moduletest/regexp/regexp.js | 87 ++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 5 deletions(-) diff --git a/ecmascript/builtins/builtins_regexp.cpp b/ecmascript/builtins/builtins_regexp.cpp index b63df51bbc..8bbfefed9e 100644 --- a/ecmascript/builtins/builtins_regexp.cpp +++ b/ecmascript/builtins/builtins_regexp.cpp @@ -2431,11 +2431,17 @@ EcmaString *BuiltinsRegExp::EscapeRegExpPattern(JSThread *thread, const JSHandle if (srcStdStr.empty()) { srcStdStr = "(?:)"; } - // "/" -> "\/" - srcStdStr = base::StringHelper::ReplaceAll(srcStdStr, "/", "\\/"); - // "\\" -> "\" - srcStdStr = base::StringHelper::ReplaceAll(srcStdStr, "\\", "\\"); - + bool escapeChar = false; + for (int i = 0; i < srcStdStr.size(); i++) { + if (srcStdStr[i] == '\\') { + escapeChar=!escapeChar; + } else if (!escapeChar && srcStdStr[i]=='/') { + srcStdStr.insert(i, "\\"); + i++; + } else { + escapeChar = false; + } + } return *factory->NewFromUtf8(srcStdStr); } diff --git a/test/moduletest/regexp/expect_output.txt b/test/moduletest/regexp/expect_output.txt index 25d57ae82a..726ecf71d5 100644 --- a/test/moduletest/regexp/expect_output.txt +++ b/test/moduletest/regexp/expect_output.txt @@ -176,3 +176,19 @@ gs gu dg g +\/ ["/"] +\/[a-z]*> ["/style>"] +\/[a-z]*> ["/style>"] +\/[a-z]*> ["/style>"] +\\\/[a-z]*> ["\\/style>"] +\\\/[a-z]*> ["\\/style>"] +\\\/[a-z]*> ["\\/style>"] +\\\/[a-z]*> ["\\/style>"] +SyntaxError +SyntaxError +\[ ["["] +\[ ["["] +SyntaxError +SyntaxError +\\\[ ["\\["] +\\\[ ["\\["] \ No newline at end of file diff --git a/test/moduletest/regexp/regexp.js b/test/moduletest/regexp/regexp.js index 57be9cf3e1..201257e21b 100644 --- a/test/moduletest/regexp/regexp.js +++ b/test/moduletest/regexp/regexp.js @@ -726,3 +726,90 @@ print(res7.flags); const res8 = /abc/; res8.lastIndex = -1; print(res8.flags); + +{ + let str = "" + let reg = new RegExp("/"); + print(reg.source,JSON.stringify(reg.exec(str))); + + reg = new RegExp("\/[a-z]*>"); + print(reg.source,JSON.stringify(reg.exec(str))); + + reg = new RegExp("\\/[a-z]*>"); + print(reg.source,JSON.stringify(reg.exec(str))); + + reg = new RegExp("\\\/[a-z]*>"); + print(reg.source,JSON.stringify(reg.exec(str))); + + str="