From 104878d175f608b207a71e2650d2e04386da049c Mon Sep 17 00:00:00 2001 From: "yingguofeng@huawei.com" Date: Wed, 29 Sep 2021 20:46:00 +0800 Subject: [PATCH 001/115] Delete JSNativeObject Signed-off-by: yingguofeng@huawei.com Change-Id: I2f4a2e518497bf1f8a4724c63ef566cefed28271 Signed-off-by: yingguofeng@huawei.com --- ecmascript/builtins.cpp | 10 ---- ecmascript/builtins.h | 1 - ecmascript/global_env.h | 1 - ecmascript/js_hclass.h | 5 -- ecmascript/js_native_object.h | 78 ----------------------------- ecmascript/js_object.cpp | 10 +++- ecmascript/js_object.h | 3 +- ecmascript/js_tagged_value-inl.h | 5 -- ecmascript/js_tagged_value.h | 1 - ecmascript/linked_hash_table-inl.h | 10 ++-- ecmascript/mem/heap_roots-inl.h | 4 -- ecmascript/napi/include/jsnapi.h | 6 ++- ecmascript/napi/jsnapi.cpp | 17 +++---- ecmascript/object_factory-inl.h | 15 ------ ecmascript/object_factory.cpp | 20 +------- ecmascript/object_factory.h | 10 ++-- ecmascript/tests/js_object_test.cpp | 2 +- 17 files changed, 30 insertions(+), 168 deletions(-) delete mode 100644 ecmascript/js_native_object.h diff --git a/ecmascript/builtins.cpp b/ecmascript/builtins.cpp index 2395435..a74fe84 100644 --- a/ecmascript/builtins.cpp +++ b/ecmascript/builtins.cpp @@ -250,7 +250,6 @@ void Builtins::Initialize(const JSHandle &env, JSThread *thread) InitializeString(env, primRefObjDynclass); InitializeArrayBuffer(env, objFuncDynclass); InitializeDataView(env, objFuncDynclass); - InitializeJSNativeObject(env); JSHandle argumentsDynclass = factory_->CreateJSArguments(); env->SetArgumentsClass(thread_, argumentsDynclass); @@ -2724,13 +2723,4 @@ void Builtins::InitializePluralRules(const JSHandle &env) // 15.4.5 Intl.PluralRules.prototype.resolvedOptions () SetFunction(env, prPrototype, "resolvedOptions", PluralRules::ResolvedOptions, FunctionLength::ZERO); } - -void Builtins::InitializeJSNativeObject(const JSHandle &env) const -{ - [[maybe_unused]] EcmaHandleScope scope(thread_); - JSHandle dynclass = factory_->NewEcmaDynClass(JSNativeObject::SIZE, JSType::JS_NATIVE_OBJECT, - JSHandle(thread_, JSTaggedValue::Null())); - - env->SetJSNativeObjectClass(thread_, dynclass); -} } // namespace panda::ecmascript diff --git a/ecmascript/builtins.h b/ecmascript/builtins.h index 7a7753e..dcf2855 100644 --- a/ecmascript/builtins.h +++ b/ecmascript/builtins.h @@ -208,7 +208,6 @@ private: const JSHandle &getter, const JSHandle &setter) const; void SetGetter(const JSHandle &obj, const JSHandle &key, const JSHandle &getter) const; - void InitializeJSNativeObject(const JSHandle &env) const; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_BUILTINS_H diff --git a/ecmascript/global_env.h b/ecmascript/global_env.h index 6a9eff0..2181d1f 100644 --- a/ecmascript/global_env.h +++ b/ecmascript/global_env.h @@ -137,7 +137,6 @@ class JSThread; V(JSTaggedValue, JSIntlBoundFunctionClass, JS_INTL_BOUND_FUNCTION_CLASS) \ V(JSTaggedValue, NumberFormatLocales, NUMBER_FORMAT_LOCALES_INDEX) \ V(JSTaggedValue, DateTimeFormatLocales, DATE_TIMEFORMAT_LOCALES_INDEX) \ - V(JSTaggedValue, JSNativeObjectClass, JS_NATIVE_OBJECT_CLASS) \ V(JSTaggedValue, GlobalRecord, GLOBAL_RECORD) class GlobalEnv : public TaggedObject { diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index 7f29a49..486479f 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -335,11 +335,6 @@ public: return GetObjectType() == JSType::JS_NATIVE_POINTER; } - inline bool IsJSNativeObject() const - { - return GetObjectType() == JSType::JS_NATIVE_OBJECT; - } - inline bool IsJSSymbol() const { return GetObjectType() == JSType::SYMBOL; diff --git a/ecmascript/js_native_object.h b/ecmascript/js_native_object.h deleted file mode 100644 index 0b73f52..0000000 --- a/ecmascript/js_native_object.h +++ /dev/null @@ -1,78 +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_JSNATIVEOBJECT_H -#define ECMASCRIPT_JSNATIVEOBJECT_H - -#include "js_object.h" -#include "js_native_pointer.h" - -namespace panda::ecmascript { -class JSNativeObject : JSObject { -public: - static JSNativeObject *Cast(TaggedObject *object) - { - ASSERT(JSTaggedValue(object).IsJSNativeObject()); - return static_cast(object); - } - - inline void SetDeleter(DeleteEntryPoint deleter) - { - if (!GetJSNativePointer().IsJSNativePointer()) { - return; - } - JSNativePointer::Cast(GetJSNativePointer().GetHeapObject())->SetDeleter(deleter); - } - - inline void SetData(void *data) - { - if (!GetJSNativePointer().IsJSNativePointer()) { - return; - } - JSNativePointer::Cast(GetJSNativePointer().GetHeapObject())->SetData(data); - } - - inline const void *GetData() const - { - if (!GetJSNativePointer().IsJSNativePointer()) { - return nullptr; - } - return JSNativePointer::Cast(GetJSNativePointer().GetHeapObject())->GetData(); - } - - inline void Destroy() - { - if (!GetJSNativePointer().IsJSNativePointer()) { - return; - } - JSNativePointer::Cast(GetJSNativePointer().GetHeapObject())->Destroy(); - } - - inline void *GetExternalPointer() const - { - if (!GetJSNativePointer().IsJSNativePointer()) { - return nullptr; - } - return JSNativePointer::Cast(GetJSNativePointer().GetHeapObject())->GetExternalPointer(); - } - - static constexpr size_t OBJECT_OFFSET = JSObject::SIZE; - ACCESSORS(JSNativePointer, OBJECT_OFFSET, SIZE) - - DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, OBJECT_OFFSET, SIZE) -}; -} // namespace panda::ecmascript - -#endif // ECMASCRIPT_JSNATIVEOBJECT_H diff --git a/ecmascript/js_object.cpp b/ecmascript/js_object.cpp index 718f552..250875e 100644 --- a/ecmascript/js_object.cpp +++ b/ecmascript/js_object.cpp @@ -1946,7 +1946,8 @@ void *ECMAObject::GetNativePointerField(int32_t index) const return nullptr; } -void ECMAObject::SetNativePointerField(int32_t index, void *data) +void ECMAObject::SetNativePointerField(int32_t index, void *nativePointer, + const DeleteEntryPoint &callBack, void *data) { JSTaggedType hashField = Barriers::GetDynValue(this, HASH_OFFSET); JSTaggedValue value(hashField); @@ -1954,7 +1955,12 @@ void ECMAObject::SetNativePointerField(int32_t index, void *data) JSThread *thread = this->GetJSThread(); JSHandle array(thread, value); if (static_cast(array->GetLength()) > index + 1) { - JSHandle pointer = thread->GetEcmaVM()->GetFactory()->NewJSNativePointer(data); + EcmaVM *vm = thread->GetEcmaVM(); + JSHandle pointer = vm->GetFactory()->NewJSNativePointer( + nativePointer, callBack, data); + if (callBack != nullptr) { + vm->PushToArrayDataList(*pointer); + } array->Set(thread, index + 1, pointer.GetTaggedValue()); } } diff --git a/ecmascript/js_object.h b/ecmascript/js_object.h index 9030b10..9bfbb1a 100644 --- a/ecmascript/js_object.h +++ b/ecmascript/js_object.h @@ -345,7 +345,8 @@ public: } void* GetNativePointerField(int32_t index) const; - void SetNativePointerField(int32_t index, void *data); + void SetNativePointerField(int32_t index, void *nativePointer, + const DeleteEntryPoint &callBack, void *data); int32_t GetNativePointerFieldCount() const; void SetNativePointerFieldCount(int32_t count); diff --git a/ecmascript/js_tagged_value-inl.h b/ecmascript/js_tagged_value-inl.h index 27d6f86..56c75d0 100644 --- a/ecmascript/js_tagged_value-inl.h +++ b/ecmascript/js_tagged_value-inl.h @@ -382,11 +382,6 @@ inline bool JSTaggedValue::IsNativePointer() const return IsJSNativePointer(); } -inline bool JSTaggedValue::IsJSNativeObject() const -{ - return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSNativeObject(); -} - inline bool JSTaggedValue::IsJSNativePointer() const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSNativePointer(); diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index 1cd2204..b72cd79 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -233,7 +233,6 @@ public: bool IsTaggedArray() const; bool IsNativePointer() const; bool IsJSNativePointer() const; - bool IsJSNativeObject() const; bool IsBoolean() const; bool IsSymbol() const; bool IsJSObject() const; diff --git a/ecmascript/linked_hash_table-inl.h b/ecmascript/linked_hash_table-inl.h index b64e2c5..c4a8976 100644 --- a/ecmascript/linked_hash_table-inl.h +++ b/ecmascript/linked_hash_table-inl.h @@ -24,18 +24,14 @@ namespace panda::ecmascript { template JSTaggedValue LinkedHashTable::GetElement(int index) const { - if (UNLIKELY((index < 0 || index > static_cast(GetLength())))) { - return JSTaggedValue::Undefined(); - } + ASSERT(index >= 0 && index < static_cast(GetLength())); return Get(index); } template void LinkedHashTable::SetElement(const JSThread *thread, int index, JSTaggedValue element) { - if (UNLIKELY((index < 0 || index > static_cast(GetLength())))) { - return; - } + ASSERT(index >= 0 && index < static_cast(GetLength())); Set(thread, index, element); } @@ -272,4 +268,4 @@ bool LinkedHashMapObject::IsMatch(JSTaggedValue key, JSTaggedValue other) return JSTaggedValue::SameValueZero(key, other); } } // namespace panda::ecmascript -#endif // ECMASCRIPT_LINKED_HASH_TABLE_INL_H \ No newline at end of file +#endif // ECMASCRIPT_LINKED_HASH_TABLE_INL_H diff --git a/ecmascript/mem/heap_roots-inl.h b/ecmascript/mem/heap_roots-inl.h index e05ed38..e72b2de 100644 --- a/ecmascript/mem/heap_roots-inl.h +++ b/ecmascript/mem/heap_roots-inl.h @@ -41,7 +41,6 @@ #include "ecmascript/js_locale.h" #include "ecmascript/js_map.h" #include "ecmascript/js_map_iterator.h" -#include "ecmascript/js_native_object.h" #include "ecmascript/js_number_format.h" #include "ecmascript/js_object-inl.h" #include "ecmascript/js_primitive_ref.h" @@ -283,9 +282,6 @@ void HeapRootManager::MarkObjectBody(TaggedObject *object, JSHClass *klass, cons case JSType::JS_INTL_BOUND_FUNCTION: JSIntlBoundFunction::Cast(object)->VisitRangeSlot(visitor); break; - case JSType::JS_NATIVE_OBJECT: - JSNativeObject::Cast(object)->VisitRangeSlot(visitor); - break; default: UNREACHABLE(); } diff --git a/ecmascript/napi/include/jsnapi.h b/ecmascript/napi/include/jsnapi.h index 60a6196..ba44fb2 100644 --- a/ecmascript/napi/include/jsnapi.h +++ b/ecmascript/napi/include/jsnapi.h @@ -282,7 +282,6 @@ public: bool IsDataView(); bool IsTypedArray(); bool IsNativePointer(); - bool IsNativeObject(); bool IsDate(); bool IsError(); bool IsMap(); @@ -521,7 +520,10 @@ public: void SetNativePointerFieldCount(int32_t count); int32_t GetNativePointerFieldCount(); void *GetNativePointerField(int32_t index); - void SetNativePointerField(int32_t index, void *data); + void SetNativePointerField(int32_t index, + void *nativePointer = nullptr, + NativePointerCallback callBack = nullptr, + void *data = nullptr); }; using FunctionCallback = Local (*)(EcmaVM *, Local, diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index 37a8eaa..6a4ab36 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -69,7 +69,6 @@ using ecmascript::JSFunctionExtraInfo; using ecmascript::JSHClass; using ecmascript::JSMap; using ecmascript::JSMethod; -using ecmascript::JSNativeObject; using ecmascript::JSNativePointer; using ecmascript::JSObject; using ecmascript::JSPrimitiveRef; @@ -522,7 +521,7 @@ Local SymbolRef::GetDescription(const EcmaVM *vm) Local NativePointerRef::New(const EcmaVM *vm, void *nativePointer) { ObjectFactory *factory = vm->GetFactory(); - JSHandle obj = factory->NewJSNativeObject(nativePointer); + JSHandle obj = factory->NewJSNativePointer(nativePointer); return JSNApiHelper::ToLocal(JSHandle(obj)); } @@ -530,14 +529,14 @@ Local NativePointerRef::New( const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data) { ObjectFactory *factory = vm->GetFactory(); - JSHandle obj = factory->NewJSNativeObject(nativePointer, callBack, data); + JSHandle obj = factory->NewJSNativePointer(nativePointer, callBack, data); return JSNApiHelper::ToLocal(JSHandle(obj)); } void *NativePointerRef::Value() { JSHandle nativePointer = JSNApiHelper::ToJSHandle(this); - return JSHandle(nativePointer)->GetExternalPointer(); + return JSHandle(nativePointer)->GetExternalPointer(); } // ----------------------------------- ObjectRef ---------------------------------------- @@ -731,10 +730,11 @@ void *ObjectRef::GetNativePointerField(int32_t index) return object->GetNativePointerField(index); } -void ObjectRef::SetNativePointerField(int32_t index, void *data) +void ObjectRef::SetNativePointerField(int32_t index, void *nativePointer, + NativePointerCallback callBack, void *data) { JSHandle object(JSNApiHelper::ToJSHandle(this)); - object->SetNativePointerField(index, data); + object->SetNativePointerField(index, nativePointer, callBack, data); } // ----------------------------------- FunctionRef -------------------------------------- @@ -1671,11 +1671,6 @@ bool JSValueRef::IsNativePointer() return JSNApiHelper::ToJSTaggedValue(this).IsJSNativePointer(); } -bool JSValueRef::IsNativeObject() -{ - return JSNApiHelper::ToJSTaggedValue(this).IsJSNativeObject(); -} - bool JSValueRef::IsDate() { return JSNApiHelper::ToJSTaggedValue(this).IsDate(); diff --git a/ecmascript/object_factory-inl.h b/ecmascript/object_factory-inl.h index bc08129..402bf88 100644 --- a/ecmascript/object_factory-inl.h +++ b/ecmascript/object_factory-inl.h @@ -32,21 +32,6 @@ EcmaString *ObjectFactory::AllocStringObject(size_t size) return reinterpret_cast(heapHelper_.AllocateYoungGenerationOrHugeObject(stringClass_, size)); } -JSHandle ObjectFactory::NewJSNativePointer(void *externalPointer, bool nonMovable) -{ - TaggedObject *header; - if (nonMovable) { - header = heapHelper_.AllocateNonMovableOrHugeObject(jsNativePointerClass_); - } else { - header = heapHelper_.AllocateYoungGenerationOrHugeObject(jsNativePointerClass_); - } - JSHandle obj(thread_, header); - obj->SetExternalPointer(externalPointer); - obj->SetDeleter(nullptr); - obj->SetData(nullptr); - return obj; -} - JSHandle ObjectFactory::NewJSNativePointer(void *externalPointer, const DeleteEntryPoint &callBack, void *data, diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index 554f77f..505fa41 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -1318,14 +1318,14 @@ JSHandle ObjectFactory::NewInternalAccessor(void *setter, void *ge TaggedObject *header = heapHelper_.AllocateNonMovableOrHugeObject(internalAccessorClass_); JSHandle obj(thread_, AccessorData::Cast(header)); if (setter != nullptr) { - JSHandle setFunc = NewJSNativePointer(setter, true); + JSHandle setFunc = NewJSNativePointer(setter, nullptr, nullptr, true); obj->SetSetter(thread_, setFunc.GetTaggedValue()); } else { JSTaggedValue setFunc = JSTaggedValue::Undefined(); obj->SetSetter(thread_, setFunc); ASSERT(!obj->HasSetter()); } - JSHandle getFunc = NewJSNativePointer(getter, true); + JSHandle getFunc = NewJSNativePointer(getter, nullptr, nullptr, true); obj->SetGetter(thread_, getFunc); return obj; } @@ -2101,22 +2101,6 @@ uintptr_t ObjectFactory::NewSpaceBySnapShotAllocator(size_t size) return heapHelper_.AllocateSnapShotSpace(size); } -JSHandle ObjectFactory::NewJSNativeObject(void *externalPointer) -{ - return NewJSNativeObject(externalPointer, nullptr, nullptr); -} - -JSHandle ObjectFactory::NewJSNativeObject(void *externalPointer, DeleteEntryPoint callback, void *data) -{ - JSHandle env = vm_->GetGlobalEnv(); - JSHandle dynclass(env->GetJSNativeObjectClass()); - JSHandle nativeObject = JSHandle::Cast(NewJSObject(dynclass)); - JSHandle pointer = NewJSNativePointer(externalPointer, callback, data); - nativeObject->SetJSNativePointer(thread_, pointer.GetTaggedValue()); - vm_->PushToArrayDataList(*pointer); - return nativeObject; -} - JSHandle ObjectFactory::NewMachineCodeObject(size_t length, const uint8_t *data) { NewObjectHook(); diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index e4ac085..f155af6 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -21,7 +21,6 @@ #include "ecmascript/js_function_kind.h" #include "ecmascript/js_handle.h" #include "ecmascript/js_hclass.h" -#include "ecmascript/js_native_object.h" #include "ecmascript/js_native_pointer.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/machine_code.h" @@ -308,9 +307,10 @@ public: EcmaString *InternString(const JSHandle &key); - inline JSHandle NewJSNativePointer(void *externalPointer, bool nonMovable = false); - inline JSHandle NewJSNativePointer(void *externalPointer, const DeleteEntryPoint &callBack, - void *data, bool nonMovable = false); + inline JSHandle NewJSNativePointer(void *externalPointer, + const DeleteEntryPoint &callBack = nullptr, + void *data = nullptr, + bool nonMovable = false); JSHandle NewJSObjectByClass(const JSHandle &keys, const JSHandle &values); JSHandle NewJSObjectByClass(const JSHandle &properties, size_t length); @@ -333,8 +333,6 @@ public: uintptr_t NewSpaceBySnapShotAllocator(size_t size); JSHandle NewMachineCodeObject(size_t length, const uint8_t *data); - JSHandle NewJSNativeObject(void *externalPointer); - JSHandle NewJSNativeObject(void *externalPointer, DeleteEntryPoint callback, void *data); ~ObjectFactory() = default; diff --git a/ecmascript/tests/js_object_test.cpp b/ecmascript/tests/js_object_test.cpp index e004cb4..69a9ee1 100644 --- a/ecmascript/tests/js_object_test.cpp +++ b/ecmascript/tests/js_object_test.cpp @@ -1304,7 +1304,7 @@ HWTEST_F_L0(JSObjectTest, NativePointerField) obj->SetNativePointerFieldCount(1); char array[] = "Hello World!"; - obj->SetNativePointerField(0, array); + obj->SetNativePointerField(0, array, nullptr, nullptr); int32_t count = obj->GetNativePointerFieldCount(); EXPECT_TRUE(count == 1); void *pointer = obj->GetNativePointerField(0); -- Gitee From 8b8825786fef6dc60cba4a039ac96a436f8c4c22 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Sat, 9 Oct 2021 18:49:19 +0800 Subject: [PATCH 002/115] conflict Signed-off-by: songzhengchao --- BUILD.gn | 3 + ecmascript/compiler/BUILD.gn | 4 +- ecmascript/compiler/circuit_builder.cpp | 4 +- ecmascript/compiler/compile_llvm_lib.sh | 10 +- ecmascript/compiler/llvm/BUILD.gn | 23 + ecmascript/compiler/llvm/llvm.patch | 123 +++ .../llvm_stackmap_parser.cpp} | 51 +- .../llvm_stackmap_parser.h} | 19 +- ecmascript/compiler/llvm_ir_builder.cpp | 855 +++++++++++------- ecmascript/compiler/llvm_ir_builder.h | 94 +- ecmascript/compiler/tests/BUILD.gn | 3 +- ecmascript/compiler/tests/stub_tests.cpp | 55 +- ecmascript/frames.h | 134 ++- ecmascript/interpreter/frame_handler.cpp | 90 +- ecmascript/interpreter/frame_handler.h | 30 +- ecmascript/interpreter/interpreter-inl.h | 38 +- ecmascript/interpreter/interpreter.h | 3 +- ecmascript/js_thread.cpp | 5 +- ecmascript/js_thread.h | 1 + ecmascript/runtime_trampolines.cpp | 31 + ecmascript/runtime_trampolines.h | 28 + ecmascript/tests/test_helper.h | 3 +- ecmascript/tooling/BUILD.gn | 1 + llvm.patch | 121 +++ 24 files changed, 1288 insertions(+), 441 deletions(-) create mode 100644 ecmascript/compiler/llvm/BUILD.gn create mode 100644 ecmascript/compiler/llvm/llvm.patch rename ecmascript/compiler/{llvm_stackmap_parse.cpp => llvm/llvm_stackmap_parser.cpp} (71%) rename ecmascript/compiler/{llvm_stackmap_parse.h => llvm/llvm_stackmap_parser.h} (89%) create mode 100644 llvm.patch diff --git a/BUILD.gn b/BUILD.gn index bea20a7..7375b61 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -381,6 +381,7 @@ source_set("libark_jsruntime_static") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", + "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", sdk_libc_secshared_dep, ] @@ -446,6 +447,8 @@ ohos_shared_library("libark_jsruntime_test") { } else { deps += [ "$ark_root/runtime:libarkruntime" ] } + deps += + [ "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser" ] output_extension = "so" subsystem_name = "test" diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index 0cfb8f7..e9db2b7 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -47,7 +47,6 @@ source_set("libark_jsoptimizer_static") { "llvm_codegen.cpp", "llvm_ir_builder.cpp", "llvm_mcjit_engine.cpp", - "llvm_stackmap_parse.cpp", "scheduler.cpp", "stub.cpp", "stub_descriptor.cpp", @@ -138,6 +137,7 @@ ohos_shared_library("libark_jsoptimizer") { deps = [ ":libark_jsoptimizer_static", "//ark/js_runtime:libark_jsruntime", + "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", ] if (compile_llvm_online) { @@ -162,6 +162,8 @@ ohos_shared_library("libark_jsoptimizer_test") { if (is_standard_system) { deps += [ "$ark_root/runtime:libarkruntime_static" ] + deps += + [ "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser" ] } else { deps += [ "$ark_root/runtime:libarkruntime" ] } diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index 0fcc176..541311d 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -365,7 +365,7 @@ AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift targ AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, std::initializer_list args) { - ASSERT(descriptor->GetStubKind() == StubDescriptor::RUNTIME_STUB); + ASSERT(descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB); std::vector inputs; auto dependEntry = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY)); inputs.push_back(dependEntry); @@ -382,7 +382,7 @@ AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShi AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, AddrShift depend, std::initializer_list args) { - ASSERT(descriptor->GetStubKind() == StubDescriptor::RUNTIME_STUB); + ASSERT(descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB); std::vector inputs; inputs.push_back(depend); inputs.push_back(target); diff --git a/ecmascript/compiler/compile_llvm_lib.sh b/ecmascript/compiler/compile_llvm_lib.sh index 58c117e..0891662 100755 --- a/ecmascript/compiler/compile_llvm_lib.sh +++ b/ecmascript/compiler/compile_llvm_lib.sh @@ -25,20 +25,24 @@ echo ${BIN_PATH} echo ${BASE_HOME} if [ ! -d ${BASE_HOME}/third_party/llvm-project ]; then + cd ${BASE_HOME}/third_party dd if=/dev/zero of=/tmp/mem.swap bs=1M count=4096 - git clone https://gitee.com/github-repos/llvm-project.git + git clone https://gitee.com/surpassgoodchao/llvm-project.git fi cd ${BASE_HOME}/third_party/llvm-project if [ ! -d "build" ];then + git checkout -b local llvmorg-10.0.1 + cp ../../ark/js_runtime/ecmascript/compiler/llvm/llvm.patch . + git apply --reject llvm.patch mkdir build && cd build - cmake -GNinja -DCMAKE_BUILD_TYPE=Release ../llvm + cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_ARK_GC_SUPPORT=ON -DLLVM_ENABLE_TERMINFO=OFF DLLVM_STATIC_LINK_CXX_STDLIB=OFF -DLLVM_ENABLE_ZLIB=OFF ../llvm ninja else cd build if [ ! -d "lib" ]; then rm -rf * - cmake -GNinja -DCMAKE_BUILD_TYPE=Release ../llvm + cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_ARK_GC_SUPPORT=ON -DLLVM_ENABLE_TERMINFO=OFF DLLVM_STATIC_LINK_CXX_STDLIB=OFF -DLLVM_ENABLE_ZLIB=OFF ../llvm ninja fi fi diff --git a/ecmascript/compiler/llvm/BUILD.gn b/ecmascript/compiler/llvm/BUILD.gn new file mode 100644 index 0000000..5c930cd --- /dev/null +++ b/ecmascript/compiler/llvm/BUILD.gn @@ -0,0 +1,23 @@ +# 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. + +import("//ark/js_runtime/js_runtime_config.gni") +import("//build/ohos.gni") + +ohos_shared_library("libllvm_stackmap_parser") { + sources = [ "llvm_stackmap_parser.cpp" ] + + output_extension = "so" + relative_install_dir = "ark" + subsystem_name = "ark" +} diff --git a/ecmascript/compiler/llvm/llvm.patch b/ecmascript/compiler/llvm/llvm.patch new file mode 100644 index 0000000..73d0ec3 --- /dev/null +++ b/ecmascript/compiler/llvm/llvm.patch @@ -0,0 +1,123 @@ +diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt +index 0e85afa82c7..54a9152e44f 100644 +--- a/llvm/CMakeLists.txt ++++ b/llvm/CMakeLists.txt +@@ -505,8 +505,15 @@ option(LLVM_BUILD_RUNTIME + "Build the LLVM runtime libraries." ON) + option(LLVM_BUILD_EXAMPLES + "Build the LLVM example programs. If OFF, just generate build targets." OFF) ++option(BUILD_ARK_GC_SUPPORT ++ "ARK support GC. If ON, support GC." OFF) ++if(BUILD_ARK_GC_SUPPORT) ++ add_definitions(-DARK_GC_SUPPORT) ++endif(ARK_SUPPORT_GC) ++ + option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) + ++ + if(LLVM_BUILD_EXAMPLES) + add_definitions(-DBUILD_EXAMPLES) + endif(LLVM_BUILD_EXAMPLES) +diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp +index 1da20371caf..60d9af0d833 100644 +--- a/llvm/lib/Target/X86/X86FrameLowering.cpp ++++ b/llvm/lib/Target/X86/X86FrameLowering.cpp +@@ -31,6 +31,7 @@ + #include "llvm/Support/Debug.h" + #include "llvm/Target/TargetOptions.h" + #include ++#include + + using namespace llvm; + +@@ -1168,6 +1169,28 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, + else + MFI.setOffsetAdjustment(-StackSize); + } ++#ifdef ARK_GC_SUPPORT ++ // push marker ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ std::cout << __LINE__ << " marker:" << std::dec << marker << std::endl; ++ ++ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ /*reserve thread.fp */ ++ if (marker == 1) { ++ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ } ++ } ++#endif + + // For EH funclets, only allocate enough space for outgoing calls. Save the + // NumBytes value that we would've used for the parent frame. +@@ -1635,6 +1658,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, + uint64_t SEHStackAllocAmt = NumBytes; + + if (HasFP) { ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ ++ // pop marker ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ if (marker == 1) { ++ // pop thread.fp ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ } ++ } ++#endif + // Pop EBP. + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) +@@ -1993,8 +2037,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( + + if (hasFP(MF)) { + // emitPrologue always spills frame register the first thing. ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ if (marker == 1) { ++ SpillSlotOffset -= 3 * SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += 16; ++ } else { ++ SpillSlotOffset -= 2 * SlotSize; // add type ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += 8; ++ } ++ } else { ++ SpillSlotOffset -= SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ } ++#else + SpillSlotOffset -= SlotSize; + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++#endif + + // Since emitPrologue and emitEpilogue will handle spilling and restoring of + // the frame register, we can delete it from CSI list and not have to worry diff --git a/ecmascript/compiler/llvm_stackmap_parse.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp similarity index 71% rename from ecmascript/compiler/llvm_stackmap_parse.cpp rename to ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index e49ed47..730413c 100644 --- a/ecmascript/compiler/llvm_stackmap_parse.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "ecmascript/compiler/llvm_stackmap_parse.h" +#include "llvm_stackmap_parser.h" #include #include #include @@ -37,18 +37,55 @@ std::string LocationTy::TypeToString(Kind location) const } } -bool LLVMStackMapParse::StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetType &info) +bool LLVMStackMapParser::StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTypeVector &infos) { + bool found = false; for (auto it: callSiteInfos_) { if (it.first == funcAddr) { - info = it.second; - return true; + DwarfRegAndOffsetType info = it.second; + infos.push_back(info); + found = true; } } - return false; + return found; } -void LLVMStackMapParse::CalcCallSite() +bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t frameFp, + std::vector &slotAddrs) +{ + DwarfRegAndOffsetTypeVector infos; + if (!StackMapByAddr(funcAddr, infos)) { + return false; + } +#ifdef PANDA_TARGET_AMD64 + uintptr_t *rbp = reinterpret_cast(frameFp); + uintptr_t returnAddr = *(rbp + 1); + uintptr_t *rsp = rbp + 2; // 2: rsp offset + rbp = reinterpret_cast(*rbp); + uintptr_t **address = nullptr; + for (auto &info: infos) { + if (info.first == 7) { // 7: rsp for x86_64 + address = reinterpret_cast(reinterpret_cast(rsp) + info.second); + // rbp + } else if (info.first == 6) { // 6: rbp for x86_64 + address = reinterpret_cast(reinterpret_cast(rbp) + info.second); + } else { + address = nullptr; + abort(); + } + std::cout << std::hex << "ref addr:" << address; + std::cout << " value:" << *address; + std::cout << " *value :" << **address << std::endl; + slotAddrs.push_back(reinterpret_cast(address)); + } +#else + (void)frameFp; + (void)slotAddrs; +#endif + return true; +} + +void LLVMStackMapParser::CalcCallSite() { uint64_t recordNum = 0; for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) { @@ -74,7 +111,7 @@ void LLVMStackMapParse::CalcCallSite() } } -bool LLVMStackMapParse::CalculateStackMap(const uint8_t *stackMapAddr) +bool LLVMStackMapParser::CalculateStackMap(const uint8_t *stackMapAddr) { stackMapAddr_ = stackMapAddr; if (!stackMapAddr_) { diff --git a/ecmascript/compiler/llvm_stackmap_parse.h b/ecmascript/compiler/llvm/llvm_stackmap_parser.h similarity index 89% rename from ecmascript/compiler/llvm_stackmap_parse.h rename to ecmascript/compiler/llvm/llvm_stackmap_parser.h index e22e554..873e389 100644 --- a/ecmascript/compiler/llvm_stackmap_parse.h +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.h @@ -25,6 +25,7 @@ namespace kungfu { using OffsetType = int32_t; using DwarfRegType = uint16_t; using DwarfRegAndOffsetType = std::pair; +using DwarfRegAndOffsetTypeVector = std::vector; using Fun2InfoType = std::pair; struct Header { @@ -132,7 +133,7 @@ struct StkMapRecordTy { class DataInfo { public: - explicit DataInfo(const uint8_t* data): data_(data), offset(0) {} + explicit DataInfo(const uint8_t *data): data_(data), offset(0) {} ~DataInfo() { data_ = nullptr; @@ -150,7 +151,7 @@ public: return offset; } private: - const uint8_t* data_; + const uint8_t *data_; unsigned int offset; }; @@ -177,11 +178,11 @@ struct LLVMStackMap { } }; -class LLVMStackMapParse { +class LLVMStackMapParser { public: - static LLVMStackMapParse& GetInstance() + static LLVMStackMapParser& GetInstance() { - static LLVMStackMapParse instance; + static LLVMStackMapParser instance; return instance; } bool CalculateStackMap(const uint8_t *stackMapAddr); @@ -189,15 +190,17 @@ public: { llvmStackMap_.Print(); } - bool StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetType &info); + bool StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTypeVector &infos); + bool StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t frameFp, + std::vector &slotAddrs); private: - LLVMStackMapParse() + LLVMStackMapParser() { stackMapAddr_ = nullptr; callSiteInfos_.clear(); dataInfo_ = nullptr; } - ~LLVMStackMapParse() + ~LLVMStackMapParser() { stackMapAddr_ = nullptr; callSiteInfos_.clear(); diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 388aed1..6901890 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -15,6 +15,7 @@ #include "ecmascript/compiler/llvm_ir_builder.h" +#include #include #include "ecmascript/compiler/circuit.h" @@ -80,6 +81,90 @@ int LLVMIRBuilder::FindBasicBlock(AddrShift gate) const return -1; } +void LLVMIRBuilder::AssignHandleMap() +{ + opCodeHandleMap_ = {{OpCode::STATE_ENTRY, &LLVMIRBuilder::HandleGoto}, + {OpCode::RETURN, &LLVMIRBuilder::HandleReturn}, + {OpCode::IF_BRANCH, &LLVMIRBuilder::HandleBranch}, {OpCode::SWITCH_BRANCH, &LLVMIRBuilder::HandleSwitch}, + {OpCode::ORDINARY_BLOCK, &LLVMIRBuilder::HandleGoto}, {OpCode::IF_TRUE, &LLVMIRBuilder::HandleGoto}, + {OpCode::IF_FALSE, &LLVMIRBuilder::HandleGoto}, {OpCode::SWITCH_CASE, &LLVMIRBuilder::HandleGoto}, + {OpCode::MERGE, &LLVMIRBuilder::HandleGoto}, {OpCode::DEFAULT_CASE, &LLVMIRBuilder::HandleGoto}, + {OpCode::LOOP_BEGIN, &LLVMIRBuilder::HandleGoto}, {OpCode::LOOP_BACK, &LLVMIRBuilder::HandleGoto}, + {OpCode::VALUE_SELECTOR_INT1, &LLVMIRBuilder::HandlePhi}, + {OpCode::VALUE_SELECTOR_INT32, &LLVMIRBuilder::HandlePhi}, + {OpCode::VALUE_SELECTOR_INT64, &LLVMIRBuilder::HandlePhi}, + {OpCode::VALUE_SELECTOR_FLOAT64, &LLVMIRBuilder::HandlePhi}, + {OpCode::CALL, &LLVMIRBuilder::HandleCall}, {OpCode::INT1_CALL, &LLVMIRBuilder::HandleCall}, + {OpCode::INT32_CALL, &LLVMIRBuilder::HandleCall}, {OpCode::FLOAT64_CALL, &LLVMIRBuilder::HandleCall}, + {OpCode::INT64_CALL, &LLVMIRBuilder::HandleCall}, {OpCode::ALLOCA, &LLVMIRBuilder::HandleAlloca}, + {OpCode::INT1_ARG, &LLVMIRBuilder::HandleParameter}, {OpCode::INT32_ARG, &LLVMIRBuilder::HandleParameter}, + {OpCode::INT64_ARG, &LLVMIRBuilder::HandleParameter}, + {OpCode::INT32_CONSTANT, &LLVMIRBuilder::HandleInt32Constant}, + {OpCode::JS_CONSTANT, &LLVMIRBuilder::HandleInt64Constant}, + {OpCode::INT64_CONSTANT, &LLVMIRBuilder::HandleInt64Constant}, + {OpCode::FLOAT64_CONSTANT, &LLVMIRBuilder::HandleFloat64Constant}, + {OpCode::ZEXT_INT1_TO_INT32, &LLVMIRBuilder::HandleZExtInt}, + {OpCode::ZEXT_INT32_TO_INT64, &LLVMIRBuilder::HandleZExtInt}, + {OpCode::ZEXT_INT1_TO_INT64, &LLVMIRBuilder::HandleZExtInt}, + {OpCode::SEXT_INT1_TO_INT32, &LLVMIRBuilder::HandleSExtInt}, + {OpCode::SEXT_INT1_TO_INT64, &LLVMIRBuilder::HandleSExtInt}, + {OpCode::SEXT_INT32_TO_INT64, &LLVMIRBuilder::HandleSExtInt}, + {OpCode::TRUNC_INT64_TO_INT1, &LLVMIRBuilder::HandleCastIntXToIntY}, + {OpCode::TRUNC_INT32_TO_INT1, &LLVMIRBuilder::HandleCastIntXToIntY}, + {OpCode::TRUNC_INT64_TO_INT32, &LLVMIRBuilder::HandleCastIntXToIntY}, + {OpCode::INT32_REV, &LLVMIRBuilder::HandleIntRev}, + {OpCode::INT64_REV, &LLVMIRBuilder::HandleIntRev}, + {OpCode::INT32_ADD, &LLVMIRBuilder::HandleIntAdd}, + {OpCode::INT64_ADD, &LLVMIRBuilder::HandleIntAdd}, + {OpCode::FLOAT64_ADD, &LLVMIRBuilder::HandleFloatAdd}, + {OpCode::FLOAT64_SUB, &LLVMIRBuilder::HandleFloatSub}, + {OpCode::FLOAT64_MUL, &LLVMIRBuilder::HandleFloatMul}, + {OpCode::FLOAT64_DIV, &LLVMIRBuilder::HandleFloatDiv}, + {OpCode::INT32_SUB, &LLVMIRBuilder::HandleIntSub}, + {OpCode::INT64_SUB, &LLVMIRBuilder::HandleIntSub}, + {OpCode::INT32_MUL, &LLVMIRBuilder::HandleIntMul}, + {OpCode::INT64_MUL, &LLVMIRBuilder::HandleIntMul}, + {OpCode::INT32_AND, &LLVMIRBuilder::HandleIntAnd}, + {OpCode::INT64_AND, &LLVMIRBuilder::HandleIntAnd}, + {OpCode::INT32_OR, &LLVMIRBuilder::HandleIntOr}, + {OpCode::INT64_OR, &LLVMIRBuilder::HandleIntOr}, + {OpCode::INT64_XOR, &LLVMIRBuilder::HandleIntXor}, + {OpCode::INT32_LSR, &LLVMIRBuilder::HandleIntLsr}, + {OpCode::INT64_LSR, &LLVMIRBuilder::HandleIntLsr}, + {OpCode::INT32_SLT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_SLT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_ULT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_ULT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_SLE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_SLE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_SGT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_SGT, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_SGE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_SGE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_EQ, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_EQ, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::FLOAT64_EQ, &LLVMIRBuilder::HandleFloatOrDoubleCmp}, + {OpCode::INT32_NE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT64_NE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT32_LOAD, &LLVMIRBuilder::HandleLoad}, + {OpCode::INT64_LOAD, &LLVMIRBuilder::HandleLoad}, + {OpCode::INT32_STORE, &LLVMIRBuilder::HandleStore}, + {OpCode::INT64_STORE, &LLVMIRBuilder::HandleStore}, + {OpCode::INT32_TO_FLOAT64, &LLVMIRBuilder::HandleCastInt32ToDouble}, + {OpCode::INT64_TO_FLOAT64, &LLVMIRBuilder::HandleCastInt64ToDouble}, + {OpCode::FLOAT64_TO_INT64, &LLVMIRBuilder::HandleCastDoubleToInt}, + {OpCode::INT32_LSL, &LLVMIRBuilder::HandleIntLsl}, + {OpCode::INT64_LSL, &LLVMIRBuilder::HandleIntLsl}, + {OpCode::FLOAT64_SMOD, &LLVMIRBuilder::HandleFloatMod}, + {OpCode::INT32_SMOD, &LLVMIRBuilder::HandleIntMod}, + + }; + opCodeHandleIgnore= {OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY, + OpCode::FRAMESTATE_ENTRY, OpCode::RETURN_LIST, OpCode::THROW_LIST, + OpCode::CONSTANT_LIST, OpCode::ARG_LIST, OpCode::THROW, + OpCode::DEPEND_SELECTOR, OpCode::DEPEND_RELAY, OpCode::DEPEND_AND}; +} + void LLVMIRBuilder::Build() { LOG_ECMA(INFO) << "LLVM IR Builder Create Id Map of Blocks..."; @@ -89,8 +174,8 @@ void LLVMIRBuilder::Build() instIdMapBbId_[gateId] = bbIdx; } } - LOG_ECMA(INFO) << "LLVM IR Builder Visit Gate..."; + AssignHandleMap(); for (size_t bbIdx = 0; bbIdx < (*schedule_).size(); bbIdx++) { OperandsVector predecessors; for (auto in : circuit_->GetInVector((*schedule_)[bbIdx][0])) { @@ -105,310 +190,17 @@ void LLVMIRBuilder::Build() AddrShift gate = (*schedule_)[bbIdx][instIdx - 1]; std::vector ins = circuit_->GetInVector(gate); std::vector outs = circuit_->GetOutVector(gate); - switch (circuit_->GetOpCode(gate)) { - case OpCode::NOP: - break; - case OpCode::CIRCUIT_ROOT: - break; - case OpCode::STATE_ENTRY: { - int block = instIdMapBbId_[circuit_->GetId(gate)]; - int bbOut = instIdMapBbId_[circuit_->GetId(outs[0])]; - VisitGoto(block, bbOut); - break; - } - case OpCode::DEPEND_ENTRY: - break; - case OpCode::FRAMESTATE_ENTRY: - break; - case OpCode::RETURN_LIST: - break; - case OpCode::THROW_LIST: - break; - case OpCode::CONSTANT_LIST: - break; - case OpCode::ARG_LIST: - break; - case OpCode::RETURN: { - // [STATE] [DEPEND] [VALUE] [RETURN_LIST] - VisitReturn(gate, 1, ins); - break; - } - case OpCode::THROW: - break; - case OpCode::IF_BRANCH: { - AddrShift bTrue = (circuit_->GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1]; - AddrShift bFalse = (circuit_->GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1]; - int bbTrue = instIdMapBbId_[circuit_->GetId(bTrue)]; - int bbFalse = instIdMapBbId_[circuit_->GetId(bFalse)]; - VisitBranch(gate, ins[1], bbTrue, bbFalse); - break; - } - case OpCode::SWITCH_BRANCH: { - VisitSwitch(gate, ins[1], outs); - break; - } - case OpCode::ORDINARY_BLOCK: - case OpCode::IF_TRUE: - case OpCode::IF_FALSE: - case OpCode::SWITCH_CASE: - case OpCode::DEFAULT_CASE: { - int block = instIdMapBbId_[circuit_->GetId(gate)]; - int bbOut = instIdMapBbId_[circuit_->GetId(outs[0])]; - VisitGoto(block, bbOut); - break; - } - case OpCode::MERGE: { - int block = instIdMapBbId_[circuit_->GetId(gate)]; - int bbOut; - for (int i = 0; i < static_cast(outs.size()); i++) { - bbOut = instIdMapBbId_[circuit_->GetId(outs[i])]; - VisitGoto(block, bbOut); - } - break; - } - case OpCode::LOOP_BEGIN: { - int block = instIdMapBbId_[circuit_->GetId(gate)]; - int bbOut; - for (int i = 0; i < static_cast(outs.size()); i++) { - bbOut = instIdMapBbId_[circuit_->GetId(outs[i])]; - VisitGoto(block, bbOut); - } - break; - } - case OpCode::LOOP_BACK: { - int block = instIdMapBbId_[circuit_->GetId(gate)]; - int bbOut = instIdMapBbId_[circuit_->GetId(outs[0])]; - VisitGoto(block, bbOut); - break; - } - case OpCode::VALUE_SELECTOR_INT1: { - VisitPhi(gate, ins, MachineRep::K_BIT); - break; - } - case OpCode::VALUE_SELECTOR_INT32: { - VisitPhi(gate, ins, MachineRep::K_WORD32); - break; - } - case OpCode::VALUE_SELECTOR_INT64: { - VisitPhi(gate, ins, MachineRep::K_WORD64); - break; - } - case OpCode::VALUE_SELECTOR_FLOAT64: { - VisitPhi(gate, ins, MachineRep::K_FLOAT64); - break; - } - case OpCode::DEPEND_SELECTOR: - break; - case OpCode::DEPEND_RELAY: - break; - case OpCode::CALL: - case OpCode::INT1_CALL: - case OpCode::INT32_CALL: - case OpCode::INT64_CALL: { - VisitCall(gate, ins); - break; - } - case OpCode::ALLOCA: { - VisitAlloca(gate); - break; - } - case OpCode::INT1_ARG: // no break, fall through - case OpCode::INT32_ARG: // no break, fall through - case OpCode::INT64_ARG: { - VisitParameter(gate); - break; - } - case OpCode::INT32_CONSTANT: { - int32_t value = circuit_->GetBitField(gate); - VisitInt32Constant(gate, value); - break; - } - case OpCode::JS_CONSTANT: // no break, fall through - case OpCode::INT64_CONSTANT: { - int64_t value = circuit_->GetBitField(gate); - VisitInt64Constant(gate, value); - break; - } - case OpCode::FLOAT64_CONSTANT: { - int64_t value = circuit_->GetBitField(gate); - double doubleValue = bit_cast(value); // actual double value - VisitFloat64Constant(gate, doubleValue); - break; - } - case OpCode::ZEXT_INT1_TO_INT32: { - VisitZExtInt(gate, ins[0], MachineRep::K_WORD32); - break; - } - case OpCode::ZEXT_INT32_TO_INT64: // no break, fall through - case OpCode::ZEXT_INT1_TO_INT64: { - VisitZExtInt(gate, ins[0], MachineRep::K_WORD64); - break; - } - case OpCode::SEXT_INT1_TO_INT32: { - VisitSExtInt(gate, ins[0], MachineRep::K_WORD32); - break; - } - case OpCode::SEXT_INT1_TO_INT64: // no break, fall through - case OpCode::SEXT_INT32_TO_INT64: { - VisitSExtInt(gate, ins[0], MachineRep::K_WORD64); - break; - } - case OpCode::TRUNC_INT64_TO_INT1: - case OpCode::TRUNC_INT32_TO_INT1: { - VisitCastIntXToIntY(gate, ins[0], MachineRep::K_BIT); - break; - } - case OpCode::TRUNC_INT64_TO_INT32: { - VisitCastIntXToIntY(gate, ins[0], MachineRep::K_WORD32); - break; - } - case OpCode::INT32_REV: // no break, fall through - case OpCode::INT64_REV: { - VisitIntRev(gate, ins[0]); - break; - } - case OpCode::INT32_ADD: { - VisitIntAdd(gate, ins[0], ins[1], MachineRep::K_WORD32); - break; - } - case OpCode::INT64_ADD: { - VisitIntAdd(gate, ins[0], ins[1], MachineRep::K_WORD64); - break; - } - case OpCode::FLOAT64_ADD: { - VisitFloatAdd(gate, ins[0], ins[1]); - break; - } - case OpCode::FLOAT64_SUB: { - VisitFloatSub(gate, ins[0], ins[1]); - break; - } - case OpCode::FLOAT64_MUL: { - VisitFloatMul(gate, ins[0], ins[1]); - break; - } - case OpCode::FLOAT64_DIV: { - VisitFloatDiv(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_SUB: // no break, fall through - case OpCode::INT64_SUB: { - VisitIntSub(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_MUL: // no break, fall through - case OpCode::INT64_MUL: { - VisitIntMul(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_AND: // no break, fall through - case OpCode::INT64_AND: { - VisitIntAnd(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_OR: // no break, fall through - case OpCode::INT64_OR: { - VisitIntOr(gate, ins[0], ins[1]); - break; - } - case OpCode::INT64_XOR: { - VisitIntXor(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_LSR: // no break, fall through - case OpCode::INT64_LSR: { - VisitIntLsr(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_LSL: // no break, fall through - case OpCode::INT64_LSL: { - VisitIntLsl(gate, ins[0], ins[1]); - break; - } - case OpCode::INT32_SLT: // no break, fall through - case OpCode::INT64_SLT: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSLT); - break; - } - case OpCode::INT32_ULT: // no break, fall through - case OpCode::INT64_ULT: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntULT); - break; - } - case OpCode::INT32_SLE: // no break, fall through - case OpCode::INT64_SLE: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSLE); - break; - } - case OpCode::INT32_SGT: // no break, fall through - case OpCode::INT64_SGT: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSGT); - break; - } - case OpCode::INT32_SGE: // no break, fall through - case OpCode::INT64_SGE: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSGE); - break; - } - case OpCode::INT32_EQ: // no break, fall through - case OpCode::INT64_EQ: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntEQ); - break; - } - case OpCode::FLOAT64_EQ: { - VisitFloatOrDoubleCmp(gate, ins[0], ins[1], LLVMRealOEQ); - break; - } - case OpCode::INT32_NE: // no break, fall through - case OpCode::INT64_NE: { - VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntNE); - break; - } - case OpCode::INT32_LOAD: { - AddrShift base = ins[1]; - VisitLoad(gate, MachineRep::K_WORD32, base); - break; - } - case OpCode::INT64_LOAD: { - AddrShift base = ins[1]; - VisitLoad(gate, MachineRep::K_WORD64, base); - break; - } - case OpCode::INT32_STORE: { - VisitStore(gate, MachineRep::K_WORD32, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate - break; - } - case OpCode::INT64_STORE: { - VisitStore(gate, MachineRep::K_WORD64, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate - break; - } - case OpCode::INT32_TO_FLOAT64: { - VisitCastInt32ToDouble(gate, ins[0]); - break; - } - case OpCode::INT64_TO_FLOAT64: { - VisitCastInt64ToDouble(gate, ins[0]); - break; - } - case OpCode::FLOAT64_TO_INT64: { - VisitCastDoubleToInt(gate, ins[0]); - break; - } - case OpCode::DEPEND_AND: - break; - case OpCode::INT32_SMOD: { - VisitIntMod(gate, ins[0], ins[1]); - break; - } - case OpCode::FLOAT64_SMOD: { - VisitFloatMod(gate, ins[0], ins[1]); - break; - } - default: { - LOG_ECMA(ERROR) << "The gate below need to be translated "; - circuit_->Print(gate); - UNREACHABLE(); - } + std::cout << "instIdx :" << instIdx << std::endl; + circuit_->Print(gate); + auto found = opCodeHandleMap_.find(circuit_->GetOpCode(gate)); + if (found != opCodeHandleMap_.end()) { + (this->*(found->second))(gate); + continue; + } + if (opCodeHandleIgnore.find(circuit_->GetOpCode(gate)) == opCodeHandleIgnore.end()) { + LOG_ECMA(ERROR) << "The gate below need to be translated "; + circuit_->Print(gate); + UNREACHABLE(); } } } @@ -507,7 +299,7 @@ void LLVMIRBuilder::PrologueHandle(LLVMModuleRef &module, LLVMBuilderRef &builde return; } - LLVMValueRef baseAddr = LLVMCallingFp(module_, builder_); + LLVMValueRef llvmFpAddr = LLVMCallingFp(module_, builder_); /* current frame 0 pre rbp <-- rbp -8 type @@ -521,7 +313,8 @@ void LLVMIRBuilder::PrologueHandle(LLVMModuleRef &module, LLVMBuilderRef &builde LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(LLVMInt64Type(), 0), ""); LLVMValueRef threadFpValue = LLVMBuildLoad(builder_, rtbaseAddr, ""); - LLVMValueRef value = LLVMBuildStore(builder_, threadFpValue, baseAddr); + LLVMValueRef value = LLVMBuildStore(builder_, threadFpValue, + LLVMBuildIntToPtr(builder_, llvmFpAddr, LLVMPointerType(LLVMInt64Type(), 0), "cast")); LOG_ECMA(INFO) << "store value:" << value << " " << "value type" << LLVMTypeOf(value); } @@ -585,6 +378,24 @@ LLVMTypeRef LLVMIRBuilder::GetMachineRepType(MachineRep rep) const return dstType; } +void LLVMIRBuilder::HandleCall(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::CALL: + case OpCode::INT1_CALL: + case OpCode::INT32_CALL: + case OpCode::FLOAT64_CALL: + case OpCode::INT64_CALL: { + VisitCall(gate, ins); + break; + } + default: { + break; + } + } +} + void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inList) { int paraStartIndex = 2; @@ -626,6 +437,11 @@ void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inLi return; } +void LLVMIRBuilder::HandleAlloca(AddrShift gate) +{ + return VisitAlloca(gate); +} + void LLVMIRBuilder::VisitAlloca(AddrShift gate) { uint64_t sizeEnum = circuit_->GetBitField(gate); @@ -636,6 +452,32 @@ void LLVMIRBuilder::VisitAlloca(AddrShift gate) return; } +void LLVMIRBuilder::HandlePhi(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::VALUE_SELECTOR_INT1: { + VisitPhi(gate, ins, MachineRep::K_BIT); + break; + } + case OpCode::VALUE_SELECTOR_INT32: { + VisitPhi(gate, ins, MachineRep::K_WORD32); + break; + } + case OpCode::VALUE_SELECTOR_INT64: { + VisitPhi(gate, ins, MachineRep::K_WORD64); + break; + } + case OpCode::VALUE_SELECTOR_FLOAT64: { + VisitPhi(gate, ins, MachineRep::K_FLOAT64); + break; + } + default: { + break; + } + } +} + void LLVMIRBuilder::VisitPhi(AddrShift gate, const std::vector &srcGates, MachineRep rep) { LLVMTypeRef type = GetMachineRepType(rep); @@ -694,6 +536,12 @@ void LLVMIRBuilder::VisitReturn(AddrShift gate, AddrShift popCount, const std::v LLVMBuildRet(builder_, returnValue); } +void LLVMIRBuilder::HandleReturn(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitReturn(gate, 1, ins); +} + void LLVMIRBuilder::VisitBlock(int gate, const OperandsVector &predecessors) // NOLINTNEXTLINE(misc-unused-parameters) { LOG_ECMA(INFO) << " BBIdx:" << gate; @@ -721,6 +569,27 @@ void LLVMIRBuilder::VisitBlock(int gate, const OperandsVector &predecessors) // } } +void LLVMIRBuilder::HandleGoto(AddrShift gate) +{ + std::vector outs = circuit_->GetOutVector(gate); + int block = instIdMapBbId_[circuit_->GetId(gate)]; + int bbOut = instIdMapBbId_[circuit_->GetId(outs[0])]; + switch (circuit_->GetOpCode(gate)) { + case OpCode::MERGE: + case OpCode::LOOP_BEGIN: { + for (int i = 0; i < static_cast(outs.size()); i++) { + bbOut = instIdMapBbId_[circuit_->GetId(outs[i])]; + VisitGoto(block, bbOut); + } + break; + } + default: { + VisitGoto(block, bbOut); + break; + } + } +} + void LLVMIRBuilder::VisitGoto(int block, int bbOut) { if (block == bbOut) { @@ -737,6 +606,63 @@ void LLVMIRBuilder::VisitGoto(int block, int bbOut) EndCurrentBlock(); } +void LLVMIRBuilder::HandleInt32Constant(AddrShift gate) +{ + int32_t value = circuit_->GetBitField(gate); + VisitInt32Constant(gate, value); +} + +void LLVMIRBuilder::HandleInt64Constant(AddrShift gate) +{ + int64_t value = circuit_->GetBitField(gate); + VisitInt64Constant(gate, value); +} + +void LLVMIRBuilder::HandleFloat64Constant(AddrShift gate) +{ + int64_t value = circuit_->GetBitField(gate); + double doubleValue = bit_cast(value); // actual double value + VisitFloat64Constant(gate, doubleValue); +} + +void LLVMIRBuilder::HandleZExtInt(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::ZEXT_INT1_TO_INT32: { + VisitZExtInt(gate, ins[0], MachineRep::K_WORD32); + break; + } + case OpCode::ZEXT_INT32_TO_INT64: // no break, fall through + case OpCode::ZEXT_INT1_TO_INT64: { + VisitZExtInt(gate, ins[0], MachineRep::K_WORD64); + break; + } + default: { + break; + } + } +} + +void LLVMIRBuilder::HandleSExtInt(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::SEXT_INT1_TO_INT32: { + VisitSExtInt(gate, ins[0], MachineRep::K_WORD32); + break; + } + case OpCode::SEXT_INT1_TO_INT64: // no break, fall through + case OpCode::SEXT_INT32_TO_INT64: { + VisitSExtInt(gate, ins[0], MachineRep::K_WORD64); + break; + } + default: { + break; + } + } +} + void LLVMIRBuilder::VisitInt32Constant(AddrShift gate, int32_t value) const { LLVMValueRef llvmValue = LLVMConstInt(LLVMInt32Type(), value, 0); @@ -770,6 +696,11 @@ void LLVMIRBuilder::VisitFloat64Constant(AddrShift gate, double value) const LOG_ECMA(INFO) << "VisitFloat64Constant " << str; } +void LLVMIRBuilder::HandleParameter(AddrShift gate) +{ + return VisitParameter(gate); +} + void LLVMIRBuilder::VisitParameter(AddrShift gate) const { int argth = circuit_->LoadGatePtrConst(gate)->GetBitField(); @@ -788,6 +719,55 @@ void LLVMIRBuilder::VisitParameter(AddrShift gate) const LOG_ECMA(INFO) << "para arg:" << argth << "value IR:" << str; } + + +void LLVMIRBuilder::HandleBranch(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + AddrShift bTrue = (circuit_->GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1]; + AddrShift bFalse = (circuit_->GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1]; + int bbTrue = instIdMapBbId_[circuit_->GetId(bTrue)]; + int bbFalse = instIdMapBbId_[circuit_->GetId(bFalse)]; + VisitBranch(gate, ins[1], bbTrue, bbFalse); +} + +void LLVMIRBuilder::HandleIntMod(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitIntMod(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::VisitIntMod(AddrShift gate, AddrShift e1, AddrShift e2) const +{ + LOG_ECMA(INFO) << "int mod gate:" << gate; + LLVMValueRef e1Value = g_values[e1]; + LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LLVMValueRef e2Value = g_values[e2]; + LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LLVMValueRef result = LLVMBuildSRem(builder_, e1Value, e2Value, ""); + g_values[gate] = result; + LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); +} + +void LLVMIRBuilder::HandleFloatMod(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitFloatMod(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::VisitFloatMod(AddrShift gate, AddrShift e1, AddrShift e2) const +{ + LOG_ECMA(INFO) << "float mod gate:" << gate; + LLVMValueRef e1Value = g_values[e1]; + LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LLVMValueRef e2Value = g_values[e2]; + LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LLVMValueRef result = LLVMBuildFRem(builder_, e1Value, e2Value, ""); + g_values[gate] = result; + LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); +} + void LLVMIRBuilder::VisitBranch(AddrShift gate, AddrShift cmp, int btrue, int bfalse) { LOG_ECMA(INFO) << "cmp gate:" << cmp; @@ -810,6 +790,13 @@ void LLVMIRBuilder::VisitBranch(AddrShift gate, AddrShift cmp, int btrue, int bf g_values[gate] = result; } +void LLVMIRBuilder::HandleSwitch(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitSwitch(gate, ins[1], outs); +} + void LLVMIRBuilder::VisitSwitch(AddrShift gate, AddrShift input, const std::vector &outList) { LLVMValueRef cond = g_values[input]; @@ -889,6 +876,12 @@ void LLVMIRBuilder::VisitFloatOrDoubleCmp(AddrShift gate, AddrShift e1, AddrShif LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleIntRev(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitIntRev(gate, ins[0]); +} + void LLVMIRBuilder::VisitIntRev(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "int sign invert gate:" << gate; @@ -899,6 +892,25 @@ void LLVMIRBuilder::VisitIntRev(AddrShift gate, AddrShift e1) const LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleIntAdd(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::INT32_ADD: { + VisitIntAdd(gate, ins[0], ins[1], MachineRep::K_WORD32); + break; + } + case OpCode::INT64_ADD: { + VisitIntAdd(gate, ins[0], ins[1], MachineRep::K_WORD64); + break; + } + default: { + break; + } + } +} + void LLVMIRBuilder::VisitIntAdd(AddrShift gate, AddrShift e1, AddrShift e2, MachineRep rep) const { LOG_ECMA(INFO) << "int add gate:" << gate; @@ -914,6 +926,13 @@ void LLVMIRBuilder::VisitIntAdd(AddrShift gate, AddrShift e1, AddrShift e2, Mach LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleFloatAdd(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitFloatAdd(gate, ins[0], ins[1]); +} + void LLVMIRBuilder::VisitFloatAdd(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "float add gate:" << gate; @@ -926,6 +945,161 @@ void LLVMIRBuilder::VisitFloatAdd(AddrShift gate, AddrShift e1, AddrShift e2) co LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleFloatSub(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitFloatSub(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleFloatMul(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitFloatMul(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleFloatDiv(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitFloatDiv(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntSub(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntSub(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntMul(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntMul(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntOr(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntOr(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntXor(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntXor(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntLsr(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntLsr(gate, ins[0], ins[1]); +} + +void LLVMIRBuilder::HandleIntOrUintCmp(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::INT32_SLT: // no break, fall through + case OpCode::INT64_SLT: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSLT); + break; + } + case OpCode::INT32_ULT: // no break, fall through + case OpCode::INT64_ULT: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntULT); + break; + } + case OpCode::INT32_SLE: // no break, fall through + case OpCode::INT64_SLE: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSLE); + break; + } + case OpCode::INT32_SGT: // no break, fall through + case OpCode::INT64_SGT: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSGT); + break; + } + case OpCode::INT32_SGE: // no break, fall through + case OpCode::INT64_SGE: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntSGE); + break; + } + case OpCode::INT32_EQ: // no break, fall through + case OpCode::INT64_EQ: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntEQ); + break; + } + case OpCode::INT32_NE: // no break, fall through + case OpCode::INT64_NE: { + VisitIntOrUintCmp(gate, ins[0], ins[1], LLVMIntNE); + break; + } + default: { + break; + } + } +} + +void LLVMIRBuilder::HandleFloatOrDoubleCmp(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitFloatOrDoubleCmp(gate, ins[0], ins[1], LLVMRealOEQ); +} + +void LLVMIRBuilder::HandleLoad(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::INT32_LOAD: { + AddrShift base = ins[1]; + VisitLoad(gate, MachineRep::K_WORD32, base); + break; + } + case OpCode::INT64_LOAD: { + AddrShift base = ins[1]; + VisitLoad(gate, MachineRep::K_WORD64, base); + break; + } + default: { + break; + } + } +} + +void LLVMIRBuilder::HandleStore(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::INT32_STORE: { + VisitStore(gate, MachineRep::K_WORD32, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate + break; + } + case OpCode::INT64_STORE: { + VisitStore(gate, MachineRep::K_WORD64, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate + break; + } + default: { + break; + } + } +} + +void LLVMIRBuilder::HandleCastInt32ToDouble(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitCastInt32ToDouble(gate, ins[0]); +} + void LLVMIRBuilder::VisitFloatSub(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "float sub gate:" << gate; @@ -986,30 +1160,6 @@ void LLVMIRBuilder::VisitIntMul(AddrShift gate, AddrShift e1, AddrShift e2) cons LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } -void LLVMIRBuilder::VisitIntMod(AddrShift gate, AddrShift e1, AddrShift e2) const -{ - LOG_ECMA(INFO) << "int mod gate:" << gate; - LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); - LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); - LLVMValueRef result = LLVMBuildSRem(builder_, e1Value, e2Value, ""); - g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); -} - -void LLVMIRBuilder::VisitFloatMod(AddrShift gate, AddrShift e1, AddrShift e2) const -{ - LOG_ECMA(INFO) << "float mod gate:" << gate; - LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); - LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); - LLVMValueRef result = LLVMBuildFRem(builder_, e1Value, e2Value, ""); - g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); -} - void LLVMIRBuilder::VisitIntOr(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int or gate:" << gate; @@ -1022,6 +1172,12 @@ void LLVMIRBuilder::VisitIntOr(AddrShift gate, AddrShift e1, AddrShift e2) const LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleIntAnd(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitIntAnd(gate, ins[0], ins[1]); +} + void LLVMIRBuilder::VisitIntAnd(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int and gate:" << gate; @@ -1058,6 +1214,12 @@ void LLVMIRBuilder::VisitIntLsr(AddrShift gate, AddrShift e1, AddrShift e2) cons LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleIntLsl(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitIntLsl(gate, ins[0], ins[1]); +} + void LLVMIRBuilder::VisitIntLsl(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int lsl gate:" << gate; @@ -1090,6 +1252,25 @@ void LLVMIRBuilder::VisitSExtInt(AddrShift gate, AddrShift e1, MachineRep rep) c LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleCastIntXToIntY(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + switch (circuit_->GetOpCode(gate)) { + case OpCode::TRUNC_INT64_TO_INT1: + case OpCode::TRUNC_INT32_TO_INT1: { + VisitCastIntXToIntY(gate, ins[0], MachineRep::K_BIT); + break; + } + case OpCode::TRUNC_INT64_TO_INT32: { + VisitCastIntXToIntY(gate, ins[0], MachineRep::K_WORD32); + break; + } + default: { + break; + } + } +} + void LLVMIRBuilder::VisitCastIntXToIntY(AddrShift gate, AddrShift e1, MachineRep rep) const { LOG_ECMA(INFO) << "int cast2 int gate:" << gate; @@ -1110,6 +1291,12 @@ void LLVMIRBuilder::VisitCastInt32ToDouble(AddrShift gate, AddrShift e1) const LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleCastInt64ToDouble(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitCastInt64ToDouble(gate, ins[0]); +} + void LLVMIRBuilder::VisitCastInt64ToDouble(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "int cast2 double gate:" << gate; @@ -1120,6 +1307,12 @@ void LLVMIRBuilder::VisitCastInt64ToDouble(AddrShift gate, AddrShift e1) const LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::HandleCastDoubleToInt(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitCastDoubleToInt(gate, ins[0]); +} + void LLVMIRBuilder::VisitCastDoubleToInt(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "double cast2 int gate:" << gate; diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index cd703fd..43f43ef 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -31,6 +31,8 @@ namespace kungfu { using OperandsVector = std::set; class BasicBlock; using BasicBlockMap = std::map>; +class LLVMIRBuilder; +typedef void (LLVMIRBuilder::*HandleType)(AddrShift gate); enum class MachineRep { K_NONE, @@ -138,6 +140,49 @@ private: LLVMModuleRef module_; }; +#define OPCODES(V) \ + V(Call, (AddrShift gate, const std::vector &inList)) \ + V(Alloca, (AddrShift gate)) \ + V(Block, (int id, const OperandsVector &predecessors)) \ + V(Goto, (int block, int bbout)) \ + V(Parameter, (AddrShift gate) const ) \ + V(Int32Constant, (AddrShift gate, int32_t value) const ) \ + V(Int64Constant, (AddrShift gate, int64_t value) const ) \ + V(Float64Constant, (AddrShift gate, double value) const ) \ + V(ZExtInt, (AddrShift gate, AddrShift e1, MachineRep rep) const ) \ + V(SExtInt, (AddrShift gate, AddrShift e1, MachineRep rep) const ) \ + V(Load, (AddrShift gate, MachineRep rep, AddrShift base) const ) \ + V(Store, (AddrShift gate, MachineRep rep, AddrShift base, AddrShift value) const ) \ + V(IntRev, (AddrShift gate, AddrShift e1) const ) \ + V(IntAdd, (AddrShift gate, AddrShift e1, AddrShift e2, MachineRep rep) const ) \ + V(FloatAdd, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(FloatSub, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(FloatMul, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(FloatDiv, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntSub, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntMul, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntOr, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntAnd, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntXor, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntLsr, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(Int32LessThanOrEqual, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ + V(IntOrUintCmp, (AddrShift gate, AddrShift e1, AddrShift e2, LLVMIntPredicate opcode) const ) \ + V(FloatOrDoubleCmp, (AddrShift gate, AddrShift e1, AddrShift e2, LLVMRealPredicate opcode) const ) \ + V(Branch, (AddrShift gate, AddrShift cmp, AddrShift btrue, AddrShift bfalse)) \ + V(Switch, (AddrShift gate, AddrShift input, const std::vector &outList)) \ + V(SwitchCase, (AddrShift gate, AddrShift switchBranch, AddrShift out)) \ + V(Phi, (AddrShift gate, const std::vector &srcGates, MachineRep rep)) \ + V(Return, (AddrShift gate, AddrShift popCount, const std::vector &operands) const ) \ + V(CastIntXToIntY, (AddrShift gate, AddrShift e1, MachineRep rep) const ) \ + V(CastInt32ToDouble, (AddrShift gate, AddrShift e1) const ) \ + V(CastInt64ToDouble, (AddrShift gate, AddrShift e1) const ) \ + V(CastDoubleToInt, (AddrShift gate, AddrShift e1) const ) \ + V(CastInt64ToPointer, (AddrShift gate, AddrShift e1) const ) \ + V(IntLsl, (AddrShift gate, AddrShift e1, AddrShift e2) const) \ + V(IntMod, (AddrShift gate, AddrShift e1, AddrShift e2) const) \ + V(FloatMod, (AddrShift gate, AddrShift e1, AddrShift e2) const) \ + + class LLVMIRBuilder { public: explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit); @@ -149,46 +194,12 @@ public: ~LLVMIRBuilder() = default; private: - void VisitCall(AddrShift gate, const std::vector &inList); - void VisitAlloca(AddrShift gate); - void VisitBlock(int id, const OperandsVector &predecessors); - void VisitGoto(int block, int bbout); - void VisitParameter(AddrShift gate) const; - void VisitInt32Constant(AddrShift gate, int32_t value) const; - void VisitInt64Constant(AddrShift gate, int64_t value) const; - void VisitFloat64Constant(AddrShift gate, double value) const; - void VisitZExtInt(AddrShift gate, AddrShift e1, MachineRep rep) const; - void VisitSExtInt(AddrShift gate, AddrShift e1, MachineRep rep) const; - void VisitLoad(AddrShift gate, MachineRep rep, AddrShift base) const; - void VisitStore(AddrShift gate, MachineRep rep, AddrShift base, AddrShift value) const; - void VisitIntRev(AddrShift gate, AddrShift e1) const; - void VisitIntAdd(AddrShift gate, AddrShift e1, AddrShift e2, MachineRep rep) const; - void VisitFloatAdd(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitFloatSub(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitFloatMul(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitFloatDiv(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntSub(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntMul(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntOr(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntAnd(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntXor(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntLsr(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntLsl(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitInt32LessThanOrEqual(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitIntOrUintCmp(AddrShift gate, AddrShift e1, AddrShift e2, LLVMIntPredicate opcode) const; - void VisitFloatOrDoubleCmp(AddrShift gate, AddrShift e1, AddrShift e2, LLVMRealPredicate opcode) const; - void VisitBranch(AddrShift gate, AddrShift cmp, AddrShift btrue, AddrShift bfalse); - void VisitSwitch(AddrShift gate, AddrShift input, const std::vector &outList); - void VisitSwitchCase(AddrShift gate, AddrShift switchBranch, AddrShift out); - void VisitPhi(AddrShift gate, const std::vector &srcGates, MachineRep rep); - void VisitReturn(AddrShift gate, AddrShift popCount, const std::vector &operands) const; - void VisitCastIntXToIntY(AddrShift gate, AddrShift e1, MachineRep rep) const; - void VisitCastInt32ToDouble(AddrShift gate, AddrShift e1) const; - void VisitCastInt64ToDouble(AddrShift gate, AddrShift e1) const; - void VisitCastDoubleToInt(AddrShift gate, AddrShift e1) const; - void VisitCastInt64ToPointer(AddrShift gate, AddrShift e1) const; - void VisitIntMod(AddrShift gate, AddrShift e1, AddrShift e2) const; - void VisitFloatMod(AddrShift gate, AddrShift e1, AddrShift e2) const; + #define DECLAREVISITOPCODE(name, signature) void Visit##name signature; + OPCODES(DECLAREVISITOPCODE) + #undef DECLAREVISITOPCODE + #define DECLAREHANDLEOPCODE(name, ignore) void Handle##name(AddrShift gate); + OPCODES(DECLAREHANDLEOPCODE) + #undef DECLAREHANDLEOPCODE BasicBlock *EnsurBasicBlock(int id); LLVMValueRef LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder); @@ -203,6 +214,7 @@ private: void End(); void ProcessPhiWorkList(); + void AssignHandleMap(); private: const std::vector> *schedule_ {nullptr}; @@ -219,6 +231,8 @@ private: std::vector phiRebuildWorklist_; LLVMStubModule *stubModule_ {nullptr}; + std::unordered_map opCodeHandleMap_; + std::set opCodeHandleIgnore; }; } // namespace kungfu #endif // PANDA_RUNTIME_ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H \ No newline at end of file diff --git a/ecmascript/compiler/tests/BUILD.gn b/ecmascript/compiler/tests/BUILD.gn index 5268dae..7adb64d 100644 --- a/ecmascript/compiler/tests/BUILD.gn +++ b/ecmascript/compiler/tests/BUILD.gn @@ -113,7 +113,8 @@ host_unittest_action("StubTest") { deps = [ "$ark_root/libpandabase:libarkbase", - "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer_test", + "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer_test(${host_toolchain})", + "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", sdk_libc_secshared_dep, ] } diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index c684a94..6a2f63c 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -20,7 +20,7 @@ #include "ecmascript/compiler/fast_stub.h" #include "ecmascript/compiler/llvm_ir_builder.h" #include "ecmascript/compiler/llvm_mcjit_engine.h" -#include "ecmascript/compiler/llvm_stackmap_parse.h" +#include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" #include "ecmascript/compiler/scheduler.h" #include "ecmascript/compiler/stub_descriptor.h" #include "ecmascript/compiler/verifier.h" @@ -720,6 +720,27 @@ int RuntimeFunc2(struct ThreadTy *fpInfo) for (int i = 0; i < 40; i++) { // print 40 ptr value for debug std::cout << std::hex << &(rbp[i]) << " :" << rbp[i] << std::endl; } + /* walk back + stack frame: 0 pre rbp <-- rbp + -8 type + -16 pre frame thread fp + */ + int64_t *frameType = nullptr; + int64_t *gcFp = nullptr; + std::cout << "-----------------walkback----------------" << std::endl; + do { + frameType = rbp - 1; + if (*frameType == 1) { + gcFp = rbp - 2; // 2: 2 stack slot + } else { + gcFp = rbp; + } + rbp = reinterpret_cast(*gcFp); + std::cout << std::hex << "frameType :" << *frameType << " gcFp:" << *gcFp << std::endl; + } while (*gcFp != 0); + std::cout << "+++++++++++++++++walkback++++++++++++++++" << std::endl; + std::cout << "call RuntimeFunc2 func ThreadTy fp: " << fpInfo->fp << " magic:" << fpInfo->magic << std::endl; + std::cout << "RuntimeFunc2 +" << std::endl; return 0; } } @@ -770,7 +791,7 @@ LLVMValueRef LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder) return frameAddr; } -#ifdef LLVM_SUPPORT_GC +#ifdef ARK_GC_SUPPORT HWTEST_F_L0(StubTest, JSEntryTest) { std::cout << " ---------- JSEntryTest ------------- " << std::endl; @@ -1062,7 +1083,7 @@ HWTEST_F_L0(StubTest, LoadGCIRTest) { std::cout << "--------------LoadGCIRTest--------------------" << std::endl; char *path = get_current_dir_name(); - std::string filePath = std::string(path) + "/../../ark/js_runtime/ecmascript/compiler/tests/satepoint_GC_0.ll"; + std::string filePath = std::string(path) + "/ark/js_runtime/ecmascript/compiler/tests/satepoint_GC_0.ll"; char resolvedPath[PATH_MAX]; char *res = realpath(filePath.c_str(), resolvedPath); @@ -1089,8 +1110,8 @@ HWTEST_F_L0(StubTest, LoadGCIRTest) auto *mainPtr = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); uint8_t *ptr = assembler.GetStackMapsSection(); - LLVMStackMapParse::GetInstance().CalculateStackMap(ptr); - LLVMStackMapParse::GetInstance().Print(); + LLVMStackMapParser::GetInstance().CalculateStackMap(ptr); + LLVMStackMapParser::GetInstance().Print(); assembler.Disassemble(); LLVMDumpModule(module); @@ -1108,19 +1129,21 @@ void DoSafepoint() uintptr_t returnAddr = *(rbp + 1); uintptr_t *rsp = rbp + 2; // move 2 steps from rbp to get rsp rbp = reinterpret_cast(*rbp); - DwarfRegAndOffsetType info; - bool found = LLVMStackMapParse::GetInstance().StackMapByAddr(returnAddr, info); + DwarfRegAndOffsetTypeVector infos; + bool found = LLVMStackMapParser::GetInstance().StackMapByAddr(returnAddr, infos); if (found) { - uintptr_t **address = nullptr; - if (info.first == 7) { // 7: x86_64 dwarf register num, representing rsp - address = reinterpret_cast(reinterpret_cast(rsp) + info.second); - // rbp - } else if (info.first == 6) { // 6: x86_64 dwarf register num, representing rbp - address = reinterpret_cast(reinterpret_cast(rbp) + info.second); + for (auto &info : infos) { + uintptr_t **address = nullptr; + if (info.first == 7) { // 7: x86_64 dwarf register num, representing rsp + address = reinterpret_cast(reinterpret_cast(rsp) + info.second); + // rbp + } else if (info.first == 6) { // 6: x86_64 dwarf register num, representing rbp + address = reinterpret_cast(reinterpret_cast(rbp) + info.second); + } + std::cout << std::hex << "ref addr:" << address; + std::cout << " value:" << *address; + std::cout << " *value :" << **address << std::endl; } - std::cout << std::hex << "ref addr:" << address; - std::cout << " value:" << *address; - std::cout << " *value :" << **address << std::endl; } std::cout << std::endl << std::endl; std::cout << std::hex << "+++++++++++++++++++ returnAddr : 0x" << returnAddr << " rbp:" << rbp diff --git a/ecmascript/frames.h b/ecmascript/frames.h index dc5c002..5fcdcaf 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -13,11 +13,128 @@ * limitations under the License. */ +// OptimizedEntry Frame are divided up into four regions. +// The first region, Caller Frame: Interpreter Call Stub comply c calling convention, if parameter number +// larger than caller register number, then spill to stack frame. +// The second region, Fixed Header: return addr、saved c frame ptr(pointer to caller frame)、OPTIMIZED_ENTRY_FRAME +// (codegen prologue insert frame type)、saved gc frame ptr(pointer to interpreter iframe) +// The third region, which contains the callee-saved registers must be +// reserved after register allocation, since its size can only be precisely +// determined after register allocation once the number of used callee-saved +// register is certain. +// The fourth region is spill slot. Comply c calling convertion, local variable is larger callee save register, +// spill local variable to stack; heap ptr also spill stack slot before call runtime function, after call we will +// rewrite heap ptr +// slot OptimizedEntry frame +// +-----------------+-------------------------------- +// | parameter n | ^ +// |- - - - - - - - -| | +// | parameter n-1 | Caller +// | ... | frame +// | parameter n-2 | comply c calling convention +// |- - - - - - - - -| i-n th prameter spill to slot +// | parameter i | v +// -----+-----------------+-------------------------------- +// 0 | return addr | ^ ^ +// |- - - - - - - - - | | | +// 1 | saved c frame ptr | Fixed | +// |- - - - - - - - - | Header <-- frame ptr | +// 2 |OPTIMIZED_ENTRY_FRAME| | | +// |- - - - - - - - - | | | +// 3 | saved gc frame ptr | v | +// +-----------------+---- | +// 4 | callee-saved 1 | ^ | +// |- - - - - - - - -| | | +// | ... | Callee-saved | +// |- - - - - - - - -| | | +// r+3 | callee-saved r | v | +// +-----------------+---- | +// ^ +// r+4 | local variables | | | +// |- - - - - - - - -| | | +// | ... | spill slot | +// |- - - - - - - - -| | | +// | heap ptr | v v +// -----+-----------------+----- <-- stack ptr ------------- + + +// Optimized Frame is similar to OptimizedEntry Frame, only difference is Fixed Header. +// slot OptimizedEntry frame +// +-----------------+-------------------------------- +// | parameter n | ^ +// |- - - - - - - - -| | +// | parameter n-1 | Caller +// | ... | frame +// | parameter n-2 | comply c calling convention +// |- - - - - - - - -| i-n th prameter spill to slot +// | parameter i | v +// -----+-----------------+-------------------------------- +// 0 | return addr | ^ ^ +// |- - - - - - - - - | | | +// 1 | saved c frame ptr | Fixed | +// |- - - - - - - - - | Header <-- frame ptr | +// 2 | OPTIMIZED_FRAME | | | +// 3 | - - - - - - - - - | v | +// +-----------------+---- | +// 4 | callee-saved 1 | ^ | +// |- - - - - - - - -| | | +// | ... | Callee-saved | +// |- - - - - - - - -| | | +// r+3 | callee-saved r | v | +// +-----------------+---- | +// ^ +// r+4 | local variables | | | +// |- - - - - - - - -| | | +// | ... | spill slot | +// |- - - - - - - - -| | | +// | heap ptr | v v +// -----+-----------------+----- <-- stack ptr ------------- + +// for exampe: +// calls calls +// foo --------> bar ------> baz +// (interpreted) (compiled) (runtime) +// baz trigger gc, baz get current frame pointer(bar gc frame pointer), then visit foo's +// interpreter frame by reading bar gc frame pointer value +// ----+----------------+ <--- ManagedThread::GetCurrentFrame() +// / | | | +// | | | +// baz | | | +// | return address | | +// ---- +----------------+ | +// | data | | +// +----------------+ | +// +----------------+ <+------------------ +// bar | pointer to the | ----------------------+ +// | interpreter | | +// | frame(gc frame | | +// | pointer) | | +// +----------------+ | +// +----------------+ | +// | OPTIMIZED_ENTRY_ | +// | FRAME | | +// +----------------+ | +// | c frame pointer| <-----+ +// | return address | | | +// | | | | +// ---- +----------------+ | | +// E | native frame | | | +// x u | of | | | +// e t | interpreter | | | +// c e |c frame pointer | <---- | | +// ---- +----------------+ | +// | ... | | +// +----------------+ <+-------------------- +// | foo's | +// | interpreter | +// | frame | +// +----------------+ #ifndef ECMASCRIPT_FRAMES_H #define ECMASCRIPT_FRAMES_H namespace panda::ecmascript { -enum class FrameType: unsigned int { +class JSThread; +enum class FrameType: uint64_t { OPTIMIZED_FRAME = 0, OPTIMIZED_ENTRY_FRAME = 1, INTERPRETER_FRAME = 2, @@ -30,16 +147,22 @@ auto as_integer(Enumeration const value) return static_cast::type>(value); } -class FrameStateBase { +class OptFrameStateBase { public: FrameType frameType; uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc }; -class LLVMBoundaryFrameState { +class InterPretFrameStateBase { +public: + uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + FrameType frameType; +}; + +class LLVMOptimizedEntryFrameState { public: uint64_t *threadFp; // for gc - FrameStateBase base; + OptFrameStateBase base; }; constexpr int kSystemPointerSize = sizeof(void*); @@ -47,8 +170,7 @@ class FrameConst { public: uint64_t *prev; FrameType frameType; - static constexpr int kPreOffset = -kSystemPointerSize; - static constexpr int kFrameType = -2 * kSystemPointerSize; + static constexpr int kFrameType = -kSystemPointerSize; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_FRAMES_H \ No newline at end of file diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index c0ac197..f50b97c 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -15,9 +15,12 @@ #include "ecmascript/interpreter/frame_handler.h" +#include + #include "ecmascript/interpreter/interpreter.h" #include "ecmascript/js_thread.h" #include "libpandafile/bytecode_instruction-inl.h" +#include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" namespace panda::ecmascript { EcmaFrameHandler::EcmaFrameHandler(const JSThread *thread) @@ -44,7 +47,7 @@ void EcmaFrameHandler::PrevFrame() ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(sp_) - 1; - sp_ = state->prev; + sp_ = state->base.prev; } EcmaFrameHandler EcmaFrameHandler::GetPrevFrame() const @@ -52,7 +55,7 @@ EcmaFrameHandler EcmaFrameHandler::GetPrevFrame() const ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(sp_) - 1; - return EcmaFrameHandler(state->prev); + return EcmaFrameHandler(state->base.prev); } JSTaggedValue EcmaFrameHandler::GetVRegValue(size_t index) const @@ -82,7 +85,7 @@ uint32_t EcmaFrameHandler::GetSize() const ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(sp_) - 1; - JSTaggedType *prevSp = state->prev; + JSTaggedType *prevSp = state->base.prev; ASSERT(prevSp != nullptr); auto size = (prevSp - sp_) - FRAME_STATE_SIZE; return static_cast(size); @@ -152,14 +155,14 @@ JSTaggedValue EcmaFrameHandler::GetEnv() const void EcmaFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) { JSTaggedType *current = sp_; - while (current != nullptr) { + if (current != nullptr) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(current) - 1; if (state->sp != nullptr) { uintptr_t start = ToUintPtr(current); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - FrameState *prev_state = reinterpret_cast(state->prev) - 1; + FrameState *prev_state = reinterpret_cast(state->base.prev) - 1; uintptr_t end = ToUintPtr(prev_state); v1(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end)); if (state->pc != nullptr) { @@ -170,7 +173,6 @@ void EcmaFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1 v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&state->profileTypeInfo))); } } - current = state->prev; } } @@ -194,4 +196,80 @@ void EcmaFrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const int offset = pc - JSMethod::Cast(frameHandler.GetMethod())->GetBytecodeArray(); os << "offset: " << offset << "\n"; } + +void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const +{ +#ifdef PANDA_TARGET_AMD64 + JSTaggedType *current = fp_; + if (current != nullptr) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + std::vector slotAddrs; + auto returnAddr = reinterpret_cast(*(current + 1)); + bool ret = kungfu::LLVMStackMapParser::GetInstance().StackMapByFuncAddrFp( + returnAddr, + reinterpret_cast(fp_), + slotAddrs); + if (ret == false) { + return; + } + for (auto &address: slotAddrs) { + v0(Root::ROOT_FRAME, ObjectSlot(address)); + } + } +#else + (void)v0; + (void)v1; +#endif +} + +void OptimizedEntryFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const +{ +#ifdef PANDA_TARGET_AMD64 + JSTaggedType *current = fp_; + if (current != nullptr) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + std::vector slotAddrs; + auto returnAddr = *(current + 1); + bool ret = kungfu::LLVMStackMapParser::GetInstance().StackMapByFuncAddrFp( + reinterpret_cast(returnAddr), + reinterpret_cast(fp_), + slotAddrs); + if (ret == false) { + return; + } + for (auto &address: slotAddrs) { + v0(Root::ROOT_FRAME, ObjectSlot(address)); + } + } +#else + (void)v0; + (void)v1; +#endif +} + +void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const +{ + JSTaggedType *current = fp_; + while (current) { + FrameType type = *(reinterpret_cast( + reinterpret_cast(current) + FrameConst::kFrameType)); + if (type == FrameType::INTERPRETER_FRAME) { + FrameState *state = reinterpret_cast(current) - 1; + EcmaFrameHandler(current).Iterate(v0, v1); + current = state->base.prev; + } else if (type == FrameType::OPTIMIZED_FRAME) { + OptFrameStateBase *state = reinterpret_cast( + reinterpret_cast(current) - + MEMBER_OFFSET(OptFrameStateBase, prev)); + OptimizedFrameHandler(current).Iterate(v0, v1); + current = reinterpret_cast(state->prev); + } else { + LLVMOptimizedEntryFrameState *state = reinterpret_cast( + reinterpret_cast(current) - + MEMBER_OFFSET(LLVMOptimizedEntryFrameState, base.prev)); + OptimizedEntryFrameHandler(current).Iterate(v0, v1); + current = reinterpret_cast(state->threadFp); + } + } +} } // namespace panda::ecmascript diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index ad82f37..717060d 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -68,6 +68,34 @@ public: private: JSTaggedType *sp_{nullptr}; }; -} // namespace ecmascript + +class OptimizedFrameHandler { +public: + explicit OptimizedFrameHandler(JSTaggedType *fp) : fp_(fp) {} + explicit OptimizedFrameHandler(const JSThread *thread); + ~OptimizedFrameHandler() = default; + void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; +private: + JSTaggedType *fp_{nullptr}; +}; + +class OptimizedEntryFrameHandler { +public: + explicit OptimizedEntryFrameHandler(JSTaggedType *fp) : fp_(fp) {} + explicit OptimizedEntryFrameHandler(const JSThread *thread); + ~OptimizedEntryFrameHandler() = default; + void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; +private: + JSTaggedType *fp_{nullptr}; +}; + +class FrameIterator { +public: + explicit FrameIterator(JSTaggedType *fp) : fp_(fp) {} + void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; +private: + JSTaggedType *fp_{nullptr}; +}; +} // namespace ecmascript } // namespace panda #endif // ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index a9232e5..596acfa 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -228,7 +228,8 @@ JSTaggedValue EcmaInterpreter::ExecuteNative(JSThread *thread, const CallParams& } FrameState *state = GET_FRAME(newSp); - state->prev = sp; + state->base.prev = sp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->pc = nullptr; state->sp = newSp; state->method = methodToCall; @@ -261,7 +262,8 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param FrameState *breakState = GET_FRAME(newSp); breakState->pc = nullptr; breakState->sp = nullptr; - breakState->prev = originalPrevSp; + breakState->base.prev = originalPrevSp; + breakState->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; breakState->numActualArgs = 0; JSTaggedType *prevSp = newSp; @@ -300,7 +302,8 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param ConstantPool *constpool = ConstantPool::Cast(thisFunc->GetConstantPool().GetTaggedObject()); state->constpool = constpool; state->profileTypeInfo = thisFunc->GetProfileTypeInfo(); - state->prev = prevSp; + state->base.prev = prevSp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->numActualArgs = numActualArgs; JSTaggedValue env = thisFunc->GetLexicalEnv(); @@ -338,7 +341,8 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH FrameState *breakState = GET_FRAME(breakSp); breakState->pc = nullptr; breakState->sp = nullptr; - breakState->prev = currentSp; + breakState->base.prev = currentSp; + breakState->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; breakState->numActualArgs = 0; // create new frame and resume sp and pc @@ -368,7 +372,8 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH state->profileTypeInfo = func->GetProfileTypeInfo(); state->acc = context->GetAcc(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - state->prev = breakSp; + state->base.prev = breakSp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; JSTaggedValue env = context->GetLexicalEnv(); state->env = env; // execute interpreter @@ -399,7 +404,8 @@ void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandlepc = nullptr; breakState->sp = nullptr; - breakState->prev = currentSp; + breakState->base.prev = currentSp; + breakState->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; // create new frame and resume sp and pc uint32_t nregs = context->GetNRegs().GetInt(); @@ -428,7 +434,8 @@ void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandleprofileTypeInfo = func->GetProfileTypeInfo(); state->acc = context->GetAcc(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - state->prev = breakSp; + state->base.prev = breakSp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->env = context->GetLexicalEnv(); thread->SetCurrentSPFrame(newSp); @@ -438,7 +445,7 @@ void EcmaInterpreter::ResumeContext(JSThread *thread) { JSTaggedType *sp = const_cast(thread->GetCurrentSPFrame()); FrameState *state = GET_FRAME(sp); - thread->SetCurrentSPFrame(state->prev); + thread->SetCurrentSPFrame(state->base.prev); } void EcmaInterpreter::NotifyBytecodePcChanged(JSThread *thread) @@ -771,7 +778,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool } FrameState *state = GET_FRAME(newSp); - state->prev = sp; + state->base.prev = sp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->pc = nullptr; state->sp = newSp; state->method = methodToCall; @@ -854,7 +862,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool InterpreterFrameCopyArgs(newSp, numVregs, actualNumArgs, numDeclaredArgs); FrameState *state = GET_FRAME(newSp); - state->prev = sp; + state->base.prev = sp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; state->pc = pc = JSMethod::Cast(methodToCall)->GetBytecodeArray(); state->sp = sp = newSp; state->method = methodToCall; @@ -880,7 +889,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool << std::hex << reinterpret_cast(state->pc); [[maybe_unused]] auto fistPC = state->method->GetInstructions(); UPDATE_HOTNESS_COUNTER(-(pc - fistPC)); - sp = state->prev; + sp = state->base.prev; ASSERT(sp != nullptr); FrameState *prevState = GET_FRAME(sp); pc = prevState->pc; @@ -904,7 +913,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool << std::hex << reinterpret_cast(state->pc); [[maybe_unused]] auto fistPC = state->method->GetInstructions(); UPDATE_HOTNESS_COUNTER_NON_ACC(-(pc - fistPC)); - sp = state->prev; + sp = state->base.prev; ASSERT(sp != nullptr); FrameState *prevState = GET_FRAME(sp); pc = prevState->pc; @@ -2003,7 +2012,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool UPDATE_HOTNESS_COUNTER(-(pc - fistPC)); LOG(DEBUG, INTERPRETER) << "Exit: SuspendGenerator " << std::hex << reinterpret_cast(sp) << " " << std::hex << reinterpret_cast(state->pc); - sp = state->prev; + sp = state->base.prev; ASSERT(sp != nullptr); FrameState *prevState = GET_FRAME(sp); pc = prevState->pc; @@ -3215,7 +3224,8 @@ void EcmaInterpreter::InitStackFrame(JSThread *thread) state->acc = JSTaggedValue::Hole(); state->constpool = nullptr; state->profileTypeInfo = JSTaggedValue::Undefined(); - state->prev = nullptr; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.prev = nullptr; state->numActualArgs = 0; } diff --git a/ecmascript/interpreter/interpreter.h b/ecmascript/interpreter/interpreter.h index cb988f3..0c1a504 100644 --- a/ecmascript/interpreter/interpreter.h +++ b/ecmascript/interpreter/interpreter.h @@ -20,6 +20,7 @@ #include "ecmascript/js_tagged_value.h" #include "ecmascript/js_handle.h" #include "ecmascript/js_thread.h" +#include "ecmascript/frames.h" namespace panda::ecmascript { class ConstantPool; @@ -32,7 +33,6 @@ using TaggedType = coretypes::TaggedType; struct FrameState { const uint8_t *pc; JSTaggedType *sp; - uint64_t *prev; JSMethod *method; // aligned with 8 bits alignas(sizeof(uint64_t)) ConstantPool *constpool; @@ -40,6 +40,7 @@ struct FrameState { JSTaggedValue acc; JSTaggedValue env; uint64_t numActualArgs; + InterPretFrameStateBase base; }; // NOLINTNEXTLINE(bugprone-sizeof-expression) diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index 5ed5834..6338196 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -86,14 +86,13 @@ void JSThread::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) if (!exception_.IsHole()) { v0(Root::ROOT_VM, ObjectSlot(ToUintPtr(&exception_))); } - // visit global Constant globalConst_.VisitRangeSlot(v1); // visit stack roots - EcmaFrameHandler(currentFrame_).Iterate(v0, v1); + FrameIterator iterator(currentFrame_); + iterator.Iterate(v0, v1); // visit internal call params internalCallParams_->Iterate(v1); - // visit tagged handle storage roots if (currentHandleStorageIndex_ != -1) { int32_t nid = currentHandleStorageIndex_; diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 7f597de..9edc945 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -22,6 +22,7 @@ #include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/mem/heap_roots.h" #include "include/thread.h" +#include "ecmascript/frames.h" namespace panda::ecmascript { class EcmaVM; diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index 839459d..efb4b20 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -18,6 +18,7 @@ #include "ecmascript/ecma_macros.h" #include "ecmascript/js_object.h" #include "ecmascript/js_proxy.h" +#include "ecmascript/frames.h" #include "ecmascript/layout_info.h" #include "ecmascript/message_string.h" #include "ecmascript/object_factory.h" @@ -26,7 +27,12 @@ namespace panda::ecmascript { bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argReceiver, uint32_t argIndex, uint64_t argValue, uint32_t argAttr) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiver(thread, reinterpret_cast(argReceiver)); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); @@ -37,7 +43,12 @@ bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argRece bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint64_t argReceiver, uint64_t argValue, bool argMayThrow) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiver(thread, JSTaggedValue(reinterpret_cast(argReceiver))); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); @@ -47,7 +58,12 @@ bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint void RuntimeTrampolines::ThrowTypeError(uint64_t argThread, int argMessageStringId) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); std::string message = MessageString::GetMessageString(argMessageStringId); ObjectFactory *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); @@ -58,7 +74,12 @@ void RuntimeTrampolines::ThrowTypeError(uint64_t argThread, int argMessageString bool RuntimeTrampolines::JSProxySetProperty(uint64_t argThread, uint64_t argProxy, uint64_t argKey, uint64_t argValue, uint64_t argReceiver, bool argMayThrow) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle proxy(thread, JSTaggedValue(reinterpret_cast(argProxy))); JSHandle index(thread, JSTaggedValue(reinterpret_cast(argKey))); @@ -76,7 +97,12 @@ uint32_t RuntimeTrampolines::GetHash32(uint64_t key, uint64_t len) uint64_t RuntimeTrampolines::CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); return JSObject::CallGetter(thread, accessor, objHandle).GetRawData(); @@ -84,7 +110,12 @@ uint64_t RuntimeTrampolines::CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t RuntimeTrampolines::AccessorGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver) { + JSTaggedType *fp = nullptr; +#ifdef PANDA_TARGET_AMD64 + asm("mov %%rbp, %0" : "=rm" (fp)); +#endif auto thread = reinterpret_cast(argThread); + StubCallRunTimeThreadFpLock(thread, fp); auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); return accessor->CallInternalGet(thread, objHandle).GetRawData(); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 678ea52..88a83ce 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -49,5 +49,33 @@ public: static int32_t FindElementWithCache(uint64_t argThread, uint64_t hClass, uint64_t key, int32_t num); static uint32_t StringGetHashCode(uint64_t ecmaString); }; + +class StubCallRunTimeThreadFpLock { +public: + StubCallRunTimeThreadFpLock(JSThread *thread, JSTaggedType *newFp) + :oldRbp_(const_cast(thread->GetCurrentSPFrame())), + thread_(thread) + { + thread_->SetCurrentSPFrame(newFp); + + std::cout << "StubCallRunTimeThreadFpLock newFp: " << newFp << " oldRbp_ : " << oldRbp_ + << " thread_->fp:" << thread_->GetCurrentSPFrame() <( + reinterpret_cast(newFp) + FrameConst::kFrameType)); + std::cout << "type = " << as_integer(type) << std::endl; + } + ~StubCallRunTimeThreadFpLock() + { + std::cout << "~StubCallRunTimeThreadFpLock oldRbp_: " << oldRbp_ << + " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; + FrameType type = *(reinterpret_cast( + reinterpret_cast(oldRbp_) + FrameConst::kFrameType)); + std::cout << "type = " << as_integer(type) << std::endl; + thread_->SetCurrentSPFrame(oldRbp_); + } +private: + JSTaggedType *oldRbp_; + JSThread *thread_; +}; } // namespace panda::ecmascript #endif \ No newline at end of file diff --git a/ecmascript/tests/test_helper.h b/ecmascript/tests/test_helper.h index 4a5a202..fd21b70 100644 --- a/ecmascript/tests/test_helper.h +++ b/ecmascript/tests/test_helper.h @@ -64,7 +64,8 @@ public: JSTaggedType *newSp = sp - frameSize; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(newSp) - 1; - state->prev = sp; + state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.prev = sp; state->pc = nullptr; state->sp = newSp; state->method = thread->GetEcmaVM()->GetMethodForNativeFunction(nullptr); diff --git a/ecmascript/tooling/BUILD.gn b/ecmascript/tooling/BUILD.gn index e789c1b..4466c7e 100644 --- a/ecmascript/tooling/BUILD.gn +++ b/ecmascript/tooling/BUILD.gn @@ -94,6 +94,7 @@ ohos_shared_library("libark_ecma_debugger_test") { deps = [ ":libark_ecma_debugger_test_static", "//ark/js_runtime:libark_jsruntime_test_static", + "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", ] configs = [ diff --git a/llvm.patch b/llvm.patch new file mode 100644 index 0000000..86f6381 --- /dev/null +++ b/llvm.patch @@ -0,0 +1,121 @@ +diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt +index 0e85afa82c7..f56219422d2 100644 +--- a/llvm/CMakeLists.txt ++++ b/llvm/CMakeLists.txt +@@ -507,6 +507,12 @@ option(LLVM_BUILD_EXAMPLES + "Build the LLVM example programs. If OFF, just generate build targets." OFF) + option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) + ++option(BUILD_ARK_GC_SUPPORT ++ "ARK support GC. If ON, support GC." OFF) ++if(BUILD_ARK_GC_SUPPORT) ++ add_definitions(-DARK_GC_SUPPORT) ++endif(ARK_SUPPORT_GC) ++ + if(LLVM_BUILD_EXAMPLES) + add_definitions(-DBUILD_EXAMPLES) + endif(LLVM_BUILD_EXAMPLES) +diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp +index 1da20371caf..875184f32b2 100644 +--- a/llvm/lib/Target/X86/X86FrameLowering.cpp ++++ b/llvm/lib/Target/X86/X86FrameLowering.cpp +@@ -31,6 +31,7 @@ + #include "llvm/Support/Debug.h" + #include "llvm/Target/TargetOptions.h" + #include ++#include + + using namespace llvm; + +@@ -1169,6 +1170,29 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, + MFI.setOffsetAdjustment(-StackSize); + } + ++#ifdef ARK_GC_SUPPORT ++ // push marker ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ std::cout << __LINE__ << " marker:" << std::dec << marker << std::endl; ++ ++ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ /*reserve thread.fp */ ++ if (marker == 1) { ++ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ } ++ } ++#endif ++ + // For EH funclets, only allocate enough space for outgoing calls. Save the + // NumBytes value that we would've used for the parent frame. + unsigned ParentFrameNumBytes = NumBytes; +@@ -1635,6 +1659,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, + uint64_t SEHStackAllocAmt = NumBytes; + + if (HasFP) { ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ ++ // pop marker ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ if (marker == 1) { ++ // pop thread.fp ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ } ++ } ++#endif + // Pop EBP. + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) +@@ -1993,8 +2038,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( + + if (hasFP(MF)) { + // emitPrologue always spills frame register the first thing. ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ if (marker == 1) { ++ SpillSlotOffset -= 3 * SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += 16; ++ } else { ++ SpillSlotOffset -= 2 * SlotSize; // add type ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += 8; ++ } ++ } else { ++ SpillSlotOffset -= SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ } ++#else + SpillSlotOffset -= SlotSize; + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++#endif + + // Since emitPrologue and emitEpilogue will handle spilling and restoring of + // the frame register, we can delete it from CSI list and not have to worry -- Gitee From 4d1b014eb957f37712b0399e8261da82d509f1c5 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Sun, 10 Oct 2021 10:44:14 +0800 Subject: [PATCH 003/115] add frames descriptor Signed-off-by: songzhengchao --- .../compiler/llvm/llvm_stackmap_parser.cpp | 1 + ecmascript/frames.h | 307 +++++++++++------- 2 files changed, 192 insertions(+), 116 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index 730413c..6481933 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -81,6 +81,7 @@ bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t fram #else (void)frameFp; (void)slotAddrs; + UNREACHABLE(); #endif return true; } diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 5fcdcaf..b88cf67 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -13,122 +13,197 @@ * limitations under the License. */ -// OptimizedEntry Frame are divided up into four regions. -// The first region, Caller Frame: Interpreter Call Stub comply c calling convention, if parameter number -// larger than caller register number, then spill to stack frame. -// The second region, Fixed Header: return addr、saved c frame ptr(pointer to caller frame)、OPTIMIZED_ENTRY_FRAME -// (codegen prologue insert frame type)、saved gc frame ptr(pointer to interpreter iframe) -// The third region, which contains the callee-saved registers must be -// reserved after register allocation, since its size can only be precisely -// determined after register allocation once the number of used callee-saved -// register is certain. -// The fourth region is spill slot. Comply c calling convertion, local variable is larger callee save register, -// spill local variable to stack; heap ptr also spill stack slot before call runtime function, after call we will -// rewrite heap ptr -// slot OptimizedEntry frame -// +-----------------+-------------------------------- -// | parameter n | ^ -// |- - - - - - - - -| | -// | parameter n-1 | Caller -// | ... | frame -// | parameter n-2 | comply c calling convention -// |- - - - - - - - -| i-n th prameter spill to slot -// | parameter i | v -// -----+-----------------+-------------------------------- -// 0 | return addr | ^ ^ -// |- - - - - - - - - | | | -// 1 | saved c frame ptr | Fixed | -// |- - - - - - - - - | Header <-- frame ptr | -// 2 |OPTIMIZED_ENTRY_FRAME| | | -// |- - - - - - - - - | | | -// 3 | saved gc frame ptr | v | -// +-----------------+---- | -// 4 | callee-saved 1 | ^ | -// |- - - - - - - - -| | | -// | ... | Callee-saved | -// |- - - - - - - - -| | | -// r+3 | callee-saved r | v | -// +-----------------+---- | -// ^ -// r+4 | local variables | | | -// |- - - - - - - - -| | | -// | ... | spill slot | -// |- - - - - - - - -| | | -// | heap ptr | v v -// -----+-----------------+----- <-- stack ptr ------------- - - -// Optimized Frame is similar to OptimizedEntry Frame, only difference is Fixed Header. -// slot OptimizedEntry frame -// +-----------------+-------------------------------- -// | parameter n | ^ -// |- - - - - - - - -| | -// | parameter n-1 | Caller -// | ... | frame -// | parameter n-2 | comply c calling convention -// |- - - - - - - - -| i-n th prameter spill to slot -// | parameter i | v -// -----+-----------------+-------------------------------- -// 0 | return addr | ^ ^ -// |- - - - - - - - - | | | -// 1 | saved c frame ptr | Fixed | -// |- - - - - - - - - | Header <-- frame ptr | -// 2 | OPTIMIZED_FRAME | | | -// 3 | - - - - - - - - - | v | -// +-----------------+---- | -// 4 | callee-saved 1 | ^ | -// |- - - - - - - - -| | | -// | ... | Callee-saved | -// |- - - - - - - - -| | | -// r+3 | callee-saved r | v | -// +-----------------+---- | -// ^ -// r+4 | local variables | | | -// |- - - - - - - - -| | | -// | ... | spill slot | -// |- - - - - - - - -| | | -// | heap ptr | v v -// -----+-----------------+----- <-- stack ptr ------------- - -// for exampe: -// calls calls -// foo --------> bar ------> baz -// (interpreted) (compiled) (runtime) -// baz trigger gc, baz get current frame pointer(bar gc frame pointer), then visit foo's -// interpreter frame by reading bar gc frame pointer value -// ----+----------------+ <--- ManagedThread::GetCurrentFrame() -// / | | | -// | | | -// baz | | | -// | return address | | -// ---- +----------------+ | -// | data | | -// +----------------+ | -// +----------------+ <+------------------ -// bar | pointer to the | ----------------------+ -// | interpreter | | -// | frame(gc frame | | -// | pointer) | | -// +----------------+ | -// +----------------+ | -// | OPTIMIZED_ENTRY_ | -// | FRAME | | -// +----------------+ | -// | c frame pointer| <-----+ -// | return address | | | -// | | | | -// ---- +----------------+ | | -// E | native frame | | | -// x u | of | | | -// e t | interpreter | | | -// c e |c frame pointer | <---- | | -// ---- +----------------+ | -// | ... | | -// +----------------+ <+-------------------- -// | foo's | -// | interpreter | -// | frame | -// +----------------+ +// in aot project, three Frame: Interpreter Frame、Runtime Frame、Optimized Frame. Optimized Frame split +// Optimized Entry Frame(interpreter call stub) and Optimized Frame(stub call stub) by call scenario. +// ​we gc trigger, we skip Runtime Frame, thus define OPTIMIZED_FRAME、OPTIMIZED_ENTRY_FRAME、INTERPRETER_FRAME respectively +// represent optimized frame、optimized entry frame、interpreter frame. + +// Frame Layout +// Interpreter Frame(alias **iframe** ) Layout as follow: +// ``` +// +---------------------------------+--------------------+ +// | argv[n-1] | ^ +// |----------------------------------| | +// | ........ | | +// | argv[0] | | +// |----------------------------------| | +// | thisArg | | +// |----------------------------------| | +// | newTarget | | +// |----------------------------------| | +// | callTarget | | +// +----------------------------------+--------+ | +// | FrameType | ^ interpreter frame +// |----------------------------------| | | +// | pre(pre stack pointer) | | | +// |----------------------------------| | | +// | numActualArgs | | | +// |----------------------------------| | | +// | env | | | +// |----------------------------------| | | +// | acc | FrameState | +// |----------------------------------| | | +// | constantpool | | | +// |----------------------------------| | | +// | method | | | +// |----------------------------------| | | +// | sp(current stack point) | | | +// |----------------------------------| | | +// | pc(bytecode addr) | v v +// +----------------------------------+--------+----------+ +// ``` +// address space grow from high address to low address.we add new field **FrameType** , +// the field's value is INTERPRETER_FRAME(represent interpreter frame). +// **currentsp** is pointer to callTarget field address, sp field 's value is **currentsp** , +// pre field pointer pre stack frame point. fill JSthread's sp field with iframe sp field +// by calling JSThread->SetCurrentSPFrame and save pre Frame address to iframe pre field. + +// Runtime Frame: comply with C-ABI without custom modify, function generat frame. +// ​ +// Optimized Frame and Optimized Entry Frame, we also comply with C-ABI, +//the difference from Runtime Frame is that prologue and epilogue is customed. + +// Optimized Entry Frame layout as follow, we reserve two stack slot for saving eparately new field **FrameType** +// which's value is OPTIMIZED_ENTRY_FRAME and new field pre that's value is iframe.sp by calling JSThread->GetCurrentSPFrame. +// fp field point to pre frame, **currentfp** is pointer to fp field address. +// save JSthread's sp to pre field and fill JSthread's sp field with **currentfp** . + + +// ``` +// +---------------------------------------------------+ +// | parameter i | ^ +// |- - - - - - - - - -- | | +// | parameter n-2 | Caller frame +// | ... | comply c-abi +// | parameter n-1 | paramters push to stack from left to right +// |- - - - - - - - - | i-n th prameter spill to slot +// | parameter n | v +// +--------------------------+------------------------+ +// | return addr | ^ ^ +// |- - - - - - - - - | | | +// | fp | Fixed | +// |- - - - - - - - - | Header <-- frame ptr | +// | FrameType | | callee frame Header +// |- - - - - - - - - | | | +// | pre | v | +// +--------------------------+------------------------+ +// ``` + +// ​ Optimized Frame layout as follow, we reserve one stack slot for saving FrameType field, +// which's value is OPTIMIZED_FRAME. + +// ``` +// +---------------------------------------------------+ +// | parameter n | ^ +// |- - - - - - - - - -- | | +// | parameter n-1 | Caller frame +// | ... | comply c-abi +// | parameter n-2 | paramters push to stack from left to right +// |- - - - - - - - - | i-n th prameter spill to slot +// | parameter i | v +// +--------------------------+------------------------+ +// | return addr | ^ ^ +// |- - - - - - - - - | | | +// | fp | Fixed | +// |- - - - - - - - - | Header <-- frame ptr callee frame Header +// | FrameType | V | +// +--------------------------+------------------------+ +// ``` + +// ​ JSthread's sp will be updated dynamic, the scenarios is as follows by different Frames: +// **SAVE** is to save JSthread's sp to current Frame pre field, +// **UPDATE** is to fill JSthread's sp with currentsp or currentfp when current frame is iframe or Optimized EntryFrame/Optimized Frame. +// **nop** represent don't call SAVE or UPDATE, **illegal** represent this secnarios don't existed. + +// ``` +// iframe OptimizedEntry Optimized RunTime +// iframe SAVE/UPATE SAVE illegal SAVE/UPATE +// OptimizedEntry UPATE illegal nop UPATE +// Optimized UPATE illegal nop UPATE +// RunTime nop illegal illegal nop +// ``` + +// ​ Iterator Frame from Runtime Frame, the process is as flollows: + +// 1 calling JSThread->GetCurrentSPFrame get Current Frame, then get FrameType field + +// 2 Iterator previous Frame: + +// ​ accessing fp field when the current frame is Optimized Frame; + +// ​ accessing pre field when the current frame is Optimized Entry Frame or Interpreter Frame + +// 3 repeat process 2 until Current Frame is nullptr + +// For Example: +// ``` +// call call call +// foo -----------------> bar --------------->baz---------------------> rtfunc +// (interpret frame) (Optimized Entry Frame) (Optimized Frame) (Runtime Frame) +// ``` + +// Frame Layout as follow: +// ``` +// +---------------------------------+--------------------+ +// | argv[n-1] | ^ +// |----------------------------------| | +// | ........ | | +// | argv[0] | | +// |----------------------------------| | +// | thisArg | | +// |----------------------------------| | +// | newTarget | | +// |----------------------------------| | +// | callTarget | | +// +----------------------------------+--------+ | +// | FrameType | ^ foo's frame +// |----------------------------------| | | +// | pre(pre stack pointer) | | | +// |----------------------------------| | | +// | numActualArgs | | | +// |----------------------------------| | | +// | env | | | +// |----------------------------------| | | +// | acc | FrameState | +// |----------------------------------| | | +// | constantpool | | | +// |----------------------------------| | | +// | method | | | +// |----------------------------------| | | +// | sp(current stack point) | | | +// |----------------------------------| | | +// | pc(bytecode addr) | v v +// +----------------------------------+--------+----------+ +// | ............. | +// +--------------------------+---------------------------+ +// | return addr | ^ ^ +// |- - - - - - - - - | | | +// | fp | Fixed | +// |- - - - - - - - - | Header <-- frame ptr | +// | FrameType | | bar's frame Header +// |- - - - - - - - - | | | +// | pre | v | +// +--------------------------+---------------------------+ +// | ............. | +// +--------------------------+---------------------------+ +// | return addr | ^ ^ +// |- - - - - - - - - | | | +// | fp | Fixed | +// |- - - - - - - - - | Header <-- frame ptr | +// | FrameType | v baz's frame Header +// | ............. | +// +--------------------------+---------------------------+ +// | | +// | rtfunc's Frame | +// | | +// +------------------------------------------------------+ +// ``` +// Iterator: +// rtfunc get baz's Frame **currentfp** by calling GetCurrentSPFrame. +// baz'Frame fp field point to bar's Frame **currentfp**, then get bar's Frame pre field. +// bar's Frame pre field point to foo's Frame **currentsp**. +// finally we can iterator foo's Frame. + #ifndef ECMASCRIPT_FRAMES_H #define ECMASCRIPT_FRAMES_H -- Gitee From b3d8eca4a174fe91255f381843d55291b989c8a6 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Sun, 10 Oct 2021 11:17:39 +0800 Subject: [PATCH 004/115] fastboot Signed-off-by: songzhengchao --- ecmascript/compiler/llvm/llvm_stackmap_parser.cpp | 6 +++--- ecmascript/compiler/llvm/llvm_stackmap_parser.h | 2 +- ecmascript/compiler/llvm_ir_builder.cpp | 2 -- ecmascript/frames.h | 8 +++++--- ecmascript/interpreter/frame_handler.h | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index 6481933..ddbb9ee 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -19,9 +19,9 @@ #include namespace kungfu { -std::string LocationTy::TypeToString(Kind location) const +std::string LocationTy::TypeToString(Kind loc) const { - switch (location) { + switch (loc) { case Kind::REGISTER: return "Register Reg Value in a register"; case Kind::DIRECT: @@ -81,7 +81,7 @@ bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t fram #else (void)frameFp; (void)slotAddrs; - UNREACHABLE(); + abort(); #endif return true; } diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.h b/ecmascript/compiler/llvm/llvm_stackmap_parser.h index 873e389..797a791 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.h +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.h @@ -89,7 +89,7 @@ struct LocationTy { uint16_t Reserved_1; OffsetType OffsetOrSmallConstant; - std::string TypeToString(Kind location) const; + std::string TypeToString(Kind loc) const; void Print() const { diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 6901890..36ea4d9 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -719,8 +719,6 @@ void LLVMIRBuilder::VisitParameter(AddrShift gate) const LOG_ECMA(INFO) << "para arg:" << argth << "value IR:" << str; } - - void LLVMIRBuilder::HandleBranch(AddrShift gate) { std::vector ins = circuit_->GetInVector(gate); diff --git a/ecmascript/frames.h b/ecmascript/frames.h index b88cf67..2702ebd 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -64,7 +64,8 @@ //the difference from Runtime Frame is that prologue and epilogue is customed. // Optimized Entry Frame layout as follow, we reserve two stack slot for saving eparately new field **FrameType** -// which's value is OPTIMIZED_ENTRY_FRAME and new field pre that's value is iframe.sp by calling JSThread->GetCurrentSPFrame. +// which's value is OPTIMIZED_ENTRY_FRAME and +// new field pre that's value is iframe.sp by calling JSThread->GetCurrentSPFrame. // fp field point to pre frame, **currentfp** is pointer to fp field address. // save JSthread's sp to pre field and fill JSthread's sp field with **currentfp** . @@ -112,8 +113,9 @@ // ​ JSthread's sp will be updated dynamic, the scenarios is as follows by different Frames: // **SAVE** is to save JSthread's sp to current Frame pre field, -// **UPDATE** is to fill JSthread's sp with currentsp or currentfp when current frame is iframe or Optimized EntryFrame/Optimized Frame. -// **nop** represent don't call SAVE or UPDATE, **illegal** represent this secnarios don't existed. +// **UPDATE** is to fill JSthread's sp with currentsp or currentfp when current frame is iframe +// or Optimized EntryFrame/Optimized Frame. +// **nop** represent don't call SAVE or UPDATE, **illegal** represent this secnarios don't existed. // ``` // iframe OptimizedEntry Optimized RunTime diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index 717060d..25b3e53 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -76,7 +76,7 @@ public: ~OptimizedFrameHandler() = default; void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; private: - JSTaggedType *fp_{nullptr}; + JSTaggedType *fp_ {nullptr}; }; class OptimizedEntryFrameHandler { @@ -86,7 +86,7 @@ public: ~OptimizedEntryFrameHandler() = default; void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; private: - JSTaggedType *fp_{nullptr}; + JSTaggedType *fp_ {nullptr}; }; class FrameIterator { @@ -94,7 +94,7 @@ public: explicit FrameIterator(JSTaggedType *fp) : fp_(fp) {} void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; private: - JSTaggedType *fp_{nullptr}; + JSTaggedType *fp_ {nullptr}; }; } // namespace ecmascript } // namespace panda -- Gitee From 709be51df71a7a995da428f3b421112da5848532 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Sun, 10 Oct 2021 11:47:37 +0800 Subject: [PATCH 005/115] fastboot Signed-off-by: surpassgoodchao --- ecmascript/frames.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 2702ebd..0012242 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -15,7 +15,8 @@ // in aot project, three Frame: Interpreter Frame、Runtime Frame、Optimized Frame. Optimized Frame split // Optimized Entry Frame(interpreter call stub) and Optimized Frame(stub call stub) by call scenario. -// ​we gc trigger, we skip Runtime Frame, thus define OPTIMIZED_FRAME、OPTIMIZED_ENTRY_FRAME、INTERPRETER_FRAME respectively +// ​we gc trigger, we skip Runtime Frame, thus define OPTIMIZED_FRAME、OPTIMIZED_ENTRY_FRAME、 +// INTERPRETER_FRAME respectively // represent optimized frame、optimized entry frame、interpreter frame. // Frame Layout @@ -61,7 +62,7 @@ // Runtime Frame: comply with C-ABI without custom modify, function generat frame. // ​ // Optimized Frame and Optimized Entry Frame, we also comply with C-ABI, -//the difference from Runtime Frame is that prologue and epilogue is customed. +// the difference from Runtime Frame is that prologue and epilogue is customed. // Optimized Entry Frame layout as follow, we reserve two stack slot for saving eparately new field **FrameType** // which's value is OPTIMIZED_ENTRY_FRAME and -- Gitee From 87a2b2bc94a145022dd768d5b00f880c921b7ae5 Mon Sep 17 00:00:00 2001 From: Gongyuhang <517563583@qq.com> Date: Mon, 11 Oct 2021 10:46:40 +0800 Subject: [PATCH 006/115] fix for ecma_string_test.cpp Signed-off-by: Gongyuhang <517563583@qq.com> --- ecmascript/tests/ecma_string_test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ecmascript/tests/ecma_string_test.cpp b/ecmascript/tests/ecma_string_test.cpp index 5a1a29a..cb158a4 100644 --- a/ecmascript/tests/ecma_string_test.cpp +++ b/ecmascript/tests/ecma_string_test.cpp @@ -1257,8 +1257,7 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_004) EXPECT_EQ(ecmaStrEmptyPtr->GetHashcode(), 0); EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EcmaString *ecmaStrNotCompEmptyPtr = EcmaString::CreateEmptyString(ecmaVMPtr); - EXPECT_EQ(ecmaStrNotCompEmptyPtr->GetHashcode(), 0); + EXPECT_EQ(ecmaStrEmptyPtr->GetHashcode(), 0); EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } -- Gitee From 2d4e495adfdbafa9bca8f51e641dbf411aa20647 Mon Sep 17 00:00:00 2001 From: xliu Date: Mon, 11 Oct 2021 11:39:04 +0800 Subject: [PATCH 007/115] fixed ace2.0 bugs Signed-off-by: xliu --- ecmascript/js_tagged_value.cpp | 5 ++--- ecmascript/napi/jsnapi.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ecmascript/js_tagged_value.cpp b/ecmascript/js_tagged_value.cpp index b86a3f1..3b7ca14 100644 --- a/ecmascript/js_tagged_value.cpp +++ b/ecmascript/js_tagged_value.cpp @@ -261,11 +261,10 @@ JSTaggedValue JSTaggedValue::ToPrimitive(JSThread *thread, const JSHandleIsECMAObject()) { - JSHandle object(tagged); EcmaVM *vm = thread->GetEcmaVM(); JSHandle keyString = vm->GetGlobalEnv()->GetToPrimitiveSymbol(); - JSHandle exoticToprim = JSObject::GetProperty(thread, object, keyString).GetValue(); + JSHandle exoticToprim = GetProperty(thread, tagged, keyString).GetValue(); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); if (!exoticToprim->IsUndefined()) { JSTaggedValue value = GetTypeString(thread, type).GetTaggedValue(); @@ -298,7 +297,7 @@ JSTaggedValue JSTaggedValue::OrdinaryToPrimitive(JSThread *thread, const JSHandl } else { keyString = globalConst->GetHandledValueOfString(); } - JSHandle entryfunc = JSObject::GetProperty(thread, tagged, keyString).GetValue(); + JSHandle entryfunc = GetProperty(thread, tagged, keyString).GetValue(); if (entryfunc->IsCallable()) { JSTaggedValue valueResult = JSFunction::Call(thread, entryfunc, tagged, 0, nullptr); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index 37a8eaa..5c06d0f 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -592,7 +592,7 @@ Local ObjectRef::Get(const EcmaVM *vm, Local key) OperationResult ret = JSTaggedValue::GetProperty(thread, obj, keyValue); RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm)); if (!ret.GetPropertyMetaData().IsFound()) { - return Local(); + return JSValueRef::Undefined(vm); } return JSNApiHelper::ToLocal(ret.GetValue()); } -- Gitee From b46fe4bc9c7bcd5c4148e59f92ca49a1f1365250 Mon Sep 17 00:00:00 2001 From: Gongyuhang <517563583@qq.com> Date: Mon, 11 Oct 2021 16:32:52 +0800 Subject: [PATCH 008/115] fix for ecma_string_test.cpp Signed-off-by: Gongyuhang <517563583@qq.com> --- ecmascript/tests/ecma_string_test.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ecmascript/tests/ecma_string_test.cpp b/ecmascript/tests/ecma_string_test.cpp index cb158a4..0af6897 100644 --- a/ecmascript/tests/ecma_string_test.cpp +++ b/ecmascript/tests/ecma_string_test.cpp @@ -1255,10 +1255,6 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_004) // GetHashcode(). EcmaString made by CreateEmptyString(). EcmaString *ecmaStrEmptyPtr = EcmaString::CreateEmptyString(ecmaVMPtr); EXPECT_EQ(ecmaStrEmptyPtr->GetHashcode(), 0); - - EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_EQ(ecmaStrEmptyPtr->GetHashcode(), 0); - EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } HWTEST_F_L0(EcmaStringTest, GetHashcode_005) @@ -1271,9 +1267,5 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_005) EcmaString *ecmaStrAllocNotCompPtr = EcmaString::AllocStringObject(sizeAlloc, false, ecmaVMPtr); EXPECT_EQ(ecmaStrAllocCompPtr->GetHashcode(), 0); EXPECT_EQ(ecmaStrAllocNotCompPtr->GetHashcode(), 0); - - EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_EQ(ecmaStrAllocNotCompPtr->GetHashcode(), 0); - EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } } // namespace panda::ecmascript -- Gitee From cf2f40cf77747397900a09c1e49e52fd33584bcf Mon Sep 17 00:00:00 2001 From: Gongyuhang <517563583@qq.com> Date: Mon, 11 Oct 2021 20:14:30 +0800 Subject: [PATCH 009/115] restore ecma_string_test.cpp and fix ecma_string.cpp Signed-off-by: Gongyuhang <517563583@qq.com> --- ecmascript/ecma_string.cpp | 2 +- ecmascript/tests/ecma_string_test.cpp | 27 +++++++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/ecmascript/ecma_string.cpp b/ecmascript/ecma_string.cpp index 51e300d..1cab135 100644 --- a/ecmascript/ecma_string.cpp +++ b/ecmascript/ecma_string.cpp @@ -415,7 +415,7 @@ uint32_t EcmaString::ComputeHashcode() const hash = ComputeHashForData(GetDataUtf16(), GetLength()); } } else { - ASSERT(static_cast(GetLength()) > (std::numeric_limits::max() >> 1U)); + ASSERT(static_cast(GetLength()) < std::numeric_limits::max() >> 1U); hash = ComputeHashForData(GetDataUtf16(), GetLength()); } return hash; diff --git a/ecmascript/tests/ecma_string_test.cpp b/ecmascript/tests/ecma_string_test.cpp index 0af6897..7aa808c 100644 --- a/ecmascript/tests/ecma_string_test.cpp +++ b/ecmascript/tests/ecma_string_test.cpp @@ -81,9 +81,9 @@ HWTEST_F_L0(EcmaStringTest, CreateEmptyString) EXPECT_FALSE(ecmaStrEmptyPtr->IsUtf16()); EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EcmaString *ecmaStrEmptyNotCompPtr = EcmaString::CreateEmptyString(ecmaVMPtr); - EXPECT_EQ(ecmaStrEmptyNotCompPtr->GetLength(), 0); - EXPECT_TRUE(ecmaStrEmptyNotCompPtr->IsUtf16()); + EcmaString *ecmaStrEmptyDisableCompPtr = EcmaString::CreateEmptyString(ecmaVMPtr); + EXPECT_EQ(ecmaStrEmptyDisableCompPtr->GetLength(), 0); + EXPECT_TRUE(ecmaStrEmptyDisableCompPtr->IsUtf16()); EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } @@ -111,7 +111,8 @@ HWTEST_F_L0(EcmaStringTest, AllocStringObject) EXPECT_FALSE(ecmaStrAllocNotCompPtr->IsUtf8()); EXPECT_TRUE(ecmaStrAllocNotCompPtr->IsUtf16()); EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_TRUE(ecmaStrAllocNotCompPtr->IsUtf16()); + EcmaString *ecmaStrAllocNotCompDisableCompPtr = EcmaString::AllocStringObject(sizeAllocNotComp, false, ecmaVMPtr); + EXPECT_TRUE(ecmaStrAllocNotCompDisableCompPtr->IsUtf16()); EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } @@ -151,7 +152,9 @@ HWTEST_F_L0(EcmaStringTest, CreateFromUtf16) EXPECT_FALSE(ecmaStrU16NotCompPtr->IsUtf8()); EXPECT_TRUE(ecmaStrU16NotCompPtr->IsUtf16()); EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_TRUE(ecmaStrU16NotCompPtr->IsUtf16()); + EcmaString *ecmaStrU16NotCompDisableCompPtr = EcmaString::CreateFromUtf16(&arrayU16NotComp[0], + lengthEcmaStrU16NotComp, ecmaVMPtr, false); + EXPECT_TRUE(ecmaStrU16NotCompDisableCompPtr->IsUtf16()); EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } @@ -1244,7 +1247,9 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_003) EXPECT_EQ(ecmaStrU16NotCompPtr->GetHashcode(), static_cast(hashExpect)); EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_EQ(ecmaStrU16NotCompPtr->GetHashcode(), static_cast(hashExpect)); + EcmaString *ecmaStrU16NotCompDisableCompPtr = EcmaString::CreateFromUtf16(&arrayU16NotComp[0], + lengthEcmaStrU16NotComp, ecmaVMPtr, false); + EXPECT_EQ(ecmaStrU16NotCompDisableCompPtr->GetHashcode(), static_cast(hashExpect)); EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } @@ -1255,6 +1260,11 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_004) // GetHashcode(). EcmaString made by CreateEmptyString(). EcmaString *ecmaStrEmptyPtr = EcmaString::CreateEmptyString(ecmaVMPtr); EXPECT_EQ(ecmaStrEmptyPtr->GetHashcode(), 0); + + EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. + EcmaString *ecmaStrEmptyDisableCompPtr = EcmaString::CreateEmptyString(ecmaVMPtr); + EXPECT_EQ(ecmaStrEmptyDisableCompPtr->GetHashcode(), 0); + EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } HWTEST_F_L0(EcmaStringTest, GetHashcode_005) @@ -1267,5 +1277,10 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_005) EcmaString *ecmaStrAllocNotCompPtr = EcmaString::AllocStringObject(sizeAlloc, false, ecmaVMPtr); EXPECT_EQ(ecmaStrAllocCompPtr->GetHashcode(), 0); EXPECT_EQ(ecmaStrAllocNotCompPtr->GetHashcode(), 0); + + EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. + EcmaString *ecmaStrAllocNotCompDisableCompPtr = EcmaString::AllocStringObject(sizeAlloc, false, ecmaVMPtr); + EXPECT_EQ(ecmaStrAllocNotCompDisableCompPtr->GetHashcode(), 0); + EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } } // namespace panda::ecmascript -- Gitee From 8724269cb93108b6b68f867498b41261d26dfca1 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Tue, 12 Oct 2021 11:48:03 +0800 Subject: [PATCH 010/115] StubCallRunTimeThreadFpLock --> StubCallRunTimeThreadFpScope .cpp use PANDA_TARGET_AMD64 delete Signed-off-by: surpassgoodchao --- .../compiler/llvm/llvm_stackmap_parser.cpp | 20 ++++------- .../compiler/llvm/llvm_stackmap_parser.h | 10 ++++++ ecmascript/frames.h | 6 ++++ ecmascript/interpreter/frame_handler.cpp | 10 ------ ecmascript/runtime_trampolines.cpp | 36 +++++++------------ ecmascript/runtime_trampolines.h | 10 +++--- 6 files changed, 39 insertions(+), 53 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index ddbb9ee..0c4650c 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -57,18 +57,15 @@ bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t fram if (!StackMapByAddr(funcAddr, infos)) { return false; } -#ifdef PANDA_TARGET_AMD64 - uintptr_t *rbp = reinterpret_cast(frameFp); - uintptr_t returnAddr = *(rbp + 1); - uintptr_t *rsp = rbp + 2; // 2: rsp offset - rbp = reinterpret_cast(*rbp); + uintptr_t *fp = reinterpret_cast(frameFp); uintptr_t **address = nullptr; for (auto &info: infos) { - if (info.first == 7) { // 7: rsp for x86_64 + if (info.first == SP_DWARF_REG_NUM) { + uintptr_t *rsp = fp + SP_OFFSET; address = reinterpret_cast(reinterpret_cast(rsp) + info.second); - // rbp - } else if (info.first == 6) { // 6: rbp for x86_64 - address = reinterpret_cast(reinterpret_cast(rbp) + info.second); + } else if (info.first == FP_DWARF_REG_NUM) { + fp = reinterpret_cast(*fp); + address = reinterpret_cast(reinterpret_cast(fp) + info.second); } else { address = nullptr; abort(); @@ -78,11 +75,6 @@ bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t fram std::cout << " *value :" << **address << std::endl; slotAddrs.push_back(reinterpret_cast(address)); } -#else - (void)frameFp; - (void)slotAddrs; - abort(); -#endif return true; } diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.h b/ecmascript/compiler/llvm/llvm_stackmap_parser.h index 797a791..6e994e6 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.h +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.h @@ -21,6 +21,16 @@ #include #include +#ifdef PANDA_TARGET_AMD64 +#define SP_DWARF_REG_NUM 7 +#define FP_DWARF_REG_NUM 6 +#define SP_OFFSET 2 +#else +#define SP_DWARF_REG_NUM 0 +#define FP_DWARF_REG_NUM 0 +#define SP_OFFSET 0 +#endif + namespace kungfu { using OffsetType = int32_t; using DwarfRegType = uint16_t; diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 0012242..e13e023 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -210,6 +210,12 @@ #ifndef ECMASCRIPT_FRAMES_H #define ECMASCRIPT_FRAMES_H +#ifdef PANDA_TARGET_AMD64 +#define GET_CURRETN_FP(fp) asm("mov %%rbp, %0" : "=rm" (fp)) +#else +#define GET_CURRETN_FP(fp) +#endif + namespace panda::ecmascript { class JSThread; enum class FrameType: uint64_t { diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index f50b97c..cc9c75a 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -199,7 +199,6 @@ void EcmaFrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const { -#ifdef PANDA_TARGET_AMD64 JSTaggedType *current = fp_; if (current != nullptr) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -216,15 +215,10 @@ void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisito v0(Root::ROOT_FRAME, ObjectSlot(address)); } } -#else - (void)v0; - (void)v1; -#endif } void OptimizedEntryFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const { -#ifdef PANDA_TARGET_AMD64 JSTaggedType *current = fp_; if (current != nullptr) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -241,10 +235,6 @@ void OptimizedEntryFrameHandler::Iterate(const RootVisitor &v0, const RootRangeV v0(Root::ROOT_FRAME, ObjectSlot(address)); } } -#else - (void)v0; - (void)v1; -#endif } void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index efb4b20..f52e2bf 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -28,11 +28,9 @@ bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argRece uint64_t argValue, uint32_t argAttr) { JSTaggedType *fp = nullptr; -#ifdef PANDA_TARGET_AMD64 - asm("mov %%rbp, %0" : "=rm" (fp)); -#endif + GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpLock(thread, fp); + StubCallRunTimeThreadFpScope(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiver(thread, reinterpret_cast(argReceiver)); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); @@ -44,11 +42,9 @@ bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint bool argMayThrow) { JSTaggedType *fp = nullptr; -#ifdef PANDA_TARGET_AMD64 - asm("mov %%rbp, %0" : "=rm" (fp)); -#endif + GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpLock(thread, fp); + StubCallRunTimeThreadFpScope(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiver(thread, JSTaggedValue(reinterpret_cast(argReceiver))); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); @@ -59,11 +55,9 @@ bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint void RuntimeTrampolines::ThrowTypeError(uint64_t argThread, int argMessageStringId) { JSTaggedType *fp = nullptr; -#ifdef PANDA_TARGET_AMD64 - asm("mov %%rbp, %0" : "=rm" (fp)); -#endif + GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpLock(thread, fp); + StubCallRunTimeThreadFpScope(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); std::string message = MessageString::GetMessageString(argMessageStringId); ObjectFactory *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); @@ -75,11 +69,9 @@ bool RuntimeTrampolines::JSProxySetProperty(uint64_t argThread, uint64_t argProx uint64_t argReceiver, bool argMayThrow) { JSTaggedType *fp = nullptr; -#ifdef PANDA_TARGET_AMD64 - asm("mov %%rbp, %0" : "=rm" (fp)); -#endif + GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpLock(thread, fp); + StubCallRunTimeThreadFpScope(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle proxy(thread, JSTaggedValue(reinterpret_cast(argProxy))); JSHandle index(thread, JSTaggedValue(reinterpret_cast(argKey))); @@ -98,11 +90,9 @@ uint32_t RuntimeTrampolines::GetHash32(uint64_t key, uint64_t len) uint64_t RuntimeTrampolines::CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver) { JSTaggedType *fp = nullptr; -#ifdef PANDA_TARGET_AMD64 - asm("mov %%rbp, %0" : "=rm" (fp)); -#endif + GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpLock(thread, fp); + StubCallRunTimeThreadFpScope(thread, fp); auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); return JSObject::CallGetter(thread, accessor, objHandle).GetRawData(); @@ -111,11 +101,9 @@ uint64_t RuntimeTrampolines::CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t RuntimeTrampolines::AccessorGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver) { JSTaggedType *fp = nullptr; -#ifdef PANDA_TARGET_AMD64 - asm("mov %%rbp, %0" : "=rm" (fp)); -#endif + GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpLock(thread, fp); + StubCallRunTimeThreadFpScope(thread, fp); auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); return accessor->CallInternalGet(thread, objHandle).GetRawData(); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 88a83ce..94e7115 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -50,23 +50,23 @@ public: static uint32_t StringGetHashCode(uint64_t ecmaString); }; -class StubCallRunTimeThreadFpLock { +class StubCallRunTimeThreadFpScope { public: - StubCallRunTimeThreadFpLock(JSThread *thread, JSTaggedType *newFp) + StubCallRunTimeThreadFpScope(JSThread *thread, JSTaggedType *newFp) :oldRbp_(const_cast(thread->GetCurrentSPFrame())), thread_(thread) { thread_->SetCurrentSPFrame(newFp); - std::cout << "StubCallRunTimeThreadFpLock newFp: " << newFp << " oldRbp_ : " << oldRbp_ + std::cout << "StubCallRunTimeThreadFpScope newFp: " << newFp << " oldRbp_ : " << oldRbp_ << " thread_->fp:" << thread_->GetCurrentSPFrame() <( reinterpret_cast(newFp) + FrameConst::kFrameType)); std::cout << "type = " << as_integer(type) << std::endl; } - ~StubCallRunTimeThreadFpLock() + ~StubCallRunTimeThreadFpScope() { - std::cout << "~StubCallRunTimeThreadFpLock oldRbp_: " << oldRbp_ << + std::cout << "~StubCallRunTimeThreadFpScope oldRbp_: " << oldRbp_ << " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; FrameType type = *(reinterpret_cast( reinterpret_cast(oldRbp_) + FrameConst::kFrameType)); -- Gitee From d15fafc5ac14f2cb7df4cbba69620c354396cdd0 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Tue, 12 Oct 2021 12:26:02 +0800 Subject: [PATCH 011/115] fastboot review Signed-off-by: surpassgoodchao --- ecmascript/base/error_helper.cpp | 2 +- ecmascript/compiler/tests/stub_tests.cpp | 5 +- ecmascript/dump.cpp | 2 +- ecmascript/ecma_language_context.cpp | 4 +- ecmascript/frames.h | 25 +++++---- ecmascript/ic/function_cache.h | 2 +- ecmascript/interpreter/frame_handler.cpp | 55 ++++++++++--------- ecmascript/interpreter/frame_handler.h | 14 ++--- ecmascript/interpreter/interpreter-inl.h | 6 +- ecmascript/interpreter/interpreter.h | 2 +- .../interpreter/slow_runtime_helper.cpp | 6 +- ecmascript/interpreter/slow_runtime_stub.cpp | 6 +- ecmascript/js_thread.cpp | 2 +- ecmascript/object_factory.cpp | 2 +- ecmascript/runtime_trampolines.cpp | 12 ++-- ecmascript/runtime_trampolines.h | 10 ++-- ecmascript/tooling/agent/js_backend.cpp | 6 +- ecmascript/tooling/agent/js_backend.h | 4 +- ecmascript/tooling/interface/debugger_api.cpp | 22 ++++---- ecmascript/tooling/interface/debugger_api.h | 14 ++--- ecmascript/tooling/pt_js_extractor.cpp | 2 +- 21 files changed, 104 insertions(+), 99 deletions(-) diff --git a/ecmascript/base/error_helper.cpp b/ecmascript/base/error_helper.cpp index 4b6e4f0..eb3ca02 100644 --- a/ecmascript/base/error_helper.cpp +++ b/ecmascript/base/error_helper.cpp @@ -192,7 +192,7 @@ CString ErrorHelper::BuildNativeEcmaStackTrace(JSThread *thread) { auto ecmaVm = thread->GetEcmaVM(); CString data; - EcmaFrameHandler frameHandler(thread); + InterpretedFrameHandler frameHandler(thread); for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { if (frameHandler.IsBreakFrame()) { continue; diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 6a2f63c..16d815c 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -1134,10 +1134,9 @@ void DoSafepoint() if (found) { for (auto &info : infos) { uintptr_t **address = nullptr; - if (info.first == 7) { // 7: x86_64 dwarf register num, representing rsp + if (info.first == SP_DWARF_REG_NUM) { address = reinterpret_cast(reinterpret_cast(rsp) + info.second); - // rbp - } else if (info.first == 6) { // 6: x86_64 dwarf register num, representing rbp + } else if (info.first == FP_DWARF_REG_NUM) { address = reinterpret_cast(reinterpret_cast(rbp) + info.second); } std::cout << std::hex << "ref addr:" << address; diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index 30bacd0..f5adfe9 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -552,7 +552,7 @@ void JSTaggedValue::DumpVal(JSThread *thread, JSTaggedType val) void JSThread::DumpStack() { - EcmaFrameHandler handler(this); + InterpretedFrameHandler handler(this); handler.DumpStack(std::cout); } diff --git a/ecmascript/ecma_language_context.cpp b/ecmascript/ecma_language_context.cpp index 5bd1549..8a59b2e 100644 --- a/ecmascript/ecma_language_context.cpp +++ b/ecmascript/ecma_language_context.cpp @@ -25,7 +25,7 @@ #include "include/tooling/pt_lang_extension.h" namespace panda { -using ecmascript::EcmaFrameHandler; +using ecmascript::InterpretedFrameHandler; using ecmascript::EcmaVM; using ecmascript::JSThread; @@ -34,7 +34,7 @@ std::pair EcmaLanguageContext::GetCatchMethodAndOffset(Metho Method *catchMethod = method; uint32_t catchOffset = 0; auto jsThread = static_cast(thread); - EcmaFrameHandler frameHandler(jsThread); + InterpretedFrameHandler frameHandler(jsThread); for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { if (frameHandler.IsBreakFrame()) { continue; diff --git a/ecmascript/frames.h b/ecmascript/frames.h index e13e023..822d8e5 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -118,12 +118,17 @@ // or Optimized EntryFrame/Optimized Frame. // **nop** represent don't call SAVE or UPDATE, **illegal** represent this secnarios don't existed. -// ``` -// iframe OptimizedEntry Optimized RunTime -// iframe SAVE/UPATE SAVE illegal SAVE/UPATE -// OptimizedEntry UPATE illegal nop UPATE -// Optimized UPATE illegal nop UPATE -// RunTime nop illegal illegal nop +// +----------------------------------------------------------------------+ +// | | iframe | OptimizedEntry | Optimized | RunTime | +// |----------------------------------------------------------------------- +// |iframe | SAVE/UPATE | SAVE | illegal | SAVE/UPATE | +// |----------------------------------------------------------------------- +// |OptimizedEntry | UPATE | illegal | nop | UPATE | +// |----------------------------------------------------------------------- +// |Optimized | UPATE | illegal | nop | UPATE | +// |----------------------------------------------------------------------- +// |RunTime | nop | illegal | illegal | nop | +// +----------------------------------------------------------------------+ // ``` // ​ Iterator Frame from Runtime Frame, the process is as flollows: @@ -231,22 +236,22 @@ auto as_integer(Enumeration const value) return static_cast::type>(value); } -class OptFrameStateBase { +class OptimizedFrameStateBase { public: FrameType frameType; uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc }; -class InterPretFrameStateBase { +class InterpretedFrameStateBase { public: uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc FrameType frameType; }; -class LLVMOptimizedEntryFrameState { +class OptimizedEntryFrameState { public: uint64_t *threadFp; // for gc - OptFrameStateBase base; + OptimizedFrameStateBase base; }; constexpr int kSystemPointerSize = sizeof(void*); diff --git a/ecmascript/ic/function_cache.h b/ecmascript/ic/function_cache.h index edf42f0..b2ddcd5 100644 --- a/ecmascript/ic/function_cache.h +++ b/ecmascript/ic/function_cache.h @@ -36,7 +36,7 @@ public: static inline FunctionCache *GetCurrent(JSThread *thread) { - JSTaggedValue funcValue = EcmaFrameHandler(thread).GetFunction(); + JSTaggedValue funcValue = InterpretedFrameHandler(thread).GetFunction(); JSFunction *func = JSFunction::Cast(funcValue.GetTaggedObject()); return FunctionCache::Cast(func->GetFunctionCache().GetTaggedObject()); } diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index cc9c75a..91e2804 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -23,18 +23,18 @@ #include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" namespace panda::ecmascript { -EcmaFrameHandler::EcmaFrameHandler(const JSThread *thread) +InterpretedFrameHandler::InterpretedFrameHandler(const JSThread *thread) { sp_ = const_cast(thread->GetCurrentSPFrame()); } -bool EcmaFrameHandler::HasFrame() const +bool InterpretedFrameHandler::HasFrame() const { // Breakframe also is a frame return sp_ != nullptr; } -bool EcmaFrameHandler::IsBreakFrame() const +bool InterpretedFrameHandler::IsBreakFrame() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -42,7 +42,7 @@ bool EcmaFrameHandler::IsBreakFrame() const return state->sp == nullptr; } -void EcmaFrameHandler::PrevFrame() +void InterpretedFrameHandler::PrevFrame() { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -50,29 +50,29 @@ void EcmaFrameHandler::PrevFrame() sp_ = state->base.prev; } -EcmaFrameHandler EcmaFrameHandler::GetPrevFrame() const +InterpretedFrameHandler InterpretedFrameHandler::GetPrevFrame() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(sp_) - 1; - return EcmaFrameHandler(state->base.prev); + return InterpretedFrameHandler(state->base.prev); } -JSTaggedValue EcmaFrameHandler::GetVRegValue(size_t index) const +JSTaggedValue InterpretedFrameHandler::GetVRegValue(size_t index) const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) return JSTaggedValue(sp_[index]); } -void EcmaFrameHandler::SetVRegValue(size_t index, JSTaggedValue value) +void InterpretedFrameHandler::SetVRegValue(size_t index, JSTaggedValue value) { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) sp_[index] = value.GetRawData(); } -JSTaggedValue EcmaFrameHandler::GetAcc() const +JSTaggedValue InterpretedFrameHandler::GetAcc() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -80,7 +80,7 @@ JSTaggedValue EcmaFrameHandler::GetAcc() const return state->acc; } -uint32_t EcmaFrameHandler::GetSize() const +uint32_t InterpretedFrameHandler::GetSize() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -91,7 +91,7 @@ uint32_t EcmaFrameHandler::GetSize() const return static_cast(size); } -uint32_t EcmaFrameHandler::GetBytecodeOffset() const +uint32_t InterpretedFrameHandler::GetBytecodeOffset() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -101,7 +101,7 @@ uint32_t EcmaFrameHandler::GetBytecodeOffset() const return static_cast(offset); } -JSMethod *EcmaFrameHandler::GetMethod() const +JSMethod *InterpretedFrameHandler::GetMethod() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -109,7 +109,7 @@ JSMethod *EcmaFrameHandler::GetMethod() const return state->method; } -JSTaggedValue EcmaFrameHandler::GetFunction() const +JSTaggedValue InterpretedFrameHandler::GetFunction() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -120,7 +120,7 @@ JSTaggedValue EcmaFrameHandler::GetFunction() const return func; } -const uint8_t *EcmaFrameHandler::GetPc() const +const uint8_t *InterpretedFrameHandler::GetPc() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -128,7 +128,7 @@ const uint8_t *EcmaFrameHandler::GetPc() const return state->pc; } -JSTaggedType *EcmaFrameHandler::GetSp() const +JSTaggedType *InterpretedFrameHandler::GetSp() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -136,7 +136,7 @@ JSTaggedType *EcmaFrameHandler::GetSp() const return state->sp; } -ConstantPool *EcmaFrameHandler::GetConstpool() const +ConstantPool *InterpretedFrameHandler::GetConstpool() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -144,7 +144,7 @@ ConstantPool *EcmaFrameHandler::GetConstpool() const return state->constpool; } -JSTaggedValue EcmaFrameHandler::GetEnv() const +JSTaggedValue InterpretedFrameHandler::GetEnv() const { ASSERT(HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -152,7 +152,7 @@ JSTaggedValue EcmaFrameHandler::GetEnv() const return state->env; } -void EcmaFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) +void InterpretedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) { JSTaggedType *current = sp_; if (current != nullptr) { @@ -176,10 +176,10 @@ void EcmaFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1 } } -void EcmaFrameHandler::DumpStack(std::ostream &os) const +void InterpretedFrameHandler::DumpStack(std::ostream &os) const { size_t i = 0; - EcmaFrameHandler frameHandler(sp_); + InterpretedFrameHandler frameHandler(sp_); for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { os << "[" << i++ << "]:" << frameHandler.GetMethod()->ParseFunctionName() @@ -187,9 +187,9 @@ void EcmaFrameHandler::DumpStack(std::ostream &os) const } } -void EcmaFrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const +void InterpretedFrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const { - EcmaFrameHandler frameHandler(sp_); + InterpretedFrameHandler frameHandler(sp_); ASSERT(frameHandler.HasFrame()); // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions, bugprone-narrowing-conversions) @@ -245,18 +245,19 @@ void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) c reinterpret_cast(current) + FrameConst::kFrameType)); if (type == FrameType::INTERPRETER_FRAME) { FrameState *state = reinterpret_cast(current) - 1; - EcmaFrameHandler(current).Iterate(v0, v1); + InterpretedFrameHandler(current).Iterate(v0, v1); current = state->base.prev; } else if (type == FrameType::OPTIMIZED_FRAME) { - OptFrameStateBase *state = reinterpret_cast( + OptimizedFrameStateBase *state = reinterpret_cast( reinterpret_cast(current) - - MEMBER_OFFSET(OptFrameStateBase, prev)); + MEMBER_OFFSET(OptimizedFrameStateBase, prev)); OptimizedFrameHandler(current).Iterate(v0, v1); current = reinterpret_cast(state->prev); } else { - LLVMOptimizedEntryFrameState *state = reinterpret_cast( + ASSERT(type == FrameType::OPTIMIZED_ENTRY_FRAME); + OptimizedEntryFrameState *state = reinterpret_cast( reinterpret_cast(current) - - MEMBER_OFFSET(LLVMOptimizedEntryFrameState, base.prev)); + MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); OptimizedEntryFrameHandler(current).Iterate(v0, v1); current = reinterpret_cast(state->threadFp); } diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index 25b3e53..9c8a6b7 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -26,18 +26,18 @@ class JSThread; class JSFunction; class ConstantPool; -class EcmaFrameHandler { +class InterpretedFrameHandler { public: - explicit EcmaFrameHandler(JSTaggedType *sp) : sp_(sp) {} - explicit EcmaFrameHandler(const JSThread *thread); - ~EcmaFrameHandler() = default; - DEFAULT_COPY_SEMANTIC(EcmaFrameHandler); - DEFAULT_MOVE_SEMANTIC(EcmaFrameHandler); + explicit InterpretedFrameHandler(JSTaggedType *sp) : sp_(sp) {} + explicit InterpretedFrameHandler(const JSThread *thread); + ~InterpretedFrameHandler() = default; + DEFAULT_COPY_SEMANTIC(InterpretedFrameHandler); + DEFAULT_MOVE_SEMANTIC(InterpretedFrameHandler); bool HasFrame() const; bool IsBreakFrame() const; void PrevFrame(); - EcmaFrameHandler GetPrevFrame() const; + InterpretedFrameHandler GetPrevFrame() const; JSTaggedValue GetVRegValue(size_t index) const; void SetVRegValue(size_t index, JSTaggedValue value); diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 596acfa..0241782 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -229,7 +229,7 @@ JSTaggedValue EcmaInterpreter::ExecuteNative(JSThread *thread, const CallParams& FrameState *state = GET_FRAME(newSp); state->base.prev = sp; - state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.frameType = FrameType::INTERPRETER_FRAME; state->pc = nullptr; state->sp = newSp; state->method = methodToCall; @@ -450,7 +450,7 @@ void EcmaInterpreter::ResumeContext(JSThread *thread) void EcmaInterpreter::NotifyBytecodePcChanged(JSThread *thread) { - EcmaFrameHandler frameHandler(thread); + InterpretedFrameHandler frameHandler(thread); for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { if (frameHandler.IsBreakFrame()) { continue; @@ -3183,7 +3183,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool HANDLE_OPCODE(EXCEPTION_HANDLER) { auto exception = thread->GetException(); - EcmaFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(sp); uint32_t pcOffset = panda_file::INVALID_OFFSET; for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { if (frameHandler.IsBreakFrame()) { diff --git a/ecmascript/interpreter/interpreter.h b/ecmascript/interpreter/interpreter.h index 0c1a504..1e119c3 100644 --- a/ecmascript/interpreter/interpreter.h +++ b/ecmascript/interpreter/interpreter.h @@ -40,7 +40,7 @@ struct FrameState { JSTaggedValue acc; JSTaggedValue env; uint64_t numActualArgs; - InterPretFrameStateBase base; + InterpretedFrameStateBase base; }; // NOLINTNEXTLINE(bugprone-sizeof-expression) diff --git a/ecmascript/interpreter/slow_runtime_helper.cpp b/ecmascript/interpreter/slow_runtime_helper.cpp index 4d89e3d..1d9a9a8 100644 --- a/ecmascript/interpreter/slow_runtime_helper.cpp +++ b/ecmascript/interpreter/slow_runtime_helper.cpp @@ -82,7 +82,7 @@ JSTaggedValue SlowRuntimeHelper::NewObject(JSThread *thread, JSHandle context) { - EcmaFrameHandler frameHandler(thread); + InterpretedFrameHandler frameHandler(thread); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); uint32_t nregs = frameHandler.GetSize(); JSHandle regsArray = factory->NewTaggedArray(nregs); @@ -122,7 +122,7 @@ JSTaggedValue ConstructGeneric(JSThread *thread, JSHandle ctor, JSHa } // Add the input parameter - EcmaFrameHandler frameHandler(thread); + InterpretedFrameHandler frameHandler(thread); CallParams params; params.callTarget = ECMAObject::Cast(*ctor); params.newTarget = newTgt.GetTaggedType(); @@ -221,7 +221,7 @@ JSTaggedValue ConstructProxy(JSThread *thread, JSHandle ctor, JSHandle< args->Set(thread, i, value); } } - EcmaFrameHandler frameHandler(thread); + InterpretedFrameHandler frameHandler(thread); for (array_size_t i = 0; i < argsCount; ++i) { JSTaggedValue value = frameHandler.GetVRegValue(baseArgLocation + i); args->Set(thread, i + preArgsSize, value); diff --git a/ecmascript/interpreter/slow_runtime_stub.cpp b/ecmascript/interpreter/slow_runtime_stub.cpp index 43f35cd..4081456 100644 --- a/ecmascript/interpreter/slow_runtime_stub.cpp +++ b/ecmascript/interpreter/slow_runtime_stub.cpp @@ -439,7 +439,7 @@ JSTaggedValue SlowRuntimeStub::CreateObjectWithExcludedKeys(JSThread *thread, ui JSHandle obj(thread, objVal); array_size_t numExcludedKeys = 0; JSHandle excludedKeys = factory->NewTaggedArray(numKeys + 1); - EcmaFrameHandler frameHandler(thread); + InterpretedFrameHandler frameHandler(thread); JSTaggedValue excludedKey = frameHandler.GetVRegValue(firstArgRegIdx); if (!excludedKey.IsUndefined()) { numExcludedKeys = numKeys + 1; @@ -1716,7 +1716,7 @@ JSTaggedValue SlowRuntimeStub::SuperCall(JSThread *thread, JSTaggedValue func, J INTERPRETER_TRACE(thread, SuperCall); [[maybe_unused]] EcmaHandleScope handleScope(thread); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - EcmaFrameHandler frameHandler(thread); + InterpretedFrameHandler frameHandler(thread); JSHandle funcHandle(thread, func); JSHandle newTargetHandle(thread, newTarget); @@ -1741,7 +1741,7 @@ JSTaggedValue SlowRuntimeStub::SuperCallSpread(JSThread *thread, JSTaggedValue f { INTERPRETER_TRACE(thread, SuperCallSpread); [[maybe_unused]] EcmaHandleScope handleScope(thread); - EcmaFrameHandler frameHandler(thread); + InterpretedFrameHandler frameHandler(thread); JSHandle funcHandle(thread, func); JSHandle newTargetHandle(thread, newTarget); diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index 6338196..0282716 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -78,7 +78,7 @@ void JSThread::ClearException() JSTaggedValue JSThread::GetCurrentLexenv() const { - return EcmaFrameHandler(currentFrame_).GetEnv(); + return InterpretedFrameHandler(currentFrame_).GetEnv(); } void JSThread::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index 554f77f..d760c31 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -2088,7 +2088,7 @@ JSHandle ObjectFactory::NewEmptyJSObject() EcmaString *ObjectFactory::ResolveString(uint32_t stringId) { - JSMethod *caller = EcmaFrameHandler(thread_).GetMethod(); + JSMethod *caller = InterpretedFrameHandler(thread_).GetMethod(); auto *pf = caller->GetPandaFile(); auto id = panda_file::File::EntityId(stringId); auto foundStr = pf->GetStringData(id); diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index f52e2bf..e9592ee 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -30,7 +30,7 @@ bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argRece JSTaggedType *fp = nullptr; GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpScope(thread, fp); + CallRuntimeTrampolinesScope scope(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiver(thread, reinterpret_cast(argReceiver)); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); @@ -44,7 +44,7 @@ bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint JSTaggedType *fp = nullptr; GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpScope(thread, fp); + CallRuntimeTrampolinesScope scope(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiver(thread, JSTaggedValue(reinterpret_cast(argReceiver))); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); @@ -57,7 +57,7 @@ void RuntimeTrampolines::ThrowTypeError(uint64_t argThread, int argMessageString JSTaggedType *fp = nullptr; GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpScope(thread, fp); + CallRuntimeTrampolinesScope scope(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); std::string message = MessageString::GetMessageString(argMessageStringId); ObjectFactory *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); @@ -71,7 +71,7 @@ bool RuntimeTrampolines::JSProxySetProperty(uint64_t argThread, uint64_t argProx JSTaggedType *fp = nullptr; GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpScope(thread, fp); + CallRuntimeTrampolinesScope scope(thread, fp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle proxy(thread, JSTaggedValue(reinterpret_cast(argProxy))); JSHandle index(thread, JSTaggedValue(reinterpret_cast(argKey))); @@ -92,7 +92,7 @@ uint64_t RuntimeTrampolines::CallGetter(uint64_t argThread, uint64_t argGetter, JSTaggedType *fp = nullptr; GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpScope(thread, fp); + CallRuntimeTrampolinesScope scope(thread, fp); auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); return JSObject::CallGetter(thread, accessor, objHandle).GetRawData(); @@ -103,7 +103,7 @@ uint64_t RuntimeTrampolines::AccessorGetter(uint64_t argThread, uint64_t argGett JSTaggedType *fp = nullptr; GET_CURRETN_FP(fp); auto thread = reinterpret_cast(argThread); - StubCallRunTimeThreadFpScope(thread, fp); + CallRuntimeTrampolinesScope scope(thread, fp); auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); return accessor->CallInternalGet(thread, objHandle).GetRawData(); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 94e7115..e221bbb 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -50,23 +50,23 @@ public: static uint32_t StringGetHashCode(uint64_t ecmaString); }; -class StubCallRunTimeThreadFpScope { +class CallRuntimeTrampolinesScope { public: - StubCallRunTimeThreadFpScope(JSThread *thread, JSTaggedType *newFp) + CallRuntimeTrampolinesScope(JSThread *thread, JSTaggedType *newFp) :oldRbp_(const_cast(thread->GetCurrentSPFrame())), thread_(thread) { thread_->SetCurrentSPFrame(newFp); - std::cout << "StubCallRunTimeThreadFpScope newFp: " << newFp << " oldRbp_ : " << oldRbp_ + std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " oldRbp_ : " << oldRbp_ << " thread_->fp:" << thread_->GetCurrentSPFrame() <( reinterpret_cast(newFp) + FrameConst::kFrameType)); std::cout << "type = " << as_integer(type) << std::endl; } - ~StubCallRunTimeThreadFpScope() + ~CallRuntimeTrampolinesScope() { - std::cout << "~StubCallRunTimeThreadFpScope oldRbp_: " << oldRbp_ << + std::cout << "~CallRuntimeTrampolinesScope oldRbp_: " << oldRbp_ << " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; FrameType type = *(reinterpret_cast( reinterpret_cast(oldRbp_) + FrameConst::kFrameType)); diff --git a/ecmascript/tooling/agent/js_backend.cpp b/ecmascript/tooling/agent/js_backend.cpp index 6172d2a..9cf7c70 100644 --- a/ecmascript/tooling/agent/js_backend.cpp +++ b/ecmascript/tooling/agent/js_backend.cpp @@ -458,7 +458,7 @@ PtJSExtractor *JSBackend::GetExtractor(const CString &url) bool JSBackend::GenerateCallFrames(CVector> *callFrames) { int32_t callFrameId = 0; - auto walkerFunc = [this, &callFrameId, &callFrames](const EcmaFrameHandler *frameHandler) -> StackState { + auto walkerFunc = [this, &callFrameId, &callFrames](const InterpretedFrameHandler *frameHandler) -> StackState { JSMethod *method = DebuggerApi::GetMethod(frameHandler); if (method->IsNative()) { LOG(INFO, DEBUGGER) << "GenerateCallFrames: Skip CFrame and Native method"; @@ -478,7 +478,7 @@ bool JSBackend::GenerateCallFrames(CVector> *callFram return DebuggerApi::StackWalker(ecmaVm_, walkerFunc); } -bool JSBackend::GenerateCallFrame(CallFrame *callFrame, const EcmaFrameHandler *frameHandler, int32_t callFrameId) +bool JSBackend::GenerateCallFrame(CallFrame *callFrame, const InterpretedFrameHandler *frameHandler, int32_t callFrameId) { JSMethod *method = DebuggerApi::GetMethod(frameHandler); auto *pf = method->GetPandaFile(); @@ -528,7 +528,7 @@ bool JSBackend::GenerateCallFrame(CallFrame *callFrame, const EcmaFrameHandler * return true; } -std::unique_ptr JSBackend::GetLocalScopeChain(const EcmaFrameHandler *frameHandler, +std::unique_ptr JSBackend::GetLocalScopeChain(const InterpretedFrameHandler *frameHandler, std::unique_ptr *thisObj) { auto localScope = std::make_unique(); diff --git a/ecmascript/tooling/agent/js_backend.h b/ecmascript/tooling/agent/js_backend.h index 4406002..2cdff1c 100644 --- a/ecmascript/tooling/agent/js_backend.h +++ b/ecmascript/tooling/agent/js_backend.h @@ -109,8 +109,8 @@ private: PtJSExtractor *GetExtractor(const panda_file::File *file); PtJSExtractor *GetExtractor(const CString &url); bool GenerateCallFrames(CVector> *callFrames); - bool GenerateCallFrame(CallFrame *callFrame, const EcmaFrameHandler *frameHandler, int32_t frameId); - std::unique_ptr GetLocalScopeChain(const EcmaFrameHandler *frameHandler, + bool GenerateCallFrame(CallFrame *callFrame, const InterpretedFrameHandler *frameHandler, int32_t frameId); + std::unique_ptr GetLocalScopeChain(const InterpretedFrameHandler *frameHandler, std::unique_ptr *thisObj); std::unique_ptr GetGlobalScopeChain(); std::optional SetValue(int32_t regIndex, std::unique_ptr *result, const CString &varValue); diff --git a/ecmascript/tooling/interface/debugger_api.cpp b/ecmascript/tooling/interface/debugger_api.cpp index 93ae8e7..ab62924 100644 --- a/ecmascript/tooling/interface/debugger_api.cpp +++ b/ecmascript/tooling/interface/debugger_api.cpp @@ -49,11 +49,11 @@ CString DebuggerApi::ConvertToString(const std::string &str) return panda::ecmascript::ConvertToString(str); } -// EcmaFrameHandler +// InterpretedFrameHandler uint32_t DebuggerApi::GetStackDepth(const EcmaVM *ecmaVm) { uint32_t count = 0; - EcmaFrameHandler frameHandler(ecmaVm->GetJSThread()); + InterpretedFrameHandler frameHandler(ecmaVm->GetJSThread()); for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { if (frameHandler.IsBreakFrame()) { continue; @@ -63,9 +63,9 @@ uint32_t DebuggerApi::GetStackDepth(const EcmaVM *ecmaVm) return count; } -bool DebuggerApi::StackWalker(const EcmaVM *ecmaVm, std::function func) +bool DebuggerApi::StackWalker(const EcmaVM *ecmaVm, std::function func) { - EcmaFrameHandler frameHandler(ecmaVm->GetJSThread()); + InterpretedFrameHandler frameHandler(ecmaVm->GetJSThread()); for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { if (frameHandler.IsBreakFrame()) { continue; @@ -84,37 +84,37 @@ bool DebuggerApi::StackWalker(const EcmaVM *ecmaVm, std::functionGetJSThread()).GetBytecodeOffset(); + return InterpretedFrameHandler(ecmaVm->GetJSThread()).GetBytecodeOffset(); } JSMethod *DebuggerApi::GetMethod(const EcmaVM *ecmaVm) { - return EcmaFrameHandler(ecmaVm->GetJSThread()).GetMethod(); + return InterpretedFrameHandler(ecmaVm->GetJSThread()).GetMethod(); } Local DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm, size_t index) { - auto value = EcmaFrameHandler(ecmaVm->GetJSThread()).GetVRegValue(index); + auto value = InterpretedFrameHandler(ecmaVm->GetJSThread()).GetVRegValue(index); JSHandle handledValue(ecmaVm->GetJSThread(), value); return JSNApiHelper::ToLocal(handledValue); } void DebuggerApi::SetVRegValue(const EcmaVM *ecmaVm, size_t index, Local value) { - return EcmaFrameHandler(ecmaVm->GetJSThread()).SetVRegValue(index, JSNApiHelper::ToJSTaggedValue(*value)); + return InterpretedFrameHandler(ecmaVm->GetJSThread()).SetVRegValue(index, JSNApiHelper::ToJSTaggedValue(*value)); } -uint32_t DebuggerApi::GetBytecodeOffset(const EcmaFrameHandler *frameHandler) +uint32_t DebuggerApi::GetBytecodeOffset(const InterpretedFrameHandler *frameHandler) { return frameHandler->GetBytecodeOffset(); } -JSMethod *DebuggerApi::GetMethod(const EcmaFrameHandler *frameHandler) +JSMethod *DebuggerApi::GetMethod(const InterpretedFrameHandler *frameHandler) { return frameHandler->GetMethod(); } -Local DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm, const EcmaFrameHandler *frameHandler, size_t index) +Local DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm, const InterpretedFrameHandler *frameHandler, size_t index) { auto value = frameHandler->GetVRegValue(index); JSHandle handledValue(ecmaVm->GetJSThread(), value); diff --git a/ecmascript/tooling/interface/debugger_api.h b/ecmascript/tooling/interface/debugger_api.h index fa9458c..18b6f3b 100644 --- a/ecmascript/tooling/interface/debugger_api.h +++ b/ecmascript/tooling/interface/debugger_api.h @@ -32,7 +32,7 @@ class JSDebugger; } // tooling::ecmascript namespace ecmascript { -class EcmaFrameHandler; +class InterpretedFrameHandler; class EcmaVM; class JSMethod; class JSThread; @@ -41,7 +41,7 @@ class JSThread; namespace panda::tooling::ecmascript { using panda::ecmascript::CString; -using panda::ecmascript::EcmaFrameHandler; +using panda::ecmascript::InterpretedFrameHandler; using panda::ecmascript::EcmaVM; using panda::ecmascript::JSMethod; using panda::ecmascript::JSThread; @@ -59,16 +59,16 @@ public: static CString ToCString(int32_t number); static CString ConvertToString(const std::string &str); - // EcmaFrameHandler + // InterpretedFrameHandler static uint32_t GetStackDepth(const EcmaVM *ecmaVm); - static bool StackWalker(const EcmaVM *ecmaVm, std::function func); + static bool StackWalker(const EcmaVM *ecmaVm, std::function func); static uint32_t GetBytecodeOffset(const EcmaVM *ecmaVm); static JSMethod *GetMethod(const EcmaVM *ecmaVm); static Local GetVRegValue(const EcmaVM *ecmaVm, size_t index); static void SetVRegValue(const EcmaVM *ecmaVm, size_t index, Local value); - static uint32_t GetBytecodeOffset(const EcmaFrameHandler *frameHandler); - static JSMethod *GetMethod(const EcmaFrameHandler *frameHandler); - static Local GetVRegValue(const EcmaVM *ecmaVm, const EcmaFrameHandler *frameHandler, size_t index); + static uint32_t GetBytecodeOffset(const InterpretedFrameHandler *frameHandler); + static JSMethod *GetMethod(const InterpretedFrameHandler *frameHandler); + static Local GetVRegValue(const EcmaVM *ecmaVm, const InterpretedFrameHandler *frameHandler, size_t index); // JSThread static Local GetException(const EcmaVM *ecmaVm); diff --git a/ecmascript/tooling/pt_js_extractor.cpp b/ecmascript/tooling/pt_js_extractor.cpp index 7498f82..fe9e50f 100644 --- a/ecmascript/tooling/pt_js_extractor.cpp +++ b/ecmascript/tooling/pt_js_extractor.cpp @@ -17,7 +17,7 @@ #include "ecmascript/tooling/pt_js_extractor.h" namespace panda::tooling::ecmascript { -using panda::ecmascript::EcmaFrameHandler; +using panda::ecmascript::InterpretedFrameHandler; using panda::ecmascript::JSTaggedType; uint32_t PtJSExtractor::SingleStepper::GetStackDepth() const { -- Gitee From 1c36b50587bf478675f6d7646ee08b86b288d86c Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Tue, 12 Oct 2021 12:55:04 +0800 Subject: [PATCH 012/115] review code fix Signed-off-by: surpassgoodchao --- ecmascript/compiler/tests/stub_tests.cpp | 1 + ecmascript/runtime_trampolines.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 16d815c..9511e89 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -1139,6 +1139,7 @@ void DoSafepoint() } else if (info.first == FP_DWARF_REG_NUM) { address = reinterpret_cast(reinterpret_cast(rbp) + info.second); } + // print ref and vlue for debug std::cout << std::hex << "ref addr:" << address; std::cout << " value:" << *address; std::cout << " *value :" << **address << std::endl; diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index e221bbb..7d7c286 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -57,7 +57,7 @@ public: thread_(thread) { thread_->SetCurrentSPFrame(newFp); - + // print newfp and type for debug std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " oldRbp_ : " << oldRbp_ << " thread_->fp:" << thread_->GetCurrentSPFrame() <( @@ -66,6 +66,7 @@ public: } ~CallRuntimeTrampolinesScope() { + // print oldfp and type for debug std::cout << "~CallRuntimeTrampolinesScope oldRbp_: " << oldRbp_ << " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; FrameType type = *(reinterpret_cast( -- Gitee From 507111a0e893d4bf19016a5e54f00cd0cb99a497 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Tue, 12 Oct 2021 14:17:00 +0800 Subject: [PATCH 013/115] fastboot fix Signed-off-by: surpassgoodchao --- ecmascript/interpreter/frame_handler.cpp | 3 --- ecmascript/tooling/agent/js_backend.cpp | 3 ++- ecmascript/tooling/interface/debugger_api.cpp | 3 ++- ecmascript/tooling/interface/debugger_api.h | 3 ++- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 91e2804..dd2522d 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -14,9 +14,6 @@ */ #include "ecmascript/interpreter/frame_handler.h" - -#include - #include "ecmascript/interpreter/interpreter.h" #include "ecmascript/js_thread.h" #include "libpandafile/bytecode_instruction-inl.h" diff --git a/ecmascript/tooling/agent/js_backend.cpp b/ecmascript/tooling/agent/js_backend.cpp index 9cf7c70..d461c61 100644 --- a/ecmascript/tooling/agent/js_backend.cpp +++ b/ecmascript/tooling/agent/js_backend.cpp @@ -478,7 +478,8 @@ bool JSBackend::GenerateCallFrames(CVector> *callFram return DebuggerApi::StackWalker(ecmaVm_, walkerFunc); } -bool JSBackend::GenerateCallFrame(CallFrame *callFrame, const InterpretedFrameHandler *frameHandler, int32_t callFrameId) +bool JSBackend::GenerateCallFrame(CallFrame *callFrame, + const InterpretedFrameHandler *frameHandler, int32_t callFrameId) { JSMethod *method = DebuggerApi::GetMethod(frameHandler); auto *pf = method->GetPandaFile(); diff --git a/ecmascript/tooling/interface/debugger_api.cpp b/ecmascript/tooling/interface/debugger_api.cpp index ab62924..ef48956 100644 --- a/ecmascript/tooling/interface/debugger_api.cpp +++ b/ecmascript/tooling/interface/debugger_api.cpp @@ -114,7 +114,8 @@ JSMethod *DebuggerApi::GetMethod(const InterpretedFrameHandler *frameHandler) return frameHandler->GetMethod(); } -Local DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm, const InterpretedFrameHandler *frameHandler, size_t index) +Local DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm, + const InterpretedFrameHandler *frameHandler, size_t index) { auto value = frameHandler->GetVRegValue(index); JSHandle handledValue(ecmaVm->GetJSThread(), value); diff --git a/ecmascript/tooling/interface/debugger_api.h b/ecmascript/tooling/interface/debugger_api.h index 18b6f3b..e030405 100644 --- a/ecmascript/tooling/interface/debugger_api.h +++ b/ecmascript/tooling/interface/debugger_api.h @@ -68,7 +68,8 @@ public: static void SetVRegValue(const EcmaVM *ecmaVm, size_t index, Local value); static uint32_t GetBytecodeOffset(const InterpretedFrameHandler *frameHandler); static JSMethod *GetMethod(const InterpretedFrameHandler *frameHandler); - static Local GetVRegValue(const EcmaVM *ecmaVm, const InterpretedFrameHandler *frameHandler, size_t index); + static Local GetVRegValue(const EcmaVM *ecmaVm, + const InterpretedFrameHandler *frameHandler, size_t index); // JSThread static Local GetException(const EcmaVM *ecmaVm); -- Gitee From 63b77386f4869fb81ae60b5cb1d52c34c04a7038 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Tue, 12 Oct 2021 14:19:18 +0800 Subject: [PATCH 014/115] fastboot fix Signed-off-by: surpassgoodchao --- ecmascript/interpreter/interpreter-inl.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 0241782..110addc 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -263,7 +263,7 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param breakState->pc = nullptr; breakState->sp = nullptr; breakState->base.prev = originalPrevSp; - breakState->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + breakState->base.frameType = FrameType::INTERPRETER_FRAME; breakState->numActualArgs = 0; JSTaggedType *prevSp = newSp; @@ -303,7 +303,7 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param state->constpool = constpool; state->profileTypeInfo = thisFunc->GetProfileTypeInfo(); state->base.prev = prevSp; - state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.frameType = FrameType::INTERPRETER_FRAME; state->numActualArgs = numActualArgs; JSTaggedValue env = thisFunc->GetLexicalEnv(); @@ -342,7 +342,7 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH breakState->pc = nullptr; breakState->sp = nullptr; breakState->base.prev = currentSp; - breakState->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + breakState->base.frameType = FrameType::INTERPRETER_FRAME; breakState->numActualArgs = 0; // create new frame and resume sp and pc @@ -373,7 +373,7 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH state->acc = context->GetAcc(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) state->base.prev = breakSp; - state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.frameType = FrameType::INTERPRETER_FRAME; JSTaggedValue env = context->GetLexicalEnv(); state->env = env; // execute interpreter @@ -405,7 +405,7 @@ void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandlepc = nullptr; breakState->sp = nullptr; breakState->base.prev = currentSp; - breakState->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + breakState->base.frameType = FrameType::INTERPRETER_FRAME; // create new frame and resume sp and pc uint32_t nregs = context->GetNRegs().GetInt(); @@ -435,7 +435,7 @@ void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandleacc = context->GetAcc(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) state->base.prev = breakSp; - state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.frameType = FrameType::INTERPRETER_FRAME; state->env = context->GetLexicalEnv(); thread->SetCurrentSPFrame(newSp); @@ -779,7 +779,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool FrameState *state = GET_FRAME(newSp); state->base.prev = sp; - state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.frameType = FrameType::INTERPRETER_FRAME; state->pc = nullptr; state->sp = newSp; state->method = methodToCall; @@ -863,7 +863,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool FrameState *state = GET_FRAME(newSp); state->base.prev = sp; - state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.frameType = FrameType::INTERPRETER_FRAME; state->pc = pc = JSMethod::Cast(methodToCall)->GetBytecodeArray(); state->sp = sp = newSp; state->method = methodToCall; @@ -3224,7 +3224,7 @@ void EcmaInterpreter::InitStackFrame(JSThread *thread) state->acc = JSTaggedValue::Hole(); state->constpool = nullptr; state->profileTypeInfo = JSTaggedValue::Undefined(); - state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.frameType = FrameType::INTERPRETER_FRAME; state->base.prev = nullptr; state->numActualArgs = 0; } -- Gitee From 064135d18a3f48b69f40885347edcaeab982c88b Mon Sep 17 00:00:00 2001 From: Han00000000 Date: Tue, 12 Oct 2021 11:50:58 +0800 Subject: [PATCH 015/115] fix stub_aot_opt running errors and add arm/arm64 target for js optimizer Signed-off-by: Han00000000 Change-Id: Idb10d3dffbf79a7f615ccb3f8a468cd35caf73a0 --- BUILD.gn | 24 +++++ ecmascript/compiler/BUILD.gn | 40 ++++--- ecmascript/compiler/circuit_builder.cpp | 4 +- ecmascript/compiler/fast_stub.cpp | 17 +-- ecmascript/compiler/fast_stub.h | 70 ++++++------- ecmascript/compiler/llvm_codegen.cpp | 5 +- ecmascript/compiler/llvm_codegen.h | 5 +- ecmascript/compiler/llvm_ir_builder.cpp | 38 +------ ecmascript/compiler/llvm_ir_builder.h | 4 +- ecmascript/compiler/llvm_mcjit_engine.cpp | 41 +++++--- ecmascript/compiler/llvm_mcjit_engine.h | 34 +++--- ecmascript/compiler/options.h.erb | 118 +++++++++++++++++++++ ecmascript/compiler/stub.cpp | 42 +++++--- ecmascript/compiler/stub.h | 13 ++- ecmascript/compiler/stub_aot_compiler.cpp | 121 +++++++++++----------- ecmascript/compiler/stub_aot_compiler.h | 12 ++- ecmascript/compiler/stub_aot_options.yaml | 31 ++++++ ecmascript/compiler/tests/stub_tests.cpp | 74 ++++++------- ecmascript/mem/machine_code.h | 3 +- js_runtime_config.gni | 49 +++++++++ test/test_helper.gni | 1 + 21 files changed, 500 insertions(+), 246 deletions(-) create mode 100644 ecmascript/compiler/options.h.erb create mode 100644 ecmascript/compiler/stub_aot_options.yaml diff --git a/BUILD.gn b/BUILD.gn index bea20a7..080f62c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -182,6 +182,15 @@ config("ark_jsruntime_common_config") { "-O0", "-ggdb3", ] + if (is_linux && (current_cpu == "x86" || current_cpu == "x64") && + run_with_asan) { + cflags_cc += [ + "-fsanitize=address", + "-fno-omit-frame-pointer", + ] + ldflags += [ "-L" + rebase_path("${root_out_dir}/ark/ark_js_runtime") ] + libs = [ "clang_rt.asan-x86_64" ] + } } else { defines += [ "NDEBUG" ] } @@ -390,6 +399,11 @@ source_set("libark_jsruntime_static") { } else { deps += [ "$ark_root/runtime:libarkruntime" ] } + + if (is_debug && is_linux && (current_cpu == "x86" || current_cpu == "x64") && + run_with_asan) { + deps += [ ":copy_asan_runtime" ] + } } ohos_shared_library("libark_jsruntime") { @@ -423,6 +437,11 @@ source_set("libark_jsruntime_test_static") { sdk_libc_secshared_dep, ] + if (is_debug && is_linux && (current_cpu == "x86" || current_cpu == "x64") && + run_with_asan) { + deps += [ ":copy_asan_runtime" ] + } + public_configs = [ ":ark_jsruntime_public_config", # should add before # arkruntime_public_config @@ -472,3 +491,8 @@ action("copy_resource_xml") { inputs = [ src_path + src_xml ] outputs = [ "$target_out_dir" ] } + +ohos_copy("copy_asan_runtime") { + sources = [ "${asan_lib_path}/libclang_rt.asan-x86_64.a" ] + outputs = [ "${root_out_dir}/ark/ark_js_runtime/{{source_file_part}}" ] +} diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index 0cfb8f7..b211d1c 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -107,25 +107,28 @@ source_set("libark_jsoptimizer_static") { "LLVMAsmParser", "LLVMMCParser", "LLVMMIRParser", - "LLVMX86Info", - "LLVMAArch64Info", - "LLVMARMDesc", - "LLVMAArch64Desc", - "LLVMX86Desc", - "LLVMX86Disassembler", - "LLVMARMDisassembler", - "LLVMAArch64Disassembler", "LLVMMCDisassembler", - "LLVMAArch64CodeGen", - "LLVMARMCodeGen", "LLVMCodeGen", - "LLVMX86CodeGen", - "LLVMX86AsmParser", "LLVMTransformUtils", - "LLVMAArch64Utils", + "LLVMIRReader", "LLVMARMUtils", + "LLVMARMCodeGen", + "LLVMARMDisassembler", + "LLVMARMDesc", + "LLVMARMInfo", + "LLVMARMAsmParser", + "LLVMAArch64Utils", + "LLVMAArch64CodeGen", + "LLVMAArch64Info", + "LLVMAArch64Desc", + "LLVMAArch64Disassembler", + "LLVMAArch64AsmParser", "LLVMX86Utils", - "LLVMIRReader", + "LLVMX86AsmParser", + "LLVMX86CodeGen", + "LLVMX86Desc", + "LLVMX86Disassembler", + "LLVMX86Info", ] deps = [ @@ -174,8 +177,16 @@ ohos_shared_library("libark_jsoptimizer_test") { subsystem_name = "test" } +ark_gen_file("stub_aot_options_gen_h") { + template_file = "options.h.erb" + data_file = "stub_aot_options.yaml" + requires = [ "$ark_root/templates/common.rb" ] + output_file = "$target_gen_dir/generated/stub_aot_options_gen.h" +} + ohos_executable("ark_stub_opt") { sources = [ "stub_aot_compiler.cpp" ] + include_dirs = [ "$target_gen_dir" ] configs = [ ":include_llvm", @@ -185,6 +196,7 @@ ohos_executable("ark_stub_opt") { ] deps = [ + ":stub_aot_options_gen_h", "$ark_root/libpandabase:libarkbase", "//ark/js_runtime:libark_jsruntime", "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer", diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index 0fcc176..541311d 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -365,7 +365,7 @@ AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift targ AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, std::initializer_list args) { - ASSERT(descriptor->GetStubKind() == StubDescriptor::RUNTIME_STUB); + ASSERT(descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB); std::vector inputs; auto dependEntry = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY)); inputs.push_back(dependEntry); @@ -382,7 +382,7 @@ AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShi AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, AddrShift depend, std::initializer_list args) { - ASSERT(descriptor->GetStubKind() == StubDescriptor::RUNTIME_STUB); + ASSERT(descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB); std::vector inputs; inputs.push_back(depend); inputs.push_back(target); diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index ac005e5..cea7472 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -344,7 +344,7 @@ void FastDivStub::GenerateCircuit() } } -void FastFindOwnElementStub::GenerateCircuit() +void FindOwnElementStub::GenerateCircuit() { auto env = GetEnvironment(); AddrShift thread = PtrArgument(0); @@ -401,7 +401,7 @@ void FastFindOwnElementStub::GenerateCircuit() Return(GetHoleConstant()); } -void FastGetElementStub::GenerateCircuit() +void GetElementStub::GenerateCircuit() { auto env = GetEnvironment(); AddrShift thread = PtrArgument(0); @@ -432,7 +432,7 @@ void FastGetElementStub::GenerateCircuit() LoopEnd(&loopHead); } -void FastFindOwnElement2Stub::GenerateCircuit() +void FindOwnElement2Stub::GenerateCircuit() { auto env = GetEnvironment(); AddrShift thread = PtrArgument(0); @@ -493,7 +493,7 @@ void FastFindOwnElement2Stub::GenerateCircuit() Return(GetHoleConstant()); } -void FastSetElementStub::GenerateCircuit() +void SetElementStub::GenerateCircuit() { auto env = GetEnvironment(); AddrShift thread = PtrArgument(0); @@ -507,6 +507,7 @@ void FastSetElementStub::GenerateCircuit() AddrShift pattr = Alloca(static_cast(MachineRep::K_WORD32)); AddrShift pindexOrEntry = Alloca(static_cast(MachineRep::K_WORD32)); Label loopHead(env); + Label loopEnd(env); Jump(&loopHead); LoopBegin(&loopHead); { @@ -647,13 +648,15 @@ void FastSetElementStub::GenerateCircuit() } Bind(¬JsProxy); onPrototype = TrueConstant(); + Jump(&loopEnd); } } } + Bind(&loopEnd); LoopEnd(&loopHead); } -void FastGetPropertyByIndexStub::GenerateCircuit() +void GetPropertyByIndexStub::GenerateCircuit() { auto env = GetEnvironment(); AddrShift thread = PtrArgument(0); @@ -765,7 +768,7 @@ void FastGetPropertyByIndexStub::GenerateCircuit() } } -void FastSetPropertyByIndexStub::GenerateCircuit() +void SetPropertyByIndexStub::GenerateCircuit() { auto env = GetEnvironment(); AddrShift thread = PtrArgument(0); @@ -857,7 +860,7 @@ void FastSetPropertyByIndexStub::GenerateCircuit() } } -void FastGetPropertyByNameStub::GenerateCircuit() +void GetPropertyByNameStub::GenerateCircuit() { auto env = GetEnvironment(); AddrShift thread = PtrArgument(0); diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 6814fa3..109b7be 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -70,73 +70,73 @@ public: void GenerateCircuit() override; }; -class FastFindOwnElementStub : public Stub { +class FindOwnElementStub : public Stub { public: // 3 : 3 means argument counts - explicit FastFindOwnElementStub(Circuit *circuit) : Stub("FastFindOwnElement", 3, circuit) {} - ~FastFindOwnElementStub() = default; - NO_MOVE_SEMANTIC(FastFindOwnElementStub); - NO_COPY_SEMANTIC(FastFindOwnElementStub); + explicit FindOwnElementStub(Circuit *circuit) : Stub("FindOwnElement", 3, circuit) {} + ~FindOwnElementStub() = default; + NO_MOVE_SEMANTIC(FindOwnElementStub); + NO_COPY_SEMANTIC(FindOwnElementStub); void GenerateCircuit() override; }; -class FastGetElementStub : public Stub { +class GetElementStub : public Stub { public: // 3 : 3 means argument counts - explicit FastGetElementStub(Circuit *circuit) : Stub("FastGetElement", 3, circuit) {} - ~FastGetElementStub() = default; - NO_MOVE_SEMANTIC(FastGetElementStub); - NO_COPY_SEMANTIC(FastGetElementStub); + explicit GetElementStub(Circuit *circuit) : Stub("GetElement", 3, circuit) {} + ~GetElementStub() = default; + NO_MOVE_SEMANTIC(GetElementStub); + NO_COPY_SEMANTIC(GetElementStub); void GenerateCircuit() override; }; -class FastFindOwnElement2Stub : public Stub { +class FindOwnElement2Stub : public Stub { public: // 6 : 6 means argument counts - explicit FastFindOwnElement2Stub(Circuit *circuit) : Stub("FastFindOwnElement2", 6, circuit) {} - ~FastFindOwnElement2Stub() = default; - NO_MOVE_SEMANTIC(FastFindOwnElement2Stub); - NO_COPY_SEMANTIC(FastFindOwnElement2Stub); + explicit FindOwnElement2Stub(Circuit *circuit) : Stub("FindOwnElement2", 6, circuit) {} + ~FindOwnElement2Stub() = default; + NO_MOVE_SEMANTIC(FindOwnElement2Stub); + NO_COPY_SEMANTIC(FindOwnElement2Stub); void GenerateCircuit() override; }; -class FastSetElementStub : public Stub { +class SetElementStub : public Stub { public: // 5 : 5 means argument counts - explicit FastSetElementStub(Circuit *circuit) : Stub("FastSetElement", 5, circuit) {} - ~FastSetElementStub() = default; - NO_MOVE_SEMANTIC(FastSetElementStub); - NO_COPY_SEMANTIC(FastSetElementStub); + explicit SetElementStub(Circuit *circuit) : Stub("SetElement", 5, circuit) {} + ~SetElementStub() = default; + NO_MOVE_SEMANTIC(SetElementStub); + NO_COPY_SEMANTIC(SetElementStub); void GenerateCircuit() override; }; -class FastGetPropertyByIndexStub : public Stub { +class GetPropertyByIndexStub : public Stub { public: // 3 : 3 means argument counts - explicit FastGetPropertyByIndexStub(Circuit *circuit) : Stub("FastGetPropertyByIndex", 3, circuit) {} - ~FastGetPropertyByIndexStub() = default; - NO_MOVE_SEMANTIC(FastGetPropertyByIndexStub); - NO_COPY_SEMANTIC(FastGetPropertyByIndexStub); + explicit GetPropertyByIndexStub(Circuit *circuit) : Stub("GetPropertyByIndex", 3, circuit) {} + ~GetPropertyByIndexStub() = default; + NO_MOVE_SEMANTIC(GetPropertyByIndexStub); + NO_COPY_SEMANTIC(GetPropertyByIndexStub); void GenerateCircuit() override; }; -class FastSetPropertyByIndexStub : public Stub { +class SetPropertyByIndexStub : public Stub { public: // 4 : 4 means argument counts - explicit FastSetPropertyByIndexStub(Circuit *circuit) : Stub("FastSetPropertyByIndex", 4, circuit) {} - ~FastSetPropertyByIndexStub() = default; - NO_MOVE_SEMANTIC(FastSetPropertyByIndexStub); - NO_COPY_SEMANTIC(FastSetPropertyByIndexStub); + explicit SetPropertyByIndexStub(Circuit *circuit) : Stub("SetPropertyByIndex", 4, circuit) {} + ~SetPropertyByIndexStub() = default; + NO_MOVE_SEMANTIC(SetPropertyByIndexStub); + NO_COPY_SEMANTIC(SetPropertyByIndexStub); void GenerateCircuit() override; }; -class FastGetPropertyByNameStub : public Stub { +class GetPropertyByNameStub : public Stub { public: // 3 : 3 means argument counts - explicit FastGetPropertyByNameStub(Circuit *circuit) : Stub("FastGetPropertyByName", 3, circuit) {} - ~FastGetPropertyByNameStub() = default; - NO_MOVE_SEMANTIC(FastGetPropertyByNameStub); - NO_COPY_SEMANTIC(FastGetPropertyByNameStub); + explicit GetPropertyByNameStub(Circuit *circuit) : Stub("GetPropertyByName", 3, circuit) {} + ~GetPropertyByNameStub() = default; + NO_MOVE_SEMANTIC(GetPropertyByNameStub); + NO_COPY_SEMANTIC(GetPropertyByNameStub); void GenerateCircuit() override; }; diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index f58bef3..d2139f5 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -43,10 +43,11 @@ void LLVMModuleAssembler::CopyAssembleCodeToModule(StubModule *module) module->SetStubEntry(i, stubEntry - codeBuff); } } + assembler_.Disassemble(); auto codeSize = assembler_.GetCodeSize(); - - MachineCode *code = reinterpret_cast(new char(sizeof(MachineCode) + codeSize)); + MachineCode *code = + reinterpret_cast(new uint64_t[(MachineCode::SIZE + codeSize) / sizeof(uint64_t) + 1]); code->SetInstructionSizeInBytes(nullptr, JSTaggedValue(codeSize), SKIP_BARRIER); code->SetData(reinterpret_cast(codeBuff), codeSize); module->SetCode(code); diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index f554630..63677de 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -38,7 +38,8 @@ private: class LLVMModuleAssembler { public: - explicit LLVMModuleAssembler(LLVMStubModule *module) : stubmodule_(module), assembler_(module->GetModule()) {} + explicit LLVMModuleAssembler(LLVMStubModule *module, const char* triple) + : stubmodule_(module), assembler_(module->GetModule(), triple) {} void AssembleModule(); void CopyAssembleCodeToModule(panda::ecmascript::StubModule *module); @@ -47,4 +48,4 @@ private: LLVMAssembler assembler_; }; } // namespace kungfu -#endif // ECMASCRIPT_COMPILER_LLVM_CODEGEN_H \ No newline at end of file +#endif // ECMASCRIPT_COMPILER_LLVM_CODEGEN_H diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 388aed1..cba0feb 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -15,8 +15,6 @@ #include "ecmascript/compiler/llvm_ir_builder.h" -#include - #include "ecmascript/compiler/circuit.h" #include "ecmascript/compiler/fast_stub.h" #include "ecmascript/compiler/gate.h" @@ -25,32 +23,16 @@ #include "ecmascript/js_thread.h" #include "llvm/IR/Instructions.h" #include "llvm/Support/Host.h" -#include "llvm_mcjit_engine.h" #include "securec.h" #include "utils/logger.h" namespace kungfu { std::unordered_map g_values = {}; -LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit) - : schedule_(schedule), circuit_(circuit) -{ - module_ = LLVMModuleCreateWithName("simple_module"); - LLVMSetTarget(module_, "x86_64-unknown-linux-gnu"); - builder_ = LLVMCreateBuilder(); - context_ = LLVMGetGlobalContext(); - LLVMTypeRef paramTys[] = { - LLVMInt32Type(), - }; - function_ = LLVMAddFunction(module_, "foo", LLVMFunctionType(LLVMInt32Type(), paramTys, 1, 0)); - bbIdMapBb_.clear(); -} - LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, LLVMModuleRef module, LLVMValueRef function) : schedule_(schedule), circuit_(circuit), module_(module), function_(function) { - LLVMSetTarget(module_, "x86_64-unknown-linux-gnu"); builder_ = LLVMCreateBuilder(); context_ = LLVMGetGlobalContext(); bbIdMapBb_.clear(); @@ -61,7 +43,6 @@ LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule : schedule_(schedule), circuit_(circuit), module_(module->GetModule()), function_(function), stubModule_(module) { - LLVMSetTarget(module_, "x86_64-unknown-linux-gnu"); builder_ = LLVMCreateBuilder(); context_ = LLVMGetGlobalContext(); bbIdMapBb_.clear(); @@ -740,8 +721,6 @@ void LLVMIRBuilder::VisitGoto(int block, int bbOut) void LLVMIRBuilder::VisitInt32Constant(AddrShift gate, int32_t value) const { LLVMValueRef llvmValue = LLVMConstInt(LLVMInt32Type(), value, 0); - LLVMTFBuilderBasicBlockImpl *impl = currentBb_->GetImpl(); - impl->values_[gate] = llvmValue; g_values[gate] = llvmValue; char *str = LLVMPrintValueToString(llvmValue); LOG_ECMA(INFO) << "VisitInt32Constant set gate:" << gate << " value:" << value; @@ -751,8 +730,6 @@ void LLVMIRBuilder::VisitInt32Constant(AddrShift gate, int32_t value) const void LLVMIRBuilder::VisitInt64Constant(AddrShift gate, int64_t value) const { LLVMValueRef llvmValue = LLVMConstInt(LLVMInt64Type(), value, 0); - LLVMTFBuilderBasicBlockImpl *impl = currentBb_->GetImpl(); - impl->values_[gate] = llvmValue; g_values[gate] = llvmValue; char *str = LLVMPrintValueToString(llvmValue); LOG_ECMA(INFO) << "VisitInt64Constant set gate:" << gate << " value:" << value; @@ -762,8 +739,6 @@ void LLVMIRBuilder::VisitInt64Constant(AddrShift gate, int64_t value) const void LLVMIRBuilder::VisitFloat64Constant(AddrShift gate, double value) const { LLVMValueRef llvmValue = LLVMConstReal(LLVMDoubleType(), value); - LLVMTFBuilderBasicBlockImpl *impl = currentBb_->GetImpl(); - impl->values_[gate] = llvmValue; g_values[gate] = llvmValue; char *str = LLVMPrintValueToString(llvmValue); LOG_ECMA(INFO) << "VisitFloat64Constant set gate:" << gate << " value:" << value; @@ -775,8 +750,6 @@ void LLVMIRBuilder::VisitParameter(AddrShift gate) const int argth = circuit_->LoadGatePtrConst(gate)->GetBitField(); LOG_ECMA(INFO) << " Parameter value" << argth; LLVMValueRef value = LLVMGetParam(function_, argth); - LLVMTFBuilderBasicBlockImpl *impl = currentBb_->GetImpl(); - impl->values_[gate] = value; g_values[gate] = value; LOG_ECMA(INFO) << "VisitParameter set gate:" << gate << " value:" << value; // NOTE: caller put args, otherwise crash @@ -791,8 +764,7 @@ void LLVMIRBuilder::VisitParameter(AddrShift gate) const void LLVMIRBuilder::VisitBranch(AddrShift gate, AddrShift cmp, int btrue, int bfalse) { LOG_ECMA(INFO) << "cmp gate:" << cmp; - LLVMTFBuilderBasicBlockImpl *impl = EnsureLLVMBBImpl(currentBb_); - if ((impl->values_.count(cmp) == 0) && (g_values.count(cmp) == 0)) { + if (g_values.count(cmp) == 0) { LOG_ECMA(ERROR) << "Branch condition gate is nullptr!"; return; } @@ -1130,12 +1102,10 @@ void LLVMIRBuilder::VisitCastDoubleToInt(AddrShift gate, AddrShift e1) const LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } -LLVMStubModule::LLVMStubModule(const char *name) +LLVMStubModule::LLVMStubModule(const char *name, const char *triple) { - module_ = LLVMModuleCreateWithName("fast_stubs"); -#ifdef PANDA_TARGET_AMD64 - LLVMSetTarget(module_, "x86_64-unknown-linux-gnu"); -#endif + module_ = LLVMModuleCreateWithName(name); + LLVMSetTarget(module_, triple); } void LLVMStubModule::Initialize() diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index cd703fd..ed35e2d 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -96,7 +96,6 @@ struct NotMergedPhiDesc { struct LLVMTFBuilderBasicBlockImpl { LLVMBasicBlockRef llvm_bb_ = nullptr; LLVMBasicBlockRef continuation = nullptr; - std::unordered_map values_ = {}; bool started = false; bool ended = false; std::vector not_merged_phis; @@ -104,7 +103,7 @@ struct LLVMTFBuilderBasicBlockImpl { class LLVMStubModule { public: - explicit LLVMStubModule(const char *name); + explicit LLVMStubModule(const char *name, const char *triple); ~LLVMStubModule() = default; void Initialize(); @@ -140,7 +139,6 @@ private: class LLVMIRBuilder { public: - explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit); explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, LLVMModuleRef module, LLVMValueRef function); explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, diff --git a/ecmascript/compiler/llvm_mcjit_engine.cpp b/ecmascript/compiler/llvm_mcjit_engine.cpp index 7d00ed8..bb3e4ec 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.cpp +++ b/ecmascript/compiler/llvm_mcjit_engine.cpp @@ -77,7 +77,6 @@ static LLVMBool RoundTripFinalizeMemory(void *object, [[maybe_unused]] char **er static void RoundTripDestroy(void *object) { std::cout << "RoundTripDestroy object " << object << " - " << std::endl; - delete static_cast(object); } void LLVMAssembler::UseRoundTripSectionMemoryManager() @@ -114,8 +113,8 @@ void LLVMAssembler::BuildAndRunPasses() const std::cout << "BuildAndRunPasses + " << std::endl; } -LLVMAssembler::LLVMAssembler(LLVMModuleRef module): module_(module), engine_(nullptr), - hostTriple_(""), error_(nullptr) +LLVMAssembler::LLVMAssembler(LLVMModuleRef module, const char* triple): module_(module), engine_(nullptr), + hostTriple_(triple), error_(nullptr) { Initialize(); InitMember(); @@ -140,15 +139,31 @@ void LLVMAssembler::Run() void LLVMAssembler::Initialize() { -#if defined(PANDA_TARGET_AMD64) - LLVMInitializeX86TargetInfo(); - LLVMInitializeX86TargetMC(); - LLVMInitializeX86Disassembler(); - /* this method must be called, ohterwise "Target does not support MC emission" */ - LLVMInitializeX86AsmPrinter(); - LLVMInitializeX86AsmParser(); - LLVMInitializeX86Target(); -#endif + if (hostTriple_.compare(AMD64_TRIPLE) == 0) { + LLVMInitializeX86TargetInfo(); + LLVMInitializeX86TargetMC(); + LLVMInitializeX86Disassembler(); + /* this method must be called, ohterwise "Target does not support MC emission" */ + LLVMInitializeX86AsmPrinter(); + LLVMInitializeX86AsmParser(); + LLVMInitializeX86Target(); + } else if (hostTriple_.compare(ARM64_TRIPLE) == 0) { + LLVMInitializeAArch64TargetInfo(); + LLVMInitializeAArch64TargetMC(); + LLVMInitializeAArch64Disassembler(); + LLVMInitializeAArch64AsmPrinter(); + LLVMInitializeAArch64AsmParser(); + LLVMInitializeAArch64Target(); + } else if (hostTriple_.compare(ARM32_TRIPLE) == 0) { + LLVMInitializeARMTargetInfo(); + LLVMInitializeARMTargetMC(); + LLVMInitializeARMDisassembler(); + LLVMInitializeARMAsmPrinter(); + LLVMInitializeARMAsmParser(); + LLVMInitializeARMTarget(); + } else { + UNREACHABLE(); + } llvm::linkAllBuiltinGCs(); LLVMInitializeMCJITCompilerOptions(&options_, sizeof(options_)); options_.OptLevel = 2; // opt level 2 @@ -166,7 +181,7 @@ static const char *SymbolLookupCallback([[maybe_unused]] void *disInfo, [[maybe_ void LLVMAssembler::Disassemble(std::map addr2name) const { - LLVMDisasmContextRef dcr = LLVMCreateDisasm("x86_64-unknown-linux-gnu", nullptr, 0, nullptr, SymbolLookupCallback); + LLVMDisasmContextRef dcr = LLVMCreateDisasm(hostTriple_.c_str(), nullptr, 0, nullptr, SymbolLookupCallback); std::cout << "========================================================================" << std::endl; for (auto it : codeInfo_.GetCodeInfo()) { uint8_t *byteSp; diff --git a/ecmascript/compiler/llvm_mcjit_engine.h b/ecmascript/compiler/llvm_mcjit_engine.h index 3eaafb2..1e0cb6e 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.h +++ b/ecmascript/compiler/llvm_mcjit_engine.h @@ -38,35 +38,35 @@ struct CodeInfo { using ByteBuffer = std::vector; using BufferList = std::list; using StringList = std::list; - CodeInfo() : machineCode(nullptr), codeBufferPos(0), stackMapsSection_(nullptr) + CodeInfo() : machineCode_(nullptr), codeBufferPos_(0), stackMapsSection_(nullptr) { Reset(); static constexpr int prot = PROT_READ | PROT_WRITE | PROT_EXEC; // NOLINT(hicpp-signed-bitwise) static constexpr int flags = MAP_ANONYMOUS | MAP_SHARED; // NOLINT(hicpp-signed-bitwise) - machineCode = static_cast(mmap(nullptr, MAX_MACHINE_CODE_SIZE, prot, flags, -1, 0)); - std::cerr << std::hex << "machineCode : " << reinterpret_cast(machineCode) << std::endl; + machineCode_ = static_cast(mmap(nullptr, MAX_MACHINE_CODE_SIZE, prot, flags, -1, 0)); } ~CodeInfo() { Reset(); - munmap(machineCode, MAX_MACHINE_CODE_SIZE); + munmap(machineCode_, MAX_MACHINE_CODE_SIZE); + machineCode_ = nullptr; } uint8_t *AllocaCodeSection(uintptr_t size, const char *sectionName) { uint8_t *addr = nullptr; - if (codeBufferPos + size > MAX_MACHINE_CODE_SIZE) { - std::cerr << std::hex << "AllocaCodeSection failed alloc codeBufferPos:" << codeBufferPos + if (codeBufferPos_ + size > MAX_MACHINE_CODE_SIZE) { + std::cerr << std::hex << "AllocaCodeSection failed alloc codeBufferPos_:" << codeBufferPos_ << " size:" << size << " larger MAX_MACHINE_CODE_SIZE:" << MAX_MACHINE_CODE_SIZE << std::endl; return nullptr; } std::cout << "AllocaCodeSection size:" << size << std::endl; - std::vector codeBuffer(machineCode[codeBufferPos], size); + std::vector codeBuffer(machineCode_[codeBufferPos_], size); std::cout << " codeBuffer size: " << codeBuffer.size() << std::endl; codeSectionNames_.push_back(sectionName); - addr = machineCode + codeBufferPos; + addr = machineCode_ + codeBufferPos_; std::cout << "AllocaCodeSection addr:" << std::hex << reinterpret_cast(addr) << std::endl; codeInfo_.push_back({addr, size}); - codeBufferPos += size; + codeBufferPos_ += size; return addr; } @@ -91,7 +91,7 @@ struct CodeInfo { dataSectionList_.clear(); dataSectionNames_.clear(); codeSectionNames_.clear(); - codeBufferPos = 0; + codeBufferPos_ = 0; } uint8_t *GetStackMapsSection() const @@ -105,21 +105,21 @@ struct CodeInfo { int GetCodeSize() const { - return codeBufferPos; + return codeBufferPos_; } uint8_t *GetCodeBuff() const { - return machineCode; + return machineCode_; } private: BufferList dataSectionList_ {}; StringList dataSectionNames_ {}; StringList codeSectionNames_ {}; - uint8_t *machineCode; + uint8_t *machineCode_; const size_t MAX_MACHINE_CODE_SIZE = (1 << 20); // 1M - int codeBufferPos = 0; + int codeBufferPos_ = 0; /* for asssembler */ std::vector> codeInfo_ {}; /* stack map */ @@ -127,7 +127,7 @@ private: }; class LLVMAssembler { public: - explicit LLVMAssembler(LLVMModuleRef module); + explicit LLVMAssembler(LLVMModuleRef module, const char* triple); virtual ~LLVMAssembler(); void Run(); const LLVMExecutionEngineRef &GetEngine() @@ -149,6 +149,10 @@ public: return codeInfo_.GetCodeBuff(); } + const char *AMD64_TRIPLE = "x86_64-unknown-linux-gnu"; + const char *ARM64_TRIPLE = "aarch64-unknown-linux-gnu"; + const char *ARM32_TRIPLE = "arm-unknown-linux-gnu"; + private: void UseRoundTripSectionMemoryManager(); bool BuildMCJITEngine(); diff --git a/ecmascript/compiler/options.h.erb b/ecmascript/compiler/options.h.erb new file mode 100644 index 0000000..55988ac --- /dev/null +++ b/ecmascript/compiler/options.h.erb @@ -0,0 +1,118 @@ +/* + * 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +#ifndef PANDA_<%= Common::module.name.upcase %>_OPTIONS_GEN_H_ +#define PANDA_<%= Common::module.name.upcase %>_OPTIONS_GEN_H_ + +#include "utils/pandargs.h" + +#include +#include +#include +#include + +namespace <%= Common::module.namespace %> { + +class <%= Common::module.name %>_Options { +public: + class Error { + public: + explicit Error(std::string msg) : msg_(std::move(msg)) {} + + std::string GetMessage() { + return msg_; + } + private: + std::string msg_; + }; + + explicit <%= Common::module.name %>_Options(const std::string &exe_path) : exe_dir_(GetExeDir(exe_path)) {} + + void AddOptions(PandArgParser *parser) { +% Common::options.each do |op| + parser->Add(&<%= op.field_name %>); +% end + } + +% Common::options.each do |op| + <%= op.type %> <%= op.getter_name %>() const { + return <%= op.field_name %>.GetValue(); + } + + void <%= op.setter_name %>(<%= op.type %> value) { + <%= op.field_name %>.SetValue(<%= op.type == 'std::string' || op.type == 'arg_list_t' ? 'std::move(value)' : 'value' %>); + } + + bool WasSet<%= op.name.split(Regexp.union(['-','.'])).map(&:capitalize).join %>() const { + return <%= op.field_name %>.WasSet(); + } + +% end +// NOLINTNEXTLINE(readability-function-size) + std::optional Validate() const { +% Common::options.each do |op| +% next unless defined? op.possible_values +% is_string = op.type == 'std::string' || op.type == 'arg_list_t' +% possible_values = op.possible_values.map { |e| is_string ? Common::to_raw(e) : e }.join(', ') + { + std::unordered_set<<%= is_string ? "std::string" : op.type %>> possible_values{<%= possible_values %>}; +% if op.type != 'arg_list_t' + std::vector<<%= op.type %>> values{<%= op.field_name %>.GetValue()}; +% else + const auto &values = <%= op.field_name %>.GetValue(); +% end + for (const auto &value : values) { + if (possible_values.find(value) == possible_values.cend()) { + return Error("argument --<%= op.name %>: invalid value: '" + <%= is_string ? "value" : "std::to_string(value)" %> + \ + R"('. Possible values: <%= op.possible_values %>)"); + } + } + } +% end + return {}; + } + +private: + static std::string GetExeDir(const std::string &exe_path) { + auto pos = exe_path.find_last_of('/'); + return exe_path.substr(0, pos); + } + +% Common::options.each do |op| +% next unless op.need_default_constant + static constexpr <%= op.type %> <%= op.default_constant_name %> = <%= op.default %>; + +% end + std::string exe_dir_; +% Common::options.each do |op| +% if defined? op.delimiter + PandArg<<%= op.type %>> <%= op.field_name %>{"<%= op.name %>", <%= op.default_value %>, <%= op.full_description %>, "<%= op.delimiter %>"}; +% elsif defined? op.range +% min, max = op.range.match('(\d+)\D*(\d+)').captures; +% if op.default.to_i > max.to_i || op.default.to_i < min.to_i +% abort "FAILED: Default value of argument " + op.name + " has out of range default parameter" +% end + PandArg<<%= op.type %>> <%= op.field_name %>{"<%= op.name %>", <%= op.default_value %>, <%= op.full_description %>, <%= min.to_i %>, <%= max.to_i %>}; +% else + PandArg<<%= op.type %>> <%= op.field_name %>{"<%= op.name %>", <%= op.default_value %>, <%= op.full_description %>}; +% end +% end +}; + +} // namespace <%= Common::module.namespace %> + +#endif // PANDA_<%= Common::module.name.upcase %>_OPTIONS_GEN_H_ diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 4f9a0ee..d5e801f 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -378,7 +378,7 @@ AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elem { auto env = GetEnvironment(); Label subentry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &subentry); + env->PushCurrentLabel(&subentry); DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1)); Label exit(env); AddrShift capcityoffset = @@ -427,14 +427,16 @@ AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elem count = Int32Add(*count, GetInteger32Constant(1)); LoopEnd(&loopHead); Bind(&exit); - return *result; + auto ret = *result; + env->PopCurrentLabel(); + return ret; } AddrShift Stub::IsMatchInNumberDictionary(AddrShift key, AddrShift other) { auto env = GetEnvironment(); Label entry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + env->PushCurrentLabel(&entry); Label exit(env); DEFVARIABLE(result, BOOL_TYPE, FalseConstant()); Label isHole(env); @@ -464,14 +466,16 @@ AddrShift Stub::IsMatchInNumberDictionary(AddrShift key, AddrShift other) Bind(&keyNotInt); Jump(&exit); Bind(&exit); - return *result; + auto ret = *result; + env->PopCurrentLabel(); + return ret; } AddrShift Stub::GetKeyFromNumberDictionary(AddrShift elements, AddrShift entry) { auto env = GetEnvironment(); Label subentry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &subentry); + env->PushCurrentLabel(&subentry); Label exit(env); DEFVARIABLE(result, TAGGED_TYPE, GetUndefinedConstant()); Label ltZero(env); @@ -493,7 +497,9 @@ AddrShift Stub::GetKeyFromNumberDictionary(AddrShift elements, AddrShift entry) result = GetValueFromTaggedArray(elements, arrayIndex); Jump(&exit); Bind(&exit); - return *result; + auto ret = *result; + env->PopCurrentLabel(); + return ret; } // int TaggedHashTable::FindEntry(const JSTaggedValue &key) in tagged_hash_table-inl.h @@ -501,7 +507,7 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements { auto env = GetEnvironment(); Label funcEntry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &funcEntry); + env->PushCurrentLabel(&funcEntry); Label exit(env); DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1)); AddrShift capcityoffset = @@ -594,14 +600,16 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements } } Bind(&exit); - return *result; + auto ret = *result; + env->PopCurrentLabel(); + return ret; } AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift attr) { auto env = GetEnvironment(); Label entry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + env->PushCurrentLabel(&entry); Label exit(env); DEFVARIABLE(result, TAGGED_TYPE, GetUndefinedConstant()); Label inlinedProp(env); @@ -631,7 +639,9 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a } } Bind(&exit); - return *result; + auto ret = *result; + env->PopCurrentLabel(); + return ret; } void Stub::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val) @@ -646,7 +656,7 @@ AddrShift Stub::TaggedToRepresentation(AddrShift value) { auto env = GetEnvironment(); Label entry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + env->PushCurrentLabel(&entry); Label exit(env); DEFVARIABLE(resultRep, INT64_TYPE, GetWord64Constant(static_cast(panda::ecmascript::Representation::OBJECT))); @@ -676,14 +686,16 @@ AddrShift Stub::TaggedToRepresentation(AddrShift value) } } Bind(&exit); - return *resultRep; + auto ret = *resultRep; + env->PopCurrentLabel(); + return ret; } AddrShift Stub::UpdateRepresention(AddrShift oldRep, AddrShift value) { auto env = GetEnvironment(); Label entry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + env->PushCurrentLabel(&entry); Label exit(env); DEFVARIABLE(resultRep, INT64_TYPE, oldRep); Label isMixedRep(env); @@ -770,7 +782,9 @@ AddrShift Stub::UpdateRepresention(AddrShift oldRep, AddrShift value) } } Bind(&exit); - return *resultRep; + auto ret = *resultRep; + env->PopCurrentLabel(); + return ret; } void Stub::UpdateAndStoreRepresention(AddrShift hclass, AddrShift value) diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 1260e34..186759a 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -242,19 +242,19 @@ public: Label GetLabelFromSelector(AddrShift sel) { - LabelImpl *rawlabel = phi_to_labels[sel]; + LabelImpl *rawlabel = phi_to_labels_[sel]; return Label(rawlabel); } void AddSelectorToLabel(AddrShift sel, Label label) { - phi_to_labels[sel] = label.GetRawLabel(); + phi_to_labels_[sel] = label.GetRawLabel(); } LabelImpl *NewLabel(Environment *env, AddrShift control = -1) { auto impl = new LabelImpl(env, control); - rawlabels_.push_back(impl); + rawlabels_.emplace_back(impl); return impl; } @@ -286,7 +286,7 @@ public: Label *currentLabel_ {nullptr}; Circuit *circuit_; CircuitBuilder builder_; - std::unordered_map phi_to_labels; + std::unordered_map phi_to_labels_; std::vector arguments_; Label entry_; std::vector rawlabels_; @@ -1346,6 +1346,11 @@ public: return nextVariableId_++; } + std::string GetMethodName() const + { + return methodName_; + } + private: Environment env_; std::string methodName_; diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index 530c676..d1b3fff 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -14,10 +14,14 @@ */ #include "stub_aot_compiler.h" + #include #include #include #include "fast_stub.h" +#include "generated/stub_aot_options_gen.h" +#include "libpandabase/utils/pandargs.h" +#include "libpandabase/utils/span.h" #include "llvm_codegen.h" #include "scheduler.h" #include "stub.h" @@ -99,15 +103,17 @@ public: } }; -void StubAotCompiler::BuildStubModule(panda::ecmascript::StubModule *module) +void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascript::StubModule *module, + const std::string &filename) { - LLVMStubModule stubModule("fast_stubs"); + LLVMStubModule stubModule("fast_stubs", triple); stubModule.Initialize(); for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { - auto Stub = stubs_[i]; - if (Stub != nullptr) { - Stub->GenerateCircuit(); - auto circuit = Stub->GetEnvironment()->GetCircuit(); + auto stub = stubs_[i]; + if (stub != nullptr) { + std::cout << "Stub Name: " << stub->GetMethodName() << std::endl; + stub->GenerateCircuit(); + auto circuit = stub->GetEnvironment()->GetCircuit(); PassPayLoad data(circuit, &stubModule); PassRunner pipeline(&data); pipeline.RunPass(); @@ -116,68 +122,63 @@ void StubAotCompiler::BuildStubModule(panda::ecmascript::StubModule *module) } } - LLVMModuleAssembler assembler(&stubModule); + LLVMModuleAssembler assembler(&stubModule, triple); assembler.AssembleModule(); assembler.CopyAssembleCodeToModule(module); + + module->Save(filename); } } // namespace kungfu -int main(int argc, char *argv[]) +#define SET_STUB_TO_MODULE(module, name) \ + kungfu::Circuit name##Circuit; \ + kungfu::name##Stub name##Stub(& name##Circuit); \ + module.SetStub(FAST_STUB_ID(name), & name##Stub); + + +#define SET_ALL_STUB_TO_MODEULE(module) \ + SET_STUB_TO_MODULE(module, FastAdd) \ + SET_STUB_TO_MODULE(module, FastSub) \ + SET_STUB_TO_MODULE(module, FastMul) \ + SET_STUB_TO_MODULE(module, FastDiv) \ + SET_STUB_TO_MODULE(module, FindOwnElement) \ + SET_STUB_TO_MODULE(module, GetElement) \ + SET_STUB_TO_MODULE(module, FindOwnElement2) \ + SET_STUB_TO_MODULE(module, SetElement) \ + SET_STUB_TO_MODULE(module, GetPropertyByIndex) \ + SET_STUB_TO_MODULE(module, SetPropertyByIndex) \ + SET_STUB_TO_MODULE(module, GetPropertyByName) + +int main(const int argc, const char **argv) { - int opt; - // 3 means ark_stub_opt -f stub.m - if (argc != 3) { - std::cerr << "Usage: " << argv[0] << " -f stub.m" << std::endl; - return -1; - } - std::string moduleFilename; - while ((opt = getopt(argc, argv, "f:")) != -1) { - switch (opt) { - case 'f': - moduleFilename += optarg; - break; - default: /* '?' */ - std::cerr << "Usage: " << argv[0] << " -f stub.m" << std::endl; - return -1; - } + panda::Span sp(argv, argc); + panda::Stub_Aot_Options stubOptions(sp[0]); + panda::PandArg help("help", false, "Print this message and exit"); + panda::PandArg options("options", false, "Print compiler options"); + panda::PandArgParser paParser; + + stubOptions.AddOptions(&paParser); + paParser.Add(&help); + paParser.Add(&options); + + if (!paParser.Parse(argc, argv) || help.GetValue()) { + std::cerr << paParser.GetErrorString() << std::endl; + std::cerr << "Usage: " << "ark_stub_opt" << " [OPTIONS]" << std::endl; + std::cerr << std::endl; + std::cerr << "optional arguments:" << std::endl; + std::cerr << paParser.GetHelpString() << std::endl; + return 1; } + std::string moduleFilename = stubOptions.GetStubOutputFile(); + std::string tripes = stubOptions.GetTargetTriple(); + kungfu::StubAotCompiler mouldeBuilder; + SET_ALL_STUB_TO_MODEULE(mouldeBuilder); + panda::ecmascript::StubModule stubModule; - /* Set Stub into module */ - kungfu::Circuit fastaddCircuit; - kungfu::FastAddStub fastaddStub(&fastaddCircuit); - mouldeBuilder.SetStub(FAST_STUB_ID(FastAdd), &fastaddStub); - - kungfu::Circuit fastsubCircuit; - kungfu::FastSubStub fastsubStub(&fastsubCircuit); - mouldeBuilder.SetStub(FAST_STUB_ID(FastSub), &fastsubStub); - - kungfu::Circuit fastmulCircuit; - kungfu::FastMulStub fastmulStub(&fastmulCircuit); - mouldeBuilder.SetStub(FAST_STUB_ID(FastMul), &fastmulStub); - - kungfu::Circuit fastdivCircuit; - kungfu::FastDivStub fastdivStub(&fastdivCircuit); - mouldeBuilder.SetStub(FAST_STUB_ID(FastDiv), &fastdivStub); - - kungfu::Circuit fastFindOwnElementCircuit; - kungfu::FastFindOwnElementStub fastFindOwnElementStub(&fastFindOwnElementCircuit); - mouldeBuilder.SetStub(FAST_STUB_ID(FindOwnElement), &fastFindOwnElementStub); - - kungfu::Circuit fastGetElementCircuit; - kungfu::FastGetElementStub fastGetElementStub(&fastGetElementCircuit); - mouldeBuilder.SetStub(FAST_STUB_ID(GetElement), &fastGetElementStub); - - kungfu::Circuit fastFindOwnElement2Circuit; - kungfu::FastFindOwnElement2Stub fastFindOwnElement2Stub(&fastFindOwnElement2Circuit); - mouldeBuilder.SetStub(FAST_STUB_ID(FindOwnElement2), &fastFindOwnElement2Stub); - - kungfu::Circuit fastSetElementCircuit; - kungfu::FastSetElementStub fastSetElementStub(&fastSetElementCircuit); - mouldeBuilder.SetStub(FAST_STUB_ID(SetElement), &fastSetElementStub); - - mouldeBuilder.BuildStubModule(&stubModule); - stubModule.Save(moduleFilename); - exit(0); + mouldeBuilder.BuildStubModuleAndSave(tripes.c_str(), &stubModule, moduleFilename); + + std::cout << "BuildStubModuleAndSave success" << std::endl; + return 0; } \ No newline at end of file diff --git a/ecmascript/compiler/stub_aot_compiler.h b/ecmascript/compiler/stub_aot_compiler.h index 736ba00..e3e2aad 100644 --- a/ecmascript/compiler/stub_aot_compiler.h +++ b/ecmascript/compiler/stub_aot_compiler.h @@ -30,9 +30,15 @@ public: for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { stubs_[i] = nullptr; } - }; - ~StubAotCompiler() = default; - void BuildStubModule(panda::ecmascript::StubModule *module); + } + ~StubAotCompiler() + { + for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { + stubs_[i] = nullptr; + } + } + void BuildStubModuleAndSave(const char *triple, panda::ecmascript::StubModule *module, + const std::string &filename); void SetStub(int index, Stub *optimizer) { stubs_[index] = optimizer; diff --git a/ecmascript/compiler/stub_aot_options.yaml b/ecmascript/compiler/stub_aot_options.yaml new file mode 100644 index 0000000..4d58964 --- /dev/null +++ b/ecmascript/compiler/stub_aot_options.yaml @@ -0,0 +1,31 @@ +# 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. + +module: + name: Stub_Aot + namespace: panda + +options: +- name: stub-output-file + type: std::string + default: stub.m + description: stub aot compiler output file name + +- name: target-triple + type: std::string + default: x86_64-unknown-linux-gnu + possible_values: + - x86_64-unknown-linux-gnu + - arm-unknown-linux-gnu + - aarch64-unknown-linux-gnu + description: stub aot compiler target triple \ No newline at end of file diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index c684a94..3101ab9 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -63,7 +63,7 @@ public: PandaVM *instance {nullptr}; EcmaHandleScope *scope {nullptr}; JSThread *thread {nullptr}; - LLVMStubModule stubModule{"fast_stub"}; + LLVMStubModule stubModule {"fast_stub", "x86_64-unknown-linux-gnu"}; }; HWTEST_F_L0(StubTest, FastLoadElement) @@ -94,7 +94,7 @@ HWTEST_F_L0(StubTest, FastLoadElement) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); /* exec function */ @@ -166,7 +166,7 @@ HWTEST_F_L0(StubTest, PhiGateTest) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); /* exec function */ @@ -262,7 +262,7 @@ HWTEST_F_L0(StubTest, LoopTest) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); @@ -332,7 +332,7 @@ HWTEST_F_L0(StubTest, LoopTest1) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); /* exec function */ @@ -368,7 +368,7 @@ HWTEST_F_L0(StubTest, FastAddTest) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); /* exec function */ @@ -409,7 +409,7 @@ HWTEST_F_L0(StubTest, FastSubTest) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); /* exec function */ @@ -445,7 +445,7 @@ HWTEST_F_L0(StubTest, FastMulTest) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); @@ -502,7 +502,7 @@ HWTEST_F_L0(StubTest, FastDivTest) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); @@ -535,12 +535,12 @@ HWTEST_F_L0(StubTest, FastDivTest) EXPECT_EQ(res3, expectedG3); } -HWTEST_F_L0(StubTest, FastFindOwnElementStub) +HWTEST_F_L0(StubTest, FindOwnElementStub) { auto module = stubModule.GetModule(); LLVMValueRef findFunction = LLVMGetNamedFunction(module, "FindOwnElement"); Circuit netOfGates; - FastFindOwnElementStub optimizer(&netOfGates); + FindOwnElementStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); @@ -553,16 +553,16 @@ HWTEST_F_L0(StubTest, FastFindOwnElementStub) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); } -HWTEST_F_L0(StubTest, FastGetElementStub) +HWTEST_F_L0(StubTest, GetElementStub) { auto module = stubModule.GetModule(); LLVMValueRef findFunction = LLVMGetNamedFunction(module, "FindOwnElement"); Circuit netOfGates; - FastFindOwnElementStub findOptimizer(&netOfGates); + FindOwnElementStub findOptimizer(&netOfGates); findOptimizer.GenerateCircuit(); auto cfg = Scheduler::Run(&netOfGates); for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { @@ -575,7 +575,7 @@ HWTEST_F_L0(StubTest, FastGetElementStub) LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction); llvmBuilder.Build(); Circuit getNetOfGates; - FastGetElementStub getOptimizer(&getNetOfGates); + GetElementStub getOptimizer(&getNetOfGates); getOptimizer.GenerateCircuit(); getNetOfGates.PrintAllGates(); auto getCfg = Scheduler::Run(&getNetOfGates); @@ -587,17 +587,17 @@ HWTEST_F_L0(StubTest, FastGetElementStub) } } llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); } -HWTEST_F_L0(StubTest, FastFindOwnElement2Stub) +HWTEST_F_L0(StubTest, FindOwnElement2Stub) { - std::cout << " ------------------------FastFindOwnElement2Stub ---------------------" << std::endl; + std::cout << " ------------------------FindOwnElement2Stub ---------------------" << std::endl; auto module = stubModule.GetModule(); LLVMValueRef function = LLVMGetNamedFunction(module, "FindOwnElement2"); Circuit netOfGates; - FastFindOwnElement2Stub optimizer(&netOfGates); + FindOwnElement2Stub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); @@ -610,7 +610,7 @@ HWTEST_F_L0(StubTest, FastFindOwnElement2Stub) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); auto *findOwnElement2Ptr = reinterpret_cast( @@ -1166,12 +1166,12 @@ HWTEST_F_L0(StubTest, FastGetPropertyByIndexStub) EXPECT_EQ(resVal.GetNumber(), y); } -HWTEST_F_L0(StubTest, FastSetPropertyByIndexStub) +HWTEST_F_L0(StubTest, SetPropertyByIndexStub) { auto module = stubModule.GetModule(); LLVMValueRef function = LLVMGetNamedFunction(module, "SetPropertyByIndex"); Circuit netOfGates; - FastSetPropertyByIndexStub optimizer(&netOfGates); + SetPropertyByIndexStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); bool result = Verifier::Run(&netOfGates); @@ -1186,7 +1186,7 @@ HWTEST_F_L0(StubTest, FastSetPropertyByIndexStub) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); auto *setpropertyByIndex = reinterpret_cast( @@ -1206,12 +1206,12 @@ HWTEST_F_L0(StubTest, FastSetPropertyByIndexStub) } } -HWTEST_F_L0(StubTest, FastGetPropertyByNameStub) +HWTEST_F_L0(StubTest, GetPropertyByNameStub) { auto module = stubModule.GetModule(); LLVMValueRef function = LLVMGetNamedFunction(module, "GetPropertyByName"); Circuit netOfGates; - FastGetPropertyByNameStub optimizer(&netOfGates); + GetPropertyByNameStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); bool result = Verifier::Run(&netOfGates); @@ -1226,7 +1226,7 @@ HWTEST_F_L0(StubTest, FastGetPropertyByNameStub) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); auto *getPropertyByNamePtr = reinterpret_cast( @@ -1270,7 +1270,7 @@ HWTEST_F_L0(StubTest, FastModTest) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); - LLVMAssembler assembler(module); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); diff --git a/ecmascript/mem/machine_code.h b/ecmascript/mem/machine_code.h index 6cfca75..90221bf 100644 --- a/ecmascript/mem/machine_code.h +++ b/ecmascript/mem/machine_code.h @@ -36,10 +36,11 @@ public: static constexpr size_t INS_SIZE_OFFSET = TaggedObjectSize(); ACCESSORS(InstructionSizeInBytes, INS_SIZE_OFFSET, DATA_OFFSET); + static constexpr size_t SIZE = DATA_OFFSET; uintptr_t GetDataOffsetAddress(void) { - return reinterpret_cast(this + DATA_OFFSET); + return reinterpret_cast(this) + DATA_OFFSET; } void SetData(const uint8_t *codeData, size_t codeLength) diff --git a/js_runtime_config.gni b/js_runtime_config.gni index ea4700b..bf6c093 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -14,7 +14,56 @@ ark_root = "//ark/runtime_core" js_root = "//ark/js_runtime" compile_llvm_online = false +run_with_asan = false +asan_lib_path = "/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux" # For OpenHarmony build, always link with the static lib: sdk_libc_secshared_dep = "//utils/native/base:utilsecurec" sdk_libc_secshared_config = "//utils/native/base:utils_config" + +# Generate file for a template and YAML data provided. +# +# Mandatory arguments: +# data_file -- YAML data full name +# template_file -- template full name +# output_file -- output file full name +# requires -- a list of scripts that provide data-querying API for templates +# extra_dependencies -- a list of files that should be considered as dependencies, must be lable +template("ark_gen_file") { + assert(defined(invoker.data_file), "data_file is required!") + assert(defined(invoker.template_file), "template_file is required!") + assert(defined(invoker.output_file), "output_file is required!") + + requires = "" + if (defined(invoker.requires)) { + requires = string_join(",", rebase_path(invoker.requires, root_build_dir)) + } + + extra_dependencies = [] + if (defined(invoker.extra_dependencies)) { + extra_dependencies += invoker.extra_dependencies + } + + action("$target_name") { + script = "$ark_root/isa/gen.rb" + + # rerun action when data file or template file update + inputs = [ + invoker.template_file, + invoker.data_file, + ] + outputs = [ invoker.output_file ] + args = [ + "--template", + rebase_path(invoker.template_file, root_build_dir), + "--data", + rebase_path(invoker.data_file, root_build_dir), + "--require", + requires, + "--output", + rebase_path(outputs[0]), + ] + + deps = extra_dependencies + } +} diff --git a/test/test_helper.gni b/test/test_helper.gni index 4cc7e23..6fda215 100644 --- a/test/test_helper.gni +++ b/test/test_helper.gni @@ -38,6 +38,7 @@ template("host_unittest_action") { _host_test_target_ = ":${_target_name_}(${host_toolchain})" _root_out_dir_ = get_label_info(_host_test_target_, "root_out_dir") + deps = [ _host_test_target_ ] script = "//ark/js_runtime/test/run_ark_executable.py" -- Gitee From 85698a20dc2942b0d9f47e9cc9f934fff4421e13 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Tue, 12 Oct 2021 15:41:13 +0800 Subject: [PATCH 016/115] compiler fix Signed-off-by: surpassgoodchao --- ecmascript/interpreter/frame_handler.cpp | 8 ++++---- ecmascript/interpreter/frame_handler.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index dd2522d..a362901 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -196,7 +196,7 @@ void InterpretedFrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const { - JSTaggedType *current = fp_; + uintptr_t *current = fp_; if (current != nullptr) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) std::vector slotAddrs; @@ -216,7 +216,7 @@ void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisito void OptimizedEntryFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const { - JSTaggedType *current = fp_; + uintptr_t *current = fp_; if (current != nullptr) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) std::vector slotAddrs; @@ -248,14 +248,14 @@ void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) c OptimizedFrameStateBase *state = reinterpret_cast( reinterpret_cast(current) - MEMBER_OFFSET(OptimizedFrameStateBase, prev)); - OptimizedFrameHandler(current).Iterate(v0, v1); + OptimizedFrameHandler(reinterpret_cast(current)).Iterate(v0, v1); current = reinterpret_cast(state->prev); } else { ASSERT(type == FrameType::OPTIMIZED_ENTRY_FRAME); OptimizedEntryFrameState *state = reinterpret_cast( reinterpret_cast(current) - MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); - OptimizedEntryFrameHandler(current).Iterate(v0, v1); + OptimizedEntryFrameHandler(reinterpret_cast(current)).Iterate(v0, v1); current = reinterpret_cast(state->threadFp); } } diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index 9c8a6b7..ae44d2f 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -71,22 +71,22 @@ private: class OptimizedFrameHandler { public: - explicit OptimizedFrameHandler(JSTaggedType *fp) : fp_(fp) {} + explicit OptimizedFrameHandler(uintptr_t *fp) : fp_(fp) {} explicit OptimizedFrameHandler(const JSThread *thread); ~OptimizedFrameHandler() = default; void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; private: - JSTaggedType *fp_ {nullptr}; + uintptr_t *fp_ {nullptr}; }; class OptimizedEntryFrameHandler { public: - explicit OptimizedEntryFrameHandler(JSTaggedType *fp) : fp_(fp) {} + explicit OptimizedEntryFrameHandler(uintptr_t *fp) : fp_(fp) {} explicit OptimizedEntryFrameHandler(const JSThread *thread); ~OptimizedEntryFrameHandler() = default; void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; private: - JSTaggedType *fp_ {nullptr}; + uintptr_t *fp_ {nullptr}; }; class FrameIterator { -- Gitee From 40983361586f367dcdbd4ee4286902bb2a057c11 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Tue, 12 Oct 2021 15:46:23 +0800 Subject: [PATCH 017/115] fix generated header file dependence Signed-off-by: wengchangcheng --- BUILD.gn | 2 ++ ecmascript/compiler/BUILD.gn | 1 + ecmascript/tooling/BUILD.gn | 6 ++---- js_runtime_config.gni | 8 ++++++++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 080f62c..3f459bd 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -127,6 +127,7 @@ source_set("libark_js_intl_static") { "//third_party/icu/icu4c:shared_icuuc", sdk_libc_secshared_dep, ] + deps += arkruntime_header_gen_deps } config("ark_jsruntime_common_config") { @@ -436,6 +437,7 @@ source_set("libark_jsruntime_test_static") { "//third_party/icu/icu4c:shared_icuuc", sdk_libc_secshared_dep, ] + deps += arkruntime_header_gen_deps if (is_debug && is_linux && (current_cpu == "x86" || current_cpu == "x64") && run_with_asan) { diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index b211d1c..80de56a 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -135,6 +135,7 @@ source_set("libark_jsoptimizer_static") { "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", ] + deps += arkruntime_header_gen_deps } ohos_shared_library("libark_jsoptimizer") { diff --git a/ecmascript/tooling/BUILD.gn b/ecmascript/tooling/BUILD.gn index e789c1b..c25bf31 100644 --- a/ecmascript/tooling/BUILD.gn +++ b/ecmascript/tooling/BUILD.gn @@ -47,8 +47,8 @@ source_set("libark_ecma_debugger_static") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", - "$ark_root/runtime:arkruntime_gen_intrinsics_intrinsics_h", ] + deps += arkruntime_header_gen_deps cflags_cc = [ "-fvisibility=hidden" ] } @@ -84,10 +84,8 @@ source_set("libark_ecma_debugger_test_static") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", - "$ark_root/runtime:arkruntime_gen_intrinsics_intrinsics_h", - "$ark_root/runtime:libarkruntime_options_gen_h", - "$ark_root/verification/gen:verification_verifier_messages_h", ] + deps += arkruntime_header_gen_deps } ohos_shared_library("libark_ecma_debugger_test") { diff --git a/js_runtime_config.gni b/js_runtime_config.gni index bf6c093..c21daa0 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -21,6 +21,14 @@ asan_lib_path = "/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux" sdk_libc_secshared_dep = "//utils/native/base:utilsecurec" sdk_libc_secshared_config = "//utils/native/base:utils_config" +# Add for header file dependence, should dependent this when include +# header file of runtime, but not dependent libarkruntime +arkruntime_header_gen_deps = [ + "$ark_root/runtime:arkruntime_gen_intrinsics_intrinsics_h", + "$ark_root/runtime:libarkruntime_options_gen_h", + "$ark_root/verification/gen:verification_verifier_messages_h", +] + # Generate file for a template and YAML data provided. # # Mandatory arguments: -- Gitee From 807af102c3ebdce615506ac1b95af8b7a4c78e2d Mon Sep 17 00:00:00 2001 From: luochuhao Date: Mon, 11 Oct 2021 22:17:27 +0800 Subject: [PATCH 018/115] Tweak on llvm api usage in stub_test.cpp and multiple optimizations Signed-off-by: luochuhao Change-Id: Ia21b1a3e2b3ae13ab5dd151b7654c1f220e3b362 --- ecmascript/compiler/fast_stub.cpp | 1 - ecmascript/compiler/fast_stub_define.h | 18 +- ecmascript/compiler/llvm_ir_builder.cpp | 9 +- ecmascript/compiler/llvm_ir_builder.h | 13 +- ecmascript/compiler/llvm_mcjit_engine.cpp | 21 +- ecmascript/compiler/llvm_mcjit_engine.h | 18 +- ecmascript/compiler/stub.h | 4 +- ecmascript/compiler/stub_descriptor.cpp | 64 ++- ecmascript/compiler/stub_descriptor.h | 1 + ecmascript/compiler/tests/stub_tests.cpp | 540 ++++++++-------------- 10 files changed, 300 insertions(+), 389 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index cea7472..2dee2e8 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -36,7 +36,6 @@ void FastArrayLoadElementStub::GenerateCircuit() aVal = TruncInt64ToInt32(aVal); } AddrShift taggedLength = Load(MachineType::TAGGED_TYPE, aVal, lengthOffset); - AddrShift intLength = TaggedCastToInt32(taggedLength); // if index < length Label ifTrue(env); diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index ccf3bf3..036fc11 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -59,9 +59,17 @@ namespace kungfu { V(GetPropertyByIndex, 3) \ V(SetPropertyByIndex, 4) -#define CALL_STUB_LIST(V) \ - FAST_RUNTIME_STUB_LIST(V) \ - EXTERNAL_RUNTIMESTUB_LIST(V) +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define TEST_FUNC_LIST(V) \ + V(FastLoadElement, 2) \ + V(PhiGateTest, 1) \ + V(LoopTest, 1) \ + V(LoopTest1, 1) + +#define CALL_STUB_LIST(V) \ + FAST_RUNTIME_STUB_LIST(V) \ + EXTERNAL_RUNTIMESTUB_LIST(V) \ + TEST_FUNC_LIST(V) enum CallStubId { // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) @@ -69,8 +77,10 @@ enum CallStubId { FAST_RUNTIME_STUB_LIST(DEF_FAST_STUB) FAST_STUB_MAXCOUNT, EXTERNAL_RUNTIME_STUB_BEGIN = FAST_STUB_MAXCOUNT - 1, EXTERNAL_RUNTIMESTUB_LIST(DEF_FAST_STUB) EXTERN_RUNTIME_STUB_MAXCOUNT, + TEST_FUNC_BEGIN = EXTERN_RUNTIME_STUB_MAXCOUNT - 1, + TEST_FUNC_LIST(DEF_FAST_STUB) TEST_FUNC_MAXCOUNT, #undef DEF_FAST_STUB - CALL_STUB_MAXCOUNT = EXTERN_RUNTIME_STUB_MAXCOUNT, + CALL_STUB_MAXCOUNT = TEST_FUNC_MAXCOUNT, }; // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index cba0feb..e717f48 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -1120,7 +1120,13 @@ void LLVMStubModule::Initialize() for (i = 0; i < MAX_EXTERNAL_FUNCTION_COUNT; i++) { auto externalDescriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(i + EXTERNAL_FUNCTION_OFFSET); if (!externalDescriptor->GetName().empty()) { - externalFuctionType_[i] = GetLLVMFunctionTypeStubDescriptor(externalDescriptor); + externalFunctionType_[i] = GetLLVMFunctionTypeStubDescriptor(externalDescriptor); + } + } + for (i = 0; i < MAX_TEST_FUNCTION_COUNT; i++) { + auto testFuncDescriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(i + TEST_FUNCTION_OFFSET); + if (!testFuncDescriptor->GetName().empty()) { + testFunctions_[i] = GetLLVMFunctionByStubDescriptor(testFuncDescriptor); } } } @@ -1159,6 +1165,7 @@ LLVMTypeRef LLVMStubModule::ConvertLLVMTypeFromMachineType(MachineType type) {MachineType::UINT64_TYPE, LLVMInt64Type()}, {MachineType::FLOAT32_TYPE, LLVMFloatType()}, {MachineType::FLOAT64_TYPE, LLVMDoubleType()}, + {MachineType::TAGGED_TYPE, LLVMInt64Type()}, }; return machineTypeMap[type]; } diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index ed35e2d..e05358a 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -116,7 +116,7 @@ public: LLVMTypeRef GetExternalFunctionType(uint32_t index) const { ASSERT(index - EXTERNAL_FUNCTION_OFFSET < MAX_EXTERNAL_FUNCTION_COUNT); - return externalFuctionType_[index - EXTERNAL_FUNCTION_OFFSET]; + return externalFunctionType_[index - EXTERNAL_FUNCTION_OFFSET]; } LLVMValueRef GetStubFunction(uint32_t index) @@ -125,6 +125,12 @@ public: return stubFunctions_[index]; } + LLVMValueRef GetTestFunction(uint32_t index) + { + ASSERT(index - TEST_FUNCTION_OFFSET < MAX_TEST_FUNCTION_COUNT); + return testFunctions_[index - TEST_FUNCTION_OFFSET]; + } + private: LLVMValueRef GetLLVMFunctionByStubDescriptor(StubDescriptor *stubDescriptor); LLVMTypeRef GetLLVMFunctionTypeStubDescriptor(StubDescriptor *stubDescriptor); @@ -132,8 +138,11 @@ private: static constexpr uint32_t MAX_EXTERNAL_FUNCTION_COUNT = kungfu::EXTERN_RUNTIME_STUB_MAXCOUNT - kungfu::EXTERNAL_RUNTIME_STUB_BEGIN - 1; static constexpr uint32_t EXTERNAL_FUNCTION_OFFSET = kungfu::EXTERNAL_RUNTIME_STUB_BEGIN + 1; + static constexpr uint32_t MAX_TEST_FUNCTION_COUNT = kungfu::TEST_FUNC_MAXCOUNT - kungfu::TEST_FUNC_BEGIN - 1; + static constexpr uint32_t TEST_FUNCTION_OFFSET = kungfu::TEST_FUNC_BEGIN + 1; std::array stubFunctions_ {nullptr}; - std::array externalFuctionType_ {nullptr}; + std::array externalFunctionType_ {nullptr}; + std::array testFunctions_ {nullptr}; LLVMModuleRef module_; }; diff --git a/ecmascript/compiler/llvm_mcjit_engine.cpp b/ecmascript/compiler/llvm_mcjit_engine.cpp index bb3e4ec..73d5071 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.cpp +++ b/ecmascript/compiler/llvm_mcjit_engine.cpp @@ -52,11 +52,11 @@ namespace kungfu { static uint8_t *RoundTripAllocateCodeSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, [[maybe_unused]] unsigned sectionID, const char *sectionName) { - std::cout << "RoundTripAllocateCodeSection object " << object << " - " << std::endl; + LOG_ECMA(INFO) << "RoundTripAllocateCodeSection object " << object << " - "; struct CodeInfo& state = *static_cast(object); uint8_t *addr = state.AllocaCodeSection(size, sectionName); - std::cout << "RoundTripAllocateCodeSection addr:" << std::hex << reinterpret_cast(addr) << addr - << " size:0x" << size << " +" << std::endl; + LOG_ECMA(INFO) << "RoundTripAllocateCodeSection addr:" << std::hex << reinterpret_cast(addr) << + addr << " size:0x" << size << " + "; return addr; } @@ -70,13 +70,13 @@ static uint8_t *RoundTripAllocateDataSection(void *object, uintptr_t size, [[may static LLVMBool RoundTripFinalizeMemory(void *object, [[maybe_unused]] char **errMsg) { - std::cout << "RoundTripFinalizeMemory object " << object << " - " << std::endl; + LOG_ECMA(INFO) << "RoundTripFinalizeMemory object " << object << " - "; return 0; } static void RoundTripDestroy(void *object) { - std::cout << "RoundTripDestroy object " << object << " - " << std::endl; + LOG_ECMA(INFO) << "RoundTripDestroy object " << object << " - "; } void LLVMAssembler::UseRoundTripSectionMemoryManager() @@ -89,20 +89,19 @@ void LLVMAssembler::UseRoundTripSectionMemoryManager() bool LLVMAssembler::BuildMCJITEngine() { - std::cout << " BuildMCJITEngine - " << std::endl; + LOG_ECMA(INFO) << " BuildMCJITEngine - "; LLVMBool ret = LLVMCreateMCJITCompilerForModule(&engine_, module_, &options_, sizeof(options_), &error_); - std::cout << " engine_ " << engine_ << std::endl; if (ret) { - std::cout << "error_ : " << error_ << std::endl; + LOG_ECMA(ERROR) << "error_ : " << error_; return false; } - std::cout << " BuildMCJITEngine ++++++++++++ " << std::endl; + LOG_ECMA(INFO) << " BuildMCJITEngine + "; return true; } void LLVMAssembler::BuildAndRunPasses() const { - std::cout << "BuildAndRunPasses - " << std::endl; + LOG_ECMA(INFO) << "BuildAndRunPasses - "; LLVMPassManagerRef pass = LLVMCreatePassManager(); LLVMAddConstantPropagationPass(pass); LLVMAddInstructionCombiningPass(pass); @@ -110,7 +109,7 @@ void LLVMAssembler::BuildAndRunPasses() const LOG_ECMA(INFO) << "Current Module: " << LLVMPrintModuleToString(module_); LLVMRunPassManager(pass, module_); LLVMDisposePassManager(pass); - std::cout << "BuildAndRunPasses + " << std::endl; + LOG_ECMA(INFO) << "BuildAndRunPasses + "; } LLVMAssembler::LLVMAssembler(LLVMModuleRef module, const char* triple): module_(module), engine_(nullptr), diff --git a/ecmascript/compiler/llvm_mcjit_engine.h b/ecmascript/compiler/llvm_mcjit_engine.h index 1e0cb6e..feb851f 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.h +++ b/ecmascript/compiler/llvm_mcjit_engine.h @@ -22,6 +22,7 @@ #include #include +#include "ecmascript/ecma_macros.h" #include "llvm/ExecutionEngine/Interpreter.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" @@ -55,16 +56,16 @@ struct CodeInfo { { uint8_t *addr = nullptr; if (codeBufferPos_ + size > MAX_MACHINE_CODE_SIZE) { - std::cerr << std::hex << "AllocaCodeSection failed alloc codeBufferPos_:" << codeBufferPos_ - << " size:" << size << " larger MAX_MACHINE_CODE_SIZE:" << MAX_MACHINE_CODE_SIZE << std::endl; + LOG_ECMA(INFO) << std::hex << "AllocaCodeSection failed alloc codeBufferPos_:" << codeBufferPos_ + << " size:" << size << " larger MAX_MACHINE_CODE_SIZE:" << MAX_MACHINE_CODE_SIZE; return nullptr; } - std::cout << "AllocaCodeSection size:" << size << std::endl; + LOG_ECMA(INFO) << "AllocaCodeSection size:" << size; std::vector codeBuffer(machineCode_[codeBufferPos_], size); - std::cout << " codeBuffer size: " << codeBuffer.size() << std::endl; + LOG_ECMA(INFO) << " codeBuffer size: " << codeBuffer.size(); codeSectionNames_.push_back(sectionName); addr = machineCode_ + codeBufferPos_; - std::cout << "AllocaCodeSection addr:" << std::hex << reinterpret_cast(addr) << std::endl; + LOG_ECMA(INFO) << "AllocaCodeSection addr:" << std::hex << reinterpret_cast(addr); codeInfo_.push_back({addr, size}); codeBufferPos_ += size; return addr; @@ -78,7 +79,7 @@ struct CodeInfo { dataSectionNames_.push_back(sectionName); addr = static_cast(dataSectionList_.back().data()); if (!strcmp(sectionName, ".llvm_stackmaps")) { - std::cout << "llvm_stackmaps : " << addr << std::endl; + LOG_ECMA(INFO) << "llvm_stackmaps : " << addr; stackMapsSection_ = addr; } return addr; @@ -149,10 +150,13 @@ public: return codeInfo_.GetCodeBuff(); } + void *GetFuncPtrFromCompiledModule(LLVMValueRef function) + { + return LLVMGetPointerToGlobal(engine_, function); + } const char *AMD64_TRIPLE = "x86_64-unknown-linux-gnu"; const char *ARM64_TRIPLE = "aarch64-unknown-linux-gnu"; const char *ARM32_TRIPLE = "arm-unknown-linux-gnu"; - private: void UseRoundTripSectionMemoryManager(); bool BuildMCJITEngine(); diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 186759a..1ae07f2 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -841,8 +841,8 @@ public: AddrShift negativeInfinity = GetDoubleConstant(-base::POSITIVE_INFINITY); AddrShift diff1 = DoubleEqual(x, infinity); AddrShift diff2 = DoubleEqual(x, negativeInfinity); - return Word32Or(Word32Equal(SExtInt1ToInt32(diff1), GetInteger32Constant(1)), - Word32Equal(SExtInt1ToInt32(diff2), GetInteger32Constant(1))); + return TruncInt32ToInt1(Word32Or(Word32Equal(SExtInt1ToInt32(diff1), GetInteger32Constant(1)), + Word32Equal(SExtInt1ToInt32(diff2), GetInteger32Constant(1)))); } AddrShift IntBuildTagged(AddrShift x) diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 31cc658..bc59aad 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -79,7 +79,18 @@ CALL_STUB_INIT_DESCRIPTOR(FastDiv) descriptor->SetParameters(params.data()); } -CALL_STUB_INIT_DESCRIPTOR(FastMod) {} +CALL_STUB_INIT_DESCRIPTOR(FastMod) +{ + // 2 : 2 input parameters + static StubDescriptor fastMod("FastMod", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + *descriptor = fastMod; + // 2 : 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); +} CALL_STUB_INIT_DESCRIPTOR(FastEqual) {} @@ -325,15 +336,62 @@ CALL_STUB_INIT_DESCRIPTOR(FindElementWithCache) CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) { - static StubDescriptor stringGetHashCode("StringGetHashCode", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + // 2 : 2 input parameters + static StubDescriptor stringGetHashCode("StringGetHashCode", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); *descriptor = stringGetHashCode; - std::array params = { + std::array params = { // // 2 : 2 input parameters MachineType::UINT64_TYPE, }; descriptor->SetParameters(params.data()); descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } +CALL_STUB_INIT_DESCRIPTOR(FastLoadElement) +{ + // 2 : 2 input parameters + static StubDescriptor fastLoadElement("FastLoadElement", 0, 2, ArgumentsOrder::DEFAULT_ORDER, TAGGED_TYPE); + *descriptor = fastLoadElement; + std::array params = { // 2 : 2 input parameters + MachineType::UINT64_TYPE, + MachineType::UINT32_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::TEST_FUNC); +} + +CALL_STUB_INIT_DESCRIPTOR(PhiGateTest) +{ + static StubDescriptor phiGateTest("PhiGateTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + *descriptor = phiGateTest; + std::array params = { + MachineType::UINT32_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::TEST_FUNC); +} + +CALL_STUB_INIT_DESCRIPTOR(LoopTest) +{ + static StubDescriptor loopTest("LoopTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + *descriptor = loopTest; + std::array params = { + MachineType::UINT32_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::TEST_FUNC); +} + +CALL_STUB_INIT_DESCRIPTOR(LoopTest1) +{ + static StubDescriptor loopTest1("LoopTest1", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + *descriptor = loopTest1; + std::array params = { + MachineType::UINT32_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::TEST_FUNC); +} + void FastStubDescriptors::InitializeStubDescriptors() { // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/compiler/stub_descriptor.h b/ecmascript/compiler/stub_descriptor.h index c921dac..57823d8 100644 --- a/ecmascript/compiler/stub_descriptor.h +++ b/ecmascript/compiler/stub_descriptor.h @@ -33,6 +33,7 @@ public: enum class CallStubKind { CODE_STUB, RUNTIME_STUB, + TEST_FUNC, }; explicit StubDescriptor(std::string name, int flags, int paramCounter, ArgumentsOrder order, MachineType returnType) diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 3101ab9..c050de6 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -55,9 +55,15 @@ public: TestHelper::DestroyEcmaVMWithScope(instance, scope); } - JSTaggedValue FastMul2(JSTaggedValue x, JSTaggedValue y) + void PrintCircuitByBasicBlock(const std::vector> &cfg, const Circuit &netOfGates) { - return FastRuntimeStub::FastMul(x, y); + for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { + std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" + << std::endl; + for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { + netOfGates.Print(cfg[bbIdx][instIdx - 1]); + } + } } PandaVM *instance {nullptr}; @@ -68,16 +74,8 @@ public: HWTEST_F_L0(StubTest, FastLoadElement) { - auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); - LLVMModuleRef module = LLVMModuleCreateWithName("simple_module"); - LLVMSetTarget(module, "x86_64-unknown-linux-gnu"); - LLVMTypeRef paramTys[] = { - LLVMPointerType(LLVMInt64Type(), 0), - LLVMInt32Type(), - }; - LLVMValueRef function = - // 2 : parameter number - LLVMAddFunction(module, "FastLoadElement", LLVMFunctionType(LLVMInt64Type(), paramTys, 2, 0)); + auto module = stubModule.GetModule(); + auto function = stubModule.GetTestFunction(FAST_STUB_ID(FastLoadElement)); Circuit netOfGates; FastArrayLoadElementStub optimizer(&netOfGates); optimizer.GenerateCircuit(); @@ -85,35 +83,24 @@ HWTEST_F_L0(StubTest, FastLoadElement) bool result = Verifier::Run(&netOfGates); ASSERT_TRUE(result); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); - /* exec function */ - auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); - // 5 : 5 means that there are 5 cases in total. - JSHandle values(factory->NewTaggedArray(5)); - // 5 : 5 means that there are 5 cases in total. - for (int i = 0; i < 5; i++) { + // Testcase build and run + auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); + auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); + JSHandle values(factory->NewTaggedArray(5)); // 5 : 5 elements in array + for (int i = 0; i < 5; i++) { // 5 : 5 elements in array values->Set(thread, i, JSTaggedValue(i)); } JSHandle array(JSArray::CreateArrayFromList(thread, values)); JSArray *arr = array.GetObject(); auto valValid = fn(arr, 1); EXPECT_EQ(valValid, 0xffff000000000001); - // 6 : size of array - auto valUndefine = fn(arr, 6); + auto valUndefine = fn(arr, 6); // 6 : size of array EXPECT_EQ(valUndefine, 0xa); - std::cerr << "valValid = " << std::hex << valValid << std::endl; - std::cerr << "valUndefine = " << std::hex << valUndefine << std::endl; } class PhiStub : public Stub { @@ -130,14 +117,17 @@ public: Label ifTrue(env); Label ifFalse(env); Label next(env); - Branch(Word32Equal(*x, GetInteger32Constant(10)), &ifTrue, &ifFalse); // 10 : size of entry Bind(&ifTrue); - z = Int32Add(*x, GetInteger32Constant(10)); // 10 : size of entry - Jump(&next); - Bind(&ifFalse); // else - z = Int32Add(*x, GetInteger32Constant(100)); // 100 : size of entry - Jump(&next); + { + z = Int32Add(*x, GetInteger32Constant(10)); // 10 : size of entry + Jump(&next); + } + Bind(&ifFalse); + { + z = Int32Add(*x, GetInteger32Constant(100)); // 100 : size of entry + Jump(&next); + } Bind(&next); Return(*z); } @@ -145,64 +135,26 @@ public: HWTEST_F_L0(StubTest, PhiGateTest) { - std::cout << "---------------------PhiGateTest-----------------------------------------------------" << std::endl; - LLVMModuleRef module = LLVMModuleCreateWithName("simple_module"); - LLVMSetTarget(module, "x86_64-unknown-linux-gnu"); - LLVMTypeRef paramTys[] = { - LLVMInt32Type(), - }; - LLVMValueRef function = LLVMAddFunction(module, "PhiGateTest", LLVMFunctionType(LLVMInt32Type(), paramTys, 1, 0)); + auto module = stubModule.GetModule(); + auto function = stubModule.GetTestFunction(FAST_STUB_ID(PhiGateTest)); Circuit netOfGates; PhiStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); - /* exec function */ - auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); - auto val = fn(3); // 3 : size of array - auto val2 = fn(0); - std::cout << "val = " << std::dec << val << std::endl; - std::cout << "val2 = " << std::dec << val2 << std::endl; - std::cout << "+++++++++++++++++++++PhiGateTest+++++++++++++++++++++++++++++++++++++++++++++++++++++" << std::endl; + // Testcase build and run + auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); + auto valA = fn(3); // 3 : size of array + auto valB = fn(0); + EXPECT_EQ(valA, 103); // 103 : eXpert res for fn(3) + EXPECT_EQ(valB, 100); // 100 : eXpert res for fn(0) } -class CallPhiStub : public Stub { -public: - explicit CallPhiStub(Circuit *circuit) - : Stub("CallPhi", 1, circuit), - phi_descriptor_("phi", 0, 1, ArgumentsOrder::DEFAULT_ORDER, MachineType::INT32_TYPE) - { - std::array *params = new std::array(); - (*params)[0] = MachineType::INT32_TYPE; - phi_descriptor_.SetParameters(params->data()); - } - ~CallPhiStub() = default; - NO_MOVE_SEMANTIC(CallPhiStub); - NO_COPY_SEMANTIC(CallPhiStub); - void GenerateCircuit() override - { - DEFVARIABLE(x, MachineType::INT32_TYPE, Int32Argument(0)); - x = Int32Add(*x, GetInteger32Constant(1)); - AddrShift callFoo = CallStub(&phi_descriptor_, GetWord64Constant(0), {*x}); - Return(Int32Add(callFoo, GetInteger32Constant(1))); - } - -private: - StubDescriptor phi_descriptor_; -}; - class LoopStub : public Stub { public: explicit LoopStub(Circuit *circuit) : Stub("loop", 1, circuit) {} @@ -242,38 +194,26 @@ public: HWTEST_F_L0(StubTest, LoopTest) { - LLVMModuleRef module = LLVMModuleCreateWithName("simple_module"); - LLVMSetTarget(module, "x86_64-unknown-linux-gnu"); - LLVMTypeRef paramTys[] = { - LLVMInt32Type(), - }; - LLVMValueRef function = LLVMAddFunction(module, "LoopTest", LLVMFunctionType(LLVMInt32Type(), paramTys, 1, 0)); + auto module = stubModule.GetModule(); + auto function = stubModule.GetTestFunction(FAST_STUB_ID(LoopTest)); Circuit netOfGates; LoopStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t inst_idx = cfg[bbIdx].size(); inst_idx > 0; inst_idx--) { - netOfGates.Print(cfg[bbIdx][inst_idx - 1]); - } - } + PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); - - /* exec function */ - auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); - auto resValid = fn(1); - auto resValid2 = fn(9); // 9 : size of array - auto resInvalid = fn(11); // 11 : size of array - std::cout << "res for loop(1) = " << std::dec << resValid << std::endl; - std::cout << "res for loop(9) = " << std::dec << resValid2 << std::endl; - std::cout << "res for loop(11) = " << std::dec << resInvalid << std::endl; + // Testcase build and run + auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); + auto valA = fn(1); + auto valB = fn(9); // 9 : size of array + auto valC = fn(11); // 11 : size of array + EXPECT_EQ(valA, 109); // 109 : eXpert res for fn(1) + EXPECT_EQ(valB, 19); // 10 : eXpert res for fn(9) + EXPECT_EQ(valC, 0); } class LoopStub1 : public Stub { @@ -324,61 +264,47 @@ HWTEST_F_L0(StubTest, LoopTest1) optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } + PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); auto engine = assembler.GetEngine(); - /* exec function */ + // Testcase build and run auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); - auto resValid = fn(1); - auto resValid2 = fn(9); // 9 : size of array - auto resInvalid = fn(11); // 11 : size of array - std::cout << "res for loop1(1) = " << std::dec << resValid << std::endl; - std::cout << "res for loop1(9) = " << std::dec << resValid2 << std::endl; - std::cout << "res for loop1(11) = " << std::dec << resInvalid << std::endl; + auto valA = fn(1); + auto valB = fn(9); // 9 : size of array + auto valC = fn(11); // 11 : size of array + EXPECT_EQ(valA, 10); // 10 : eXpert res for fn(1) + EXPECT_EQ(valB, 10); // 10 : eXpert res for fn(9) + EXPECT_EQ(valC, 11); // 10 : eXpert res for fn(11) } HWTEST_F_L0(StubTest, FastAddTest) { - LLVMModuleRef module = LLVMModuleCreateWithName("fast_add_module"); - LLVMSetTarget(module, "x86_64-unknown-linux-gnu"); - LLVMTypeRef paramTys[] = { - LLVMInt64Type(), - LLVMInt64Type(), - }; - LLVMValueRef function = LLVMAddFunction(module, "FastAddTest", LLVMFunctionType(LLVMInt64Type(), paramTys, 2, 0)); + auto module = stubModule.GetModule(); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(FastAdd)); Circuit netOfGates; FastAddStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); - /* exec function */ - auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); - auto resValid = fn(JSTaggedValue(1).GetRawData(), JSTaggedValue(1).GetRawData()); - auto resValid2 = fn(JSTaggedValue(2).GetRawData(), JSTaggedValue(2).GetRawData()); // 2 : test case - auto resInvalid = fn(JSTaggedValue(11).GetRawData(), JSTaggedValue(11).GetRawData()); // 11 : test case - std::cout << "res for FastAdd(1, 1) = " << std::dec << resValid.GetNumber() << std::endl; - std::cout << "res for FastAdd(2, 2) = " << std::dec << resValid2.GetNumber() << std::endl; - std::cout << "res for FastAdd(11, 11) = " << std::dec << resInvalid.GetNumber() << std::endl; + // Testcase build and run + auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); + auto resA = fn(JSTaggedValue(1).GetRawData(), JSTaggedValue(1).GetRawData()); + auto resB = fn(JSTaggedValue(2).GetRawData(), JSTaggedValue(2).GetRawData()); // 2 : test case + auto resC = fn(JSTaggedValue(11).GetRawData(), JSTaggedValue(11).GetRawData()); // 11 : test case + LOG_ECMA(INFO) << "res for FastAdd(1, 1) = " << resA.GetNumber(); + LOG_ECMA(INFO) << "res for FastAdd(2, 2) = " << resB.GetNumber(); + LOG_ECMA(INFO) << "res for FastAdd(11, 11) = " << resC.GetNumber(); + EXPECT_EQ(resA.GetNumber(), JSTaggedValue(2).GetNumber()); + EXPECT_EQ(resB.GetNumber(), JSTaggedValue(4).GetNumber()); + EXPECT_EQ(resC.GetNumber(), JSTaggedValue(22).GetNumber()); int x1 = 2147483647; int y1 = 15; auto resG = fn(JSTaggedValue(x1).GetRawData(), JSTaggedValue(y1).GetRawData()); @@ -388,75 +314,53 @@ HWTEST_F_L0(StubTest, FastAddTest) HWTEST_F_L0(StubTest, FastSubTest) { - LLVMModuleRef module = LLVMModuleCreateWithName("fast_sub_module"); - LLVMSetTarget(module, "x86_64-unknown-linux-gnu"); - LLVMTypeRef paramTys[] = { - LLVMInt64Type(), - LLVMInt64Type(), - }; - LLVMValueRef function = LLVMAddFunction(module, "FastSubTest", LLVMFunctionType(LLVMInt64Type(), paramTys, 2, 0)); + auto module = stubModule.GetModule(); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(FastSub)); Circuit netOfGates; FastSubStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); - /* exec function */ - auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); + // Testcase build and run + auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); auto resA = fn(JSTaggedValue(2).GetRawData(), JSTaggedValue(1).GetRawData()); // 2 : test case auto resB = fn(JSTaggedValue(7).GetRawData(), JSTaggedValue(2).GetRawData()); // 7, 2 : test cases auto resC = fn(JSTaggedValue(11).GetRawData(), JSTaggedValue(11).GetRawData()); // 11 : test case - std::cout << "res for FastSub(2, 1) = " << std::dec << resA.GetNumber() << std::endl; - std::cout << "res for FastSub(7, 2) = " << std::dec << resB.GetNumber() << std::endl; - std::cout << "res for FastSub(11, 11) = " << std::dec << resC.GetNumber() << std::endl; + LOG_ECMA(INFO) << "res for FastSub(2, 1) = " << resA.GetNumber(); + LOG_ECMA(INFO) << "res for FastSub(7, 2) = " << resB.GetNumber(); + LOG_ECMA(INFO) << "res for FastSub(11, 11) = " << resC.GetNumber(); + EXPECT_EQ(resA, JSTaggedValue(1)); + EXPECT_EQ(resB, JSTaggedValue(5)); + EXPECT_EQ(resC, JSTaggedValue(0)); } HWTEST_F_L0(StubTest, FastMulTest) { - LLVMModuleRef module = LLVMModuleCreateWithName("fast_mul_module"); - LLVMSetTarget(module, "x86_64-unknown-linux-gnu"); - LLVMTypeRef paramTys[] = { - LLVMInt64Type(), - LLVMInt64Type(), - }; - LLVMValueRef function = LLVMAddFunction(module, "FastMulTest", LLVMFunctionType(LLVMInt64Type(), paramTys, 2, 0)); + auto module = stubModule.GetModule(); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(FastMul)); Circuit netOfGates; FastMulStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); - - /* exec function */ - auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); + // Testcase build and run + auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); auto resA = fn(JSTaggedValue(-2).GetRawData(), JSTaggedValue(1).GetRawData()); // -2 : test case auto resB = fn(JSTaggedValue(-7).GetRawData(), JSTaggedValue(-2).GetRawData()); // -7, -2 : test case auto resC = fn(JSTaggedValue(11).GetRawData(), JSTaggedValue(11).GetRawData()); // 11 : test case - std::cout << "res for FastMul(-2, 1) = " << std::dec << resA.GetNumber() << std::endl; - std::cout << "res for FastMul(-7, -2) = " << std::dec << resB.GetNumber() << std::endl; - std::cout << "res for FastMul(11, 11) = " << std::dec << resC.GetNumber() << std::endl; + LOG_ECMA(INFO) << "res for FastMul(-2, 1) = " << std::dec << resA.GetNumber(); + LOG_ECMA(INFO) << "res for FastMul(-7, -2) = " << std::dec << resB.GetNumber(); + LOG_ECMA(INFO) << "res for FastMul(11, 11) = " << std::dec << resC.GetNumber(); int x = 7; double y = 1125899906842624; auto resD = fn(JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData()); @@ -481,76 +385,117 @@ HWTEST_F_L0(StubTest, FastMulTest) HWTEST_F_L0(StubTest, FastDivTest) { - LLVMModuleRef module = LLVMModuleCreateWithName("fast_div_module"); - LLVMSetTarget(module, "x86_64-unknown-linux-gnu"); - LLVMTypeRef paramTys[] = { - LLVMInt64Type(), - LLVMInt64Type(), - }; - LLVMValueRef function = LLVMAddFunction(module, "FastDiv", LLVMFunctionType(LLVMInt64Type(), paramTys, 2, 0)); + auto module = stubModule.GetModule(); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(FastDiv)); Circuit netOfGates; FastDivStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); - auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); - + auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); // test normal Division operation uint64_t x1 = JSTaggedValue(50).GetRawData(); uint64_t y1 = JSTaggedValue(25).GetRawData(); - std::cout << "x1 = " << x1 << " y1 = " << y1 << std::endl; + LOG_ECMA(INFO) << "x1 = " << x1 << " y1 = " << y1; auto res1 = fn(x1, y1); - std::cout << "res for FastDiv(50, 25) = " << res1.GetRawData() << std::endl; + LOG_ECMA(INFO) << "res for FastDiv(50, 25) = " << res1.GetRawData(); auto expectedG1 = FastRuntimeStub::FastDiv(JSTaggedValue(x1), JSTaggedValue(y1)); EXPECT_EQ(res1, expectedG1); // test x == 0.0 or std::isnan(x) uint64_t x2 = JSTaggedValue(base::NAN_VALUE).GetRawData(); uint64_t y2 = JSTaggedValue(0).GetRawData(); - std::cout << "x2 = " << x1 << " y2 = " << y2 << std::endl; + LOG_ECMA(INFO) << "x2 = " << x1 << " y2 = " << y2; auto res2 = fn(x2, y2); - std::cout << "res for FastDiv(base::NAN_VALUE, 0) = " << res2.GetRawData() << std::endl; + LOG_ECMA(INFO) << "res for FastDiv(base::NAN_VALUE, 0) = " << res2.GetRawData(); auto expectedG2 = FastRuntimeStub::FastDiv(JSTaggedValue(x2), JSTaggedValue(y2)); EXPECT_EQ(res2, expectedG2); // test other uint64_t x3 = JSTaggedValue(7).GetRawData(); uint64_t y3 = JSTaggedValue(0).GetRawData(); - std::cout << "x2 = " << x3 << " y2 = " << y3 << std::endl; + LOG_ECMA(INFO) << "x2 = " << x3 << " y2 = " << y3; auto res3 = fn(x3, y3); - std::cout << "res for FastDiv(7, 0) = " << res3.GetRawData() << std::endl; + LOG_ECMA(INFO) << "res for FastDiv(7, 0) = " << res3.GetRawData(); auto expectedG3 = FastRuntimeStub::FastDiv(JSTaggedValue(x3), JSTaggedValue(y3)); EXPECT_EQ(res3, expectedG3); } -HWTEST_F_L0(StubTest, FindOwnElementStub) +HWTEST_F_L0(StubTest, FastModTest) +{ + auto module = stubModule.GetModule(); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(FastMod)); + Circuit netOfGates; + FastModStub optimizer(&netOfGates); + optimizer.GenerateCircuit(); + netOfGates.PrintAllGates(); + auto cfg = Scheduler::Run(&netOfGates); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); + llvmBuilder.Build(); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); + assembler.Run(); + auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); + + // test left, right are all integer + int x = 7; + int y = 3; + auto result = fn(JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData()); + JSTaggedValue expectRes = FastRuntimeStub::FastMod(JSTaggedValue(x), JSTaggedValue(y)); + EXPECT_EQ(result, expectRes); + + // test y == 0.0 || std::isnan(y) || std::isnan(x) || std::isinf(x) return NAN_VALUE + double x2 = 7.3; + int y2 = base::NAN_VALUE; + auto result2 = fn(JSTaggedValue(x2).GetRawData(), JSTaggedValue(y2).GetRawData()); + auto expectRes2 = FastRuntimeStub::FastMod(JSTaggedValue(x2), JSTaggedValue(y2)); + EXPECT_EQ(result2, expectRes2); + LOG_ECMA(INFO) << "result2 for FastMod(7, 'helloworld') = " << result2.GetRawData(); + LOG_ECMA(INFO) << "expectRes2 for FastMod(7, 'helloworld') = " << expectRes2.GetRawData(); + + // // test modular operation under normal conditions + double x3 = 33.0; + double y3 = 44.0; + auto result3 = fn(JSTaggedValue(x3).GetRawData(), JSTaggedValue(y3).GetRawData()); + auto expectRes3 = FastRuntimeStub::FastMod(JSTaggedValue(x3), JSTaggedValue(y3)); + EXPECT_EQ(result3, expectRes3); + + // test x == 0.0 || std::isinf(y) return x + double x4 = base::NAN_VALUE; + int y4 = 7; + auto result4 = fn(JSTaggedValue(x4).GetRawData(), JSTaggedValue(y4).GetRawData()); + auto expectRes4 = FastRuntimeStub::FastMod(JSTaggedValue(x4), JSTaggedValue(y4)); + + LOG_ECMA(INFO) << "result4 for FastMod(base::NAN_VALUE, 7) = " << result4.GetRawData(); + LOG_ECMA(INFO) << "expectRes4 for FastMod(base::NAN_VALUE, 7) = " << expectRes4.GetRawData(); + EXPECT_EQ(result4, expectRes4); + + // test all non-conforming conditions + int x5 = 7; + auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); + auto y5 = factory->NewFromStdString("hello world"); + auto result5 = fn(JSTaggedValue(x5).GetRawData(), y5.GetTaggedValue().GetRawData()); + EXPECT_EQ(result5, JSTaggedValue::Hole()); + auto expectRes5 = FastRuntimeStub::FastMod(JSTaggedValue(x5), y5.GetTaggedValue()); + LOG_ECMA(INFO) << "result1 for FastMod(7, 'helloworld') = " << result5.GetRawData(); + EXPECT_EQ(result5, expectRes5); +} + +HWTEST_F_L0(StubTest, FastFindOwnElementStub) { auto module = stubModule.GetModule(); - LLVMValueRef findFunction = LLVMGetNamedFunction(module, "FindOwnElement"); + auto findFunction = stubModule.GetStubFunction(FAST_STUB_ID(FindOwnElement)); Circuit netOfGates; FindOwnElementStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } + PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); @@ -560,18 +505,11 @@ HWTEST_F_L0(StubTest, FindOwnElementStub) HWTEST_F_L0(StubTest, GetElementStub) { auto module = stubModule.GetModule(); - LLVMValueRef findFunction = LLVMGetNamedFunction(module, "FindOwnElement"); + auto findFunction = stubModule.GetStubFunction(FAST_STUB_ID(FindOwnElement)); Circuit netOfGates; FindOwnElementStub findOptimizer(&netOfGates); findOptimizer.GenerateCircuit(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction); llvmBuilder.Build(); Circuit getNetOfGates; @@ -579,13 +517,7 @@ HWTEST_F_L0(StubTest, GetElementStub) getOptimizer.GenerateCircuit(); getNetOfGates.PrintAllGates(); auto getCfg = Scheduler::Run(&getNetOfGates); - for (size_t bbIdx = 0; bbIdx < getCfg.size(); bbIdx++) { - std::cout << (getNetOfGates.GetOpCode(getCfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = getCfg[bbIdx].size(); instIdx > 0; instIdx--) { - getNetOfGates.Print(getCfg[bbIdx][instIdx - 1]); - } - } + PrintCircuitByBasicBlock(getCfg, getNetOfGates); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); @@ -593,29 +525,21 @@ HWTEST_F_L0(StubTest, GetElementStub) HWTEST_F_L0(StubTest, FindOwnElement2Stub) { - std::cout << " ------------------------FindOwnElement2Stub ---------------------" << std::endl; auto module = stubModule.GetModule(); - LLVMValueRef function = LLVMGetNamedFunction(module, "FindOwnElement2"); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(FindOwnElement2)); Circuit netOfGates; FindOwnElement2Stub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } + PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); auto *findOwnElement2Ptr = reinterpret_cast( - reinterpret_cast(LLVMGetPointerToGlobal(engine, function))); + reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function))); auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); JSHandle obj = factory->NewEmptyJSObject(); int x = 213; @@ -631,25 +555,18 @@ HWTEST_F_L0(StubTest, FindOwnElement2Stub) EXPECT_EQ(resVal.GetNumber(), x); resVal = findOwnElement2Ptr(thread, elements, 10250, isDict, &attr, &indexOrEntry); EXPECT_EQ(resVal.GetNumber(), y); - std::cout << " ++++++++++++++++++++FindOwnElement2Stub ++++++++++++++++++" << std::endl; } HWTEST_F_L0(StubTest, SetElementStub) { auto module = stubModule.GetModule(); - LLVMValueRef function = LLVMGetNamedFunction(module, "SetElement"); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(SetElement)); Circuit netOfGates; SetElementStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } + PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); @@ -1133,26 +1050,19 @@ void DoSafepoint() HWTEST_F_L0(StubTest, GetPropertyByIndexStub) { auto module = stubModule.GetModule(); - LLVMValueRef function = LLVMGetNamedFunction(module, "GetPropertyByIndex"); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(GetPropertyByIndex)); Circuit netOfGates; GetPropertyByIndexStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } + PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); auto *getpropertyByIndex = reinterpret_cast( - reinterpret_cast(LLVMGetPointerToGlobal(engine, function))); + reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function))); auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); JSHandle obj = factory->NewEmptyJSObject(); int x = 213; @@ -1169,7 +1079,7 @@ HWTEST_F_L0(StubTest, GetPropertyByIndexStub) HWTEST_F_L0(StubTest, SetPropertyByIndexStub) { auto module = stubModule.GetModule(); - LLVMValueRef function = LLVMGetNamedFunction(module, "SetPropertyByIndex"); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(SetPropertyByIndex)); Circuit netOfGates; SetPropertyByIndexStub optimizer(&netOfGates); optimizer.GenerateCircuit(); @@ -1177,20 +1087,13 @@ HWTEST_F_L0(StubTest, SetPropertyByIndexStub) bool result = Verifier::Run(&netOfGates); ASSERT_TRUE(result); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } + PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); auto *setpropertyByIndex = reinterpret_cast( - reinterpret_cast(LLVMGetPointerToGlobal(engine, function))); + reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function))); auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); JSHandle array = factory->NewJSArray(); assembler.Disassemble(); @@ -1209,7 +1112,7 @@ HWTEST_F_L0(StubTest, SetPropertyByIndexStub) HWTEST_F_L0(StubTest, GetPropertyByNameStub) { auto module = stubModule.GetModule(); - LLVMValueRef function = LLVMGetNamedFunction(module, "GetPropertyByName"); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(GetPropertyByName)); Circuit netOfGates; GetPropertyByNameStub optimizer(&netOfGates); optimizer.GenerateCircuit(); @@ -1217,20 +1120,13 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub) bool result = Verifier::Run(&netOfGates); ASSERT_TRUE(result); auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { - netOfGates.Print(cfg[bbIdx][instIdx - 1]); - } - } + PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); auto *getPropertyByNamePtr = reinterpret_cast( - reinterpret_cast(LLVMGetPointerToGlobal(engine, function))); + reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function))); auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); JSHandle obj = factory->NewEmptyJSObject(); int x = 213; @@ -1246,76 +1142,4 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub) resVal = getPropertyByNamePtr(thread, obj.GetTaggedValue().GetRawData(), strBig.GetTaggedValue().GetRawData()); EXPECT_EQ(resVal.GetNumber(), y); } - -HWTEST_F_L0(StubTest, FastModTest) -{ - LLVMModuleRef module = LLVMModuleCreateWithName("fast_mod_module"); - LLVMSetTarget(module, "x86_64-unknown-linux-gnu"); - LLVMTypeRef paramTys[] = { - LLVMInt64Type(), - LLVMInt64Type(), - }; - LLVMValueRef function = LLVMAddFunction(module, "FastMod", LLVMFunctionType(LLVMInt64Type(), paramTys, 2, 0)); - Circuit netOfGates; - FastModStub optimizer(&netOfGates); - optimizer.GenerateCircuit(); - netOfGates.PrintAllGates(); - auto cfg = Scheduler::Run(&netOfGates); - for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { - std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" - << std::endl; - for (size_t instIdex = cfg[bbIdx].size(); instIdex < 0; instIdex--) { - netOfGates.Print(cfg[bbIdx][instIdex - 1]); - } - } - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); - llvmBuilder.Build(); - LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); - assembler.Run(); - auto engine = assembler.GetEngine(); - auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); - - // test left, right are all integer - int x = 7; - int y = 3; - auto result = fn(JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData()); - JSTaggedValue expectRes = FastRuntimeStub::FastMod(JSTaggedValue(x), JSTaggedValue(y)); - EXPECT_EQ(result, expectRes); - - // test y == 0.0 || std::isnan(y) || std::isnan(x) || std::isinf(x) return NAN_VALUE - double x2 = 7.3; - int y2 = base::NAN_VALUE; - auto result2 = fn(JSTaggedValue(x2).GetRawData(), JSTaggedValue(y2).GetRawData()); - auto expectRes2 = FastRuntimeStub::FastMod(JSTaggedValue(x2), JSTaggedValue(y2)); - EXPECT_EQ(result2, expectRes2); - std::cout << "result2 for FastMod(7, 'helloworld') = " << result2.GetRawData() << std::endl; - std::cout << "expectRes2 for FastMod(7, 'helloworld') = " << expectRes2.GetRawData() << std::endl; - - // // test modular operation under normal conditions - double x3 = 33.0; - double y3 = 44.0; - auto result3 = fn(JSTaggedValue(x3).GetRawData(), JSTaggedValue(y3).GetRawData()); - auto expectRes3 = FastRuntimeStub::FastMod(JSTaggedValue(x3), JSTaggedValue(y3)); - EXPECT_EQ(result3, expectRes3); - - // test x == 0.0 || std::isinf(y) return x - double x4 = base::NAN_VALUE; - int y4 = 7; - auto result4 = fn(JSTaggedValue(x4).GetRawData(), JSTaggedValue(y4).GetRawData()); - auto expectRes4 = FastRuntimeStub::FastMod(JSTaggedValue(x4), JSTaggedValue(y4)); - - std::cout << "result4 for FastMod(base::NAN_VALUE, 7) = " << result4.GetRawData() << std::endl; - std::cout << "expectRes4 for FastMod(base::NAN_VALUE, 7) = " << expectRes4.GetRawData() << std::endl; - EXPECT_EQ(result4, expectRes4); - - // test all non-conforming conditions - int x5 = 7; - auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); - auto y5 = factory->NewFromStdString("hello world"); - auto result5 = fn(JSTaggedValue(x5).GetRawData(), y5.GetTaggedValue().GetRawData()); - EXPECT_EQ(result5, JSTaggedValue::Hole()); - auto expectRes5 = FastRuntimeStub::FastMod(JSTaggedValue(x5), y5.GetTaggedValue()); - std::cout << "result1 for FastMod(7, 'helloworld') = " << result5.GetRawData() << std::endl; - EXPECT_EQ(result5, expectRes5); -} } // namespace panda::test -- Gitee From 8f551973b8b2466a1b4caaf304389d4bc1a6e4d1 Mon Sep 17 00:00:00 2001 From: ding Date: Tue, 12 Oct 2021 16:57:22 +0800 Subject: [PATCH 019/115] add global record to IC Signed-off-by: ding --- ecmascript/ecma_vm.cpp | 3 +- ecmascript/ic/ic_runtime.cpp | 20 +++++++---- ecmascript/ic/profile_type_info.cpp | 6 ++++ ecmascript/ic/profile_type_info.h | 1 + ecmascript/interpreter/interpreter-inl.h | 2 +- ecmascript/interpreter/slow_runtime_stub.cpp | 35 ++++++++++++++------ 6 files changed, 48 insertions(+), 19 deletions(-) diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index fd4b50b..170156e 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -22,6 +22,7 @@ #include "ecmascript/class_linker/program_object-inl.h" #include "ecmascript/ecma_module.h" #include "ecmascript/ecma_string_table.h" +#include "ecmascript/global_dictionary.h" #include "ecmascript/global_env.h" #include "ecmascript/global_env_constants-inl.h" #include "ecmascript/global_env_constants.h" @@ -153,7 +154,7 @@ bool EcmaVM::Initialize() globalEnv->SetEmptyArray(thread_, factory_->NewEmptyArray()); globalEnv->SetEmptyLayoutInfo(thread_, factory_->CreateLayoutInfo(0)); globalEnv->SetRegisterSymbols(thread_, JSTaggedValue(SymbolTable::Create(thread_))); - globalEnv->SetGlobalRecord(thread_, JSTaggedValue(NameDictionary::Create(thread_))); + globalEnv->SetGlobalRecord(thread_, JSTaggedValue(GlobalDictionary::Create(thread_))); JSTaggedValue emptyStr = thread_->GlobalConstants()->GetEmptyString(); stringTable_->InternEmptyString(EcmaString::Cast(emptyStr.GetTaggedObject())); globalEnv->SetEmptyTaggedQueue(thread_, factory_->NewTaggedQueue(0)); diff --git a/ecmascript/ic/ic_runtime.cpp b/ecmascript/ic/ic_runtime.cpp index 33b3161..bac8bae 100644 --- a/ecmascript/ic/ic_runtime.cpp +++ b/ecmascript/ic/ic_runtime.cpp @@ -136,15 +136,18 @@ JSTaggedValue LoadICRuntime::LoadMiss(JSHandle receiver, JSHandle if (receiver->IsTypedArray() || !receiver->IsJSObject()) { return JSTaggedValue::GetProperty(thread_, receiver, key).GetValue().GetTaggedValue(); } - // 1. find from global record + + // global variable find from global record firstly if (GetICKind() == ICKind::NamedGlobalLoadIC) { bool found = false; - JSTaggedValue res = SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue(), &found); + JSTaggedValue box = SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue(), &found); if (found) { - return res; + ASSERT(box.IsPropertyBox()); + icAccessor_.AddGlobalRecordHandler(JSHandle(thread_, box)); + return PropertyBox::Cast(box.GetTaggedObject())->GetValue(); } } - // 2. find from global object + ObjectOperator op(GetThread(), receiver, key); auto result = JSHandle(thread_, JSObject::GetProperty(GetThread(), &op)); if (!op.IsFound() && GetICKind() == ICKind::NamedGlobalLoadIC) { @@ -176,18 +179,21 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle receiver, JSHand bool success = JSTaggedValue::SetProperty(GetThread(), receiver, key, value, true); return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); } - // 1. find from global record + + // global variable find from global record firstly if (GetICKind() == ICKind::NamedGlobalStoreIC) { bool found = false; - SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue(), &found); + JSTaggedValue box = SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue(), &found); if (found) { + ASSERT(box.IsPropertyBox()); SlowRuntimeStub::TryUpdateGlobalRecord(thread_, key.GetTaggedValue(), value.GetTaggedValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); + icAccessor_.AddGlobalRecordHandler(JSHandle(thread_, box)); return JSTaggedValue::Undefined(); } } UpdateReceiverHClass(JSHandle(GetThread(), JSHandle::Cast(receiver)->GetClass())); - // 2. find from global object + ObjectOperator op(GetThread(), receiver, key); bool success = JSObject::SetProperty(&op, value, true); if (!success && GetICKind() == ICKind::NamedGlobalStoreIC) { diff --git a/ecmascript/ic/profile_type_info.cpp b/ecmascript/ic/profile_type_info.cpp index 9091b89..6725d36 100644 --- a/ecmascript/ic/profile_type_info.cpp +++ b/ecmascript/ic/profile_type_info.cpp @@ -181,6 +181,12 @@ void ProfileTypeAccessor::AddGlobalHandlerKey(JSHandle key, JSHan profileTypeInfo_->Set(thread_, index, newArr.GetTaggedValue()); } +void ProfileTypeAccessor::AddGlobalRecordHandler(JSHandle handler) const +{ + uint32_t index = slotId_; + profileTypeInfo_->Set(thread_, index, handler.GetTaggedValue()); +} + void ProfileTypeAccessor::SetAsMega() const { profileTypeInfo_->Set(thread_, slotId_, JSTaggedValue::Hole()); diff --git a/ecmascript/ic/profile_type_info.h b/ecmascript/ic/profile_type_info.h index 3546a85..f7fecfe 100644 --- a/ecmascript/ic/profile_type_info.h +++ b/ecmascript/ic/profile_type_info.h @@ -116,6 +116,7 @@ public: void AddHandlerWithKey(JSHandle key, JSHandle dynclass, JSHandle handler) const; void AddGlobalHandlerKey(JSHandle key, JSHandle handler) const; + void AddGlobalRecordHandler(JSHandle handler) const; JSTaggedValue GetWeakRef(JSTaggedValue value) const { diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index a9232e5..462d952 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -2640,7 +2640,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool // order: 1. global record 2. global object JSTaggedValue result = SlowRuntimeStub::LdGlobalRecord(thread, prop, &found); if (found) { - SET_ACC(result); + SET_ACC(PropertyBox::Cast(result.GetTaggedObject())->GetValue()); } else { JSTaggedValue globalResult = FastRuntimeStub::GetGlobalOwnProperty(globalObj, prop, &found); if (found) { diff --git a/ecmascript/interpreter/slow_runtime_stub.cpp b/ecmascript/interpreter/slow_runtime_stub.cpp index 43f35cd..bf9106c 100644 --- a/ecmascript/interpreter/slow_runtime_stub.cpp +++ b/ecmascript/interpreter/slow_runtime_stub.cpp @@ -1380,16 +1380,21 @@ JSTaggedValue SlowRuntimeStub::TryUpdateGlobalRecord(JSThread *thread, JSTaggedV EcmaVM *vm = thread->GetEcmaVM(); JSHandle env = vm->GetGlobalEnv(); - NameDictionary *dict = NameDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); int entry = dict->FindEntry(prop); + ASSERT(entry != -1); + if (dict->GetAttributes(entry).IsConstProps()) { - return ThrowSyntaxError(thread, " const can not be modified"); + return ThrowSyntaxError(thread, "const variable can not be modified"); } - dict->UpdateValue(thread, entry, value); + + PropertyBox *box = dict->GetBox(entry); + box->SetValue(thread, value); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return JSTaggedValue::True(); } +// return box JSTaggedValue SlowRuntimeStub::LdGlobalRecord(JSThread *thread, JSTaggedValue key, bool *found) { INTERPRETER_TRACE(thread, LdGlobalRecord); @@ -1397,11 +1402,11 @@ JSTaggedValue SlowRuntimeStub::LdGlobalRecord(JSThread *thread, JSTaggedValue ke EcmaVM *vm = thread->GetEcmaVM(); JSHandle env = vm->GetGlobalEnv(); - NameDictionary *dict = NameDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); int entry = dict->FindEntry(key); if (entry != -1) { *found = true; - return dict->GetValue(entry); + return JSTaggedValue(dict->GetBox(entry)); } return JSTaggedValue::Undefined(); } @@ -1413,18 +1418,28 @@ JSTaggedValue SlowRuntimeStub::StGlobalRecord(JSThread *thread, JSTaggedValue pr EcmaVM *vm = thread->GetEcmaVM(); JSHandle env = vm->GetGlobalEnv(); - NameDictionary *dict = NameDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + // cross files global record name binding judgment int entry = dict->FindEntry(prop); if (entry != -1) { - return ThrowReferenceError(thread, prop, " is not defined"); + return ThrowSyntaxError(thread, "Duplicate identifier"); } + PropertyAttributes attributes; - attributes.SetIsConstProps(isConst); + if (isConst) { + attributes.SetIsConstProps(true); + } JSHandle propHandle(thread, prop); JSHandle valueHandle(thread, value); - JSHandle dictHandle(thread, dict); - dict->PutIfAbsent(thread, dictHandle, propHandle, valueHandle, attributes); + JSHandle dictHandle(thread, dict); + + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle box = factory->NewPropertyBox(valueHandle); + PropertyBoxType boxType = valueHandle->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT; + attributes.SetBoxType(boxType); + + dict->PutIfAbsent(thread, dictHandle, propHandle, JSHandle(box), attributes); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return JSTaggedValue::True(); } -- Gitee From 019c3026092b80c39c244f8a41037dcc0fc73e77 Mon Sep 17 00:00:00 2001 From: xliu Date: Tue, 12 Oct 2021 21:28:06 +0800 Subject: [PATCH 020/115] fixed Utf16ToUtf8Size Signed-off-by: xliu --- ecmascript/base/utf_helper.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ecmascript/base/utf_helper.cpp b/ecmascript/base/utf_helper.cpp index 25e0995..5cb168e 100644 --- a/ecmascript/base/utf_helper.cpp +++ b/ecmascript/base/utf_helper.cpp @@ -138,8 +138,14 @@ size_t Utf16ToUtf8Size(const uint16_t *utf16, uint32_t length, bool modify) } else if (utf16[i] < utf::HI_SURROGATE_MIN || utf16[i] > utf::HI_SURROGATE_MAX) { res += UtfLength::THREE; } else { - res += UtfLength::FOUR; - ++i; + if (i < length - 1 && + utf16[i + 1] >= utf::LO_SURROGATE_MIN && // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + utf16[i + 1] <= utf::LO_SURROGATE_MAX) { // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + res += UtfLength::FOUR; + ++i; + } else { + res += UtfLength::THREE; + } } } return res; -- Gitee From 707b17db883449feb671782fc5d53683492e12c3 Mon Sep 17 00:00:00 2001 From: Han00000000 Date: Wed, 13 Oct 2021 11:07:48 +0800 Subject: [PATCH 021/115] fix build gn Signed-off-by: Han00000000 Change-Id: I709d18bbfeb94c3c21b10c7887c7ec6f4812f196 --- BUILD.gn | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 9b9aa87..28f5d74 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -497,7 +497,10 @@ action("copy_resource_xml") { outputs = [ "$target_out_dir" ] } -ohos_copy("copy_asan_runtime") { - sources = [ "${asan_lib_path}/libclang_rt.asan-x86_64.a" ] - outputs = [ "${root_out_dir}/ark/ark_js_runtime/{{source_file_part}}" ] +if (is_debug && is_linux && (current_cpu == "x86" || current_cpu == "x64") && + run_with_asan) { + ohos_copy("copy_asan_runtime") { + sources = [ "${asan_lib_path}/libclang_rt.asan-x86_64.a" ] + outputs = [ "${root_out_dir}/ark/ark_js_runtime/{{source_file_part}}" ] + } } -- Gitee From c259d52c5f151f80ff7f6abc3908943e16fa7cba Mon Sep 17 00:00:00 2001 From: "yingguofeng@huawei.com" Date: Fri, 24 Sep 2021 14:31:54 +0800 Subject: [PATCH 022/115] Concurrent sweep Signed-off-by: yingguofeng@huawei.com Change-Id: I2a5a0172577971c96e156f99b5ccf1f6c3d0063c --- BUILD.gn | 4 + ecmascript/ecma_vm.cpp | 3 + ecmascript/hprof/heap_profiler.cpp | 2 + ecmascript/mem/allocator-inl.h | 55 ++++- ecmascript/mem/allocator.h | 15 +- ecmascript/mem/compress_collector.cpp | 63 +----- ecmascript/mem/compress_collector.h | 1 - ecmascript/mem/concurrent_sweeper.cpp | 247 +++++++++++++++++++++ ecmascript/mem/concurrent_sweeper.h | 93 ++++++++ ecmascript/mem/ecma_heap_manager-inl.h | 22 +- ecmascript/mem/ecma_heap_manager.cpp | 5 +- ecmascript/mem/ecma_heap_manager.h | 21 +- ecmascript/mem/free_object_kind.cpp | 3 + ecmascript/mem/free_object_kind.h | 5 +- ecmascript/mem/free_object_list.cpp | 114 ++++++---- ecmascript/mem/free_object_list.h | 20 +- ecmascript/mem/heap.cpp | 31 +-- ecmascript/mem/heap.h | 19 +- ecmascript/mem/old_space_collector-inl.h | 22 +- ecmascript/mem/old_space_collector.cpp | 125 ++++------- ecmascript/mem/old_space_collector.h | 21 +- ecmascript/mem/region.h | 36 ++- ecmascript/mem/semi_space_collector.cpp | 2 +- ecmascript/mem/semi_space_collector.h | 1 - ecmascript/mem/semi_space_worker.cpp | 29 +++ ecmascript/mem/semi_space_worker.h | 15 +- ecmascript/mem/space.cpp | 30 ++- ecmascript/mem/space.h | 12 +- ecmascript/mem/tlab_allocator-inl.h | 2 +- ecmascript/object_factory.cpp | 2 + ecmascript/platform/platform.cpp | 45 ++++ ecmascript/platform/platform.h | 59 +++++ ecmascript/platform/runner.cpp | 46 ++++ ecmascript/platform/runner.h | 48 ++++ ecmascript/platform/task.h | 32 +++ ecmascript/platform/task_queue.cpp | 50 +++++ ecmascript/platform/task_queue.h | 49 ++++ ecmascript/tests/BUILD.gn | 1 + ecmascript/tests/concurrent_sweep_test.cpp | 64 ++++++ 39 files changed, 1111 insertions(+), 303 deletions(-) create mode 100644 ecmascript/mem/concurrent_sweeper.cpp create mode 100644 ecmascript/mem/concurrent_sweeper.h create mode 100644 ecmascript/platform/platform.cpp create mode 100644 ecmascript/platform/platform.h create mode 100644 ecmascript/platform/runner.cpp create mode 100644 ecmascript/platform/runner.h create mode 100644 ecmascript/platform/task.h create mode 100644 ecmascript/platform/task_queue.cpp create mode 100644 ecmascript/platform/task_queue.h create mode 100644 ecmascript/tests/concurrent_sweep_test.cpp diff --git a/BUILD.gn b/BUILD.gn index 28f5d74..4b09033 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -338,6 +338,7 @@ ecma_source = [ "ecmascript/mem/c_string.cpp", "ecmascript/mem/chunk.cpp", "ecmascript/mem/compress_collector.cpp", + "ecmascript/mem/concurrent_sweeper.cpp", "ecmascript/mem/ecma_heap_manager.cpp", "ecmascript/mem/free_object_kind.cpp", "ecmascript/mem/free_object_list.cpp", @@ -355,6 +356,9 @@ ecma_source = [ "ecmascript/napi/jsnapi.cpp", "ecmascript/object_factory.cpp", "ecmascript/object_operator.cpp", + "ecmascript/platform/platform.cpp", + "ecmascript/platform/runner.cpp", + "ecmascript/platform/task_queue.cpp", "ecmascript/layout_info.cpp", "ecmascript/regexp/dyn_chunk.cpp", "ecmascript/regexp/regexp_executor.cpp", diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 170156e..e00c372 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -36,6 +36,7 @@ #include "ecmascript/mem/heap.h" #include "ecmascript/tagged_dictionary.h" #include "ecmascript/object_factory.h" +#include "ecmascript/platform/platform.h" #include "ecmascript/regexp/regexp_parser_cache.h" #include "ecmascript/runtime_call_id.h" #include "ecmascript/runtime_trampolines.h" @@ -117,6 +118,7 @@ EcmaVM::EcmaVM(RuntimeOptions options) bool EcmaVM::Initialize() { trace::ScopedTrace scoped_trace("EcmaVM::Initialize"); + Platform::GetCurrentPlatform()->Initialize(); RuntimeTrampolines::InitializeRuntimeTrampolines(thread_); @@ -232,6 +234,7 @@ bool EcmaVM::InitializeFinish() } EcmaVM::~EcmaVM() { + Platform::GetCurrentPlatform()->Destory(); vmInitialized_ = false; ClearNativeMethodsData(); diff --git a/ecmascript/hprof/heap_profiler.cpp b/ecmascript/hprof/heap_profiler.cpp index 42a3801..e2a8b34 100644 --- a/ecmascript/hprof/heap_profiler.cpp +++ b/ecmascript/hprof/heap_profiler.cpp @@ -23,6 +23,7 @@ #include "ecmascript/hprof/heap_snapshot.h" #include "ecmascript/js_thread.h" #include "ecmascript/mem/assert_scope-inl.h" +#include "ecmascript/mem/concurrent_sweeper.h" #include "ecmascript/mem/heap.h" namespace panda::ecmascript { @@ -161,6 +162,7 @@ HeapSnapShot *HeapProfiler::MakeHeapSnapShot(JSThread *thread, SampleType sample { LOG(ERROR, RUNTIME) << "HeapProfiler::MakeHeapSnapShot"; DISALLOW_GARBAGE_COLLECTION; + heap_->GetSweeper()->EnsureAllTaskFinish(); switch (sampleType) { case SampleType::ONE_SHOT: { auto *snapShot = const_cast(heap_->GetRegionFactory())->New(thread, heap_); diff --git a/ecmascript/mem/allocator-inl.h b/ecmascript/mem/allocator-inl.h index bf0d150..f9ddfe7 100644 --- a/ecmascript/mem/allocator-inl.h +++ b/ecmascript/mem/allocator-inl.h @@ -19,6 +19,7 @@ #include #include "ecmascript/mem/allocator.h" +#include "ecmascript/mem/concurrent_sweeper.h" #include "ecmascript/mem/heap-inl.h" #include "ecmascript/mem/space.h" #include "ecmascript/free_object.h" @@ -67,13 +68,13 @@ uintptr_t BumpPointerAllocator::Allocate(size_t size) return result; } -FreeListAllocator::FreeListAllocator(const Space *space) +FreeListAllocator::FreeListAllocator(const Space *space) : heap_(space->GetHeap()), type_(space->GetSpaceType()) { freeList_ = std::make_unique(); - heap_ = space->GetHeap(); uintptr_t begin = space->GetCurrentRegion()->GetBegin(); size_t size = space->GetCurrentRegion()->GetSize(); FreeObject::Cast(begin)->SetAvailable(size); + FreeObject::Cast(begin)->SetNext(nullptr); freeList_->Free(begin, size); } @@ -96,18 +97,39 @@ uintptr_t FreeListAllocator::Allocate(size_t size) } FreeObject *object = freeList_->Allocator(size); if (LIKELY(object != nullptr && !object->IsEmpty())) { - FreeBumpPoint(); - bpAllocator_.Reset(object->GetBegin(), object->GetEnd()); - ret = bpAllocator_.Allocate(size); - if (ret != 0 && bpAllocator_.Available() > 0) { - FreeObject::FillFreeObject(heap_->GetEcmaVM(), bpAllocator_.GetTop(), bpAllocator_.Available()); + return Allocate(object, size); + } + + if (sweeping_) { + // Concurrent sweep maybe sweep same region + heap_->GetSweeper()->FillSweptRegion(type_); + object = freeList_->Allocator(size); + if (LIKELY(object != nullptr && !object->IsEmpty())) { + return Allocate(object, size); + } + + // Parallel + heap_->GetSweeper()->WaitingTaskFinish(type_); + object = freeList_->Allocator(size); + if (LIKELY(object != nullptr && !object->IsEmpty())) { + return Allocate(object, size); } - return ret; } return 0; } +uintptr_t FreeListAllocator::Allocate(FreeObject *object, size_t size) +{ + FreeBumpPoint(); + bpAllocator_.Reset(object->GetBegin(), object->GetEnd()); + auto ret = bpAllocator_.Allocate(size); + if (ret != 0 && bpAllocator_.Available() > 0) { + FreeObject::FillFreeObject(heap_->GetEcmaVM(), bpAllocator_.GetTop(), bpAllocator_.Available()); + } + return ret; +} + void FreeListAllocator::FreeBumpPoint() { auto begin = bpAllocator_.GetTop(); @@ -116,7 +138,7 @@ void FreeListAllocator::FreeBumpPoint() bpAllocator_.Reset(); } -void FreeListAllocator::Free(uintptr_t begin, uintptr_t end) +void FreeListAllocator::Free(uintptr_t begin, uintptr_t end, bool isAdd) { ASSERT(heap_ != nullptr); size_t size = end - begin; @@ -125,7 +147,7 @@ void FreeListAllocator::Free(uintptr_t begin, uintptr_t end) } FreeObject::FillFreeObject(heap_->GetEcmaVM(), begin, size); - freeList_->Free(begin, static_cast(end - begin)); + freeList_->Free(begin, size, isAdd); } void FreeListAllocator::RebuildFreeList() @@ -133,5 +155,18 @@ void FreeListAllocator::RebuildFreeList() bpAllocator_.Reset(); freeList_->Rebuild(); } + +void FreeListAllocator::FillFreeList(FreeObjectKind *kind) +{ + freeList_->AddKind(kind); +} + +size_t FreeListAllocator::GetAvailableSize() const +{ + if (sweeping_) { + heap_->GetSweeper()->WaitingTaskFinish(type_); + } + return freeList_->GetFreeObjectSize(); +} } // namespace panda::ecmascript #endif // ECMASCRIPT_MEM_ALLOCATOR_INL_H diff --git a/ecmascript/mem/allocator.h b/ecmascript/mem/allocator.h index 25b3d3d..0ea0cf0 100644 --- a/ecmascript/mem/allocator.h +++ b/ecmascript/mem/allocator.h @@ -91,28 +91,37 @@ public: inline void AddFree(Region *region); inline void RebuildFreeList(); + inline void FillFreeList(FreeObjectKind *kind); void Swap(FreeListAllocator &other) { heap_ = other.heap_; bpAllocator_.Swap(other.bpAllocator_); freeList_.swap(other.freeList_); + type_ = other.type_; + sweeping_ = other.sweeping_; } inline void FreeBumpPoint(); - inline void Free(uintptr_t begin, uintptr_t end); + inline void Free(uintptr_t begin, uintptr_t end, bool isAdd = true); inline void SplitFreeObject(FreeObject *current, size_t allocateSize); - size_t GetAvailableSize() const + inline size_t GetAvailableSize() const; + + void SetSweeping(bool sweeping) { - return freeList_->GetFreeObjectSize(); + sweeping_ = sweeping; } private: + inline uintptr_t Allocate(FreeObject *object, size_t size); + BumpPointerAllocator bpAllocator_; std::unique_ptr freeList_; Heap *heap_{nullptr}; + MemSpaceType type_ = OLD_SPACE; + bool sweeping_ = false; }; } // namespace panda::ecmascript diff --git a/ecmascript/mem/compress_collector.cpp b/ecmascript/mem/compress_collector.cpp index db37595..8fd14bb 100644 --- a/ecmascript/mem/compress_collector.cpp +++ b/ecmascript/mem/compress_collector.cpp @@ -13,9 +13,10 @@ * limitations under the License. */ +#include "ecmascript/mem/compress_collector.h" + #include "ecmascript/ecma_vm.h" #include "ecmascript/mem/clock_scope.h" -#include "ecmascript/mem/compress_collector.h" #include "ecmascript/mem/compress_gc_marker-inl.h" #include "ecmascript/mem/ecma_heap_manager.h" #include "ecmascript/mem/heap-inl.h" @@ -58,6 +59,7 @@ void CompressCollector::RunPhases() void CompressCollector::InitializePhase() { heap_->GetThreadPool()->WaitTaskFinish(); + heap_->GetSweeper()->EnsureAllTaskFinish(); auto compressSpace = const_cast(heap_->GetCompressSpace()); if (compressSpace->GetCommittedSize() == 0) { compressSpace->Initialize(); @@ -70,8 +72,6 @@ void CompressCollector::InitializePhase() FreeListAllocator compressAllocator(compressSpace); oldSpaceAllocator_.Swap(compressAllocator); fromSpaceAllocator_.Reset(fromSpace); - auto heapManager = heap_->GetHeapManager(); - nonMovableAllocator_.Swap(heapManager->GetNonMovableSpaceAllocator()); auto callback = [](Region *current) { // ensure mark bitmap @@ -87,6 +87,7 @@ void CompressCollector::InitializePhase() } }; heap_->GetNonMovableSpace()->EnumerateRegions(callback); + heap_->GetMachineCodeSpace()->EnumerateRegions(callback); heap_->GetSnapShotSpace()->EnumerateRegions(callback); heap_->GetHugeObjectSpace()->EnumerateRegions(callback); @@ -116,7 +117,6 @@ void CompressCollector::FinishPhase() workList_->Finish(youngAndOldAliveSize_); auto heapManager = heap_->GetHeapManager(); heapManager->GetOldSpaceAllocator().Swap(oldSpaceAllocator_); - heapManager->GetNonMovableSpaceAllocator().Swap(nonMovableAllocator_); heapManager->GetNewSpaceAllocator().Swap(fromSpaceAllocator_); } @@ -230,60 +230,7 @@ void CompressCollector::SweepPhases() heap_->GetEcmaVM()->GetJSThread()->IterateWeakEcmaGlobalStorage(gcUpdateWeak); heap_->GetEcmaVM()->ProcessReferences(gcUpdateWeak); - SweepSpace(const_cast(heap_->GetNonMovableSpace()), nonMovableAllocator_); - SweepSpace(const_cast(heap_->GetHugeObjectSpace())); -} - -void CompressCollector::SweepSpace(HugeObjectSpace *space) -{ - Region *currentRegion = space->GetRegionList().GetFirst(); - while (currentRegion != nullptr) { - Region *next = currentRegion->GetNext(); - auto markBitmap = currentRegion->GetMarkBitmap(); - bool isMarked = false; - markBitmap->IterateOverMarkedChunks([&isMarked]([[maybe_unused]] void *mem) { isMarked = true; }); - if (!isMarked) { - space->GetRegionList().RemoveNode(currentRegion); - space->ClearAndFreeRegion(currentRegion); - } - currentRegion = next; - } -} - -void CompressCollector::SweepSpace(Space *space, FreeListAllocator &allocator) -{ - allocator.RebuildFreeList(); - space->EnumerateRegions([this, &allocator](Region *current) { - auto markBitmap = current->GetMarkBitmap(); - ASSERT(markBitmap != nullptr); - uintptr_t freeStart = current->GetBegin(); - markBitmap->IterateOverMarkedChunks([this, ¤t, &freeStart, &allocator](void *mem) { - ASSERT(current->InRange(ToUintPtr(mem))); - auto header = reinterpret_cast(mem); - auto klass = header->GetClass(); - JSType jsType = klass->GetObjectType(); - auto size = klass->SizeFromJSHClass(jsType, header); - size = AlignUp(size, static_cast(MemAlignment::MEM_ALIGN_OBJECT)); - - uintptr_t freeEnd = ToUintPtr(mem); - if (freeStart != freeEnd) { - FreeLiveRange(allocator, current, freeStart, freeEnd); - } - freeStart = freeEnd + size; - }); - uintptr_t freeEnd = current->GetEnd(); - if (freeStart != freeEnd) { - FreeLiveRange(allocator, current, freeStart, freeEnd); - } - }); -} - -void CompressCollector::FreeLiveRange(FreeListAllocator &allocator, Region *current, uintptr_t freeStart, - uintptr_t freeEnd) -{ - allocator.Free(freeStart, freeEnd); - nonMoveSpaceFreeSize_ += freeEnd - freeStart; - heap_->ClearSlotsRange(current, freeStart, freeEnd); + heap_->GetSweeper()->SweepPhases(true); } uintptr_t CompressCollector::AllocateOld(size_t size) diff --git a/ecmascript/mem/compress_collector.h b/ecmascript/mem/compress_collector.h index 535a3f4..8cfb405 100644 --- a/ecmascript/mem/compress_collector.h +++ b/ecmascript/mem/compress_collector.h @@ -61,7 +61,6 @@ private: os::memory::Mutex mtx_; BumpPointerAllocator fromSpaceAllocator_{}; FreeListAllocator oldSpaceAllocator_{}; - FreeListAllocator nonMovableAllocator_{}; size_t youngAndOldAliveSize_ = 0; size_t nonMoveSpaceFreeSize_ = 0; diff --git a/ecmascript/mem/concurrent_sweeper.cpp b/ecmascript/mem/concurrent_sweeper.cpp new file mode 100644 index 0000000..5906885 --- /dev/null +++ b/ecmascript/mem/concurrent_sweeper.cpp @@ -0,0 +1,247 @@ +/* + * 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/mem/concurrent_sweeper.h" + +#include "ecmascript/js_hclass-inl.h" +#include "ecmascript/mem/allocator-inl.h" +#include "ecmascript/mem/ecma_heap_manager.h" +#include "ecmascript/mem/free_object_list.h" +#include "ecmascript/mem/heap.h" +#include "ecmascript/platform/platform.h" + +namespace panda::ecmascript { +ConcurrentSweeper::ConcurrentSweeper(Heap *heap, bool concurrentSweep) + : heap_(heap), concurrentSweep_(concurrentSweep) +{ +} + +void ConcurrentSweeper::SweepPhases(bool compressGC) +{ + if (concurrentSweep_) { + // Add all region to region list. Ensure all task finish + trace::ScopedTrace scoped_trace("ConcurrentSweeper::SweepPhases"); + if (!compressGC) { + heap_->GetOldSpace()->EnumerateRegions([this](Region *current) { AddRegion(OLD_SPACE, current); }); + } + heap_->GetNonMovableSpace()->EnumerateRegions([this](Region *current) { AddRegion(NON_MOVABLE, current); }); + heap_->GetMachineCodeSpace()->EnumerateRegions([this](Region *current) { + AddRegion(MACHINE_CODE_SPACE, current); + }); + + // Prepare + isSweeping_ = true; + startSpaceType_ = compressGC ? NON_MOVABLE : OLD_SPACE; + for (int type = startSpaceType_; type < FREE_LIST_NUM; type++) { + auto spaceType = static_cast(type); + FreeListAllocator &allocator = heap_->GetHeapManager()->GetFreeListAllocator(spaceType); + remainderTaskNum_[type] = FREE_LIST_NUM - startSpaceType_; + allocator.SetSweeping(true); + allocator.RebuildFreeList(); + } + + if (!compressGC) { + Platform::GetCurrentPlatform()->PostTask(std::make_unique(this, OLD_SPACE)); + } + Platform::GetCurrentPlatform()->PostTask(std::make_unique(this, NON_MOVABLE)); + Platform::GetCurrentPlatform()->PostTask(std::make_unique(this, MACHINE_CODE_SPACE)); + } else { + if (!compressGC) { + SweepSpace(const_cast(heap_->GetOldSpace()), heap_->GetHeapManager()->GetOldSpaceAllocator()); + } + SweepSpace(const_cast(heap_->GetNonMovableSpace()), + heap_->GetHeapManager()->GetNonMovableSpaceAllocator()); + SweepSpace(const_cast(heap_->GetMachineCodeSpace()), + heap_->GetHeapManager()->GetMachineCodeSpaceAllocator()); + } + SweepHugeSpace(); +} + +void ConcurrentSweeper::SweepSpace(MemSpaceType type, bool isMain) +{ + trace::ScopedTrace scoped_trace("Sweeper::SweepSpace"); + FreeListAllocator &allocator = heap_->GetHeapManager()->GetFreeListAllocator(type); + Region *current = GetRegionSafe(type); + while (current != nullptr) { + FreeRegion(current, allocator, isMain); + // Main thread sweeping region is added; + if (!isMain) { + AddSweptRegionSafe(type, current); + } + current = GetRegionSafe(type); + } + + if (!isMain) { + os::memory::LockHolder holder(mutexs_[type]); + remainderTaskNum_[type]--; + if (remainderTaskNum_[type] == 0) { + cvs_[type].SignalAll(); + } + } +} + +void ConcurrentSweeper::SweepSpace(Space *space, FreeListAllocator &allocator) +{ + allocator.RebuildFreeList(); + space->EnumerateRegions([this, &allocator](Region *current) { FreeRegion(current, allocator); }); +} + +void ConcurrentSweeper::SweepHugeSpace() +{ + trace::ScopedTrace scoped_trace("SweepSpace HugeObject"); + HugeObjectSpace *space = const_cast(heap_->GetHugeObjectSpace()); + Region *currentRegion = space->GetRegionList().GetFirst(); + + while (currentRegion != nullptr) { + Region *next = currentRegion->GetNext(); + auto markBitmap = currentRegion->GetMarkBitmap(); + bool isMarked = false; + markBitmap->IterateOverMarkedChunks([&isMarked]([[maybe_unused]] void *mem) { isMarked = true; }); + if (!isMarked) { + space->GetRegionList().RemoveNode(currentRegion); + space->ClearAndFreeRegion(currentRegion); + } + currentRegion = next; + } +} + +void ConcurrentSweeper::FreeRegion(Region *current, FreeListAllocator &allocator, bool isMain) +{ + auto markBitmap = current->GetMarkBitmap(); + ASSERT(markBitmap != nullptr); + uintptr_t freeStart = current->GetBegin(); + markBitmap->IterateOverMarkedChunks([this, ¤t, &freeStart, &allocator, isMain](void *mem) { + ASSERT(current->InRange(ToUintPtr(mem))); + auto header = reinterpret_cast(mem); + auto klass = header->GetClass(); + JSType jsType = klass->GetObjectType(); + auto size = klass->SizeFromJSHClass(jsType, header); + size = AlignUp(size, static_cast(MemAlignment::MEM_ALIGN_OBJECT)); + + uintptr_t freeEnd = ToUintPtr(mem); + if (freeStart != freeEnd) { + FreeLiveRange(allocator, current, freeStart, freeEnd, isMain); + } + freeStart = freeEnd + size; + }); + uintptr_t freeEnd = current->GetEnd(); + if (freeStart != freeEnd) { + FreeLiveRange(allocator, current, freeStart, freeEnd, isMain); + } +} + +void ConcurrentSweeper::FillSweptRegion(MemSpaceType type) +{ + trace::ScopedTrace scoped_trace("Sweeper::FillSweptRegion"); + if (sweptList_[type].empty()) { + return; + } + FreeListAllocator &allocator = heap_->GetHeapManager()->GetFreeListAllocator(type); + Region *region = nullptr; + while ((region = GetSweptRegionSafe(type)) != nullptr) { + region->EnumerateKinds([&allocator](FreeObjectKind *kind) { + if (kind == nullptr || kind->Empty()) { + return; + } + allocator.FillFreeList(kind); + }); + } +} + +void ConcurrentSweeper::FreeLiveRange(FreeListAllocator &allocator, Region *current, uintptr_t freeStart, + uintptr_t freeEnd, bool isMain) +{ + allocator.Free(freeStart, freeEnd, isMain); + heap_->ClearSlotsRange(current, freeStart, freeEnd); +} + +void ConcurrentSweeper::AddRegion(MemSpaceType type, Region *region) +{ + sweepingList_[type].emplace_back(region); +} + +Region *ConcurrentSweeper::GetRegionSafe(MemSpaceType type) +{ + os::memory::LockHolder holder(mutexs_[type]); + Region *region = nullptr; + if (!sweepingList_[type].empty()) { + region = sweepingList_[type].back(); + sweepingList_[type].pop_back(); + } + return region; +} + +void ConcurrentSweeper::AddSweptRegionSafe(MemSpaceType type, Region *region) +{ + os::memory::LockHolder holder(mutexs_[type]); + sweptList_[type].emplace_back(region); +} + +Region *ConcurrentSweeper::GetSweptRegionSafe(MemSpaceType type) +{ + os::memory::LockHolder holder(mutexs_[type]); + Region *region = nullptr; + if (!sweptList_[type].empty()) { + region = sweptList_[type].back(); + sweptList_[type].pop_back(); + } + return region; +} + +void ConcurrentSweeper::EnsureAllTaskFinish() +{ + if (!isSweeping_) { + return; + } + for (int i = startSpaceType_; i < FREE_LIST_NUM; i++) { + WaitingTaskFinish(static_cast(i)); + } + isSweeping_ = false; +} + +void ConcurrentSweeper::WaitingTaskFinish(MemSpaceType type) +{ + if (remainderTaskNum_[type] > 0) { + SweepSpace(type); + { + os::memory::LockHolder holder(mutexs_[type]); + while (remainderTaskNum_[type] > 0) { + cvs_[type].Wait(&mutexs_[type]); + } + } + } + FinishSweeping(type); +} + +void ConcurrentSweeper::FinishSweeping(MemSpaceType type) +{ + FillSweptRegion(type); + FreeListAllocator &allocator = heap_->GetHeapManager()->GetFreeListAllocator(type); + allocator.SetSweeping(false); + if (type == OLD_SPACE) { + heap_->RecomputeLimits(); + } +} + +bool ConcurrentSweeper::SweeperTask::Run() +{ + int sweepTypeNum = FREE_LIST_NUM - sweeper_->startSpaceType_; + for (size_t i = sweeper_->startSpaceType_; i < FREE_LIST_NUM; i++) { + auto type = static_cast(((i + type_) % sweepTypeNum) + sweeper_->startSpaceType_); + sweeper_->SweepSpace(type, false); + } + return true; +} +} // namespace panda::ecmascript diff --git a/ecmascript/mem/concurrent_sweeper.h b/ecmascript/mem/concurrent_sweeper.h new file mode 100644 index 0000000..b24b5a6 --- /dev/null +++ b/ecmascript/mem/concurrent_sweeper.h @@ -0,0 +1,93 @@ +/* + * 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_MEM_CONCURRENT_SWEEPER_H +#define ECMASCRIPT_MEM_CONCURRENT_SWEEPER_H + +#include +#include + +#include "ecmascript/mem/space.h" +#include "ecmascript/platform/task.h" +#include "os/mutex.h" + +namespace panda::ecmascript { +class FreeListAllocator; + +class ConcurrentSweeper { +public: + ConcurrentSweeper(Heap *heap, bool concurrentSweep); + ~ConcurrentSweeper() = default; + + NO_COPY_SEMANTIC(ConcurrentSweeper); + NO_MOVE_SEMANTIC(ConcurrentSweeper); + + void SweepPhases(bool compressGC = false); + + void EnsureAllTaskFinish(); + // Ensure task finish + void WaitingTaskFinish(MemSpaceType type); + + void FillSweptRegion(MemSpaceType type); + + bool IsConcurrentSweepEnabled() + { + return concurrentSweep_; + } + +private: + class SweeperTask : public Task { + public: + SweeperTask(ConcurrentSweeper *sweeper, MemSpaceType type) : sweeper_(sweeper), type_(type) {}; + ~SweeperTask() override = default; + bool Run() override; + + NO_COPY_SEMANTIC(SweeperTask); + NO_MOVE_SEMANTIC(SweeperTask); + + private: + ConcurrentSweeper *sweeper_; + MemSpaceType type_; + }; + + void SweepSpace(MemSpaceType type, bool isMain = true); + void SweepSpace(Space *space, FreeListAllocator &allocator); + void SweepHugeSpace(); + void FinishSweeping(MemSpaceType type); + + void FreeRegion(Region *current, FreeListAllocator &allocator, bool isMain = true); + void FreeLiveRange(FreeListAllocator &allocator, Region *current, uintptr_t freeStart, uintptr_t freeEnd, + bool isMain); + + void AddRegion(MemSpaceType type, Region *region); + Region *GetRegionSafe(MemSpaceType type); + + void AddSweptRegionSafe(MemSpaceType type, Region *region); + Region *GetSweptRegionSafe(MemSpaceType type); + + std::array mutexs_; + std::array cvs_; + std::array remainderTaskNum_ = {0, 0, 0}; + + std::array, FREE_LIST_NUM> sweepingList_; + std::array, FREE_LIST_NUM> sweptList_; + + Heap *heap_; + bool concurrentSweep_ = false; + bool isSweeping_ = false; + MemSpaceType startSpaceType_ = MemSpaceType::OLD_SPACE; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_MEM_CONCURRENT_SWEEPER_H diff --git a/ecmascript/mem/ecma_heap_manager-inl.h b/ecmascript/mem/ecma_heap_manager-inl.h index 4b65d6c..8b9f0e1 100644 --- a/ecmascript/mem/ecma_heap_manager-inl.h +++ b/ecmascript/mem/ecma_heap_manager-inl.h @@ -83,18 +83,18 @@ TaggedObject *EcmaHeapManager::AllocateNonMovableOrHugeObject(JSHClass *hclass, if (size > MAX_REGULAR_HEAP_OBJECT_SIZE) { return AllocateHugeObject(hclass, size); } - auto object = reinterpret_cast(nonMovableAllocator_.Allocate(size)); + auto object = reinterpret_cast(GetNonMovableSpaceAllocator().Allocate(size)); if (UNLIKELY(object == nullptr)) { if (heap_->CheckAndTriggerNonMovableGC()) { - object = reinterpret_cast(nonMovableAllocator_.Allocate(size)); + object = reinterpret_cast(GetNonMovableSpaceAllocator().Allocate(size)); } if (UNLIKELY(object == nullptr)) { // hclass must be nonmovable - if (!heap_->FillNonMovableSpaceAndTryGC(&nonMovableAllocator_)) { + if (!heap_->FillNonMovableSpaceAndTryGC(&GetNonMovableSpaceAllocator())) { LOG_ECMA_MEM(FATAL) << "OOM : extend failed"; UNREACHABLE(); } - object = reinterpret_cast(nonMovableAllocator_.Allocate(size)); + object = reinterpret_cast(GetNonMovableSpaceAllocator().Allocate(size)); if (UNLIKELY(object == nullptr)) { heap_->ThrowOutOfMemoryError(size); UNREACHABLE(); @@ -140,18 +140,18 @@ TaggedObject *EcmaHeapManager::AllocateOldGenerationOrHugeObject(JSHClass *hclas if (size > MAX_REGULAR_HEAP_OBJECT_SIZE) { return AllocateHugeObject(hclass, size); } - auto object = reinterpret_cast(oldSpaceAllocator_.Allocate(size)); + auto object = reinterpret_cast(GetOldSpaceAllocator().Allocate(size)); if (UNLIKELY(object == nullptr)) { if (heap_->CheckAndTriggerOldGC()) { - object = reinterpret_cast(oldSpaceAllocator_.Allocate(size)); + object = reinterpret_cast(GetOldSpaceAllocator().Allocate(size)); } if (UNLIKELY(object == nullptr)) { // hclass must nonmovable - if (!heap_->FillOldSpaceAndTryGC(&oldSpaceAllocator_)) { + if (!heap_->FillOldSpaceAndTryGC(&GetOldSpaceAllocator())) { LOG_ECMA_MEM(FATAL) << "OOM : extend failed"; UNREACHABLE(); } - object = reinterpret_cast(oldSpaceAllocator_.Allocate(size)); + object = reinterpret_cast(GetOldSpaceAllocator().Allocate(size)); if (UNLIKELY(object == nullptr)) { heap_->ThrowOutOfMemoryError(size); UNREACHABLE(); @@ -186,12 +186,12 @@ TaggedObject *EcmaHeapManager::AllocateHugeObject(JSHClass *hclass, size_t size) TaggedObject *EcmaHeapManager::AllocateMachineCodeSpaceObject(JSHClass *hclass, size_t size) { - auto object = reinterpret_cast(machineCodeSpaceAllocator_.Allocate(size)); + auto object = reinterpret_cast(GetMachineCodeSpaceAllocator().Allocate(size)); if (UNLIKELY(object == nullptr)) { - if (!heap_->FillMachineCodeSpaceAndTryGC(&machineCodeSpaceAllocator_)) { + if (!heap_->FillMachineCodeSpaceAndTryGC(&GetMachineCodeSpaceAllocator())) { return nullptr; } - object = reinterpret_cast(machineCodeSpaceAllocator_.Allocate(size)); + object = reinterpret_cast(GetMachineCodeSpaceAllocator().Allocate(size)); if (UNLIKELY(object == nullptr)) { heap_->ThrowOutOfMemoryError(size); return nullptr; diff --git a/ecmascript/mem/ecma_heap_manager.cpp b/ecmascript/mem/ecma_heap_manager.cpp index ea3d0b9..4314882 100644 --- a/ecmascript/mem/ecma_heap_manager.cpp +++ b/ecmascript/mem/ecma_heap_manager.cpp @@ -20,9 +20,8 @@ namespace panda::ecmascript { EcmaHeapManager::EcmaHeapManager(Heap *heap) : heap_(heap), newSpaceAllocator_(heap->GetNewSpace()), - nonMovableAllocator_(heap->GetNonMovableSpace()), - oldSpaceAllocator_(heap->GetOldSpace()), - machineCodeSpaceAllocator_(heap->GetMachineCodeSpace()) + freeListAllocator_ { FreeListAllocator(heap->GetOldSpace()), FreeListAllocator(heap_->GetNonMovableSpace()), + FreeListAllocator(heap->GetMachineCodeSpace()) } { ASSERT(heap != nullptr); heap->SetHeapManager(this); diff --git a/ecmascript/mem/ecma_heap_manager.h b/ecmascript/mem/ecma_heap_manager.h index 6bfd120..82ec7bc 100644 --- a/ecmascript/mem/ecma_heap_manager.h +++ b/ecmascript/mem/ecma_heap_manager.h @@ -48,9 +48,14 @@ public: return heap_; } - FreeListAllocator &GetOldSpaceAllocator() + FreeListAllocator &GetFreeListAllocator(MemSpaceType type) { - return oldSpaceAllocator_; + return freeListAllocator_[type]; + } + + inline FreeListAllocator &GetOldSpaceAllocator() + { + return freeListAllocator_[OLD_SPACE]; } BumpPointerAllocator &GetNewSpaceAllocator() @@ -58,9 +63,9 @@ public: return newSpaceAllocator_; } - FreeListAllocator &GetNonMovableSpaceAllocator() + inline FreeListAllocator &GetNonMovableSpaceAllocator() { - return nonMovableAllocator_; + return freeListAllocator_[NON_MOVABLE]; } const BumpPointerAllocator &GetSnapShotSpaceAllocator() const @@ -68,18 +73,16 @@ public: return snapshotSpaceAllocator_; } - FreeListAllocator &GetMachineCodeSpaceAllocator() + inline FreeListAllocator &GetMachineCodeSpaceAllocator() { - return machineCodeSpaceAllocator_; + return freeListAllocator_[MACHINE_CODE_SPACE]; } private: Heap *heap_{nullptr}; BumpPointerAllocator newSpaceAllocator_; - FreeListAllocator nonMovableAllocator_; - FreeListAllocator oldSpaceAllocator_; + std::array freeListAllocator_; BumpPointerAllocator snapshotSpaceAllocator_; - FreeListAllocator machineCodeSpaceAllocator_; }; } // namespace panda::ecmascript diff --git a/ecmascript/mem/free_object_kind.cpp b/ecmascript/mem/free_object_kind.cpp index 951871f..94829d6 100644 --- a/ecmascript/mem/free_object_kind.cpp +++ b/ecmascript/mem/free_object_kind.cpp @@ -31,6 +31,9 @@ void FreeObjectKind::Rebuild() { freeObject_ = nullptr; available_ = 0; + isAdded_ = false; + next_ = nullptr; + prev_ = nullptr; } FreeObject *FreeObjectKind::SearchSmallFreeObject(size_t size) diff --git a/ecmascript/mem/free_object_kind.h b/ecmascript/mem/free_object_kind.h index 869689c..057968a 100644 --- a/ecmascript/mem/free_object_kind.h +++ b/ecmascript/mem/free_object_kind.h @@ -27,9 +27,9 @@ class FreeObject; class FreeObjectKind { public: - FreeObjectKind(KindType type, uintptr_t begin, size_t size) : kindType_(type) + FreeObjectKind(KindType type) : kindType_(type) { - Free(begin, size); + Rebuild(); } ~FreeObjectKind() = default; @@ -60,6 +60,7 @@ private: FreeObjectKind *prev_ = nullptr; KindType kindType_ = INVALID_KIND_TYPE; size_t available_ = 0; + bool isAdded_ = false; FreeObject *freeObject_ = nullptr; friend class FreeObjectList; diff --git a/ecmascript/mem/free_object_list.cpp b/ecmascript/mem/free_object_list.cpp index 43e220f..e25e288 100644 --- a/ecmascript/mem/free_object_list.cpp +++ b/ecmascript/mem/free_object_list.cpp @@ -20,17 +20,16 @@ #include "ecmascript/mem/mem.h" namespace panda::ecmascript { -FreeObjectList::FreeObjectList() +FreeObjectList::FreeObjectList() : kinds_(new FreeObjectKind *[NUMBER_OF_KINDS](), NUMBER_OF_KINDS) { - kinds_ = Span(new FreeObjectKind *[NUMBER_OF_KINDS](), NUMBER_OF_KINDS); + for (int i = 0; i < NUMBER_OF_KINDS; i++) { + kinds_[i] = nullptr; + } noneEmptyKindBitMap_ = 0; } FreeObjectList::~FreeObjectList() { - for (auto it : kinds_) { - delete it; - } delete[] kinds_.data(); noneEmptyKindBitMap_ = 0; } @@ -49,33 +48,39 @@ FreeObject *FreeObjectList::Allocator(size_t size) KindType lastType = type - 1; for (type = CalcNextNoneEmptyIndex(type); type > lastType && type < NUMBER_OF_KINDS; - type = CalcNextNoneEmptyIndex(type + 1)) { + type = CalcNextNoneEmptyIndex(type + 1)) { lastType = type; - FreeObjectKind *top = kinds_[type]; - if (top == nullptr || top->Available() < size) { - continue; - } - FreeObject *current = nullptr; - if (type <= SMALL_KIND_MAX_INDEX) { - current = top->SearchSmallFreeObject(size); - } else { - current = top->SearchLargeFreeObject(size); - } - if (top->Empty()) { - RemoveKind(top); - } - if (current != nullptr) { - size_t currentSize = current->Available(); - available_ -= currentSize; - if (currentSize >= size) { - return current; + FreeObjectKind *current = kinds_[type]; + while (current != nullptr) { + if (current->Available() < size) { + current = current->next_; + continue; } + FreeObjectKind *next = nullptr; + FreeObject *object = nullptr; + if (type <= SMALL_KIND_MAX_INDEX) { + object = current->SearchSmallFreeObject(size); + } else { + next = current->next_; + object = current->SearchLargeFreeObject(size); + } + if (current->Empty()) { + RemoveKind(current); + } + if (object != nullptr) { + size_t objectSize = object->Available(); + available_ -= objectSize; + if (objectSize >= size) { + return object; + } + } + current = next; } } return nullptr; } -void FreeObjectList::Free(uintptr_t start, size_t size) +void FreeObjectList::Free(uintptr_t start, size_t size, bool isAdd) { if (start == 0 || size == 0) { return; @@ -86,26 +91,28 @@ void FreeObjectList::Free(uintptr_t start, size_t size) return; } - auto kind = kinds_[type]; + Region *region = Region::ObjectAddressToRange(reinterpret_cast(start)); + auto kind = region->GetFreeObjectKind(type); if (kind == nullptr) { - kind = new FreeObjectKind(type, start, size); - if (!AddKind(kind)) { - delete kind; - return; + LOG_ECMA(FATAL) << "The kind of region is nullptr"; + return; + } + kind->Free(start, size); + + if (isAdd) { + if (kind->isAdded_) { + available_ += size; + } else { + AddKind(kind); } - } else { - kind->Free(start, size); } - available_ += size; } void FreeObjectList::Rebuild() { - for (auto kind : kinds_) { - if (kind != nullptr) { - kind->Rebuild(); - RemoveKind(kind); - } + EnumerateKinds([](FreeObjectKind *kind) { kind->Rebuild(); }); + for (int i = 0; i < NUMBER_OF_KINDS; i++) { + kinds_[i] = nullptr; } available_ = 0; noneEmptyKindBitMap_ = 0; @@ -118,20 +125,22 @@ size_t FreeObjectList::GetFreeObjectSize() const bool FreeObjectList::AddKind(FreeObjectKind *kind) { - if (kind == nullptr || kind->Empty()) { + if (kind == nullptr || kind->Empty() || kind->isAdded_) { return false; } KindType type = kind->kindType_; FreeObjectKind *top = kinds_[type]; if (kind == top) { - return true; + return false; } if (top != nullptr) { top->prev_ = kind; } + kind->isAdded_ = true; kind->next_ = top; kinds_[type] = kind; SetNoneEmptyBit(type); + available_ += kind->Available(); return true; } @@ -151,11 +160,30 @@ void FreeObjectList::RemoveKind(FreeObjectKind *kind) if (kind->next_ != nullptr) { kind->next_->prev_ = kind->prev_; } - kind->prev_ = nullptr; - kind->next_ = nullptr; if (kinds_[type] == nullptr) { ClearNoneEmptyBit(type); } - delete kind; + available_ -= kind->Available(); + kind->Rebuild(); +} + +template +void FreeObjectList::EnumerateKinds(const Callback &cb) const +{ + for (KindType i = 0; i < NUMBER_OF_KINDS; i++) { + EnumerateKinds(i, cb); + } +} + +template +void FreeObjectList::EnumerateKinds(KindType type, const Callback &cb) const +{ + FreeObjectKind *current = kinds_[type]; + while (current != nullptr) { + // maybe reset + FreeObjectKind *next = current->next_; + cb(current); + current = next; + } } } // namespace panda::ecmascript diff --git a/ecmascript/mem/free_object_list.h b/ecmascript/mem/free_object_list.h index c7db111..553dd5d 100644 --- a/ecmascript/mem/free_object_list.h +++ b/ecmascript/mem/free_object_list.h @@ -29,15 +29,30 @@ public: FreeObject *Allocator(size_t size); - void Free(uintptr_t start, size_t size); + void Free(uintptr_t start, size_t size, bool isAdd = true); void Rebuild(); + bool AddKind(FreeObjectKind *kind); + + void RemoveKind(FreeObjectKind *kind); + + template + void EnumerateKinds(const Callback &cb) const; + + template + void EnumerateKinds(KindType type, const Callback &cb) const; + NO_COPY_SEMANTIC(FreeObjectList); NO_MOVE_SEMANTIC(FreeObjectList); size_t GetFreeObjectSize() const; + static int NumberOfKinds() + { + return NUMBER_OF_KINDS; + } + private: static constexpr int NUMBER_OF_KINDS = 39; static constexpr size_t MIN_SIZE = 16; @@ -58,9 +73,6 @@ private: inline void ClearNoneEmptyBit(KindType type); inline size_t CalcNextNoneEmptyIndex(KindType start); - bool AddKind(FreeObjectKind *kind); - void RemoveKind(FreeObjectKind *kind); - size_t available_ = 0; uint64_t noneEmptyKindBitMap_; Span kinds_ {}; diff --git a/ecmascript/mem/heap.cpp b/ecmascript/mem/heap.cpp index 61aba40..76bfc94 100644 --- a/ecmascript/mem/heap.cpp +++ b/ecmascript/mem/heap.cpp @@ -20,6 +20,7 @@ #include "ecmascript/ecma_vm.h" #include "ecmascript/mem/assert_scope-inl.h" #include "ecmascript/mem/compress_collector.h" +#include "ecmascript/mem/concurrent_sweeper.h" #include "ecmascript/mem/ecma_heap_manager.h" #include "ecmascript/mem/mark_stack.h" #include "ecmascript/mem/mem_controller.h" @@ -54,8 +55,6 @@ void Heap::Initialize() machineCodeSpace_ = new MachineCodeSpace(this); machineCodeSpace_->Initialize(); hugeObjectSpace_ = new HugeObjectSpace(this); - markStack_ = new MarkStack(this); - weakProcessQueue_ = new ProcessQueue(this); bool paralledGc = ecmaVm_->GetOptions().IsEnableParalledYoungGc(); if (paralledGc) { int numOfCpuCore = get_nprocs(); @@ -63,12 +62,15 @@ void Heap::Initialize() pool_ = new ThreadPool(numThread); semiSpaceCollector_ = new SemiSpaceCollector(this, true); compressCollector_ = new CompressCollector(this, true); + oldSpaceCollector_ = new OldSpaceCollector(this, true); } else { pool_ = new ThreadPool(1); semiSpaceCollector_ = new SemiSpaceCollector(this, false); compressCollector_ = new CompressCollector(this, false); + oldSpaceCollector_ = new OldSpaceCollector(this, false); } - oldSpaceCollector_ = new OldSpaceCollector(this); + // After EcmaOptions merged, it will modified to EcmaOptions configuration + sweeper_ = new ConcurrentSweeper(this, true); } void Heap::FlipNewSpace() @@ -87,6 +89,7 @@ void Heap::FlipCompressSpace() void Heap::Destroy() { pool_->WaitTaskFinish(); + sweeper_->EnsureAllTaskFinish(); toSpace_->Destroy(); delete toSpace_; toSpace_ = nullptr; @@ -109,16 +112,10 @@ void Heap::Destroy() machineCodeSpace_->Destroy(); delete machineCodeSpace_; machineCodeSpace_ = nullptr; - markStack_->Destroy(); - delete markStack_; - markStack_ = nullptr; hugeObjectSpace_->Destroy(); delete hugeObjectSpace_; hugeObjectSpace_ = nullptr; - weakProcessQueue_->Destroy(); - delete weakProcessQueue_; - weakProcessQueue_ = nullptr; delete semiSpaceCollector_; semiSpaceCollector_ = nullptr; delete oldSpaceCollector_; @@ -130,6 +127,8 @@ void Heap::Destroy() memController_ = nullptr; delete pool_; pool_ = nullptr; + delete sweeper_; + sweeper_ = nullptr; } void Heap::CollectGarbage(TriggerGCType gcType) @@ -138,6 +137,7 @@ void Heap::CollectGarbage(TriggerGCType gcType) // pre gc heap verify { if (ecmaVm_->GetOptions().IsPreGcHeapVerifyEnabled()) { + sweeper_->EnsureAllTaskFinish(); auto failCount = Verification(this).VerifyAll(); if (failCount > 0) { LOG(FATAL, GC) << "Before gc heap corrupted and " << failCount << " corruptions"; @@ -158,18 +158,18 @@ void Heap::CollectGarbage(TriggerGCType gcType) } break; case TriggerGCType::OLD_GC: - if (oldSpace_->GetHeapObjectSize() < OLD_SPACE_LIMIT_BEGIN) { - oldSpaceCollector_->RunPhases(); - } else { - compressCollector_->RunPhases(); + oldSpaceCollector_->RunPhases(); + if (!sweeper_->IsConcurrentSweepEnabled()) { + RecomputeLimits(); } - RecomputeLimits(); break; case TriggerGCType::NON_MOVE_GC: case TriggerGCType::HUGE_GC: case TriggerGCType::MACHINE_CODE_GC: oldSpaceCollector_->RunPhases(); - RecomputeLimits(); + if (!sweeper_->IsConcurrentSweepEnabled()) { + RecomputeLimits(); + } break; case TriggerGCType::COMPRESS_FULL_GC: compressCollector_->RunPhases(); @@ -183,6 +183,7 @@ void Heap::CollectGarbage(TriggerGCType gcType) // post gc heap verify { if (ecmaVm_->GetOptions().IsPreGcHeapVerifyEnabled()) { + sweeper_->EnsureAllTaskFinish(); auto failCount = Verification(this).VerifyAll(); if (failCount > 0) { LOG(FATAL, GC) << "After gc heap corrupted and " << failCount << " corruptions"; diff --git a/ecmascript/mem/heap.h b/ecmascript/mem/heap.h index bc112f2..55ce680 100644 --- a/ecmascript/mem/heap.h +++ b/ecmascript/mem/heap.h @@ -31,6 +31,7 @@ class FreeListAllocator; class RegionFactory; class HeapTracker; class MemController; +class ConcurrentSweeper; class Heap { public: @@ -93,16 +94,6 @@ public: return machineCodeSpace_; } - MarkStack *GetMarkStack() const - { - return markStack_; - } - - ProcessQueue *GetProcessQueue() const - { - return weakProcessQueue_; - } - SemiSpaceCollector *GetSemiSpaceCollector() const { return semiSpaceCollector_; @@ -118,6 +109,11 @@ public: return compressCollector_; } + ConcurrentSweeper *GetSweeper() const + { + return sweeper_; + } + EcmaVM *GetEcmaVM() const { return ecmaVm_; @@ -271,11 +267,10 @@ private: SnapShotSpace *snapshotSpace_ {nullptr}; NonMovableSpace *nonMovableSpace_ {nullptr}; MachineCodeSpace *machineCodeSpace_ {nullptr}; - MarkStack *markStack_ {nullptr}; - ProcessQueue *weakProcessQueue_ {nullptr}; SemiSpaceCollector *semiSpaceCollector_ {nullptr}; OldSpaceCollector *oldSpaceCollector_ {nullptr}; CompressCollector *compressCollector_ {nullptr}; + ConcurrentSweeper *sweeper_ {nullptr}; EcmaHeapManager *heapManager_ {nullptr}; RegionFactory *regionFactory_ {nullptr}; HeapTracker *tracker_ {nullptr}; diff --git a/ecmascript/mem/old_space_collector-inl.h b/ecmascript/mem/old_space_collector-inl.h index a8f88de..b6c82b7 100644 --- a/ecmascript/mem/old_space_collector-inl.h +++ b/ecmascript/mem/old_space_collector-inl.h @@ -24,31 +24,19 @@ #include "ecmascript/js_hclass-inl.h" namespace panda::ecmascript { -void OldSpaceCollector::MarkObject(TaggedObject *object) +void OldSpaceCollector::MarkObject(uint64_t threadId, TaggedObject *object) { Region *objectRegion = Region::ObjectAddressToRange(object); auto markBitmap = objectRegion->GetMarkBitmap(); - if (!markBitmap->Test(object)) { - markBitmap->Set(object); - markStack_.PushBack(object); + if (!markBitmap->AtomicTestAndSet(object)) { + workList_->Push(threadId, object); } } -void OldSpaceCollector::RecordWeakReference(JSTaggedType *ref) +void OldSpaceCollector::RecordWeakReference(uint64_t threadId, JSTaggedType *ref) { - Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast(ref)); - if (!objectRegion->InYoungGeneration()) { - weakProcessQueue_.PushBack(ref); - } -} - -void OldSpaceCollector::FreeLiveRange(FreeListAllocator &allocator, Region *current, uintptr_t freeStart, - uintptr_t freeEnd) -{ - allocator.Free(freeStart, freeEnd); - freeSize_ += freeEnd - freeStart; - heap_->ClearSlotsRange(current, freeStart, freeEnd); + workList_->PushWeakReference(threadId, ref); } } // namespace panda::ecmascript diff --git a/ecmascript/mem/old_space_collector.cpp b/ecmascript/mem/old_space_collector.cpp index 3572760..343f7c7 100644 --- a/ecmascript/mem/old_space_collector.cpp +++ b/ecmascript/mem/old_space_collector.cpp @@ -27,7 +27,11 @@ #include "ecmascript/vmstat/runtime_stat.h" namespace panda::ecmascript { -OldSpaceCollector::OldSpaceCollector(Heap *heap) : heap_(heap), rootManager_(heap->GetEcmaVM()) {} +OldSpaceCollector::OldSpaceCollector(Heap *heap, bool parallelGc) + : heap_(heap), rootManager_(heap->GetEcmaVM()), paralledGC_(parallelGc) +{ + workList_ = new OldGCWorker(heap_, heap_->GetThreadPool()->GetThreadNum()); +} void OldSpaceCollector::RunPhases() { @@ -45,12 +49,8 @@ void OldSpaceCollector::RunPhases() void OldSpaceCollector::InitializePhase() { - markStack_.BeginMarking(heap_, heap_->GetMarkStack()); - weakProcessQueue_.BeginMarking(heap_, heap_->GetProcessQueue()); - auto heapManager = heap_->GetHeapManager(); - oldSpaceAllocator_.Swap(heapManager->GetOldSpaceAllocator()); - nonMovableAllocator_.Swap(heapManager->GetNonMovableSpaceAllocator()); - machineCodeSpaceAllocator_.Swap(heapManager->GetMachineCodeSpaceAllocator()); + heap_->GetThreadPool()->WaitTaskFinish(); + heap_->GetSweeper()->EnsureAllTaskFinish(); heap_->EnumerateRegions([](Region *current) { // ensure mark bitmap auto bitmap = current->GetMarkBitmap(); @@ -60,6 +60,7 @@ void OldSpaceCollector::InitializePhase() bitmap->ClearAllBits(); } }); + workList_->Initialize(); freeSize_ = 0; hugeSpaceFreeSize_ = 0; oldSpaceCommitSize_ = heap_->GetOldSpace()->GetCommittedSize(); @@ -68,13 +69,8 @@ void OldSpaceCollector::InitializePhase() void OldSpaceCollector::FinishPhase() { - // swap - markStack_.FinishMarking(heap_->GetMarkStack()); - weakProcessQueue_.FinishMarking(heap_->GetProcessQueue()); - auto heapManager = heap_->GetHeapManager(); - heapManager->GetOldSpaceAllocator().Swap(oldSpaceAllocator_); - heapManager->GetNonMovableSpaceAllocator().Swap(nonMovableAllocator_); - heapManager->GetMachineCodeSpaceAllocator().Swap(machineCodeSpaceAllocator_); + size_t aliveSize = 0; + workList_->Finish(aliveSize); } void OldSpaceCollector::MarkingPhase() @@ -83,112 +79,72 @@ void OldSpaceCollector::MarkingPhase() RootVisitor gcMarkYoung = [this]([[maybe_unused]] Root type, ObjectSlot slot) { JSTaggedValue value(slot.GetTaggedType()); if (value.IsHeapObject()) { - MarkObject(value.GetTaggedObject()); + MarkObject(0, value.GetTaggedObject()); } }; RootRangeVisitor gcMarkRangeYoung = [this]([[maybe_unused]] Root type, ObjectSlot start, ObjectSlot end) { for (ObjectSlot slot = start; slot < end; slot++) { JSTaggedValue value(slot.GetTaggedType()); if (value.IsHeapObject()) { - MarkObject(value.GetTaggedObject()); + MarkObject(0, value.GetTaggedObject()); } } }; rootManager_.VisitVMRoots(gcMarkYoung, gcMarkRangeYoung); - ProcessMarkStack(); + ProcessMarkStack(0); + if (paralledGC_) { + heap_->GetThreadPool()->WaitTaskFinish(); + } } -void OldSpaceCollector::ProcessMarkStack() +void OldSpaceCollector::ProcessMarkStack(uint64_t threadId) { while (true) { - auto obj = markStack_.PopBack(); - if (UNLIKELY(obj == nullptr)) { + TaggedObject *obj = nullptr; + if (!workList_->Pop(threadId, &obj)) { break; } auto jsHclass = obj->GetClass(); // mark dynClass - MarkObject(jsHclass); + MarkObject(threadId, jsHclass); rootManager_.MarkObjectBody( - obj, jsHclass, [this]([[maybe_unused]] TaggedObject *root, ObjectSlot start, ObjectSlot end) { + obj, jsHclass, [this, &threadId]([[maybe_unused]] TaggedObject *root, ObjectSlot start, ObjectSlot end) { for (ObjectSlot slot = start; slot < end; slot++) { JSTaggedValue value(slot.GetTaggedType()); if (value.IsWeak()) { - RecordWeakReference(reinterpret_cast(slot.SlotAddress())); + RecordWeakReference(threadId, reinterpret_cast(slot.SlotAddress())); continue; } if (value.IsHeapObject()) { - MarkObject(value.GetTaggedObject()); + MarkObject(threadId, value.GetTaggedObject()); } } }); } } -void OldSpaceCollector::SweepSpace(Space *space, FreeListAllocator &allocator) -{ - allocator.RebuildFreeList(); - space->EnumerateRegions([this, &allocator](Region *current) { - auto markBitmap = current->GetMarkBitmap(); - ASSERT(markBitmap != nullptr); - uintptr_t freeStart = current->GetBegin(); - markBitmap->IterateOverMarkedChunks([this, ¤t, &freeStart, &allocator](void *mem) { - ASSERT(current->InRange(ToUintPtr(mem))); - auto header = reinterpret_cast(mem); - auto klass = header->GetClass(); - JSType jsType = klass->GetObjectType(); - auto size = klass->SizeFromJSHClass(jsType, header); - size = AlignUp(size, static_cast(MemAlignment::MEM_ALIGN_OBJECT)); - - uintptr_t freeEnd = ToUintPtr(mem); - if (freeStart != freeEnd) { - FreeLiveRange(allocator, current, freeStart, freeEnd); - } - freeStart = freeEnd + size; - }); - uintptr_t freeEnd = current->GetEnd(); - if (freeStart != freeEnd) { - FreeLiveRange(allocator, current, freeStart, freeEnd); - } - }); -} - -void OldSpaceCollector::SweepSpace(HugeObjectSpace *space) -{ - Region *currentRegion = space->GetRegionList().GetFirst(); - - while (currentRegion != nullptr) { - Region *next = currentRegion->GetNext(); - auto markBitmap = currentRegion->GetMarkBitmap(); - bool isMarked = false; - markBitmap->IterateOverMarkedChunks([&isMarked]([[maybe_unused]] void *mem) { isMarked = true; }); - if (!isMarked) { - space->GetRegionList().RemoveNode(currentRegion); - hugeSpaceFreeSize_ += currentRegion->GetCapacity(); - space->ClearAndFreeRegion(currentRegion); - } - currentRegion = next; - } -} - void OldSpaceCollector::SweepPhases() { trace::ScopedTrace scoped_trace("OldSpaceCollector::SweepPhases"); // process weak reference - while (true) { - auto obj = weakProcessQueue_.PopBack(); - if (UNLIKELY(obj == nullptr)) { - break; - } - ObjectSlot slot(ToUintPtr(obj)); - JSTaggedValue value(slot.GetTaggedType()); - auto header = value.GetTaggedWeakRef(); + for (uint32_t i = 0; i < heap_->GetThreadPool()->GetThreadNum(); i++) { + ProcessQueue *queue = workList_->GetWeakReferenceQueue(i); + while (true) { + auto obj = queue->PopBack(); + if (UNLIKELY(obj == nullptr)) { + break; + } + ObjectSlot slot(ToUintPtr(obj)); + JSTaggedValue value(slot.GetTaggedType()); + auto header = value.GetTaggedWeakRef(); - Region *objectRegion = Region::ObjectAddressToRange(header); - auto markBitmap = objectRegion->GetMarkBitmap(); - if (!markBitmap->Test(header)) { - slot.Update(static_cast(JSTaggedValue::Undefined().GetRawData())); + Region *objectRegion = Region::ObjectAddressToRange(header); + auto markBitmap = objectRegion->GetMarkBitmap(); + if (!markBitmap->Test(header)) { + slot.Update(static_cast(JSTaggedValue::Undefined().GetRawData())); + } } } @@ -209,9 +165,6 @@ void OldSpaceCollector::SweepPhases() heap_->GetEcmaVM()->GetJSThread()->IterateWeakEcmaGlobalStorage(gcUpdateWeak); heap_->GetEcmaVM()->ProcessReferences(gcUpdateWeak); - SweepSpace(const_cast(heap_->GetOldSpace()), oldSpaceAllocator_); - SweepSpace(const_cast(heap_->GetNonMovableSpace()), nonMovableAllocator_); - SweepSpace(const_cast(heap_->GetHugeObjectSpace())); - SweepSpace(const_cast(heap_->GetMachineCodeSpace()), machineCodeSpaceAllocator_); + heap_->GetSweeper()->SweepPhases(); } } // namespace panda::ecmascript diff --git a/ecmascript/mem/old_space_collector.h b/ecmascript/mem/old_space_collector.h index 6494035..5da8b52 100644 --- a/ecmascript/mem/old_space_collector.h +++ b/ecmascript/mem/old_space_collector.h @@ -21,6 +21,7 @@ #include "ecmascript/mem/allocator.h" #include "ecmascript/mem/mark_stack-inl.h" #include "ecmascript/mem/mark_word.h" +#include "ecmascript/mem/semi_space_worker.h" #include "ecmascript/mem/slots.h" #include "ecmascript/mem/heap_roots.h" #include "ecmascript/mem/remembered_set.h" @@ -33,7 +34,7 @@ class JSHClass; class OldSpaceCollector : public GarbageCollector { public: - explicit OldSpaceCollector(Heap *heap); + explicit OldSpaceCollector(Heap *heap, bool parallelGc); ~OldSpaceCollector() override = default; NO_COPY_SEMANTIC(OldSpaceCollector); NO_MOVE_SEMANTIC(OldSpaceCollector); @@ -50,26 +51,22 @@ private: void SweepPhases(); void FinishPhase(); - void ProcessMarkStack(); + void ProcessMarkStack(uint64_t threadId); void MarkObjectBody(TaggedObject *object, JSHClass *klass, const EcmaObjectRangeVisitor &visitor); - inline void MarkObject(TaggedObject *object); - inline void FreeLiveRange(FreeListAllocator &allocator, Region *current, uintptr_t freeStart, uintptr_t freeEnd); - inline void RecordWeakReference(JSTaggedType *ref); - void SweepSpace(Space *space, FreeListAllocator &allocator); - void SweepSpace(HugeObjectSpace *space); // Only sweep huge space. + inline void MarkObject(uint64_t threadId, TaggedObject *object); + inline void RecordWeakReference(uint64_t threadId, JSTaggedType *ref); Heap *heap_; HeapRootManager rootManager_; - MarkStack markStack_; - ProcessQueue weakProcessQueue_; - FreeListAllocator oldSpaceAllocator_ {}; - FreeListAllocator nonMovableAllocator_ {}; - FreeListAllocator machineCodeSpaceAllocator_ {}; + bool paralledGC_{false}; + OldGCWorker *workList_{nullptr}; size_t freeSize_{0}; size_t hugeSpaceFreeSize_ = 0; size_t oldSpaceCommitSize_ = 0; size_t nonMoveSpaceCommitSize_ = 0; + + friend class OldGCWorker; }; } // namespace ecmascript } // namespace panda diff --git a/ecmascript/mem/region.h b/ecmascript/mem/region.h index 4e541d1..207abda 100644 --- a/ecmascript/mem/region.h +++ b/ecmascript/mem/region.h @@ -16,6 +16,7 @@ #ifndef ECMASCRIPT_MEM_REGION_H #define ECMASCRIPT_MEM_REGION_H +#include "ecmascript/mem/free_object_list.h" #include "ecmascript/mem/mem.h" #include "mem/gc/bitmap.h" @@ -41,9 +42,11 @@ enum RegionFlags { // NOLINTNEXTLINE(hicpp-signed-bitwise) IS_IN_OLD_GENERATION = 1 << 6, // NOLINTNEXTLINE(hicpp-signed-bitwise) + IS_IN_NON_MOVABLE_GENERATION = 1 << 7, + // NOLINTNEXTLINE(hicpp-signed-bitwise) IS_IN_YOUNG_OR_OLD_GENERATION = IS_IN_YOUNG_GENERATION | IS_IN_OLD_GENERATION, // NOLINTNEXTLINE(hicpp-signed-bitwise) - IS_INVALID = 1 << 7, + IS_INVALID = 1 << 8, }; class Region { @@ -206,6 +209,36 @@ public: return res; } + void InitializeKind() + { + kinds_ = Span(new FreeObjectKind *[FreeObjectList::NumberOfKinds()](), + FreeObjectList::NumberOfKinds()); + for (int i = 0; i < FreeObjectList::NumberOfKinds(); i++) { + kinds_[i] = new FreeObjectKind(i); + } + } + + void DestoryKind() + { + for (auto kind : kinds_) { + delete kind; + } + delete[] kinds_.data(); + } + + FreeObjectKind *GetFreeObjectKind(KindType type) + { + return kinds_[type]; + } + + template + void EnumerateKinds(Callback cb) + { + for (auto kind : kinds_) { + cb(kind); + } + } + private: Space *space_; uintptr_t flags_; // Memory alignment, only low 32bits are used now @@ -218,6 +251,7 @@ private: RangeBitmap *markBitmap_{nullptr}; RememberedSet *crossRegionSet_{nullptr}; RememberedSet *oldToNewSet_{nullptr}; + Span kinds_; friend class SnapShot; }; } // namespace ecmascript diff --git a/ecmascript/mem/semi_space_collector.cpp b/ecmascript/mem/semi_space_collector.cpp index ef69750..0cc31fd 100644 --- a/ecmascript/mem/semi_space_collector.cpp +++ b/ecmascript/mem/semi_space_collector.cpp @@ -59,7 +59,7 @@ void SemiSpaceCollector::RunPhases() void SemiSpaceCollector::InitializePhase() { heap_->GetThreadPool()->WaitTaskFinish(); - gcTime_++; + heap_->GetSweeper()->EnsureAllTaskFinish(); auto fromSpace = heap_->GetFromSpace(); if (fromSpace->GetCommittedSize() == 0) { heap_->InitializeFromSpace(); diff --git a/ecmascript/mem/semi_space_collector.h b/ecmascript/mem/semi_space_collector.h index 6e5a31f..3a76149 100644 --- a/ecmascript/mem/semi_space_collector.h +++ b/ecmascript/mem/semi_space_collector.h @@ -91,7 +91,6 @@ private: size_t semiCopiedSize_{0}; size_t commitSize_ = 0; uintptr_t ageMark_{0}; - size_t gcTime_{0}; friend class TlabAllocator; friend class SemiSpaceWorker; friend class SemiSpaceMarker; diff --git a/ecmascript/mem/semi_space_worker.cpp b/ecmascript/mem/semi_space_worker.cpp index dbaa62b..0df831f 100644 --- a/ecmascript/mem/semi_space_worker.cpp +++ b/ecmascript/mem/semi_space_worker.cpp @@ -19,6 +19,7 @@ #include "ecmascript/mem/compress_collector.h" #include "ecmascript/mem/heap.h" #include "ecmascript/mem/mark_stack.h" +#include "ecmascript/mem/old_space_collector.h" #include "ecmascript/mem/region_factory.h" #include "ecmascript/mem/tlab_allocator-inl.h" @@ -197,4 +198,32 @@ void CompressGCWorker::Initialize() holder.aliveSize_ = 0; } } + +void OldGCWorker::Initialize() +{ + spaceTop_ = markSpace_; + markSpaceEnd_ = markSpace_ + SPACE_SIZE; + for (uint32_t i = 0; i < threadNum_; i++) { + WorkNodeHolder &holder = workList_[i]; + holder.pushNode_ = AllocalWorkNode(); + holder.popNode_ = AllocalWorkNode(); + holder.weakQueue_ = new ProcessQueue(); + holder.weakQueue_->BeginMarking(heap_, continuousQueue_[i]); + } +} + +void OldGCWorker::PushWorkNodeToGlobal(uint32_t threadId) +{ + WorkNode *&pushNode = workList_[threadId].pushNode_; + if (!pushNode->IsEmpty()) { + globalWork_.Push(pushNode); + pushNode = AllocalWorkNode(); + + auto pool = heap_->GetThreadPool(); + if (pool->GetTaskCount() < pool->GetThreadNum() - 1) { + pool->Submit(std::bind(&OldSpaceCollector::ProcessMarkStack, heap_->GetOldSpaceCollector(), + std::placeholders::_1)); + } + } +} } // namespace panda::ecmascript diff --git a/ecmascript/mem/semi_space_worker.h b/ecmascript/mem/semi_space_worker.h index 2572c47..0a88f31 100644 --- a/ecmascript/mem/semi_space_worker.h +++ b/ecmascript/mem/semi_space_worker.h @@ -233,6 +233,19 @@ public: NO_COPY_SEMANTIC(CompressGCWorker); NO_MOVE_SEMANTIC(CompressGCWorker); }; -} // namespace panda::ecmascript +class OldGCWorker : public Worker { +public: + OldGCWorker() = delete; + OldGCWorker(Heap *heap, uint32_t threadNum) : Worker(heap, threadNum) {} + + ~OldGCWorker() override = default; + + void PushWorkNodeToGlobal(uint32_t threadId) override; + void Initialize() override; + + NO_COPY_SEMANTIC(OldGCWorker); + NO_MOVE_SEMANTIC(OldGCWorker); +}; +} // namespace panda::ecmascript #endif // ECMASCRIPT_MEM_SEMI_SPACE_WORKER_H diff --git a/ecmascript/mem/space.cpp b/ecmascript/mem/space.cpp index 7a66528..c1156bc 100644 --- a/ecmascript/mem/space.cpp +++ b/ecmascript/mem/space.cpp @@ -37,11 +37,16 @@ void Space::Initialize() } else if (spaceType_ == MemSpaceType::SNAPSHOT_SPACE) { region->SetFlag(RegionFlags::IS_IN_SNAPSHOT_GENERATION); } else if (spaceType_ == MemSpaceType::OLD_SPACE) { + region->InitializeKind(); region->SetFlag(RegionFlags::IS_IN_OLD_GENERATION); } else if (spaceType_ == MemSpaceType::MACHINE_CODE_SPACE) { + region->InitializeKind(); region->SetFlag(RegionFlags::IS_IN_OLD_GENERATION); int res = region->SetCodeExecutableAndReadable(); LOG_ECMA_MEM(DEBUG) << "Initialize SetCodeExecutableAndReadable" << res; + } else if (spaceType_ == MemSpaceType::NON_MOVABLE) { + region->InitializeKind(); + region->SetFlag(RegionFlags::IS_IN_NON_MOVABLE_GENERATION); } AddRegion(region); @@ -75,6 +80,11 @@ void Space::ClearAndFreeRegion(Region *region) delete rememberedSet; } DecrementCommitted(region->GetCapacity()); + if (spaceType_ == MemSpaceType::OLD_SPACE || + spaceType_ == MemSpaceType::NON_MOVABLE || + spaceType_ == MemSpaceType::MACHINE_CODE_SPACE) { + region->DestoryKind(); + } const_cast(heap_->GetRegionFactory())->FreeRegion(region); } @@ -177,6 +187,7 @@ bool OldSpace::Expand() Region *region = const_cast(GetHeap()->GetRegionFactory())->AllocateAlignedRegion(this, DEFAULT_REGION_SIZE); region->SetFlag(RegionFlags::IS_IN_OLD_GENERATION); + region->InitializeKind(); AddRegion(region); return true; } @@ -231,8 +242,7 @@ size_t OldSpace::GetHeapObjectSize() const { size_t result; size_t availableSize = GetHeap()->GetHeapManager()->GetOldSpaceAllocator().GetAvailableSize(); - size_t regionSize = GetRegionList().GetLength() * DEFAULT_REGION_SIZE; - result = regionSize - availableSize; + result = GetCommittedSize() - availableSize; result += GetHeap()->GetHugeObjectSpace()->GetHeapObjectSize(); return result; } @@ -250,6 +260,8 @@ bool NonMovableSpace::Expand() } Region *region = const_cast(GetHeap()->GetRegionFactory())->AllocateAlignedRegion(this, DEFAULT_REGION_SIZE); + region->SetFlag(IS_IN_NON_MOVABLE_GENERATION); + region->InitializeKind(); AddRegion(region); return true; } @@ -372,6 +384,12 @@ uintptr_t HugeObjectSpace::Allocate(size_t objectSize) return region->GetBegin(); } +void HugeObjectSpace::Free(Region *region) +{ + GetRegionList().RemoveNode(region); + ClearAndFreeRegion(region); +} + bool HugeObjectSpace::ContainObject(TaggedObject *object) const { auto region = GetRegionList().GetFirst(); @@ -391,12 +409,7 @@ bool HugeObjectSpace::IsLive(TaggedObject *object) const size_t HugeObjectSpace::GetHeapObjectSize() const { - size_t result = 0; - EnumerateRegions([&result](Region *current) { - auto obj = reinterpret_cast(current->GetBegin()); - result += obj->GetObjectSize(); - }); - return result; + return GetCommittedSize(); } void HugeObjectSpace::IterateOverObjects(const std::function &objectVisitor) const @@ -420,6 +433,7 @@ bool MachineCodeSpace::Expand() } Region *region = const_cast(GetHeap()->GetRegionFactory())->AllocateAlignedRegion(this, DEFAULT_REGION_SIZE); + region->InitializeKind(); AddRegion(region); int res = region->SetCodeExecutableAndReadable(); LOG_ECMA_MEM(DEBUG) << "MachineCodeSpace::Expand() SetCodeExecutableAndReadable" << res; diff --git a/ecmascript/mem/space.h b/ecmascript/mem/space.h index 7e6012f..25f353e 100644 --- a/ecmascript/mem/space.h +++ b/ecmascript/mem/space.h @@ -29,13 +29,16 @@ class Heap; class Program; enum MemSpaceType { - SEMI_SPACE, - OLD_SPACE, + OLD_SPACE = 0, NON_MOVABLE, + MACHINE_CODE_SPACE, HUGE_OBJECT_SPACE, + SEMI_SPACE, SNAPSHOT_SPACE, - MACHINE_CODE_SPACE, - SPACE_TYPE_LAST // Count of different types + COMPRESS_SPACE, + SPACE_TYPE_LAST, // Count of different types + + FREE_LIST_NUM = MACHINE_CODE_SPACE - OLD_SPACE + 1, }; enum TriggerGCType { @@ -238,6 +241,7 @@ public: NO_COPY_SEMANTIC(HugeObjectSpace); NO_MOVE_SEMANTIC(HugeObjectSpace); uintptr_t Allocate(size_t objectSize); + void Free(Region *region); size_t GetHeapObjectSize() const; bool ContainObject(TaggedObject *object) const; bool IsLive(TaggedObject *object) const; diff --git a/ecmascript/mem/tlab_allocator-inl.h b/ecmascript/mem/tlab_allocator-inl.h index 9e37544..32f713e 100644 --- a/ecmascript/mem/tlab_allocator-inl.h +++ b/ecmascript/mem/tlab_allocator-inl.h @@ -24,7 +24,7 @@ #include "ecmascript/mem/tlab_allocator.h" namespace panda::ecmascript { -static constexpr size_t YOUNG_BUFFER_SIZE = 32 * 1024; +static constexpr size_t YOUNG_BUFFER_SIZE = 31 * 1024; static constexpr size_t OLD_BUFFER_SIZE = 255 * 1024; TlabAllocator::TlabAllocator(Heap *heap, TriggerGCType gcType) diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index d760c31..ba2673f 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -793,10 +793,12 @@ FreeObject *ObjectFactory::FillFreeObject(uintptr_t address, size_t size, Remove if (size >= FreeObject::SIZE_OFFSET && size < FreeObject::SIZE) { object = reinterpret_cast(address); object->SetClass(freeObjectWithOneFieldClass_); + object->SetNext(nullptr); } else if (size >= FreeObject::SIZE) { object = reinterpret_cast(address); object->SetClass(freeObjectWithTwoFieldClass_); object->SetAvailable(size); + object->SetNext(nullptr); } else if (size == FreeObject::NEXT_OFFSET) { object = reinterpret_cast(address); object->SetClass(freeObjectWithNoneFieldClass_); diff --git a/ecmascript/platform/platform.cpp b/ecmascript/platform/platform.cpp new file mode 100644 index 0000000..f589f38 --- /dev/null +++ b/ecmascript/platform/platform.cpp @@ -0,0 +1,45 @@ +/* + * 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/platform/platform.h" + +#include "sys/sysinfo.h" + +namespace panda::ecmascript { +void Platform::Initialize(int threadNum) +{ + os::memory::LockHolder lock(mutex_); + if (isInitialized_++ <= 0) { + runner_ = std::make_unique(TheMostSuitableThreadNum(threadNum)); + } +} + +void Platform::Destory() +{ + os::memory::LockHolder lock(mutex_); + if (--isInitialized_ <= 0) { + runner_->Terminate(); + } +} + +int Platform::TheMostSuitableThreadNum(int threadNum) const +{ + if (threadNum > 0) { + return std::min(threadNum, MAX_PLATFORM_THREAD_NUM); + } + int numOfCpuCore = get_nprocs() - 1; + return std::min(numOfCpuCore, MAX_PLATFORM_THREAD_NUM); +} +} // namespace panda::ecmascript diff --git a/ecmascript/platform/platform.h b/ecmascript/platform/platform.h new file mode 100644 index 0000000..d62af79 --- /dev/null +++ b/ecmascript/platform/platform.h @@ -0,0 +1,59 @@ +/* + * 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_PALTFORM_PLATFORM_H +#define ECMASCRIPT_PALTFORM_PLATFORM_H + +#include + +#include "ecmascript/platform/runner.h" +#include "os/mutex.h" + +namespace panda::ecmascript { +class Platform { +public: + static Platform *GetCurrentPlatform() + { + static Platform platform; + return &platform; + } + + Platform() = default; + ~Platform() = default; + + NO_COPY_SEMANTIC(Platform); + NO_MOVE_SEMANTIC(Platform); + + void Initialize(int threadNum = DEFAULT_PLATFORM_THREAD_NUM); + void Destory(); + + void PostTask(std::unique_ptr task) const + { + ASSERT(isInitialized_ > 0); + runner_->PostTask(std::move(task)); + } + +private: + static constexpr uint32_t MAX_PLATFORM_THREAD_NUM = 7; + static constexpr uint32_t DEFAULT_PLATFORM_THREAD_NUM = 0; + + int TheMostSuitableThreadNum(int threadNum) const; + + std::unique_ptr runner_; + int isInitialized_ = 0; + os::memory::Mutex mutex_; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_PALTFORM_PLATFORM_H diff --git a/ecmascript/platform/runner.cpp b/ecmascript/platform/runner.cpp new file mode 100644 index 0000000..9496079 --- /dev/null +++ b/ecmascript/platform/runner.cpp @@ -0,0 +1,46 @@ +/* + * 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/platform/runner.h" + +#include "os/thread.h" + +namespace panda::ecmascript { +Runner::Runner(int threadNum) +{ + for (int i = 0; i < threadNum; i++) { + std::unique_ptr thread = std::make_unique(&Runner::Run, this); + os::thread::SetThreadName(thread->native_handle(), "GC_WorkerThread"); + threadPool_.emplace_back(std::move(thread)); + } +} + +void Runner::Terminate() +{ + taskQueue_.Terminate(); + int threadNum = threadPool_.size(); + for (int i = 0; i < threadNum; i++) { + threadPool_.at(i)->join(); + } + threadPool_.clear(); +} + +void Runner::Run() +{ + while (std::unique_ptr task = taskQueue_.PopTask()) { + task->Run(); + } +} +} // namespace panda::ecmascript diff --git a/ecmascript/platform/runner.h b/ecmascript/platform/runner.h new file mode 100644 index 0000000..be0ada0 --- /dev/null +++ b/ecmascript/platform/runner.h @@ -0,0 +1,48 @@ +/* + * 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_PLATFORM_RUNNER_H +#define ECMASCRIPT_PLATFORM_RUNNER_H + +#include +#include +#include + +#include "ecmascript/platform/task_queue.h" + +namespace panda::ecmascript { +class Runner { +public: + explicit Runner(int threadNum); + ~Runner() = default; + + NO_COPY_SEMANTIC(Runner); + NO_MOVE_SEMANTIC(Runner); + + void PostTask(std::unique_ptr task) + { + taskQueue_.PostTask(std::move(task)); + } + + void Terminate(); + +private: + void Run(); + + std::vector> threadPool_ {}; + TaskQueue taskQueue_ {}; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_PLATFORM_RUNNER_H diff --git a/ecmascript/platform/task.h b/ecmascript/platform/task.h new file mode 100644 index 0000000..71eff10 --- /dev/null +++ b/ecmascript/platform/task.h @@ -0,0 +1,32 @@ +/* + * 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_PLATFORM_TASK_H +#define ECMASCRIPT_PLATFORM_TASK_H + +#include "macros.h" + +namespace panda::ecmascript { +class Task { +public: + Task() = default; + virtual ~Task() = default; + virtual bool Run() = 0; + + NO_COPY_SEMANTIC(Task); + NO_MOVE_SEMANTIC(Task); +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_PLATFORM_TASK_H diff --git a/ecmascript/platform/task_queue.cpp b/ecmascript/platform/task_queue.cpp new file mode 100644 index 0000000..b90c205 --- /dev/null +++ b/ecmascript/platform/task_queue.cpp @@ -0,0 +1,50 @@ +/* + * 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/platform/task_queue.h" + +namespace panda::ecmascript { +void TaskQueue::PostTask(std::unique_ptr task) +{ + os::memory::LockHolder holder(mtx_); + ASSERT(!terminate_); + tasks_.push(std::move(task)); + cv_.Signal(); +} + +std::unique_ptr TaskQueue::PopTask() +{ + os::memory::LockHolder holder(mtx_); + while (true) { + if (!tasks_.empty()) { + std::unique_ptr task = std::move(tasks_.front()); + tasks_.pop(); + return task; + } + if (terminate_) { + cv_.SignalAll(); + return nullptr; + } + cv_.Wait(&mtx_); + } +} + +void TaskQueue::Terminate() +{ + os::memory::LockHolder holder(mtx_); + terminate_ = true; + cv_.SignalAll(); +} +} // namespace panda::ecmascript diff --git a/ecmascript/platform/task_queue.h b/ecmascript/platform/task_queue.h new file mode 100644 index 0000000..ab8d7b1 --- /dev/null +++ b/ecmascript/platform/task_queue.h @@ -0,0 +1,49 @@ +/* + * 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_PLATFORM_TASK_QUEUE_H +#define ECMASCRIPT_PLATFORM_TASK_QUEUE_H + +#include +#include +#include +#include + +#include "ecmascript/platform/task.h" +#include "os/mutex.h" + +namespace panda::ecmascript { +class TaskQueue { +public: + TaskQueue() = default; + ~TaskQueue() = default; + + NO_COPY_SEMANTIC(TaskQueue); + NO_MOVE_SEMANTIC(TaskQueue); + + void PostTask(std::unique_ptr task); + std::unique_ptr PopTask(); + + void Terminate(); + +private: + std::queue> tasks_; + + std::atomic_bool terminate_ = false; + os::memory::Mutex mtx_; + os::memory::ConditionVariable cv_; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_PLATFORM_TASK_QUEUE_H diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index f54a7db..99ea6cc 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -831,6 +831,7 @@ host_unittest_action("GcTest") { sources = [ # test file + "concurrent_sweep_test.cpp", "gc_test.cpp", ] diff --git a/ecmascript/tests/concurrent_sweep_test.cpp b/ecmascript/tests/concurrent_sweep_test.cpp new file mode 100644 index 0000000..6759428 --- /dev/null +++ b/ecmascript/tests/concurrent_sweep_test.cpp @@ -0,0 +1,64 @@ +/* + * 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/tests/test_helper.h" + +#include "ecmascript/ecma_vm.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_handle.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class ConcurrentSweepTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + + PandaVM *instance {nullptr}; + EcmaHandleScope *scope {nullptr}; + JSThread *thread; +}; + +TEST_F(ConcurrentSweepTest, ConcurrentSweep) +{ + auto vm = EcmaVM::Cast(instance); + const uint8_t *utf8 = reinterpret_cast("test"); + JSHandle test1(thread, EcmaString::CreateFromUtf8(utf8, 4, vm, false)); + if (vm->IsInitialized()) { + vm->CollectGarbage(ecmascript::TriggerGCType::OLD_GC); + } + JSHandle test2(thread, EcmaString::CreateFromUtf8(utf8, 4, vm, false)); + ASSERT_EQ(test1->GetLength(), 4); + ASSERT_NE(test1.GetTaggedValue().GetHeapObject(), test2.GetTaggedValue().GetHeapObject()); +} +} // namespace panda::test -- Gitee From 68271c1b3f0da6aca25e48e2e489615c87dbd49b Mon Sep 17 00:00:00 2001 From: lichenshuai Date: Thu, 14 Oct 2021 14:46:53 +0800 Subject: [PATCH 023/115] Add support for -m (module) parameter. Signed-off-by: lichenshuai --- test/moduletest/module/BUILD.gn | 3 +++ test/test_helper.gni | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/test/moduletest/module/BUILD.gn b/test/moduletest/module/BUILD.gn index fbf4dea..5e9c5dd 100644 --- a/test/moduletest/module/BUILD.gn +++ b/test/moduletest/module/BUILD.gn @@ -15,10 +15,12 @@ import("//ark/js_runtime/test/test_helper.gni") host_moduletest_action("B") { deps = [] + is_module = true } host_moduletest_action("C") { deps = [] + is_module = true } host_moduletest_action("module") { @@ -26,4 +28,5 @@ host_moduletest_action("module") { ":gen_B_abc", ":gen_C_abc", ] + is_module = true } diff --git a/test/test_helper.gni b/test/test_helper.gni index 6fda215..74c3071 100644 --- a/test/test_helper.gni +++ b/test/test_helper.gni @@ -65,6 +65,10 @@ template("host_unittest_action") { template("host_moduletest_action") { _target_name_ = "${target_name}" _deps_ = invoker.deps + _is_module_ = false + if (defined(invoker.is_module) && invoker.is_module) { + _is_module_ = true + } _test_js_path_ = "./${_target_name_}.js" _test_abc_path_ = "$target_out_dir/${_target_name_}.abc" @@ -76,6 +80,9 @@ template("host_moduletest_action") { src_js = rebase_path(_test_js_path_) dst_file = rebase_path(_test_abc_path_) extra_args = [ "--debug" ] + if (_is_module_) { + extra_args += [ "--module" ] + } in_puts = [ _test_js_path_, -- Gitee From 752319768ba8dc80cf79bfcbf8d163633d70304b Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Thu, 14 Oct 2021 12:02:17 +0800 Subject: [PATCH 024/115] l2 don't find libllvm_stackmap_parser Signed-off-by: surpassgoodchao --- BUILD.gn | 1 + ecmascript/compiler/llvm/BUILD.gn | 9 +++++++-- test/test_helper.gni | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 4b09033..404fa23 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -438,6 +438,7 @@ source_set("libark_jsruntime_test_static") { ":copy_resource_xml", "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", + "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", "//third_party/icu/icu4c:shared_icui18n", "//third_party/icu/icu4c:shared_icuuc", sdk_libc_secshared_dep, diff --git a/ecmascript/compiler/llvm/BUILD.gn b/ecmascript/compiler/llvm/BUILD.gn index 5c930cd..b5895f3 100644 --- a/ecmascript/compiler/llvm/BUILD.gn +++ b/ecmascript/compiler/llvm/BUILD.gn @@ -9,7 +9,7 @@ # 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. +# limitations under the License. import("//ark/js_runtime/js_runtime_config.gni") import("//build/ohos.gni") @@ -17,7 +17,12 @@ import("//build/ohos.gni") ohos_shared_library("libllvm_stackmap_parser") { sources = [ "llvm_stackmap_parser.cpp" ] + install_enable = true + part_name = "ark_js_runtime" + output_extension = "so" - relative_install_dir = "ark" + if (!is_standard_system) { + relative_install_dir = "ark" + } subsystem_name = "ark" } diff --git a/test/test_helper.gni b/test/test_helper.gni index 6fda215..b322504 100644 --- a/test/test_helper.gni +++ b/test/test_helper.gni @@ -51,7 +51,8 @@ template("host_unittest_action") { "0", "--env-path", rebase_path(_root_out_dir_) + "/ark/ark:" + rebase_path(_root_out_dir_) + - "/test/test:" + rebase_path(_root_out_dir_) + "/global/${icu_path}:" + + "/ark/ark_js_runtime:" + rebase_path(_root_out_dir_) + "/test/test:" + + rebase_path(_root_out_dir_) + "/global/${icu_path}:" + rebase_path("//prebuilts/clang/ohos/linux-x86_64/llvm/lib/"), ] -- Gitee From e907567a15ea839db1087193921946a80077fd02 Mon Sep 17 00:00:00 2001 From: "yingguofeng@huawei.com" Date: Thu, 14 Oct 2021 14:58:40 +0800 Subject: [PATCH 025/115] Delete NativeObject type Signed-off-by: yingguofeng@huawei.com Change-Id: I6d6fe177a8a85e65cae90e36ac00f76e6d8e1c71 --- ecmascript/js_hclass.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index 486479f..e12d76c 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -91,7 +91,6 @@ class ProtoChangeDetails; JS_FLOAT32_ARRAY, /* ////////////////////////////////////////////////////////////////////////-PADDING */ \ JS_FLOAT64_ARRAY, /* JS_TYPED_ARRAY_END ///////////////////////////////////////////////////////////// */ \ JS_PRIMITIVE_REF, /* number\boolean\string. SPECIAL indexed objects end, DON'T CHANGE HERE ////////-PADDING */ \ - JS_NATIVE_OBJECT, /* //////////////////////////////////////////////////////////////////////////////-PADDING */ \ JS_GLOBAL_OBJECT, /* JS_OBJECT_END/////////////////////////////////////////////////////////////////-PADDING */ \ JS_PROXY, /* ECMA_OBJECT_END ////////////////////////////////////////////////////////////////////////////// */ \ \ -- Gitee From e8389db4797657c243aa2c948eb7821c59f436b7 Mon Sep 17 00:00:00 2001 From: Han00000000 Date: Thu, 14 Oct 2021 16:43:34 +0800 Subject: [PATCH 026/115] fix js opt bugs for ASAN Signed-off-by: Han00000000 Change-Id: Ia058688171c00c190c74dbbc133a10ff4d5e5edc --- ecmascript/compiler/llvm_codegen.cpp | 9 +- ecmascript/compiler/llvm_codegen.h | 11 +- ecmascript/compiler/llvm_ir_builder.cpp | 158 ++++++++++++---------- ecmascript/compiler/llvm_ir_builder.h | 3 +- ecmascript/compiler/llvm_mcjit_engine.cpp | 18 +-- ecmascript/compiler/stub_aot_compiler.cpp | 14 +- ecmascript/compiler/stub_descriptor.cpp | 5 +- ecmascript/mem/machine_code.h | 2 - 8 files changed, 119 insertions(+), 101 deletions(-) diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index d2139f5..d0c2606 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -32,7 +32,7 @@ void LLVMModuleAssembler::AssembleModule() assembler_.Run(); } -void LLVMModuleAssembler::CopyAssembleCodeToModule(StubModule *module) +void LLVMModuleAssembler::AssembleStubModule(StubModule *module) { auto codeBuff = reinterpret_cast
(assembler_.GetCodeBuffer()); auto engine = assembler_.GetEngine(); @@ -44,12 +44,5 @@ void LLVMModuleAssembler::CopyAssembleCodeToModule(StubModule *module) } } assembler_.Disassemble(); - - auto codeSize = assembler_.GetCodeSize(); - MachineCode *code = - reinterpret_cast(new uint64_t[(MachineCode::SIZE + codeSize) / sizeof(uint64_t) + 1]); - code->SetInstructionSizeInBytes(nullptr, JSTaggedValue(codeSize), SKIP_BARRIER); - code->SetData(reinterpret_cast(codeBuff), codeSize); - module->SetCode(code); } } // namespace kungfu diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index 63677de..3fc988a 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -41,8 +41,15 @@ public: explicit LLVMModuleAssembler(LLVMStubModule *module, const char* triple) : stubmodule_(module), assembler_(module->GetModule(), triple) {} void AssembleModule(); - void CopyAssembleCodeToModule(panda::ecmascript::StubModule *module); - + void AssembleStubModule(panda::ecmascript::StubModule *module); + int GetCodeSize() const + { + return assembler_.GetCodeSize(); + } + void CopyAssemblerToCode(panda::ecmascript::MachineCode *code) + { + code->SetData(reinterpret_cast(assembler_.GetCodeBuffer()), assembler_.GetCodeSize()); + } private: LLVMStubModule *stubmodule_; LLVMAssembler assembler_; diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 2a93ff1..c6963d4 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -49,6 +49,13 @@ LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule bbIdMapBb_.clear(); } +LLVMIRBuilder::~LLVMIRBuilder() +{ + if (builder_ != nullptr) { + LLVMDisposeBuilder(builder_); + } +} + int LLVMIRBuilder::FindBasicBlock(AddrShift gate) const { for (size_t bbIdx = 0; bbIdx < schedule_->size(); bbIdx++) { @@ -146,6 +153,14 @@ void LLVMIRBuilder::AssignHandleMap() OpCode::DEPEND_SELECTOR, OpCode::DEPEND_RELAY, OpCode::DEPEND_AND}; } +std::string LLVMIRBuilder::LLVMValueToString(LLVMValueRef val) const +{ + char* msg = LLVMPrintValueToString(val); + std::string str(msg); + LLVMDisposeMessage(msg); + return str; +} + void LLVMIRBuilder::Build() { LOG_ECMA(INFO) << "LLVM IR Builder Create Id Map of Blocks..."; @@ -327,6 +342,7 @@ LLVMBasicBlockRef LLVMIRBuilder::EnsureLLVMBB(BasicBlock *bb) const if (impl->llvm_bb_) { return impl->llvm_bb_; } + std::string buf = "B" + std::to_string(bb->GetId()); LLVMBasicBlockRef llvmBB = LLVMAppendBasicBlock(function_, buf.c_str()); impl->llvm_bb_ = llvmBB; @@ -407,8 +423,8 @@ void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inLi AddrShift gateTmp = inList[paraIdx]; params[paraIdx - paraStartIndex] = g_values[gateTmp]; circuit_->Print(gateTmp); - LOG_ECMA(INFO) << "arg" << paraIdx - paraStartIndex << ": " - << LLVMPrintValueToString(params[paraIdx - paraStartIndex]); + LOG_ECMA(INFO) << "arg" << paraIdx - paraStartIndex << ": " << + LLVMValueToString(params[paraIdx - paraStartIndex]); } if (callee == nullptr) { LOG_ECMA(ERROR) << "callee nullptr"; @@ -513,7 +529,7 @@ void LLVMIRBuilder::VisitReturn(AddrShift gate, AddrShift popCount, const std::v LOG_ECMA(INFO) << " gate: " << gate << " popCount: " << popCount; LOG_ECMA(INFO) << " return: " << operand << " gateId: " << circuit_->GetId(operand); LLVMValueRef returnValue = g_values[operand]; - LOG_ECMA(INFO) << LLVMPrintValueToString(returnValue); + LOG_ECMA(INFO) << LLVMValueToString(returnValue); LLVMBuildRet(builder_, returnValue); } @@ -648,27 +664,24 @@ void LLVMIRBuilder::VisitInt32Constant(AddrShift gate, int32_t value) const { LLVMValueRef llvmValue = LLVMConstInt(LLVMInt32Type(), value, 0); g_values[gate] = llvmValue; - char *str = LLVMPrintValueToString(llvmValue); LOG_ECMA(INFO) << "VisitInt32Constant set gate:" << gate << " value:" << value; - LOG_ECMA(INFO) << "VisitInt32Constant " << str; + LOG_ECMA(INFO) << "VisitInt32Constant " << LLVMValueToString(llvmValue); } void LLVMIRBuilder::VisitInt64Constant(AddrShift gate, int64_t value) const { LLVMValueRef llvmValue = LLVMConstInt(LLVMInt64Type(), value, 0); g_values[gate] = llvmValue; - char *str = LLVMPrintValueToString(llvmValue); LOG_ECMA(INFO) << "VisitInt64Constant set gate:" << gate << " value:" << value; - LOG_ECMA(INFO) << "VisitInt64Constant " << str; + LOG_ECMA(INFO) << "VisitInt64Constant " << LLVMValueToString(llvmValue); } void LLVMIRBuilder::VisitFloat64Constant(AddrShift gate, double value) const { LLVMValueRef llvmValue = LLVMConstReal(LLVMDoubleType(), value); g_values[gate] = llvmValue; - char *str = LLVMPrintValueToString(llvmValue); LOG_ECMA(INFO) << "VisitFloat64Constant set gate:" << gate << " value:" << value; - LOG_ECMA(INFO) << "VisitFloat64Constant " << str; + LOG_ECMA(INFO) << "VisitFloat64Constant " << LLVMValueToString(llvmValue); } void LLVMIRBuilder::HandleParameter(AddrShift gate) @@ -688,8 +701,7 @@ void LLVMIRBuilder::VisitParameter(AddrShift gate) const LOG_ECMA(ERROR) << "generate LLVM IR for para: " << argth << "fail"; return; } - char *str = LLVMPrintValueToString(value); - LOG_ECMA(INFO) << "para arg:" << argth << "value IR:" << str; + LOG_ECMA(INFO) << "para arg:" << argth << "value IR:" << LLVMValueToString(value); } void LLVMIRBuilder::HandleBranch(AddrShift gate) @@ -713,12 +725,12 @@ void LLVMIRBuilder::VisitIntMod(AddrShift gate, AddrShift e1, AddrShift e2) cons { LOG_ECMA(INFO) << "int mod gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildSRem(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::HandleFloatMod(AddrShift gate) @@ -731,12 +743,12 @@ void LLVMIRBuilder::VisitFloatMod(AddrShift gate, AddrShift e1, AddrShift e2) co { LOG_ECMA(INFO) << "float mod gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFRem(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitBranch(AddrShift gate, AddrShift cmp, int btrue, int bfalse) @@ -826,24 +838,24 @@ void LLVMIRBuilder::VisitIntOrUintCmp(AddrShift gate, AddrShift e1, AddrShift e2 { LOG_ECMA(INFO) << "cmp gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildICmp(builder_, opcode, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitFloatOrDoubleCmp(AddrShift gate, AddrShift e1, AddrShift e2, LLVMRealPredicate opcode) const { LOG_ECMA(INFO) << "cmp gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFCmp(builder_, opcode, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::HandleIntRev(AddrShift gate) @@ -856,10 +868,10 @@ void LLVMIRBuilder::VisitIntRev(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "int sign invert gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildNeg(builder_, e1Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::HandleIntAdd(AddrShift gate) @@ -885,15 +897,15 @@ void LLVMIRBuilder::VisitIntAdd(AddrShift gate, AddrShift e1, AddrShift e2, Mach { LOG_ECMA(INFO) << "int add gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); if (LLVMGetTypeKind(LLVMTypeOf(e1Value)) == LLVMPointerTypeKind) { // for scenario: pointer + offset e1Value = LLVMBuildPtrToInt(builder_, e1Value, GetMachineRepType(rep), ""); } LLVMValueRef result = LLVMBuildAdd(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::HandleFloatAdd(AddrShift gate) @@ -907,12 +919,12 @@ void LLVMIRBuilder::VisitFloatAdd(AddrShift gate, AddrShift e1, AddrShift e2) co { LOG_ECMA(INFO) << "float add gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFAdd(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::HandleFloatSub(AddrShift gate) @@ -1074,72 +1086,72 @@ void LLVMIRBuilder::VisitFloatSub(AddrShift gate, AddrShift e1, AddrShift e2) co { LOG_ECMA(INFO) << "float sub gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFSub(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitFloatMul(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "float mul gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFMul(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitFloatDiv(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "float div gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFDiv(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitIntSub(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int sub gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildSub(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitIntMul(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int mul gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildMul(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitIntOr(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int or gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildOr(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::HandleIntAnd(AddrShift gate) @@ -1152,36 +1164,36 @@ void LLVMIRBuilder::VisitIntAnd(AddrShift gate, AddrShift e1, AddrShift e2) cons { LOG_ECMA(INFO) << "int and gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildAnd(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitIntXor(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int xor gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildXor(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitIntLsr(AddrShift gate, AddrShift e1, AddrShift e2) const { LOG_ECMA(INFO) << "int lsr gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildLShr(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::HandleIntLsl(AddrShift gate) @@ -1194,32 +1206,32 @@ void LLVMIRBuilder::VisitIntLsl(AddrShift gate, AddrShift e1, AddrShift e2) cons { LOG_ECMA(INFO) << "int lsl gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMPrintValueToString(e2Value); + LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildShl(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitZExtInt(AddrShift gate, AddrShift e1, MachineRep rep) const { LOG_ECMA(INFO) << "int zero extension gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildZExt(builder_, e1Value, GetMachineRepType(rep), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitSExtInt(AddrShift gate, AddrShift e1, MachineRep rep) const { LOG_ECMA(INFO) << "int sign extension gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildSExt(builder_, e1Value, GetMachineRepType(rep), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::HandleCastIntXToIntY(AddrShift gate) @@ -1245,20 +1257,20 @@ void LLVMIRBuilder::VisitCastIntXToIntY(AddrShift gate, AddrShift e1, MachineRep { LOG_ECMA(INFO) << "int cast2 int gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildIntCast2(builder_, e1Value, GetMachineRepType(rep), 1, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::VisitCastInt32ToDouble(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "int cast2 double gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildSIToFP(builder_, e1Value, LLVMDoubleType(), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::HandleCastInt64ToDouble(AddrShift gate) @@ -1271,10 +1283,10 @@ void LLVMIRBuilder::VisitCastInt64ToDouble(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "int cast2 double gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildBitCast(builder_, e1Value, LLVMDoubleType(), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } void LLVMIRBuilder::HandleCastDoubleToInt(AddrShift gate) @@ -1287,10 +1299,10 @@ void LLVMIRBuilder::VisitCastDoubleToInt(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "double cast2 int gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildBitCast(builder_, e1Value, LLVMInt64Type(), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } LLVMStubModule::LLVMStubModule(const char *name, const char *triple) diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index 5b9d6f4..3bb6735 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -197,8 +197,8 @@ public: LLVMModuleRef module, LLVMValueRef function); explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, LLVMStubModule *module, LLVMValueRef function); + ~LLVMIRBuilder(); void Build(); - ~LLVMIRBuilder() = default; private: #define DECLAREVISITOPCODE(name, signature) void Visit##name signature; @@ -222,6 +222,7 @@ private: void ProcessPhiWorkList(); void AssignHandleMap(); + std::string LLVMValueToString(LLVMValueRef val) const; private: const std::vector> *schedule_ {nullptr}; diff --git a/ecmascript/compiler/llvm_mcjit_engine.cpp b/ecmascript/compiler/llvm_mcjit_engine.cpp index 73d5071..3fb6d34 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.cpp +++ b/ecmascript/compiler/llvm_mcjit_engine.cpp @@ -106,7 +106,9 @@ void LLVMAssembler::BuildAndRunPasses() const LLVMAddConstantPropagationPass(pass); LLVMAddInstructionCombiningPass(pass); llvm::unwrap(pass)->add(llvm::createRewriteStatepointsForGCLegacyPass()); - LOG_ECMA(INFO) << "Current Module: " << LLVMPrintModuleToString(module_); + char *info = LLVMPrintModuleToString(module_); + LOG_ECMA(INFO) << "Current Module: " << info; + LLVMDisposeMessage(info); LLVMRunPassManager(pass, module_); LLVMDisposePassManager(pass); LOG_ECMA(INFO) << "BuildAndRunPasses + "; @@ -116,13 +118,14 @@ LLVMAssembler::LLVMAssembler(LLVMModuleRef module, const char* triple): module_( hostTriple_(triple), error_(nullptr) { Initialize(); - InitMember(); } LLVMAssembler::~LLVMAssembler() { module_ = nullptr; - engine_ = nullptr; + if (engine_ != nullptr) { + LLVMDisposeExecutionEngine(engine_); + } hostTriple_ = ""; error_ = nullptr; } @@ -212,13 +215,6 @@ void LLVMAssembler::Disassemble(std::map addr2name) const } } std::cout << "========================================================================" << std::endl; -} - -void LLVMAssembler::InitMember() -{ - if (module_ == nullptr) { - module_ = LLVMModuleCreateWithName("simple_module"); - LLVMSetTarget(module_, "x86_64-unknown-linux-gnu"); - } + LLVMDisasmDispose(dcr); } } // namespace kungfu diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index d1b3fff..79d0ab6 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -124,9 +124,20 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri LLVMModuleAssembler assembler(&stubModule, triple); assembler.AssembleModule(); - assembler.CopyAssembleCodeToModule(module); + assembler.AssembleStubModule(module); + auto codeSize = assembler.GetCodeSize(); + panda::ecmascript::MachineCode *code = reinterpret_cast( + new uint64_t[(panda::ecmascript::MachineCode::SIZE + codeSize) / sizeof(uint64_t) + 1]); + code->SetInstructionSizeInBytes(nullptr, panda::ecmascript::JSTaggedValue(codeSize), + panda::ecmascript::SKIP_BARRIER); + + assembler.CopyAssemblerToCode(code); + + module->SetCode(code); module->Save(filename); + + delete code; } } // namespace kungfu @@ -141,6 +152,7 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri SET_STUB_TO_MODULE(module, FastSub) \ SET_STUB_TO_MODULE(module, FastMul) \ SET_STUB_TO_MODULE(module, FastDiv) \ + SET_STUB_TO_MODULE(module, FastMod) \ SET_STUB_TO_MODULE(module, FindOwnElement) \ SET_STUB_TO_MODULE(module, GetElement) \ SET_STUB_TO_MODULE(module, FindOwnElement2) \ diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index bc59aad..135f379 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -336,10 +336,9 @@ CALL_STUB_INIT_DESCRIPTOR(FindElementWithCache) CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) { - // 2 : 2 input parameters - static StubDescriptor stringGetHashCode("StringGetHashCode", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + static StubDescriptor stringGetHashCode("StringGetHashCode", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); *descriptor = stringGetHashCode; - std::array params = { // // 2 : 2 input parameters + std::array params = { MachineType::UINT64_TYPE, }; descriptor->SetParameters(params.data()); diff --git a/ecmascript/mem/machine_code.h b/ecmascript/mem/machine_code.h index 90221bf..0181d96 100644 --- a/ecmascript/mem/machine_code.h +++ b/ecmascript/mem/machine_code.h @@ -24,8 +24,6 @@ namespace panda { namespace ecmascript { class MachineCode : public TaggedObject { public: - MachineCode(); - ~MachineCode(); NO_COPY_SEMANTIC(MachineCode); NO_MOVE_SEMANTIC(MachineCode); static MachineCode *Cast(ObjectHeader *object) -- Gitee From 96aa1e76231ab5809929d9f4b9a3404b38fffd34 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Thu, 14 Oct 2021 19:48:53 +0800 Subject: [PATCH 027/115] delete llvm_stackmap_parse so Signed-off-by: surpassgoodchao --- BUILD.gn | 5 +---- ecmascript/compiler/BUILD.gn | 3 --- ecmascript/compiler/llvm/BUILD.gn | 28 ---------------------------- ecmascript/compiler/tests/BUILD.gn | 1 - ecmascript/tooling/BUILD.gn | 1 - 5 files changed, 1 insertion(+), 37 deletions(-) delete mode 100644 ecmascript/compiler/llvm/BUILD.gn diff --git a/BUILD.gn b/BUILD.gn index 404fa23..4e7eeb9 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -375,6 +375,7 @@ ecma_source = [ "ecmascript/vmstat/caller_stat.cpp", "ecmascript/vmstat/runtime_stat.cpp", "ecmascript/weak_vector.cpp", + "ecmascript/compiler/llvm/llvm_stackmap_parser.cpp", ] ecma_source += [ @@ -395,7 +396,6 @@ source_set("libark_jsruntime_static") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", - "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", sdk_libc_secshared_dep, ] @@ -438,7 +438,6 @@ source_set("libark_jsruntime_test_static") { ":copy_resource_xml", "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", - "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", "//third_party/icu/icu4c:shared_icui18n", "//third_party/icu/icu4c:shared_icuuc", sdk_libc_secshared_dep, @@ -473,8 +472,6 @@ ohos_shared_library("libark_jsruntime_test") { } else { deps += [ "$ark_root/runtime:libarkruntime" ] } - deps += - [ "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser" ] output_extension = "so" subsystem_name = "test" diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index 8599902..f217398 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -141,7 +141,6 @@ ohos_shared_library("libark_jsoptimizer") { deps = [ ":libark_jsoptimizer_static", "//ark/js_runtime:libark_jsruntime", - "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", ] if (compile_llvm_online) { @@ -166,8 +165,6 @@ ohos_shared_library("libark_jsoptimizer_test") { if (is_standard_system) { deps += [ "$ark_root/runtime:libarkruntime_static" ] - deps += - [ "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser" ] } else { deps += [ "$ark_root/runtime:libarkruntime" ] } diff --git a/ecmascript/compiler/llvm/BUILD.gn b/ecmascript/compiler/llvm/BUILD.gn deleted file mode 100644 index b5895f3..0000000 --- a/ecmascript/compiler/llvm/BUILD.gn +++ /dev/null @@ -1,28 +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. - -import("//ark/js_runtime/js_runtime_config.gni") -import("//build/ohos.gni") - -ohos_shared_library("libllvm_stackmap_parser") { - sources = [ "llvm_stackmap_parser.cpp" ] - - install_enable = true - part_name = "ark_js_runtime" - - output_extension = "so" - if (!is_standard_system) { - relative_install_dir = "ark" - } - subsystem_name = "ark" -} diff --git a/ecmascript/compiler/tests/BUILD.gn b/ecmascript/compiler/tests/BUILD.gn index 7adb64d..2035a33 100644 --- a/ecmascript/compiler/tests/BUILD.gn +++ b/ecmascript/compiler/tests/BUILD.gn @@ -114,7 +114,6 @@ host_unittest_action("StubTest") { deps = [ "$ark_root/libpandabase:libarkbase", "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer_test(${host_toolchain})", - "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", sdk_libc_secshared_dep, ] } diff --git a/ecmascript/tooling/BUILD.gn b/ecmascript/tooling/BUILD.gn index acd0fc6..c25bf31 100644 --- a/ecmascript/tooling/BUILD.gn +++ b/ecmascript/tooling/BUILD.gn @@ -92,7 +92,6 @@ ohos_shared_library("libark_ecma_debugger_test") { deps = [ ":libark_ecma_debugger_test_static", "//ark/js_runtime:libark_jsruntime_test_static", - "//ark/js_runtime/ecmascript/compiler/llvm:libllvm_stackmap_parser", ] configs = [ -- Gitee From 96a03dc5e5205db22ef956f892db9d751fdc7dc2 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Thu, 14 Oct 2021 21:36:56 +0800 Subject: [PATCH 028/115] fix length error of Chainese char Signed-off-by: wengchangcheng --- ecmascript/ecma_string.h | 2 +- ecmascript/napi/test/jsnapi_tests.cpp | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ecmascript/ecma_string.h b/ecmascript/ecma_string.h index 4992957..53fdd3a 100644 --- a/ecmascript/ecma_string.h +++ b/ecmascript/ecma_string.h @@ -138,7 +138,7 @@ public: } return length; } - return base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf, length, maxLength - 1, start) - 1; + return base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf, length, maxLength - 1, start); } inline uint32_t CopyDataUtf16(uint16_t *buf, uint32_t maxLength) const diff --git a/ecmascript/napi/test/jsnapi_tests.cpp b/ecmascript/napi/test/jsnapi_tests.cpp index 8e14616..bb0ce36 100644 --- a/ecmascript/napi/test/jsnapi_tests.cpp +++ b/ecmascript/napi/test/jsnapi_tests.cpp @@ -192,15 +192,28 @@ HWTEST_F_L0(JSNApiTests, Symbol) ASSERT_TRUE(symbol->IsSymbol()); } -HWTEST_F_L0(JSNApiTests, StringUtf8) +HWTEST_F_L0(JSNApiTests, StringUtf8_001) { LocalScope scope(vm_); std::string test = "Hello world"; Local testString = StringRef::NewFromUtf8(vm_, test.c_str()); - ASSERT_TRUE(testString->Utf8Length() == 12); // 12 : length of testString("Hello World") + EXPECT_TRUE(testString->Utf8Length() == 12); // 12 : length of testString("Hello World") char buffer[12]; // 12 : length of testString - ASSERT_TRUE(testString->WriteUtf8(buffer, 12) == 12); // 12 : length of testString("Hello World") + EXPECT_TRUE(testString->WriteUtf8(buffer, 12) == 12); // 12 : length of testString("Hello World") + std::string res(buffer); + ASSERT_EQ(res, test); +} + +HWTEST_F_L0(JSNApiTests, StringUtf8_002) +{ + LocalScope scope(vm_); + std::string test = "年"; + Local testString = StringRef::NewFromUtf8(vm_, test.c_str()); + + EXPECT_TRUE(testString->Utf8Length() == 4); // 4 : length of testString("年") + char buffer[4]; // 4 : length of testString + EXPECT_TRUE(testString->WriteUtf8(buffer, 4) == 4); // 4 : length of testString("年") std::string res(buffer); ASSERT_EQ(res, test); } -- Gitee From df5eaeb715344567b498d1955d79dcb2b329e22b Mon Sep 17 00:00:00 2001 From: wanyanglan Date: Fri, 15 Oct 2021 11:59:23 +0800 Subject: [PATCH 029/115] Temporarily shield some use cases of stubbest Signed-off-by: wanyanglan Change-Id: I167df367d753faf61287a2e67f4a8565daafa2cc --- ecmascript/compiler/tests/stub_tests.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 8ef83ef..173fda7 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -1070,6 +1070,7 @@ void DoSafepoint() } } +#ifdef NDEBUG HWTEST_F_L0(StubTest, GetPropertyByIndexStub) { auto module = stubModule.GetModule(); @@ -1131,6 +1132,7 @@ HWTEST_F_L0(StubTest, SetPropertyByIndexStub) JSArray::FastGetPropertyByValue(thread, JSHandle::Cast(array), i).GetTaggedValue()); } } +#endif HWTEST_F_L0(StubTest, GetPropertyByNameStub) { -- Gitee From 7d667e38f0be6fb536e04af4ae2b793f428131db Mon Sep 17 00:00:00 2001 From: lichenshuai Date: Fri, 15 Oct 2021 17:20:37 +0800 Subject: [PATCH 030/115] Add support for relative path and enable moduleAction. Signed-off-by: lichenshuai --- ecmascript/ecma_vm.cpp | 15 +++++++++++++++ test/moduletest/BUILD.gn | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index e00c372..0609e82 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -690,6 +690,21 @@ JSHandle EcmaVM::GetModuleByName(JSHandle moduleNa auto pos = scriptName.find_last_of('.'); CString abcPath = dirPath.append(scriptName.substr(0, pos == std::string::npos ? 0 : pos)).append(".abc"); + // handle relative path + if (abcPath.find("./") == 0) { // starts with "./" + std::string fullPath = std::get<1>(pandaFileWithProgram_.back())->GetFilename(); + auto lastSlash = fullPath.find_last_of('/'); + if (lastSlash != std::string::npos) { + abcPath = fullPath.substr(0, lastSlash).append(abcPath.substr(1)); // 1: ignore "." + } + } else if (abcPath.find("../") == 0) { // starts with "../" + std::string fullPath = std::get<1>(pandaFileWithProgram_.back())->GetFilename(); + auto lastSlash = fullPath.find_last_of('/'); + if (lastSlash != std::string::npos) { + abcPath = fullPath.substr(0, lastSlash + 1).append(abcPath); // 1: with "/" + } + } + // Uniform module name JSHandle abcModuleName = factory_->NewFromString(abcPath); diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index a2fe10f..0648fb4 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -25,7 +25,7 @@ group("ark_js_moduletest") { "helloworld:helloworldAction", "lexicalenv:lexicalenvAction", - # "module:moduleAction", + "module:moduleAction", "multiargs:multiargsAction", "newobjdynrange:newobjdynrangeAction", "promise:promiseAction", -- Gitee From 91bca28537f84a078ad2e98931d9ae595590437c Mon Sep 17 00:00:00 2001 From: Gongyuhang <517563583@qq.com> Date: Fri, 15 Oct 2021 17:49:39 +0800 Subject: [PATCH 031/115] add the brackets Signed-off-by: Gongyuhang <517563583@qq.com> --- ecmascript/ecma_string.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecmascript/ecma_string.cpp b/ecmascript/ecma_string.cpp index 1cab135..797848f 100644 --- a/ecmascript/ecma_string.cpp +++ b/ecmascript/ecma_string.cpp @@ -415,7 +415,7 @@ uint32_t EcmaString::ComputeHashcode() const hash = ComputeHashForData(GetDataUtf16(), GetLength()); } } else { - ASSERT(static_cast(GetLength()) < std::numeric_limits::max() >> 1U); + ASSERT(static_cast(GetLength()) < (std::numeric_limits::max() >> 1U)); hash = ComputeHashForData(GetDataUtf16(), GetLength()); } return hash; -- Gitee From 7dd6afa6b2131c5c3bf5e014fdc5a087d9032bc1 Mon Sep 17 00:00:00 2001 From: lichenshuai Date: Mon, 18 Oct 2021 09:32:22 +0800 Subject: [PATCH 032/115] Modified for codeCheck. Signed-off-by: lichenshuai --- ecmascript/ecma_vm.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 0609e82..006fcda 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -689,7 +689,6 @@ JSHandle EcmaVM::GetModuleByName(JSHandle moduleNa // need to check abc file auto pos = scriptName.find_last_of('.'); CString abcPath = dirPath.append(scriptName.substr(0, pos == std::string::npos ? 0 : pos)).append(".abc"); - // handle relative path if (abcPath.find("./") == 0) { // starts with "./" std::string fullPath = std::get<1>(pandaFileWithProgram_.back())->GetFilename(); -- Gitee From 4d8c0e87bf4acab192b0dea326782546b4791de9 Mon Sep 17 00:00:00 2001 From: lichenshuai Date: Mon, 18 Oct 2021 09:32:22 +0800 Subject: [PATCH 033/115] Modified for codeCheck. Signed-off-by: lichenshuai --- test/moduletest/BUILD.gn | 1 - 1 file changed, 1 deletion(-) diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index 0648fb4..ea18c4b 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -24,7 +24,6 @@ group("ark_js_moduletest") { "globalrecord:globalrecordAction", "helloworld:helloworldAction", "lexicalenv:lexicalenvAction", - "module:moduleAction", "multiargs:multiargsAction", "newobjdynrange:newobjdynrangeAction", -- Gitee From 7ae9944ad31fa47e5662d8e400aba64660d93402 Mon Sep 17 00:00:00 2001 From: xujie Date: Mon, 18 Oct 2021 14:22:40 +0800 Subject: [PATCH 034/115] fix SerializeKeys gc bug Signed-off-by: xujie --- ecmascript/base/json_stringifier.cpp | 23 +++++++++++++---------- ecmascript/base/json_stringifier.h | 11 ++++++++++- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/ecmascript/base/json_stringifier.cpp b/ecmascript/base/json_stringifier.cpp index 719f4a7..56b1a5e 100644 --- a/ecmascript/base/json_stringifier.cpp +++ b/ecmascript/base/json_stringifier.cpp @@ -631,21 +631,23 @@ bool JsonStringifier::SerializeElements(const JSHandle &obj, const JSH } } else { JSHandle numberDic(elementsArr); - CVector sortArr; + CVector> sortArr; int size = numberDic->Size(); for (int hashIndex = 0; hashIndex < size; hashIndex++) { JSTaggedValue key = numberDic->GetKey(hashIndex); if (!key.IsUndefined() && !key.IsHole()) { PropertyAttributes attr = numberDic->GetAttributes(hashIndex); if (attr.IsEnumerable()) { - sortArr.emplace_back(JSTaggedValue(static_cast(key.GetInt()))); + JSTaggedValue numberKey = JSTaggedValue(static_cast(key.GetInt())); + sortArr.emplace_back(JSHandle(thread_, numberKey)); } } } - std::sort(sortArr.begin(), sortArr.end(), NumberDictionary::CompKey); + std::sort(sortArr.begin(), sortArr.end(), CompareNumber); for (const auto &entry : sortArr) { - handleKey_.Update(entry); - int index = numberDic->FindEntry(entry); + JSTaggedValue entryKey = entry.GetTaggedValue(); + handleKey_.Update(entryKey); + int index = numberDic->FindEntry(entryKey); JSTaggedValue value = numberDic->GetValue(index); handleValue_.Update(value); hasContent = JsonStringifier::AppendJsonString(obj, replacer, hasContent); @@ -720,7 +722,7 @@ bool JsonStringifier::SerializeKeys(const JSHandle &obj, const JSHandl } JSHandle nameDic(propertiesArr); int size = nameDic->Size(); - CVector> sortArr; + CVector, PropertyAttributes>> sortArr; for (int hashIndex = 0; hashIndex < size; hashIndex++) { JSTaggedValue key = nameDic->GetKey(hashIndex); if (!key.IsString()) { @@ -730,13 +732,14 @@ bool JsonStringifier::SerializeKeys(const JSHandle &obj, const JSHandl if (!attr.IsEnumerable()) { continue; } - std::pair pair(key, attr); + std::pair, PropertyAttributes> pair(JSHandle(thread_, key), attr); sortArr.emplace_back(pair); } - std::sort(sortArr.begin(), sortArr.end(), NameDictionary::CompKey); + std::sort(sortArr.begin(), sortArr.end(), CompareKey); for (const auto &entry : sortArr) { - handleKey_.Update(entry.first); - int index = nameDic->FindEntry(entry.first); + JSTaggedValue entryKey = entry.first.GetTaggedValue(); + handleKey_.Update(entryKey); + int index = nameDic->FindEntry(entryKey); JSTaggedValue value = nameDic->GetValue(index); if (UNLIKELY(value.IsAccessor())) { value = JSObject::CallGetter(thread_, AccessorData::Cast(value.GetTaggedObject()), diff --git a/ecmascript/base/json_stringifier.h b/ecmascript/base/json_stringifier.h index 6979f0e..b4f1401 100644 --- a/ecmascript/base/json_stringifier.h +++ b/ecmascript/base/json_stringifier.h @@ -66,7 +66,16 @@ private: bool SerializeElements(const JSHandle &obj, const JSHandle &replacer, bool hasContent); bool SerializeKeys(const JSHandle &obj, const JSHandle &replacer, bool hasContent); - static void FastStorePropertyByIndex(JSThread *thread, JSTaggedValue obj, uint32_t idx, JSTaggedValue value); + static inline bool CompareKey(const std::pair, PropertyAttributes> &a, + const std::pair, PropertyAttributes> &b) + { + return a.second.GetDictionaryOrder() < b.second.GetDictionaryOrder(); + } + + static inline bool CompareNumber(const JSHandle &a, const JSHandle &b) + { + return a->GetNumber() < b->GetNumber(); + } CString gap_; CString result_; -- Gitee From 84968c06771450f20eed58764e238da0e6c3fe38 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Mon, 18 Oct 2021 16:54:11 +0800 Subject: [PATCH 035/115] seperate debugger notification manager of js and java Signed-off-by: wengchangcheng --- ecmascript/ecma_vm.cpp | 15 ++++++++++++--- ecmascript/ecma_vm.h | 8 +++++++- ecmascript/interpreter/interpreter-inl.h | 2 +- ecmascript/tooling/agent/js_backend.cpp | 4 ++-- ecmascript/tooling/interface/debugger_api.cpp | 4 ++-- ecmascript/tooling/interface/debugger_api.h | 2 +- ecmascript/tooling/interface/js_debugger.h | 15 +++------------ .../tooling/test/debugger_commands_test.cpp | 2 +- 8 files changed, 29 insertions(+), 23 deletions(-) diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 006fcda..569edd1 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -113,6 +113,10 @@ EcmaVM::EcmaVM(RuntimeOptions options) } fileName_ = options_.GetSnapshotFile(); frameworkAbcFileName_ = options_.GetFrameworkAbcFile(); + + auto runtime = Runtime::GetCurrent(); + notificationManager_ = chunk_.New(runtime->GetInternalAllocator()); + notificationManager_->SetRendezvous(rendezvous_); } bool EcmaVM::Initialize() @@ -184,8 +188,8 @@ bool EcmaVM::Initialize() moduleManager_ = new ModuleManager(this); InitializeFinish(); - Runtime::GetCurrent()->GetNotificationManager()->VmStartEvent(); - Runtime::GetCurrent()->GetNotificationManager()->VmInitializationEvent(0); + notificationManager_->VmStartEvent(); + notificationManager_->VmInitializationEvent(0); return true; } @@ -263,6 +267,11 @@ EcmaVM::~EcmaVM() delete regExpParserCache_; regExpParserCache_ = nullptr; + if (notificationManager_ != nullptr) { + chunk_.Delete(notificationManager_); + notificationManager_ = nullptr; + } + if (factory_ != nullptr) { chunk_.Delete(factory_); factory_ = nullptr; @@ -456,7 +465,7 @@ void EcmaVM::AddPandaFile(const panda_file::File *pf, bool isModule) pandaFileWithProgram_.push_back(std::make_tuple(nullptr, pf, isModule)); // for debugger - Runtime::GetCurrent()->GetNotificationManager()->LoadModuleEvent(pf->GetFilename()); + notificationManager_->LoadModuleEvent(pf->GetFilename()); } void EcmaVM::SetProgram(Program *program, const panda_file::File *pf) diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index 94c5079..cde72c5 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -38,6 +38,7 @@ #include "libpandabase/os/library_loader.h" namespace panda { +class RuntimeNotificationManager; namespace panda_file { class File; } // namespace panda_file @@ -346,7 +347,10 @@ public: return JSHandle(reinterpret_cast(®expCache_)); } - friend class ValueSerializer; + RuntimeNotificationManager *GetNotificationManager() const + { + return notificationManager_; + } protected: bool CheckEntrypointSignature([[maybe_unused]] Method *entrypoint) override @@ -403,6 +407,7 @@ private: CString frameworkAbcFileName_; bool isTestMode_{false}; + RuntimeNotificationManager *notificationManager_ {nullptr}; // init EcmaVM Create JSThread *thread_{nullptr}; @@ -433,6 +438,7 @@ private: friend class SnapShotSerialize; friend class ObjectFactory; + friend class ValueSerializer; }; } // namespace ecmascript } // namespace panda diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index c1a2cc4..ad41ab5 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -461,7 +461,7 @@ void EcmaInterpreter::NotifyBytecodePcChanged(JSThread *thread) continue; } auto bcOffset = frameHandler.GetBytecodeOffset(); - Runtime::GetCurrent()->GetNotificationManager()->BytecodePcChangedEvent(thread, method, bcOffset); + thread->GetEcmaVM()->GetNotificationManager()->BytecodePcChangedEvent(thread, method, bcOffset); return; } } diff --git a/ecmascript/tooling/agent/js_backend.cpp b/ecmascript/tooling/agent/js_backend.cpp index d461c61..f7dd532 100644 --- a/ecmascript/tooling/agent/js_backend.cpp +++ b/ecmascript/tooling/agent/js_backend.cpp @@ -32,14 +32,14 @@ JSBackend::JSBackend(FrontEnd *frontend) : frontend_(frontend) ecmaVm_ = static_cast(frontend)->GetEcmaVM(); hooks_ = std::make_unique(this); - debugger_ = DebuggerApi::CreateJSDebugger(Runtime::GetCurrent(), ecmaVm_); + debugger_ = DebuggerApi::CreateJSDebugger(ecmaVm_); DebuggerApi::RegisterHooks(debugger_, hooks_.get()); } JSBackend::JSBackend(const EcmaVM *vm) : ecmaVm_(vm) { // For testcases - debugger_ = DebuggerApi::CreateJSDebugger(Runtime::GetCurrent(), ecmaVm_); + debugger_ = DebuggerApi::CreateJSDebugger(ecmaVm_); } JSBackend::~JSBackend() diff --git a/ecmascript/tooling/interface/debugger_api.cpp b/ecmascript/tooling/interface/debugger_api.cpp index ef48956..84ec85a 100644 --- a/ecmascript/tooling/interface/debugger_api.cpp +++ b/ecmascript/tooling/interface/debugger_api.cpp @@ -162,9 +162,9 @@ double DebuggerApi::StringToDouble(const uint8_t *start, const uint8_t *end, uin } // JSDebugger -JSDebugger *DebuggerApi::CreateJSDebugger(Runtime *runtime, const EcmaVM *ecmaVm) +JSDebugger *DebuggerApi::CreateJSDebugger(const EcmaVM *ecmaVm) { - return new JSDebugger(runtime, ecmaVm); + return new JSDebugger(ecmaVm); } void DebuggerApi::DestroyJSDebugger(JSDebugger *debugger) diff --git a/ecmascript/tooling/interface/debugger_api.h b/ecmascript/tooling/interface/debugger_api.h index e030405..4c94ee3 100644 --- a/ecmascript/tooling/interface/debugger_api.h +++ b/ecmascript/tooling/interface/debugger_api.h @@ -83,7 +83,7 @@ public: static double StringToDouble(const uint8_t *start, const uint8_t *end, uint8_t radix); // JSDebugger - static JSDebugger *CreateJSDebugger(Runtime *runtime, const EcmaVM *ecmaVm); + static JSDebugger *CreateJSDebugger(const EcmaVM *ecmaVm); static void DestroyJSDebugger(JSDebugger *debugger); static std::optional RegisterHooks(JSDebugger *debugger, PtHooks *hooks); static std::optional SetBreakpoint(JSDebugger *debugger, const PtLocation &location); diff --git a/ecmascript/tooling/interface/js_debugger.h b/ecmascript/tooling/interface/js_debugger.h index 416ab5c..f0b4de9 100644 --- a/ecmascript/tooling/interface/js_debugger.h +++ b/ecmascript/tooling/interface/js_debugger.h @@ -27,23 +27,15 @@ using panda::ecmascript::CUnorderedSet; class JSDebugger : public DebugInterface, RuntimeListener { public: - JSDebugger(const Runtime *runtime, const EcmaVM *vm) : runtime_(runtime), ecmaVm_(vm) + JSDebugger(const EcmaVM *vm) : ecmaVm_(vm) { - auto notificationMgr = runtime_->GetNotificationManager(); - // set EcmaVM rendezvous - notificationMgr->SetRendezvous(ecmaVm_->GetRendezvous()); + auto notificationMgr = ecmaVm_->GetNotificationManager(); notificationMgr->AddListener(this, JSDEBUG_EVENT_MASK); - // set PandaVM rendezvous - notificationMgr->SetRendezvous(runtime_->GetPandaVM()->GetRendezvous()); } ~JSDebugger() override { - auto notificationMgr = runtime_->GetNotificationManager(); - // set EcmaVM rendezvous - notificationMgr->SetRendezvous(ecmaVm_->GetRendezvous()); + auto notificationMgr = ecmaVm_->GetNotificationManager(); notificationMgr->RemoveListener(this, JSDEBUG_EVENT_MASK); - // set PandaVM rendezvous - notificationMgr->SetRendezvous(runtime_->GetPandaVM()->GetRendezvous()); } std::optional RegisterHooks(PtHooks *hooks) override @@ -234,7 +226,6 @@ private: void HandleExceptionThrowEvent(const JSThread *thread, const JSMethod *method, uint32_t bcOffset); bool HandleStep(const JSThread *thread, const JSMethod *method, uint32_t bcOffset); - const Runtime *runtime_; const EcmaVM *ecmaVm_; PtHooks *hooks_ {nullptr}; diff --git a/ecmascript/tooling/test/debugger_commands_test.cpp b/ecmascript/tooling/test/debugger_commands_test.cpp index d2d9c53..cc9c1bf 100644 --- a/ecmascript/tooling/test/debugger_commands_test.cpp +++ b/ecmascript/tooling/test/debugger_commands_test.cpp @@ -62,7 +62,7 @@ protected: HWTEST_F_L0(DebuggerCommandsTest, CreateDebuggerTest) { - std::unique_ptr debugger = std::make_unique(Runtime::GetCurrent(), ecmaVm); + std::unique_ptr debugger = std::make_unique(ecmaVm); ASSERT_NE(debugger, nullptr); } } // namespace panda::test \ No newline at end of file -- Gitee From 03efe364c590f6341939f487e812c392ae62a832 Mon Sep 17 00:00:00 2001 From: DaiHN Date: Mon, 18 Oct 2021 19:29:23 +0800 Subject: [PATCH 036/115] IC polymorphic optimization Signed-off-by: DaiHN --- ecmascript/interpreter/interpreter-inl.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index c1a2cc4..4896537 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -2501,7 +2501,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool if (LIKELY(firstValue.IsHeapObject())) { JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryLoadICByValue(thread, receiver, propKey, firstValue, secondValue); - } else if (firstValue.IsUndefined()) { + } + if (res.IsHole() && !firstValue.IsHole()) { //ic miss not mega res = ICRuntimeStub::LoadICByValue(thread, profileTypeArray, receiver, propKey, slotId); @@ -2552,7 +2553,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool if (LIKELY(firstValue.IsHeapObject())) { JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryStoreICByValue(thread, receiver, propKey, firstValue, secondValue, value); - } else if (firstValue.IsUndefined()) { + } + if (res.IsHole() && !firstValue.IsHole()) { //ic miss not mega res = ICRuntimeStub::StoreICByValue(thread, profileTypeArray, receiver, propKey, value, slotId); @@ -2864,7 +2866,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool if (LIKELY(firstValue.IsHeapObject())) { JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryLoadICByName(thread, receiver, firstValue, secondValue); - } else if (firstValue.IsUndefined()) { + } + if (res.IsHole() && !firstValue.IsHole()) { //ic miss not mega uint32_t stringId = READ_INST_32_1(); JSTaggedValue propKey = constpool->GetObjectFromCache(stringId); res = ICRuntimeStub::LoadICByName(thread, @@ -2918,7 +2921,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool if (LIKELY(firstValue.IsHeapObject())) { JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryStoreICByName(thread, receiver, firstValue, secondValue, value); - } else if (firstValue.IsUndefined()) { + } + if (res.IsHole() && !firstValue.IsHole()) { //ic miss not mega uint32_t stringId = READ_INST_32_1(); JSTaggedValue propKey = constpool->GetObjectFromCache(stringId); res = ICRuntimeStub::StoreICByName(thread, -- Gitee From 50ee964a21d1f799421d5f5f1fb26500684cfbf4 Mon Sep 17 00:00:00 2001 From: wupengyong Date: Mon, 18 Oct 2021 11:32:58 +0800 Subject: [PATCH 037/115] add function call and bugfix ThrowTypeAndReturn Signed-off-by: wupengyong Change-Id: I085d81d00b00a0b49daa0d28af591b83dc1c9759 --- ecmascript/compiler/fast_stub.cpp | 25 +++++++++++++++++ ecmascript/compiler/fast_stub.h | 10 +++++++ ecmascript/compiler/fast_stub_define.h | 2 ++ ecmascript/compiler/stub.cpp | 5 ++-- ecmascript/compiler/stub.h | 30 +++++++++++++++++++++ ecmascript/compiler/stub_aot_compiler.cpp | 1 + ecmascript/compiler/stub_descriptor.cpp | 33 +++++++++++++++++++++++ ecmascript/compiler/tests/stub_tests.cpp | 16 +++++++++++ ecmascript/message_string.h | 5 ++-- ecmascript/runtime_trampolines.cpp | 17 ++++++++++++ ecmascript/runtime_trampolines.h | 1 + 11 files changed, 141 insertions(+), 4 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 2dee2e8..0b9bf37 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -1160,4 +1160,29 @@ void FastModStub::GenerateCircuit() } } } + +void FunctionCallInternalStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift func = PtrArgument(1); + AddrShift thisArg = Int64Argument(2); /* 2 : 3rd parameter is value */ + AddrShift argc = Int32Argument(3); /* 3 : 4th parameter is value */ + AddrShift argv = PtrArgument(4); /* 4 : 5th parameter is ptr */ + Label funcNotBuiltinsConstructor(env); + Label funcIsBuiltinsConstructorOrFuncNotClassConstructor(env); + Label funcIsClassConstructor(env); + Branch(NotBuiltinsConstructor(func), &funcNotBuiltinsConstructor, + &funcIsBuiltinsConstructorOrFuncNotClassConstructor); + Bind(&funcNotBuiltinsConstructor); + { + Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcIsBuiltinsConstructorOrFuncNotClassConstructor); + Bind(&funcIsClassConstructor); + ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(FunctionCallNotConstructor), FalseConstant()); + } + Bind(&funcIsBuiltinsConstructorOrFuncNotClassConstructor); + StubDescriptor *execute = GET_STUBDESCRIPTOR(Execute); + Return(CallRuntime(execute, thread, GetWord64Constant(FAST_STUB_ID(Execute)), + {thread, func, thisArg, argc, argv})); +} } // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 109b7be..642d5c2 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -149,5 +149,15 @@ public: NO_COPY_SEMANTIC(FastModStub); void GenerateCircuit() override; }; + +class FunctionCallInternalStub : public Stub { +public: + // 5 : 5 means argument counts + explicit FunctionCallInternalStub(Circuit *circuit) : Stub("FunctionCallInternal", 5, circuit) {} + ~FunctionCallInternalStub() = default; + NO_MOVE_SEMANTIC(FunctionCallInternalStub); + NO_COPY_SEMANTIC(FunctionCallInternalStub); + void GenerateCircuit() override; +}; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index 036fc11..9147c85 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -27,6 +27,7 @@ namespace kungfu { V(JSProxySetProperty, 6) \ V(GetHash32, 2) \ V(FindElementWithCache, 4) \ + V(Execute, 5) \ V(StringGetHashCode, 1) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) @@ -57,6 +58,7 @@ namespace kungfu { V(FindOwnProperty2, 6) \ V(FindOwnElement2, 6) \ V(GetPropertyByIndex, 3) \ + V(FunctionCallInternal, 5) \ V(SetPropertyByIndex, 4) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index d5e801f..4550be2 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -646,9 +646,10 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a void Stub::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val) { + AddrShift taggedId = GetInteger32Constant(messageId); StubDescriptor *throwTypeError = GET_STUBDESCRIPTOR(ThrowTypeError); - AddrShift taggedId = IntBuildTagged(GetInteger32Constant(messageId)); - CallStub(throwTypeError, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), {thread, taggedId}); + CallRuntime(throwTypeError, thread, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), + {thread, taggedId}); Return(val); } diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 1ae07f2..c6042d4 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -22,6 +22,7 @@ #include "ecmascript/compiler/circuit_builder.h" #include "ecmascript/compiler/gate.h" #include "ecmascript/compiler/stub_descriptor.h" +#include "ecmascript/js_function.h" #include "ecmascript/js_object.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/layout_info.h" @@ -1065,6 +1066,35 @@ public: GetWord64Constant(0)); } + AddrShift NotBuiltinsConstructor(AddrShift object) + { + AddrShift hclass = LoadHClass(object); + AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + + AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + // decode + return Word64Equal( + Word64And( + Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::BuiltinsCtorBit::START_BIT)), + GetWord64Constant((1LLU << panda::ecmascript::JSHClass::BuiltinsCtorBit::SIZE) - 1)), + GetWord64Constant(0)); + } + + AddrShift IsClassConstructor(AddrShift object) + { + AddrShift functionInfoFlagOffset = GetPtrConstant(panda::ecmascript::JSFunction::FUNCTION_INFO_FLAG_OFFSET); + AddrShift functionInfoTaggedValue = Load(MachineType::UINT64_TYPE, object, functionInfoFlagOffset); + AddrShift functionInfoInt32 = TaggedCastToInt32(functionInfoTaggedValue); + AddrShift functionInfoFlag = ZExtInt32ToInt64(functionInfoInt32); + // decode + return Word64NotEqual( + Word64And( + Word64LSR(functionInfoFlag, + GetWord64Constant(panda::ecmascript::JSFunction::ClassConstructorBit::START_BIT)), + GetWord64Constant((1LLU << panda::ecmascript::JSFunction::ClassConstructorBit::SIZE) - 1)), + GetWord64Constant(0)); + } + AddrShift IsExtensible(AddrShift object) { AddrShift hclass = LoadHClass(object); diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index 79d0ab6..6bfb263 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -159,6 +159,7 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri SET_STUB_TO_MODULE(module, SetElement) \ SET_STUB_TO_MODULE(module, GetPropertyByIndex) \ SET_STUB_TO_MODULE(module, SetPropertyByIndex) \ + SET_STUB_TO_MODULE(module, FunctionCallInternal) \ SET_STUB_TO_MODULE(module, GetPropertyByName) int main(const int argc, const char **argv) diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 135f379..ea20f07 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -334,6 +334,39 @@ CALL_STUB_INIT_DESCRIPTOR(FindElementWithCache) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } +CALL_STUB_INIT_DESCRIPTOR(Execute) +{ + // 5 : 5 input parameters + static StubDescriptor execute("Execute", 0, 5, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + *descriptor = execute; + std::array params = { // 5 : 5 input parameters + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT32_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + +CALL_STUB_INIT_DESCRIPTOR(FunctionCallInternal) +{ + // 5 : 5 input parameters + static StubDescriptor functionCallInternal("FunctionCallInternal", 0, 5, + ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + *descriptor = functionCallInternal; + std::array params = { // 5 : 5 input parameters + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT32_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) { static StubDescriptor stringGetHashCode("StringGetHashCode", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 173fda7..8bd6d0b 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -502,6 +502,22 @@ HWTEST_F_L0(StubTest, FastFindOwnElementStub) assembler.Run(); } +HWTEST_F_L0(StubTest, FunctionCallInternal) +{ + auto module = stubModule.GetModule(); + auto findFunction = stubModule.GetStubFunction(FAST_STUB_ID(FunctionCallInternal)); + Circuit netOfGates; + FunctionCallInternalStub optimizer(&netOfGates); + optimizer.GenerateCircuit(); + netOfGates.PrintAllGates(); + auto cfg = Scheduler::Run(&netOfGates); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction); + llvmBuilder.Build(); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); + assembler.Run(); +} + HWTEST_F_L0(StubTest, GetElementStub) { auto module = stubModule.GetModule(); diff --git a/ecmascript/message_string.h b/ecmascript/message_string.h index 61a6ba1..144f8bd 100644 --- a/ecmascript/message_string.h +++ b/ecmascript/message_string.h @@ -20,8 +20,9 @@ namespace panda::ecmascript { // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define MESSAGE_STRING_LIST(V) \ - V(SetReadOnlyProperty, "Cannot set readonly property") \ +#define MESSAGE_STRING_LIST(V) \ + V(SetReadOnlyProperty, "Cannot set readonly property") \ + V(FunctionCallNotConstructor, "class constructor cannot call") \ V(SetPropertyWhenNotExtensible, "Cannot add property in prevent extensions ") class MessageString { diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index e9592ee..36457e0 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -22,6 +22,7 @@ #include "ecmascript/layout_info.h" #include "ecmascript/message_string.h" #include "ecmascript/object_factory.h" +#include "ecmascript/interpreter/interpreter-inl.h" namespace panda::ecmascript { bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argReceiver, uint32_t argIndex, @@ -122,4 +123,20 @@ uint32_t RuntimeTrampolines::StringGetHashCode(uint64_t ecmaString) auto string = reinterpret_cast(ecmaString); return string->GetHashcode(); } + +uint64_t RuntimeTrampolines::Execute(uint64_t argThread, uint64_t argFunc, + uint64_t thisArg, uint32_t argc, uint64_t argArgv) +{ + auto thread = reinterpret_cast(argThread); + auto func = reinterpret_cast(argFunc); + auto argv = reinterpret_cast(argArgv); + CallParams params; + params.callTarget = func; + params.newTarget = JSTaggedValue::VALUE_UNDEFINED; + params.thisArg = thisArg; + params.argc = argc; + params.argv = argv; + + return EcmaInterpreter::Execute(thread, params).GetRawData(); +} } // namespace panda::ecmascript diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 7d7c286..62a20bb 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -48,6 +48,7 @@ public: static uint32_t GetHash32(uint64_t key, uint64_t len); static int32_t FindElementWithCache(uint64_t argThread, uint64_t hClass, uint64_t key, int32_t num); static uint32_t StringGetHashCode(uint64_t ecmaString); + static uint64_t Execute(uint64_t argThread, uint64_t argFunc, uint64_t thisArg, uint32_t argc, uint64_t argArgv); }; class CallRuntimeTrampolinesScope { -- Gitee From d4704cb73871e4ce4c64b1bd297df8c97cf82e81 Mon Sep 17 00:00:00 2001 From: wanyanglan Date: Fri, 15 Oct 2021 10:20:54 +0800 Subject: [PATCH 038/115] translate FastTypeOf function and add corresponding test cases Signed-off-by: wanyanglan Change-Id: I3a5d408a7bfe9f21dbe78d3f002fbfb8b0fc9010 --- ecmascript/compiler/fast_stub.cpp | 126 +++++++++++++++++++++++ ecmascript/compiler/fast_stub.h | 10 ++ ecmascript/compiler/llvm_ir_builder.cpp | 2 +- ecmascript/compiler/stub.h | 40 ++++++- ecmascript/compiler/stub_descriptor.cpp | 13 ++- ecmascript/compiler/tests/stub_tests.cpp | 88 ++++++++++++++++ ecmascript/js_thread.h | 5 + 7 files changed, 278 insertions(+), 6 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 2dee2e8..4ccd80c 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -658,6 +658,7 @@ void SetElementStub::GenerateCircuit() void GetPropertyByIndexStub::GenerateCircuit() { auto env = GetEnvironment(); + env->SetFrameType(FrameType::OPTIMIZED_ENTRY_FRAME); AddrShift thread = PtrArgument(0); AddrShift receiver = PtrArgument(1); AddrShift index = Int32Argument(2); /* 2 : 3rd parameter is index */ @@ -770,6 +771,7 @@ void GetPropertyByIndexStub::GenerateCircuit() void SetPropertyByIndexStub::GenerateCircuit() { auto env = GetEnvironment(); + env->SetFrameType(FrameType::OPTIMIZED_ENTRY_FRAME); AddrShift thread = PtrArgument(0); AddrShift receiver = PtrArgument(1); AddrShift index = Int32Argument(2); /* 2 : 3rd parameter is index */ @@ -1160,4 +1162,128 @@ void FastModStub::GenerateCircuit() } } } + +void FastTypeOfStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift obj = PtrArgument(1); + DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, obj); + AddrShift gConstOffset = PtrAdd(thread, GetPtrConstant(panda::ecmascript::JSThread::GetGlobalConstantOffset())); + AddrShift booleanIndex = GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX); + AddrShift gConstUndefindStr = Load(TAGGED_TYPE, gConstOffset, booleanIndex); + DEFVARIABLE(resultRep, MachineType::TAGGED_TYPE, gConstUndefindStr); + Label objIsTrue(env); + Label objNotTrue(env); + Label exit(env); + Label defaultLabel(env); + AddrShift gConstBooleanStr = Load( + TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX)); + Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_TRUE)), &objIsTrue, &objNotTrue); + Bind(&objIsTrue); + { + resultRep = gConstBooleanStr; + Jump(&exit); + } + Bind(&objNotTrue); + { + Label objIsFalse(env); + Label objNotFalse(env); + Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_FALSE)), &objIsFalse, &objNotFalse); + Bind(&objIsFalse); + { + resultRep = gConstBooleanStr; + Jump(&exit); + } + Bind(&objNotFalse); + { + Label objIsNull(env); + Label objNotNull(env); + Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_NULL)), &objIsNull, &objNotNull); + Bind(&objIsNull); + { + resultRep = Load(TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotNull); + { + Label objIsUndefined(env); + Label objNotUndefined(env); + Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_UNDEFINED)), &objIsUndefined, + &objNotUndefined); + Bind(&objIsUndefined); + { + resultRep = Load(TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotUndefined); + Jump(&defaultLabel); + } + } + } + Bind(&defaultLabel); + { + Label objIsHeapObject(env); + Label ObjNotHeapObject(env); + Branch(TaggedIsHeapObject(obj), &objIsHeapObject, &ObjNotHeapObject); + Bind(&objIsHeapObject); + { + Label objIsString(env); + Label objNotString(env); + Branch(IsString(obj), &objIsString, &objNotString); + Bind(&objIsString); + { + resultRep = Load(TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotString); + { + Label objIsSymbol(env); + Label ObjNotSymbol(env); + Branch(IsSymbol(obj), &objIsSymbol, &ObjNotSymbol); + Bind(&objIsSymbol); + { + resultRep = Load(TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::SYMBOL_STRING_INDEX)); + Jump(&exit); + } + Bind(&ObjNotSymbol); + { + Label objIsCallable(env); + Label objNotCallable(env); + Branch(IsCallable(obj), &objIsCallable, &objNotCallable); + Bind(&objIsCallable); + { + resultRep = Load( + TAGGED_TYPE, gConstOffset,GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotCallable); + { + resultRep = Load( + TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); + Jump(&exit); + } + } + } + } + Bind(&ObjNotHeapObject); + { + Label objIsNum(env); + Label objNotNum(env); + Branch(TaggedIsNumber(obj), &objIsNum, &objNotNum); + Bind(&objIsNum); + { + resultRep = Load( + TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotNum); + Jump(&exit); + } + } + Bind(&exit); + Return(*resultRep); +} } // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 109b7be..31153d1 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -149,5 +149,15 @@ public: NO_COPY_SEMANTIC(FastModStub); void GenerateCircuit() override; }; + +class FastTypeOfStub : public Stub { +public: + // 2 means argument counts + explicit FastTypeOfStub(Circuit *circuit) : Stub("FastTypeOf", 2, circuit) {} + ~FastTypeOfStub() = default; + NO_MOVE_SEMANTIC(FastTypeOfStub); + NO_COPY_SEMANTIC(FastTypeOfStub); + void GenerateCircuit() override; +}; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H \ No newline at end of file diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index c6963d4..4422c6e 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -869,7 +869,7 @@ void LLVMIRBuilder::VisitIntRev(AddrShift gate, AddrShift e1) const LOG_ECMA(INFO) << "int sign invert gate:" << gate; LLVMValueRef e1Value = g_values[e1]; LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); - LLVMValueRef result = LLVMBuildNeg(builder_, e1Value, ""); + LLVMValueRef result = LLVMBuildNot(builder_, e1Value, ""); g_values[gate] = result; LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 1ae07f2..bfd1f81 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -282,6 +282,11 @@ public: } } + void SetFrameType(panda::ecmascript::FrameType type) + { + circuit_->SetFrameType(type); + } + private: Label *currentLabel_ {nullptr}; Circuit *circuit_; @@ -735,7 +740,11 @@ public: return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT64_XOR), x, y); } - AddrShift Word32Not(AddrShift x); + AddrShift Word32Not(AddrShift x) + { + return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_REV), x); + } + AddrShift Word64Not(AddrShift x) { return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT64_REV), x); @@ -814,11 +823,11 @@ public: AddrShift TaggedIsSpecial(AddrShift x) { - return TruncInt32ToInt1(WordLogicAnd( + return TruncInt32ToInt1(Word32And( SExtInt1ToInt32( Word64Equal(Word64And(x, GetWord64Constant(~panda::ecmascript::JSTaggedValue::TAG_SPECIAL_MASK)), GetWord64Constant(0))), - WordLogicOr(SExtInt1ToInt32(Word64NotEqual( + Word32Or(SExtInt1ToInt32(Word64NotEqual( Word64And(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_SPECIAL_MASK)), GetWord64Constant(0))), SExtInt1ToInt32(TaggedIsHole(x))))); } @@ -826,7 +835,7 @@ public: AddrShift TaggedIsHeapObject(AddrShift x) { return TruncInt32ToInt1( - WordLogicAnd(SExtInt1ToInt32(TaggedIsObject(x)), WordLogicNot(SExtInt1ToInt32(TaggedIsSpecial(x))))); + Word32And(SExtInt1ToInt32(TaggedIsObject(x)), Word32Not(SExtInt1ToInt32(TaggedIsSpecial(x))))); } AddrShift DoubleIsNAN(AddrShift x) @@ -1351,6 +1360,29 @@ public: return methodName_; } + AddrShift GetGlobalConstantAddr(AddrShift index) + { + return Int64Mul(GetWord64Constant(sizeof(JSTaggedValue)), index); + } + + AddrShift GetGlobalConstantString(ConstantIndex index) + { + return GetGlobalConstantAddr(GetWord64Constant(static_cast(index))); + } + + AddrShift IsCallable(AddrShift obj) + { + AddrShift hclass = LoadHClass(obj); + AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + + AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + // decode + return Word64NotEqual( + Word64And(Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::CallableBit::START_BIT)), + GetWord64Constant((1LLU << panda::ecmascript::JSHClass::CallableBit::SIZE) - 1)), + GetWord64Constant(0)); + } + private: Environment env_; std::string methodName_; diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 135f379..755bc89 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -94,7 +94,18 @@ CALL_STUB_INIT_DESCRIPTOR(FastMod) CALL_STUB_INIT_DESCRIPTOR(FastEqual) {} -CALL_STUB_INIT_DESCRIPTOR(FastTypeOf) {} +CALL_STUB_INIT_DESCRIPTOR(FastTypeOf) +{ + // 4 : 4 input parameters + static StubDescriptor fastTypeOf("FastTypeOf", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + *descriptor = fastTypeOf; + // 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); +} CALL_STUB_INIT_DESCRIPTOR(FastStrictEqual) {} diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 8ef83ef..352ba97 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -17,6 +17,7 @@ #include #include "gtest/gtest.h" +#include "ecmascript/builtins/builtins_promise_handler.h" #include "ecmascript/compiler/fast_stub.h" #include "ecmascript/compiler/llvm_ir_builder.h" #include "ecmascript/compiler/llvm_mcjit_engine.h" @@ -41,6 +42,7 @@ namespace panda::test { using namespace panda::coretypes; using namespace panda::ecmascript; using namespace kungfu; +using BuiltinsPromiseHandler = builtins::BuiltinsPromiseHandler; class StubTest : public testing::Test { public: @@ -1165,4 +1167,90 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub) resVal = getPropertyByNamePtr(thread, obj.GetTaggedValue().GetRawData(), strBig.GetTaggedValue().GetRawData()); EXPECT_EQ(resVal.GetNumber(), y); } + +HWTEST_F_L0(StubTest, FastTypeOfTest) +{ + auto module = stubModule.GetModule(); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(FastMod)); + Circuit netOfGates; + FastTypeOfStub optimizer(&netOfGates); + optimizer.GenerateCircuit(); + netOfGates.PrintAllGates(); + bool verRes = Verifier::Run(&netOfGates); + ASSERT_TRUE(verRes); + auto cfg = Scheduler::Run(&netOfGates); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); + llvmBuilder.Build(); + char *error = nullptr; + LLVMVerifyModule(module, LLVMAbortProcessAction, &error); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); + assembler.Run(); + LLVMDumpModule(module); + auto *typeOfPtr = + reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); + const GlobalEnvConstants *globalConst = thread->GlobalConstants(); + + // obj is JSTaggedValue::VALUE_TRUE + JSTaggedValue resultVal = typeOfPtr(thread, JSTaggedValue::True().GetRawData()); + JSTaggedValue expectResult = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::True()); + EXPECT_EQ(resultVal, globalConst->GetBooleanString()); + EXPECT_EQ(resultVal, expectResult); + + // obj is JSTaggedValue::VALUE_FALSE + JSTaggedValue resultVal2 = typeOfPtr(thread, JSTaggedValue::False().GetRawData()); + JSTaggedValue expectResult2 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::False()); + EXPECT_EQ(resultVal2, globalConst->GetBooleanString()); + EXPECT_EQ(resultVal2, expectResult2); + + // obj is JSTaggedValue::VALUE_NULL + JSTaggedValue resultVal3 = typeOfPtr(thread, JSTaggedValue::Null().GetRawData()); + JSTaggedValue expectResult3 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::Null()); + EXPECT_EQ(resultVal3, globalConst->GetObjectString()); + EXPECT_EQ(resultVal3, expectResult3); + + // obj is JSTaggedValue::VALUE_UNDEFINED + JSTaggedValue resultVal4 = typeOfPtr(thread, JSTaggedValue::Undefined().GetRawData()); + JSTaggedValue expectResult4 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::Undefined()); + EXPECT_EQ(resultVal4, globalConst->GetUndefinedString()); + EXPECT_EQ(resultVal4, expectResult4); + + // obj is IsNumber + JSTaggedValue resultVal5 = typeOfPtr(thread, JSTaggedValue(5).GetRawData()); + JSTaggedValue expectResult5 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue(5)); + EXPECT_EQ(resultVal5, globalConst->GetNumberString()); + EXPECT_EQ(resultVal5, expectResult5); + + // obj is String + auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); + JSHandle str1 = factory->NewFromStdString("a"); + JSHandle str2 = factory->NewFromStdString("a"); + JSTaggedValue expectResult6 = FastRuntimeStub::FastTypeOf(thread, str1.GetTaggedValue()); + JSTaggedValue resultVal6 = typeOfPtr(thread, str2.GetTaggedValue().GetRawData()); + EXPECT_EQ(resultVal6, globalConst->GetStringString()); + EXPECT_EQ(resultVal6, expectResult6); + + // obj is Symbol + JSHandle globalEnv = JSThread::Cast(thread)->GetEcmaVM()->GetGlobalEnv(); + JSTaggedValue symbol = globalEnv->GetIteratorSymbol().GetTaggedValue(); + JSTaggedValue expectResult7= FastRuntimeStub::FastTypeOf(thread, symbol); + JSTaggedValue resultVal7 = typeOfPtr(thread, symbol.GetRawData()); + EXPECT_EQ(resultVal7, globalConst->GetSymbolString()); + EXPECT_EQ(resultVal7, expectResult7); + + // obj is callable + JSHandle resolveCallable = + factory->CreateJSPromiseReactionsFunction(reinterpret_cast(BuiltinsPromiseHandler::Resolve)); + JSTaggedValue expectResult8= FastRuntimeStub::FastTypeOf(thread, resolveCallable.GetTaggedValue()); + JSTaggedValue resultVal8 = typeOfPtr(thread, resolveCallable.GetTaggedValue().GetRawData()); + EXPECT_EQ(resultVal8, globalConst->GetFunctionString()); + EXPECT_EQ(resultVal8, expectResult8); + + // obj is heapObject + JSHandle object = factory->NewEmptyJSObject(); + JSTaggedValue expectResult9= FastRuntimeStub::FastTypeOf(thread, object.GetTaggedValue()); + JSTaggedValue resultVal9 = typeOfPtr(thread, object.GetTaggedValue().GetRawData()); + EXPECT_EQ(resultVal9, globalConst->GetObjectString()); + EXPECT_EQ(resultVal9, expectResult9); +} } // namespace panda::test diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 9edc945..0dcdf19 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -182,6 +182,11 @@ public: return MEMBER_OFFSET(JSThread, currentFrame_); } + static uint64_t GetGlobalConstantOffset() + { + return MEMBER_OFFSET(JSThread, globalConst_); + } + InternalCallParams *GetInternalCallParams() const { return internalCallParams_; -- Gitee From 29ed0182f47bba00a5d2c9768a22e18b82a95244 Mon Sep 17 00:00:00 2001 From: hjzhangcm <845154910@qq.com> Date: Tue, 19 Oct 2021 11:23:00 +0800 Subject: [PATCH 039/115] add js_arguments_test.cpp Signed-off-by: hjzhangcm <845154910@qq.com> --- ecmascript/tests/BUILD.gn | 29 +++++ ecmascript/tests/js_arguments_test.cpp | 165 +++++++++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 ecmascript/tests/js_arguments_test.cpp diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index 99ea6cc..653a46d 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -583,6 +583,33 @@ host_unittest_action("HugeObjectTest") { } } +host_unittest_action("JsArgumentsTest") { + module_out_path = module_output_path + + sources = [ + # test file + "js_arguments_test.cpp", + ] + + configs = [ + "//ark/js_runtime:ecma_test_config", + "//ark/js_runtime:ark_jsruntime_public_config", # should add before + # arkruntime_public_config + "//ark/js_runtime:ark_jsruntime_config", + "$ark_root/runtime:arkruntime_public_config", + ] + + deps = [ + "$ark_root/libpandabase:libarkbase", + "//ark/js_runtime:libark_jsruntime_test", + sdk_libc_secshared_dep, + ] + + if (!is_standard_system) { + deps += [ "$ark_root/runtime:libarkruntime" ] + } +} + host_unittest_action("LexicalEnvTest") { module_out_path = module_output_path @@ -866,6 +893,7 @@ group("unittest") { ":GcTest", ":GlueRegsTest", ":HugeObjectTest", + ":JsArgumentsTest", ":JsArrayTest", ":JsDateTest", ":JsForinIteratorTest", @@ -905,6 +933,7 @@ group("host_unittest") { ":GcTestAction", ":GlueRegsTestAction", ":HugeObjectTestAction", + ":JsArgumentsTestAction", ":JsArrayTestAction", ":JsDateTestAction", ":JsForinIteratorTestAction", diff --git a/ecmascript/tests/js_arguments_test.cpp b/ecmascript/tests/js_arguments_test.cpp new file mode 100644 index 0000000..5e5f06d --- /dev/null +++ b/ecmascript/tests/js_arguments_test.cpp @@ -0,0 +1,165 @@ +/* + * 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/js_arguments.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class JsArgumentsTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + ecmascript::EcmaHandleScope *scope {nullptr}; + PandaVM *instance {nullptr}; + JSThread *thread {nullptr}; +}; + +static JSFunction *JSObjectTestCreate(JSThread *thread) +{ + EcmaVM *ecmaVM = thread->GetEcmaVM(); + JSHandle globalEnv = ecmaVM->GetGlobalEnv(); + return globalEnv->GetObjectFunction().GetObject(); +} + +HWTEST_F_L0(JsArgumentsTest, SetProperty) +{ + JSHandle argFunc(thread, JSObjectTestCreate(thread)); + JSHandle jsarg = + thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle(argFunc), argFunc); + JSHandle arg = thread->GetEcmaVM()->GetFactory()->NewJSArguments(); + + char array[] = "x"; + JSHandle key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(array)); + JSHandle value(thread, JSTaggedValue(1)); + + // receive must be jsarg's conversion + JSHandle receiver = JSHandle::Cast(jsarg); + EXPECT_TRUE(JSArguments::SetProperty(thread, arg, key, value, receiver)); + EXPECT_EQ(JSObject::GetProperty(thread, JSHandle(jsarg), key).GetValue()->GetInt(), 1); + EXPECT_EQ(JSArguments::GetProperty(thread, jsarg, key).GetValue()->GetInt(), 1); + + JSHandle value2(thread, JSTaggedValue(2)); + EXPECT_TRUE(JSArguments::SetProperty(thread, arg, key, value2, receiver)); + EXPECT_EQ(JSObject::GetProperty(thread, JSHandle(jsarg), key).GetValue()->GetInt(), 2); + EXPECT_EQ(JSArguments::GetProperty(thread, jsarg, key).GetValue()->GetInt(), 2); +} + +HWTEST_F_L0(JsArgumentsTest, GetProperty) +{ + JSHandle argFunc(thread, JSObjectTestCreate(thread)); + JSHandle jsarg = + thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle(argFunc), argFunc); + JSHandle arg = thread->GetEcmaVM()->GetFactory()->NewJSArguments(); + + char array[] = "x"; + JSHandle key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(array)); + JSHandle value(thread, JSTaggedValue(1)); + + JSHandle receiver = JSHandle::Cast(jsarg); + JSArguments::SetProperty(thread, arg, key, value, receiver); + EXPECT_EQ(JSObject::GetProperty(thread, JSHandle(jsarg), key).GetValue()->GetInt(), 1); + EXPECT_EQ(JSArguments::GetProperty(thread, JSHandle(jsarg), key, receiver).GetValue()->GetInt(), 1); + + JSHandle value2(thread, JSTaggedValue(2)); + JSArguments::SetProperty(thread, arg, key, value2, receiver); + EXPECT_EQ(JSArguments::GetProperty(thread, jsarg, key).GetValue()->GetInt(), 2); + EXPECT_EQ(JSObject::GetProperty(thread, JSHandle(jsarg), key).GetValue()->GetInt(), 2); +} + +HWTEST_F_L0(JsArgumentsTest, DeleteProperty) +{ + JSHandle argFunc(thread, JSObjectTestCreate(thread)); + JSHandle jsarg = + thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle(argFunc), argFunc); + JSHandle arg = thread->GetEcmaVM()->GetFactory()->NewJSArguments(); + + char array[] = "delete"; + JSHandle key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(array)); + JSHandle value(thread, JSTaggedValue(1)); + JSHandle receiver = JSHandle::Cast(jsarg); + JSArguments::SetProperty(thread, arg, key, value, receiver); + EXPECT_EQ(JSArguments::GetProperty(thread, jsarg, key).GetValue()->GetInt(), 1); + + // test delete + bool result = JSArguments::DeleteProperty(thread, JSHandle(jsarg), key); + EXPECT_TRUE(result); + EXPECT_TRUE(JSObject::GetProperty(thread, JSHandle(jsarg), key).GetValue()->IsUndefined()); +} + +HWTEST_F_L0(JsArgumentsTest, DefineOwnProperty) +{ + JSHandle argFunc(thread, JSObjectTestCreate(thread)); + JSHandle jsarg = + thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle(argFunc), argFunc); + JSHandle arg = thread->GetEcmaVM()->GetFactory()->NewJSArguments(); + + JSHandle key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("x")); + JSHandle value1(thread, JSTaggedValue(1)); + JSHandle value2(thread, JSTaggedValue(2)); + JSHandle receiver = JSHandle::Cast(jsarg); + JSArguments::SetProperty(thread, arg, key, value2, receiver); + EXPECT_EQ(JSObject::GetProperty(thread, JSHandle(jsarg), key).GetValue()->GetInt(), 2); + + PropertyDescriptor Desc(thread); + // set value1 + Desc.SetValue(value1); + Desc.SetWritable(false); + EXPECT_TRUE(JSArguments::DefineOwnProperty(thread, JSHandle(jsarg), key, Desc)); + EXPECT_EQ(JSObject::GetProperty(thread, JSHandle(jsarg), key).GetValue()->GetInt(), 1); +} + +HWTEST_F_L0(JsArgumentsTest, GetOwnProperty) +{ + JSHandle argFunc(thread, JSObjectTestCreate(thread)); + JSHandle jsarg = + thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle(argFunc), argFunc); + JSHandle arg = thread->GetEcmaVM()->GetFactory()->NewJSArguments(); + + JSHandle key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("x")); + JSHandle value(thread, JSTaggedValue(1)); + JSHandle receiver = JSHandle::Cast(jsarg); + JSArguments::SetProperty(thread, arg, key, value, receiver); + + PropertyDescriptor Desc(thread); + JSHandle caller = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("caller"); + // key is not caller + EXPECT_FALSE(JSTaggedValue::SameValue(key.GetTaggedValue(), caller.GetTaggedValue())); + EXPECT_TRUE(JSArguments::GetOwnProperty(thread, JSHandle(jsarg), key, Desc)); + EXPECT_EQ(Desc.GetValue()->GetInt(), 1); +} +} // namespace panda::test -- Gitee From 09ed64e38a70d1b6213e720f61dd4f976a453970 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Tue, 19 Oct 2021 12:28:43 +0800 Subject: [PATCH 040/115] fix gc bug of EcmaModule Signed-off-by: wengchangcheng --- ecmascript/ecma_module.cpp | 22 ++++++++++++---------- ecmascript/ecma_module.h | 6 ++++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/ecmascript/ecma_module.cpp b/ecmascript/ecma_module.cpp index 3dc94b5..8a1a7c1 100644 --- a/ecmascript/ecma_module.cpp +++ b/ecmascript/ecma_module.cpp @@ -36,17 +36,18 @@ JSHandle EcmaModule::GetItem(const JSThread *thread, JSHandle(thread, JSTaggedValue::Undefined()); } -void EcmaModule::AddItem(const JSThread *thread, JSHandle itemName, JSHandle itemValue) +void EcmaModule::AddItem(const JSThread *thread, JSHandle module, JSHandle itemName, + JSHandle itemValue) { - JSHandle data(thread, GetNameDictionary()); + JSHandle data(thread, module->GetNameDictionary()); if (data->IsUndefined()) { JSHandle dict(thread, NameDictionary::Create(thread, DICTIONART_CAP)); auto result = dict->Put(thread, dict, itemName, itemValue, PropertyAttributes::Default()); - SetNameDictionary(thread, JSTaggedValue(result)); + module->SetNameDictionary(thread, JSTaggedValue(result)); } else { JSHandle dataDict = JSHandle::Cast(data); auto result = dataDict->Put(thread, dataDict, itemName, itemValue, PropertyAttributes::Default()); - SetNameDictionary(thread, JSTaggedValue(result)); + module->SetNameDictionary(thread, JSTaggedValue(result)); } } @@ -59,7 +60,8 @@ void EcmaModule::RemoveItem(const JSThread *thread, JSHandle item } } -void EcmaModule::CopyModuleInternal(const JSThread *thread, JSHandle srcModule) +void EcmaModule::CopyModuleInternal(const JSThread *thread, JSHandle dstModule, + JSHandle srcModule) { JSHandle moduleItems(thread, NameDictionary::Cast(srcModule->GetNameDictionary().GetTaggedObject())); @@ -76,7 +78,7 @@ void EcmaModule::CopyModuleInternal(const JSThread *thread, JSHandle if (entry != -1) { itemName.Update(allKeys->Get(i)); itemValue.Update(moduleItems->GetValue(entry)); - AddItem(thread, itemName, itemValue); + EcmaModule::AddItem(thread, dstModule, itemName, itemValue); } } } @@ -168,11 +170,11 @@ void ModuleManager::AddModuleItem(const JSThread *thread, JSHandle module = GetModule(thread, JSHandle::Cast(moduleName)); if (module->IsUndefined()) { JSHandle emptyModule = factory->NewEmptyEcmaModule(); - emptyModule->AddItem(thread, itemName, value); + EcmaModule::AddItem(thread, emptyModule, itemName, value); AddModule(JSHandle::Cast(moduleName), JSHandle::Cast(emptyModule)); } else { - EcmaModule::Cast(module->GetTaggedObject())->AddItem(thread, itemName, value); + EcmaModule::AddItem(thread, JSHandle(module), itemName, value); } } @@ -195,11 +197,11 @@ void ModuleManager::CopyModule(const JSThread *thread, JSHandle s if (dstModule->IsUndefined()) { JSHandle emptyModule = factory->NewEmptyEcmaModule(); - emptyModule->CopyModuleInternal(thread, srcModule); + EcmaModule::CopyModuleInternal(thread, emptyModule, srcModule); AddModule(JSHandle::Cast(moduleName), JSHandle::Cast(emptyModule)); } else { - JSHandle::Cast(dstModule)->CopyModuleInternal(thread, srcModule); + EcmaModule::CopyModuleInternal(thread, JSHandle(dstModule), srcModule); } } diff --git a/ecmascript/ecma_module.h b/ecmascript/ecma_module.h index 707724d..b6a053a 100644 --- a/ecmascript/ecma_module.h +++ b/ecmascript/ecma_module.h @@ -33,7 +33,8 @@ public: JSHandle GetItem(const JSThread *thread, JSHandle itemName); - void AddItem(const JSThread *thread, JSHandle itemName, JSHandle itemValue); + static void AddItem(const JSThread *thread, JSHandle module, JSHandle itemName, + JSHandle itemValue); void RemoveItem(const JSThread *thread, JSHandle itemName); @@ -45,7 +46,8 @@ public: DECL_VISIT_OBJECT_FOR_JS_OBJECT(ECMAObject, NAME_DICTIONARY_OFFSET, SIZE) protected: - void CopyModuleInternal(const JSThread *thread, JSHandle srcModule); + static void CopyModuleInternal(const JSThread *thread, JSHandle dstModule, + JSHandle srcModule); friend class ModuleManager; }; -- Gitee From f4a2f13790119b8b1fc3000b94aa0fdf844c0592 Mon Sep 17 00:00:00 2001 From: xliu Date: Tue, 19 Oct 2021 11:55:00 +0800 Subject: [PATCH 041/115] add arkTools.print Signed-off-by: xliu --- BUILD.gn | 1 + ecmascript/builtins.cpp | 18 ++++++- ecmascript/builtins.h | 1 + ecmascript/builtins/builtins_ark_tools.cpp | 44 ++++++++++++++++ ecmascript/builtins/builtins_ark_tools.h | 31 +++++++++++ ecmascript/ecma_vm.cpp | 11 ++-- ecmascript/ecma_vm.h | 13 +++-- ecmascript/js_runtime_options.h | 57 +++++++++++++++++++++ ecmascript/js_vm/main.cpp | 4 +- ecmascript/napi/include/jsnapi.h | 13 +++++ ecmascript/napi/jsnapi.cpp | 13 ++++- ecmascript/snapshot/tests/snapshot_test.cpp | 2 +- ecmascript/tests/gc_test.cpp | 2 +- ecmascript/tests/js_serializer_test.cpp | 2 +- ecmascript/tests/test_helper.h | 3 +- 15 files changed, 199 insertions(+), 16 deletions(-) create mode 100644 ecmascript/builtins/builtins_ark_tools.cpp create mode 100644 ecmascript/builtins/builtins_ark_tools.h create mode 100644 ecmascript/js_runtime_options.h diff --git a/BUILD.gn b/BUILD.gn index 4e7eeb9..9ca4294 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -245,6 +245,7 @@ ecma_source = [ "ecmascript/base/typed_array_helper.cpp", "ecmascript/base/utf_helper.cpp", "ecmascript/builtins.cpp", + "ecmascript/builtins/builtins_ark_tools.cpp", "ecmascript/builtins/builtins_array.cpp", "ecmascript/builtins/builtins_arraybuffer.cpp", "ecmascript/builtins/builtins_async_function.cpp", diff --git a/ecmascript/builtins.cpp b/ecmascript/builtins.cpp index a74fe84..5c32ec6 100644 --- a/ecmascript/builtins.cpp +++ b/ecmascript/builtins.cpp @@ -17,6 +17,7 @@ #include "ecmascript/base/error_type.h" #include "ecmascript/base/number_helper.h" +#include "ecmascript/builtins/builtins_ark_tools.h" #include "ecmascript/builtins/builtins_array.h" #include "ecmascript/builtins/builtins_arraybuffer.h" #include "ecmascript/builtins/builtins_async_function.h" @@ -74,6 +75,7 @@ #include "ecmascript/js_promise.h" #include "ecmascript/js_regexp.h" #include "ecmascript/js_relative_time_format.h" +#include "ecmascript/js_runtime_options.h" #include "ecmascript/js_set.h" #include "ecmascript/js_set_iterator.h" #include "ecmascript/js_string_iterator.h" @@ -267,7 +269,7 @@ void Builtins::Initialize(const JSHandle &env, JSThread *thread) InitializePromise(env, objFuncDynclass); InitializePromiseJob(env); - RuntimeOptions options = vm_->GetOptions(); + JSRuntimeOptions options = vm_->GetJSOptions(); std::string icuPath = options.GetIcuDataPath(); if (icuPath == "default") { SetHwIcuDirectory(); @@ -301,6 +303,11 @@ void Builtins::InitializeGlobalObject(const JSHandle &env, const JSHa SetFunction(env, globalObject, "stopRuntimeStat", Global::StopRuntimeStat, 0); #endif + JSRuntimeOptions options = vm_->GetJSOptions(); + if (options.IsEnableArkTools()) { + SetConstant(globalObject, "ArkTools", InitializeArkTools(env).GetTaggedValue()); + } + // Global object function SetFunction(env, globalObject, "eval", Global::NotSupportEval, FunctionLength::ONE); SetFunction(env, globalObject, "isFinite", Global::IsFinite, FunctionLength::ONE); @@ -2723,4 +2730,13 @@ void Builtins::InitializePluralRules(const JSHandle &env) // 15.4.5 Intl.PluralRules.prototype.resolvedOptions () SetFunction(env, prPrototype, "resolvedOptions", PluralRules::ResolvedOptions, FunctionLength::ZERO); } + +JSHandle Builtins::InitializeArkTools(const JSHandle &env) const +{ + [[maybe_unused]] EcmaHandleScope scope(thread_); + + JSHandle tools = factory_->NewEmptyJSObject(); + SetFunction(env, tools, "print", builtins::BuiltinsArkTools::ObjectDump, FunctionLength::ZERO); + return tools; +} } // namespace panda::ecmascript diff --git a/ecmascript/builtins.h b/ecmascript/builtins.h index dcf2855..63fa4b4 100644 --- a/ecmascript/builtins.h +++ b/ecmascript/builtins.h @@ -208,6 +208,7 @@ private: const JSHandle &getter, const JSHandle &setter) const; void SetGetter(const JSHandle &obj, const JSHandle &key, const JSHandle &getter) const; + JSHandle InitializeArkTools(const JSHandle &env) const; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_BUILTINS_H diff --git a/ecmascript/builtins/builtins_ark_tools.cpp b/ecmascript/builtins/builtins_ark_tools.cpp new file mode 100644 index 0000000..d2b063f --- /dev/null +++ b/ecmascript/builtins/builtins_ark_tools.cpp @@ -0,0 +1,44 @@ +/* + * 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/builtins/builtins_ark_tools.h" +#include "ecmascript/base/string_helper.h" + +namespace panda::ecmascript::builtins { +using StringHelper = base::StringHelper; + +JSTaggedValue BuiltinsArkTools::ObjectDump(EcmaRuntimeCallInfo *msg) +{ + ASSERT(msg); + JSThread *thread = msg->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + JSHandle str = JSTaggedValue::ToString(thread, GetCallArg(msg, 0)); + // The default log level of ace_engine and js_runtime is error + LOG(ERROR, RUNTIME) << ": " << base::StringHelper::ToStdString(*str); + + uint32_t numArgs = msg->GetArgsNumber(); + for (uint32_t i = 1; i < numArgs; i++) { + JSHandle obj = GetCallArg(msg, i); + std::ostringstream oss; + obj->Dump(thread, oss); + + // The default log level of ace_engine and js_runtime is error + LOG(ERROR, RUNTIME) << ": " << oss.str(); + } + + return JSTaggedValue::Undefined(); +} +} // namespace panda::ecmascript::builtins diff --git a/ecmascript/builtins/builtins_ark_tools.h b/ecmascript/builtins/builtins_ark_tools.h new file mode 100644 index 0000000..f5256bb --- /dev/null +++ b/ecmascript/builtins/builtins_ark_tools.h @@ -0,0 +1,31 @@ +/* + * 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_BUILTINS_BUILTINS_ARK_TOOLS_H +#define ECMASCRIPT_BUILTINS_BUILTINS_ARK_TOOLS_H + +#include "ecmascript/base/builtins_base.h" +#include "ecmascript/js_thread.h" + +namespace panda::ecmascript::builtins { +class BuiltinsArkTools : public base::BuiltinsBase { +public: + // Make sure the ECMASCRIPT_OBJECT_DUMP in config.h has been opened before use it + // Use through arkTools.print(msg, [obj1, obj2, ... objn]) in js + static JSTaggedValue ObjectDump(EcmaRuntimeCallInfo *msg); +}; +} // namespace panda::ecmascript::builtins + +#endif // ECMASCRIPT_BUILTINS_BUILTINS_ARK_TOOLS_H diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 569edd1..9348f37 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -56,9 +56,10 @@ namespace panda::ecmascript { // NOLINTNEXTLINE(fuchsia-statically-constructed-objects) static const std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0"; +JSRuntimeOptions EcmaVM::options_; // NOLINT(fuchsia-statically-constructed-objects) /* static */ -EcmaVM *EcmaVM::Create(const RuntimeOptions &options) +EcmaVM *EcmaVM::Create(const JSRuntimeOptions &options) { auto runtime = Runtime::GetCurrent(); auto vm = runtime->GetInternalAllocator()->New(options); @@ -93,18 +94,18 @@ Expected EcmaVM::Create(Runtime *runtime) } // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -EcmaVM::EcmaVM() : EcmaVM(Runtime::GetOptions()) +EcmaVM::EcmaVM() : EcmaVM(EcmaVM::GetJSOptions()) { isTestMode_ = true; } -EcmaVM::EcmaVM(RuntimeOptions options) - : options_(std::move(options)), - stringTable_(new EcmaStringTable(this)), +EcmaVM::EcmaVM(JSRuntimeOptions options) + : stringTable_(new EcmaStringTable(this)), regionFactory_(std::make_unique()), chunk_(regionFactory_.get()), nativeMethods_(&chunk_) { + options_ = std::move(options); icEnable_ = options_.IsIcEnable(); rendezvous_ = chunk_.New(); snapshotSerializeEnable_ = options_.IsSnapshotSerializeEnabled(); diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index cde72c5..63a93b7 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -24,6 +24,7 @@ #include "ecmascript/js_handle.h" #include "ecmascript/js_method.h" #include "ecmascript/js_native_pointer.h" +#include "ecmascript/js_runtime_options.h" #include "ecmascript/mem/c_containers.h" #include "ecmascript/mem/c_string.h" #include "ecmascript/mem/chunk_containers.h" @@ -75,11 +76,11 @@ public: return reinterpret_cast(object); } - static EcmaVM *Create(const RuntimeOptions &options); + static EcmaVM *Create(const JSRuntimeOptions &options); static bool Destroy(PandaVM *vm); - explicit EcmaVM(RuntimeOptions options); + explicit EcmaVM(JSRuntimeOptions options); static Expected Create([[maybe_unused]] Runtime *runtime); @@ -211,6 +212,11 @@ public: } const RuntimeOptions &GetOptions() const override + { + return Runtime::GetOptions(); + } + + static const JSRuntimeOptions &GetJSOptions() { return options_; } @@ -393,7 +399,7 @@ private: NO_COPY_SEMANTIC(EcmaVM); // init EcmaVM construct - RuntimeOptions options_; + static JSRuntimeOptions options_; EcmaStringTable *stringTable_; std::unique_ptr regionFactory_; Chunk chunk_; @@ -439,6 +445,7 @@ private: friend class SnapShotSerialize; friend class ObjectFactory; friend class ValueSerializer; + friend class panda::JSNApi; }; } // namespace ecmascript } // namespace panda diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h new file mode 100644 index 0000000..5c13618 --- /dev/null +++ b/ecmascript/js_runtime_options.h @@ -0,0 +1,57 @@ +/* + * 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_JS_RUNTIME_OPTIONS_H_ +#define ECMASCRIPT_JS_RUNTIME_OPTIONS_H_ + +#include "runtime/include/runtime_options.h" +#include "utils/logger.h" + +// namespace panda { +namespace panda::ecmascript { +class JSRuntimeOptions : public RuntimeOptions { +public: + explicit JSRuntimeOptions(const std::string &exe_path = "") : RuntimeOptions(exe_path) {} + ~JSRuntimeOptions() = default; + DEFAULT_COPY_SEMANTIC(JSRuntimeOptions); + DEFAULT_MOVE_SEMANTIC(JSRuntimeOptions); + + void AddOptions(PandArgParser *parser) + { + RuntimeOptions::AddOptions(parser); + parser->Add(&enable_ark_tools_); + } + + bool IsEnableArkTools() const + { + return enable_ark_tools_.GetValue(); + } + + void SetEnableArkTools(bool value) + { + enable_ark_tools_.SetValue(value); + } + + bool WasSetEnableArkTools() const + { + return enable_ark_tools_.WasSet(); + } + +private: + PandArg enable_ark_tools_{"enable-ark-tools", false, R"(Enable ark tools to debug. Default: false)"}; +}; +} // namespace panda::ecmascript + +#endif // ECMASCRIPT_JS_RUNTIME_OPTIONS_H_ diff --git a/ecmascript/js_vm/main.cpp b/ecmascript/js_vm/main.cpp index a3bad4b..9d76603 100644 --- a/ecmascript/js_vm/main.cpp +++ b/ecmascript/js_vm/main.cpp @@ -23,6 +23,7 @@ #include "ecmascript/ecma_language_context.h" #include "ecmascript/ecma_string.h" #include "ecmascript/ecma_vm.h" +#include "ecmascript/js_runtime_options.h" #include "ecmascript/napi/include/jsnapi.h" #include "include/runtime.h" #include "libpandabase/os/native_stack.h" @@ -59,7 +60,7 @@ int Main(const int argc, const char **argv) BlockSignals(); Span sp(argv, argc); - RuntimeOptions runtimeOptions(sp[0]); + JSRuntimeOptions runtimeOptions(sp[0]); panda::PandArg help("help", false, "Print this message and exit"); panda::PandArg options("options", false, "Print compiler and runtime options"); @@ -106,6 +107,7 @@ int Main(const int argc, const char **argv) runtimeOptions.SetShouldInitializeIntrinsics(false); runtimeOptions.SetBootClassSpaces({"ecmascript"}); runtimeOptions.SetRuntimeType("ecmascript"); + JSNApi::SetOptions(runtimeOptions); static EcmaLanguageContext lcEcma; bool ret = Runtime::Create(runtimeOptions, {&lcEcma}); if (!ret) { diff --git a/ecmascript/napi/include/jsnapi.h b/ecmascript/napi/include/jsnapi.h index aff0c0f..a3a4885 100644 --- a/ecmascript/napi/include/jsnapi.h +++ b/ecmascript/napi/include/jsnapi.h @@ -44,6 +44,7 @@ class JSNApiTests; namespace ecmascript { class EcmaVM; +class JSRuntimeOptions; } // namespace ecmascript using Deleter = void (*)(void *buffer, void *data); @@ -726,6 +727,10 @@ public: debuggerLibraryPath_ = path; } + void SetEnableArkTools(bool value) { + enableArkTools_ = value; + } + private: std::string GetGcType() const { @@ -784,11 +789,18 @@ private: return debuggerLibraryPath_; } + bool GetEnableArkTools() const + { + return enableArkTools_; + } + + GC_TYPE gcType_ = GC_TYPE::EPSILON; LOG_LEVEL logLevel_ = LOG_LEVEL::DEBUG; uint32_t gcPoolSize_ = DEFAULT_GC_POOL_SIZE; LOG_PRINT logBufPrint_{nullptr}; std::string debuggerLibraryPath_{}; + bool enableArkTools_{false}; friend JSNApi; }; @@ -821,6 +833,7 @@ public: static void* SerializeValue(const EcmaVM *vm, Local data, Local transfer); static Local DeserializeValue(const EcmaVM *vm, void* recoder); static void DeleteSerializationData(void *data); + static void SetOptions(const ecmascript::JSRuntimeOptions &options); private: static bool CreateRuntime(const RuntimeOption &option); diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index 865091e..edad0b4 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -39,6 +39,7 @@ #include "ecmascript/js_primitive_ref.h" #include "ecmascript/js_promise.h" #include "ecmascript/js_regexp.h" +#include "ecmascript/js_runtime_options.h" #include "ecmascript/js_serializer.h" #include "ecmascript/js_set.h" #include "ecmascript/js_tagged_number.h" @@ -93,6 +94,7 @@ using ecmascript::base::JsonParser; using ecmascript::base::JsonStringifier; using ecmascript::base::StringHelper; using ecmascript::base::TypedArrayHelper; +using ecmascript::JSRuntimeOptions; template using JSHandle = ecmascript::JSHandle; @@ -107,7 +109,7 @@ constexpr std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0"; // ------------------------------------ Panda ----------------------------------------------- bool JSNApi::CreateRuntime(const RuntimeOption &option) { - RuntimeOptions runtimeOptions; + JSRuntimeOptions runtimeOptions; runtimeOptions.SetRuntimeType("ecmascript"); // GC @@ -138,6 +140,8 @@ bool JSNApi::CreateRuntime(const RuntimeOption &option) // Debugger runtimeOptions.SetDebuggerLibraryPath(option.GetDebuggerLibraryPath()); + runtimeOptions.SetEnableArkTools(option.GetEnableArkTools()); + SetOptions(runtimeOptions); static EcmaLanguageContext lcEcma; if (!Runtime::Create(runtimeOptions, {&lcEcma})) { std::cerr << "Error: cannot create runtime" << std::endl; @@ -162,7 +166,7 @@ EcmaVM *JSNApi::CreateJSVM(const RuntimeOption &option) runtime = Runtime::GetCurrent(); return EcmaVM::Cast(runtime->GetPandaVM()); } - RuntimeOptions runtimeOptions; + JSRuntimeOptions runtimeOptions; // GC runtimeOptions.SetGcTriggerType("no-gc-for-start-up"); // A non-production gc strategy. Prohibit stw-gc 10 times. @@ -381,6 +385,11 @@ Local JSNApi::GetExportObject(EcmaVM *vm, const std::string &file, co JSHandle exportObj = moduleManager->GetModuleItem(vm->GetJSThread(), moduleObj, itemString); return JSNApiHelper::ToLocal(exportObj); } + +void JSNApi::SetOptions(const ecmascript::JSRuntimeOptions &options) +{ + ecmascript::EcmaVM::options_ = options; +} // ----------------------------------- HandleScope ------------------------------------- LocalScope::LocalScope(const EcmaVM *vm) : thread_(vm->GetJSThread()) { diff --git a/ecmascript/snapshot/tests/snapshot_test.cpp b/ecmascript/snapshot/tests/snapshot_test.cpp index 3131e0b..f28064c 100644 --- a/ecmascript/snapshot/tests/snapshot_test.cpp +++ b/ecmascript/snapshot/tests/snapshot_test.cpp @@ -40,7 +40,7 @@ public: void SetUp() override { - RuntimeOptions options; + JSRuntimeOptions options; options.SetShouldLoadBootPandaFiles(false); options.SetShouldInitializeIntrinsics(false); options.SetBootIntrinsicSpaces({"ecmascript"}); diff --git a/ecmascript/tests/gc_test.cpp b/ecmascript/tests/gc_test.cpp index bece8ee..3ba0b6f 100644 --- a/ecmascript/tests/gc_test.cpp +++ b/ecmascript/tests/gc_test.cpp @@ -38,7 +38,7 @@ public: void SetUp() override { - RuntimeOptions options; + JSRuntimeOptions options; options.SetShouldLoadBootPandaFiles(false); options.SetShouldInitializeIntrinsics(false); options.SetBootClassSpaces({"ecmascript"}); diff --git a/ecmascript/tests/js_serializer_test.cpp b/ecmascript/tests/js_serializer_test.cpp index e40c634..5a0d702 100644 --- a/ecmascript/tests/js_serializer_test.cpp +++ b/ecmascript/tests/js_serializer_test.cpp @@ -41,7 +41,7 @@ public: JSDeserializerTest() : ecmaVm(nullptr), scope(nullptr), thread(nullptr) {} void Init() { - RuntimeOptions options; + JSRuntimeOptions options; options.SetShouldLoadBootPandaFiles(false); options.SetShouldInitializeIntrinsics(false); options.SetBootIntrinsicSpaces({"ecmascript"}); diff --git a/ecmascript/tests/test_helper.h b/ecmascript/tests/test_helper.h index fd21b70..f65d77e 100644 --- a/ecmascript/tests/test_helper.h +++ b/ecmascript/tests/test_helper.h @@ -33,6 +33,7 @@ using panda::ecmascript::JSTaggedType; using panda::ecmascript::JSTaggedValue; using panda::ecmascript::JSThread; using panda::ecmascript::NUM_MANDATORY_JSFUNC_ARGS; +using ecmascript::JSRuntimeOptions; // Add for hmf tests platform, define to TEST_F or TEST_P when running gtest in gitlab #define HWTEST_F_L0(testsuit, testcase) HWTEST_F(testsuit, testcase, testing::ext::TestSize.Level0) @@ -81,7 +82,7 @@ public: // If you want to call once create, you can refer to BuiltinsMathTest for detail. static void CreateEcmaVMWithScope(PandaVM *&instance, JSThread *&thread, EcmaHandleScope *&scope) { - RuntimeOptions options; + JSRuntimeOptions options; options.SetShouldLoadBootPandaFiles(false); options.SetShouldInitializeIntrinsics(false); options.SetBootClassSpaces({"ecmascript"}); -- Gitee From c6b37545d7a7609a28194dcafe47f7aa082ba17b Mon Sep 17 00:00:00 2001 From: lichenshuai Date: Tue, 19 Oct 2021 14:51:14 +0800 Subject: [PATCH 042/115] Reconstruct code for readability. Signed-off-by: lichenshuai --- ecmascript/ecma_module.cpp | 23 +++++++++++++++++++++++ ecmascript/ecma_module.h | 2 ++ ecmascript/ecma_vm.cpp | 27 +++++++-------------------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/ecmascript/ecma_module.cpp b/ecmascript/ecma_module.cpp index 3dc94b5..63d6f4e 100644 --- a/ecmascript/ecma_module.cpp +++ b/ecmascript/ecma_module.cpp @@ -137,6 +137,29 @@ JSHandle ModuleManager::GetModule(const JSThread *thread, return thread->GlobalConstants()->GetHandledUndefined(); } +CString ModuleManager::GenerateModuleFullPath(const std::string ¤tPathFile, const CString &relativeFile) +{ + if (relativeFile.find("./") != 0 && relativeFile.find("../") != 0) { // not start with "./" or "../" + return relativeFile; // not relative + } + + auto slashPos = currentPathFile.find_last_of('/'); + if (slashPos == std::string::npos) { + return relativeFile; // no need to process + } + + auto dotPos = relativeFile.find_last_of("."); + if (dotPos == std::string::npos) { + dotPos = 0; + } + + CString fullPath; + fullPath.append(currentPathFile.substr(0, slashPos + 1)); // 1: with "/" + fullPath.append(relativeFile.substr(0, dotPos)); + fullPath.append(".abc"); // ".js" -> ".abc" + return fullPath; +} + const CString &ModuleManager::GetCurrentExportModuleName() { return moduleStack_.GetTop(); diff --git a/ecmascript/ecma_module.h b/ecmascript/ecma_module.h index 707724d..c2a3497 100644 --- a/ecmascript/ecma_module.h +++ b/ecmascript/ecma_module.h @@ -79,6 +79,8 @@ public: JSHandle GetModule(const JSThread *thread, JSHandle moduleName); + CString GenerateModuleFullPath(const std::string ¤tPathFile, const CString &relativeFile); + const CString &GetCurrentExportModuleName(); const CString &GetPrevExportModuleName(); diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 569edd1..711f260 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -692,26 +692,13 @@ void EcmaVM::SetMicroJobQueue(job::MicroJobQueue *queue) JSHandle EcmaVM::GetModuleByName(JSHandle moduleName) { - CString dirPath; - CString scriptName = ConvertToString(EcmaString::Cast(moduleName->GetTaggedObject())); - - // need to check abc file - auto pos = scriptName.find_last_of('.'); - CString abcPath = dirPath.append(scriptName.substr(0, pos == std::string::npos ? 0 : pos)).append(".abc"); - // handle relative path - if (abcPath.find("./") == 0) { // starts with "./" - std::string fullPath = std::get<1>(pandaFileWithProgram_.back())->GetFilename(); - auto lastSlash = fullPath.find_last_of('/'); - if (lastSlash != std::string::npos) { - abcPath = fullPath.substr(0, lastSlash).append(abcPath.substr(1)); // 1: ignore "." - } - } else if (abcPath.find("../") == 0) { // starts with "../" - std::string fullPath = std::get<1>(pandaFileWithProgram_.back())->GetFilename(); - auto lastSlash = fullPath.find_last_of('/'); - if (lastSlash != std::string::npos) { - abcPath = fullPath.substr(0, lastSlash + 1).append(abcPath); // 1: with "/" - } - } + auto currentFileTuple = pandaFileWithProgram_.back(); + auto currentFileInfo = std::get<1>(currentFileTuple); + std::string currentPathFile = currentFileInfo->GetFilename(); + CString relativeFile = ConvertToString(EcmaString::Cast(moduleName->GetTaggedObject())); + + // generate full path + CString abcPath = moduleManager_->GenerateModuleFullPath(currentPathFile, relativeFile); // Uniform module name JSHandle abcModuleName = factory_->NewFromString(abcPath); -- Gitee From 0df116c2136a012801fcea57931f778f273394f0 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Tue, 19 Oct 2021 21:28:25 +0800 Subject: [PATCH 043/115] fix EcmaModule RemoveItem bug when dictionary update Signed-off-by: wengchangcheng --- ecmascript/ecma_module.cpp | 11 ++++++++--- ecmascript/ecma_module.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ecmascript/ecma_module.cpp b/ecmascript/ecma_module.cpp index 8a1a7c1..260d839 100644 --- a/ecmascript/ecma_module.cpp +++ b/ecmascript/ecma_module.cpp @@ -51,12 +51,17 @@ void EcmaModule::AddItem(const JSThread *thread, JSHandle module, JS } } -void EcmaModule::RemoveItem(const JSThread *thread, JSHandle itemName) +void EcmaModule::RemoveItem(const JSThread *thread, JSHandle module, JSHandle itemName) { - JSHandle moduleItems(thread, NameDictionary::Cast(GetNameDictionary().GetTaggedObject())); + JSHandle data(thread, module->GetNameDictionary()); + if (data->IsUndefined()) { + return; + } + JSHandle moduleItems(data); int entry = moduleItems->FindEntry(itemName.GetTaggedValue()); if (entry != -1) { - NameDictionary::Remove(thread, moduleItems, entry); // discard return + NameDictionary *newDict = NameDictionary::Remove(thread, moduleItems, entry); // discard return + module->SetNameDictionary(thread, JSTaggedValue(newDict)); } } diff --git a/ecmascript/ecma_module.h b/ecmascript/ecma_module.h index b6a053a..ee744ac 100644 --- a/ecmascript/ecma_module.h +++ b/ecmascript/ecma_module.h @@ -36,7 +36,7 @@ public: static void AddItem(const JSThread *thread, JSHandle module, JSHandle itemName, JSHandle itemValue); - void RemoveItem(const JSThread *thread, JSHandle itemName); + static void RemoveItem(const JSThread *thread, JSHandle module, JSHandle itemName); void DebugPrint(const JSThread *thread, const CString &caller); -- Gitee From 3a8a769a8a9483411bae892efdcb020bbc7e61fe Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Wed, 20 Oct 2021 10:06:42 +0800 Subject: [PATCH 044/115] fix generated header file dependent Signed-off-by: wengchangcheng --- BUILD.gn | 4 ++-- ecmascript/compiler/BUILD.gn | 2 +- ecmascript/tooling/BUILD.gn | 4 ++-- js_runtime_config.gni | 8 -------- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 9ca4294..61a2103 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -123,11 +123,11 @@ source_set("libark_js_intl_static") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", + "$ark_root/runtime:arkruntime_header_deps", "//third_party/icu/icu4c:shared_icui18n", "//third_party/icu/icu4c:shared_icuuc", sdk_libc_secshared_dep, ] - deps += arkruntime_header_gen_deps } config("ark_jsruntime_common_config") { @@ -439,11 +439,11 @@ source_set("libark_jsruntime_test_static") { ":copy_resource_xml", "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", + "$ark_root/runtime:arkruntime_header_deps", "//third_party/icu/icu4c:shared_icui18n", "//third_party/icu/icu4c:shared_icuuc", sdk_libc_secshared_dep, ] - deps += arkruntime_header_gen_deps if (is_debug && is_linux && (current_cpu == "x86" || current_cpu == "x64") && run_with_asan) { diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index f217398..6c63f6d 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -133,8 +133,8 @@ source_set("libark_jsoptimizer_static") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", + "$ark_root/runtime:arkruntime_header_deps", ] - deps += arkruntime_header_gen_deps } ohos_shared_library("libark_jsoptimizer") { diff --git a/ecmascript/tooling/BUILD.gn b/ecmascript/tooling/BUILD.gn index c25bf31..170f72c 100644 --- a/ecmascript/tooling/BUILD.gn +++ b/ecmascript/tooling/BUILD.gn @@ -47,8 +47,8 @@ source_set("libark_ecma_debugger_static") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", + "$ark_root/runtime:arkruntime_header_deps", ] - deps += arkruntime_header_gen_deps cflags_cc = [ "-fvisibility=hidden" ] } @@ -84,8 +84,8 @@ source_set("libark_ecma_debugger_test_static") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", + "$ark_root/runtime:arkruntime_header_deps", ] - deps += arkruntime_header_gen_deps } ohos_shared_library("libark_ecma_debugger_test") { diff --git a/js_runtime_config.gni b/js_runtime_config.gni index c21daa0..bf6c093 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -21,14 +21,6 @@ asan_lib_path = "/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux" sdk_libc_secshared_dep = "//utils/native/base:utilsecurec" sdk_libc_secshared_config = "//utils/native/base:utils_config" -# Add for header file dependence, should dependent this when include -# header file of runtime, but not dependent libarkruntime -arkruntime_header_gen_deps = [ - "$ark_root/runtime:arkruntime_gen_intrinsics_intrinsics_h", - "$ark_root/runtime:libarkruntime_options_gen_h", - "$ark_root/verification/gen:verification_verifier_messages_h", -] - # Generate file for a template and YAML data provided. # # Mandatory arguments: -- Gitee From f6cec779bb3af2ff6250a7910cf8945b34880228 Mon Sep 17 00:00:00 2001 From: Gongyuhang <517563583@qq.com> Date: Wed, 20 Oct 2021 12:40:12 +0800 Subject: [PATCH 045/115] Add a cpp that tests the public functions of EcmaModule class, ModuleManager class and ModuleStack class. Signed-off-by: Gongyuhang <517563583@qq.com> --- ecmascript/tests/BUILD.gn | 29 ++ ecmascript/tests/ecma_module_test.cpp | 548 ++++++++++++++++++++++++++ 2 files changed, 577 insertions(+) create mode 100644 ecmascript/tests/ecma_module_test.cpp diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index 653a46d..c8abe68 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -98,6 +98,33 @@ host_unittest_action("DumpTest") { } } +host_unittest_action("EcmaModuleTest") { + module_out_path = module_output_path + + sources = [ + # test file + "ecma_module_test.cpp", + ] + + configs = [ + "//ark/js_runtime:ecma_test_config", + "//ark/js_runtime:ark_jsruntime_public_config", # should add before + # arkruntime_public_config + "//ark/js_runtime:ark_jsruntime_common_config", + "$ark_root/runtime:arkruntime_public_config", + ] + + deps = [ + "$ark_root/libpandabase:libarkbase", + "//ark/js_runtime:libark_jsruntime_test", + sdk_libc_secshared_dep, + ] + + if (!is_standard_system) { + deps += [ "$ark_root/runtime:libarkruntime" ] + } +} + host_unittest_action("EcmaStringTest") { module_out_path = module_output_path @@ -889,6 +916,7 @@ group("unittest") { ":AssertScopeTest", ":BuiltinsTest", ":DumpTest", + ":EcmaModuleTest", ":EcmaStringTest", ":GcTest", ":GlueRegsTest", @@ -929,6 +957,7 @@ group("host_unittest") { ":AssertScopeTestAction", ":BuiltinsTestAction", ":DumpTestAction", + ":EcmaModuleTestAction", ":EcmaStringTestAction", ":GcTestAction", ":GlueRegsTestAction", diff --git a/ecmascript/tests/ecma_module_test.cpp b/ecmascript/tests/ecma_module_test.cpp new file mode 100644 index 0000000..f214c0b --- /dev/null +++ b/ecmascript/tests/ecma_module_test.cpp @@ -0,0 +1,548 @@ +/* + * 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_module.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_locale.h" +#include "ecmascript/tagged_dictionary.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class EcmaModuleTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TesrDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + PandaVM *instance {nullptr}; + ecmascript::EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; +}; + +EcmaModule *EcmaModuleCreate(JSThread *thread) +{ + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleEcmaModule = objectFactory->NewEmptyEcmaModule(); + return *handleEcmaModule; +} + +/* + * Feature: EcmaModule + * Function: AddItem + * SubFunction: GetItem + * FunctionPoints: Add Item To EcmaModule + * CaseDescription: Add an item for a EcmaModule that has called "SetNameDictionary" function in the HWTEST_F_L0, and + * check its value through 'GetItem' function. + */ +HWTEST_F_L0(EcmaModuleTest, AddItem_001) +{ + int numOfElementsDict = 4; + CString cStrItemName = "key1"; + int intItemValue = 1; + JSHandle handleEcmaModule(thread, EcmaModuleCreate(thread)); + JSHandle handleNameDict(thread, NameDictionary::Create(thread, numOfElementsDict)); + JSHandle handleTagValItemName( + thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(cStrItemName)); + JSHandle handleTagValItemValue(thread, JSTaggedValue(intItemValue)); + + handleEcmaModule->SetNameDictionary(thread, handleNameDict); // Call SetNameDictionary in HWTEST_F_L0 + EcmaModule::AddItem(thread, handleEcmaModule, handleTagValItemName, handleTagValItemValue); + EXPECT_EQ(handleEcmaModule->GetItem(thread, handleTagValItemName)->GetNumber(), intItemValue); +} + +/* + * Feature: EcmaModule + * Function: AddItem + * SubFunction: GetItem + * FunctionPoints: Add Item To EcmaModule + * CaseDescription: Add an item for a EcmaModule that has not called "SetNameDictionary" function in the HWTEST_F_L0, + * and check its value through 'GetItem' function. + */ +HWTEST_F_L0(EcmaModuleTest, AddItem_002) +{ + CString cStrItemName = "cStrItemName"; + int intItemValue = 1; + JSHandle handleEcmaModule(thread, EcmaModuleCreate(thread)); + JSHandle handleTagValItemName( + thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(cStrItemName)); + JSHandle handleTagValItemValue(thread, JSTaggedValue(intItemValue)); + + // This EcmaModule calls 'SetNameDictionary' function through 'AddItem' function of "ecma_module.cpp". + EcmaModule::AddItem(thread, handleEcmaModule, handleTagValItemName, handleTagValItemValue); + EXPECT_EQ(handleEcmaModule->GetItem(thread, handleTagValItemName)->GetNumber(), intItemValue); +} + +/* + * Feature: EcmaModule + * Function: RemoveItem + * SubFunction: AddItem/GetItem + * FunctionPoints: Remove Item From EcmaModule + * CaseDescription: Add an item for an empty EcmaModule through 'AddItem' function, then remove the item from the + * EcmaModule through 'RemoveItem' function, finally check whether the item obtained from the + * EcmaModule through 'GetItem' function is undefined. + */ +HWTEST_F_L0(EcmaModuleTest, RemoveItem) +{ + ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory(); + + CString cStrItemName = "cStrItemName"; + int intItemValue = 1; + JSHandle handleEcmaModule(thread, EcmaModuleCreate(thread)); + JSHandle handleTagValItemName(objFactory->NewFromCanBeCompressString(cStrItemName)); + JSHandle handleTagValItemValue(thread, JSTaggedValue(intItemValue)); + + EcmaModule::AddItem(thread, handleEcmaModule, handleTagValItemName, handleTagValItemValue); + EcmaModule::RemoveItem(thread, handleEcmaModule, handleTagValItemName); + EXPECT_TRUE(handleEcmaModule->GetItem(thread, handleTagValItemName)->IsUndefined()); +} + +/* + * Feature: EcmaModule + * Function: SetNameDictionary + * SubFunction: NameDictionary::Put/GetNameDictionary + * FunctionPoints: Set NameDictionary For EcmaModule + * CaseDescription: Create a source key, a source value, a source NameDictionary and a target EcmaModule, change the + * NameDictionary through 'NameDictionary::Put' function, set the changed source NameDictionary as + * this target EcmaModule's NameDictionary through 'SetNameDictionary' function, check whether the + * result returned through 'GetNameDictionary' function from the target EcmaModule are within + * expectations. + */ +HWTEST_F_L0(EcmaModuleTest, SetNameDictionary) +{ + ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory(); + + int numOfElementsDict = 4; + JSHandle handleNameDict(thread, NameDictionary::Create(thread, numOfElementsDict)); + JSHandle handleObjFunc = thread->GetEcmaVM()->GetGlobalEnv()->GetObjectFunction(); + CString keyArray1 = "hello1"; + JSHandle stringKey1 = objFactory->NewFromCanBeCompressString(keyArray1); + JSHandle key1(stringKey1); + JSHandle value1(objFactory + ->NewJSObjectByConstructor(JSHandle(handleObjFunc), handleObjFunc)); + JSHandle handleNameDictionaryFrom(thread, + NameDictionary::Put(thread, handleNameDict, key1, value1, PropertyAttributes::Default())); + JSHandle handleEcmaModule(thread, EcmaModuleCreate(thread)); + + handleEcmaModule->SetNameDictionary(thread, handleNameDictionaryFrom); + JSHandle handleNameDictionaryTo(thread, + NameDictionary::Cast(handleEcmaModule->GetNameDictionary().GetTaggedObject())); + EXPECT_EQ(handleNameDictionaryTo->EntriesCount(), 1); + int entry1 = handleNameDictionaryTo->FindEntry(key1.GetTaggedValue()); + EXPECT_TRUE(key1.GetTaggedValue() == handleNameDictionaryTo->GetKey(entry1)); + EXPECT_TRUE(value1.GetTaggedValue() == handleNameDictionaryTo->GetValue(entry1)); +} + +/* + * Feature: ModuleManager + * Function: AddModule + * SubFunction: AddItem/GetModule/GetItem + * FunctionPoints: Add EcmaModule To ModuleManager + * CaseDescription: Create 2 source EcmaModules that both add an item, create a ModuleManager that add the 2 source + * EcmaModule, check whether the items of EcmaModules obtained from the ModuleManager through + * 'GetModule' function and 'GetItem' function are within expectations. + */ +HWTEST_F_L0(EcmaModuleTest, ModuleManager_AddModule) +{ + ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory(); + ModuleManager *moduleManager = thread->GetEcmaVM()->GetModuleManager(); + + int numOfElementsDict1 = 4; + int numOfElementsDict2 = 4; + CString cStrItemName1 = "cStrItemName1"; + CString cStrItemName2 = "cStrItemName2"; + int intItemValue1 = 1; + int intItemValue2 = 2; + JSHandle handleNameDict1(thread, NameDictionary::Create(thread, numOfElementsDict1)); + JSHandle handleNameDict2(thread, NameDictionary::Create(thread, numOfElementsDict2)); + JSHandle handleItemName1( + thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(cStrItemName1)); + JSHandle handleItemName2( + thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(cStrItemName2)); + JSHandle handleItemValue1(thread, JSTaggedValue(intItemValue1)); + JSHandle handleItemValue2(thread, JSTaggedValue(intItemValue2)); + JSHandle handleEcmaModuleAddFrom1(thread, EcmaModuleCreate(thread)); + JSHandle handleEcmaModuleAddFrom2(thread, EcmaModuleCreate(thread)); + handleEcmaModuleAddFrom1->SetNameDictionary(thread, handleNameDict1); + handleEcmaModuleAddFrom2->SetNameDictionary(thread, handleNameDict2); + + EcmaModule::AddItem(thread, handleEcmaModuleAddFrom1, handleItemName1, handleItemValue1); + JSHandle handleTagValEcmaModuleAddFrom1(thread, handleEcmaModuleAddFrom1.GetTaggedValue()); + std::string stdStrNameEcmaModuleAdd1 = "NameEcmaModule1"; + JSHandle handleTagValNameEcmaModuleAdd1(objFactory->NewFromStdString(stdStrNameEcmaModuleAdd1)); + EcmaModule::AddItem(thread, handleEcmaModuleAddFrom2, handleItemName2, handleItemValue2); + JSHandle handleTagValEcmaModuleAddFrom2(thread, handleEcmaModuleAddFrom2.GetTaggedValue()); + std::string stdStrNameEcmaModuleAdd2 = "NameEcmaModule2"; + JSHandle handleTagValNameEcmaModuleAdd2(objFactory->NewFromStdString(stdStrNameEcmaModuleAdd2)); + + moduleManager->AddModule(handleTagValNameEcmaModuleAdd1, handleTagValEcmaModuleAddFrom1); + moduleManager->AddModule(handleTagValNameEcmaModuleAdd2, handleTagValEcmaModuleAddFrom2); + JSHandle handleTagValEcmaModuleGet1 = moduleManager->GetModule(thread, + handleTagValNameEcmaModuleAdd1); + JSHandle handleTagValEcmaModuleGet2 = moduleManager->GetModule(thread, + handleTagValNameEcmaModuleAdd2); + EXPECT_EQ(JSHandle::Cast(handleTagValEcmaModuleGet1)->GetItem(thread, handleItemName1)->GetNumber(), + intItemValue1); + EXPECT_EQ(JSHandle::Cast(handleTagValEcmaModuleGet2)->GetItem(thread, handleItemName2)->GetNumber(), + intItemValue2); +} + +/* + * Feature: ModuleManager + * Function: RemoveModule + * SubFunction: AddItem/GetModule/AddModule/GetItem + * FunctionPoints: Remove EcmaModule From ModuleManager + * CaseDescription: Create two source EcmaModules that add different items, create a ModuleManager that add the two + * source EcmaModules, check whether the properties of the EcmaModules obtained from the ModuleManager + * through 'GetModule' function are within expectations while removing EcmaModules from the + * ModuleManager through 'RemoveModule' function one by one. + */ +HWTEST_F_L0(EcmaModuleTest, ModuleManager_RemoveModule) +{ + ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory(); + ModuleManager *moduleManager = thread->GetEcmaVM()->GetModuleManager(); + + std::string stdStrNameEcmaModuleAdd1 = "NameEcmaModule1"; + std::string stdStrNameEcmaModuleAdd2 = "NameEcmaModule2"; + int intItemValue1 = 1; + int intItemValue2 = 2; + int numOfElementsDict1 = 4; + int numOfElementsDict2 = 4; + JSHandle handleTagValNameEcmaModuleAdd1(objFactory->NewFromStdString(stdStrNameEcmaModuleAdd1)); + JSHandle handleTagValNameEcmaModuleAdd2(objFactory->NewFromStdString(stdStrNameEcmaModuleAdd2)); + JSHandle handleTagValItemName1(objFactory->NewFromCanBeCompressString("name1")); + JSHandle handleTagValItemName2(objFactory->NewFromCanBeCompressString("name2")); + JSHandle handleTagValItemValue1(thread, JSTaggedValue(intItemValue1)); + JSHandle handleTagValItemValue2(thread, JSTaggedValue(intItemValue2)); + JSHandle handleEcmaModuleAddFrom1(thread, EcmaModuleCreate(thread)); + JSHandle handleEcmaModuleAddFrom2(thread, EcmaModuleCreate(thread)); + JSHandle handleNameDict1(thread, NameDictionary::Create(thread, numOfElementsDict1)); + JSHandle handleNameDict2(thread, NameDictionary::Create(thread, numOfElementsDict2)); + handleEcmaModuleAddFrom1->SetNameDictionary(thread, handleNameDict1); + handleEcmaModuleAddFrom2->SetNameDictionary(thread, handleNameDict2); + EcmaModule::AddItem(thread, handleEcmaModuleAddFrom1, handleTagValItemName1, handleTagValItemValue1); + EcmaModule::AddItem(thread, handleEcmaModuleAddFrom2, handleTagValItemName2, handleTagValItemValue2); + JSHandle handleTaggedValueEcmaModuleAddFrom1(thread, handleEcmaModuleAddFrom1.GetTaggedValue()); + JSHandle handleTaggedValueEcmaModuleAddFrom2(thread, handleEcmaModuleAddFrom2.GetTaggedValue()); + + moduleManager->AddModule(handleTagValNameEcmaModuleAdd1, handleTaggedValueEcmaModuleAddFrom1); + moduleManager->AddModule(handleTagValNameEcmaModuleAdd2, handleTaggedValueEcmaModuleAddFrom2); + EXPECT_EQ(JSHandle::Cast(moduleManager->GetModule(thread, handleTagValNameEcmaModuleAdd1)) + ->GetItem(thread, handleTagValItemName1)->GetNumber(), intItemValue1); + EXPECT_EQ(JSHandle::Cast(moduleManager->GetModule(thread, handleTagValNameEcmaModuleAdd2)) + ->GetItem(thread, handleTagValItemName2)->GetNumber(), intItemValue2); + + moduleManager->RemoveModule(handleTagValNameEcmaModuleAdd1); + EXPECT_TRUE(moduleManager->GetModule(thread, handleTagValNameEcmaModuleAdd1)->IsUndefined()); + EXPECT_EQ(JSHandle::Cast(moduleManager->GetModule(thread, handleTagValNameEcmaModuleAdd2)) + ->GetItem(thread, handleTagValItemName2)->GetNumber(), intItemValue2); + + moduleManager->RemoveModule(handleTagValNameEcmaModuleAdd2); + EXPECT_TRUE(moduleManager->GetModule(thread, handleTagValNameEcmaModuleAdd1)->IsUndefined()); + EXPECT_TRUE(moduleManager->GetModule(thread, handleTagValNameEcmaModuleAdd2)->IsUndefined()); +} + +/* + * Feature: ModuleManager + * Function: SetCurrentExportModuleName + * SubFunction: GetCurrentExportModuleName + * FunctionPoints: Get Current ExportModuleName Of ModuleManager + * CaseDescription: Create a ModuleManager, check whether the ExportModuleName obtained from the ModuleManager through + * 'GetCurrentExportModuleName' function is within expectations while changing the Current + * ExportModuleName of the ModuleManager through 'SetCurrentExportModuleName' function. + */ +HWTEST_F_L0(EcmaModuleTest, ModuleManager_SetCurrentExportModuleName) +{ + ModuleManager *moduleManager = thread->GetEcmaVM()->GetModuleManager(); + + std::string_view strViewNameEcmaModule1 = "NameEcmaModule1"; + std::string_view strViewNameEcmaModule2 = "NameEcmaModule2"; + moduleManager->SetCurrentExportModuleName(strViewNameEcmaModule1); + EXPECT_STREQ(moduleManager->GetCurrentExportModuleName().c_str(), CString(strViewNameEcmaModule1).c_str()); + moduleManager->SetCurrentExportModuleName(strViewNameEcmaModule2); + EXPECT_STREQ(moduleManager->GetCurrentExportModuleName().c_str(), CString(strViewNameEcmaModule2).c_str()); +} + +/* + * Feature: ModuleManager + * Function: GetPrevExportModuleName + * SubFunction: SetCurrentExportModuleName + * FunctionPoints: Get Previous ExportModuleName Of ModuleManager + * CaseDescription: Create a ModuleManager, check whether the previous ExportModuleName obtained from the ModuleManager + * through 'GetPrevExportModuleName' function is within expectations while changing the Current + * ExportModuleName of the ModuleManager through 'SetCurrentExportModuleName' function. + */ +HWTEST_F_L0(EcmaModuleTest, ModuleManager_GetPrevExportModuleName) +{ + ModuleManager *moduleManager = thread->GetEcmaVM()->GetModuleManager(); + + std::string_view strViewNameEcmaModule1 = "NameEcmaModule1"; + std::string_view strViewNameEcmaModule2 = "NameEcmaModule2"; + std::string_view strViewNameEcmaModule3 = "NameEcmaModule3"; + moduleManager->SetCurrentExportModuleName(strViewNameEcmaModule1); + moduleManager->SetCurrentExportModuleName(strViewNameEcmaModule2); + EXPECT_STREQ(moduleManager->GetPrevExportModuleName().c_str(), CString(strViewNameEcmaModule1).c_str()); + moduleManager->SetCurrentExportModuleName(strViewNameEcmaModule3); + EXPECT_STREQ(moduleManager->GetPrevExportModuleName().c_str(), CString(strViewNameEcmaModule2).c_str()); +} + +/* + * Feature: ModuleManager + * Function: RestoreCurrentExportModuleName + * SubFunction: SetCurrentExportModuleName/GetCurrentExportModuleName + * FunctionPoints: Restore Current ExportModuleName Of ModuleManager + * CaseDescription: Create a ModuleManager, check whether the current ExportModuleName obtained from the ModuleManager + * through 'GetCurrentExportModuleName' function is within expectations while changing the Current + * ExportModuleName of the ModuleManager through 'SetCurrentExportModuleName' function and + * 'RestoreCurrentExportModuleName' function. + */ +HWTEST_F_L0(EcmaModuleTest, ModuleManager_RestoreCurrentExportModuleName) +{ + ModuleManager *moduleManager = thread->GetEcmaVM()->GetModuleManager(); + + std::string_view strViewNameEcmaModule1 = "NameEcmaModule1"; + std::string_view strViewNameEcmaModule2 = "NameEcmaModule2"; + std::string_view strViewNameEcmaModule3 = "NameEcmaModule3"; + moduleManager->SetCurrentExportModuleName(strViewNameEcmaModule1); + moduleManager->SetCurrentExportModuleName(strViewNameEcmaModule2); + moduleManager->SetCurrentExportModuleName(strViewNameEcmaModule3); + EXPECT_STREQ(moduleManager->GetCurrentExportModuleName().c_str(), CString(strViewNameEcmaModule3).c_str()); + moduleManager->RestoreCurrentExportModuleName(); + EXPECT_STREQ(moduleManager->GetCurrentExportModuleName().c_str(), CString(strViewNameEcmaModule2).c_str()); + moduleManager->RestoreCurrentExportModuleName(); + EXPECT_STREQ(moduleManager->GetCurrentExportModuleName().c_str(), CString(strViewNameEcmaModule1).c_str()); +} + +/* + * Feature: ModuleManager + * Function: AddModuleItem + * SubFunction: SetCurrentExportModuleName/GetModule/GetModuleItem + * FunctionPoints: Add ModuleItem For Current EcmaModule Of ModuleManager + * CaseDescription: Create a ModuleManager, set the current EcmaModule for the ModuleManager through + * 'SetCurrentExportModuleName' function, add source ModuleItems for the current EcmaModule Of the + * ModuleManager, check whether the ModuleItems obtained through 'GetModuleItem' function from the + * ModuleManager are within expectations. + */ +HWTEST_F_L0(EcmaModuleTest, ModuleManager_AddModuleItem) +{ + ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory(); + ModuleManager *moduleManager = thread->GetEcmaVM()->GetModuleManager(); + + int intItemValue11 = 11; + int intItemValue12 = 12; + int intItemValue21 = 21; + int intItemValue22 = 22; + JSHandle handleTagValItemName11(objFactory->NewFromCanBeCompressString("cStrItemName11")); + JSHandle handleTagValItemName12(objFactory->NewFromCanBeCompressString("cStrItemName12")); + JSHandle handleTagValItemName21(objFactory->NewFromCanBeCompressString("cStrItemName21")); + JSHandle handleTagValItemName22(objFactory->NewFromCanBeCompressString("cStrItemName22")); + JSHandle handleTagValItemValue11(thread, JSTaggedValue(intItemValue11)); + JSHandle handleTagValItemValue12(thread, JSTaggedValue(intItemValue12)); + JSHandle handleTagValItemValue21(thread, JSTaggedValue(intItemValue21)); + JSHandle handleTagValItemValue22(thread, JSTaggedValue(intItemValue22)); + JSHandle handleEcmaStrNameEcmaModule1 = objFactory->NewFromString("cStrNameEcmaModule1"); + JSHandle handleEcmaStrNameEcmaModule2 = objFactory->NewFromString("cStrNameEcmaModule2"); + std::string stdStrModuleFileName1 = JSLocale::ConvertToStdString(handleEcmaStrNameEcmaModule1); + std::string stdStrModuleFileName2 = JSLocale::ConvertToStdString(handleEcmaStrNameEcmaModule2); + JSHandle handleTagValEcmaModuleName1(handleEcmaStrNameEcmaModule1); + JSHandle handleTagValEcmaModuleName2(handleEcmaStrNameEcmaModule2); + + // Test when the module is created through 'NewEmptyEcmaModule' function called at HWTEST_F_L0. + JSHandle handleEcmaModule1(thread, EcmaModuleCreate(thread)); + JSHandle handleTagValEcmaModule1(thread, handleEcmaModule1.GetTaggedValue()); + moduleManager->AddModule(handleTagValEcmaModuleName1, handleTagValEcmaModule1); + moduleManager->SetCurrentExportModuleName(stdStrModuleFileName1); + moduleManager->AddModuleItem(thread, handleTagValItemName11, handleTagValItemValue11); + moduleManager->AddModuleItem(thread, handleTagValItemName12, handleTagValItemValue12); + + EXPECT_EQ(moduleManager->GetModuleItem(thread, handleTagValEcmaModule1, handleTagValItemName11)->GetNumber(), + intItemValue11); + EXPECT_EQ(moduleManager->GetModuleItem(thread, handleTagValEcmaModule1, handleTagValItemName12)->GetNumber(), + intItemValue12); + + // Test when the module is created through 'NewEmptyEcmaModule' function called at "ecma_module.cpp". + moduleManager->SetCurrentExportModuleName(stdStrModuleFileName2); + moduleManager->AddModuleItem(thread, handleTagValItemName21, handleTagValItemValue21); + moduleManager->AddModuleItem(thread, handleTagValItemName22, handleTagValItemValue22); + + JSHandle handleTagValEcmaModule2 = moduleManager->GetModule(thread, handleTagValEcmaModuleName2); + EXPECT_EQ(moduleManager->GetModuleItem(thread, handleTagValEcmaModule1, handleTagValItemName11)->GetNumber(), + intItemValue11); + EXPECT_EQ(moduleManager->GetModuleItem(thread, handleTagValEcmaModule1, handleTagValItemName12)->GetNumber(), + intItemValue12); + EXPECT_EQ(moduleManager->GetModuleItem(thread, handleTagValEcmaModule2, handleTagValItemName21)->GetNumber(), + intItemValue21); + EXPECT_EQ(moduleManager->GetModuleItem(thread, handleTagValEcmaModule2, handleTagValItemName22)->GetNumber(), + intItemValue22); +} + +/* + * Feature: ModuleManager + * Function: CopyModule + * SubFunction: AddItem/SetCurrentExportModuleName/GetModule/GetModuleItem + * FunctionPoints: Copy EcmaModule To ModuleManager + * CaseDescription: Create two source EcmaModules and one target ModuleManager, prepare the two source EcmaModules + * through 'AddItem' function, check whether the the ModuleItems obtained through 'GetModuleItem' from + * the target ModuleManager are within expectations while changing the target ModuleManager through + * 'SetCurrentExportModuleName' function and 'CopyModule' function. + */ +HWTEST_F_L0(EcmaModuleTest, ModuleManager_CopyModule) +{ + ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory(); + ModuleManager *moduleManager = thread->GetEcmaVM()->GetModuleManager(); + + int intItemValue11 = 11; + int intItemValue12 = 12; + int intItemValue21 = 21; + int intItemValue22 = 22; + std::string_view fileNameEcmaModuleCopyTo1 = "fileNameEcmaModuleCopyTo1"; + std::string_view fileNameEcmaModuleCopyTo2 = "fileNameEcmaModuleCopyTo2"; + JSHandle handleTagValItemName11(objFactory->NewFromCanBeCompressString("ItemName11")); + JSHandle handleTagValItemName12(objFactory->NewFromCanBeCompressString("ItemName12")); + JSHandle handleTagValItemName21(objFactory->NewFromCanBeCompressString("ItemName21")); + JSHandle handleTagValItemName22(objFactory->NewFromCanBeCompressString("ItemName22")); + JSHandle handleTagValItemValue11(thread, JSTaggedValue(intItemValue11)); + JSHandle handleTagValItemValue12(thread, JSTaggedValue(intItemValue12)); + JSHandle handleTagValItemValue21(thread, JSTaggedValue(intItemValue21)); + JSHandle handleTagValItemValue22(thread, JSTaggedValue(intItemValue22)); + JSHandle handleEcmaModuleCopyFrom1(thread, EcmaModuleCreate(thread)); + JSHandle handleEcmaModuleCopyFrom2(thread, EcmaModuleCreate(thread)); + JSHandle handleTagValEcmaModuleCopyFrom1(thread, handleEcmaModuleCopyFrom1.GetTaggedValue()); + JSHandle handleTagValEcmaModuleCopyFrom2(thread, handleEcmaModuleCopyFrom2.GetTaggedValue()); + EcmaModule::AddItem(thread, handleEcmaModuleCopyFrom1, handleTagValItemName11, handleTagValItemValue11); + EcmaModule::AddItem(thread, handleEcmaModuleCopyFrom1, handleTagValItemName12, handleTagValItemValue12); + EcmaModule::AddItem(thread, handleEcmaModuleCopyFrom2, handleTagValItemName21, handleTagValItemValue21); + EcmaModule::AddItem(thread, handleEcmaModuleCopyFrom2, handleTagValItemName22, handleTagValItemValue22); + + moduleManager->SetCurrentExportModuleName(fileNameEcmaModuleCopyTo1); + moduleManager->CopyModule(thread, handleTagValEcmaModuleCopyFrom1); + JSHandle handleTagValEcmaModuleCopyTo1 = moduleManager->GetModule(thread, + JSHandle::Cast(objFactory->NewFromString(CString(fileNameEcmaModuleCopyTo1)))); + EXPECT_EQ(intItemValue11, + moduleManager->GetModuleItem(thread, handleTagValEcmaModuleCopyTo1, handleTagValItemName11)->GetNumber()); + EXPECT_EQ(intItemValue12, + moduleManager->GetModuleItem(thread, handleTagValEcmaModuleCopyTo1, handleTagValItemName12)->GetNumber()); + + moduleManager->SetCurrentExportModuleName(fileNameEcmaModuleCopyTo2); + moduleManager->CopyModule(thread, handleTagValEcmaModuleCopyFrom2); + JSHandle handleTagValEcmaModuleCopyTo2 = moduleManager->GetModule(thread, + JSHandle::Cast(objFactory->NewFromString(CString(fileNameEcmaModuleCopyTo2)))); + EXPECT_EQ(intItemValue11, + moduleManager->GetModuleItem(thread, handleTagValEcmaModuleCopyTo1, handleTagValItemName11)->GetNumber()); + EXPECT_EQ(intItemValue12, + moduleManager->GetModuleItem(thread, handleTagValEcmaModuleCopyTo1, handleTagValItemName12)->GetNumber()); + EXPECT_EQ(intItemValue21, + moduleManager->GetModuleItem(thread, handleTagValEcmaModuleCopyTo2, handleTagValItemName21)->GetNumber()); + EXPECT_EQ(intItemValue22, + moduleManager->GetModuleItem(thread, handleTagValEcmaModuleCopyTo2, handleTagValItemName22)->GetNumber()); +} + +// ModuleStack +/* + * Feature: ModuleStack + * Function: PushModule + * SubFunction: GetTop + * FunctionPoints: Push EcmaModule By Name + * CaseDescription: Create a target ModuleStack, push a source EcmaModule name at the back of the name vector of the + * target ModuleStack, check whether the returned EcmaModule name obtained through 'GetTop' function + * from the target ModuleStack is the same with the source EcmaModule name. + */ +HWTEST_F_L0(EcmaModuleTest, ModuleStack_PushModule) +{ + ModuleStack moduleStack; + + CString cStrPushNo1 = "cStrPushNo1"; + CString cStrPushNo2 = "cStrPushNo2"; + CString cStrPushNo3 = "cStrPushNo3"; + moduleStack.PushModule(cStrPushNo1); + EXPECT_STREQ(moduleStack.GetTop().c_str(), cStrPushNo1.c_str()); + moduleStack.PushModule(cStrPushNo2); + EXPECT_STREQ(moduleStack.GetTop().c_str(), cStrPushNo2.c_str()); + moduleStack.PushModule(cStrPushNo3); + EXPECT_STREQ(moduleStack.GetTop().c_str(), cStrPushNo3.c_str()); +} + +/* + * Feature: ModuleStack + * Function: PopModule + * SubFunction: PushModule/GetTop + * FunctionPoints: Pop EcmaModule At The Back + * CaseDescription: Create a target ModuleStack, push some source EcmaModule names at the back of the name vector of + * the target ModuleStack, check whether the returned EcmaModule name obtained through 'GetTop' + * function from the target ModuleStack now and the returned EcmaModule name obtained through 'GetTop' + * function from the target ModuleStack after the target ModuleStack calls 'PopModule' function are + * within expectations. + */ +HWTEST_F_L0(EcmaModuleTest, ModuleStack_PopModule) +{ + ModuleStack moduleStack; + + CString cStrPushNo1 = "cStrPushNo1"; + CString cStrPushNo2 = "cStrPushNo2"; + CString cStrPushNo3 = "cStrPushNo3"; + moduleStack.PushModule(cStrPushNo1); + moduleStack.PushModule(cStrPushNo2); + moduleStack.PushModule(cStrPushNo3); + EXPECT_STREQ(moduleStack.GetTop().c_str(), cStrPushNo3.c_str()); + moduleStack.PopModule(); + EXPECT_STREQ(moduleStack.GetTop().c_str(), cStrPushNo2.c_str()); + moduleStack.PopModule(); + EXPECT_STREQ(moduleStack.GetTop().c_str(), cStrPushNo1.c_str()); + moduleStack.PopModule(); +} + +/* + * Feature: ModuleStack + * Function: GetPrevModule + * SubFunction: PushModule/GetTop/PopModule + * FunctionPoints: Get Previous Module + * CaseDescription: Create a target ModuleStack, push some source EcmaModule names at the back of the name vector of + * the target ModuleStack, check whether the returned EcmaModule name obtained through 'GetPrevModule' + * function from the target ModuleStack now and the returned EcmaModule name obtained through + * 'GetPrevModule' function from the target ModuleStack after the target ModuleStack calls 'PushModule' + * function or 'PopModule' function are within expectations. + */ +HWTEST_F_L0(EcmaModuleTest, ModuleStack_GetPrevModule) +{ + ModuleStack moduleStack; + + CString cStrPushNo1 = "cStrPushNo1"; + CString cStrPushNo2 = "cStrPushNo2"; + CString cStrPushNo3 = "cStrPushNo3"; + moduleStack.PushModule(cStrPushNo1); + moduleStack.PushModule(cStrPushNo2); + EXPECT_STREQ(moduleStack.GetPrevModule().c_str(), cStrPushNo1.c_str()); + moduleStack.PushModule(cStrPushNo3); + EXPECT_STREQ(moduleStack.GetPrevModule().c_str(), cStrPushNo2.c_str()); + moduleStack.PopModule(); + EXPECT_STREQ(moduleStack.GetPrevModule().c_str(), cStrPushNo1.c_str()); +} +} // namespace panda::ecmascript -- Gitee From 9a7fcb6e3cf2881f05bdf4d8308411730ef4851c Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Wed, 20 Oct 2021 17:35:03 +0800 Subject: [PATCH 046/115] fix container using error and gc bug Signed-off-by: wengchangcheng --- ecmascript/builtins/builtins_promise.cpp | 4 +-- .../builtins/builtins_promise_handler.cpp | 2 +- .../builtins/tests/builtins_promise_test.cpp | 10 +++---- ecmascript/ecma_module.cpp | 20 +++++++------- ecmascript/ecma_vm.cpp | 4 +-- ecmascript/ecma_vm.h | 10 ------- .../interpreter/fast_runtime_stub-inl.h | 20 +++++++------- ecmascript/interpreter/slow_runtime_stub.cpp | 3 ++- ecmascript/jobs/micro_job_queue.cpp | 26 +++++++++---------- ecmascript/jobs/micro_job_queue.h | 6 ++--- ecmascript/js_array.cpp | 4 +-- ecmascript/js_for_in_iterator.cpp | 9 ++++--- ecmascript/js_hclass-inl.h | 10 ++++--- ecmascript/js_map.cpp | 8 +++--- ecmascript/js_object.cpp | 26 ++++++++++--------- ecmascript/js_promise.cpp | 2 +- ecmascript/js_set.cpp | 8 +++--- ecmascript/js_weak_container.cpp | 16 ++++++------ ecmascript/object_operator.cpp | 18 ++++++------- ecmascript/tests/name_dictionary_test.cpp | 15 ++++++----- ecmascript/weak_vector-inl.h | 2 +- 21 files changed, 111 insertions(+), 112 deletions(-) diff --git a/ecmascript/builtins/builtins_promise.cpp b/ecmascript/builtins/builtins_promise.cpp index 0e57dd6..663bd1d 100644 --- a/ecmascript/builtins/builtins_promise.cpp +++ b/ecmascript/builtins/builtins_promise.cpp @@ -414,7 +414,7 @@ JSTaggedValue BuiltinsPromise::PerformPromiseThen(JSThread *thread, const JSHand argv->Set(thread, 1, promise->GetPromiseResult()); JSHandle promiseReactionsJob(env->GetPromiseReactionJob()); - job->EnqueueJob(thread, job::QueueType::QUEUE_PROMISE, promiseReactionsJob, argv); + job::MicroJobQueue::EnqueueJob(thread, job, job::QueueType::QUEUE_PROMISE, promiseReactionsJob, argv); } else if (JSTaggedValue::SameValue(promise->GetPromiseState(), JSTaggedValue(static_cast(PromiseStatus::REJECTED)))) { JSHandle argv = factory->NewTaggedArray(2); // 2: 2 means two args stored in array @@ -422,7 +422,7 @@ JSTaggedValue BuiltinsPromise::PerformPromiseThen(JSThread *thread, const JSHand argv->Set(thread, 1, promise->GetPromiseResult()); JSHandle promiseReactionsJob(env->GetPromiseReactionJob()); - job->EnqueueJob(thread, job::QueueType::QUEUE_PROMISE, promiseReactionsJob, argv); + job::MicroJobQueue::EnqueueJob(thread, job, job::QueueType::QUEUE_PROMISE, promiseReactionsJob, argv); } return capability->GetPromise(); } diff --git a/ecmascript/builtins/builtins_promise_handler.cpp b/ecmascript/builtins/builtins_promise_handler.cpp index 0d9a8cf..966e132 100644 --- a/ecmascript/builtins/builtins_promise_handler.cpp +++ b/ecmascript/builtins/builtins_promise_handler.cpp @@ -95,7 +95,7 @@ JSTaggedValue BuiltinsPromiseHandler::Resolve(EcmaRuntimeCallInfo *argv) JSHandle promiseResolveThenableJob(env->GetPromiseResolveThenableJob()); JSHandle job = thread->GetEcmaVM()->GetMicroJobQueue(); - job->EnqueueJob(thread, job::QueueType::QUEUE_PROMISE, promiseResolveThenableJob, arguments); + job::MicroJobQueue::EnqueueJob(thread, job, job::QueueType::QUEUE_PROMISE, promiseResolveThenableJob, arguments); // 13. Return undefined. return JSTaggedValue::Undefined(); diff --git a/ecmascript/builtins/tests/builtins_promise_test.cpp b/ecmascript/builtins/tests/builtins_promise_test.cpp index cba9fba..d5e7bcb 100644 --- a/ecmascript/builtins/tests/builtins_promise_test.cpp +++ b/ecmascript/builtins/tests/builtins_promise_test.cpp @@ -449,7 +449,7 @@ HWTEST_F_L0(BuiltinsPromiseTest, Race2) */ auto microJobQueue = EcmaVM::Cast(instance)->GetMicroJobQueue(); if (!thread->HasPendingException()) { - microJobQueue->ExecutePendingJob(thread); + job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue); } } @@ -550,7 +550,7 @@ HWTEST_F_L0(BuiltinsPromiseTest, All) */ auto microJobQueue = EcmaVM::Cast(instance)->GetMicroJobQueue(); if (!thread->HasPendingException()) { - microJobQueue->ExecutePendingJob(thread); + job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue); } } @@ -606,7 +606,7 @@ HWTEST_F_L0(BuiltinsPromiseTest, Catch) */ auto microJobQueue = EcmaVM::Cast(instance)->GetMicroJobQueue(); if (!thread->HasPendingException()) { - microJobQueue->ExecutePendingJob(thread); + job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue); } } @@ -664,7 +664,7 @@ HWTEST_F_L0(BuiltinsPromiseTest, ThenResolve) */ auto microJobQueue = EcmaVM::Cast(instance)->GetMicroJobQueue(); if (!thread->HasPendingException()) { - microJobQueue->ExecutePendingJob(thread); + job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue); } } @@ -721,7 +721,7 @@ HWTEST_F_L0(BuiltinsPromiseTest, ThenReject) */ auto microJobQueue = EcmaVM::Cast(instance)->GetMicroJobQueue(); if (!thread->HasPendingException()) { - microJobQueue->ExecutePendingJob(thread); + job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue); } } } // namespace panda::test diff --git a/ecmascript/ecma_module.cpp b/ecmascript/ecma_module.cpp index 32f7c2b..cebd2c0 100644 --- a/ecmascript/ecma_module.cpp +++ b/ecmascript/ecma_module.cpp @@ -42,12 +42,13 @@ void EcmaModule::AddItem(const JSThread *thread, JSHandle module, JS JSHandle data(thread, module->GetNameDictionary()); if (data->IsUndefined()) { JSHandle dict(thread, NameDictionary::Create(thread, DICTIONART_CAP)); - auto result = dict->Put(thread, dict, itemName, itemValue, PropertyAttributes::Default()); - module->SetNameDictionary(thread, JSTaggedValue(result)); + NameDictionary *newDict = NameDictionary::Put(thread, dict, itemName, itemValue, PropertyAttributes::Default()); + module->SetNameDictionary(thread, JSTaggedValue(newDict)); } else { JSHandle dataDict = JSHandle::Cast(data); - auto result = dataDict->Put(thread, dataDict, itemName, itemValue, PropertyAttributes::Default()); - module->SetNameDictionary(thread, JSTaggedValue(result)); + NameDictionary *newDict = + NameDictionary::Put(thread, dataDict, itemName, itemValue, PropertyAttributes::Default()); + module->SetNameDictionary(thread, JSTaggedValue(newDict)); } } @@ -117,20 +118,21 @@ ModuleManager::ModuleManager(EcmaVM *vm) : vm_(vm) // class ModuleManager void ModuleManager::AddModule(JSHandle moduleName, JSHandle module) { - [[maybe_unused]] EcmaHandleScope scope(vm_->GetJSThread()); - JSHandle dict(vm_->GetJSThread(), ecmaModules_); + JSThread *thread = vm_->GetJSThread(); + [[maybe_unused]] EcmaHandleScope scope(thread); + JSHandle dict(thread, ecmaModules_); ecmaModules_ = - JSTaggedValue(dict->Put(vm_->GetJSThread(), dict, moduleName, module, PropertyAttributes::Default())); + JSTaggedValue(NameDictionary::Put(thread, dict, moduleName, module, PropertyAttributes::Default())); } void ModuleManager::RemoveModule(JSHandle moduleName) { - [[maybe_unused]] EcmaHandleScope scope(vm_->GetJSThread()); JSThread *thread = vm_->GetJSThread(); + [[maybe_unused]] EcmaHandleScope scope(thread); JSHandle moduleItems(thread, ecmaModules_); int entry = moduleItems->FindEntry(moduleName.GetTaggedValue()); if (entry != -1) { - NameDictionary::Remove(vm_->GetJSThread(), moduleItems, entry); // discard return + ecmaModules_ = JSTaggedValue(NameDictionary::Remove(thread, moduleItems, entry)); } } diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index d9ddd25..7d5de2b 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -449,7 +449,7 @@ Expected EcmaVM::InvokeEcmaEntrypoint(const panda_file::Fil params->MakeArgList(*jsargs); panda::ecmascript::InvokeJsFunction(thread_, func, global, newTarget, params); if (!thread_->HasPendingException()) { - job::MicroJobQueue::Cast(microJobQueue_.GetTaggedObject())->ExecutePendingJob(thread_); + job::MicroJobQueue::ExecutePendingJob(thread_, GetMicroJobQueue()); } // print exception information @@ -650,7 +650,7 @@ void EcmaVM::ClearBufferData() bool EcmaVM::ExecutePromisePendingJob() const { if (!thread_->HasPendingException()) { - job::MicroJobQueue::Cast(microJobQueue_.GetTaggedObject())->ExecutePendingJob(thread_); + job::MicroJobQueue::ExecutePendingJob(thread_, GetMicroJobQueue()); return true; } return false; diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index 63a93b7..d100ccf 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -337,16 +337,6 @@ public: return moduleManager_; } - static constexpr uint32_t GetGlobalEnvOffset() - { - return MEMBER_OFFSET(EcmaVM, globalEnv_); - } - - static constexpr uint32_t GetMicroJobQueueOffset() - { - return MEMBER_OFFSET(EcmaVM, microJobQueue_); - } - void SetupRegExpResultCache(); JSHandle GetRegExpCache() { diff --git a/ecmascript/interpreter/fast_runtime_stub-inl.h b/ecmascript/interpreter/fast_runtime_stub-inl.h index f5ec114..7d2faab 100644 --- a/ecmascript/interpreter/fast_runtime_stub-inl.h +++ b/ecmascript/interpreter/fast_runtime_stub-inl.h @@ -269,8 +269,8 @@ JSTaggedValue FastRuntimeStub::AddPropertyByName(JSThread *thread, JSTaggedValue // change to dictionary and add one. JSHandle dict(JSObject::TransitionToDictionary(thread, objHandle)); attr.SetDictionaryOrder(PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES); - auto result = JSTaggedValue(NameDictionary::PutIfAbsent(thread, dict, keyHandle, valueHandle, attr)); - objHandle->SetProperties(thread, result); + NameDictionary *newDict = NameDictionary::PutIfAbsent(thread, dict, keyHandle, valueHandle, attr); + objHandle->SetProperties(thread, JSTaggedValue(newDict)); // index is not essential when fastMode is false; return JSTaggedValue::Undefined(); } @@ -286,8 +286,8 @@ JSTaggedValue FastRuntimeStub::AddPropertyByName(JSThread *thread, JSTaggedValue array->Set(thread, outProps, valueHandle.GetTaggedValue()); } else { JSHandle dictHandle(array); - auto result = JSTaggedValue(NameDictionary::PutIfAbsent(thread, dictHandle, keyHandle, valueHandle, attr)); - objHandle->SetProperties(thread, result); + NameDictionary *newDict = NameDictionary::PutIfAbsent(thread, dictHandle, keyHandle, valueHandle, attr); + objHandle->SetProperties(thread, JSTaggedValue(newDict)); } return JSTaggedValue::Undefined(); } @@ -970,9 +970,9 @@ bool FastRuntimeStub::SetGlobalOwnProperty(JSThread *thread, JSTaggedValue recei PropertyBoxType boxType = valHandle->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT; attr.SetBoxType(boxType); - objHandle->SetProperties( - thread, JSTaggedValue(GlobalDictionary::PutIfAbsent(thread, dict_handle, keyHandle, - JSHandle(boxHandle), attr))); + GlobalDictionary *properties = + GlobalDictionary::PutIfAbsent(thread, dict_handle, keyHandle, JSHandle(boxHandle), attr); + objHandle->SetProperties(thread, JSTaggedValue(properties)); return true; } @@ -1020,9 +1020,9 @@ bool FastRuntimeStub::SetGlobalOwnProperty(JSThread *thread, JSTaggedValue recei PropertyBoxType boxType = valHandle->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT; attr.SetBoxType(boxType); - objHandle->SetProperties(thread, JSTaggedValue(GlobalDictionary::PutIfAbsent( - thread, dict_handle, keyHandle, - JSHandle(boxHandle), attr))); + GlobalDictionary *properties = + GlobalDictionary::PutIfAbsent(thread, dict_handle, keyHandle, JSHandle(boxHandle), attr); + objHandle->SetProperties(thread, JSTaggedValue(properties)); return true; } diff --git a/ecmascript/interpreter/slow_runtime_stub.cpp b/ecmascript/interpreter/slow_runtime_stub.cpp index 1b89dde..0731b5f 100644 --- a/ecmascript/interpreter/slow_runtime_stub.cpp +++ b/ecmascript/interpreter/slow_runtime_stub.cpp @@ -1439,8 +1439,9 @@ JSTaggedValue SlowRuntimeStub::StGlobalRecord(JSThread *thread, JSTaggedValue pr PropertyBoxType boxType = valueHandle->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT; attributes.SetBoxType(boxType); - dict->PutIfAbsent(thread, dictHandle, propHandle, JSHandle(box), attributes); + dict = GlobalDictionary::PutIfAbsent(thread, dictHandle, propHandle, JSHandle(box), attributes); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + env->SetGlobalRecord(thread, JSTaggedValue(dict)); return JSTaggedValue::True(); } diff --git a/ecmascript/jobs/micro_job_queue.cpp b/ecmascript/jobs/micro_job_queue.cpp index 52eee1b..87605df 100644 --- a/ecmascript/jobs/micro_job_queue.cpp +++ b/ecmascript/jobs/micro_job_queue.cpp @@ -27,8 +27,8 @@ #include "utils/expected.h" namespace panda::ecmascript::job { -void MicroJobQueue::EnqueueJob(JSThread *thread, QueueType queueType, const JSHandle &job, - const JSHandle &argv) +void MicroJobQueue::EnqueueJob(JSThread *thread, JSHandle jobQueue, QueueType queueType, + const JSHandle &job, const JSHandle &argv) { // 1. Assert: Type(queueName) is String and its value is the name of a Job Queue recognized by this implementation. // 2. Assert: job is the name of a Job. @@ -39,24 +39,22 @@ void MicroJobQueue::EnqueueJob(JSThread *thread, QueueType queueType, const JSHa [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle pendingJob(factory->NewPendingJob(job, argv)); if (queueType == QueueType::QUEUE_PROMISE) { - JSHandle promiseQueue(thread, GetPromiseJobQueue()); + JSHandle promiseQueue(thread, jobQueue->GetPromiseJobQueue()); LOG_ECMA(DEBUG) << "promiseQueue start length: " << promiseQueue->Size(); - JSHandle newPromiseQueue( - thread, TaggedQueue::Push(thread, promiseQueue, JSHandle::Cast(pendingJob))); - SetPromiseJobQueue(thread, newPromiseQueue.GetTaggedValue()); + TaggedQueue *newPromiseQueue = TaggedQueue::Push(thread, promiseQueue, JSHandle(pendingJob)); + jobQueue->SetPromiseJobQueue(thread, JSTaggedValue(newPromiseQueue)); LOG_ECMA(DEBUG) << "promiseQueue end length: " << newPromiseQueue->Size(); } else if (queueType == QueueType::QUEUE_SCRIPT) { - JSHandle scriptQueue(thread, GetScriptJobQueue()); - JSHandle newScriptQueue( - thread, TaggedQueue::Push(thread, scriptQueue, JSHandle::Cast(pendingJob))); - SetScriptJobQueue(thread, newScriptQueue.GetTaggedValue()); + JSHandle scriptQueue(thread, jobQueue->GetScriptJobQueue()); + TaggedQueue *newScriptQueue = TaggedQueue::Push(thread, scriptQueue, JSHandle(pendingJob)); + jobQueue->SetScriptJobQueue(thread, JSTaggedValue(newScriptQueue)); } } -void MicroJobQueue::ExecutePendingJob(JSThread *thread) +void MicroJobQueue::ExecutePendingJob(JSThread *thread, JSHandle jobQueue) { [[maybe_unused]] EcmaHandleScope handleScope(thread); - JSHandle promiseQueue(thread, GetPromiseJobQueue()); + JSMutableHandle promiseQueue(thread, jobQueue->GetPromiseJobQueue()); JSMutableHandle pendingJob(thread, JSTaggedValue::Undefined()); while (!promiseQueue->Empty()) { LOG_ECMA(DEBUG) << "promiseQueue start length: " << promiseQueue->Size(); @@ -66,10 +64,10 @@ void MicroJobQueue::ExecutePendingJob(JSThread *thread) if (thread->HasPendingException()) { return; } - promiseQueue = JSHandle(thread, GetPromiseJobQueue()); + promiseQueue.Update(jobQueue->GetPromiseJobQueue()); } - JSHandle scriptQueue(thread, GetScriptJobQueue()); + JSHandle scriptQueue(thread, jobQueue->GetScriptJobQueue()); while (!scriptQueue->Empty()) { pendingJob.Update(scriptQueue->Pop(thread)); PendingJob::ExecutePendingJob(pendingJob, thread); diff --git a/ecmascript/jobs/micro_job_queue.h b/ecmascript/jobs/micro_job_queue.h index c2b4d12..73ab7e1 100644 --- a/ecmascript/jobs/micro_job_queue.h +++ b/ecmascript/jobs/micro_job_queue.h @@ -40,9 +40,9 @@ public: return static_cast(object); } - void EnqueueJob(JSThread *thread, QueueType queueType, const JSHandle &job, - const JSHandle &argv); - void ExecutePendingJob(JSThread *thread); + static void EnqueueJob(JSThread *thread, JSHandle jobQueue, QueueType queueType, + const JSHandle &job, const JSHandle &argv); + static void ExecutePendingJob(JSThread *thread, JSHandle jobQueue); static constexpr size_t PROMISE_JOB_QUEUE_OFFSET = Record::SIZE; ACCESSORS(PromiseJobQueue, PROMISE_JOB_QUEUE_OFFSET, SCRIPT_JOB_QUEUE_OFFSET); diff --git a/ecmascript/js_array.cpp b/ecmascript/js_array.cpp index c48c280..fa31ce0 100644 --- a/ecmascript/js_array.cpp +++ b/ecmascript/js_array.cpp @@ -190,8 +190,8 @@ void JSArray::SetCapacity(JSThread *thread, const JSHandle &array, uin uint32_t attr = dictHandle->GetAttributes(entry).GetValue(); PropertyAttributes propAttr(attr); if (propAttr.IsConfigurable()) { - NumberDictionary *dictionary = NumberDictionary::Remove(thread, dictHandle, entry); - array->SetElements(thread, JSTaggedValue(dictionary)); + NumberDictionary *newDict = NumberDictionary::Remove(thread, dictHandle, entry); + array->SetElements(thread, JSTaggedValue(newDict)); if (i == 0) { newNumOfElements = i; break; diff --git a/ecmascript/js_for_in_iterator.cpp b/ecmascript/js_for_in_iterator.cpp index 7568ade..73a20f5 100644 --- a/ecmascript/js_for_in_iterator.cpp +++ b/ecmascript/js_for_in_iterator.cpp @@ -197,7 +197,8 @@ void JSForInIterator::SlowGetAllEnumKeys(JSThread *thread, const JSHandleGet(i)); if (value->IsString()) { - remaining.Update(JSTaggedValue(TaggedQueue::Push(thread, remaining, value))); + TaggedQueue *newQueue = TaggedQueue::Push(thread, remaining, value); + remaining.Update(JSTaggedValue(newQueue)); } } it->SetRemainingKeys(thread, remaining); @@ -244,9 +245,9 @@ std::pair JSForInIterator::NextInternal(JSThread *thread, c PropertyDescriptor desc(thread); bool has = JSTaggedValue::GetOwnProperty(thread, object, key, desc); if (has) { - auto queue = JSTaggedValue(TaggedQueue::Push(thread, visited, key)); - visited.Update(queue); - it->SetVisitedKeys(thread, queue); + auto newQueue = JSTaggedValue(TaggedQueue::Push(thread, visited, key)); + visited.Update(newQueue); + it->SetVisitedKeys(thread, newQueue); if (desc.IsEnumerable()) { return std::make_pair(key.GetTaggedValue(), false); } diff --git a/ecmascript/js_hclass-inl.h b/ecmascript/js_hclass-inl.h index 2eeccd9..2ab5b76 100644 --- a/ecmascript/js_hclass-inl.h +++ b/ecmascript/js_hclass-inl.h @@ -38,6 +38,7 @@ void JSHClass::AddTransitions(const JSThread *thread, const JSHandle & child->SetParent(thread, parent.GetTaggedValue()); return; } + JSMutableHandle dict(thread, JSTaggedValue::Undefined()); if (transitions.IsJSHClass()) { auto cachedHClass = JSHClass::Cast(transitions.GetTaggedObject()); int last = cachedHClass->GetPropertiesNumber() - 1; @@ -45,11 +46,11 @@ void JSHClass::AddTransitions(const JSThread *thread, const JSHandle & auto attr = JSHandle(thread, JSTaggedValue(layoutInfo->GetAttr(last).GetPropertyMetaData())); auto lastKey = JSHandle(thread, layoutInfo->GetKey(last)); auto lastHClass = JSHandle(thread, cachedHClass); - auto dict = JSHandle(thread, TransitionsDictionary::Create(thread)); + dict.Update(JSTaggedValue(TransitionsDictionary::Create(thread))); transitions = JSTaggedValue(TransitionsDictionary::PutIfAbsent(thread, dict, lastKey, lastHClass, attr)); } auto attr = JSHandle(thread, JSTaggedValue(attributes.GetPropertyMetaData())); - JSHandle dict(thread, transitions); + dict.Update(transitions); transitions = JSTaggedValue(TransitionsDictionary::PutIfAbsent(thread, dict, key, JSHandle(child), attr)); parent->SetTransitions(thread, transitions); @@ -68,6 +69,7 @@ void JSHClass::AddProtoTransitions(const JSThread *thread, const JSHandle &proto) { JSTaggedValue transitions = parent->GetTransitions(); + JSMutableHandle dict(thread, JSTaggedValue::Undefined()); if (transitions.IsNull()) { transitions = JSTaggedValue(TransitionsDictionary::Create(thread)); } else if (transitions.IsJSHClass()) { @@ -77,11 +79,11 @@ void JSHClass::AddProtoTransitions(const JSThread *thread, const JSHandle(thread, JSTaggedValue(layoutInfo->GetAttr(last).GetPropertyMetaData())); auto lastKey = JSHandle(thread, layoutInfo->GetKey(last)); auto lastHClass = JSHandle(thread, cachedHClass); - auto dict = JSHandle(thread, TransitionsDictionary::Create(thread)); + dict.Update(JSTaggedValue(TransitionsDictionary::Create(thread))); transitions = JSTaggedValue(TransitionsDictionary::PutIfAbsent(thread, dict, lastKey, lastHClass, attr)); } - JSHandle dict(thread, transitions); + dict.Update(transitions); transitions = JSTaggedValue(TransitionsDictionary::PutIfAbsent(thread, dict, key, JSHandle(child), proto)); parent->SetTransitions(thread, transitions); diff --git a/ecmascript/js_map.cpp b/ecmascript/js_map.cpp index 9dc0130..d51326b 100644 --- a/ecmascript/js_map.cpp +++ b/ecmascript/js_map.cpp @@ -28,8 +28,8 @@ void JSMap::Set(JSThread *thread, const JSHandle &map, const JSHandle mapHandle(thread, LinkedHashMap::Cast(map->GetLinkedMap().GetTaggedObject())); - auto result = LinkedHashMap::Set(thread, mapHandle, key, value); - map->SetLinkedMap(thread, result); + JSTaggedValue newMap = LinkedHashMap::Set(thread, mapHandle, key, value); + map->SetLinkedMap(thread, newMap); } bool JSMap::Delete(const JSThread *thread, const JSHandle &map, const JSHandle &key) @@ -41,8 +41,8 @@ bool JSMap::Delete(const JSThread *thread, const JSHandle &map, const JSH } mapHandle->RemoveEntry(thread, entry); - auto result = LinkedHashMap::Shrink(thread, mapHandle); - map->SetLinkedMap(thread, result); + JSTaggedValue newMap = LinkedHashMap::Shrink(thread, mapHandle); + map->SetLinkedMap(thread, newMap); return true; } diff --git a/ecmascript/js_object.cpp b/ecmascript/js_object.cpp index 250875e..7682656 100644 --- a/ecmascript/js_object.cpp +++ b/ecmascript/js_object.cpp @@ -127,7 +127,8 @@ JSHandle JSObject::TransitionToDictionary(const JSThread *thread attr.SetBoxType(PropertyBoxType::UNDEFINED); valueHandle.Update(value); keyHandle.Update(key); - dict.Update(JSTaggedValue(NameDictionary::PutIfAbsent(thread, dict, keyHandle, valueHandle, attr))); + NameDictionary *newDict = NameDictionary::PutIfAbsent(thread, dict, keyHandle, valueHandle, attr); + dict.Update(JSTaggedValue(newDict)); } receiver->SetProperties(thread, dict); @@ -152,7 +153,8 @@ void JSObject::ElementsToDictionary(const JSThread *thread, JSHandle o } key.Update(JSTaggedValue(i)); valueHandle.Update(value); - dict.Update(JSTaggedValue(NumberDictionary::PutIfAbsent(thread, dict, key, valueHandle, attr))); + NumberDictionary *newDict = NumberDictionary::PutIfAbsent(thread, dict, key, valueHandle, attr); + dict.Update(JSTaggedValue(newDict)); } obj->SetElements(thread, dict); @@ -193,9 +195,9 @@ bool JSObject::AddElementInternal(JSThread *thread, const JSHandle &re if (isDictionary) { ASSERT(elements->IsDictionaryMode()); JSHandle keyHandle(thread, JSTaggedValue(static_cast(index))); - NumberDictionary *dict = + NumberDictionary *newDict = NumberDictionary::Put(thread, JSHandle(thread, elements), keyHandle, value, attr); - receiver->SetElements(thread, JSTaggedValue(dict)); + receiver->SetElements(thread, JSTaggedValue(newDict)); return true; } @@ -205,8 +207,8 @@ bool JSObject::AddElementInternal(JSThread *thread, const JSHandle &re JSObject::ElementsToDictionary(thread, receiver); JSHandle keyHandle(thread, JSTaggedValue(static_cast(index))); JSHandle dict(thread, receiver->GetElements()); - auto key = JSTaggedValue(NumberDictionary::Put(thread, dict, keyHandle, value, attr)); - receiver->SetElements(thread, key); + NumberDictionary *newKey = NumberDictionary::Put(thread, dict, keyHandle, value, attr); + receiver->SetElements(thread, JSTaggedValue(newKey)); return true; } elements = *JSObject::GrowElementsCapacity(thread, receiver, index + 1); @@ -223,8 +225,8 @@ void JSObject::DeletePropertyInternal(JSThread *thread, const JSHandle if (obj->IsJSGlobalObject()) { JSHandle dictHandle(thread, obj->GetProperties()); - GlobalDictionary *dict = GlobalDictionary::Remove(thread, dictHandle, index); - obj->SetProperties(thread, JSTaggedValue(dict)); + GlobalDictionary *newDict = GlobalDictionary::Remove(thread, dictHandle, index); + obj->SetProperties(thread, JSTaggedValue(newDict)); return; } @@ -232,14 +234,14 @@ void JSObject::DeletePropertyInternal(JSThread *thread, const JSHandle JSHandle dictHandle(TransitionToDictionary(thread, obj)); int entry = dictHandle->FindEntry(key.GetTaggedValue()); ASSERT(entry != -1); - NameDictionary *dict = NameDictionary::Remove(thread, dictHandle, entry); - obj->SetProperties(thread, JSTaggedValue(dict)); + NameDictionary *newDict = NameDictionary::Remove(thread, dictHandle, entry); + obj->SetProperties(thread, JSTaggedValue(newDict)); return; } JSHandle dictHandle(array); - NameDictionary *dict = NameDictionary::Remove(thread, dictHandle, index); - obj->SetProperties(thread, JSTaggedValue(dict)); + NameDictionary *newDict = NameDictionary::Remove(thread, dictHandle, index); + obj->SetProperties(thread, JSTaggedValue(newDict)); } void JSObject::GetAllKeys(const JSThread *thread, const JSHandle &obj, int offset, diff --git a/ecmascript/js_promise.cpp b/ecmascript/js_promise.cpp index a8a3a1f..ef1ff24 100644 --- a/ecmascript/js_promise.cpp +++ b/ecmascript/js_promise.cpp @@ -178,7 +178,7 @@ JSTaggedValue JSPromise::TriggerPromiseReactions(JSThread *thread, const JSHandl JSHandle arguments = factory->NewTaggedArray(2); // 2 means the length of new array arguments->Set(thread, 0, reaction); arguments->Set(thread, 1, argument); - job->EnqueueJob(thread, job::QueueType::QUEUE_PROMISE, promiseReactionsJob, arguments); + job::MicroJobQueue::EnqueueJob(thread, job, job::QueueType::QUEUE_PROMISE, promiseReactionsJob, arguments); } // 2. Return undefined. return globalConst->GetUndefined(); diff --git a/ecmascript/js_set.cpp b/ecmascript/js_set.cpp index 58a4694..e83e11e 100644 --- a/ecmascript/js_set.cpp +++ b/ecmascript/js_set.cpp @@ -28,8 +28,8 @@ void JSSet::Add(JSThread *thread, const JSHandle &set, const JSHandle setHandle(thread, LinkedHashSet::Cast(set->GetLinkedSet().GetTaggedObject())); - auto table = LinkedHashSet::Add(thread, setHandle, value); - set->SetLinkedSet(thread, table); + JSTaggedValue newSet = LinkedHashSet::Add(thread, setHandle, value); + set->SetLinkedSet(thread, newSet); } bool JSSet::Delete(const JSThread *thread, const JSHandle &set, const JSHandle &value) @@ -40,8 +40,8 @@ bool JSSet::Delete(const JSThread *thread, const JSHandle &set, const JSH return false; } setHandle->RemoveEntry(thread, entry); - auto table = LinkedHashSet::Shrink(thread, setHandle); - set->SetLinkedSet(thread, table); + JSTaggedValue newSet = LinkedHashSet::Shrink(thread, setHandle); + set->SetLinkedSet(thread, newSet); return true; } diff --git a/ecmascript/js_weak_container.cpp b/ecmascript/js_weak_container.cpp index 7a4a132..0616ee7 100644 --- a/ecmascript/js_weak_container.cpp +++ b/ecmascript/js_weak_container.cpp @@ -30,8 +30,8 @@ void JSWeakMap::Set(JSThread *thread, const JSHandle &map, const JSHa } JSHandle mapHandle(thread, LinkedHashMap::Cast(map->GetLinkedMap().GetTaggedObject())); - auto result = LinkedHashMap::SetWeakRef(thread, mapHandle, key, value); - map->SetLinkedMap(thread, result); + JSTaggedValue newMap = LinkedHashMap::SetWeakRef(thread, mapHandle, key, value); + map->SetLinkedMap(thread, newMap); } bool JSWeakMap::Delete(JSThread *thread, const JSHandle &map, const JSHandle &key) @@ -43,8 +43,8 @@ bool JSWeakMap::Delete(JSThread *thread, const JSHandle &map, const J } mapHandle->RemoveEntry(thread, entry); - auto result = LinkedHashMap::Shrink(thread, mapHandle); - map->SetLinkedMap(thread, result); + JSTaggedValue newMap = LinkedHashMap::Shrink(thread, mapHandle); + map->SetLinkedMap(thread, newMap); return true; } @@ -70,8 +70,8 @@ void JSWeakSet::Add(JSThread *thread, const JSHandle &weakSet, const } JSHandle weakSetHandle(thread, LinkedHashSet::Cast(weakSet->GetLinkedSet().GetTaggedObject())); - auto result = LinkedHashSet::AddWeakRef(thread, weakSetHandle, value); - weakSet->SetLinkedSet(thread, result); + JSTaggedValue newSet = LinkedHashSet::AddWeakRef(thread, weakSetHandle, value); + weakSet->SetLinkedSet(thread, newSet); } bool JSWeakSet::Delete(JSThread *thread, const JSHandle &weakSet, const JSHandle &value) @@ -82,8 +82,8 @@ bool JSWeakSet::Delete(JSThread *thread, const JSHandle &weakSet, con return false; } weakSetHandle->RemoveEntry(thread, entry); - auto result = LinkedHashSet::Shrink(thread, weakSetHandle); - weakSet->SetLinkedSet(thread, result); + JSTaggedValue newSet = LinkedHashSet::Shrink(thread, weakSetHandle); + weakSet->SetLinkedSet(thread, newSet); return true; } diff --git a/ecmascript/object_operator.cpp b/ecmascript/object_operator.cpp index a2ca2eb..9f71941 100644 --- a/ecmascript/object_operator.cpp +++ b/ecmascript/object_operator.cpp @@ -568,8 +568,8 @@ void ObjectOperator::DeleteElementInHolder() const JSObject::ElementsToDictionary(thread_, JSHandle(holder_)); } else { JSHandle dictHandle(thread_, elements); - NumberDictionary *dict = NumberDictionary::Remove(thread_, dictHandle, GetIndex()); - obj->SetElements(thread_, JSTaggedValue(dict)); + NumberDictionary *newDict = NumberDictionary::Remove(thread_, dictHandle, GetIndex()); + obj->SetElements(thread_, JSTaggedValue(newDict)); } } @@ -661,9 +661,9 @@ void ObjectOperator::AddPropertyInternal(const JSHandle &value) PropertyBoxType cellType = value->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT; attr.SetBoxType(cellType); - JSTaggedValue properties( - GlobalDictionary::PutIfAbsent(thread_, dict, key_, JSHandle(cellHandle), attr)); - obj->SetProperties(thread_, properties); + GlobalDictionary *properties = + GlobalDictionary::PutIfAbsent(thread_, dict, key_, JSHandle(cellHandle), attr); + obj->SetProperties(thread_, JSTaggedValue(properties)); // index and fastMode is not essential for global obj; SetFound(0, cellHandle.GetTaggedValue(), attr.GetValue(), true); return; @@ -704,8 +704,8 @@ void ObjectOperator::AddPropertyInternal(const JSHandle &value) // change to dictionary and add one. JSHandle dict(JSObject::TransitionToDictionary(thread_, obj)); attr.SetDictionaryOrder(PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES); - auto result = JSTaggedValue(NameDictionary::PutIfAbsent(thread_, dict, key_, value, attr)); - obj->SetProperties(thread_, result); + NameDictionary *newDict = NameDictionary::PutIfAbsent(thread_, dict, key_, value, attr); + obj->SetProperties(thread_, JSTaggedValue(newDict)); // index is not essential when fastMode is false; SetFound(0, value.GetTaggedValue(), attr.GetValue(), false); return; @@ -724,8 +724,8 @@ void ObjectOperator::AddPropertyInternal(const JSHandle &value) } JSHandle dictHandle(array); - auto result = JSTaggedValue(NameDictionary::PutIfAbsent(thread_, dictHandle, key_, value, attr)); - obj->SetProperties(thread_, result); + NameDictionary *newDict = NameDictionary::PutIfAbsent(thread_, dictHandle, key_, value, attr); + obj->SetProperties(thread_, JSTaggedValue(newDict)); SetFound(0, value.GetTaggedValue(), attr.GetValue(), false); } diff --git a/ecmascript/tests/name_dictionary_test.cpp b/ecmascript/tests/name_dictionary_test.cpp index cd8dbe8..24b29ce 100644 --- a/ecmascript/tests/name_dictionary_test.cpp +++ b/ecmascript/tests/name_dictionary_test.cpp @@ -78,7 +78,7 @@ HWTEST_F_L0(NameDictionaryTest, addKeyAndValue) int numOfElement = 64; JSHandle dictJShandle(thread, NameDictionary::Create(thread, numOfElement)); EXPECT_TRUE(*dictJShandle != nullptr); - JSHandle dictHandle(dictJShandle); + JSMutableHandle dictHandle(dictJShandle); JSHandle objFun = GetGlobalEnv(thread)->GetObjectFunction(); // create key and values @@ -103,7 +103,8 @@ HWTEST_F_L0(NameDictionaryTest, addKeyAndValue) PropertyAttributes metaData2; // test insert() - JSHandle dict(thread, NameDictionary::PutIfAbsent(thread, dictHandle, key1, value1, metaData1)); + NameDictionary *dict = NameDictionary::PutIfAbsent(thread, dictHandle, key1, value1, metaData1); + dictHandle.Update(JSTaggedValue(dict)); EXPECT_EQ(dict->EntriesCount(), 1); // test find() and lookup() @@ -111,10 +112,10 @@ HWTEST_F_L0(NameDictionaryTest, addKeyAndValue) EXPECT_EQ(key1.GetTaggedValue(), JSTaggedValue(dict->GetKey(entry1).GetRawData())); EXPECT_EQ(value1.GetTaggedValue(), JSTaggedValue(dict->GetValue(entry1).GetRawData())); - JSHandle dict2(thread, dict->PutIfAbsent(thread, dictHandle, key2, value2, metaData2)); + JSHandle dict2(thread, NameDictionary::PutIfAbsent(thread, dictHandle, key2, value2, metaData2)); EXPECT_EQ(dict2->EntriesCount(), 2); // test remove() - dict->Remove(thread, dictHandle, entry1); + dict = NameDictionary::Remove(thread, dictHandle, entry1); EXPECT_EQ(-1, dict->FindEntry(key1.GetTaggedValue())); EXPECT_EQ(dict->EntriesCount(), 1); } @@ -172,7 +173,8 @@ HWTEST_F_L0(NameDictionaryTest, ShrinkCapacity) PropertyAttributes metaData; // test insert() - dictHandle.Update(JSTaggedValue(NameDictionary::PutIfAbsent(thread, dictHandle, key, value, metaData))); + NameDictionary *newDict = NameDictionary::PutIfAbsent(thread, dictHandle, key, value, metaData); + dictHandle.Update(JSTaggedValue(newDict)); } keyArray[5] = '2'; @@ -183,7 +185,8 @@ HWTEST_F_L0(NameDictionaryTest, ShrinkCapacity) int entry = dictHandle->FindEntry(arrayHandle.GetTaggedValue()); EXPECT_NE(entry, -1); - dictHandle.Update(JSTaggedValue(NameDictionary::Remove(thread, dictHandle, entry))); + NameDictionary *newDict1 = NameDictionary::Remove(thread, dictHandle, entry); + dictHandle.Update(JSTaggedValue(newDict1)); EXPECT_EQ(dictHandle->EntriesCount(), 9); EXPECT_EQ(dictHandle->Size(), 16); } diff --git a/ecmascript/weak_vector-inl.h b/ecmascript/weak_vector-inl.h index 9f27e48..d17c66a 100644 --- a/ecmascript/weak_vector-inl.h +++ b/ecmascript/weak_vector-inl.h @@ -49,7 +49,7 @@ JSTaggedValue WeakVector::Get(array_size_t index) const void WeakVector::Set(const JSThread *thread, array_size_t index, JSTaggedValue value) { ASSERT(index < GetCapacity()); - return TaggedArray::Set(thread, VectorToArrayIndex(index), value); + TaggedArray::Set(thread, VectorToArrayIndex(index), value); } void WeakVector::SetEnd(const JSThread *thread, array_size_t end) -- Gitee From 0228910be4d10621048aa1298d33453bb6644f04 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Thu, 21 Oct 2021 14:13:03 +0800 Subject: [PATCH 047/115] bug fix machine code and runtime_trampolines Signed-off-by: surpassgoodchao --- ecmascript/compiler/llvm/llvm.patch | 237 +++++++++++++--------------- ecmascript/frames.h | 8 +- ecmascript/js_thread.cpp | 3 + ecmascript/js_thread.h | 9 ++ ecmascript/mem/heap_roots-inl.h | 3 + ecmascript/mem/machine_code.h | 11 +- ecmascript/object_factory.cpp | 2 +- ecmascript/runtime_trampolines.cpp | 43 ++--- ecmascript/runtime_trampolines.h | 24 ++- 9 files changed, 186 insertions(+), 154 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm.patch b/ecmascript/compiler/llvm/llvm.patch index 73d0ec3..c679f27 100644 --- a/ecmascript/compiler/llvm/llvm.patch +++ b/ecmascript/compiler/llvm/llvm.patch @@ -1,123 +1,114 @@ -diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt -index 0e85afa82c7..54a9152e44f 100644 ---- a/llvm/CMakeLists.txt -+++ b/llvm/CMakeLists.txt -@@ -505,8 +505,15 @@ option(LLVM_BUILD_RUNTIME - "Build the LLVM runtime libraries." ON) - option(LLVM_BUILD_EXAMPLES - "Build the LLVM example programs. If OFF, just generate build targets." OFF) -+option(BUILD_ARK_GC_SUPPORT -+ "ARK support GC. If ON, support GC." OFF) -+if(BUILD_ARK_GC_SUPPORT) -+ add_definitions(-DARK_GC_SUPPORT) -+endif(ARK_SUPPORT_GC) -+ - option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) - -+ - if(LLVM_BUILD_EXAMPLES) - add_definitions(-DBUILD_EXAMPLES) - endif(LLVM_BUILD_EXAMPLES) -diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp -index 1da20371caf..60d9af0d833 100644 ---- a/llvm/lib/Target/X86/X86FrameLowering.cpp -+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp -@@ -31,6 +31,7 @@ - #include "llvm/Support/Debug.h" - #include "llvm/Target/TargetOptions.h" - #include -+#include - - using namespace llvm; - -@@ -1168,6 +1169,28 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, - else - MFI.setOffsetAdjustment(-StackSize); - } -+#ifdef ARK_GC_SUPPORT -+ // push marker -+ if (MF.getFunction().hasFnAttribute("js-stub-call")) -+ { -+ int64_t marker = 0x0; -+ MF.getFunction() -+ .getFnAttribute("js-stub-call") -+ .getValueAsString() -+ .getAsInteger(10, marker);//marker 1 break frame -+ std::cout << __LINE__ << " marker:" << std::dec << marker << std::endl; -+ -+ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); -+ /*reserve thread.fp */ -+ if (marker == 1) { -+ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); -+ } -+ } -+#endif - - // For EH funclets, only allocate enough space for outgoing calls. Save the - // NumBytes value that we would've used for the parent frame. -@@ -1635,6 +1658,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, - uint64_t SEHStackAllocAmt = NumBytes; - - if (HasFP) { -+#ifdef ARK_GC_SUPPORT -+ if (MF.getFunction().hasFnAttribute("js-stub-call")) -+ { -+ int64_t marker = 0x0; -+ MF.getFunction() -+ .getFnAttribute("js-stub-call") -+ .getValueAsString() -+ .getAsInteger(10, marker);//marker 1 break frame -+ -+ // pop marker -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), -+ MachineFramePtr) -+ .setMIFlag(MachineInstr::FrameDestroy); -+ if (marker == 1) { -+ // pop thread.fp -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), -+ MachineFramePtr) -+ .setMIFlag(MachineInstr::FrameDestroy); -+ } -+ } -+#endif - // Pop EBP. - BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), - MachineFramePtr) -@@ -1993,8 +2037,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( - - if (hasFP(MF)) { - // emitPrologue always spills frame register the first thing. -+#ifdef ARK_GC_SUPPORT -+ if (MF.getFunction().hasFnAttribute("js-stub-call")) { -+ int64_t marker = 0x0; -+ MF.getFunction() -+ .getFnAttribute("js-stub-call") -+ .getValueAsString() -+ .getAsInteger(10, marker);//marker 1 break frame -+ if (marker == 1) { -+ SpillSlotOffset -= 3 * SlotSize; // add type and thread.fp -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ CalleeSavedFrameSize += 16; -+ } else { -+ SpillSlotOffset -= 2 * SlotSize; // add type -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ CalleeSavedFrameSize += 8; -+ } -+ } else { -+ SpillSlotOffset -= SlotSize; // add type and thread.fp -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ } -+#else - SpillSlotOffset -= SlotSize; - MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+#endif - - // Since emitPrologue and emitEpilogue will handle spilling and restoring of - // the frame register, we can delete it from CSI list and not have to worry +diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt +index 0e85afa82c7..43756892e40 100644 +--- a/llvm/CMakeLists.txt ++++ b/llvm/CMakeLists.txt +@@ -505,8 +505,15 @@ option(LLVM_BUILD_RUNTIME + "Build the LLVM runtime libraries." ON) + option(LLVM_BUILD_EXAMPLES + "Build the LLVM example programs. If OFF, just generate build targets." OFF) ++option(BUILD_ARK_GC_SUPPORT ++ "ARK support GC. If ON, support GC." OFF) ++if(BUILD_ARK_GC_SUPPORT) ++ add_definitions(-DARK_GC_SUPPORT) ++endif(BUILD_ARK_GC_SUPPORT) ++ + option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) + ++ + if(LLVM_BUILD_EXAMPLES) + add_definitions(-DBUILD_EXAMPLES) + endif(LLVM_BUILD_EXAMPLES) +diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp +index 1da20371caf..a00a28fa5e9 100644 +--- a/llvm/lib/Target/X86/X86FrameLowering.cpp ++++ b/llvm/lib/Target/X86/X86FrameLowering.cpp +@@ -1168,6 +1168,27 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, + else + MFI.setOffsetAdjustment(-StackSize); + } ++#ifdef ARK_GC_SUPPORT ++ // push marker ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ ++ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ /*reserve thread.fp */ ++ if (marker == 1) { ++ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ } ++ } ++#endif + + // For EH funclets, only allocate enough space for outgoing calls. Save the + // NumBytes value that we would've used for the parent frame. +@@ -1635,6 +1656,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, + uint64_t SEHStackAllocAmt = NumBytes; + + if (HasFP) { ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ ++ // pop marker ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ if (marker == 1) { ++ // pop thread.fp ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ } ++ } ++#endif + // Pop EBP. + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) +@@ -1993,8 +2035,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( + + if (hasFP(MF)) { + // emitPrologue always spills frame register the first thing. ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ if (marker == 1) { ++ SpillSlotOffset -= 3 * SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += 16; ++ } else { ++ SpillSlotOffset -= 2 * SlotSize; // add type ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += 8; ++ } ++ } else { ++ SpillSlotOffset -= SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ } ++#else + SpillSlotOffset -= SlotSize; + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++#endif + + // Since emitPrologue and emitEpilogue will handle spilling and restoring of + // the frame register, we can delete it from CSI list and not have to worry diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 822d8e5..ec9e50d 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -217,8 +217,12 @@ #ifdef PANDA_TARGET_AMD64 #define GET_CURRETN_FP(fp) asm("mov %%rbp, %0" : "=rm" (fp)) -#else -#define GET_CURRETN_FP(fp) +#define POINTER_CAST(fp, type) static_cast(static_cast(fp) +#define GET_PREV_FP(fp) reinterpret_cast(*(fp)) +#else +#define GET_CURRETN_FP(fp) +#define POINTER_CAST(fp, type) static_cast(static_cast(fp)) +#define GET_PREV_FP(fp) reinterpret_cast(*(POINTER_CAST(fp, uintptr_t *))) #endif namespace panda::ecmascript { diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index 0282716..d8fefaf 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -86,6 +86,9 @@ void JSThread::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) if (!exception_.IsHole()) { v0(Root::ROOT_VM, ObjectSlot(ToUintPtr(&exception_))); } + if (!stubCode_.IsHole()) { + v0(Root::ROOT_VM, ObjectSlot(ToUintPtr(&stubCode_))); + } // visit global Constant globalConst_.VisitRangeSlot(v1); // visit stack roots diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 9edc945..249835a 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -199,6 +199,14 @@ public: void IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor); + uintptr_t* GetRuntimeTrampolinesFP() const + { + return runtimeTrampolinesFP; + } + void SetRuntimeTrampolinesFP(uintptr_t* pc) + { + runtimeTrampolinesFP = pc; + } private: NO_COPY_SEMANTIC(JSThread); NO_MOVE_SEMANTIC(JSThread); @@ -233,6 +241,7 @@ private: bool stableArrayElementsGuardians_ {true}; GlobalEnvConstants globalConst_; // Place-Holder InternalCallParams *internalCallParams_ {nullptr}; + uintptr_t *runtimeTrampolinesFP = 0; friend class EcmaHandleScope; friend class GlobalHandleCollection; diff --git a/ecmascript/mem/heap_roots-inl.h b/ecmascript/mem/heap_roots-inl.h index e72b2de..eb32956 100644 --- a/ecmascript/mem/heap_roots-inl.h +++ b/ecmascript/mem/heap_roots-inl.h @@ -282,6 +282,9 @@ void HeapRootManager::MarkObjectBody(TaggedObject *object, JSHClass *klass, cons case JSType::JS_INTL_BOUND_FUNCTION: JSIntlBoundFunction::Cast(object)->VisitRangeSlot(visitor); break; + case JSType::MACHINE_CODE_OBJECT: + MachineCode::Cast(object)->VisitRangeSlot(visitor); + break; default: UNREACHABLE(); } diff --git a/ecmascript/mem/machine_code.h b/ecmascript/mem/machine_code.h index 0181d96..e6f6cf0 100644 --- a/ecmascript/mem/machine_code.h +++ b/ecmascript/mem/machine_code.h @@ -53,10 +53,19 @@ public: return; } } + void VisitRangeSlot(const EcmaObjectRangeVisitor &v) + { + // no need to visit + } + + void VisitObjects([[maybe_unused]] const EcmaObjectRangeVisitor &visitor) const + { + // no field in this object + } size_t GetMachineCodeObjectSize(void) { - return sizeof(MachineCode) + this->GetInstructionSizeInBytes().GetInt(); + return SIZE + this->GetInstructionSizeInBytes().GetInt(); } }; } // namespace ecmascript diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index a4bef66..669d0e9 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -2106,7 +2106,7 @@ uintptr_t ObjectFactory::NewSpaceBySnapShotAllocator(size_t size) JSHandle ObjectFactory::NewMachineCodeObject(size_t length, const uint8_t *data) { NewObjectHook(); - TaggedObject *obj = heapHelper_.AllocateMachineCodeSpaceObject(machineCodeClass_, length + sizeof(MachineCode)); + TaggedObject *obj = heapHelper_.AllocateMachineCodeSpaceObject(machineCodeClass_, length + MachineCode::SIZE); MachineCode *code = MachineCode::Cast(obj); code->SetInstructionSizeInBytes(thread_, JSTaggedValue(static_cast(length))); if (data != nullptr) { diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index 36457e0..1cc9792 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -28,10 +28,11 @@ namespace panda::ecmascript { bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argReceiver, uint32_t argIndex, uint64_t argValue, uint32_t argAttr) { - JSTaggedType *fp = nullptr; - GET_CURRETN_FP(fp); + uintptr_t *curFp = nullptr; auto thread = reinterpret_cast(argThread); - CallRuntimeTrampolinesScope scope(thread, fp); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiver(thread, reinterpret_cast(argReceiver)); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); @@ -42,11 +43,11 @@ bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argRece bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint64_t argReceiver, uint64_t argValue, bool argMayThrow) { - JSTaggedType *fp = nullptr; - GET_CURRETN_FP(fp); + uintptr_t *curFp = nullptr; auto thread = reinterpret_cast(argThread); - CallRuntimeTrampolinesScope scope(thread, fp); - [[maybe_unused]] EcmaHandleScope handleScope(thread); + GET_CURRETN_FP(curFp); + uintptr_t * prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); JSHandle receiver(thread, JSTaggedValue(reinterpret_cast(argReceiver))); JSHandle value(thread, JSTaggedValue(reinterpret_cast(argValue))); auto setter = AccessorData::Cast((reinterpret_cast(argSetter))); @@ -55,10 +56,11 @@ bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint void RuntimeTrampolines::ThrowTypeError(uint64_t argThread, int argMessageStringId) { - JSTaggedType *fp = nullptr; - GET_CURRETN_FP(fp); + uintptr_t *curFp = nullptr; auto thread = reinterpret_cast(argThread); - CallRuntimeTrampolinesScope scope(thread, fp); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); [[maybe_unused]] EcmaHandleScope handleScope(thread); std::string message = MessageString::GetMessageString(argMessageStringId); ObjectFactory *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); @@ -69,10 +71,11 @@ void RuntimeTrampolines::ThrowTypeError(uint64_t argThread, int argMessageString bool RuntimeTrampolines::JSProxySetProperty(uint64_t argThread, uint64_t argProxy, uint64_t argKey, uint64_t argValue, uint64_t argReceiver, bool argMayThrow) { - JSTaggedType *fp = nullptr; - GET_CURRETN_FP(fp); + uintptr_t *curFp = nullptr; auto thread = reinterpret_cast(argThread); - CallRuntimeTrampolinesScope scope(thread, fp); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle proxy(thread, JSTaggedValue(reinterpret_cast(argProxy))); JSHandle index(thread, JSTaggedValue(reinterpret_cast(argKey))); @@ -90,10 +93,11 @@ uint32_t RuntimeTrampolines::GetHash32(uint64_t key, uint64_t len) uint64_t RuntimeTrampolines::CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver) { - JSTaggedType *fp = nullptr; - GET_CURRETN_FP(fp); + uintptr_t *curFp = nullptr; auto thread = reinterpret_cast(argThread); - CallRuntimeTrampolinesScope scope(thread, fp); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); return JSObject::CallGetter(thread, accessor, objHandle).GetRawData(); @@ -101,10 +105,11 @@ uint64_t RuntimeTrampolines::CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t RuntimeTrampolines::AccessorGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver) { - JSTaggedType *fp = nullptr; - GET_CURRETN_FP(fp); + uintptr_t *curFp = nullptr; auto thread = reinterpret_cast(argThread); - CallRuntimeTrampolinesScope scope(thread, fp); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); return accessor->CallInternalGet(thread, objHandle).GetRawData(); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 62a20bb..08b564a 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -53,17 +53,22 @@ public: class CallRuntimeTrampolinesScope { public: - CallRuntimeTrampolinesScope(JSThread *thread, JSTaggedType *newFp) - :oldRbp_(const_cast(thread->GetCurrentSPFrame())), + CallRuntimeTrampolinesScope(JSThread *thread, uintptr_t *newFp, uintptr_t *fp) + :oldRbp_(nullptr), thread_(thread) { - thread_->SetCurrentSPFrame(newFp); + oldRuntimeTrampolinesFP_ = thread->GetRuntimeTrampolinesFP(); + thread->SetRuntimeTrampolinesFP(fp); + JSTaggedType *cursp = const_cast(thread->GetCurrentSPFrame()); + oldRbp_ = static_cast(static_cast(cursp)); + JSTaggedType *newSp = static_cast(static_cast(newFp)); + thread_->SetCurrentSPFrame(newSp); // print newfp and type for debug std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " oldRbp_ : " << oldRbp_ - << " thread_->fp:" << thread_->GetCurrentSPFrame() <( reinterpret_cast(newFp) + FrameConst::kFrameType)); - std::cout << "type = " << as_integer(type) << std::endl; + std::cout << __FUNCTION__ << " type = " << as_integer(type) << std::endl; } ~CallRuntimeTrampolinesScope() { @@ -72,12 +77,15 @@ public: " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; FrameType type = *(reinterpret_cast( reinterpret_cast(oldRbp_) + FrameConst::kFrameType)); - std::cout << "type = " << as_integer(type) << std::endl; - thread_->SetCurrentSPFrame(oldRbp_); + std::cout << __FUNCTION__ << "type = " << as_integer(type) << std::endl; + JSTaggedType *oldSp = static_cast(static_cast(oldRbp_)); + thread_->SetCurrentSPFrame(oldSp); + thread_->SetRuntimeTrampolinesFP(oldRuntimeTrampolinesFP_); } private: - JSTaggedType *oldRbp_; + uintptr_t *oldRbp_; JSThread *thread_; + uintptr_t *oldRuntimeTrampolinesFP_; }; } // namespace panda::ecmascript #endif \ No newline at end of file -- Gitee From 4b0288c21c13fdfe8d3a0626436e98e51ad4ad09 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Thu, 21 Oct 2021 15:18:24 +0800 Subject: [PATCH 048/115] delete incorrect threadid check Signed-off-by: wengchangcheng --- ecmascript/tooling/agent/js_pt_hooks.cpp | 16 ++-------------- ecmascript/tooling/interface/js_debugger.cpp | 7 +++---- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/ecmascript/tooling/agent/js_pt_hooks.cpp b/ecmascript/tooling/agent/js_pt_hooks.cpp index a801709..52ea080 100644 --- a/ecmascript/tooling/agent/js_pt_hooks.cpp +++ b/ecmascript/tooling/agent/js_pt_hooks.cpp @@ -19,10 +19,6 @@ namespace panda::tooling::ecmascript { void JSPtHooks::Breakpoint([[maybe_unused]] PtThread thread, const PtLocation &location) { - if (thread.GetId() != ManagedThread::NON_INITIALIZED_THREAD_ID) { - // Skip none-js thread - return; - } LOG(DEBUG, DEBUGGER) << "JSPtHooks: Breakpoint => " << location.GetMethodId() << ": " << location.GetBytecodeOffset(); @@ -38,13 +34,9 @@ void JSPtHooks::Paused(PauseReason reason) backend_->NotifyPaused({}, reason); } -void JSPtHooks::Exception(PtThread thread, [[maybe_unused]] const PtLocation &location, +void JSPtHooks::Exception([[maybe_unused]] PtThread thread, [[maybe_unused]] const PtLocation &location, [[maybe_unused]] PtObject exceptionObject, [[maybe_unused]] const PtLocation &catchLocation) { - if (thread.GetId() != ManagedThread::NON_INITIALIZED_THREAD_ID) { - // Skip none-js thread - return; - } LOG(DEBUG, DEBUGGER) << "JSPtHooks: Exception"; [[maybe_unused]] LocalScope scope(backend_->ecmaVm_); @@ -58,12 +50,8 @@ void JSPtHooks::Exception(PtThread thread, [[maybe_unused]] const PtLocation &lo } } -void JSPtHooks::SingleStep(PtThread thread, const PtLocation &location) +void JSPtHooks::SingleStep([[maybe_unused]] PtThread thread, const PtLocation &location) { - if (thread.GetId() != ManagedThread::NON_INITIALIZED_THREAD_ID) { - // Skip none-js thread - return; - } LOG(DEBUG, DEBUGGER) << "JSPtHooks: SingleStep => " << location.GetBytecodeOffset(); [[maybe_unused]] LocalScope scope(backend_->ecmaVm_); diff --git a/ecmascript/tooling/interface/js_debugger.cpp b/ecmascript/tooling/interface/js_debugger.cpp index 893707f..e3fecc1 100644 --- a/ecmascript/tooling/interface/js_debugger.cpp +++ b/ecmascript/tooling/interface/js_debugger.cpp @@ -73,8 +73,7 @@ void JSDebugger::BytecodePcChanged(ManagedThread *thread, Method *method, uint32 HandleBreakpoint(JSThread::Cast(thread), JSMethod::Cast(method), bcOffset); } -bool JSDebugger::HandleBreakpoint([[maybe_unused]] const JSThread *thread, const JSMethod *method, - uint32_t bcOffset) +bool JSDebugger::HandleBreakpoint(const JSThread *thread, const JSMethod *method, uint32_t bcOffset) { if (!FindBreakpoint(method, bcOffset)) { return false; @@ -83,7 +82,7 @@ bool JSDebugger::HandleBreakpoint([[maybe_unused]] const JSThread *thread, const auto *pf = method->GetPandaFile(); PtLocation location {pf->GetFilename().c_str(), method->GetFileId(), bcOffset}; if (hooks_ != nullptr) { - hooks_->Breakpoint(PtThread(ManagedThread::NON_INITIALIZED_THREAD_ID), location); + hooks_->Breakpoint(PtThread(thread->GetId()), location); } return true; @@ -99,7 +98,7 @@ void JSDebugger::HandleExceptionThrowEvent(const JSThread *thread, const JSMetho PtLocation throwLocation {pf->GetFilename().c_str(), method->GetFileId(), bcOffset}; if (hooks_ != nullptr) { - hooks_->Exception(PtThread(ManagedThread::NON_INITIALIZED_THREAD_ID), throwLocation, PtObject(), throwLocation); + hooks_->Exception(PtThread(thread->GetId()), throwLocation, PtObject(), throwLocation); } } -- Gitee From 0eaf069cf437e962bd2ad468151525f2075b9af7 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Thu, 21 Oct 2021 15:47:54 +0800 Subject: [PATCH 049/115] code review Signed-off-by: surpassgoodchao --- ecmascript/compiler/llvm/llvm.patch | 31 ++++++++++++++++++++--------- ecmascript/mem/machine_code.h | 4 ++-- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm.patch b/ecmascript/compiler/llvm/llvm.patch index c679f27..7c5e6c3 100644 --- a/ecmascript/compiler/llvm/llvm.patch +++ b/ecmascript/compiler/llvm/llvm.patch @@ -19,7 +19,7 @@ index 0e85afa82c7..43756892e40 100644 add_definitions(-DBUILD_EXAMPLES) endif(LLVM_BUILD_EXAMPLES) diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp -index 1da20371caf..a00a28fa5e9 100644 +index 1da20371caf..d6f82baa7d7 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -1168,6 +1168,27 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, @@ -36,14 +36,14 @@ index 1da20371caf..a00a28fa5e9 100644 + .getValueAsString() + .getAsInteger(10, marker);//marker 1 break frame + -+ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); + /*reserve thread.fp */ -+ if (marker == 1) { -+ BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64i32)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); ++ if (marker == JS_ENTRY_FRAME_MARK) { ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); + } + } +#endif @@ -67,7 +67,7 @@ index 1da20371caf..a00a28fa5e9 100644 + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) + .setMIFlag(MachineInstr::FrameDestroy); -+ if (marker == 1) { ++ if (marker == JS_ENTRY_FRAME_MARK) { + // pop thread.fp + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) @@ -112,3 +112,16 @@ index 1da20371caf..a00a28fa5e9 100644 // Since emitPrologue and emitEpilogue will handle spilling and restoring of // the frame register, we can delete it from CSI list and not have to worry +diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h +index 2103d6471ea..3fd89b0d9ee 100644 +--- a/llvm/lib/Target/X86/X86FrameLowering.h ++++ b/llvm/lib/Target/X86/X86FrameLowering.h +@@ -15,6 +15,8 @@ + + #include "llvm/CodeGen/TargetFrameLowering.h" + ++#define JS_ENTRY_FRAME_MARK 1 ++ + namespace llvm { + + class MachineInstrBuilder; diff --git a/ecmascript/mem/machine_code.h b/ecmascript/mem/machine_code.h index e6f6cf0..d34ad88 100644 --- a/ecmascript/mem/machine_code.h +++ b/ecmascript/mem/machine_code.h @@ -55,12 +55,12 @@ public: } void VisitRangeSlot(const EcmaObjectRangeVisitor &v) { - // no need to visit + // left blank deliberately,only need to visit TaggedObject type object. } void VisitObjects([[maybe_unused]] const EcmaObjectRangeVisitor &visitor) const { - // no field in this object + // left blank deliberately,only need to visit TaggedObject type object. } size_t GetMachineCodeObjectSize(void) -- Gitee From 16a03305e33eabaeac29c4bf64a6101f06f5fea2 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Thu, 21 Oct 2021 16:04:00 +0800 Subject: [PATCH 050/115] code review Signed-off-by: surpassgoodchao --- ecmascript/frames.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecmascript/frames.h b/ecmascript/frames.h index ec9e50d..08261a5 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -219,7 +219,7 @@ #define GET_CURRETN_FP(fp) asm("mov %%rbp, %0" : "=rm" (fp)) #define POINTER_CAST(fp, type) static_cast(static_cast(fp) #define GET_PREV_FP(fp) reinterpret_cast(*(fp)) -#else +#else #define GET_CURRETN_FP(fp) #define POINTER_CAST(fp, type) static_cast(static_cast(fp)) #define GET_PREV_FP(fp) reinterpret_cast(*(POINTER_CAST(fp, uintptr_t *))) -- Gitee From 1ec42f43ac6cfb3aef2bf8f182c49545ba7025f1 Mon Sep 17 00:00:00 2001 From: xiongluo Date: Sun, 17 Oct 2021 20:11:40 -1000 Subject: [PATCH 051/115] heapdump Signed-off-by: xiongluo --- ecmascript/class_linker/program_object.h | 3 +- ecmascript/dump.cpp | 969 +++++++++++++++++-- ecmascript/ecma_macros.h | 9 +- ecmascript/ecma_module.h | 1 + ecmascript/hprof/heap_profiler.cpp | 16 +- ecmascript/hprof/heap_profiler.h | 6 +- ecmascript/hprof/heap_profiler_interface.cpp | 4 +- ecmascript/hprof/heap_profiler_interface.h | 5 +- ecmascript/hprof/heap_snapshot.cpp | 407 ++++---- ecmascript/hprof/heap_snapshot.h | 10 +- ecmascript/hprof/tests/hprof_test.cpp | 554 +++++++++++ ecmascript/ic/ic_handler.h | 2 + ecmascript/ic/property_box.h | 1 + ecmascript/ic/proto_change_details.h | 2 + ecmascript/js_collator.h | 1 + ecmascript/js_date_time_format.h | 1 + ecmascript/js_for_in_iterator.h | 1 + ecmascript/js_function.h | 1 + ecmascript/js_function_extra_info.h | 1 + ecmascript/js_generator_object.h | 3 + ecmascript/js_intl.h | 1 + ecmascript/js_locale.h | 1 + ecmascript/js_number_format.h | 1 + ecmascript/js_object.h | 2 +- ecmascript/js_plural_rules.h | 1 + ecmascript/js_realm.h | 3 + ecmascript/js_relative_time_format.h | 1 + ecmascript/js_string_iterator.h | 1 + ecmascript/js_tagged_value.h | 3 +- ecmascript/mem/heap_roots-inl.h | 19 +- ecmascript/mem/machine_code.h | 2 + ecmascript/object_factory.h | 11 +- 32 files changed, 1758 insertions(+), 285 deletions(-) diff --git a/ecmascript/class_linker/program_object.h b/ecmascript/class_linker/program_object.h index 6f27229..df56dea 100644 --- a/ecmascript/class_linker/program_object.h +++ b/ecmascript/class_linker/program_object.h @@ -37,8 +37,8 @@ public: inline void FreeMethodData(RegionFactory *factory); - DECL_DUMP() DECL_VISIT_OBJECT(LOCATION_OFFSET, METHODS_DATA_OFFSET) + DECL_DUMP() }; class LexicalFunction : public ECMAObject { @@ -65,6 +65,7 @@ public: ACCESSORS(Program, PROGRAM_OFFSET, SIZE) DECL_VISIT_OBJECT(NAME_OFFSET, SIZE) + DECL_DUMP() }; class ConstantPool : public TaggedArray { diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index f5adfe9..77df22a 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -20,27 +20,44 @@ #include "ecmascript/accessor_data.h" #include "ecmascript/class_linker/program_object-inl.h" +#include "ecmascript/ecma_module.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/global_dictionary-inl.h" #include "ecmascript/global_env.h" +#include "ecmascript/ic/ic_handler.h" +#include "ecmascript/ic/proto_change_details.h" +#include "ecmascript/ic/property_box.h" #include "ecmascript/jobs/micro_job_queue.h" #include "ecmascript/jobs/pending_job.h" #include "ecmascript/js_array.h" #include "ecmascript/js_array_iterator.h" #include "ecmascript/js_arraybuffer.h" #include "ecmascript/js_async_function.h" +#include "ecmascript/js_collator.h" #include "ecmascript/js_dataview.h" #include "ecmascript/js_date.h" +#include "ecmascript/js_date_time_format.h" +#include "ecmascript/js_for_in_iterator.h" #include "ecmascript/js_function.h" +#include "ecmascript/js_function_extra_info.h" +#include "ecmascript/js_generator_object.h" +#include "ecmascript/js_global_object.h" #include "ecmascript/js_handle.h" +#include "ecmascript/js_intl.h" +#include "ecmascript/js_locale.h" #include "ecmascript/js_map.h" #include "ecmascript/js_map_iterator.h" +#include "ecmascript/js_number_format.h" #include "ecmascript/js_object-inl.h" +#include "ecmascript/js_plural_rules.h" #include "ecmascript/js_primitive_ref.h" #include "ecmascript/js_promise.h" +#include "ecmascript/js_realm.h" #include "ecmascript/js_regexp.h" +#include "ecmascript/js_relative_time_format.h" #include "ecmascript/js_set.h" #include "ecmascript/js_set_iterator.h" +#include "ecmascript/js_string_iterator.h" #include "ecmascript/js_tagged_number.h" #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/js_thread.h" @@ -51,8 +68,10 @@ #include "ecmascript/linked_hash_table-inl.h" #include "ecmascript/mem/assert_scope-inl.h" #include "ecmascript/mem/c_containers.h" +#include "ecmascript/mem/machine_code.h" #include "ecmascript/tagged_array.h" #include "ecmascript/tagged_dictionary.h" +#include "ecmascript/template_map.h" #include "ecmascript/transitions_dictionary.h" namespace panda::ecmascript { @@ -73,6 +92,8 @@ CString JSHClass::DumpJSType(JSType type) return "TaggedDictionary"; case JSType::STRING: return "BaseString"; + case JSType::JS_NATIVE_POINTER: + return "NativePointer"; case JSType::JS_OBJECT: return "Object"; case JSType::JS_FUNCTION_BASE: @@ -193,6 +214,42 @@ CString JSHClass::DumpJSType(JSType type) return "AsyncAwaitStatusFunction"; case JSType::JS_ASYNC_FUNC_OBJECT: return "AsyncFunctionObject"; + case JSType::JS_REALM: + return "Realm"; + case JSType::JS_GLOBAL_OBJECT: + return "GlobalObject"; + case JSType::JS_INTL: + return "JSIntl"; + case JSType::JS_LOCALE: + return "JSLocale"; + case JSType::JS_DATE_TIME_FORMAT: + return "JSDateTimeFormat"; + case JSType::JS_RELATIVE_TIME_FORMAT: + return "JSRelativeTimeFormat"; + case JSType::JS_NUMBER_FORMAT: + return "JSNumberFormat"; + case JSType::JS_COLLATOR: + return "JSCollator"; + case JSType::JS_PLURAL_RULES: + return "JSPluralRules"; + case JSType::JS_GENERATOR_OBJECT: + return "JSGeneratorObject"; + case JSType::JS_GENERATOR_CONTEXT: + return "JSGeneratorContext"; + case JSType::PROTO_CHANGE_MARKER: + return "ProtoChangeMarker"; + case JSType::PROTOTYPE_INFO: + return "PrototypeInfo"; + case JSType::PROGRAM: + return "program"; + case JSType::LEXICAL_FUNCTION: + return "LexicalFunction"; + case JSType::FUNCTION_EXTRA_INFO: + return "FunctionExtraInfo"; + case JSType::MACHINE_CODE_OBJECT: + return "MachineCode"; + case JSType::ECMA_MODULE: + return "EcmaModule"; default: { CString ret = "unknown type "; return ret + static_cast(type); @@ -321,12 +378,15 @@ static void DumpObject(JSThread *thread, TaggedObject *obj, std::ostream &os) return DumpDynClass(thread, obj, os); case JSType::TAGGED_ARRAY: case JSType::TAGGED_DICTIONARY: + case JSType::TEMPLATE_MAP: DumpArrayClass(thread, TaggedArray::Cast(obj), os); break; case JSType::STRING: DumpStringClass(EcmaString::Cast(obj), os); os << "\n"; break; + case JSType::JS_NATIVE_POINTER: + break; case JSType::JS_OBJECT: case JSType::JS_GLOBAL_OBJECT: case JSType::JS_ERROR: @@ -447,13 +507,88 @@ static void DumpObject(JSThread *thread, TaggedObject *obj, std::ostream &os) case JSType::JS_GENERATOR_FUNCTION: JSGeneratorFunction::Cast(obj)->Dump(thread, os); break; + case JSType::JS_INTL_BOUND_FUNCTION: + JSIntlBoundFunction::Cast(obj)->Dump(thread, os); + break; case JSType::JS_ITERATOR: + break; case JSType::JS_FORIN_ITERATOR: + JSForInIterator::Cast(obj)->Dump(thread, os); + break; case JSType::JS_MAP_ITERATOR: + JSMapIterator::Cast(obj)->Dump(thread, os); + break; case JSType::JS_SET_ITERATOR: + JSSetIterator::Cast(obj)->Dump(thread, os); + break; case JSType::JS_ARRAY_ITERATOR: + JSArrayIterator::Cast(obj)->Dump(thread, os); + break; case JSType::JS_STRING_ITERATOR: + JSStringIterator::Cast(obj)->Dump(thread, os); + break; + case JSType::PROTOTYPE_HANDLER: + PrototypeHandler::Cast(obj)->Dump(thread, os); + break; + case JSType::TRANSITION_HANDLER: + TransitionHandler::Cast(obj)->Dump(thread, os); + break; case JSType::PROPERTY_BOX: + PropertyBox::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_REALM: + JSRealm::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_INTL: + JSIntl::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_LOCALE: + JSLocale::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_DATE_TIME_FORMAT: + JSDateTimeFormat::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_RELATIVE_TIME_FORMAT: + JSRelativeTimeFormat::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_NUMBER_FORMAT: + JSNumberFormat::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_COLLATOR: + JSCollator::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_PLURAL_RULES: + JSPluralRules::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_GENERATOR_OBJECT: + JSGeneratorObject::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_ASYNC_FUNC_OBJECT: + JSAsyncFuncObject::Cast(obj)->Dump(thread, os); + break; + case JSType::JS_GENERATOR_CONTEXT: + GeneratorContext::Cast(obj)->Dump(thread, os); + break; + case JSType::PROTOTYPE_INFO: + ProtoChangeDetails::Cast(obj)->Dump(thread, os); + break; + case JSType::PROTO_CHANGE_MARKER: + ProtoChangeMarker::Cast(obj)->Dump(thread, os); + break; + case JSType::PROGRAM: + Program::Cast(obj)->Dump(thread, os); + break; + case JSType::LEXICAL_FUNCTION: + LexicalFunction::Cast(obj)->Dump(thread, os); + break; + case JSType::FUNCTION_EXTRA_INFO: + JSFunctionExtraInfo::Cast(obj)->Dump(thread, os); + break; + case JSType::MACHINE_CODE_OBJECT: + MachineCode::Cast(obj)->Dump(thread, os); + break; + case JSType::ECMA_MODULE: + EcmaModule::Cast(obj)->Dump(thread, os); break; default: UNREACHABLE(); @@ -762,16 +897,16 @@ void AccessorData::Dump(JSThread *thread, std::ostream &os) const void Program::Dump(JSThread *thread, std::ostream &os) const { os << " - Location: "; - GetLocation().DumpTaggedValue(thread, os); + GetLocation().Dump(thread); os << "\n"; os << " - ConstantPool: "; - TaggedArray *arr = TaggedArray::Cast(GetConstantPool().GetTaggedObject()); - DumpArrayClass(thread, arr, os); + GetConstantPool().Dump(thread); os << "\n"; - os << " - MainFunction: "; - GetMainFunction().DumpTaggedValue(thread, os); + GetMainFunction().Dump(thread); os << "\n"; + os << " - MethodsData: " << GetMethodsData() << "\n"; + os << " - NumberMethods: " << GetNumberMethods() << "\n"; } void ConstantPool::Dump(JSThread *thread, std::ostream &os) const @@ -781,6 +916,27 @@ void ConstantPool::Dump(JSThread *thread, std::ostream &os) const void JSFunction::Dump(JSThread *thread, std::ostream &os) const { + os << " - ProtoOrDynClass: "; + GetProtoOrDynClass().Dump(thread); + os << "\n"; + os << " - LexicalEnv: "; + GetLexicalEnv().Dump(thread); + os << "\n"; + os << " - HomeObject: "; + GetHomeObject().Dump(thread); + os << "\n"; + os << " - FunctionInfoFlag: "; + GetFunctionInfoFlag().Dump(thread); + os << "\n"; + os << " - FunctionExtraInfo: "; + GetFunctionExtraInfo().Dump(thread); + os << "\n"; + os << " - ConstantPool: "; + GetConstantPool().Dump(thread); + os << "\n"; + os << " - ProfileTypeInfo: "; + GetProfileTypeInfo().Dump(thread); + os << "\n"; JSObject::Dump(thread, os); } @@ -833,6 +989,23 @@ void JSMap::Dump(JSThread *thread, std::ostream &os) const map->Dump(thread, os); } +void JSForInIterator::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - Object : "; + GetObject().DumpTaggedValue(thread, os); + os << "\n"; + os << " - WasVisited : "; + GetWasVisited().DumpTaggedValue(thread, os); + os << "\n"; + os << " - VisitedKeys : "; + GetVisitedKeys().DumpTaggedValue(thread, os); + os << "\n"; + os << " - RemainingKeys : "; + GetRemainingKeys().DumpTaggedValue(thread, os); + os << "\n"; + JSObject::Dump(thread, os); +} + void JSMapIterator::Dump(JSThread *thread, std::ostream &os) const { LinkedHashMap *map = LinkedHashMap::Cast(GetIteratedMap().GetTaggedObject()); @@ -914,6 +1087,13 @@ void JSArrayIterator::Dump(JSThread *thread, std::ostream &os) const JSObject::Dump(thread, os); } +void JSStringIterator::Dump(JSThread *thread, std::ostream &os) const +{ + EcmaString *str = EcmaString::Cast(GetIteratedString().GetTaggedObject()); + os << " - IteratedString: " << str->GetCString().get() << "\n"; + os << " - StringIteratorNextIndex: " << std::dec << GetStringIteratorNextIndex().GetInt() << "\n"; + JSObject::Dump(thread, os); +} void JSTypedArray::Dump(JSThread *thread, std::ostream &os) const { os << " - viewed-array-buffer: "; @@ -931,11 +1111,20 @@ void JSTypedArray::Dump(JSThread *thread, std::ostream &os) const void JSRegExp::Dump(JSThread *thread, std::ostream &os) const { - os << " - source: "; - DumpStringClass(EcmaString::Cast(GetOriginalSource().GetTaggedObject()), os); + os << " - LastIndex: "; + GetLastIndex().Dump(thread); os << "\n"; - os << " - flags: "; - os << GetOriginalFlags().GetInt(); + os << " - ByteCodeBuffer: "; + GetByteCodeBuffer().Dump(thread); + os << "\n"; + os << " - OriginalSource: "; + GetOriginalSource().Dump(thread); + os << "\n"; + os << " - OriginalFlags: "; + GetOriginalFlags().Dump(thread); + os << "\n"; + os << " - Length: "; + GetLength().Dump(thread); os << "\n"; JSObject::Dump(thread, os); } @@ -1197,6 +1386,8 @@ void JSArrayBuffer::Dump(JSThread *thread, std::ostream &os) const GetArrayBufferByteLength().Dump(thread); os << " - buffer-data: "; GetArrayBufferData().Dump(thread); + os << " - Shared: "; + GetShared().Dump(thread); } void PromiseReaction::Dump(JSThread *thread, std::ostream &os) const @@ -1315,7 +1506,7 @@ void JSProxyRevocFunction::Dump(JSThread *thread, std::ostream &os) const { os << " - RevocableProxy: "; os << "\n"; - JSObject::Cast(GetRevocableProxy().GetTaggedObject())->Dump(thread, os); + GetRevocableProxy().Dump(thread); os << "\n"; } @@ -1328,7 +1519,7 @@ void JSAsyncAwaitStatusFunction::Dump(JSThread *thread, std::ostream &os) const { os << " - AsyncContext: "; os << "\n"; - JSObject::Cast(GetAsyncContext().GetTaggedObject())->Dump(thread, os); + GetAsyncContext().Dump(thread); os << "\n"; } @@ -1337,6 +1528,364 @@ void JSGeneratorFunction::Dump(JSThread *thread, std::ostream &os) const JSFunction::Dump(thread, os); } +void JSIntlBoundFunction::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - NumberFormat: "; + GetNumberFormat().Dump(thread); + os << "\n"; + os << " - DateTimeFormat: "; + GetDateTimeFormat().Dump(thread); + os << "\n"; + os << " - Collator: "; + GetCollator().Dump(thread); + os << "\n"; + JSObject::Dump(thread, os); +} + +void PropertyBox::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - Value: "; + GetValue().Dump(thread); + os << "\n"; +} + +void PrototypeHandler::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - HandlerInfo: "; + GetHandlerInfo().Dump(thread); + os << "\n"; + os << " - ProtoCell: "; + GetHandlerInfo().Dump(thread); + os << "\n"; + os << " - Holder: "; + GetHandlerInfo().Dump(thread); + os << "\n"; +} + +void TransitionHandler::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - HandlerInfo: "; + GetHandlerInfo().Dump(thread); + os << "\n"; + os << " - TransitionHClass: "; + GetTransitionHClass().Dump(thread); + os << "\n"; +} + +void JSRealm::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - Value: "; + GetValue().Dump(thread); + os << "\n"; + os << " - GlobalEnv: "; + GetGlobalEnv().Dump(thread); + os << "\n"; + JSObject::Dump(thread, os); +} + +void JSIntl::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - FallbackSymbol: "; + GetFallbackSymbol().Dump(thread); + os << "\n"; + JSObject::Dump(thread, os); +} + +void JSLocale::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - IcuField: "; + GetIcuField().Dump(thread); + os << "\n"; + JSObject::Dump(thread, os); +} + +void JSDateTimeFormat::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - Locale: "; + GetLocale().Dump(thread); + os << "\n"; + os << " - Calendar: "; + GetCalendar().Dump(thread); + os << "\n"; + os << " - NumberingSystem: "; + GetNumberingSystem().Dump(thread); + os << "\n"; + os << " - TimeZone: "; + GetTimeZone().Dump(thread); + os << "\n"; + os << " - HourCycle: "; + GetHourCycle().Dump(thread); + os << "\n"; + os << " - LocaleIcu: "; + GetLocaleIcu().Dump(thread); + os << "\n"; + os << " - SimpleDateTimeFormatIcu: "; + GetSimpleDateTimeFormatIcu().Dump(thread); + os << "\n"; + os << " - Iso8601: "; + GetIso8601().Dump(thread); + os << "\n"; + os << " - DateStyle: "; + GetDateStyle().Dump(thread); + os << "\n"; + os << " - TimeStyle: "; + GetTimeStyle().Dump(thread); + os << "\n"; + os << " - BoundFormat: "; + GetBoundFormat().Dump(thread); + os << "\n"; + JSObject::Dump(thread, os); +} + +void JSRelativeTimeFormat::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - Locale: "; + GetLocale().Dump(thread); + os << "\n"; + os << " - InitializedRelativeTimeFormat: "; + GetInitializedRelativeTimeFormat().Dump(thread); + os << "\n"; + os << " - NumberingSystem: "; + GetNumberingSystem().Dump(thread); + os << "\n"; + os << " - Style: "; + GetStyle().Dump(thread); + os << "\n"; + os << " - Numeric: "; + GetNumeric().Dump(thread); + os << "\n"; + os << " - AvailableLocales: "; + GetAvailableLocales().Dump(thread); + os << "\n"; + os << " - IcuField: "; + GetIcuField().Dump(thread); + os << "\n"; + JSObject::Dump(thread, os); +} + +void JSNumberFormat::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - Locale: "; + GetLocale().Dump(thread); + os << "\n" << " - NumberingSystem: "; + GetNumberingSystem().Dump(thread); + os << "\n" << " - Style: "; + GetStyle().Dump(thread); + os << "\n" << " - Currency: "; + GetCurrency().Dump(thread); + os << "\n" << " - CurrencyDisplay: "; + GetCurrencyDisplay().Dump(thread); + os << "\n" << " - CurrencySign: "; + GetCurrencySign().Dump(thread); + os << "\n" << " - Unit: "; + GetUnit().Dump(thread); + os << "\n" << " - UnitDisplay: "; + GetUnitDisplay().Dump(thread); + os << "\n" << " - MinimumIntegerDigits: "; + GetMinimumIntegerDigits().Dump(thread); + os << "\n" << " - MinimumFractionDigits: "; + GetMinimumFractionDigits().Dump(thread); + os << "\n" << " - MaximumFractionDigits: "; + GetMaximumFractionDigits().Dump(thread); + os << "\n" << " - MinimumSignificantDigits: "; + GetMinimumSignificantDigits().Dump(thread); + os << "\n" << " - MaximumSignificantDigits: "; + GetMaximumSignificantDigits().Dump(thread); + os << "\n" << " - UseGrouping: "; + GetUseGrouping().Dump(thread); + os << "\n" << " - RoundingType: "; + GetUseGrouping().Dump(thread); + os << "\n" << " - Notation: "; + GetMinimumIntegerDigits().Dump(thread); + os << "\n" << " - CompactDisplay: "; + GetMaximumSignificantDigits().Dump(thread); + os << "\n" << " - SignDisplay: "; + GetMinimumFractionDigits().Dump(thread); + os << "\n" << " - BoundFormat: "; + GetMaximumFractionDigits().Dump(thread); + os << "\n" << " - IcuField: "; + GetMinimumSignificantDigits().Dump(thread); + os << "\n"; + JSObject::Dump(thread, os); +} + +void JSCollator::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - IcuField: "; + GetIcuField().Dump(thread); + os << "\n"; + os << " - Locale: "; + GetLocale().Dump(thread); + os << "\n"; + os << " - Usage: "; + GetUsage().Dump(thread); + os << "\n"; + os << " - Sensitivity: "; + GetSensitivity().Dump(thread); + os << "\n"; + os << " - IgnorePunctuation: "; + GetIgnorePunctuation().Dump(thread); + os << "\n"; + os << " - Collation: "; + GetCollation().Dump(thread); + os << "\n"; + os << " - Numeric: "; + GetNumeric().Dump(thread); + os << "\n"; + os << " - CaseFirst: "; + GetCaseFirst().Dump(thread); + os << "\n"; + os << " - BoundCompare: "; + GetBoundCompare().Dump(thread); + os << "\n"; + JSObject::Dump(thread, os); +} + +void JSPluralRules::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - Locale: "; + GetLocale().Dump(thread); + os << "\n"; + os << " - InitializedPluralRules: "; + GetInitializedPluralRules().Dump(thread); + os << "\n"; + os << " - Type: "; + GetType().Dump(thread); + os << "\n"; + os << " - MinimumIntegerDigits: "; + GetMinimumIntegerDigits().Dump(thread); + os << "\n"; + os << " - MinimumFractionDigits: "; + GetMinimumFractionDigits().Dump(thread); + os << "\n"; + os << " - MaximumFractionDigits: "; + GetMaximumFractionDigits().Dump(thread); + os << "\n"; + os << " - MinimumSignificantDigits: "; + GetMinimumSignificantDigits().Dump(thread); + os << "\n"; + os << " - MaximumSignificantDigits: "; + GetMaximumSignificantDigits().Dump(thread); + os << "\n"; + os << " - RoundingType: "; + GetRoundingType().Dump(thread); + os << "\n"; + os << " - IcuPR: "; + GetIcuPR().Dump(thread); + os << "\n"; + os << " - IcuNF: "; + GetIcuNF().Dump(thread); + os << "\n"; + JSObject::Dump(thread, os); +} + +void JSGeneratorObject::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - GeneratorState: "; + GetGeneratorState().Dump(thread); + os << "\n"; + os << " - GeneratorContext: "; + GetGeneratorContext().Dump(thread); + os << "\n"; + os << " - ResumeResult: "; + GetResumeResult().Dump(thread); + os << "\n"; + os << " - ResumeMode: "; + GetResumeMode().Dump(thread); + os << "\n"; + JSObject::Dump(thread, os); +} + +void JSAsyncFuncObject::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - Promise: "; + GetPromise().Dump(thread); + os << "\n"; +} + +void GeneratorContext::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - RegsArray: "; + GetRegsArray().Dump(thread); + os << "\n"; + os << " - Method: "; + GetMethod().Dump(thread); + os << "\n"; + os << " - Acc: "; + GetAcc().Dump(thread); + os << "\n"; + os << " - NRegs: "; + GetNRegs().Dump(thread); + os << "\n"; + os << " - BCOffset: "; + GetBCOffset().Dump(thread); + os << "\n"; + os << " - GeneratorObject: "; + GetGeneratorObject().Dump(thread); + os << "\n"; + os << " - LexicalEnv: "; + GetLexicalEnv().Dump(thread); + os << "\n"; +} + +void ProtoChangeMarker::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - HasChanged: " << GetHasChanged() << "\n"; +} + +void ProtoChangeDetails::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - ChangeListener: "; + GetChangeListener().Dump(thread); + os << "\n"; + os << " - RegisterIndex: "; + GetRegisterIndex().Dump(thread); + os << "\n"; +} + +void LexicalFunction::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - Name: "; + GetName().Dump(thread); + os << "\n"; + os << " - NumberVRegs: "; + GetNumberVRegs().Dump(thread); + os << "\n"; + os << " - NumberICSlots: "; + GetNumberICSlots().Dump(thread); + os << "\n"; + os << " - Bytecode: "; + GetBytecode().Dump(thread); + os << "\n"; + os << " - Program: "; + GetProgram().Dump(thread); + os << "\n"; +} + +void JSFunctionExtraInfo::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - Callback: "; + GetCallback().Dump(thread); + os << "\n"; + os << " - Data: "; + GetData().Dump(thread); + os << "\n"; +} + +void MachineCode::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - InstructionSizeInBytes: "; + GetInstructionSizeInBytes().Dump(thread); + os << "\n"; +} + +void EcmaModule::Dump(JSThread *thread, std::ostream &os) const +{ + os << " - NameDictionary: "; + GetNameDictionary().Dump(thread); + os << "\n"; +} + // ######################################################################################## // Dump for Snapshot // ######################################################################################## @@ -1352,6 +1901,12 @@ static void DumpArrayClass([[maybe_unused]] JSThread *thread, const TaggedArray } } +static void DumpStringClass([[maybe_unused]] JSThread *thread, const EcmaString *str, + std::vector> &vec) +{ + vec.push_back(std::make_pair("string", JSTaggedValue(str))); +} + static void DumpDynClass([[maybe_unused]] JSThread *thread, TaggedObject *obj, std::vector> &vec) { @@ -1359,7 +1914,8 @@ static void DumpDynClass([[maybe_unused]] JSThread *thread, TaggedObject *obj, vec.push_back(std::make_pair("__proto__", jshclass->GetPrototype())); } -static void DumpObject(JSThread *thread, TaggedObject *obj, std::vector> &vec) +static void DumpObject(JSThread *thread, TaggedObject *obj, + std::vector> &vec, bool isVmMode) { DISALLOW_GARBAGE_COLLECTION; auto jsHclass = obj->GetClass(); @@ -1368,14 +1924,16 @@ static void DumpObject(JSThread *thread, TaggedObject *obj, std::vectorDumpForSnapshot(thread, vec); - break; + return; case JSType::JS_FUNCTION_BASE: case JSType::JS_FUNCTION: JSFunction::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_BOUND_FUNCTION: JSBoundFunction::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_SET: JSSet::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_MAP: JSMap::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_WEAK_SET: JSWeakSet::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_WEAK_MAP: JSWeakMap::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_REG_EXP: JSRegExp::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_DATE: JSDate::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_ARRAY: JSArray::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_TYPED_ARRAY: case JSType::JS_INT8_ARRAY: case JSType::JS_UINT8_ARRAY: @@ -1426,62 +1985,59 @@ static void DumpObject(JSThread *thread, TaggedObject *obj, std::vectorDumpForSnapshot(thread, vec); - break; + return; case JSType::JS_PROXY: JSProxy::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_PRIMITIVE_REF: JSPrimitiveRef::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::SYMBOL: JSSymbol::Cast(obj)->DumpForSnapshot(thread, vec); - break; - case JSType::GLOBAL_ENV: - GlobalEnv::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::ACCESSOR_DATA: case JSType::INTERNAL_ACCESSOR: AccessorData::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_DATA_VIEW: JSDataView::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::PROMISE_REACTIONS: PromiseReaction::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::PROMISE_CAPABILITY: PromiseCapability::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::PROMISE_ITERATOR_RECORD: PromiseIteratorRecord::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::PROMISE_RECORD: PromiseRecord::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::RESOLVING_FUNCTIONS_RECORD: ResolvingFunctionsRecord::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_PROMISE: JSPromise::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_PROMISE_REACTIONS_FUNCTION: JSPromiseReactionsFunction::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_PROMISE_EXECUTOR_FUNCTION: JSPromiseExecutorFunction::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION: JSPromiseAllResolveElementFunction::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::MICRO_JOB_QUEUE: MicroJobQueue::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::PENDING_JOB: PendingJob::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::COMPLETION_RECORD: CompletionRecord::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_ITERATOR: case JSType::JS_FORIN_ITERATOR: case JSType::JS_MAP_ITERATOR: @@ -1490,26 +2046,101 @@ static void DumpObject(JSThread *thread, TaggedObject *obj, std::vectorDumpForSnapshot(thread, vec); - break; + return; case JSType::JS_PROXY_REVOC_FUNCTION: JSProxyRevocFunction::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_ASYNC_FUNCTION: JSAsyncFunction::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION: JSAsyncAwaitStatusFunction::Cast(obj)->DumpForSnapshot(thread, vec); - break; + return; case JSType::JS_GENERATOR_FUNCTION: JSGeneratorFunction::Cast(obj)->DumpForSnapshot(thread, vec); - break; - case JSType::TRANSITION_HANDLER: - case JSType::PROTOTYPE_HANDLER: - case JSType::PROPERTY_BOX: - break; + return; + case JSType::JS_INTL_BOUND_FUNCTION: + JSIntlBoundFunction::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_REALM: + JSRealm::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_INTL: + JSIntl::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_LOCALE: + JSLocale::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_DATE_TIME_FORMAT: + JSDateTimeFormat::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_RELATIVE_TIME_FORMAT: + JSRelativeTimeFormat::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_NUMBER_FORMAT: + JSNumberFormat::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_COLLATOR: + JSCollator::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_PLURAL_RULES: + JSPluralRules::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_GENERATOR_OBJECT: + JSGeneratorObject::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_ASYNC_FUNC_OBJECT: + JSAsyncFuncObject::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::JS_GENERATOR_CONTEXT: + GeneratorContext::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::FUNCTION_EXTRA_INFO: + JSFunctionExtraInfo::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::ECMA_MODULE: + EcmaModule::Cast(obj)->DumpForSnapshot(thread, vec); + return; default: break; } + if (isVmMode) { + switch (type) { + case JSType::PROPERTY_BOX: + PropertyBox::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::TEMPLATE_MAP: + DumpArrayClass(thread, TaggedArray::Cast(obj), vec); + return; + case JSType::LEXICAL_FUNCTION: + LexicalFunction::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::GLOBAL_ENV: + GlobalEnv::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::PROTO_CHANGE_MARKER: + ProtoChangeMarker::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::PROTOTYPE_INFO: + ProtoChangeDetails::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::PROGRAM: + Program::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::MACHINE_CODE_OBJECT: + MachineCode::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::TRANSITION_HANDLER: + TransitionHandler::Cast(obj)->DumpForSnapshot(thread, vec); + return; + case JSType::PROTOTYPE_HANDLER: + PrototypeHandler::Cast(obj)->DumpForSnapshot(thread, vec); + return; + default: + UNREACHABLE(); + break; + } + } } static inline void EcmaStringToStd(CString &res, EcmaString *str) @@ -1544,10 +2175,11 @@ static void KeyToStd(CString &res, JSTaggedValue key) } } -void JSTaggedValue::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +void JSTaggedValue::DumpForSnapshot(JSThread *thread, + std::vector> &vec, bool isVmMode) const { if (IsHeapObject()) { - return DumpObject(thread, GetTaggedObject(), vec); + return DumpObject(thread, GetTaggedObject(), vec, isVmMode); } UNREACHABLE(); @@ -1634,7 +2266,6 @@ void LinkedHashMap::DumpForSnapshot([[maybe_unused]] JSThread *thread, void JSObject::DumpForSnapshot(JSThread *thread, std::vector> &vec) const { DISALLOW_GARBAGE_COLLECTION; - JSHClass *jshclass = GetJSHClass(); vec.push_back(std::make_pair("__proto__", jshclass->GetPrototype())); @@ -1691,6 +2322,13 @@ void JSHClass::DumpForSnapshot([[maybe_unused]] JSThread *thread, void JSFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread, std::vector> &vec) const { + vec.push_back(std::make_pair(CString("ProtoOrDynClass"), GetProtoOrDynClass())); + vec.push_back(std::make_pair(CString("LexicalEnv"), GetLexicalEnv())); + vec.push_back(std::make_pair(CString("HomeObject"), GetHomeObject())); + vec.push_back(std::make_pair(CString("FunctionInfoFlag"), GetFunctionInfoFlag())); + vec.push_back(std::make_pair(CString("FunctionExtraInfo"), GetFunctionExtraInfo())); + vec.push_back(std::make_pair(CString("ConstantPool"), GetConstantPool())); + vec.push_back(std::make_pair(CString("ProfileTypeInfo"), GetProfileTypeInfo())); JSObject::DumpForSnapshot(thread, vec); } @@ -1700,6 +2338,8 @@ void Program::DumpForSnapshot([[maybe_unused]] JSThread *thread, vec.push_back(std::make_pair(CString("Location"), GetLocation())); vec.push_back(std::make_pair(CString("ConstantPool"), GetConstantPool())); vec.push_back(std::make_pair(CString("MainFunction"), GetMainFunction())); + // MethodsData is another native field, and we don't dump it for JS heap. + vec.push_back(std::make_pair(CString("NumberMethods"), JSTaggedValue(GetNumberMethods()))); } void ConstantPool::DumpForSnapshot([[maybe_unused]] JSThread *thread, @@ -1743,6 +2383,16 @@ void JSMap::DumpForSnapshot([[maybe_unused]] JSThread *thread, JSObject::DumpForSnapshot(thread, vec); } +void JSForInIterator::DumpForSnapshot([[maybe_unused]] JSThread *thread, + std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Object"), GetObject())); + vec.push_back(std::make_pair(CString("WasVisited"), GetWasVisited())); + vec.push_back(std::make_pair(CString("VisitedKeys"), GetVisitedKeys())); + vec.push_back(std::make_pair(CString("RemainingKeys"), GetRemainingKeys())); + JSObject::DumpForSnapshot(thread, vec); +} + void JSMapIterator::DumpForSnapshot([[maybe_unused]] JSThread *thread, std::vector> &vec) const { @@ -1805,6 +2455,14 @@ void JSArrayIterator::DumpForSnapshot([[maybe_unused]] JSThread *thread, JSObject::DumpForSnapshot(thread, vec); } +void JSStringIterator::DumpForSnapshot([[maybe_unused]] JSThread *thread, + std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("IteratedString"), GetIteratedString())); + vec.push_back(std::make_pair(CString("StringIteratorNextIndex"), GetStringIteratorNextIndex())); + JSObject::DumpForSnapshot(thread, vec); +} + void JSTypedArray::DumpForSnapshot([[maybe_unused]] JSThread *thread, std::vector> &vec) const { @@ -1982,6 +2640,7 @@ void JSArrayBuffer::DumpForSnapshot([[maybe_unused]] JSThread *thread, { vec.push_back(std::make_pair(CString("byte-length"), GetArrayBufferByteLength())); vec.push_back(std::make_pair(CString("buffer-data"), GetArrayBufferData())); + vec.push_back(std::make_pair(CString("shared"), GetShared())); } void PromiseReaction::DumpForSnapshot([[maybe_unused]] JSThread *thread, @@ -2101,4 +2760,198 @@ void JSGeneratorFunction::DumpForSnapshot([[maybe_unused]] JSThread *thread, { JSFunction::DumpForSnapshot(thread, vec); } + +void JSIntlBoundFunction::DumpForSnapshot(JSThread *thread, + std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("NumberFormat"), GetNumberFormat())); + vec.push_back(std::make_pair(CString("DateTimeFormat"), GetDateTimeFormat())); + vec.push_back(std::make_pair(CString("Collator"), GetCollator())); + JSObject::DumpForSnapshot(thread, vec); +} + +void PropertyBox::DumpForSnapshot([[maybe_unused]] JSThread *thread, + std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Value"), GetValue())); +} + +void PrototypeHandler::DumpForSnapshot([[maybe_unused]] JSThread *thread, + std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("HandlerInfo"), GetHandlerInfo())); + vec.push_back(std::make_pair(CString("ProtoCell"), GetProtoCell())); + vec.push_back(std::make_pair(CString("Holder"), GetHolder())); +} + +void TransitionHandler::DumpForSnapshot([[maybe_unused]] JSThread *thread, + std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("HandlerInfo"), GetHandlerInfo())); + vec.push_back(std::make_pair(CString("TransitionHClass"), GetTransitionHClass())); +} + +void JSRealm::DumpForSnapshot([[maybe_unused]] JSThread *thread, + std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Value"), GetValue())); + vec.push_back(std::make_pair(CString("GLobalEnv"), GetGlobalEnv())); + JSObject::DumpForSnapshot(thread, vec); +} + +void JSIntl::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("FallbackSymbol"), GetFallbackSymbol())); + JSObject::DumpForSnapshot(thread, vec); +} + +void JSLocale::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("IcuField"), GetIcuField())); + JSObject::DumpForSnapshot(thread, vec); +} + +void JSDateTimeFormat::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Locale"), GetLocale())); + vec.push_back(std::make_pair(CString("Calendar"), GetCalendar())); + vec.push_back(std::make_pair(CString("NumberingSystem"), GetNumberingSystem())); + vec.push_back(std::make_pair(CString("TimeZone"), GetTimeZone())); + vec.push_back(std::make_pair(CString("HourCycle"), GetHourCycle())); + vec.push_back(std::make_pair(CString("LocaleIcu"), GetLocaleIcu())); + vec.push_back(std::make_pair(CString("SimpleDateTimeFormatIcu"), GetSimpleDateTimeFormatIcu())); + vec.push_back(std::make_pair(CString("Iso8601"), GetIso8601())); + vec.push_back(std::make_pair(CString("DateStyle"), GetDateStyle())); + vec.push_back(std::make_pair(CString("TimeStyle"), GetTimeStyle())); + vec.push_back(std::make_pair(CString("BoundFormat"), GetBoundFormat())); + JSObject::DumpForSnapshot(thread, vec); +} + +void JSRelativeTimeFormat::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Locale"), GetLocale())); + vec.push_back(std::make_pair(CString("InitializedRelativeTimeFormat"), GetInitializedRelativeTimeFormat())); + vec.push_back(std::make_pair(CString("NumberingSystem"), GetNumberingSystem())); + vec.push_back(std::make_pair(CString("Style"), GetStyle())); + vec.push_back(std::make_pair(CString("Numeric"), GetNumeric())); + vec.push_back(std::make_pair(CString("AvailableLocales"), GetAvailableLocales())); + vec.push_back(std::make_pair(CString("IcuField"), GetIcuField())); + JSObject::DumpForSnapshot(thread, vec); +} + +void JSNumberFormat::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Locale"), GetLocale())); + vec.push_back(std::make_pair(CString("NumberingSystem"), GetNumberingSystem())); + vec.push_back(std::make_pair(CString("Style"), GetStyle())); + vec.push_back(std::make_pair(CString("Currency"), GetCurrency())); + vec.push_back(std::make_pair(CString("CurrencyDisplay"), GetCurrencyDisplay())); + vec.push_back(std::make_pair(CString("CurrencySign"), GetCurrencySign())); + vec.push_back(std::make_pair(CString("Unit"), GetUnit())); + vec.push_back(std::make_pair(CString("UnitDisplay"), GetUnitDisplay())); + vec.push_back(std::make_pair(CString("MinimumIntegerDigits"), GetMinimumIntegerDigits())); + vec.push_back(std::make_pair(CString("MinimumFractionDigits"), GetMinimumFractionDigits())); + vec.push_back(std::make_pair(CString("MaximumFractionDigits"), GetMaximumFractionDigits())); + vec.push_back(std::make_pair(CString("MinimumSignificantDigits"), GetMinimumSignificantDigits())); + vec.push_back(std::make_pair(CString("MaximumSignificantDigits"), GetMaximumSignificantDigits())); + vec.push_back(std::make_pair(CString("UseGrouping"), GetUseGrouping())); + vec.push_back(std::make_pair(CString("RoundingType"), GetRoundingType())); + vec.push_back(std::make_pair(CString("Notation"), GetNotation())); + vec.push_back(std::make_pair(CString("CompactDisplay"), GetCompactDisplay())); + vec.push_back(std::make_pair(CString("SignDisplay"), GetSignDisplay())); + vec.push_back(std::make_pair(CString("BoundFormat"), GetBoundFormat())); + vec.push_back(std::make_pair(CString("IcuField"), GetIcuField())); + JSObject::DumpForSnapshot(thread, vec); +} + +void JSCollator::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("IcuField"), GetIcuField())); + vec.push_back(std::make_pair(CString("Locale"), GetLocale())); + vec.push_back(std::make_pair(CString("Usage"), GetUsage())); + vec.push_back(std::make_pair(CString("Sensitivity"), GetSensitivity())); + vec.push_back(std::make_pair(CString("IgnorePunctuation"), GetIgnorePunctuation())); + vec.push_back(std::make_pair(CString("Collation"), GetCollation())); + vec.push_back(std::make_pair(CString("Numeric"), GetNumeric())); + vec.push_back(std::make_pair(CString("CaseFirst"), GetCaseFirst())); + vec.push_back(std::make_pair(CString("BoundCompare"), GetBoundCompare())); + JSObject::DumpForSnapshot(thread, vec); +} + +void JSPluralRules::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Locale"), GetLocale())); + vec.push_back(std::make_pair(CString("InitializedPluralRules"), GetInitializedPluralRules())); + vec.push_back(std::make_pair(CString("Type"), GetType())); + vec.push_back(std::make_pair(CString("MinimumIntegerDigits"), GetMinimumIntegerDigits())); + vec.push_back(std::make_pair(CString("MinimumFractionDigits"), GetMinimumFractionDigits())); + vec.push_back(std::make_pair(CString("MaximumFractionDigits"), GetMaximumFractionDigits())); + vec.push_back(std::make_pair(CString("MinimumSignificantDigits"), GetMinimumSignificantDigits())); + vec.push_back(std::make_pair(CString("MaximumSignificantDigits"), GetMaximumSignificantDigits())); + vec.push_back(std::make_pair(CString("RoundingType"), GetRoundingType())); + vec.push_back(std::make_pair(CString("IcuPR"), GetIcuPR())); + vec.push_back(std::make_pair(CString("IcuNF"), GetIcuNF())); + JSObject::DumpForSnapshot(thread, vec); +} + +void JSGeneratorObject::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("GeneratorState"), GetGeneratorState())); + vec.push_back(std::make_pair(CString("GeneratorContext"), GetGeneratorContext())); + vec.push_back(std::make_pair(CString("ResumeResult"), GetResumeResult())); + vec.push_back(std::make_pair(CString("ResumeMode"), GetResumeMode())); + JSObject::DumpForSnapshot(thread, vec); +} + +void JSAsyncFuncObject::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Promise"), GetPromise())); +} + +void GeneratorContext::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("RegsArray"), GetRegsArray())); + vec.push_back(std::make_pair(CString("Method"), GetMethod())); + vec.push_back(std::make_pair(CString("Acc"), GetAcc())); + vec.push_back(std::make_pair(CString("NRegs"), GetNRegs())); + vec.push_back(std::make_pair(CString("BCOffset"), GetBCOffset())); + vec.push_back(std::make_pair(CString("GeneratorObject"), GetGeneratorObject())); + vec.push_back(std::make_pair(CString("LexicalEnv"), GetLexicalEnv())); +} + +void ProtoChangeMarker::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Promise"), JSTaggedValue(GetHasChanged()))); +} + +void ProtoChangeDetails::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("ChangeListener"), GetChangeListener())); + vec.push_back(std::make_pair(CString("RegisterIndex"), GetRegisterIndex())); +} + +void LexicalFunction::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Name"), GetName())); + vec.push_back(std::make_pair(CString("NumberVRegs"), GetNumberVRegs())); + vec.push_back(std::make_pair(CString("NumberICSlots"), GetNumberICSlots())); + vec.push_back(std::make_pair(CString("Bytecode"), GetBytecode())); + vec.push_back(std::make_pair(CString("Program"), GetProgram())); +} + +void JSFunctionExtraInfo::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("Callback"), GetCallback())); + vec.push_back(std::make_pair(CString("Data"), GetData())); +} + +void MachineCode::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("InstructionSizeInBytes"), GetInstructionSizeInBytes())); +} + +void EcmaModule::DumpForSnapshot(JSThread *thread, std::vector> &vec) const +{ + vec.push_back(std::make_pair(CString("NameDictionary"), GetNameDictionary())); +} } // namespace panda::ecmascript diff --git a/ecmascript/ecma_macros.h b/ecmascript/ecma_macros.h index b13285f..b0c11b6 100644 --- a/ecmascript/ecma_macros.h +++ b/ecmascript/ecma_macros.h @@ -371,14 +371,14 @@ // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DECL_VISIT_OBJECT(BEGIN_OFFSET, SIZE) \ - void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor) \ + void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor) \ { \ visitor(this, ObjectSlot(ToUintPtr(this) + BEGIN_OFFSET), ObjectSlot(ToUintPtr(this) + SIZE)); \ } // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DECL_VISIT_OBJECT_FOR_JS_OBJECT(PARENTCLASS, BEGIN_OFFSET, SIZE) \ - void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor) \ + void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor) \ { \ VisitObjects(visitor); \ /* visit in object fields */ \ @@ -396,4 +396,9 @@ visitor(this, ObjectSlot(ToUintPtr(this) + BEGIN_OFFSET), ObjectSlot(ToUintPtr(this) + SIZE)); \ } +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define CHECK_DUMP_FILEDS(begin, end, num) \ + LOG_IF(num != (end - begin) / JSTaggedValue::TaggedTypeSize(), FATAL, RUNTIME) \ + << "Fileds in obj are not in dump list. "; + #endif // ECMASCRIPT_ECMA_MACROS_H diff --git a/ecmascript/ecma_module.h b/ecmascript/ecma_module.h index 707724d..ece8ee0 100644 --- a/ecmascript/ecma_module.h +++ b/ecmascript/ecma_module.h @@ -43,6 +43,7 @@ public: ACCESSORS(NameDictionary, NAME_DICTIONARY_OFFSET, SIZE) DECL_VISIT_OBJECT_FOR_JS_OBJECT(ECMAObject, NAME_DICTIONARY_OFFSET, SIZE) + DECL_DUMP() protected: void CopyModuleInternal(const JSThread *thread, JSHandle srcModule); diff --git a/ecmascript/hprof/heap_profiler.cpp b/ecmascript/hprof/heap_profiler.cpp index e2a8b34..016eed3 100644 --- a/ecmascript/hprof/heap_profiler.cpp +++ b/ecmascript/hprof/heap_profiler.cpp @@ -34,7 +34,7 @@ HeapProfiler::~HeapProfiler() jsonSerializer_ = nullptr; } -bool HeapProfiler::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const CString &filePath) +bool HeapProfiler::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const CString &filePath, bool isVmMode) { [[maybe_unused]] bool heapClean = ForceFullGC(thread); ASSERT(heapClean); @@ -42,7 +42,7 @@ bool HeapProfiler::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, con size_t heapSize = heap->GetNewSpace()->GetHeapObjectSize() + heap->GetOldSpace()->GetHeapObjectSize() + heap->GetNonMovableSpace()->GetHeapObjectSize(); LOG(ERROR, RUNTIME) << "HeapProfiler DumpSnapshot heap size " << heapSize; - HeapSnapShot *snapShot = MakeHeapSnapShot(thread, SampleType::ONE_SHOT); + HeapSnapShot *snapShot = MakeHeapSnapShot(thread, SampleType::ONE_SHOT, isVmMode); ASSERT(snapShot != nullptr); std::pair realPath = FilePathValid(filePath); if (realPath.first) { @@ -56,9 +56,9 @@ bool HeapProfiler::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, con UNREACHABLE(); } -bool HeapProfiler::StartHeapTracking(JSThread *thread, double timeInterval) +bool HeapProfiler::StartHeapTracking(JSThread *thread, double timeInterval, bool isVmMode) { - HeapSnapShot *snapShot = MakeHeapSnapShot(thread, SampleType::REAL_TIME); + HeapSnapShot *snapShot = MakeHeapSnapShot(thread, SampleType::REAL_TIME, isVmMode); if (snapShot == nullptr) { return false; } @@ -158,14 +158,15 @@ bool HeapProfiler::ForceFullGC(JSThread *thread) return false; } -HeapSnapShot *HeapProfiler::MakeHeapSnapShot(JSThread *thread, SampleType sampleType) +HeapSnapShot *HeapProfiler::MakeHeapSnapShot(JSThread *thread, SampleType sampleType, bool isVmMode) { LOG(ERROR, RUNTIME) << "HeapProfiler::MakeHeapSnapShot"; DISALLOW_GARBAGE_COLLECTION; heap_->GetSweeper()->EnsureAllTaskFinish(); switch (sampleType) { case SampleType::ONE_SHOT: { - auto *snapShot = const_cast(heap_->GetRegionFactory())->New(thread, heap_); + auto *snapShot = + const_cast(heap_->GetRegionFactory())->New(thread, heap_, isVmMode); if (snapShot == nullptr) { LOG_ECMA(FATAL) << "alloc snapshot failed"; UNREACHABLE(); @@ -175,7 +176,8 @@ HeapSnapShot *HeapProfiler::MakeHeapSnapShot(JSThread *thread, SampleType sample return snapShot; } case SampleType::REAL_TIME: { - auto *snapShot = const_cast(heap_->GetRegionFactory())->New(thread, heap_); + auto *snapShot = + const_cast(heap_->GetRegionFactory())->New(thread, heap_, isVmMode); if (snapShot == nullptr) { LOG_ECMA(FATAL) << "alloc snapshot failed"; UNREACHABLE(); diff --git a/ecmascript/hprof/heap_profiler.h b/ecmascript/hprof/heap_profiler.h index a516645..2510247 100644 --- a/ecmascript/hprof/heap_profiler.h +++ b/ecmascript/hprof/heap_profiler.h @@ -44,10 +44,10 @@ public: /** * dump the specific snapshot in target format */ - bool DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const CString &path); + bool DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const CString &path, bool isVmMode = true); void AddSnapShot(HeapSnapShot *snapshot); - bool StartHeapTracking(JSThread *thread, double timeInterval) override; + bool StartHeapTracking(JSThread *thread, double timeInterval, bool isVmMode = true) override; bool StopHeapTracking(JSThread *thread, DumpFormat dumpFormat, const CString &filePath) override; private: @@ -59,7 +59,7 @@ private: /** * make a new heap snapshot and put it into a container eg, vector */ - HeapSnapShot *MakeHeapSnapShot(JSThread *thread, SampleType sampleType); + HeapSnapShot *MakeHeapSnapShot(JSThread *thread, SampleType sampleType, bool isVmMode = true); std::pair FilePathValid(const CString &filePath); CString GenDumpFileName(DumpFormat dumpFormat); CString GetTimeStamp(); diff --git a/ecmascript/hprof/heap_profiler_interface.cpp b/ecmascript/hprof/heap_profiler_interface.cpp index 0292c07..715ff98 100644 --- a/ecmascript/hprof/heap_profiler_interface.cpp +++ b/ecmascript/hprof/heap_profiler_interface.cpp @@ -18,7 +18,7 @@ #include "ecmascript/mem/heap.h" namespace panda::ecmascript { -void HeapProfilerInterface::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const CString &filePath) +void HeapProfilerInterface::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const CString &filePath, bool isVmMode) { LOG(ERROR, RUNTIME) << "HeapProfilerInterface::DumpHeapSnapshot"; const Heap *heap = thread->GetEcmaVM()->GetHeap(); @@ -27,7 +27,7 @@ void HeapProfilerInterface::DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFo LOG_ECMA(FATAL) << "alloc hprof failed"; UNREACHABLE(); } - hprof->DumpHeapSnapShot(thread, dumpFormat, filePath); + hprof->DumpHeapSnapShot(thread, dumpFormat, filePath, isVmMode); const_cast(heap->GetRegionFactory())->Delete(hprof); } diff --git a/ecmascript/hprof/heap_profiler_interface.h b/ecmascript/hprof/heap_profiler_interface.h index 736f816..e7a8641 100644 --- a/ecmascript/hprof/heap_profiler_interface.h +++ b/ecmascript/hprof/heap_profiler_interface.h @@ -24,7 +24,8 @@ enum class DumpFormat { JSON, BINARY, OTHER }; class HeapProfilerInterface { public: - static void DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, const CString &filePath); + static void DumpHeapSnapShot(JSThread *thread, DumpFormat dumpFormat, + const CString &filePath, bool isVmMode = true); static HeapProfilerInterface *CreateHeapProfiler(JSThread *thread); static void Destory(JSThread *thread, HeapProfilerInterface *heapProfiler); @@ -32,7 +33,7 @@ public: HeapProfilerInterface() = default; virtual ~HeapProfilerInterface() = default; - virtual bool StartHeapTracking(JSThread *thread, double timeInterval) = 0; + virtual bool StartHeapTracking(JSThread *thread, double timeInterval, bool isVmMode = true) = 0; virtual bool StopHeapTracking(JSThread *thread, DumpFormat dumpFormat, const CString &filePath) = 0; NO_MOVE_SEMANTIC(HeapProfilerInterface); diff --git a/ecmascript/hprof/heap_snapshot.cpp b/ecmascript/hprof/heap_snapshot.cpp index 5145640..1523cd4 100644 --- a/ecmascript/hprof/heap_snapshot.cpp +++ b/ecmascript/hprof/heap_snapshot.cpp @@ -142,204 +142,36 @@ void HeapSnapShot::MoveNode(uintptr_t address, uintptr_t forward_address) // NOLINTNEXTLINE(readability-function-size) CString *HeapSnapShot::GenerateNodeName(JSThread *thread, TaggedObject *entry) { - CString *name = GetString("UnKnownType"); auto *hCls = entry->GetClass(); - if (hCls->IsTaggedArray()) { - CString arrayName; - TaggedArray *array = TaggedArray::Cast(entry); - if (hCls->IsDictionary()) { - arrayName = "TaggedDict["; - arrayName.append(ToCString(array->GetLength())); - arrayName.append("]"); - } else { + JSType type = hCls->GetObjectType(); + switch (type) { + case JSType::TAGGED_ARRAY: { + CString arrayName; + TaggedArray *array = TaggedArray::Cast(entry); arrayName = "TaggedArray["; arrayName.append(ToCString(array->GetLength())); arrayName.append("]"); + return GetString(arrayName); // String type was handled singly, see#GenerateStringNode } - name = GetString(arrayName); // String type was handled singly, see#GenerateStringNode - } else if (hCls->IsHClass()) { - name = GetString("HiddenClass"); - } else if (hCls->IsJSNativePointer()) { - name = GetString("JSNativePointer"); - } else { - if (hCls->IsRealm()) { - name = GetString("JSRealm"); - } else if (hCls->IsString()) { - name = GetString("JsString"); - } else if (hCls->IsJSSymbol()) { - name = GetString("JSSymbol"); - } else if (hCls->IsJSArray()) { - JSArray *jsArray = JSArray::Cast(entry); - CString arrayName("JSArray["); - arrayName.append(ToCString(jsArray->GetLength().GetInt())); - arrayName.append("]"); - name = GetString(arrayName); - } else if (hCls->IsTypedArray()) { - name = GetString("TypedArray"); - } else if (hCls->IsJSTypedArray()) { - name = GetString("JSTypedArray"); - } else if (hCls->IsJSInt8Array()) { - name = GetString("JSInt8Array"); - } else if (hCls->IsJSUint8Array()) { - name = GetString("JSUint8Array"); - } else if (hCls->IsJSUint8ClampedArray()) { - name = GetString("JSUint8ClampedArray"); - } else if (hCls->IsJSInt16Array()) { - name = GetString("JSInt16Array"); - } else if (hCls->IsJSUint16Array()) { - name = GetString("JSUint16Array"); - } else if (hCls->IsJSInt32Array()) { - name = GetString("JSInt32Array"); - } else if (hCls->IsJSUint32Array()) { - name = GetString("JSUint32Array"); - } else if (hCls->IsJSFloat32Array()) { - name = GetString("JSFloat32Array"); - } else if (hCls->IsJSFloat64Array()) { - name = GetString("JSFloat64Array"); - } else if (hCls->IsJsGlobalEnv()) { - name = GetString("JSGlobalEnv"); - } else if (hCls->IsJSFunctionBase()) { - name = GetString("JSFunctionBase"); - } else if (hCls->IsJsBoundFunction()) { - name = GetString("JsBoundFunction"); - } else if (hCls->IsJSIntlBoundFunction()) { - name = GetString("JSIntlBoundFunction"); - } else if (hCls->IsJSProxyRevocFunction()) { - name = GetString("JSProxyRevocFunction"); - } else if (hCls->IsJSAsyncFunction()) { - name = GetString("JSAsyncFunction"); - } else if (hCls->IsJSAsyncAwaitStatusFunction()) { - name = GetString("JSAsyncAwaitStatusFunction"); - } else if (hCls->IsJSPromiseReactionFunction()) { - name = GetString("JSPromiseReactionFunction"); - } else if (hCls->IsJSPromiseExecutorFunction()) { - name = GetString("JSPromiseExecutorFuncton"); - } else if (hCls->IsJSPromiseAllResolveElementFunction()) { - name = GetString("JSPromiseAllResolveElementFunction"); - } else if (hCls->IsJSFunctionExtraInfo()) { - name = GetString("JSFunctionExtraInfo"); - } else if (hCls->IsMicroJobQueue()) { - name = GetString("MicroJobQueue"); - } else if (hCls->IsPendingJob()) { - name = GetString("PendingJob"); - } else if (hCls->IsJsPrimitiveRef()) { - name = GetString("JsPrimitiveRef"); - } else if (hCls->IsJSSet()) { - name = GetString("JSSet"); - } else if (hCls->IsJSMap()) { - name = GetString("JSMap"); - } else if (hCls->IsJSWeakMap()) { - name = GetString("JSWeakMap"); - } else if (hCls->IsJSWeakSet()) { - name = GetString("JSWeakSet"); - } else if (hCls->IsJSFunction()) { - name = GetString("JSFunction"); - } else if (hCls->IsJSError()) { - name = GetString("JSError"); - } else if (hCls->IsArguments()) { - name = GetString("Arguments"); - } else if (hCls->IsDate()) { - name = GetString("Date"); - } else if (hCls->IsJSRegExp()) { - name = GetString("JSRegExp"); - } else if (hCls->IsJSProxy()) { - name = GetString("JSProxy"); - } else if (hCls->IsJSLocale()) { - name = GetString("JSLocale"); - } else if (hCls->IsJSIntl()) { - name = GetString("JSIntl"); - } else if (hCls->IsJSDateTimeFormat()) { - name = GetString("JSDateTimeFormat"); - } else if (hCls->IsJSRelativeTimeFormat()) { - name = GetString("JSRelativeTimeFormat"); - } else if (hCls->IsJSNumberFormat()) { - name = GetString("JSNumberFormat"); - } else if (hCls->IsAccessorData()) { - name = GetString("AccessorData"); - } else if (hCls->IsInternalAccessor()) { - name = GetString("InternalAccessor"); - } else if (hCls->IsIterator()) { - name = GetString("Iterator"); - } else if (hCls->IsForinIterator()) { - name = GetString("ForinIterator"); - } else if (hCls->IsStringIterator()) { - name = GetString("StringIterator"); - } else if (hCls->IsArrayBuffer()) { - name = GetString("ArrayBuffer"); - } else if (hCls->IsDataView()) { - name = GetString("DataView"); - } else if (hCls->IsJSSetIterator()) { - name = GetString("JSSetIterator"); - } else if (hCls->IsJSMapIterator()) { - name = GetString("JSMapIterator"); - } else if (hCls->IsJSArrayIterator()) { - name = GetString("JSArrayIterator"); - } else if (hCls->IsPrototypeHandler()) { - name = GetString("PrototypeHandler"); - } else if (hCls->IsTransitionHandler()) { - name = GetString("TransitionHandler"); - } else if (hCls->IsPropertyBox()) { - name = GetString("PropertyBox"); - } else if (hCls->IsProtoChangeMarker()) { - name = GetString("ProtoChangeMarker"); - } else if (hCls->IsProtoChangeDetails()) { - name = GetString("ProtoChangeDetails"); - } else if (hCls->IsProgram()) { - name = GetString("Program"); - } else if (hCls->IsEcmaModule()) { - name = GetString("EcmaModule"); - } else if (hCls->IsLexicalFunction()) { - name = GetString("LexicalFunction"); - } else if (hCls->IsConstructor()) { - name = GetString("Constructor"); - } else if (hCls->IsExtensible()) { - name = GetString("Extensible"); - } else if (hCls->IsPrototype()) { - name = GetString("Prototype"); - } else if (hCls->IsLiteral()) { - name = GetString("Literal"); - } else if (hCls->IsClassConstructor()) { - name = GetString("ClassConstructor"); - } else if (hCls->IsJSGlobalObject()) { - name = GetString("JSGlobalObject"); - } else if (hCls->IsClassPrototype()) { - name = GetString("ClassPrototype"); - } else if (hCls->IsGeneratorFunction()) { - name = GetString("GeneratorFunction"); - } else if (hCls->IsGeneratorObject()) { - name = GetString("GeneratorObject"); - } else if (hCls->IsAsyncFuncObject()) { - name = GetString("AsyncFunction"); - } else if (hCls->IsJSPromise()) { - name = GetString("JSPromise"); - } else if (hCls->IsResolvingFunctionsRecord()) { - name = GetString("ResolvingFunctionsRecord"); - } else if (hCls->IsPromiseRecord()) { - name = GetString("PromiseRecord"); - } else if (hCls->IsPromiseIteratorRecord()) { - name = GetString("JSPromiseIteratorRecord"); - } else if (hCls->IsPromiseCapability()) { - name = GetString("PromiseCapability"); - } else if (hCls->IsPromiseReaction()) { - name = GetString("JSPromiseReaction"); - } else if (hCls->IsCompletionRecord()) { - name = GetString("CompletionRecord"); - } else if (hCls->IsRecord()) { - name = GetString("Record"); - } else if (hCls->IsTemplateMap()) { - name = GetString("TemplateMap"); - } else if (hCls->IsFreeObjectWithOneField()) { - name = GetString("FreeObjectWithOneField"); - } else if (hCls->IsFreeObjectWithTwoField()) { - name = GetString("FreeObjectWithTwoField"); - } else if (hCls->IsJSObject()) { + case JSType::HCLASS: + return GetString("HiddenClass"); + case JSType::TAGGED_DICTIONARY: { + CString dictName; + TaggedArray *dict = TaggedArray::Cast(entry); + dictName = "TaggedDict["; + dictName.append(ToCString(dict->GetLength())); + dictName.append("]"); + return GetString(dictName); + } + case JSType::STRING: + return GetString("BaseString"); + case JSType::JS_OBJECT: { const GlobalEnvConstants *globalConst = thread->GlobalConstants(); CString objName = CString("JSOBJECT(Ctor="); // Ctor-name JSTaggedValue proto = JSObject::Cast(entry)->GetPrototype(thread); JSHandle protoHandle(thread, proto); if (protoHandle->IsNull() || protoHandle->IsUndefined()) { - name = GetString("JSObject(Ctor=UnKnown)"); - return name; + return GetString("JSObject(Ctor=UnKnown)"); } JSHandle ctor = JSObject::GetProperty(thread, protoHandle, globalConst->GetHandledConstructorString()).GetValue(); @@ -348,16 +180,197 @@ CString *HeapSnapShot::GenerateNodeName(JSThread *thread, TaggedObject *entry) JSHandle value = JSObject::GetProperty(thread, ctor, nameKey).GetValue(); CString ctorName = EntryVisitor::ConvertKey(value.GetTaggedValue()); objName.append(ctorName).append(")"); - name = GetString(objName); } - } else if (hCls->IsECMAObject()) { - name = GetString("ECMAObject"); - } else { - name = GetString("UnEmuratedJSType"); + return GetString(objName); + } + case JSType::FREE_OBJECT_WITH_ONE_FIELD: + case JSType::FREE_OBJECT_WITH_NONE_FIELD: + case JSType::FREE_OBJECT_WITH_TWO_FIELD: + case JSType::JS_NATIVE_POINTER: + { + break; + } + case JSType::JS_FUNCTION_BASE: + return GetString("JSFunctionBase"); + case JSType::JS_FUNCTION: + return GetString("JSFunction"); + case JSType::JS_ERROR: + return GetString("Error"); + case JSType::JS_EVAL_ERROR: + return GetString("Eval Error"); + case JSType::JS_RANGE_ERROR: + return GetString("Range Error"); + case JSType::JS_TYPE_ERROR: + return GetString("Type Error"); + case JSType::JS_REFERENCE_ERROR: + return GetString("Reference Error"); + case JSType::JS_URI_ERROR: + return GetString("Uri Error"); + case JSType::JS_SYNTAX_ERROR: + return GetString("Syntax Error"); + case JSType::JS_REG_EXP: + return GetString("Regexp"); + case JSType::JS_SET: + return GetString("Set"); + case JSType::JS_MAP: + return GetString("Map"); + case JSType::JS_WEAK_SET: + return GetString("WeakSet"); + case JSType::JS_WEAK_MAP: + return GetString("WeakMap"); + case JSType::JS_DATE: + return GetString("Date"); + case JSType::JS_BOUND_FUNCTION: + return GetString("Bound Function"); + case JSType::JS_ARRAY: { + JSArray *jsArray = JSArray::Cast(entry); + CString jsArrayName("JSArray["); + jsArrayName.append(ToCString(jsArray->GetLength().GetInt())); + jsArrayName.append("]"); + return GetString(jsArrayName); + } + case JSType::JS_TYPED_ARRAY: + return GetString("Typed Array"); + case JSType::JS_INT8_ARRAY: + return GetString("Int8 Array"); + case JSType::JS_UINT8_ARRAY: + return GetString("Uint8 Array"); + case JSType::JS_UINT8_CLAMPED_ARRAY: + return GetString("Uint8 Clamped Array"); + case JSType::JS_INT16_ARRAY: + return GetString("Int16 Array"); + case JSType::JS_UINT16_ARRAY: + return GetString("Uint16 Array"); + case JSType::JS_INT32_ARRAY: + return GetString("Int32 Array"); + case JSType::JS_UINT32_ARRAY: + return GetString("Uint32 Array"); + case JSType::JS_FLOAT32_ARRAY: + return GetString("Float32 Array"); + case JSType::JS_FLOAT64_ARRAY: + return GetString("Float64 Array"); + case JSType::JS_ARGUMENTS: + return GetString("Arguments"); + case JSType::JS_PROXY: + return GetString("Proxy"); + case JSType::JS_PRIMITIVE_REF: + return GetString("Primitive"); + case JSType::JS_DATA_VIEW: + return GetString("DataView"); + case JSType::JS_ITERATOR: + return GetString("Iterator"); + case JSType::JS_FORIN_ITERATOR: + return GetString("ForinInterator"); + case JSType::JS_MAP_ITERATOR: + return GetString("MapIterator"); + case JSType::JS_SET_ITERATOR: + return GetString("SetIterator"); + case JSType::JS_ARRAY_ITERATOR: + return GetString("ArrayIterator"); + case JSType::JS_STRING_ITERATOR: + return GetString("StringIterator"); + case JSType::JS_ARRAY_BUFFER: + return GetString("ArrayBuffer"); + case JSType::JS_PROXY_REVOC_FUNCTION: + return GetString("ProxyRevocFunction"); + case JSType::PROMISE_REACTIONS: + return GetString("PromiseReaction"); + case JSType::PROMISE_CAPABILITY: + return GetString("PromiseCapability"); + case JSType::PROMISE_ITERATOR_RECORD: + return GetString("PromiseIteratorRecord"); + case JSType::PROMISE_RECORD: + return GetString("PromiseRecord"); + case JSType::RESOLVING_FUNCTIONS_RECORD: + return GetString("ResolvingFunctionsRecord"); + case JSType::JS_PROMISE: + return GetString("Promise"); + case JSType::JS_PROMISE_REACTIONS_FUNCTION: + return GetString("PromiseReactionsFunction"); + case JSType::JS_PROMISE_EXECUTOR_FUNCTION: + return GetString("PromiseExecutorFunction"); + case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION: + return GetString("PromiseAllResolveElementFunction"); + case JSType::JS_GENERATOR_FUNCTION: + return GetString("JSGeneratorFunction"); + case JSType::SYMBOL: + return GetString("Symbol"); + case JSType::JS_ASYNC_FUNCTION: + return GetString("AsyncFunction"); + case JSType::JS_INTL_BOUND_FUNCTION: + return GetString("JSIntlBoundFunction"); + case JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION: + return GetString("AsyncAwaitStatusFunction"); + case JSType::JS_ASYNC_FUNC_OBJECT: + return GetString("AsyncFunctionObject"); + case JSType::JS_REALM: + return GetString("Realm"); + case JSType::JS_GLOBAL_OBJECT: + return GetString("GlobalObject"); + case JSType::JS_INTL: + return GetString("JSIntl"); + case JSType::JS_LOCALE: + return GetString("JSLocale"); + case JSType::JS_DATE_TIME_FORMAT: + return GetString("JSDateTimeFormat"); + case JSType::JS_RELATIVE_TIME_FORMAT: + return GetString("JSRelativeTimeFormat"); + case JSType::JS_NUMBER_FORMAT: + return GetString("JSNumberFormat"); + case JSType::JS_COLLATOR: + return GetString("JSCollator"); + case JSType::JS_PLURAL_RULES: + return GetString("JSPluralRules"); + case JSType::JS_GENERATOR_OBJECT: + return GetString("JSGeneratorObject"); + case JSType::JS_GENERATOR_CONTEXT: + return GetString("JSGeneratorContext"); + case JSType::ACCESSOR_DATA: + return GetString("AccessorData"); + case JSType::INTERNAL_ACCESSOR: + return GetString("InternalAccessor"); + case JSType::FUNCTION_EXTRA_INFO: + return GetString("FunctionExtraInfo"); + case JSType::MICRO_JOB_QUEUE: + return GetString("MicroJobQueue"); + case JSType::PENDING_JOB: + return GetString("PendingJob"); + case JSType::COMPLETION_RECORD: + return GetString("CompletionRecord"); + case JSType::ECMA_MODULE: + return GetString("EcmaModule"); + default: + break; + } + if (IsInVmMode()) { + switch (type) { + case JSType::PROPERTY_BOX: + return GetString("PropertyBox"); + case JSType::GLOBAL_ENV: + return GetString("GlobalEnv"); + case JSType::PROTOTYPE_HANDLER: + return GetString("ProtoTypeHandler"); + case JSType::TRANSITION_HANDLER: + return GetString("TransitionHandler"); + case JSType::PROTO_CHANGE_MARKER: + return GetString("ProtoChangeMarker"); + case JSType::PROTOTYPE_INFO: + return GetString("ProtoChangeDetails"); + case JSType::TEMPLATE_MAP: + return GetString("TemplateMap"); + case JSType::PROGRAM: + return GetString("Program"); + case JSType::LEXICAL_FUNCTION: + return GetString("LexicalFunction"); + case JSType::MACHINE_CODE_OBJECT: + return GetString("MachineCode"); + default: + break; } - return name; // Cached in String-Table + } else { + return GetString("Hidden Object"); } - return name; + return GetString("UnKnownType"); } NodeType HeapSnapShot::GenerateNodeType(TaggedObject *entry) @@ -367,7 +380,7 @@ NodeType HeapSnapShot::GenerateNodeType(TaggedObject *entry) if (hCls->IsTaggedArray()) { nodeType = NodeType::JS_ARRAY; } else if (hCls->IsHClass()) { - nodeType = NodeType::PROPERTY_BOX; + nodeType = NodeType::HCLASS; } else { nodeType = NodeType(hCls->GetObjectType()); } @@ -489,7 +502,7 @@ void HeapSnapShot::FillEdges(JSThread *thread) ASSERT(*iter != nullptr); auto *objFrom = reinterpret_cast((*iter)->GetAddress()); std::vector> nameResources; - JSTaggedValue(objFrom).DumpForSnapshot(thread, nameResources); + JSTaggedValue(objFrom).DumpForSnapshot(thread, nameResources, isVmMode_); JSTaggedValue objValue(objFrom); for (auto const &it : nameResources) { JSTaggedValue toValue = it.second; diff --git a/ecmascript/hprof/heap_snapshot.h b/ecmascript/hprof/heap_snapshot.h index f2ad5fb..43afb09 100644 --- a/ecmascript/hprof/heap_snapshot.h +++ b/ecmascript/hprof/heap_snapshot.h @@ -236,8 +236,8 @@ public: static constexpr int SEQ_STEP = 2; NO_MOVE_SEMANTIC(HeapSnapShot); NO_COPY_SEMANTIC(HeapSnapShot); - explicit HeapSnapShot(JSThread *thread, const Heap *heap) - : stringTable_(heap), thread_(thread), heap_(heap) + explicit HeapSnapShot(JSThread *thread, const Heap *heap, const bool isVmMode) + : stringTable_(heap), thread_(thread), heap_(heap), isVmMode_(isVmMode) { } ~HeapSnapShot(); @@ -293,6 +293,11 @@ public: CString *GetString(const CString &as); + bool IsInVmMode() const + { + return isVmMode_; + } + private: void FillNodes(JSThread *thread); Node *GenerateNode(JSThread *thread, JSTaggedValue entry, int sequenceId = -1); @@ -320,6 +325,7 @@ private: panda::ecmascript::HeapRootVisitor rootVisitor_; JSThread *thread_; const Heap *heap_; + bool isVmMode_{true}; }; class EntryVisitor { diff --git a/ecmascript/hprof/tests/hprof_test.cpp b/ecmascript/hprof/tests/hprof_test.cpp index a8edc9b..d602165 100644 --- a/ecmascript/hprof/tests/hprof_test.cpp +++ b/ecmascript/hprof/tests/hprof_test.cpp @@ -16,20 +16,76 @@ #include #include +#include "ecmascript/accessor_data.h" +#include "ecmascript/class_linker/program_object-inl.h" +#include "ecmascript/ecma_module.h" #include "ecmascript/ecma_vm.h" +#include "ecmascript/global_dictionary-inl.h" #include "ecmascript/global_env.h" #include "ecmascript/hprof/heap_profiler.h" #include "ecmascript/hprof/heap_profiler_interface.h" #include "ecmascript/hprof/heap_snapshot.h" #include "ecmascript/hprof/heap_snapshot_json_serializer.h" #include "ecmascript/hprof/string_hashmap.h" +#include "ecmascript/ic/ic_handler.h" +#include "ecmascript/ic/proto_change_details.h" +#include "ecmascript/ic/property_box.h" +#include "ecmascript/jobs/micro_job_queue.h" +#include "ecmascript/jobs/pending_job.h" +#include "ecmascript/js_arguments.h" +#include "ecmascript/js_array.h" +#include "ecmascript/js_array_iterator.h" +#include "ecmascript/js_arraybuffer.h" +#include "ecmascript/js_async_function.h" +#include "ecmascript/js_collator.h" +#include "ecmascript/js_dataview.h" +#include "ecmascript/js_date.h" +#include "ecmascript/js_date_time_format.h" +#include "ecmascript/js_for_in_iterator.h" +#include "ecmascript/js_function.h" +#include "ecmascript/js_function_extra_info.h" +#include "ecmascript/js_generator_object.h" +#include "ecmascript/js_global_object.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/js_intl.h" +#include "ecmascript/js_locale.h" +#include "ecmascript/js_map.h" +#include "ecmascript/js_map_iterator.h" +#include "ecmascript/js_number_format.h" +#include "ecmascript/js_object-inl.h" +#include "ecmascript/js_plural_rules.h" +#include "ecmascript/js_primitive_ref.h" +#include "ecmascript/js_promise.h" +#include "ecmascript/js_realm.h" +#include "ecmascript/js_regexp.h" +#include "ecmascript/js_relative_time_format.h" +#include "ecmascript/js_set.h" +#include "ecmascript/js_set_iterator.h" +#include "ecmascript/js_string_iterator.h" +#include "ecmascript/js_tagged_number.h" +#include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/js_thread.h" +#include "ecmascript/js_typed_array.h" +#include "ecmascript/js_weak_container.h" +#include "ecmascript/layout_info-inl.h" +#include "ecmascript/lexical_env.h" +#include "ecmascript/linked_hash_table-inl.h" +#include "ecmascript/mem/assert_scope-inl.h" +#include "ecmascript/mem/c_containers.h" +#include "ecmascript/mem/machine_code.h" #include "ecmascript/object_factory.h" +#include "ecmascript/tagged_array.h" +#include "ecmascript/tagged_dictionary.h" +#include "ecmascript/template_map.h" #include "ecmascript/tests/test_helper.h" +#include "ecmascript/transitions_dictionary.h" using namespace panda::ecmascript; +using namespace panda::ecmascript::base; namespace panda::test { +using MicroJobQueue = panda::ecmascript::job::MicroJobQueue; +using PendingJob = panda::ecmascript::job::PendingJob; class HProfTest : public testing::Test { public: static void SetUpTestCase() @@ -332,4 +388,502 @@ HWTEST_F_L0(HProfTest, ContrastTraceFunctionInfoCount) tester.ExtractCountFromPayload("\"trace_function_infos\":")); ASSERT_TRUE(tester.RemoveExistingFile()); } + +static JSHandle NewJSMap(JSThread *thread, ObjectFactory *factory, JSHandle proto) +{ + JSHandle mapClass = factory->NewEcmaDynClass(JSMap::SIZE, JSType::JS_MAP, proto); + JSHandle jsMap = JSHandle::Cast(factory->NewJSObject(mapClass)); + JSHandle linkedMap(thread, LinkedHashMap::Create(thread)); + jsMap->SetLinkedMap(thread, linkedMap); + return jsMap; +} + +static JSHandle NewJSSet(JSThread *thread, ObjectFactory *factory, JSHandle proto) +{ + JSHandle setClass = factory->NewEcmaDynClass(JSSet::SIZE, JSType::JS_SET, proto); + JSHandle jsSet = JSHandle::Cast(factory->NewJSObject(setClass)); + JSHandle linkedSet(thread, LinkedHashSet::Create(thread)); + jsSet->SetLinkedSet(thread, linkedSet); + return jsSet; +} + +static JSHandle NewJSObject(JSThread *thread, ObjectFactory *factory, JSHandle globalEnv) +{ + JSFunction *jsFunc = globalEnv->GetObjectFunction().GetObject(); + JSHandle jsFunc1(thread, jsFunc); + JSHandle jsObj = factory->NewJSObjectByConstructor(JSHandle(jsFunc1), jsFunc1); + return jsObj; +} + +HWTEST_F_L0(HProfTest, Dump) +{ + [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread); + auto factory = thread->GetEcmaVM()->GetFactory(); + auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); + auto globalConst = const_cast(thread->GlobalConstants()); + JSHandle proto = globalEnv->GetFunctionPrototype(); + std::vector> snapshotVector; + +#define DUMP_FOR_HANDLE(dumpHandle) \ + dumpHandle.GetTaggedValue().Dump(thread); \ + dumpHandle.GetTaggedValue().DumpForSnapshot(thread, snapshotVector); + +#define NEW_OBJECT_AND_DUMP(ClassName, TypeName) \ + JSHandle class##ClassName = \ + factory->NewEcmaDynClass(ClassName::SIZE, JSType::TypeName, proto); \ + JSHandle object##ClassName = factory->NewJSObject(class##ClassName); \ + object##ClassName.GetTaggedValue().Dump(thread); \ + object##ClassName.GetTaggedValue().DumpForSnapshot(thread, snapshotVector); + + for (JSType type = JSType::JS_OBJECT; type <= JSType::JS_TYPE_LAST; type = JSType(static_cast(type) + 1)) { + switch (type) { + case JSType::JS_ERROR: + case JSType::JS_EVAL_ERROR: + case JSType::JS_RANGE_ERROR: + case JSType::JS_TYPE_ERROR: + case JSType::JS_REFERENCE_ERROR: + case JSType::JS_URI_ERROR: + case JSType::JS_SYNTAX_ERROR: + case JSType::JS_OBJECT: { + CHECK_DUMP_FILEDS(ECMAObject::SIZE, JSObject::SIZE, 2) + JSHandle jsObj = NewJSObject(thread, factory, globalEnv); + DUMP_FOR_HANDLE(jsObj) + break; + } + case JSType::JS_REALM: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSRealm::SIZE, 2) + JSHandle jsRealm = factory->NewJSRealm(); + DUMP_FOR_HANDLE(jsRealm) + break; + } + case JSType::JS_FUNCTION_BASE: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSFunctionBase::SIZE, 1) + break; + } + case JSType::JS_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunctionBase::SIZE, JSFunction::SIZE, 7) + JSHandle jsFunc = globalEnv->GetFunctionFunction(); + DUMP_FOR_HANDLE(jsFunc) + break; + } + case JSType::JS_PROXY_REVOC_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSProxyRevocFunction::SIZE, 1) + JSHandle proxyRevocClass = + JSHandle::Cast(globalEnv->GetProxyRevocFunctionClass()); + JSHandle proxyRevocFunc = factory->NewJSObject(proxyRevocClass); + DUMP_FOR_HANDLE(proxyRevocFunc) + break; + } + case JSType::JS_PROMISE_REACTIONS_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSPromiseReactionsFunction::SIZE, 2) + JSHandle promiseReactClass = + JSHandle::Cast(globalEnv->GetPromiseReactionFunctionClass()); + JSHandle promiseReactFunc = factory->NewJSObject(promiseReactClass); + DUMP_FOR_HANDLE(promiseReactFunc) + break; + } + case JSType::JS_PROMISE_EXECUTOR_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSPromiseExecutorFunction::SIZE, 1) + JSHandle promiseExeClass = + JSHandle::Cast(globalEnv->GetPromiseExecutorFunctionClass()); + JSHandle promiseExeFunc = factory->NewJSObject(promiseExeClass); + DUMP_FOR_HANDLE(promiseExeFunc) + break; + } + case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSPromiseAllResolveElementFunction::SIZE, 5) + JSHandle promiseAllClass = + JSHandle::Cast(globalEnv->GetPromiseAllResolveElementFunctionClass()); + JSHandle promiseAllFunc = factory->NewJSObject(promiseAllClass); + DUMP_FOR_HANDLE(promiseAllFunc) + break; + } + case JSType::JS_GENERATOR_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSGeneratorFunction::SIZE, 0) + break; + } + case JSType::JS_ASYNC_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSAsyncFunction::SIZE, 0) + break; + } + case JSType::JS_INTL_BOUND_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSIntlBoundFunction::SIZE, 3) + JSHandle intlBoundFunc = factory->NewJSIntlBoundFunction(); + DUMP_FOR_HANDLE(intlBoundFunc) + break; + } + case JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSAsyncAwaitStatusFunction::SIZE, 1) + JSHandle asyncAwaitFunc = factory->NewJSAsyncAwaitStatusFunction(); + DUMP_FOR_HANDLE(asyncAwaitFunc) + break; + } + case JSType::JS_BOUND_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunctionBase::SIZE, JSBoundFunction::SIZE, 3) + NEW_OBJECT_AND_DUMP(JSBoundFunction, JS_BOUND_FUNCTION) + break; + } + case JSType::JS_REG_EXP: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSRegExp::SIZE, 5) + NEW_OBJECT_AND_DUMP(JSRegExp, JS_REG_EXP) + break; + } + case JSType::JS_SET: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSSet::SIZE, 1) + JSHandle jsSet = NewJSSet(thread, factory, proto); + DUMP_FOR_HANDLE(jsSet) + break; + } + case JSType::JS_MAP: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSMap::SIZE, 1) + JSHandle jsMap = NewJSMap(thread, factory, proto); + DUMP_FOR_HANDLE(jsMap) + break; + } + case JSType::JS_WEAK_MAP: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSWeakMap::SIZE, 1) + JSHandle weakMapClass = factory->NewEcmaDynClass(JSWeakMap::SIZE, JSType::JS_WEAK_MAP, proto); + JSHandle jsWeakMap = JSHandle::Cast(factory->NewJSObject(weakMapClass)); + JSHandle weakLinkedMap(thread, LinkedHashMap::Create(thread)); + jsWeakMap->SetLinkedMap(thread, weakLinkedMap); + DUMP_FOR_HANDLE(jsWeakMap) + break; + } + case JSType::JS_WEAK_SET: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSWeakSet::SIZE, 1) + JSHandle weakSetClass = factory->NewEcmaDynClass(JSWeakSet::SIZE, JSType::JS_WEAK_SET, proto); + JSHandle jsWeakSet = JSHandle::Cast(factory->NewJSObject(weakSetClass)); + JSHandle weakLinkedSet(thread, LinkedHashSet::Create(thread)); + jsWeakSet->SetLinkedSet(thread, weakLinkedSet); + DUMP_FOR_HANDLE(jsWeakSet) + break; + } + case JSType::JS_DATE: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSDate::SIZE, 2) + JSHandle dateClass = factory->NewEcmaDynClass(JSDate::SIZE, JSType::JS_DATE, proto); + JSHandle date = JSHandle::Cast(factory->NewJSObject(dateClass)); + date->SetTimeValue(thread, JSTaggedValue(0.0)); + date->SetLocalOffset(thread, JSTaggedValue(0.0)); + DUMP_FOR_HANDLE(date) + break; + } + case JSType::JS_ITERATOR: + // JS Iterate is a tool class, so we don't need to check it. + break; + case JSType::JS_FORIN_ITERATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSForInIterator::SIZE, 4) + JSHandle array(thread, factory->NewJSArray().GetTaggedValue()); + JSHandle forInIter = factory->NewJSForinIterator(array); + DUMP_FOR_HANDLE(forInIter) + break; + } + case JSType::JS_MAP_ITERATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSMapIterator::SIZE, 3) + JSHandle jsMapIter = + factory->NewJSMapIterator(NewJSMap(thread, factory, proto), IterationKind::KEY); + DUMP_FOR_HANDLE(jsMapIter) + break; + } + case JSType::JS_SET_ITERATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSSetIterator::SIZE, 3) + JSHandle jsSetIter = + factory->NewJSSetIterator(NewJSSet(thread, factory, proto), IterationKind::KEY); + DUMP_FOR_HANDLE(jsSetIter) + break; + } + case JSType::JS_ARRAY_ITERATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSArrayIterator::SIZE, 3) + JSHandle arrayIter = + factory->NewJSArrayIterator(JSHandle::Cast(factory->NewJSArray()), IterationKind::KEY); + DUMP_FOR_HANDLE(arrayIter) + break; + } + case JSType::JS_STRING_ITERATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSStringIterator::SIZE, 2) + JSHandle stringIter = globalEnv->GetStringIterator(); + DUMP_FOR_HANDLE(stringIter) + break; + } + case JSType::JS_INTL: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSIntl::SIZE, 1) + NEW_OBJECT_AND_DUMP(JSIntl, JS_INTL) + break; + } + case JSType::JS_LOCALE: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSLocale::SIZE, 1) + NEW_OBJECT_AND_DUMP(JSLocale, JS_LOCALE) + break; + } + case JSType::JS_DATE_TIME_FORMAT: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSDateTimeFormat::SIZE, 11) + NEW_OBJECT_AND_DUMP(JSDateTimeFormat, JS_DATE_TIME_FORMAT) + break; + } + case JSType::JS_RELATIVE_TIME_FORMAT: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSRelativeTimeFormat::SIZE, 7) + NEW_OBJECT_AND_DUMP(JSRelativeTimeFormat, JS_RELATIVE_TIME_FORMAT) + break; + } + case JSType::JS_NUMBER_FORMAT: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSNumberFormat::SIZE, 20) + NEW_OBJECT_AND_DUMP(JSNumberFormat, JS_NUMBER_FORMAT) + break; + } + case JSType::JS_COLLATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSCollator::SIZE, 9) + NEW_OBJECT_AND_DUMP(JSCollator, JS_COLLATOR) + break; + } + case JSType::JS_PLURAL_RULES: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSPluralRules::SIZE, 11) + NEW_OBJECT_AND_DUMP(JSPluralRules, JS_PLURAL_RULES) + break; + } + case JSType::JS_ARRAY_BUFFER: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSArrayBuffer::SIZE, 3) + NEW_OBJECT_AND_DUMP(JSArrayBuffer, JS_ARRAY_BUFFER) + break; + } + case JSType::JS_PROMISE: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSPromise::SIZE, 5) + NEW_OBJECT_AND_DUMP(JSPromise, JS_PROMISE) + break; + } + case JSType::JS_DATA_VIEW: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSDataView::SIZE, 4) + NEW_OBJECT_AND_DUMP(JSDataView, JS_DATA_VIEW) + break; + } + case JSType::JS_ARGUMENTS: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSArguments::SIZE, 1) + NEW_OBJECT_AND_DUMP(JSArguments, JS_ARGUMENTS) + break; + } + case JSType::JS_GENERATOR_OBJECT: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSGeneratorObject::SIZE, 4) + NEW_OBJECT_AND_DUMP(JSGeneratorObject, JS_GENERATOR_OBJECT) + break; + } + case JSType::JS_ASYNC_FUNC_OBJECT: { + CHECK_DUMP_FILEDS(JSGeneratorObject::SIZE, JSAsyncFuncObject::SIZE, 1) + JSHandle asyncFuncObject = factory->NewJSAsyncFuncObject(); + DUMP_FOR_HANDLE(asyncFuncObject) + break; + } + case JSType::JS_ARRAY: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSArray::SIZE, 1) + JSHandle jsArray = factory->NewJSArray(); + DUMP_FOR_HANDLE(jsArray) + break; + } + case JSType::JS_TYPED_ARRAY: + case JSType::JS_INT8_ARRAY: + case JSType::JS_UINT8_ARRAY: + case JSType::JS_UINT8_CLAMPED_ARRAY: + case JSType::JS_INT16_ARRAY: + case JSType::JS_UINT16_ARRAY: + case JSType::JS_INT32_ARRAY: + case JSType::JS_UINT32_ARRAY: + case JSType::JS_FLOAT32_ARRAY: + case JSType::JS_FLOAT64_ARRAY: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSTypedArray::SIZE, 5) + NEW_OBJECT_AND_DUMP(JSTypedArray, JS_TYPED_ARRAY) + break; + } + case JSType::JS_PRIMITIVE_REF: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSPrimitiveRef::SIZE, 1) + NEW_OBJECT_AND_DUMP(JSPrimitiveRef, JS_PRIMITIVE_REF) + break; + } + case JSType::JS_GLOBAL_OBJECT: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSGlobalObject::SIZE, 0) + JSHandle globalObject = globalEnv->GetJSGlobalObject(); + DUMP_FOR_HANDLE(globalObject) + break; + } + case JSType::JS_PROXY: { + CHECK_DUMP_FILEDS(ECMAObject::SIZE, JSProxy::SIZE, 3) + JSHandle emptyObj(thread, NewJSObject(thread, factory, globalEnv).GetTaggedValue()); + JSHandle proxy = factory->NewJSProxy(emptyObj, emptyObj); + DUMP_FOR_HANDLE(proxy) + break; + } + case JSType::HCLASS: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSHClass::SIZE, 9) + JSHandle hclass = factory->NewEcmaDynClass(JSHClass::SIZE, JSType::HCLASS, proto); + DUMP_FOR_HANDLE(hclass) + break; + } + case JSType::STRING: { + DUMP_FOR_HANDLE(globalEnv->GetObjectFunction()) + break; + } + case JSType::TAGGED_ARRAY: { + JSHandle taggedArray = factory->NewTaggedArray(4); + DUMP_FOR_HANDLE(taggedArray) + break; + } + case JSType::TAGGED_DICTIONARY: { + JSHandle dict = factory->NewDictionaryArray(4); + DUMP_FOR_HANDLE(dict) + break; + } + case JSType::FREE_OBJECT_WITH_ONE_FIELD: + case JSType::FREE_OBJECT_WITH_NONE_FIELD: + case JSType::FREE_OBJECT_WITH_TWO_FIELD: + { + break; + } + case JSType::JS_NATIVE_POINTER: { + break; + } + case JSType::GLOBAL_ENV: { + DUMP_FOR_HANDLE(globalEnv) + break; + } + case JSType::ACCESSOR_DATA: + case JSType::INTERNAL_ACCESSOR: { + CHECK_DUMP_FILEDS(Record::SIZE, AccessorData::SIZE, 2) + JSHandle accessor = factory->NewAccessorData(); + DUMP_FOR_HANDLE(accessor) + break; + } + case JSType::SYMBOL: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSSymbol::SIZE, 3) + JSHandle symbol = factory->NewJSSymbol(); + DUMP_FOR_HANDLE(symbol) + break; + } + case JSType::JS_GENERATOR_CONTEXT: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), GeneratorContext::SIZE, 7) + JSHandle genContext = factory->NewGeneratorContext(); + DUMP_FOR_HANDLE(genContext) + break; + } + case JSType::PROTOTYPE_HANDLER: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), PrototypeHandler::SIZE, 3) + JSHandle protoHandler = factory->NewPrototypeHandler(); + DUMP_FOR_HANDLE(protoHandler) + break; + } + case JSType::TRANSITION_HANDLER: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), TransitionHandler::SIZE, 2) + JSHandle transitionHandler = factory->NewTransitionHandler(); + DUMP_FOR_HANDLE(transitionHandler) + break; + } + case JSType::PROPERTY_BOX: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), PropertyBox::SIZE, 1) + JSHandle PropertyBox = factory->NewPropertyBox(globalEnv->GetEmptyArray()); + DUMP_FOR_HANDLE(PropertyBox) + break; + } + case JSType::PROTO_CHANGE_MARKER: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), ProtoChangeMarker::SIZE, 1) + JSHandle protoMaker = factory->NewProtoChangeMarker(); + DUMP_FOR_HANDLE(protoMaker) + break; + } + case JSType::PROTOTYPE_INFO: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), ProtoChangeDetails::SIZE, 2) + JSHandle protoDetails = factory->NewProtoChangeDetails(); + DUMP_FOR_HANDLE(protoDetails) + break; + } + case JSType::TEMPLATE_MAP: { + JSHandle templateMap = globalEnv->GetTemplateMap(); + DUMP_FOR_HANDLE(templateMap) + break; + } + case JSType::PROGRAM: { + CHECK_DUMP_FILEDS(ECMAObject::SIZE, Program::SIZE, 5) + JSHandle program = factory->NewProgram(); + DUMP_FOR_HANDLE(program) + break; + } + case JSType::LEXICAL_FUNCTION: { + CHECK_DUMP_FILEDS(ECMAObject::SIZE, LexicalFunction::SIZE, 5) + // unused + break; + } + case JSType::PROMISE_CAPABILITY: { + CHECK_DUMP_FILEDS(Record::SIZE, PromiseCapability::SIZE, 3) + JSHandle promiseCapa = factory->NewPromiseCapability(); + DUMP_FOR_HANDLE(promiseCapa) + break; + } + case JSType::PROMISE_RECORD: { + CHECK_DUMP_FILEDS(Record::SIZE, PromiseRecord::SIZE, 1) + JSHandle promiseRecord = factory->NewPromiseRecord(); + DUMP_FOR_HANDLE(promiseRecord) + break; + } + case JSType::RESOLVING_FUNCTIONS_RECORD: { + CHECK_DUMP_FILEDS(Record::SIZE, ResolvingFunctionsRecord::SIZE, 2) + JSHandle ResolvingFunc = factory->NewResolvingFunctionsRecord(); + DUMP_FOR_HANDLE(ResolvingFunc) + break; + } + case JSType::PROMISE_REACTIONS: { + CHECK_DUMP_FILEDS(Record::SIZE, PromiseReaction::SIZE, 3) + JSHandle promiseReact = factory->NewPromiseReaction(); + DUMP_FOR_HANDLE(promiseReact) + break; + } + case JSType::PROMISE_ITERATOR_RECORD: { + CHECK_DUMP_FILEDS(Record::SIZE, PromiseIteratorRecord::SIZE, 2) + JSHandle emptyObj(thread, NewJSObject(thread, factory, globalEnv).GetTaggedValue()); + JSHandle promiseIter = factory->NewPromiseIteratorRecord(emptyObj, emptyObj); + DUMP_FOR_HANDLE(promiseIter) + break; + } + case JSType::MICRO_JOB_QUEUE: { + CHECK_DUMP_FILEDS(Record::SIZE, MicroJobQueue::SIZE, 2) + JSHandle microJob = factory->NewMicroJobQueue(); + DUMP_FOR_HANDLE(microJob) + break; + } + case JSType::PENDING_JOB: { + CHECK_DUMP_FILEDS(Record::SIZE, PendingJob::SIZE, 2) + JSHandle pendingClass(thread, + JSHClass::Cast(globalConst->GetPendingJobClass().GetTaggedObject())); + JSHandle pendingJob(thread, factory->NewDynObject(pendingClass)); + DUMP_FOR_HANDLE(pendingJob) + break; + } + case JSType::FUNCTION_EXTRA_INFO: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSFunctionExtraInfo::SIZE, 2) + JSHandle funcExtraClass(thread, + JSHClass::Cast(globalConst->GetFunctionExtraInfoClass().GetTaggedObject())); + JSHandle funcInfo(thread, factory->NewDynObject(funcExtraClass)); + DUMP_FOR_HANDLE(funcInfo) + break; + } + case JSType::COMPLETION_RECORD: { + CHECK_DUMP_FILEDS(Record::SIZE, CompletionRecord::SIZE, 2) + JSHandle comRecord = factory->NewCompletionRecord(0, globalEnv->GetEmptyArray()); + DUMP_FOR_HANDLE(comRecord) + break; + } + case JSType::MACHINE_CODE_OBJECT: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), MachineCode::DATA_OFFSET, 1) + JSHandle machineCode = factory->NewMachineCodeObject(16, nullptr); + DUMP_FOR_HANDLE(machineCode) + break; + } + case JSType::ECMA_MODULE: { + CHECK_DUMP_FILEDS(ECMAObject::SIZE, EcmaModule::SIZE, 1) + JSHandle ecmaModule = factory->NewEmptyEcmaModule(); + DUMP_FOR_HANDLE(ecmaModule) + break; + } + default: + LOG_ECMA_MEM(ERROR) << "JSType " << static_cast(type) << " cannot be dumped."; + UNREACHABLE(); + break; + } + } +#undef NEW_OBJECT_AND_DUMP +#undef DUMP_FOR_HANDLE +} } // namespace panda::test diff --git a/ecmascript/ic/ic_handler.h b/ecmascript/ic/ic_handler.h index e87af94..51b6c6f 100644 --- a/ecmascript/ic/ic_handler.h +++ b/ecmascript/ic/ic_handler.h @@ -122,6 +122,7 @@ public: ACCESSORS(TransitionHClass, TRANSITION_HCLASS_OFFSET, SIZE) DECL_VISIT_OBJECT(HANDLER_INFO_OFFSET, SIZE) + DECL_DUMP() }; class PrototypeHandler : public TaggedObject { @@ -146,6 +147,7 @@ public: ACCESSORS(Holder, HOLDER_OFFSET, SIZE) DECL_VISIT_OBJECT(HANDLER_INFO_OFFSET, SIZE) + DECL_DUMP() }; } // namespace panda::ecmascript #endif // ECMASCRIPT_IC_IC_HANDLER_H diff --git a/ecmascript/ic/property_box.h b/ecmascript/ic/property_box.h index 180834c..23d4521 100644 --- a/ecmascript/ic/property_box.h +++ b/ecmascript/ic/property_box.h @@ -42,6 +42,7 @@ public: ACCESSORS(Value, VALUE_OFFSET, SIZE); DECL_VISIT_OBJECT(VALUE_OFFSET, SIZE) + DECL_DUMP() }; } // namespace ecmascript } // namespace panda diff --git a/ecmascript/ic/proto_change_details.h b/ecmascript/ic/proto_change_details.h index c212fd2..8ddeb5f 100644 --- a/ecmascript/ic/proto_change_details.h +++ b/ecmascript/ic/proto_change_details.h @@ -35,6 +35,7 @@ public: static constexpr size_t HAS_CHANGED_OFFSET = TaggedObjectSize(); SET_GET_PRIMITIVE_FIELD(HasChanged, bool, HAS_CHANGED_OFFSET, SIZE); + DECL_DUMP() }; class ProtoChangeDetails : public TaggedObject { @@ -51,6 +52,7 @@ public: ACCESSORS(RegisterIndex, REGISTER_INDEX_OFFSET, SIZE); DECL_VISIT_OBJECT(CHANGE_LISTENER_OFFSET, SIZE) + DECL_DUMP() }; class ChangeListener : public WeakVector { diff --git a/ecmascript/js_collator.h b/ecmascript/js_collator.h index 77b2188..e757119 100644 --- a/ecmascript/js_collator.h +++ b/ecmascript/js_collator.h @@ -54,6 +54,7 @@ public: ACCESSORS(BoundCompare, BOUND_COMPARE_OFFSET, SIZE) DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, ICU_FIELD_OFFSET, SIZE) + DECL_DUMP() icu::Collator *GetIcuCollator() const { diff --git a/ecmascript/js_date_time_format.h b/ecmascript/js_date_time_format.h index eaedd7f..77f8d49 100644 --- a/ecmascript/js_date_time_format.h +++ b/ecmascript/js_date_time_format.h @@ -107,6 +107,7 @@ public: ACCESSORS(BoundFormat, BOUND_FORMAT_OFFSET, SIZE) DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, LOCALE_OFFSET, SIZE) + DECL_DUMP() icu::Locale *GetIcuLocale() const; void SetIcuLocale(JSThread *thread, const icu::Locale &icuLocale, const DeleteEntryPoint &callback); diff --git a/ecmascript/js_for_in_iterator.h b/ecmascript/js_for_in_iterator.h index a33690a..e5a6a45 100644 --- a/ecmascript/js_for_in_iterator.h +++ b/ecmascript/js_for_in_iterator.h @@ -52,6 +52,7 @@ public: ACCESSORS(RemainingKeys, REMAINING_KEYS_OFFSET, SIZE) DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, OBJECT_OFFSET, SIZE) + DECL_DUMP() }; } // namespace panda::ecmascript diff --git a/ecmascript/js_function.h b/ecmascript/js_function.h index 316399e..5d6f3b2 100644 --- a/ecmascript/js_function.h +++ b/ecmascript/js_function.h @@ -431,6 +431,7 @@ public: ACCESSORS(Collator, COLLATOR_OFFSET, SIZE); DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, NUMBER_FORMAT_OFFSET, SIZE) + DECL_DUMP() }; } // namespace panda::ecmascript diff --git a/ecmascript/js_function_extra_info.h b/ecmascript/js_function_extra_info.h index 5c789e8..3640489 100644 --- a/ecmascript/js_function_extra_info.h +++ b/ecmascript/js_function_extra_info.h @@ -36,6 +36,7 @@ public: ACCESSORS(Data, DATA_OFFSET, SIZE); DECL_VISIT_OBJECT(CALL_BACK_OFFSET, SIZE) + DECL_DUMP() }; } // namespace panda::ecmascript #endif diff --git a/ecmascript/js_generator_object.h b/ecmascript/js_generator_object.h index faf1796..effe125 100644 --- a/ecmascript/js_generator_object.h +++ b/ecmascript/js_generator_object.h @@ -46,6 +46,7 @@ public: ACCESSORS(LexicalEnv, GENERATOR_LEXICALENV_OFFSET, SIZE) DECL_VISIT_OBJECT(GENERATOR_REGS_ARRAY_OFFSET, SIZE) + DECL_DUMP() }; class JSGeneratorObject : public JSObject { @@ -84,6 +85,7 @@ public: } DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, GENERATOR_STATE_OFFSET, SIZE) + DECL_DUMP() }; class JSAsyncFuncObject : public JSGeneratorObject { @@ -98,6 +100,7 @@ public: ACCESSORS(Promise, GENERATOR_PROMISE_OFFSET, SIZE); DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSGeneratorObject, GENERATOR_PROMISE_OFFSET, SIZE) + DECL_DUMP() }; } // namespace ecmascript } // namespace panda diff --git a/ecmascript/js_intl.h b/ecmascript/js_intl.h index d4c91a6..2b1de0b 100644 --- a/ecmascript/js_intl.h +++ b/ecmascript/js_intl.h @@ -32,6 +32,7 @@ public: ACCESSORS(FallbackSymbol, FALLBACK_SYMBOL, SIZE) DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, FALLBACK_SYMBOL, SIZE) + DECL_DUMP() }; } // namespace panda::ecmascript diff --git a/ecmascript/js_locale.h b/ecmascript/js_locale.h index e553afe..7606423 100644 --- a/ecmascript/js_locale.h +++ b/ecmascript/js_locale.h @@ -159,6 +159,7 @@ public: ACCESSORS(IcuField, ICU_FIELD_OFFSET, SIZE) DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, ICU_FIELD_OFFSET, SIZE) + DECL_DUMP() icu::Locale *GetIcuLocale() const { diff --git a/ecmascript/js_number_format.h b/ecmascript/js_number_format.h index bf0791b..2493064 100644 --- a/ecmascript/js_number_format.h +++ b/ecmascript/js_number_format.h @@ -83,6 +83,7 @@ public: ACCESSORS(IcuField, BOUND_FORMAT_OFFSET, SIZE) DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, LOCALE_OFFSET, SIZE) + DECL_DUMP() icu::number::LocalizedNumberFormatter *GetIcuCallTarget() const { diff --git a/ecmascript/js_object.h b/ecmascript/js_object.h index 9bfbb1a..b426a36 100644 --- a/ecmascript/js_object.h +++ b/ecmascript/js_object.h @@ -591,7 +591,7 @@ public: ACCESSORS(Properties, PROPERTIES_OFFSET, ELEMENTS_OFFSET); ACCESSORS(Elements, ELEMENTS_OFFSET, SIZE); - + DECL_VISIT_OBJECT_FOR_JS_OBJECT(ECMAObject, PROPERTIES_OFFSET, SIZE) DECL_DUMP() diff --git a/ecmascript/js_plural_rules.h b/ecmascript/js_plural_rules.h index 1e87fa0..4faa731 100644 --- a/ecmascript/js_plural_rules.h +++ b/ecmascript/js_plural_rules.h @@ -50,6 +50,7 @@ public: ACCESSORS(IcuNF, ICU_NUMBER_FORMAT_OFFSET, SIZE) DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, LOCALE_OFFSET, SIZE) + DECL_DUMP() icu::number::LocalizedNumberFormatter *GetIcuNumberFormatter() const; diff --git a/ecmascript/js_realm.h b/ecmascript/js_realm.h index 0372898..6d20119 100644 --- a/ecmascript/js_realm.h +++ b/ecmascript/js_realm.h @@ -29,6 +29,9 @@ public: static constexpr size_t VALUE_OFFSET = JSObject::SIZE; ACCESSORS(Value, VALUE_OFFSET, GLOBAL_ENV_OFFSET) ACCESSORS(GlobalEnv, GLOBAL_ENV_OFFSET, SIZE) + + DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, VALUE_OFFSET, SIZE) + DECL_DUMP() }; } // namespace panda::ecmascript diff --git a/ecmascript/js_relative_time_format.h b/ecmascript/js_relative_time_format.h index 2c5fdc2..418c6f4 100644 --- a/ecmascript/js_relative_time_format.h +++ b/ecmascript/js_relative_time_format.h @@ -55,6 +55,7 @@ public: ACCESSORS(IcuField, ICU_FIELD_OFFSET, SIZE) DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, LOCALE_OFFSET, SIZE) + DECL_DUMP() // 14.1.1 InitializeRelativeTimeFormat ( relativeTimeFormat, locales, options ) static JSHandle InitializeRelativeTimeFormat( diff --git a/ecmascript/js_string_iterator.h b/ecmascript/js_string_iterator.h index d13304b..db465bf 100644 --- a/ecmascript/js_string_iterator.h +++ b/ecmascript/js_string_iterator.h @@ -38,6 +38,7 @@ public: ACCESSORS(StringIteratorNextIndex, STRING_ITERATOR_NEXT_INDEX_OFFSET, SIZE) DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, ITERATED_STRING_OFFSET, SIZE) + DECL_DUMP() }; } // namespace ecmascript } // namespace panda diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index b72cd79..2d018f1 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -332,7 +332,8 @@ public: void DumpTaggedValue(JSThread *thread, std::ostream &os) const DUMP_API_ATTR; void Dump(JSThread *thread, std::ostream &os) const DUMP_API_ATTR; void Dump(JSThread *thread) const DUMP_API_ATTR; - void DumpForSnapshot(JSThread *thread, std::vector> &vec) const; + void DumpForSnapshot(JSThread *thread, std::vector> &vec, + bool isVmMode = true) const; static void DumpVal(JSThread *thread, JSTaggedType val) DUMP_API_ATTR; private: diff --git a/ecmascript/mem/heap_roots-inl.h b/ecmascript/mem/heap_roots-inl.h index e72b2de..29e4980 100644 --- a/ecmascript/mem/heap_roots-inl.h +++ b/ecmascript/mem/heap_roots-inl.h @@ -30,6 +30,7 @@ #include "ecmascript/js_array_iterator.h" #include "ecmascript/js_arraybuffer.h" #include "ecmascript/js_async_function.h" +#include "ecmascript/js_collator.h" #include "ecmascript/js_dataview.h" #include "ecmascript/js_date.h" #include "ecmascript/js_date_time_format.h" @@ -43,8 +44,10 @@ #include "ecmascript/js_map_iterator.h" #include "ecmascript/js_number_format.h" #include "ecmascript/js_object-inl.h" +#include "ecmascript/js_plural_rules.h" #include "ecmascript/js_primitive_ref.h" #include "ecmascript/js_promise.h" +#include "ecmascript/js_realm.h" #include "ecmascript/js_regexp.h" #include "ecmascript/js_relative_time_format.h" #include "ecmascript/js_set.h" @@ -53,6 +56,7 @@ #include "ecmascript/js_typed_array.h" #include "ecmascript/js_weak_container.h" #include "ecmascript/mem/heap_roots.h" +#include "ecmascript/mem/machine_code.h" #include "ecmascript/mem/mem.h" namespace panda::ecmascript { @@ -196,6 +200,7 @@ void HeapRootManager::MarkObjectBody(TaggedObject *object, JSHClass *klass, cons break; case JSType::TAGGED_ARRAY: case JSType::TAGGED_DICTIONARY: + case JSType::TEMPLATE_MAP: TaggedArray::Cast(object)->VisitRangeSlot(visitor); break; case JSType::GLOBAL_ENV: @@ -225,9 +230,6 @@ void HeapRootManager::MarkObjectBody(TaggedObject *object, JSHClass *klass, cons case JSType::PROTOTYPE_INFO: ProtoChangeDetails::Cast(object)->VisitRangeSlot(visitor); break; - case JSType::TEMPLATE_MAP: - UNREACHABLE(); - break; case JSType::PROMISE_CAPABILITY: PromiseCapability::Cast(object)->VisitRangeSlot(visitor); break; @@ -282,6 +284,17 @@ void HeapRootManager::MarkObjectBody(TaggedObject *object, JSHClass *klass, cons case JSType::JS_INTL_BOUND_FUNCTION: JSIntlBoundFunction::Cast(object)->VisitRangeSlot(visitor); break; + case JSType::JS_REALM: + JSRealm::Cast(object)->VisitRangeSlot(visitor); + break; + case JSType::JS_COLLATOR: + JSCollator::Cast(object)->VisitRangeSlot(visitor); + break; + case JSType::JS_PLURAL_RULES: + JSPluralRules::Cast(object)->VisitRangeSlot(visitor); + break; + case JSType::MACHINE_CODE_OBJECT: + break; default: UNREACHABLE(); } diff --git a/ecmascript/mem/machine_code.h b/ecmascript/mem/machine_code.h index 0181d96..ea9ff8a 100644 --- a/ecmascript/mem/machine_code.h +++ b/ecmascript/mem/machine_code.h @@ -36,6 +36,8 @@ public: ACCESSORS(InstructionSizeInBytes, INS_SIZE_OFFSET, DATA_OFFSET); static constexpr size_t SIZE = DATA_OFFSET; + DECL_DUMP() + uintptr_t GetDataOffsetAddress(void) { return reinterpret_cast(this) + DATA_OFFSET; diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index f155af6..c8adba7 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -104,7 +104,6 @@ using base::ErrorType; using DeleteEntryPoint = void (*)(void *, void *); enum class RemoveSlots { YES, NO }; - class ObjectFactory { public: explicit ObjectFactory(JSThread *thread, Heap *heap); @@ -358,6 +357,11 @@ public: JSHandle NewFromString(EcmaString *str); JSHandle ConcatFromString(const JSHandle &prefix, const JSHandle &suffix); + // used for creating Function + JSHandle NewJSObject(const JSHandle &jshclass); + // used for creating jshclass in Builtins, Function, Class_Linker + JSHandle NewEcmaDynClass(uint32_t size, JSType type, const JSHandle &prototype); + private: friend class GlobalEnv; friend class GlobalEnvConstants; @@ -419,11 +423,6 @@ private: JSHandle NewEcmaDynClass(uint32_t size, JSType type); // used for creating jshclass in GlobalEnv, EcmaVM JSHandle NewEcmaDynClass(JSHClass *hclass, uint32_t size, JSType type); - // used for creating jshclass in Builtins, Function, Class_Linker - JSHandle NewEcmaDynClass(uint32_t size, JSType type, const JSHandle &prototype); - - // used for creating Function - JSHandle NewJSObject(const JSHandle &jshclass); // used to create nonmovable js_object JSHandle NewNonMovableJSObject(const JSHandle &jshclass); -- Gitee From d7dcdcb629ddcdbe246b5cb6abfd492ccb982a32 Mon Sep 17 00:00:00 2001 From: Gongyuhang <517563583@qq.com> Date: Thu, 21 Oct 2021 20:27:21 +0800 Subject: [PATCH 052/115] add js_dataview_test.cpp and js_array_iterator_test.cpp Signed-off-by: Gongyuhang <517563583@qq.com> --- ecmascript/tests/BUILD.gn | 58 ++++++ ecmascript/tests/js_array_iterator_test.cpp | 178 ++++++++++++++++ ecmascript/tests/js_dataview_test.cpp | 214 ++++++++++++++++++++ 3 files changed, 450 insertions(+) create mode 100644 ecmascript/tests/js_array_iterator_test.cpp create mode 100644 ecmascript/tests/js_dataview_test.cpp diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index c8abe68..2ed7da7 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -179,6 +179,33 @@ host_unittest_action("GlueRegsTest") { } } +host_unittest_action("JsArrayIteratorTest") { + module_out_path = module_output_path + + sources = [ + # test file + "js_array_iterator_test.cpp", + ] + + configs = [ + "//ark/js_runtime:ecma_test_config", + "//ark/js_runtime:ark_jsruntime_public_config", # should add before + # arkruntime_public_config + "//ark/js_runtime:ark_jsruntime_common_config", + "$ark_root/runtime:arkruntime_public_config", + ] + + deps = [ + "$ark_root/libpandabase:libarkbase", + "//ark/js_runtime:libark_jsruntime_test", + sdk_libc_secshared_dep, + ] + + if (!is_standard_system) { + deps += [ "$ark_root/runtime:libarkruntime" ] + } +} + host_unittest_action("JsArrayTest") { module_out_path = module_output_path @@ -206,6 +233,33 @@ host_unittest_action("JsArrayTest") { } } +host_unittest_action("JsDataviewTest") { + module_out_path = module_output_path + + sources = [ + # test file + "js_dataview_test.cpp", + ] + + configs = [ + "//ark/js_runtime:ecma_test_config", + "//ark/js_runtime:ark_jsruntime_public_config", # should add before + # arkruntime_public_config + "//ark/js_runtime:ark_jsruntime_common_config", + "$ark_root/runtime:arkruntime_public_config", + ] + + deps = [ + "$ark_root/libpandabase:libarkbase", + "//ark/js_runtime:libark_jsruntime_test", + sdk_libc_secshared_dep, + ] + + if (!is_standard_system) { + deps += [ "$ark_root/runtime:libarkruntime" ] + } +} + host_unittest_action("JsDateTest") { module_out_path = module_output_path @@ -922,7 +976,9 @@ group("unittest") { ":GlueRegsTest", ":HugeObjectTest", ":JsArgumentsTest", + ":JsArrayIteratorTest", ":JsArrayTest", + ":JsDataviewTest", ":JsDateTest", ":JsForinIteratorTest", ":JsFunctionTest", @@ -963,7 +1019,9 @@ group("host_unittest") { ":GlueRegsTestAction", ":HugeObjectTestAction", ":JsArgumentsTestAction", + ":JsArrayIteratorTestAction", ":JsArrayTestAction", + ":JsDataviewTestAction", ":JsDateTestAction", ":JsForinIteratorTestAction", ":JsFunctionTestAction", diff --git a/ecmascript/tests/js_array_iterator_test.cpp b/ecmascript/tests/js_array_iterator_test.cpp new file mode 100644 index 0000000..74f768c --- /dev/null +++ b/ecmascript/tests/js_array_iterator_test.cpp @@ -0,0 +1,178 @@ +/* + * 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/global_env.h" +#include "ecmascript/js_array_iterator.h" +#include "ecmascript/js_array.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class JSArrayIteratorTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + PandaVM *instance {nullptr}; + ecmascript::EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; +}; + +/* + * Feature: JSArrayIterator + * Function: SetIteratedArray + * SubFunction: GetIteratedArray + * FunctionPoints: Set Iterated Array + * CaseDescription: Call the "SetIteratedArray" function, check whether the result returned through "GetIteratedArray" + * function from the JSArrayIterator is within expectations. + */ +HWTEST_F_L0(JSArrayIteratorTest, SetIteratedArray) +{ + EcmaVM *ecmaVMPtr = thread->GetEcmaVM(); + ObjectFactory *factory = ecmaVMPtr->GetFactory(); + + uint32_t arrayFrom1[10] = {0, 6, 8, 99, 200, 1, -1, -199, 33, 100}; + uint32_t arrayFrom2[10] = {1111, 3211, 737, 0, 1267, 174, 2763, 832, 11, 93}; + int numArrayFrom1 = sizeof(arrayFrom1)/sizeof(arrayFrom1[0]); + int numArrayFrom2 = sizeof(arrayFrom2)/sizeof(arrayFrom2[0]); + JSHandle handleTaggedArrayFrom1(factory->NewTaggedArray(numArrayFrom1)); + JSHandle handleTaggedArrayFrom2(factory->NewTaggedArray(numArrayFrom2)); + for (int i = 0; i < numArrayFrom1; i++) { + handleTaggedArrayFrom1->Set(thread, i, JSTaggedValue(arrayFrom1[i])); + } + for (int i = 0; i < numArrayFrom2; i++) { + handleTaggedArrayFrom2->Set(thread, i, JSTaggedValue(arrayFrom2[i])); + } + JSHandle handleJSObjectTaggedArrayFrom1(JSArray::CreateArrayFromList(thread, handleTaggedArrayFrom1)); + JSHandle handleJSObjectTaggedArrayFrom2(JSArray::CreateArrayFromList(thread, handleTaggedArrayFrom2)); + + // Call "SetIteratedArray" function through "NewJSArrayIterator" function of "object_factory.cpp". + JSHandle handleJSArrayIter = factory->NewJSArrayIterator(handleJSObjectTaggedArrayFrom1, + IterationKind::KEY); + + JSHandle handleJSArrayTo1(thread, JSArray::Cast(handleJSArrayIter->GetIteratedArray().GetTaggedObject())); + EXPECT_EQ(handleJSArrayTo1->GetArrayLength(), numArrayFrom1); + for (int i = 0; i < numArrayFrom1; i++) { + EXPECT_EQ(JSArray::FastGetPropertyByValue(thread, JSHandle(handleJSArrayTo1), i)->GetNumber(), + arrayFrom1[i]); + } + + // Call "SetIteratedArray" function in this HWTEST_F_L0. + handleJSArrayIter->SetIteratedArray(thread, handleJSObjectTaggedArrayFrom2); + + JSHandle handleJSArrayTo2(thread, JSArray::Cast(handleJSArrayIter->GetIteratedArray().GetTaggedObject())); + EXPECT_EQ(handleJSArrayTo2->GetArrayLength(), numArrayFrom2); + for (int i = 0; i < numArrayFrom2; i++) { + EXPECT_EQ(JSArray::FastGetPropertyByValue(thread, JSHandle(handleJSArrayTo2), i)->GetNumber(), + arrayFrom2[i]); + } +} + +/* + * Feature: JSArrayIterator + * Function: SetNextIndex + * SubFunction: GetNextIndex + * FunctionPoints: Set Next Index + * CaseDescription: Call the "SetNextIndex" function, check whether the result returned through "GetNextIndex" function + * from the JSArrayIterator is within expectations. + */ +HWTEST_F_L0(JSArrayIteratorTest, SetNextIndex) +{ + EcmaVM *ecmaVMPtr = thread->GetEcmaVM(); + ObjectFactory *factory = ecmaVMPtr->GetFactory(); + + uint32_t array[10] = {0, 6, 8, 99, 200, 1, -1, -199, 33, 100}; + int numArray = sizeof(array)/sizeof(array[0]); + JSHandle handleTaggedArray(factory->NewTaggedArray(numArray)); + for (int i = 0; i < numArray; i++) { + handleTaggedArray->Set(thread, i, JSTaggedValue(array[i])); + } + JSHandle handleJSObjectTaggedArray(JSArray::CreateArrayFromList(thread, handleTaggedArray)); + + // Call "SetNextIndex" function through "NewJSArrayIterator" function of "object_factory.cpp". + JSHandle handleJSArrayIter = factory->NewJSArrayIterator(handleJSObjectTaggedArray, + IterationKind::KEY); + EXPECT_EQ(handleJSArrayIter->GetNextIndex().GetNumber(), 0); + + int testQuantity = 100; + for (int i = 1; i <= testQuantity; i++) { + JSHandle handleTagValNextIndex(thread, JSTaggedValue(i)); + + // Call "SetNextIndex" function in this HWTEST_F_L0. + handleJSArrayIter->SetNextIndex(thread, handleTagValNextIndex); + EXPECT_EQ(handleJSArrayIter->GetNextIndex().GetNumber(), i); + } +} + +/* + * Feature: JSArrayIterator + * Function: SetIterationKind + * SubFunction: GetIterationKind + * FunctionPoints: Set Iteration Kind + * CaseDescription: Call the "SetIterationKind" function, check whether the result returned through "GetIterationKind" + * function from the JSArrayIterator is within expectations. + */ +HWTEST_F_L0(JSArrayIteratorTest, SetIterationKind) +{ + EcmaVM *ecmaVMPtr = thread->GetEcmaVM(); + ObjectFactory *factory = ecmaVMPtr->GetFactory(); + + uint32_t array[10] = {0, 6, 8, 99, 200, 1, -1, -199, 33, 100}; + int numArray = sizeof(array)/sizeof(array[0]); + JSHandle handleTaggedArray(factory->NewTaggedArray(numArray)); + for (int i = 0; i < numArray; i++) { + handleTaggedArray->Set(thread, i, JSTaggedValue(array[i])); + } + JSHandle handleTagVal0(thread, JSTaggedValue(0)); + JSHandle handleTagVal1(thread, JSTaggedValue(1)); + JSHandle handleTagVal2(thread, JSTaggedValue(2)); + JSHandle handleJSObjectTaggedArray(JSArray::CreateArrayFromList(thread, handleTaggedArray)); + + // Call "SetIterationKind" function through "NewJSArrayIterator" function of "object_factory.cpp". + JSHandle handleJSArrayIter = factory->NewJSArrayIterator(handleJSObjectTaggedArray, + IterationKind::KEY); + EXPECT_EQ(handleJSArrayIter->GetIterationKind().GetNumber(), 0); + handleJSArrayIter = factory->NewJSArrayIterator(handleJSObjectTaggedArray, IterationKind::VALUE); + EXPECT_EQ(handleJSArrayIter->GetIterationKind().GetNumber(), 1); + handleJSArrayIter = factory->NewJSArrayIterator(handleJSObjectTaggedArray, IterationKind::KEY_AND_VALUE); + EXPECT_EQ(handleJSArrayIter->GetIterationKind().GetNumber(), 2); + + // Call "SetIterationKind" function in this HWTEST_F_L0. + handleJSArrayIter->SetIterationKind(thread, handleTagVal0); + EXPECT_EQ(handleJSArrayIter->GetIterationKind().GetNumber(), 0); + handleJSArrayIter->SetIterationKind(thread, handleTagVal1); + EXPECT_EQ(handleJSArrayIter->GetIterationKind().GetNumber(), 1); + handleJSArrayIter->SetIterationKind(thread, handleTagVal2); + EXPECT_EQ(handleJSArrayIter->GetIterationKind().GetNumber(), 2); +} +} // namespace panda::ecmascript diff --git a/ecmascript/tests/js_dataview_test.cpp b/ecmascript/tests/js_dataview_test.cpp new file mode 100644 index 0000000..2c15663 --- /dev/null +++ b/ecmascript/tests/js_dataview_test.cpp @@ -0,0 +1,214 @@ +/* + * 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/global_env.h" +#include "ecmascript/js_arraybuffer.h" +#include "ecmascript/js_dataview.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class JSDataViewTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + PandaVM *instance {nullptr}; + ecmascript::EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; +}; + +/* + * Feature: JSDataView + * Function: GetElementSize + * SubFunction: N/A + * FunctionPoints: Get ElementSize + * CaseDescription: Check whether the returned value through "GetElementSize" function is within expectations. + */ +HWTEST_F_L0(JSDataViewTest, GetElementSize) +{ + EXPECT_EQ(JSDataView::GetElementSize(DataViewType::INT8), 1); + EXPECT_EQ(JSDataView::GetElementSize(DataViewType::UINT8), 1); + EXPECT_EQ(JSDataView::GetElementSize(DataViewType::UINT8_CLAMPED), 1); + EXPECT_EQ(JSDataView::GetElementSize(DataViewType::INT16), 2); + EXPECT_EQ(JSDataView::GetElementSize(DataViewType::UINT16), 2); + EXPECT_EQ(JSDataView::GetElementSize(DataViewType::INT32), 4); + EXPECT_EQ(JSDataView::GetElementSize(DataViewType::UINT32), 4); + EXPECT_EQ(JSDataView::GetElementSize(DataViewType::FLOAT32), 4); + EXPECT_EQ(JSDataView::GetElementSize(DataViewType::FLOAT64), 8); +} + +/* + * Feature: JSDataView + * Function: SetDataView + * SubFunction: GetDataView + * FunctionPoints: Set DataView + * CaseDescription: Check whether the returned value through "GetDataView" function is within expectations after + * calling "SetDataView" function. + */ +HWTEST_F_L0(JSDataViewTest, SetDataView) +{ + EcmaVM *ecmaVMPtr = thread->GetEcmaVM(); + ObjectFactory *factory = ecmaVMPtr->GetFactory(); + JSHandle handleGlobalEnv = ecmaVMPtr->GetGlobalEnv(); + + int32_t lengthDataArrayBuf = 8; + int32_t offsetDataView = 4; + int32_t lengthDataView = 4; + JSHandle handleFuncArrayBuf(handleGlobalEnv->GetArrayBufferFunction()); + JSHandle handleTagValFuncArrayBuf(handleFuncArrayBuf); + JSHandle handleArrayBuf( + factory->NewJSObjectByConstructor(handleFuncArrayBuf, handleTagValFuncArrayBuf)); + handleArrayBuf->SetArrayBufferByteLength(thread, JSTaggedValue(lengthDataArrayBuf)); + + // Call "SetDataView" function through "NewJSDataView" function of "object_factory.cpp" + JSHandle handleDataView = factory->NewJSDataView(handleArrayBuf, offsetDataView, + lengthDataView); + EXPECT_TRUE(handleDataView->GetDataView().IsTrue()); + + // Call "SetDataView" function in this HWTEST_F_L0. + handleDataView->SetDataView(thread, JSTaggedValue::False()); + EXPECT_TRUE(handleDataView->GetDataView().IsFalse()); + handleDataView->SetDataView(thread, JSTaggedValue::True()); + EXPECT_TRUE(handleDataView->GetDataView().IsTrue()); +} + +/* + * Feature: JSDataView + * Function: SetViewedArrayBuffer + * SubFunction: GetViewedArrayBuffer + * FunctionPoints: Set ViewedArrayBuffer + * CaseDescription: Check whether the returned value through "GetViewedArrayBuffer" function is within expectations + * after calling "SetViewedArrayBuffer" function. + */ +HWTEST_F_L0(JSDataViewTest, SetViewedArrayBuffer) +{ + EcmaVM *ecmaVMPtr = thread->GetEcmaVM(); + ObjectFactory *factory = ecmaVMPtr->GetFactory(); + JSHandle handleFuncArrayBuf(ecmaVMPtr->GetGlobalEnv()->GetArrayBufferFunction()); + JSHandle handleTagValFuncArrayBuf(handleFuncArrayBuf); + + int32_t lengthDataArrayBuf1 = 8; + int32_t lengthDataArrayBuf2 = 16; + int32_t offsetDataView = 4; + int32_t lengthDataView = 4; + JSHandle handleArrayBuf1( + factory->NewJSObjectByConstructor(handleFuncArrayBuf, handleTagValFuncArrayBuf)); + JSHandle handleArrayBuf2( + factory->NewJSObjectByConstructor(handleFuncArrayBuf, handleTagValFuncArrayBuf)); + handleArrayBuf1->SetArrayBufferByteLength(thread, JSTaggedValue(lengthDataArrayBuf1)); + handleArrayBuf2->SetArrayBufferByteLength(thread, JSTaggedValue(lengthDataArrayBuf2)); + + // Call "SetViewedArrayBuffer" function through "NewJSDataView" function of "object_factory.cpp" + JSHandle handleDataView = factory->NewJSDataView(handleArrayBuf1, offsetDataView, + lengthDataView); + JSHandle handleTagValDataViewFrom1(thread, handleArrayBuf1.GetTaggedValue()); + JSHandle handleTagValDataViewTo1(thread, handleDataView->GetViewedArrayBuffer()); + EXPECT_TRUE(JSTaggedValue::Equal(thread, handleTagValDataViewFrom1, handleTagValDataViewTo1)); + + // Call "SetViewedArrayBuffer" function in this HWTEST_F_L0. + handleDataView->SetViewedArrayBuffer(thread, handleArrayBuf2.GetTaggedValue()); + JSHandle handleTagValDataViewFrom2(thread, handleArrayBuf2.GetTaggedValue()); + JSHandle handleTagValDataViewTo2(thread, handleDataView->GetViewedArrayBuffer()); + EXPECT_TRUE(JSTaggedValue::Equal(thread, handleTagValDataViewFrom2, handleTagValDataViewTo2)); + EXPECT_FALSE(JSTaggedValue::Equal(thread, handleTagValDataViewFrom1, handleTagValDataViewFrom2)); +} + +/* + * Feature: JSDataView + * Function: SetByteLength + * SubFunction: GetByteLength + * FunctionPoints: Set ByteLength + * CaseDescription: Check whether the returned value through "GetByteLength" function is within expectations after + * calling "SetByteLength" function. + */ +HWTEST_F_L0(JSDataViewTest, SetByteLength) +{ + EcmaVM *ecmaVMPtr = thread->GetEcmaVM(); + ObjectFactory *factory = ecmaVMPtr->GetFactory(); + JSHandle handleFuncArrayBuf(ecmaVMPtr->GetGlobalEnv()->GetArrayBufferFunction()); + JSHandle handleTagValFuncArrayBuf(handleFuncArrayBuf); + + int32_t lengthDataArrayBuf = 8; + int32_t offsetDataView = 4; + int32_t lengthDataView1 = 4; + int32_t lengthDataView2 = 2; + JSHandle handleTagValLengthDataView2(thread, JSTaggedValue(lengthDataView2)); + JSHandle handleArrayBuf( + factory->NewJSObjectByConstructor(handleFuncArrayBuf, handleTagValFuncArrayBuf)); + handleArrayBuf->SetArrayBufferByteLength(thread, JSTaggedValue(lengthDataArrayBuf)); + + // Call "SetByteLength" function through "NewJSDataView" function of "object_factory.cpp" + JSHandle handleDataView = factory->NewJSDataView(handleArrayBuf, offsetDataView, + lengthDataView1); + EXPECT_EQ(handleDataView->GetByteLength().GetNumber(), lengthDataView1); + + // Call "SetByteLength" function in this HWTEST_F_L0. + handleDataView->SetByteLength(thread, handleTagValLengthDataView2); + EXPECT_EQ(handleDataView->GetByteLength().GetNumber(), lengthDataView2); +} + +/* + * Feature: JSDataView + * Function: SetByteOffset + * SubFunction: GetByteOffset + * FunctionPoints: Set ByteOffset + * CaseDescription: Check whether the returned value through "GetByteOffset" function is within expectations after + * calling "SetByteOffset" function. + */ +HWTEST_F_L0(JSDataViewTest, SetByteOffset) +{ + EcmaVM *ecmaVMPtr = thread->GetEcmaVM(); + ObjectFactory *factory = ecmaVMPtr->GetFactory(); + JSHandle handleFuncArrayBuf1(ecmaVMPtr->GetGlobalEnv()->GetArrayBufferFunction()); + JSHandle handleTagValFuncArrayBuf1(handleFuncArrayBuf1); + + int32_t lengthDataArrayBuf = 8; + int32_t offsetDataView1 = 4; + int32_t offsetDataView2 = 6; + int32_t lengthDataView = 2; + JSHandle handleTagValOffsetDataView2(thread, JSTaggedValue(offsetDataView2)); + JSHandle handleArrayBuf( + factory->NewJSObjectByConstructor(handleFuncArrayBuf1, handleTagValFuncArrayBuf1)); + handleArrayBuf->SetArrayBufferByteLength(thread, JSTaggedValue(lengthDataArrayBuf)); + + // Call "SetByteOffset" function through "NewJSDataView" function of "object_factory.cpp" + JSHandle handleDataView = factory->NewJSDataView(handleArrayBuf, offsetDataView1, + lengthDataView); + EXPECT_EQ(handleDataView->GetByteOffset().GetNumber(), offsetDataView1); + + // Call "SetByteOffset" function in this HWTEST_F_L0. + handleDataView->SetByteOffset(thread, handleTagValOffsetDataView2); + EXPECT_EQ(handleDataView->GetByteOffset().GetNumber(), offsetDataView2); +} +} // namespace panda::ecmascript -- Gitee From 385111298d6b8fb3e0d0d39c9e17875244f61e8d Mon Sep 17 00:00:00 2001 From: Gongyuhang <517563583@qq.com> Date: Thu, 21 Oct 2021 20:34:04 +0800 Subject: [PATCH 053/115] change JsDataview to JsDataView Signed-off-by: Gongyuhang <517563583@qq.com> --- ecmascript/tests/BUILD.gn | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index 2ed7da7..ce53651 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -233,7 +233,7 @@ host_unittest_action("JsArrayTest") { } } -host_unittest_action("JsDataviewTest") { +host_unittest_action("JsDataViewTest") { module_out_path = module_output_path sources = [ @@ -978,7 +978,7 @@ group("unittest") { ":JsArgumentsTest", ":JsArrayIteratorTest", ":JsArrayTest", - ":JsDataviewTest", + ":JsDataViewTest", ":JsDateTest", ":JsForinIteratorTest", ":JsFunctionTest", @@ -1021,7 +1021,7 @@ group("host_unittest") { ":JsArgumentsTestAction", ":JsArrayIteratorTestAction", ":JsArrayTestAction", - ":JsDataviewTestAction", + ":JsDataViewTestAction", ":JsDateTestAction", ":JsForinIteratorTestAction", ":JsFunctionTestAction", -- Gitee From dafdd642a688b3609985c2a3d38c4030a81824a4 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Thu, 21 Oct 2021 16:56:38 +0800 Subject: [PATCH 054/115] copy all testcase resources and fix codestyle Signed-off-by: wengchangcheng --- BUILD.gn | 13 ++++++++----- ecmascript/builtins/builtins_promise.cpp | 11 +++++------ ecmascript/ecma_module.cpp | 2 +- ecmascript/interpreter/fast_runtime_stub-inl.h | 16 ++++++++-------- test/copy_resource.py | 13 ++++++------- 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 61a2103..042bdd5 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -436,7 +436,7 @@ source_set("libark_jsruntime_test_static") { sources += intl_sources deps = [ - ":copy_resource_xml", + ":copy_ark_resource", "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", "$ark_root/runtime:arkruntime_header_deps", @@ -478,25 +478,28 @@ ohos_shared_library("libark_jsruntime_test") { subsystem_name = "test" } -action("copy_resource_xml") { +action("copy_ark_resource") { deps = [] script = "//ark/js_runtime/test/copy_resource.py" - src_path = "//ark/js_runtime/test/resource/js_runtime/" + src_path = "//ark/js_runtime/test/resource/js_runtime" src_xml = "ohos_test.xml" dst_path = "//ark/test/resource/js_runtime/" args = [ "--src-path", - rebase_path(src_path), + rebase_path("${src_path}/"), "--src-xml", src_xml, "--dst-path", rebase_path(dst_path), ] - inputs = [ src_path + src_xml ] + inputs = [ + src_path, + "${src_path}/${src_xml}", + ] outputs = [ "$target_out_dir" ] } diff --git a/ecmascript/builtins/builtins_promise.cpp b/ecmascript/builtins/builtins_promise.cpp index 663bd1d..5cdd765 100644 --- a/ecmascript/builtins/builtins_promise.cpp +++ b/ecmascript/builtins/builtins_promise.cpp @@ -399,14 +399,13 @@ JSTaggedValue BuiltinsPromise::PerformPromiseThen(JSThread *thread, const JSHand if (JSTaggedValue::SameValue(promise->GetPromiseState(), JSTaggedValue(static_cast(PromiseStatus::PENDING)))) { JSHandle fulfillReactions(thread, promise->GetPromiseFulfillReactions()); - auto result = - JSTaggedValue(TaggedQueue::Push(thread, fulfillReactions, JSHandle::Cast(fulfillReaction))); - promise->SetPromiseFulfillReactions(thread, result); + TaggedQueue *newQueue = + TaggedQueue::Push(thread, fulfillReactions, JSHandle::Cast(fulfillReaction)); + promise->SetPromiseFulfillReactions(thread, JSTaggedValue(newQueue)); JSHandle rejectReactions(thread, promise->GetPromiseRejectReactions()); - result = - JSTaggedValue(TaggedQueue::Push(thread, rejectReactions, JSHandle::Cast(rejectReaction))); - promise->SetPromiseRejectReactions(thread, result); + newQueue = TaggedQueue::Push(thread, rejectReactions, JSHandle::Cast(rejectReaction)); + promise->SetPromiseRejectReactions(thread, JSTaggedValue(newQueue)); } else if (JSTaggedValue::SameValue(promise->GetPromiseState(), JSTaggedValue(static_cast(PromiseStatus::FULFILLED)))) { JSHandle argv = factory->NewTaggedArray(2); // 2: 2 means two args stored in array diff --git a/ecmascript/ecma_module.cpp b/ecmascript/ecma_module.cpp index cebd2c0..edeaadc 100644 --- a/ecmascript/ecma_module.cpp +++ b/ecmascript/ecma_module.cpp @@ -61,7 +61,7 @@ void EcmaModule::RemoveItem(const JSThread *thread, JSHandle module, JSHandle moduleItems(data); int entry = moduleItems->FindEntry(itemName.GetTaggedValue()); if (entry != -1) { - NameDictionary *newDict = NameDictionary::Remove(thread, moduleItems, entry); // discard return + NameDictionary *newDict = NameDictionary::Remove(thread, moduleItems, entry); module->SetNameDictionary(thread, JSTaggedValue(newDict)); } } diff --git a/ecmascript/interpreter/fast_runtime_stub-inl.h b/ecmascript/interpreter/fast_runtime_stub-inl.h index 7d2faab..055ba3b 100644 --- a/ecmascript/interpreter/fast_runtime_stub-inl.h +++ b/ecmascript/interpreter/fast_runtime_stub-inl.h @@ -880,9 +880,9 @@ bool FastRuntimeStub::SetPropertyByName(JSThread *thread, JSTaggedValue receiver if (receiver.IsJSGlobalObject()) { [[maybe_unused]] EcmaHandleScope handleScope(thread); - JSHandle dict_handle(thread, properties); + JSHandle dictHandle(thread, properties); // globalobj have no internal accessor - GlobalDictionary::InvalidatePropertyBox(thread, dict_handle, indexOrEntry, attr); + GlobalDictionary::InvalidatePropertyBox(thread, dictHandle, indexOrEntry, attr); return true; } @@ -961,7 +961,7 @@ bool FastRuntimeStub::SetGlobalOwnProperty(JSThread *thread, JSTaggedValue recei JSHandle keyHandle(thread, key); JSHandle valHandle(thread, value); JSHandle objHandle(thread, obj); - JSHandle dict_handle(thread, GlobalDictionary::Create(thread)); + JSHandle dictHandle(thread, GlobalDictionary::Create(thread)); // Add PropertyBox to global dictionary ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); @@ -971,7 +971,7 @@ bool FastRuntimeStub::SetGlobalOwnProperty(JSThread *thread, JSTaggedValue recei attr.SetBoxType(boxType); GlobalDictionary *properties = - GlobalDictionary::PutIfAbsent(thread, dict_handle, keyHandle, JSHandle(boxHandle), attr); + GlobalDictionary::PutIfAbsent(thread, dictHandle, keyHandle, JSHandle(boxHandle), attr); objHandle->SetProperties(thread, JSTaggedValue(properties)); return true; } @@ -983,8 +983,8 @@ bool FastRuntimeStub::SetGlobalOwnProperty(JSThread *thread, JSTaggedValue recei if (!attr.IsAccessor()) { if (attr.IsWritable()) { // globalobj have no internal accessor - JSHandle dict_handle(thread, dict); - GlobalDictionary::InvalidatePropertyBox(thread, dict_handle, entry, attr); + JSHandle dictHandle(thread, dict); + GlobalDictionary::InvalidatePropertyBox(thread, dictHandle, entry, attr); return true; } } @@ -1011,7 +1011,7 @@ bool FastRuntimeStub::SetGlobalOwnProperty(JSThread *thread, JSTaggedValue recei JSHandle keyHandle(thread, key); JSHandle valHandle(thread, value); JSHandle objHandle(thread, obj); - JSHandle dict_handle(thread, dict); + JSHandle dictHandle(thread, dict); // Add PropertyBox to global dictionary ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); @@ -1021,7 +1021,7 @@ bool FastRuntimeStub::SetGlobalOwnProperty(JSThread *thread, JSTaggedValue recei attr.SetBoxType(boxType); GlobalDictionary *properties = - GlobalDictionary::PutIfAbsent(thread, dict_handle, keyHandle, JSHandle(boxHandle), attr); + GlobalDictionary::PutIfAbsent(thread, dictHandle, keyHandle, JSHandle(boxHandle), attr); objHandle->SetProperties(thread, JSTaggedValue(properties)); return true; } diff --git a/test/copy_resource.py b/test/copy_resource.py index b6b3a10..dfaa369 100755 --- a/test/copy_resource.py +++ b/test/copy_resource.py @@ -35,21 +35,20 @@ def parse_args(): return args -def copy_xml(args): - """copy resource xml to test direction.""" +def copy_res(args): + """copy resources to test direction.""" src_xml_file = os.path.join(args.src_path, args.src_xml) - dst_xml_file = os.path.join(args.dst_path, args.src_xml) if not os.path.isfile(src_xml_file): print(args.src_xml + " not exist.") return - if not os.path.exists(args.dst_path): - os.makedirs(args.dst_path) + if os.path.exists(args.dst_path): + shutil.rmtree(args.dst_path) - shutil.copyfile(src_xml_file, dst_xml_file) + shutil.copytree(args.src_path, args.dst_path) if __name__ == '__main__': input_args = parse_args() - copy_xml(input_args) + copy_res(input_args) -- Gitee From 5c77f230c3137db2139f2b1a3f8e0a679fac01f1 Mon Sep 17 00:00:00 2001 From: Mingliang Zeng Date: Thu, 21 Oct 2021 16:50:24 +0800 Subject: [PATCH 055/115] Add Circuit IR specification Signed-off-by: Mingliang Zeng --- .../compiler/circuit_ir_specification.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 ecmascript/compiler/circuit_ir_specification.md diff --git a/ecmascript/compiler/circuit_ir_specification.md b/ecmascript/compiler/circuit_ir_specification.md new file mode 100644 index 0000000..4f0a573 --- /dev/null +++ b/ecmascript/compiler/circuit_ir_specification.md @@ -0,0 +1,45 @@ +# Circuit IR specification + +## General design + +Circuit IR is like a circuit diagram, which is good at representing the intrinsic logic of a computation process. The circuit diagram is a directed graph: [logic gates](https://en.wikipedia.org/wiki/Logic_gate) are nodes, wires are directed edges. Circuit IR describes semantic of programs in a language-neutral and target-neutral way, targeting multi-language and multi-target support. The design of Circuit IR has a great emphasis on compilation speed (for JIT), code optimization (on both high and low levels), and canonicalization (unique representation for same intrinsic logic). + +Circuit IR splits a program into two major parts: [sequential logic](https://en.wikipedia.org/wiki/Sequential_logic) part and [combinational logic](https://en.wikipedia.org/wiki/Combinational_logic) part: + +* The **sequential logic** part is a subgraph of Circuit IR which is similar to the underlying control flow graph (CFG) of the program, and gates in this part are named **state gates** (since they acted like a [finite state machine](https://en.wikipedia.org/wiki/Finite-state_machine) (FSM)). Wires that connect two state gates represent possible state transitions of the FSM, and they are named **state wires**. + +* The **combinational logic** part is the other subgraph of Circuit IR which represents all computations in a program using a directed acyclic graph (DAG), and gates in this part are named **computation gates**. A computation gate can do simple things such as adding two integer values, or complex things such as calling a function (and thus make a change to the global memory). Most of **computation gates** will take some values as input and output a value. These values can be transferred by **data wires**. Some computation gates will load from or store to the global memory, so they should be executed non-simultaneously and in some order that will not violate memory dependencies (such as RAW, WAR and WAW). Addressing this issue, **dependency wires** are introduced to constrain the possible execution order of such computations. When a computation gate has multiple dependencies, an auxiliary gate `DEPEND_AND` is used to merge dependencies. + +In traditional [SSA](https://en.wikipedia.org/wiki/Static_single_assignment_form) form IR (e.g. LLVM IR), each instruction is placed inside a node of CFG (basic block), and all instructions in a basic block are [linearly ordered](https://en.wikipedia.org/wiki/Total_order). However, in Circuit IR, computation gates are not tied to state gates, and they are [partially ordered](https://en.wikipedia.org/wiki/Partially_ordered_set) by wires. Sequential logic part and combinational logic part are loosely coupled, they only interact in three ways: + +* State gates that have multiple transitions (corresponding to multiple control flow branches) such as `IF_BRANCH` and `SWITCH_BRANCH` will need an input value computed from combinational logic part to select which next state the FSM will transit to. + +* Similar to the Φ functions in traditional SSA form IR, there are **[selector](https://en.wikipedia.org/wiki/Multiplexer) gates** such as `VALUE_SELECTOR_INT64` and `DEPEND_SELECTOR` that select a data or dependency path based on the state transition action of the FSM. Selector gates are affiliated (many-to-one) to `MERGE` state gates (which have several transition sources), and take several values or dependencies from computation part as input, and will select a value or dependency from input as output, based on which state transition action is taken. + +* In some cases, a computation gate with side effect (i.e. may store to the global memory) should not be executed before a specific branch state transition action is taken. Addressing this problem, **[relay](https://en.wikipedia.org/wiki/Relay) gates** `DEPEND_RELAY` are introduced. They take a state gate (the target of action) as input, and reinterpret it as a kind of memory dependency that can be used by computation gates with side effect. + +Loose coupling of sequential logic part and combinational logic part can benefit compilation speed, code optimization. Firstly, most of IR passes can focus on only one part and will not be interfered by the other part, so the implementation will be simpler. In addition, some special and important code optimizations such as (register pressure sensitive) loop invariant code motion and code sink can be done in the IR scheduling phrase (without furthermore IR analysis or modification), thus they will not couple with other code optimizations and can be done perfectly. Last but not least, less coupling means more canonicalization, this implies fewer branches in the implementation of IR optimization algorithms. + +There are several gates named **root gates** in Circuit IR. Root gates are representing starting/ending vertices of the IR graph, or registering lists of starting/ending vertices of the IR graph. IR Passes usually traverse a part of all gates (forwardly or reversely) starting from root gates. Explanations of Root gates are listed below: + +* `STATE_ENTRY`: representing the initial state of the sequential logic part (for traversing forwardly from beginning to ending) + +* `DEPEND_ENTRY`: the origin of dependency flows of the entire circuit + +* `RETURN_LIST`: registering all terminal states (for traversing reversely from ending to beginning) + +* `CONSTANT_LIST` `ARG_LIST`: registering all value origins such as constants and arguments (they are special computation gates that do not depend on other values) + +## Type system + +### Levels of types + +There are two levels of types of values in Circuit IR: + +* Primary types: This level of types are **low level** (closer to ISA) and **fundamental** for Circuit IR, and are determined by the opcode of gates. They describe the bit width of values, and which type of registers (integer or float) should such values be put into. Circuit IR can be translated to correct machine code with only primary types. All primary types are `INT1` `INT8` `INT16` `INT32` `INT64` `FLOAT32` `FLOAT64`. Note that pointer type is not included in primary types, since pointers are not different from integers in common ISAs. The concept of pointers should be expressed in secondary types. + +* Secondary types: This level of types are **high level** (closer to language) and **optional**. They can provide information for program analysis, code optimization and garbage collection (generating stack maps). Secondary types can represent categories of possible bit vectors the value can be (e.g. `JS_ANY` `JS_BOOLEAN` `JS_NULL` `JS_UNDEFINED` `JS_NUMBER` `JS_SMI` etc. builtin categories and user defined bit vectors categories), and possible classes of objects the value points to as a pointer (e.g. `JS_HEAP_OBJECT` `JS_STRING` `JS_OBJECT` `JS_ARRAY` `JS_TYPED_ARRAY` `JS_UINT8_ARRAY` etc. builtin classes and user defined classes). + +### Type inference + +Primary types are all set during construction of Circuit IR, so no furthermore type inference is required. Circuit IR verifier will verify consistency of primary types. Secondary types can be not precisely set during construction (e.g. leaving many intermediate values as `JS_ANY`), and the compiler should be able to do type inference (and check consistency) following data flow paths (e.g. `c:=JS_ADD(a:, b:) -> c:=JS_ADD(a:, b:)` and `c:=VALUE_SELECTOR(a:, b:) -> c:=JS_ADD(a:, b:)`), thus the secondary types will be more precise than initially set at the end. -- Gitee From 7882a0eeae7c79f02ed1a8a1d6e1795c56cda721 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Fri, 22 Oct 2021 10:20:45 +0800 Subject: [PATCH 056/115] review fix Signed-off-by: surpassgoodchao --- ecmascript/compiler/llvm/llvm.patch | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm.patch b/ecmascript/compiler/llvm/llvm.patch index 7c5e6c3..b4c021c 100644 --- a/ecmascript/compiler/llvm/llvm.patch +++ b/ecmascript/compiler/llvm/llvm.patch @@ -19,10 +19,10 @@ index 0e85afa82c7..43756892e40 100644 add_definitions(-DBUILD_EXAMPLES) endif(LLVM_BUILD_EXAMPLES) diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp -index 1da20371caf..d6f82baa7d7 100644 +index 1da20371caf..26a11139817 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp -@@ -1168,6 +1168,27 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, +@@ -1168,6 +1168,34 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, else MFI.setOffsetAdjustment(-StackSize); } @@ -35,7 +35,14 @@ index 1da20371caf..d6f82baa7d7 100644 + .getFnAttribute("js-stub-call") + .getValueAsString() + .getAsInteger(10, marker);//marker 1 break frame -+ ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ if (marker == JS_ENTRY_FRAME_MARK) { ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ } + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) + .addImm(marker) + .setMIFlag(MachineInstr::FrameSetup); @@ -50,7 +57,7 @@ index 1da20371caf..d6f82baa7d7 100644 // For EH funclets, only allocate enough space for outgoing calls. Save the // NumBytes value that we would've used for the parent frame. -@@ -1635,6 +1656,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, +@@ -1635,6 +1663,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, uint64_t SEHStackAllocAmt = NumBytes; if (HasFP) { @@ -78,7 +85,7 @@ index 1da20371caf..d6f82baa7d7 100644 // Pop EBP. BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), MachineFramePtr) -@@ -1993,8 +2035,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( +@@ -1993,8 +2042,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( if (hasFP(MF)) { // emitPrologue always spills frame register the first thing. -- Gitee From 208b0408dacc1928901008c55aa830da06622ecf Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Fri, 22 Oct 2021 10:25:15 +0800 Subject: [PATCH 057/115] code review Signed-off-by: surpassgoodchao --- ecmascript/runtime_trampolines.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 08b564a..2f471ef 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -54,17 +54,17 @@ public: class CallRuntimeTrampolinesScope { public: CallRuntimeTrampolinesScope(JSThread *thread, uintptr_t *newFp, uintptr_t *fp) - :oldRbp_(nullptr), + :oldFramePointer_(nullptr), thread_(thread) { oldRuntimeTrampolinesFP_ = thread->GetRuntimeTrampolinesFP(); thread->SetRuntimeTrampolinesFP(fp); JSTaggedType *cursp = const_cast(thread->GetCurrentSPFrame()); - oldRbp_ = static_cast(static_cast(cursp)); + oldFramePointer_ = static_cast(static_cast(cursp)); JSTaggedType *newSp = static_cast(static_cast(newFp)); thread_->SetCurrentSPFrame(newSp); // print newfp and type for debug - std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " oldRbp_ : " << oldRbp_ + std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " oldFramePointer_ : " << oldFramePointer_ << std::endl; FrameType type = *(reinterpret_cast( reinterpret_cast(newFp) + FrameConst::kFrameType)); @@ -73,17 +73,17 @@ public: ~CallRuntimeTrampolinesScope() { // print oldfp and type for debug - std::cout << "~CallRuntimeTrampolinesScope oldRbp_: " << oldRbp_ << + std::cout << "~CallRuntimeTrampolinesScope oldFramePointer_: " << oldFramePointer_ << " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; FrameType type = *(reinterpret_cast( - reinterpret_cast(oldRbp_) + FrameConst::kFrameType)); + reinterpret_cast(oldFramePointer_) + FrameConst::kFrameType)); std::cout << __FUNCTION__ << "type = " << as_integer(type) << std::endl; - JSTaggedType *oldSp = static_cast(static_cast(oldRbp_)); + JSTaggedType *oldSp = static_cast(static_cast(oldFramePointer_)); thread_->SetCurrentSPFrame(oldSp); thread_->SetRuntimeTrampolinesFP(oldRuntimeTrampolinesFP_); } private: - uintptr_t *oldRbp_; + uintptr_t *oldFramePointer_; JSThread *thread_; uintptr_t *oldRuntimeTrampolinesFP_; }; -- Gitee From 0f8494745da14b343957b0f78bc32749683975ca Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Fri, 22 Oct 2021 10:37:32 +0800 Subject: [PATCH 058/115] review Signed-off-by: surpassgoodchao --- ecmascript/compiler/llvm/llvm.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm.patch b/ecmascript/compiler/llvm/llvm.patch index b4c021c..feb0a80 100644 --- a/ecmascript/compiler/llvm/llvm.patch +++ b/ecmascript/compiler/llvm/llvm.patch @@ -19,7 +19,7 @@ index 0e85afa82c7..43756892e40 100644 add_definitions(-DBUILD_EXAMPLES) endif(LLVM_BUILD_EXAMPLES) diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp -index 1da20371caf..26a11139817 100644 +index 1da20371caf..436819f0c44 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -1168,6 +1168,34 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, @@ -96,7 +96,7 @@ index 1da20371caf..26a11139817 100644 + .getFnAttribute("js-stub-call") + .getValueAsString() + .getAsInteger(10, marker);//marker 1 break frame -+ if (marker == 1) { ++ if (marker == JS_ENTRY_FRAME_MARK) { + SpillSlotOffset -= 3 * SlotSize; // add type and thread.fp + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -- Gitee From bb2aebfbe3a58bbc152d5e3f1c2146bf44764c50 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Fri, 22 Oct 2021 11:00:53 +0800 Subject: [PATCH 059/115] review Signed-off-by: surpassgoodchao --- ecmascript/frames.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 08261a5..b100766 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -220,7 +220,7 @@ #define POINTER_CAST(fp, type) static_cast(static_cast(fp) #define GET_PREV_FP(fp) reinterpret_cast(*(fp)) #else -#define GET_CURRETN_FP(fp) +#define GET_CURRETN_FP(fp) #define POINTER_CAST(fp, type) static_cast(static_cast(fp)) #define GET_PREV_FP(fp) reinterpret_cast(*(POINTER_CAST(fp, uintptr_t *))) #endif -- Gitee From dea2c9eb2ecc226403ad55a5fab3251ae911b9b7 Mon Sep 17 00:00:00 2001 From: surpassgoodchao Date: Fri, 22 Oct 2021 15:08:04 +0800 Subject: [PATCH 060/115] review bug Signed-off-by: surpassgoodchao --- ecmascript/compiler/llvm/llvm.patch | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm.patch b/ecmascript/compiler/llvm/llvm.patch index feb0a80..0305ea9 100644 --- a/ecmascript/compiler/llvm/llvm.patch +++ b/ecmascript/compiler/llvm/llvm.patch @@ -19,10 +19,10 @@ index 0e85afa82c7..43756892e40 100644 add_definitions(-DBUILD_EXAMPLES) endif(LLVM_BUILD_EXAMPLES) diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp -index 1da20371caf..436819f0c44 100644 +index 1da20371caf..657d215e31e 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp -@@ -1168,6 +1168,34 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, +@@ -1168,6 +1168,25 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, else MFI.setOffsetAdjustment(-StackSize); } @@ -43,21 +43,12 @@ index 1da20371caf..436819f0c44 100644 + .addImm(marker) + .setMIFlag(MachineInstr::FrameSetup); + } -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); -+ /*reserve thread.fp */ -+ if (marker == JS_ENTRY_FRAME_MARK) { -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); -+ } + } +#endif // For EH funclets, only allocate enough space for outgoing calls. Save the // NumBytes value that we would've used for the parent frame. -@@ -1635,6 +1663,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, +@@ -1635,6 +1654,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, uint64_t SEHStackAllocAmt = NumBytes; if (HasFP) { @@ -85,7 +76,7 @@ index 1da20371caf..436819f0c44 100644 // Pop EBP. BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), MachineFramePtr) -@@ -1993,8 +2042,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( +@@ -1993,8 +2033,41 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( if (hasFP(MF)) { // emitPrologue always spills frame register the first thing. @@ -101,12 +92,20 @@ index 1da20371caf..436819f0c44 100644 + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ CalleeSavedFrameSize += 16; ++ if (Is64Bit) { ++ CalleeSavedFrameSize += 16; ++ } else { ++ CalleeSavedFrameSize += 8; ++ } + } else { + SpillSlotOffset -= 2 * SlotSize; // add type + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ CalleeSavedFrameSize += 8; ++ if (Is64Bit) { ++ CalleeSavedFrameSize += 8; ++ } else { ++ CalleeSavedFrameSize += 4; ++ } + } + } else { + SpillSlotOffset -= SlotSize; // add type and thread.fp -- Gitee From fa2e1af3a8a3b0cadf0846e363d191918b0fbe74 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 22 Oct 2021 16:41:46 +0800 Subject: [PATCH 061/115] code review Signed-off-by: songzhengchao --- ecmascript/compiler/llvm/llvm.patch | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm.patch b/ecmascript/compiler/llvm/llvm.patch index 0305ea9..bfd0c41 100644 --- a/ecmascript/compiler/llvm/llvm.patch +++ b/ecmascript/compiler/llvm/llvm.patch @@ -19,7 +19,7 @@ index 0e85afa82c7..43756892e40 100644 add_definitions(-DBUILD_EXAMPLES) endif(LLVM_BUILD_EXAMPLES) diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp -index 1da20371caf..657d215e31e 100644 +index 1da20371caf..e0264827556 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -1168,6 +1168,25 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, @@ -76,7 +76,7 @@ index 1da20371caf..657d215e31e 100644 // Pop EBP. BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), MachineFramePtr) -@@ -1993,8 +2033,41 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( +@@ -1993,8 +2033,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( if (hasFP(MF)) { // emitPrologue always spills frame register the first thing. @@ -92,20 +92,12 @@ index 1da20371caf..657d215e31e 100644 + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ if (Is64Bit) { -+ CalleeSavedFrameSize += 16; -+ } else { -+ CalleeSavedFrameSize += 8; -+ } ++ CalleeSavedFrameSize += (2 * SlotSize); + } else { + SpillSlotOffset -= 2 * SlotSize; // add type + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ if (Is64Bit) { -+ CalleeSavedFrameSize += 8; -+ } else { -+ CalleeSavedFrameSize += 4; -+ } ++ CalleeSavedFrameSize += SlotSize; + } + } else { + SpillSlotOffset -= SlotSize; // add type and thread.fp -- Gitee From 61feb4e2f49f1b8335ac5dc58e13a40bede0b438 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 22 Oct 2021 16:54:30 +0800 Subject: [PATCH 062/115] code review Signed-off-by: songzhengchao --- ecmascript/runtime_trampolines.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 2f471ef..a7e451a 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -57,7 +57,7 @@ public: :oldFramePointer_(nullptr), thread_(thread) { - oldRuntimeTrampolinesFP_ = thread->GetRuntimeTrampolinesFP(); + lastOptCallRuntimePc_ = thread->GetRuntimeTrampolinesFP(); thread->SetRuntimeTrampolinesFP(fp); JSTaggedType *cursp = const_cast(thread->GetCurrentSPFrame()); oldFramePointer_ = static_cast(static_cast(cursp)); @@ -80,12 +80,12 @@ public: std::cout << __FUNCTION__ << "type = " << as_integer(type) << std::endl; JSTaggedType *oldSp = static_cast(static_cast(oldFramePointer_)); thread_->SetCurrentSPFrame(oldSp); - thread_->SetRuntimeTrampolinesFP(oldRuntimeTrampolinesFP_); + thread_->SetRuntimeTrampolinesFP(lastOptCallRuntimePc_); } private: uintptr_t *oldFramePointer_; JSThread *thread_; - uintptr_t *oldRuntimeTrampolinesFP_; + uintptr_t *lastOptCallRuntimePc_; }; } // namespace panda::ecmascript #endif \ No newline at end of file -- Gitee From 32e1e3341c0864bd759beac79387ce7b95ddd258 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 22 Oct 2021 16:59:45 +0800 Subject: [PATCH 063/115] code review Signed-off-by: songzhengchao --- ecmascript/js_thread.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 249835a..c7d855f 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -199,13 +199,13 @@ public: void IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor); - uintptr_t* GetRuntimeTrampolinesFP() const + uintptr_t* GetLastOptCallRuntimePc_() const { - return runtimeTrampolinesFP; + return lastOptCallRuntimePc_; } - void SetRuntimeTrampolinesFP(uintptr_t* pc) + void SetLastOptCallRuntimePc_(uintptr_t* pc) { - runtimeTrampolinesFP = pc; + lastOptCallRuntimePc_ = pc; } private: NO_COPY_SEMANTIC(JSThread); @@ -241,7 +241,7 @@ private: bool stableArrayElementsGuardians_ {true}; GlobalEnvConstants globalConst_; // Place-Holder InternalCallParams *internalCallParams_ {nullptr}; - uintptr_t *runtimeTrampolinesFP = 0; + uintptr_t *lastOptCallRuntimePc_ = {nullptr}; friend class EcmaHandleScope; friend class GlobalHandleCollection; -- Gitee From 08f5ec2df07bf5e8d7b8b8044bd47631340742c5 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 22 Oct 2021 17:20:06 +0800 Subject: [PATCH 064/115] code review Signed-off-by: songzhengchao --- ecmascript/js_thread.h | 4 ++-- ecmascript/runtime_trampolines.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index c7d855f..4681e88 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -199,11 +199,11 @@ public: void IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor); - uintptr_t* GetLastOptCallRuntimePc_() const + uintptr_t* GetLastOptCallRuntimePc() const { return lastOptCallRuntimePc_; } - void SetLastOptCallRuntimePc_(uintptr_t* pc) + void SetLastOptCallRuntimePc(uintptr_t* pc) { lastOptCallRuntimePc_ = pc; } diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index a7e451a..e620835 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -53,12 +53,12 @@ public: class CallRuntimeTrampolinesScope { public: - CallRuntimeTrampolinesScope(JSThread *thread, uintptr_t *newFp, uintptr_t *fp) + CallRuntimeTrampolinesScope(JSThread *thread, uintptr_t *newFp, uintptr_t *pc) :oldFramePointer_(nullptr), thread_(thread) { - lastOptCallRuntimePc_ = thread->GetRuntimeTrampolinesFP(); - thread->SetRuntimeTrampolinesFP(fp); + lastOptCallRuntimePc_ = thread->GetLastOptCallRuntimePc(); + thread->SetLastOptCallRuntimePc(pc); JSTaggedType *cursp = const_cast(thread->GetCurrentSPFrame()); oldFramePointer_ = static_cast(static_cast(cursp)); JSTaggedType *newSp = static_cast(static_cast(newFp)); @@ -80,7 +80,7 @@ public: std::cout << __FUNCTION__ << "type = " << as_integer(type) << std::endl; JSTaggedType *oldSp = static_cast(static_cast(oldFramePointer_)); thread_->SetCurrentSPFrame(oldSp); - thread_->SetRuntimeTrampolinesFP(lastOptCallRuntimePc_); + thread_->SetLastOptCallRuntimePc(lastOptCallRuntimePc_); } private: uintptr_t *oldFramePointer_; -- Gitee From ec9a4ad922395c060ed4df35563cafe03edc8a07 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 22 Oct 2021 17:29:41 +0800 Subject: [PATCH 065/115] code review Signed-off-by: songzhengchao --- @ | 17 +++++++++++++++++ ecmascript/js_thread.h | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 @ diff --git a/@ b/@ new file mode 100644 index 0000000..d169158 --- /dev/null +++ b/@ @@ -0,0 +1,17 @@ +code review + +Signed-off-by: songzhengchao + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# Date: Fri Oct 22 17:20:06 2021 +0800 +# +# On branch bug_fix_2 +# Your branch is ahead of 'origin/bug_fix_2' by 1 commit. +# (use "git push" to publish your local commits) +# +# Changes to be committed: +# modified: ecmascript/js_thread.h +# modified: ecmascript/runtime_trampolines.h +# diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 4681e88..ed6103f 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -241,7 +241,7 @@ private: bool stableArrayElementsGuardians_ {true}; GlobalEnvConstants globalConst_; // Place-Holder InternalCallParams *internalCallParams_ {nullptr}; - uintptr_t *lastOptCallRuntimePc_ = {nullptr}; + uintptr_t *lastOptCallRuntimePc_ {nullptr}; friend class EcmaHandleScope; friend class GlobalHandleCollection; -- Gitee From 48604623d95775ca44c87133077bfbbb989c838f Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 22 Oct 2021 17:37:58 +0800 Subject: [PATCH 066/115] code review Signed-off-by: songzhengchao --- ecmascript/runtime_trampolines.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index e620835..7b2d1f4 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -54,17 +54,17 @@ public: class CallRuntimeTrampolinesScope { public: CallRuntimeTrampolinesScope(JSThread *thread, uintptr_t *newFp, uintptr_t *pc) - :oldFramePointer_(nullptr), + :lastOptCallRuntimeFp_(nullptr), thread_(thread) { lastOptCallRuntimePc_ = thread->GetLastOptCallRuntimePc(); thread->SetLastOptCallRuntimePc(pc); JSTaggedType *cursp = const_cast(thread->GetCurrentSPFrame()); - oldFramePointer_ = static_cast(static_cast(cursp)); + lastOptCallRuntimeFp_ = static_cast(static_cast(cursp)); JSTaggedType *newSp = static_cast(static_cast(newFp)); thread_->SetCurrentSPFrame(newSp); // print newfp and type for debug - std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " oldFramePointer_ : " << oldFramePointer_ + std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " lastOptCallRuntimeFp_ : " << lastOptCallRuntimeFp_ << std::endl; FrameType type = *(reinterpret_cast( reinterpret_cast(newFp) + FrameConst::kFrameType)); @@ -73,17 +73,17 @@ public: ~CallRuntimeTrampolinesScope() { // print oldfp and type for debug - std::cout << "~CallRuntimeTrampolinesScope oldFramePointer_: " << oldFramePointer_ << + std::cout << "~CallRuntimeTrampolinesScope lastOptCallRuntimeFp_: " << lastOptCallRuntimeFp_ << " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; FrameType type = *(reinterpret_cast( - reinterpret_cast(oldFramePointer_) + FrameConst::kFrameType)); + reinterpret_cast(lastOptCallRuntimeFp_) + FrameConst::kFrameType)); std::cout << __FUNCTION__ << "type = " << as_integer(type) << std::endl; - JSTaggedType *oldSp = static_cast(static_cast(oldFramePointer_)); + JSTaggedType *oldSp = static_cast(static_cast(lastOptCallRuntimeFp_)); thread_->SetCurrentSPFrame(oldSp); thread_->SetLastOptCallRuntimePc(lastOptCallRuntimePc_); } private: - uintptr_t *oldFramePointer_; + uintptr_t *lastOptCallRuntimeFp_; JSThread *thread_; uintptr_t *lastOptCallRuntimePc_; }; -- Gitee From 4fa3c1ff18f5301895c2d3446913184f77ab2847 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 22 Oct 2021 17:47:58 +0800 Subject: [PATCH 067/115] code review Signed-off-by: songzhengchao --- ecmascript/runtime_trampolines.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 7b2d1f4..f8b815d 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -54,17 +54,17 @@ public: class CallRuntimeTrampolinesScope { public: CallRuntimeTrampolinesScope(JSThread *thread, uintptr_t *newFp, uintptr_t *pc) - :lastOptCallRuntimeFp_(nullptr), + :lastFp_(nullptr), thread_(thread) { lastOptCallRuntimePc_ = thread->GetLastOptCallRuntimePc(); thread->SetLastOptCallRuntimePc(pc); JSTaggedType *cursp = const_cast(thread->GetCurrentSPFrame()); - lastOptCallRuntimeFp_ = static_cast(static_cast(cursp)); + lastFp_ = static_cast(static_cast(cursp)); JSTaggedType *newSp = static_cast(static_cast(newFp)); thread_->SetCurrentSPFrame(newSp); // print newfp and type for debug - std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " lastOptCallRuntimeFp_ : " << lastOptCallRuntimeFp_ + std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " lastFp_ : " << lastFp_ << std::endl; FrameType type = *(reinterpret_cast( reinterpret_cast(newFp) + FrameConst::kFrameType)); @@ -73,17 +73,17 @@ public: ~CallRuntimeTrampolinesScope() { // print oldfp and type for debug - std::cout << "~CallRuntimeTrampolinesScope lastOptCallRuntimeFp_: " << lastOptCallRuntimeFp_ << + std::cout << "~CallRuntimeTrampolinesScope lastFp_: " << lastFp_ << " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; FrameType type = *(reinterpret_cast( - reinterpret_cast(lastOptCallRuntimeFp_) + FrameConst::kFrameType)); + reinterpret_cast(lastFp_) + FrameConst::kFrameType)); std::cout << __FUNCTION__ << "type = " << as_integer(type) << std::endl; - JSTaggedType *oldSp = static_cast(static_cast(lastOptCallRuntimeFp_)); + JSTaggedType *oldSp = static_cast(static_cast(lastFp_)); thread_->SetCurrentSPFrame(oldSp); thread_->SetLastOptCallRuntimePc(lastOptCallRuntimePc_); } private: - uintptr_t *lastOptCallRuntimeFp_; + uintptr_t *lastFp_; JSThread *thread_; uintptr_t *lastOptCallRuntimePc_; }; -- Gitee From ff9da6187f7c1ae421f682fa18e44d4e30733da5 Mon Sep 17 00:00:00 2001 From: Gongyuhang <517563583@qq.com> Date: Fri, 22 Oct 2021 19:47:25 +0800 Subject: [PATCH 068/115] chan TesrDownTestCase to TearDownTestCase Signed-off-by: Gongyuhang <517563583@qq.com> --- ecmascript/tests/ecma_module_test.cpp | 2 +- ecmascript/tests/ecma_string_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ecmascript/tests/ecma_module_test.cpp b/ecmascript/tests/ecma_module_test.cpp index f214c0b..c0c924d 100644 --- a/ecmascript/tests/ecma_module_test.cpp +++ b/ecmascript/tests/ecma_module_test.cpp @@ -29,7 +29,7 @@ public: GTEST_LOG_(INFO) << "SetUpTestCase"; } - static void TesrDownTestCase() + static void TearDownTestCase() { GTEST_LOG_(INFO) << "TearDownCase"; } diff --git a/ecmascript/tests/ecma_string_test.cpp b/ecmascript/tests/ecma_string_test.cpp index 7aa808c..1feedb7 100644 --- a/ecmascript/tests/ecma_string_test.cpp +++ b/ecmascript/tests/ecma_string_test.cpp @@ -26,7 +26,7 @@ public: GTEST_LOG_(INFO) << "SetUpTestCase"; } - static void TesrDownTestCase() + static void TearDownTestCase() { GTEST_LOG_(INFO) << "TearDownCase"; } -- Gitee From cf72eb446725638cc0b792e66ddcffa9b3300493 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Mon, 25 Oct 2021 09:26:43 +0800 Subject: [PATCH 069/115] add oat Signed-off-by: songzhengchao --- OAT.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OAT.xml b/OAT.xml index 4513e58..08893e1 100644 --- a/OAT.xml +++ b/OAT.xml @@ -65,7 +65,8 @@ Note:If the text contains special characters, please escape them according to th - + + -- Gitee From b23e476f2eac48f394cb9d85278e860506719318 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Mon, 25 Oct 2021 09:33:01 +0800 Subject: [PATCH 070/115] conflict Signed-off-by: songzhengchao --- ecmascript/mem/heap_roots-inl.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ecmascript/mem/heap_roots-inl.h b/ecmascript/mem/heap_roots-inl.h index eb32956..18afcd4 100644 --- a/ecmascript/mem/heap_roots-inl.h +++ b/ecmascript/mem/heap_roots-inl.h @@ -285,6 +285,17 @@ void HeapRootManager::MarkObjectBody(TaggedObject *object, JSHClass *klass, cons case JSType::MACHINE_CODE_OBJECT: MachineCode::Cast(object)->VisitRangeSlot(visitor); break; + case JSType::JS_REALM: + JSRealm::Cast(object)->VisitRangeSlot(visitor); + break; + case JSType::JS_COLLATOR: + JSCollator::Cast(object)->VisitRangeSlot(visitor); + break; + case JSType::JS_PLURAL_RULES: + JSPluralRules::Cast(object)->VisitRangeSlot(visitor); + break; + case JSType::MACHINE_CODE_OBJECT: + break; default: UNREACHABLE(); } -- Gitee From a4a2970c524e8f17826158d9a23852fc032ef1f2 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Mon, 25 Oct 2021 10:02:13 +0800 Subject: [PATCH 071/115] code review Signed-off-by: songzhengchao --- @ | 17 ----------------- OAT.xml | 1 - 2 files changed, 18 deletions(-) delete mode 100644 @ diff --git a/@ b/@ deleted file mode 100644 index d169158..0000000 --- a/@ +++ /dev/null @@ -1,17 +0,0 @@ -code review - -Signed-off-by: songzhengchao - -# Please enter the commit message for your changes. Lines starting -# with '#' will be ignored, and an empty message aborts the commit. -# -# Date: Fri Oct 22 17:20:06 2021 +0800 -# -# On branch bug_fix_2 -# Your branch is ahead of 'origin/bug_fix_2' by 1 commit. -# (use "git push" to publish your local commits) -# -# Changes to be committed: -# modified: ecmascript/js_thread.h -# modified: ecmascript/runtime_trampolines.h -# diff --git a/OAT.xml b/OAT.xml index 08893e1..487d424 100644 --- a/OAT.xml +++ b/OAT.xml @@ -66,7 +66,6 @@ Note:If the text contains special characters, please escape them according to th - -- Gitee From 5acdd7da207baa8d78eb1e9aa7b20393e0fa68bf Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Mon, 25 Oct 2021 10:04:24 +0800 Subject: [PATCH 072/115] code review Signed-off-by: songzhengchao --- ecmascript/mem/heap_roots-inl.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ecmascript/mem/heap_roots-inl.h b/ecmascript/mem/heap_roots-inl.h index 407027e..ec2769b 100644 --- a/ecmascript/mem/heap_roots-inl.h +++ b/ecmascript/mem/heap_roots-inl.h @@ -284,9 +284,6 @@ void HeapRootManager::MarkObjectBody(TaggedObject *object, JSHClass *klass, cons case JSType::JS_INTL_BOUND_FUNCTION: JSIntlBoundFunction::Cast(object)->VisitRangeSlot(visitor); break; - case JSType::MACHINE_CODE_OBJECT: - MachineCode::Cast(object)->VisitRangeSlot(visitor); - break; case JSType::JS_REALM: JSRealm::Cast(object)->VisitRangeSlot(visitor); break; @@ -297,6 +294,7 @@ void HeapRootManager::MarkObjectBody(TaggedObject *object, JSHClass *klass, cons JSPluralRules::Cast(object)->VisitRangeSlot(visitor); break; case JSType::MACHINE_CODE_OBJECT: + MachineCode::Cast(object)->VisitRangeSlot(visitor); break; default: UNREACHABLE(); -- Gitee From 55e9a917a95bd0605e667a6e2779c5a1403e3cd6 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Mon, 25 Oct 2021 10:25:17 +0800 Subject: [PATCH 073/115] code review Signed-off-by: songzhengchao --- OAT.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OAT.xml b/OAT.xml index 487d424..4513e58 100644 --- a/OAT.xml +++ b/OAT.xml @@ -65,7 +65,7 @@ Note:If the text contains special characters, please escape them according to th - + -- Gitee From ed58c05572f73d59ac378e0c1ca44bb364a02bc9 Mon Sep 17 00:00:00 2001 From: xujie Date: Tue, 26 Oct 2021 10:29:56 +0800 Subject: [PATCH 074/115] fix freeListAllocator Free bug Signed-off-by: xujie --- ecmascript/mem/allocator-inl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecmascript/mem/allocator-inl.h b/ecmascript/mem/allocator-inl.h index f9ddfe7..476839d 100644 --- a/ecmascript/mem/allocator-inl.h +++ b/ecmascript/mem/allocator-inl.h @@ -142,10 +142,10 @@ void FreeListAllocator::Free(uintptr_t begin, uintptr_t end, bool isAdd) { ASSERT(heap_ != nullptr); size_t size = end - begin; + FreeObject::FillFreeObject(heap_->GetEcmaVM(), begin, size); if (UNLIKELY(size < FreeObject::SIZE_OFFSET)) { return; } - FreeObject::FillFreeObject(heap_->GetEcmaVM(), begin, size); freeList_->Free(begin, size, isAdd); } -- Gitee From 30b9c163a53287be57443e9004e424cfe5102178 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Tue, 26 Oct 2021 19:20:18 +0800 Subject: [PATCH 075/115] codedex bug fix Signed-off-by: songzhengchao --- ecmascript/interpreter/frame_handler.cpp | 6 +++--- ecmascript/interpreter/frame_handler.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index a362901..34a0d99 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -239,21 +239,21 @@ void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) c JSTaggedType *current = fp_; while (current) { FrameType type = *(reinterpret_cast( - reinterpret_cast(current) + FrameConst::kFrameType)); + reinterpret_cast(current) + FrameConst::kFrameType)); if (type == FrameType::INTERPRETER_FRAME) { FrameState *state = reinterpret_cast(current) - 1; InterpretedFrameHandler(current).Iterate(v0, v1); current = state->base.prev; } else if (type == FrameType::OPTIMIZED_FRAME) { OptimizedFrameStateBase *state = reinterpret_cast( - reinterpret_cast(current) - + reinterpret_cast(current) - MEMBER_OFFSET(OptimizedFrameStateBase, prev)); OptimizedFrameHandler(reinterpret_cast(current)).Iterate(v0, v1); current = reinterpret_cast(state->prev); } else { ASSERT(type == FrameType::OPTIMIZED_ENTRY_FRAME); OptimizedEntryFrameState *state = reinterpret_cast( - reinterpret_cast(current) - + reinterpret_cast(current) - MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); OptimizedEntryFrameHandler(reinterpret_cast(current)).Iterate(v0, v1); current = reinterpret_cast(state->threadFp); diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index ae44d2f..0da418f 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -92,6 +92,7 @@ private: class FrameIterator { public: explicit FrameIterator(JSTaggedType *fp) : fp_(fp) {} + ~FrameIterator() = default; void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; private: JSTaggedType *fp_ {nullptr}; -- Gitee From 99e4839e8fbe23478643e1bf483e1fbc5bf78a2d Mon Sep 17 00:00:00 2001 From: guobingbing Date: Wed, 27 Oct 2021 09:21:33 +0800 Subject: [PATCH 076/115] solve the issue of 32bit-64bit not the same Signed-off-by: guobingbing Change-Id: Iee2cb3b39ad8d8a073dc2e617102d8833c91095c --- ecmascript/frames.h | 7 ++----- ecmascript/interpreter/frame_handler.cpp | 2 +- ecmascript/runtime_trampolines.h | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/ecmascript/frames.h b/ecmascript/frames.h index b100766..454368e 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -227,7 +227,7 @@ namespace panda::ecmascript { class JSThread; -enum class FrameType: uint64_t { +enum class FrameType: uintptr_t { OPTIMIZED_FRAME = 0, OPTIMIZED_ENTRY_FRAME = 1, INTERPRETER_FRAME = 2, @@ -258,12 +258,9 @@ public: OptimizedFrameStateBase base; }; -constexpr int kSystemPointerSize = sizeof(void*); class FrameConst { public: - uint64_t *prev; - FrameType frameType; - static constexpr int kFrameType = -kSystemPointerSize; + static constexpr size_t FRAME_TYPE_OFFSET = -sizeof(FrameType); }; } // namespace panda::ecmascript #endif // ECMASCRIPT_FRAMES_H \ No newline at end of file diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 34a0d99..4a17664 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -239,7 +239,7 @@ void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) c JSTaggedType *current = fp_; while (current) { FrameType type = *(reinterpret_cast( - reinterpret_cast(current) + FrameConst::kFrameType)); + reinterpret_cast(current) + FrameConst::FRAME_TYPE_OFFSET)); if (type == FrameType::INTERPRETER_FRAME) { FrameState *state = reinterpret_cast(current) - 1; InterpretedFrameHandler(current).Iterate(v0, v1); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index cd76e46..a7c9e11 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -68,7 +68,7 @@ public: std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " lastFp_ : " << lastFp_ << std::endl; FrameType type = *(reinterpret_cast( - reinterpret_cast(newFp) + FrameConst::kFrameType)); + reinterpret_cast(newFp) + FrameConst::FRAME_TYPE_OFFSET)); std::cout << __FUNCTION__ << " type = " << as_integer(type) << std::endl; } ~CallRuntimeTrampolinesScope() @@ -77,7 +77,7 @@ public: std::cout << "~CallRuntimeTrampolinesScope lastFp_: " << lastFp_ << " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; FrameType type = *(reinterpret_cast( - reinterpret_cast(lastFp_) + FrameConst::kFrameType)); + reinterpret_cast(lastFp_) + FrameConst::FRAME_TYPE_OFFSET)); std::cout << __FUNCTION__ << "type = " << as_integer(type) << std::endl; JSTaggedType *oldSp = static_cast(static_cast(lastFp_)); thread_->SetCurrentSPFrame(oldSp); -- Gitee From 2c7c067c1bbbd490cade32d5096c181185ead32c Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Wed, 27 Oct 2021 15:28:52 +0800 Subject: [PATCH 077/115] ark_js_vm support multi pandafile Signed-off-by: wengchangcheng Change-Id: I1c4fbb6895f63ce0414352e71c8756cb0c5064f6 --- ecmascript/js_vm/main.cpp | 28 +++++++++++--------- test/moduletest/helloworld/BUILD.gn | 17 +++++++++++- test/moduletest/helloworld/expect_output.txt | 2 ++ test/moduletest/helloworld/helloworld.js | 1 + test/moduletest/helloworld/second_module.js | 17 ++++++++++++ test/moduletest/helloworld/third_module.js | 16 +++++++++++ test/test_helper.gni | 15 ++++++++++- 7 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 test/moduletest/helloworld/second_module.js create mode 100644 test/moduletest/helloworld/third_module.js diff --git a/ecmascript/js_vm/main.cpp b/ecmascript/js_vm/main.cpp index 9d76603..c03701c 100644 --- a/ecmascript/js_vm/main.cpp +++ b/ecmascript/js_vm/main.cpp @@ -65,7 +65,7 @@ int Main(const int argc, const char **argv) panda::PandArg help("help", false, "Print this message and exit"); panda::PandArg options("options", false, "Print compiler and runtime options"); // tail arguments - panda::PandArg file("file", "", "path to pandafile"); + panda::PandArg files("files", {""}, "path to pandafiles", ":"); panda::PandArg entrypoint("entrypoint", "_GLOBAL::func_main_0", "full name of entrypoint function or method"); panda::PandArgParser paParser; @@ -74,16 +74,16 @@ int Main(const int argc, const char **argv) paParser.Add(&help); paParser.Add(&options); - paParser.PushBackTail(&file); + paParser.PushBackTail(&files); paParser.PushBackTail(&entrypoint); paParser.EnableTail(); paParser.EnableRemainder(); - if (!paParser.Parse(argc, argv) || file.GetValue().empty() || entrypoint.GetValue().empty() || help.GetValue()) { + if (!paParser.Parse(argc, argv) || files.GetValue().empty() || entrypoint.GetValue().empty() || help.GetValue()) { std::cerr << paParser.GetErrorString() << std::endl; std::cerr << "Usage: " << "panda" - << " [OPTIONS] [file] [entrypoint] -- [arguments]" << std::endl; + << " [OPTIONS] [file1:file2:file3] [entrypoint] -- [arguments]" << std::endl; std::cerr << std::endl; std::cerr << "optional arguments:" << std::endl; std::cerr << paParser.GetHelpString() << std::endl; @@ -120,16 +120,20 @@ int Main(const int argc, const char **argv) std::cout << paParser.GetRegularArgs() << std::endl; } - std::string fileName = file.GetValue(); - std::string entry = entrypoint.GetValue(); - EcmaVM *vm = EcmaVM::Cast(runtime->GetPandaVM()); - auto fileNameRef = StringRef::NewFromUtf8(vm, fileName.c_str(), fileName.size()); + + std::string entry = entrypoint.GetValue(); auto entryRef = StringRef::NewFromUtf8(vm, entry.c_str(), entry.size()); - auto res = JSNApi::Execute(vm, fileNameRef, entryRef); - if (!res) { - std::cerr << "Cannot execute panda file '" << fileName << "' with entry '" << entry << "'" << std::endl; - ret = false; + + arg_list_t fileNames = files.GetValue(); + for (const auto &fileName : fileNames) { + auto fileNameRef = StringRef::NewFromUtf8(vm, fileName.c_str(), fileName.size()); + auto res = JSNApi::Execute(vm, fileNameRef, entryRef); + if (!res) { + std::cerr << "Cannot execute panda file '" << fileName << "' with entry '" << entry << "'" << std::endl; + ret = false; + break; + } } if (!Runtime::Destroy()) { diff --git a/test/moduletest/helloworld/BUILD.gn b/test/moduletest/helloworld/BUILD.gn index 1f9c33f..1c00da7 100644 --- a/test/moduletest/helloworld/BUILD.gn +++ b/test/moduletest/helloworld/BUILD.gn @@ -13,6 +13,21 @@ import("//ark/js_runtime/test/test_helper.gni") -host_moduletest_action("helloworld") { +host_moduletest_action("second_module") { + deps = [] +} + +host_moduletest_action("third_module") { deps = [] } + +host_moduletest_action("helloworld") { + extra_modules = [ + "second_module", + "third_module", + ] + deps = [ + ":gen_second_module_abc", + ":gen_third_module_abc", + ] +} diff --git a/test/moduletest/helloworld/expect_output.txt b/test/moduletest/helloworld/expect_output.txt index d53f276..59b7042 100644 --- a/test/moduletest/helloworld/expect_output.txt +++ b/test/moduletest/helloworld/expect_output.txt @@ -12,3 +12,5 @@ # limitations under the License. hello world ! +second_module got: I'm helloworld! +third_module got: I'm second_module! diff --git a/test/moduletest/helloworld/helloworld.js b/test/moduletest/helloworld/helloworld.js index b41a5e9..a08f2c6 100644 --- a/test/moduletest/helloworld/helloworld.js +++ b/test/moduletest/helloworld/helloworld.js @@ -13,4 +13,5 @@ * limitations under the License. */ +var helloworld = "I'm helloworld!" print("hello world !") \ No newline at end of file diff --git a/test/moduletest/helloworld/second_module.js b/test/moduletest/helloworld/second_module.js new file mode 100644 index 0000000..0f42b9a --- /dev/null +++ b/test/moduletest/helloworld/second_module.js @@ -0,0 +1,17 @@ +/* + * 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. + */ + +var second_module = "I'm second_module!" +print("second_module got: " + helloworld) \ No newline at end of file diff --git a/test/moduletest/helloworld/third_module.js b/test/moduletest/helloworld/third_module.js new file mode 100644 index 0000000..e1952b4 --- /dev/null +++ b/test/moduletest/helloworld/third_module.js @@ -0,0 +1,16 @@ +/* + * 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. + */ + +print("third_module got: " + second_module) \ No newline at end of file diff --git a/test/test_helper.gni b/test/test_helper.gni index ad905c2..498344c 100644 --- a/test/test_helper.gni +++ b/test/test_helper.gni @@ -92,6 +92,17 @@ template("host_moduletest_action") { out_puts = [ _test_abc_path_ ] } + _extra_modules_ = [] + if (defined(invoker.extra_modules)) { + foreach(module, invoker.extra_modules) { + _extra_modules_ += [ "$target_out_dir/${module}.abc" ] + } + } + _test_abc_paths_ = rebase_path(_test_abc_path_) + foreach(extra_module, _extra_modules_) { + _test_abc_paths_ += ":" + rebase_path(extra_module) + } + action("${_target_name_}Action") { testonly = true @@ -102,6 +113,7 @@ template("host_moduletest_action") { ":gen_${_target_name_}_abc", _host_jsvm_target_, ] + deps += _deps_ script = "//ark/js_runtime/test/run_ark_executable.py" @@ -109,7 +121,7 @@ template("host_moduletest_action") { "--script-file", rebase_path(_root_out_dir_) + "/ark/ark_js_runtime/ark_js_vm", "--script-args", - rebase_path(_test_abc_path_), + _test_abc_paths_, "--expect-file", rebase_path(_test_expect_path_), "--env-path", @@ -120,6 +132,7 @@ template("host_moduletest_action") { ] inputs = [ _test_abc_path_ ] + inputs += _extra_modules_ outputs = [ "$target_out_dir/${_target_name_}/" ] } -- Gitee From b35952f22a8f6937b8dcb3bf2f6db63640b6c249 Mon Sep 17 00:00:00 2001 From: getingke Date: Sat, 16 Oct 2021 18:06:22 +0800 Subject: [PATCH 078/115] fixed for Set/GetPropertyByValue & test262 case verify Signed-off-by: getingke Change-Id: I06214f39ebff93754edb3d275be4d4d76c1dba0c --- ecmascript/compiler/fast_stub.cpp | 170 ++++++++++- ecmascript/compiler/fast_stub.h | 46 ++- ecmascript/compiler/fast_stub_define.h | 7 +- ecmascript/compiler/gate.cpp | 17 ++ ecmascript/compiler/gate.h | 5 + ecmascript/compiler/llvm_ir_builder.cpp | 20 +- ecmascript/compiler/llvm_mcjit_engine.cpp | 2 +- ecmascript/compiler/stub.cpp | 275 +++++++++++++++++- ecmascript/compiler/stub.h | 67 ++++- ecmascript/compiler/stub_aot_compiler.cpp | 3 +- ecmascript/compiler/stub_aot_compiler.h | 1 + ecmascript/compiler/stub_aot_options.yaml | 2 +- ecmascript/compiler/stub_descriptor.cpp | 44 +++ ecmascript/compiler/tests/stub_tests.cpp | 85 ++++++ ecmascript/ecma_string.h | 13 +- ecmascript/ecma_vm.cpp | 3 + .../interpreter/fast_runtime_stub-inl.h | 14 +- ecmascript/interpreter/fast_runtime_stub.h | 2 + ecmascript/interpreter/interpreter-inl.h | 13 +- ecmascript/js_thread.h | 8 + ecmascript/runtime_trampolines.cpp | 7 + ecmascript/runtime_trampolines.h | 1 + 22 files changed, 756 insertions(+), 49 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 176c58e..6fd646f 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -735,13 +735,13 @@ void GetPropertyByIndexStub::GenerateCircuit() StubDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter); Return(CallRuntime(callAccessorGetter, thread, GetWord64Constant(FAST_STUB_ID(AccessorGetter)), - {thread, *holder, value})); + {thread, value, *holder})); } Bind(¬Internal); { StubDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter); Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), - {thread, receiver, value})); + {thread, value, receiver})); } } Bind(¬Accessor); @@ -891,7 +891,7 @@ void GetPropertyByNameStub::GenerateCircuit() Label isDicMode(env); Label notDicMode(env); // if branch condition : LIKELY(!hclass->IsDictionaryMode()) - Branch(IsDictionaryElement(hClass), &isDicMode, ¬DicMode); + Branch(IsDictionaryModeByHClass(hClass), &isDicMode, ¬DicMode); Bind(¬DicMode); { // LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetAttributes().GetTaggedObject()) @@ -918,6 +918,7 @@ void GetPropertyByNameStub::GenerateCircuit() Label notAccessor(env); Branch(IsAccessor(attr), &isAccessor, ¬Accessor); Bind(&isAccessor); + { Label isInternal(env); Label notInternal(env); @@ -927,13 +928,13 @@ void GetPropertyByNameStub::GenerateCircuit() StubDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter); Return(CallRuntime(callAccessorGetter, thread, GetWord64Constant(FAST_STUB_ID(AccessorGetter)), - {thread, *holder, value})); + {thread, value, *holder})); } Bind(¬Internal); { StubDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter); Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), - {thread, receiver, value})); + {thread, value, receiver})); } } Bind(¬Accessor); @@ -976,13 +977,13 @@ void GetPropertyByNameStub::GenerateCircuit() StubDescriptor *callAccessorGetter1 = GET_STUBDESCRIPTOR(AccessorGetter); Return(CallRuntime(callAccessorGetter1, thread, GetWord64Constant(FAST_STUB_ID(AccessorGetter)), - {thread, *holder, value})); + {thread, value, *holder})); } Bind(¬Internal1); { StubDescriptor *callGetter1 = GET_STUBDESCRIPTOR(CallGetter); Return(CallRuntime(callGetter1, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), - {thread, receiver, value})); + {thread, value, receiver,})); } } Bind(¬Accessor1); @@ -1314,4 +1315,159 @@ void FunctionCallInternalStub::GenerateCircuit() Return(CallRuntime(execute, thread, GetWord64Constant(FAST_STUB_ID(Execute)), {thread, func, thisArg, argc, argv})); } + +void GetPropertyByValueStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift receiver = PtrArgument(1); + DEFVARIABLE(key, TAGGED_TYPE, PtrArgument(2)); /* 2 : 3rd parameter is key */ + + Label isNumberOrStringSymbol(env); + Label notNumber(env); + Label isStringOrSymbol(env); + Label notStringOrSymbol(env); + Label exit(env); + + Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number); + Bind(¬Number); + { + Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol); + Bind(¬StringOrSymbol); + { + Return(GetHoleConstant()); + } + } + Bind(&isNumberOrStringSymbol); + { + AddrShift index = TryToElementsIndex(*key); + Label validIndex(env); + Label notValidIndex(env); + Branch(Int32GreaterThanOrEqual(index, GetInteger32Constant(0)), &validIndex, ¬ValidIndex); + Bind(&validIndex); + { + auto getPropertyByIndex = GET_STUBDESCRIPTOR(GetPropertyByIndex); + Return(CallStub(getPropertyByIndex, GetWord64Constant(FAST_STUB_ID(GetPropertyByIndex)), + {thread, receiver, index})); + } + Bind(¬ValidIndex); + { + Label notNumber(env); + Label getByName(env); + Branch(TaggedIsNumber(*key), &exit, ¬Number); + Bind(¬Number); + { + Label isString(env); + Label notString(env); + Label isInternalString(env); + Label notIntenalString(env); + Branch(TaggedIsString(*key), &isString, ¬String); + Bind(&isString); + { + Branch(IsInternalString(*key), &isInternalString, ¬IntenalString); + Bind(&isInternalString); + Jump(&getByName); + Bind(¬IntenalString); + { + StubDescriptor *newInternalString = GET_STUBDESCRIPTOR(NewInternalString); + key = CallRuntime(newInternalString, thread, + GetWord64Constant(FAST_STUB_ID(NewInternalString)), + {thread, *key}); + Jump(&getByName); + } + } + Bind(¬String); + { + Jump(&getByName); + } + } + Bind(&getByName); + { + auto getPropertyByName = GET_STUBDESCRIPTOR(GetPropertyByName); + Return(CallStub(getPropertyByName, GetWord64Constant(FAST_STUB_ID(GetPropertyByName)), + {thread, receiver, *key})); + } + } + } + Bind(&exit); + Return(GetHoleConstant()); +} + +void SetPropertyByValueStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift receiver = PtrArgument(1); + DEFVARIABLE(key, TAGGED_TYPE, PtrArgument(2)); /* 2 : 3rd parameter is key */ + AddrShift value = Int64Argument(3); /* 3 : 4th parameter is value */ + + Label isNumberOrStringSymbol(env); + Label notNumber(env); + Label isStringOrSymbol(env); + Label notStringOrSymbol(env); + Label exit(env); + + Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number); + Bind(¬Number); + { + Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol); + Bind(¬StringOrSymbol); + { + Return(GetHoleConstant()); + } + } + Bind(&isNumberOrStringSymbol); + { + AddrShift index = TryToElementsIndex(*key); + Label validIndex(env); + Label notValidIndex(env); + Branch(Int32GreaterThanOrEqual(index, GetInteger32Constant(0)), &validIndex, ¬ValidIndex); + Bind(&validIndex); + { + auto setPropertyByIndex = GET_STUBDESCRIPTOR(SetPropertyByIndex); + Return(CallStub(setPropertyByIndex, GetWord64Constant(FAST_STUB_ID(SetPropertyByIndex)), + {thread, receiver, index, value})); + } + Bind(¬ValidIndex); + { + Label notNumber(env); + Label getByName(env); + Branch(TaggedIsNumber(*key), &exit, ¬Number); + Bind(¬Number); + { + Label isString(env); + Label notString(env); + Label isInternalString(env); + Label notIntenalString(env); + Branch(TaggedIsString(*key), &isString, ¬String); + Bind(&isString); + { + Branch(IsInternalString(*key), &isInternalString, ¬IntenalString); + Bind(&isInternalString); + Jump(&getByName); + Bind(¬IntenalString); + { + StubDescriptor *newInternalString = GET_STUBDESCRIPTOR(NewInternalString); + key = CallRuntime(newInternalString, thread, + GetWord64Constant(FAST_STUB_ID(NewInternalString)), + {thread, *key}); + Jump(&getByName); + } + } + Bind(¬String); + { + Jump(&getByName); + } + } + Bind(&getByName); + { + auto setPropertyByName = GET_STUBDESCRIPTOR(SetPropertyByName); + Return(CallStub(setPropertyByName, GetWord64Constant(FAST_STUB_ID(SetPropertyByName)), + {thread, receiver, *key, value})); + } + } + } + Bind(&exit); + Return(GetHoleConstant()); +} } // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 853628b..68bbb4a 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -83,7 +83,10 @@ public: class GetElementStub : public Stub { public: // 3 : 3 means argument counts - explicit GetElementStub(Circuit *circuit) : Stub("GetElement", 3, circuit) {} + explicit GetElementStub(Circuit *circuit) : Stub("GetElement", 3, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } ~GetElementStub() = default; NO_MOVE_SEMANTIC(GetElementStub); NO_COPY_SEMANTIC(GetElementStub); @@ -113,7 +116,10 @@ public: class GetPropertyByIndexStub : public Stub { public: // 3 : 3 means argument counts - explicit GetPropertyByIndexStub(Circuit *circuit) : Stub("GetPropertyByIndex", 3, circuit) {} + explicit GetPropertyByIndexStub(Circuit *circuit) : Stub("GetPropertyByIndex", 3, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } ~GetPropertyByIndexStub() = default; NO_MOVE_SEMANTIC(GetPropertyByIndexStub); NO_COPY_SEMANTIC(GetPropertyByIndexStub); @@ -123,7 +129,10 @@ public: class SetPropertyByIndexStub : public Stub { public: // 4 : 4 means argument counts - explicit SetPropertyByIndexStub(Circuit *circuit) : Stub("SetPropertyByIndex", 4, circuit) {} + explicit SetPropertyByIndexStub(Circuit *circuit) : Stub("SetPropertyByIndex", 4, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } ~SetPropertyByIndexStub() = default; NO_MOVE_SEMANTIC(SetPropertyByIndexStub); NO_COPY_SEMANTIC(SetPropertyByIndexStub); @@ -133,7 +142,10 @@ public: class GetPropertyByNameStub : public Stub { public: // 3 : 3 means argument counts - explicit GetPropertyByNameStub(Circuit *circuit) : Stub("GetPropertyByName", 3, circuit) {} + explicit GetPropertyByNameStub(Circuit *circuit) : Stub("GetPropertyByName", 3, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } ~GetPropertyByNameStub() = default; NO_MOVE_SEMANTIC(GetPropertyByNameStub); NO_COPY_SEMANTIC(GetPropertyByNameStub); @@ -172,5 +184,31 @@ public: NO_COPY_SEMANTIC(FunctionCallInternalStub); void GenerateCircuit() override; }; + +class GetPropertyByValueStub : public Stub { +public: + // 3 : 3 means argument counts + explicit GetPropertyByValueStub(Circuit *circuit) : Stub("FastGetPropertyByValue", 3, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~GetPropertyByValueStub() = default; + NO_MOVE_SEMANTIC(GetPropertyByValueStub); + NO_COPY_SEMANTIC(GetPropertyByValueStub); + void GenerateCircuit() override; +}; + +class SetPropertyByValueStub : public Stub { +public: + // 4 : 4 means argument counts + explicit SetPropertyByValueStub(Circuit *circuit) : Stub("FastSetPropertyByValue", 4, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~SetPropertyByValueStub() = default; + NO_MOVE_SEMANTIC(SetPropertyByValueStub); + NO_COPY_SEMANTIC(SetPropertyByValueStub); + void GenerateCircuit() override; +}; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index 1bc6e8c..c4682d8 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -29,7 +29,8 @@ namespace kungfu { V(FindElementWithCache, 4) \ V(Execute, 5) \ V(StringGetHashCode, 1) \ - V(FloatMod, 2) + V(FloatMod, 2) \ + V(NewInternalString, 2) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define FAST_RUNTIME_STUB_LIST(V) \ @@ -60,7 +61,9 @@ namespace kungfu { V(FindOwnElement2, 6) \ V(GetPropertyByIndex, 3) \ V(FunctionCallInternal, 5) \ - V(SetPropertyByIndex, 4) + V(SetPropertyByIndex, 4) \ + V(GetPropertyByValue, 3) \ + V(SetPropertyByValue, 4) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define TEST_FUNC_LIST(V) \ diff --git a/ecmascript/compiler/gate.cpp b/ecmascript/compiler/gate.cpp index f2e0983..bcecfad 100644 --- a/ecmascript/compiler/gate.cpp +++ b/ecmascript/compiler/gate.cpp @@ -185,12 +185,20 @@ Properties OpCode::GetProperties() const return {INT64, NO_STATE, NO_DEPEND, VALUE(INT32), NO_ROOT}; case ZEXT_INT1_TO_INT32: return {INT32, NO_STATE, NO_DEPEND, VALUE(INT1), NO_ROOT}; + case ZEXT_INT8_TO_INT32: + return {INT32, NO_STATE, NO_DEPEND, VALUE(INT8), NO_ROOT}; + case ZEXT_INT16_TO_INT32: + return {INT32, NO_STATE, NO_DEPEND, VALUE(INT16), NO_ROOT}; case ZEXT_INT1_TO_INT64: return {INT64, NO_STATE, NO_DEPEND, VALUE(INT1), NO_ROOT}; case SEXT_INT32_TO_INT64: return {INT64, NO_STATE, NO_DEPEND, VALUE(INT32), NO_ROOT}; case SEXT_INT1_TO_INT32: return {INT32, NO_STATE, NO_DEPEND, VALUE(INT1), NO_ROOT}; + case SEXT_INT8_TO_INT32: + return {INT32, NO_STATE, NO_DEPEND, VALUE(INT8), NO_ROOT}; + case SEXT_INT16_TO_INT32: + return {INT32, NO_STATE, NO_DEPEND, VALUE(INT8), NO_ROOT}; case SEXT_INT1_TO_INT64: return {INT64, NO_STATE, NO_DEPEND, VALUE(INT1), NO_ROOT}; case TRUNC_INT64_TO_INT32: @@ -400,9 +408,13 @@ std::string OpCode::Str() const {FLOAT64_CONSTANT, "FLOAT64_CONSTANT"}, {ZEXT_INT32_TO_INT64, "ZEXT_INT32_TO_INT64"}, {ZEXT_INT1_TO_INT32, "ZEXT_INT1_TO_INT32"}, + {ZEXT_INT8_TO_INT32, "ZEXT_INT8_TO_INT32"}, + {ZEXT_INT16_TO_INT32, "ZEXT_INT16_TO_INT32"}, {ZEXT_INT1_TO_INT64, "ZEXT_INT1_TO_INT64"}, {SEXT_INT32_TO_INT64, "SEXT_INT32_TO_INT64"}, {SEXT_INT1_TO_INT32, "SEXT_INT1_TO_INT32"}, + {SEXT_INT8_TO_INT32, "SEXT_INT8_TO_INT32"}, + {SEXT_INT16_TO_INT32, "SEXT_INT16_TO_INT32"}, {SEXT_INT1_TO_INT64, "SEXT_INT1_TO_INT64"}, {TRUNC_INT64_TO_INT32, "TRUNC_INT64_TO_INT32"}, {TRUNC_INT64_TO_INT1, "TRUNC_INT64_TO_INT1"}, @@ -1305,4 +1317,9 @@ bool OpCode::IsLoopHead() const { return (this->op == OpCode::LOOP_BEGIN); } + +bool OpCode::IsNop() const +{ + return (this->op == OpCode::NOP); +} } // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/gate.h b/ecmascript/compiler/gate.h index a112479..fbc99b7 100644 --- a/ecmascript/compiler/gate.h +++ b/ecmascript/compiler/gate.h @@ -147,9 +147,13 @@ public: FLOAT64_CONSTANT, ZEXT_INT32_TO_INT64, ZEXT_INT1_TO_INT32, + ZEXT_INT8_TO_INT32, + ZEXT_INT16_TO_INT32, ZEXT_INT1_TO_INT64, SEXT_INT32_TO_INT64, SEXT_INT1_TO_INT32, + SEXT_INT8_TO_INT32, + SEXT_INT16_TO_INT32, SEXT_INT1_TO_INT64, TRUNC_INT64_TO_INT32, TRUNC_INT64_TO_INT1, @@ -253,6 +257,7 @@ public: [[nodiscard]] bool IsCFGMerge() const; [[nodiscard]] bool IsControlCase() const; [[nodiscard]] bool IsLoopHead() const; + [[nodiscard]] bool IsNop() const; ~OpCode() = default; private: diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 4422c6e..ff7c55b 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -92,6 +92,8 @@ void LLVMIRBuilder::AssignHandleMap() {OpCode::INT64_CONSTANT, &LLVMIRBuilder::HandleInt64Constant}, {OpCode::FLOAT64_CONSTANT, &LLVMIRBuilder::HandleFloat64Constant}, {OpCode::ZEXT_INT1_TO_INT32, &LLVMIRBuilder::HandleZExtInt}, + {OpCode::ZEXT_INT8_TO_INT32, &LLVMIRBuilder::HandleZExtInt}, + {OpCode::ZEXT_INT16_TO_INT32, &LLVMIRBuilder::HandleZExtInt}, {OpCode::ZEXT_INT32_TO_INT64, &LLVMIRBuilder::HandleZExtInt}, {OpCode::ZEXT_INT1_TO_INT64, &LLVMIRBuilder::HandleZExtInt}, {OpCode::SEXT_INT1_TO_INT32, &LLVMIRBuilder::HandleSExtInt}, @@ -134,6 +136,8 @@ void LLVMIRBuilder::AssignHandleMap() {OpCode::FLOAT64_EQ, &LLVMIRBuilder::HandleFloatOrDoubleCmp}, {OpCode::INT32_NE, &LLVMIRBuilder::HandleIntOrUintCmp}, {OpCode::INT64_NE, &LLVMIRBuilder::HandleIntOrUintCmp}, + {OpCode::INT8_LOAD, &LLVMIRBuilder::HandleLoad}, + {OpCode::INT16_LOAD, &LLVMIRBuilder::HandleLoad}, {OpCode::INT32_LOAD, &LLVMIRBuilder::HandleLoad}, {OpCode::INT64_LOAD, &LLVMIRBuilder::HandleLoad}, {OpCode::INT32_STORE, &LLVMIRBuilder::HandleStore}, @@ -186,7 +190,6 @@ void LLVMIRBuilder::Build() AddrShift gate = (*schedule_)[bbIdx][instIdx - 1]; std::vector ins = circuit_->GetInVector(gate); std::vector outs = circuit_->GetOutVector(gate); - std::cout << "instIdx :" << instIdx << std::endl; circuit_->Print(gate); auto found = opCodeHandleMap_.find(circuit_->GetOpCode(gate)); if (found != opCodeHandleMap_.end()) { @@ -362,6 +365,9 @@ LLVMTypeRef LLVMIRBuilder::GetMachineRepType(MachineRep rep) const case MachineRep::K_WORD8: dstType = LLVMInt8TypeInContext(context_); break; + case MachineRep::K_WORD16: + dstType = LLVMInt16TypeInContext(context_); + break; case MachineRep::K_WORD32: dstType = LLVMInt32TypeInContext(context_); break; @@ -626,6 +632,8 @@ void LLVMIRBuilder::HandleZExtInt(AddrShift gate) { std::vector ins = circuit_->GetInVector(gate); switch (circuit_->GetOpCode(gate)) { + case OpCode::ZEXT_INT8_TO_INT32: // no break, fall through + case OpCode::ZEXT_INT16_TO_INT32: case OpCode::ZEXT_INT1_TO_INT32: { VisitZExtInt(gate, ins[0], MachineRep::K_WORD32); break; @@ -1041,6 +1049,16 @@ void LLVMIRBuilder::HandleLoad(AddrShift gate) std::vector ins = circuit_->GetInVector(gate); std::vector outs = circuit_->GetOutVector(gate); switch (circuit_->GetOpCode(gate)) { + case OpCode::INT8_LOAD: { + AddrShift base = ins[1]; + VisitLoad(gate, MachineRep::K_WORD8, base); + break; + } + case OpCode::INT16_LOAD: { + AddrShift base = ins[1]; + VisitLoad(gate, MachineRep::K_WORD16, base); + break; + } case OpCode::INT32_LOAD: { AddrShift base = ins[1]; VisitLoad(gate, MachineRep::K_WORD32, base); diff --git a/ecmascript/compiler/llvm_mcjit_engine.cpp b/ecmascript/compiler/llvm_mcjit_engine.cpp index 3fb6d34..c8afaed 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.cpp +++ b/ecmascript/compiler/llvm_mcjit_engine.cpp @@ -104,7 +104,7 @@ void LLVMAssembler::BuildAndRunPasses() const LOG_ECMA(INFO) << "BuildAndRunPasses - "; LLVMPassManagerRef pass = LLVMCreatePassManager(); LLVMAddConstantPropagationPass(pass); - LLVMAddInstructionCombiningPass(pass); + //LLVMAddInstructionCombiningPass(pass); llvm::unwrap(pass)->add(llvm::createRewriteStatepointsForGCLegacyPass()); char *info = LLVMPrintModuleToString(module_); LOG_ECMA(INFO) << "Current Module: " << info; diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 4550be2..9a112b8 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -34,10 +34,11 @@ AddrShift Stub::Variable::AddPhiOperand(AddrShift val) Label label = env_->GetLabelFromSelector(val); size_t idx = 0; for (auto pred : label.GetPredecessors()) { + auto preVal = pred.ReadVariable(this); + ASSERT(!env_->GetCircuit()->GetOpCode(preVal).IsNop()); idx++; - val = AddOperandToSelector(val, idx, pred.ReadVariable(this)); + val = AddOperandToSelector(val, idx, preVal); } - return TryRemoveTrivialPhi(val); } @@ -66,6 +67,7 @@ AddrShift Stub::Variable::TryRemoveTrivialPhi(AddrShift phiVal) // the phi is unreachable or in the start block same = env_->GetCircuit()->LoadGatePtr(env_->GetCircuitBuilder().UndefineConstant()); } + auto same_addr_shift = env_->GetCircuit()->SaveGatePtr(same); // remove the trivial phi // get all users of phi except self @@ -92,10 +94,15 @@ AddrShift Stub::Variable::TryRemoveTrivialPhi(AddrShift phiVal) for (auto out : outs) { if (IsSelector(out->GetGate())) { auto out_addr_shift = env_->GetCircuit()->SaveGatePtr(out->GetGate()); - TryRemoveTrivialPhi(out_addr_shift); + auto result = TryRemoveTrivialPhi(out_addr_shift); + if (same_addr_shift == out_addr_shift) + { + same_addr_shift = result; + } + } } - return env_->GetCircuit()->SaveGatePtr(same); + return same_addr_shift; } void Stub::Variable::RerouteOuts(const std::vector &outs, Gate *newGate) @@ -123,7 +130,10 @@ void LabelImpl::WriteVariable(Variable *var, AddrShift value) AddrShift LabelImpl::ReadVariable(Variable *var) { if (valueMap_.find(var) != valueMap_.end()) { - return valueMap_.at(var); + auto result = valueMap_.at(var); + if (!env_->GetCircuit()->GetOpCode(result).IsNop()) { + return result; + } } return ReadVariableRecursive(var); } @@ -423,7 +433,7 @@ AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elem Bind(¬Match); Jump(&loopEnd); Bind(&loopEnd); - entry = Word32And(Int32Add(*entry, *count), Int32Sub(capacity, GetInteger32Constant(1))); + entry = GetNextPositionForHash(*entry, *count, capacity); count = Int32Add(*count, GetInteger32Constant(1)); LoopEnd(&loopHead); Bind(&exit); @@ -594,7 +604,7 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements } Bind(&loopEnd); { - entry = Word32And(Int32Add(*entry, *count), Int32Sub(capacity, GetInteger32Constant(1))); + entry = GetNextPositionForHash(*entry, *count, capacity); count = Int32Add(*count, GetInteger32Constant(1)); LoopEnd(&loopHead); } @@ -626,7 +636,7 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a Int32Mul(Int32Sub( GetInteger32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS), attrOffset), GetInteger32Constant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()))); - result = Int64BuildTagged(Load(UINT64_TYPE, obj, ZExtInt32ToInt64(propOffset))); + result = Load(UINT64_TYPE, obj, ZExtInt32ToInt64(propOffset)); Jump(&exit); } Bind(¬InlinedProp); @@ -646,10 +656,9 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a void Stub::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val) { - AddrShift taggedId = GetInteger32Constant(messageId); StubDescriptor *throwTypeError = GET_STUBDESCRIPTOR(ThrowTypeError); - CallRuntime(throwTypeError, thread, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), - {thread, taggedId}); + AddrShift msgIntId = GetInteger32Constant(messageId); + CallRuntime(throwTypeError, thread, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), {thread, msgIntId}); Return(val); } @@ -793,4 +802,248 @@ void Stub::UpdateAndStoreRepresention(AddrShift hclass, AddrShift value) AddrShift newRep = UpdateRepresention(GetElementRepresentation(hclass), value); SetElementRepresentation(hclass, newRep); } + +AddrShift Stub::TaggedIsString(AddrShift obj) +{ + auto env = GetEnvironment(); + Label entry(env); + [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + Label exit(env); + DEFVARIABLE(result, BOOL_TYPE, FalseConstant()); + Label isHeapObject(env); + Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit); + Bind(&isHeapObject); + { + result = Word32Equal(GetObjectType(LoadHClass(obj)), + GetInteger32Constant(static_cast(panda::ecmascript::JSType::STRING))); + Jump(&exit); + } + Bind(&exit); + return *result; +} + +AddrShift Stub::TaggedIsStringOrSymbol(AddrShift obj) +{ + auto env = GetEnvironment(); + Label entry(env); + [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + Label exit(env); + DEFVARIABLE(result, BOOL_TYPE, FalseConstant()); + Label isHeapObject(env); + Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit); + Bind(&isHeapObject); + { + AddrShift objType = GetObjectType(LoadHClass(obj)); + result = Word32Equal(objType, + GetInteger32Constant(static_cast(panda::ecmascript::JSType::STRING))); + Label isString(env); + Label notString(env); + Branch(*result, &exit, ¬String); + Bind(¬String); + { + result = Word32Equal(objType, + GetInteger32Constant(static_cast(panda::ecmascript::JSType::SYMBOL))); + Jump(&exit); + } + } + Bind(&exit); + return *result; +} + +AddrShift Stub::IsUtf16String(AddrShift string) +{ + // compressedStringsEnabled fixed to true constant + AddrShift len = Load(MachineType::UINT32_TYPE, string, + GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); + return Word32Equal( + Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)), + GetInteger32Constant(panda::ecmascript::EcmaString::STRING_UNCOMPRESSED)); +} + +AddrShift Stub::IsUtf8String(AddrShift string) +{ + // compressedStringsEnabled fixed to true constant + AddrShift len = Load(MachineType::UINT32_TYPE, string, + GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); + return Word32Equal( + Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)), + GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED)); +} + +AddrShift Stub::IsInternalString(AddrShift string) +{ + // compressedStringsEnabled fixed to true constant + AddrShift len = Load(MachineType::UINT32_TYPE, string, + GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); + return Word32NotEqual( + Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_INTERN_BIT)), + GetInteger32Constant(0)); +} + +AddrShift Stub::IsDigit(AddrShift ch) +{ + return TruncInt32ToInt1( + Word32And(SExtInt1ToInt32(Int32LessThanOrEqual(ch, GetInteger32Constant('9'))), + SExtInt1ToInt32(Int32GreaterThanOrEqual(ch, GetInteger32Constant('0'))))); +} + +AddrShift Stub::StringToElementIndex(AddrShift string) +{ + auto env = GetEnvironment(); + Label entry(env); + [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + Label exit(env); + DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1)); + Label greatThanZero(env); + Label inRange(env); + AddrShift len = Load(MachineType::UINT32_TYPE, string, + GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); + len = Word32LSR(len, GetInteger32Constant(2)); + Branch(Word32Equal(len, GetInteger32Constant(0)), &exit, &greatThanZero); + Bind(&greatThanZero); + Branch(Int32GreaterThan(len, GetInteger32Constant(panda::ecmascript::MAX_INDEX_LEN)), &exit, &inRange); + Bind(&inRange); + { + AddrShift dataUtf16 = PtrAdd(string, GetPtrConstant(panda::ecmascript::EcmaString::GetDataOffset())); + DEFVARIABLE(c, UINT32_TYPE, GetInteger32Constant(0)); + Label isUtf16(env); + Label isUtf8(env); + Label getChar1(env); + AddrShift isUtf16String = IsUtf16String(string); + Branch(isUtf16String, &isUtf16, &isUtf8); + Bind(&isUtf16); + { + c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16)); + Jump(&getChar1); + } + Bind(&isUtf8); + { + c = ZExtInt8ToInt32(Load(INT8_TYPE, dataUtf16)); + Jump(&getChar1); + } + Bind(&getChar1); + { + Label isDigitZero(env); + Label notDigitZero(env); + Branch(Word32Equal(*c, GetInteger32Constant('0')), &isDigitZero, ¬DigitZero); + Bind(&isDigitZero); + { + Label lengthIsOne(env); + Branch(Word32Equal(len, GetInteger32Constant(1)), &lengthIsOne, &exit); + Bind(&lengthIsOne); + { + result = GetInteger32Constant(0); + Jump(&exit); + } + } + Bind(¬DigitZero); + { + Label isDigit(env); + DEFVARIABLE(i, UINT32_TYPE, GetInteger32Constant(1)); + DEFVARIABLE(n, UINT32_TYPE, Int32Sub(*c, GetInteger32Constant('0'))); + Branch(IsDigit(*c), &isDigit, &exit); + Label loopHead(env); + Label loopEnd(env); + Label afterLoop(env); + Bind(&isDigit); + Branch(Int32LessThan(*i, len), &loopHead, &exit); + LoopBegin(&loopHead); + { + Label isUtf16(env); + Label notUtf16(env); + Label getChar2(env); + Branch(isUtf16String, &isUtf16, ¬Utf16); + Bind(&isUtf16); + { + c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, PtrMul(*i, GetPtrConstant(2)))); + Jump(&getChar2); + } + Bind(¬Utf16); + { + c = ZExtInt8ToInt32(Load(INT8_TYPE, dataUtf16, *i)); + Jump(&getChar2); + } + Bind(&getChar2); + { + Label isDigit2(env); + Label notDigit2(env); + Branch(IsDigit(*c), &isDigit2, ¬Digit2); + Bind(&isDigit2); + { + n = Int32Add(Int32Mul(*n, GetInteger32Constant(10)), + Int32Sub(*c, GetInteger32Constant('0'))); + i = Int32Add(*i, GetInteger32Constant(1)); + Branch(Int32LessThan(*i, len), &loopEnd, &afterLoop); + } + Bind(¬Digit2); + Jump(&exit); + } + } + Bind(&loopEnd); + LoopEnd(&loopHead); + Bind(&afterLoop); + { + Label lessThanMaxIndex(env); + Branch(Word32LessThan(*n, GetInteger32Constant(panda::ecmascript::JSObject::MAX_ELEMENT_INDEX)), + &lessThanMaxIndex, &exit); + Bind(&lessThanMaxIndex); + { + result = *n; + Jump(&exit); + } + } + } + } + } + Bind(&exit); + return *result; +} + +AddrShift Stub::TryToElementsIndex(AddrShift key) +{ + auto env = GetEnvironment(); + Label entry(env); + [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + Label exit(env); + Label isKeyInt(env); + Label notKeyInt(env); + + DEFVARIABLE(resultKey, INT32_TYPE, GetInteger32Constant(0)); + Branch(TaggedIsInt(key), &isKeyInt, ¬KeyInt); + Bind(&isKeyInt); + { + resultKey = TaggedCastToInt32(key); + Jump(&exit); + } + Bind(¬KeyInt); + { + Label isString(env); + Label notString(env); + Branch(TaggedIsString(key), &isString, ¬String); + Bind(&isString); + { + resultKey = StringToElementIndex(key); + Jump(&exit); + } + Bind(¬String); + { + Label isDouble(env); + Branch(TaggedIsDouble(key), &isDouble, &exit); + Bind(&isDouble); + { + AddrShift number = TaggedCastToDouble(key); + AddrShift integer = ChangeInt64ToInt32(CastDoubleToInt64(number)); + Label isEqual(env); + Branch(DoubleEqual(number, CastInt64ToFloat64(SExtInt32ToInt64(integer))), &isEqual, &exit); + Bind(&isEqual); + { + resultKey = integer; + Jump(&exit); + } + } + } + } + Bind(&exit); + return *resultKey; +} } // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 8b011f5..21ba2e2 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -699,7 +699,16 @@ public: { return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::FLOAT64_DIV), x, y); } - AddrShift Int32Div(AddrShift x, AddrShift y); + AddrShift Int32Div(AddrShift x, AddrShift y) + { + return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_SDIV), x, y); + } + + AddrShift Word32Div(AddrShift x, AddrShift y) + { + return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_UDIV), x, y); + } + AddrShift Int64Div(AddrShift x, AddrShift y); AddrShift Int32Mod(AddrShift x, AddrShift y) @@ -761,11 +770,6 @@ public: return env_.GetCircuitBuilder().NewLogicGate(OpCode(OpCode::INT32_AND), x, y); } - AddrShift WordLogicNot(AddrShift x) - { - return env_.GetCircuitBuilder().NewLogicGate(OpCode(OpCode::INT32_REV), x); - } - AddrShift Word32LSL(AddrShift x, AddrShift y) { return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_LSL), x, y); @@ -828,15 +832,27 @@ public: SExtInt1ToInt32( Word64Equal(Word64And(x, GetWord64Constant(~panda::ecmascript::JSTaggedValue::TAG_SPECIAL_MASK)), GetWord64Constant(0))), - Word32Or(SExtInt1ToInt32(Word64NotEqual( - Word64And(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_SPECIAL_MASK)), + WordLogicOr(SExtInt1ToInt32(Word64NotEqual( + Word64And(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_SPECIAL_VALUE)), GetWord64Constant(0))), SExtInt1ToInt32(TaggedIsHole(x))))); } AddrShift TaggedIsHeapObject(AddrShift x) { return TruncInt32ToInt1( - Word32And(SExtInt1ToInt32(TaggedIsObject(x)), Word32Not(SExtInt1ToInt32(TaggedIsSpecial(x))))); + WordLogicAnd(SExtInt1ToInt32(TaggedIsObject(x)), + SExtInt1ToInt32(Word32Equal(SExtInt1ToInt32(TaggedIsSpecial(x)), GetInteger32Constant(0))))); + } + + AddrShift TaggedIsString(AddrShift obj); + + AddrShift TaggedIsStringOrSymbol(AddrShift obj); + + AddrShift GetNextPositionForHash(AddrShift last, AddrShift count, AddrShift size) + { + auto nextOffset = Word32LSR(Int32Mul(count, Int32Add(count, GetInteger32Constant(1))), + GetInteger32Constant(2)); + return Word32And(Int32Add(last, nextOffset), Int32Sub(size, GetInteger32Constant(1))); } AddrShift DoubleIsNAN(AddrShift x) @@ -1062,6 +1078,17 @@ public: GetInteger32Constant(0)); } + AddrShift IsDictionaryModeByHClass(AddrShift hClass) + { + AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + AddrShift bitfield = Load(INT64_TYPE, hClass, bitfieldOffset); + return Word64NotEqual( + Word64And( + Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::IsDictionaryBit::START_BIT)), + GetWord64Constant((1LLU << panda::ecmascript::JSHClass::IsDictionaryBit::SIZE) - 1)), + GetWord64Constant(0)); + } + AddrShift IsDictionaryElement(AddrShift hclass) { AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); @@ -1309,6 +1336,18 @@ public: AddrShift JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift propAttr); + AddrShift IsUtf16String(AddrShift string); + + AddrShift IsUtf8String(AddrShift string); + + AddrShift IsInternalString(AddrShift string); + + AddrShift IsDigit(AddrShift ch); + + AddrShift StringToElementIndex(AddrShift string); + + AddrShift TryToElementsIndex(AddrShift key); + AddrShift TaggedCastToInt64(AddrShift x) { return Word64And(x, GetWord64Constant(~panda::ecmascript::JSTaggedValue::TAG_MASK)); @@ -1365,6 +1404,16 @@ public: return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::ZEXT_INT1_TO_INT32), x); } + AddrShift ZExtInt8ToInt32(AddrShift x) + { + return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::ZEXT_INT8_TO_INT32), x); + } + + AddrShift ZExtInt16ToInt32(AddrShift x) + { + return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::ZEXT_INT16_TO_INT32), x); + } + AddrShift TruncInt64ToInt32(AddrShift x) { return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::TRUNC_INT64_TO_INT32), x); diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index 92665e9..9cf267c 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -161,7 +161,8 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri SET_STUB_TO_MODULE(module, GetPropertyByIndex) \ SET_STUB_TO_MODULE(module, SetPropertyByIndex) \ SET_STUB_TO_MODULE(module, FunctionCallInternal) \ - SET_STUB_TO_MODULE(module, GetPropertyByName) + SET_STUB_TO_MODULE(module, GetPropertyByName) \ + SET_STUB_TO_MODULE(module, GetPropertyByValue) int main(const int argc, const char **argv) { diff --git a/ecmascript/compiler/stub_aot_compiler.h b/ecmascript/compiler/stub_aot_compiler.h index e3e2aad..1bf0062 100644 --- a/ecmascript/compiler/stub_aot_compiler.h +++ b/ecmascript/compiler/stub_aot_compiler.h @@ -39,6 +39,7 @@ public: } void BuildStubModuleAndSave(const char *triple, panda::ecmascript::StubModule *module, const std::string &filename); + void SetAllStubToModule(); void SetStub(int index, Stub *optimizer) { stubs_[index] = optimizer; diff --git a/ecmascript/compiler/stub_aot_options.yaml b/ecmascript/compiler/stub_aot_options.yaml index 4d58964..7fb1b41 100644 --- a/ecmascript/compiler/stub_aot_options.yaml +++ b/ecmascript/compiler/stub_aot_options.yaml @@ -28,4 +28,4 @@ options: - x86_64-unknown-linux-gnu - arm-unknown-linux-gnu - aarch64-unknown-linux-gnu - description: stub aot compiler target triple \ No newline at end of file + description: stub aot compiler target triple diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 6a7b0c1..c742d19 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -245,6 +245,36 @@ CALL_STUB_INIT_DESCRIPTOR(SetPropertyByIndex) descriptor->SetParameters(params.data()); } +CALL_STUB_INIT_DESCRIPTOR(GetPropertyByValue) +{ + // 3 : 3 input parameters + static StubDescriptor getPropertyByValue("GetPropertyByValue", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + *descriptor = getPropertyByValue; + // 3 : 3 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); +} + +CALL_STUB_INIT_DESCRIPTOR(SetPropertyByValue) +{ + // // 4 : 4 input parameters + // static StubDescriptor setPropertyByValue("SetPropertyByValue", 0, 4, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + // *descriptor = setPropertyByValue; + // // 4 : 4 input parameters + // std::array params = { + // MachineType::UINT64_TYPE, + // MachineType::UINT64_TYPE, + // MachineType::UINT64_TYPE, + // MachineType::UINT64_TYPE, + // }; + // descriptor->SetParameters(params.data()); +} + + CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) { // 5 : 5 input parameters @@ -404,6 +434,20 @@ CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } +CALL_STUB_INIT_DESCRIPTOR(NewInternalString) +{ + // 2 : 2 input parameters + static StubDescriptor stringGetHashCode("NewInternalString", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + *descriptor = stringGetHashCode; + // 2 : 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + CALL_STUB_INIT_DESCRIPTOR(FastLoadElement) { // 2 : 2 input parameters diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 4e170fe..9274041 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -1185,6 +1185,91 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub) EXPECT_EQ(resVal.GetNumber(), y); } +HWTEST_F_L0(StubTest, FastGetPropertyByValueStub) +{ + auto module = stubModule.GetModule(); + LLVMValueRef getPropertyByIndexfunction = LLVMGetNamedFunction(module, "GetPropertyByIndex"); + Circuit netOfGates2; + GetPropertyByIndexStub getPropertyByIndexStub(&netOfGates2); + getPropertyByIndexStub.GenerateCircuit(); + netOfGates2.PrintAllGates(); + auto cfg2 = Scheduler::Run(&netOfGates2); + LLVMIRBuilder llvmBuilder2(&cfg2, &netOfGates2, &stubModule, getPropertyByIndexfunction); + llvmBuilder2.Build(); + + LLVMValueRef getPropertyByNamefunction = LLVMGetNamedFunction(module, "GetPropertyByName"); + Circuit netOfGates1; + GetPropertyByNameStub getPropertyByNameStub(&netOfGates1); + getPropertyByNameStub.GenerateCircuit(); + bool result = Verifier::Run(&netOfGates1); + ASSERT_TRUE(result); + auto cfg1 = Scheduler::Run(&netOfGates1); + LLVMIRBuilder llvmBuilder1(&cfg1, &netOfGates1, &stubModule, getPropertyByNamefunction); + llvmBuilder1.Build(); + + LLVMValueRef function = LLVMGetNamedFunction(module, "GetPropertyByValue"); + Circuit netOfGates; + GetPropertyByValueStub optimizer(&netOfGates); + optimizer.GenerateCircuit(); + netOfGates.PrintAllGates(); + result = Verifier::Run(&netOfGates); + ASSERT_TRUE(result); + auto cfg = Scheduler::Run(&netOfGates); + for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) { + std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":" + << std::endl; + for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) { + netOfGates.Print(cfg[bbIdx][instIdx - 1]); + } + } + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); + llvmBuilder.Build(); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); + assembler.Run(); + auto engine = assembler.GetEngine(); + auto *getPropertyByValuePtr = reinterpret_cast( + reinterpret_cast(LLVMGetPointerToGlobal(engine, function))); + auto *getPropertyByNamePtr = reinterpret_cast( + reinterpret_cast(LLVMGetPointerToGlobal(engine, getPropertyByNamefunction))); + auto *getpropertyByIndexPtr = reinterpret_cast( + reinterpret_cast(LLVMGetPointerToGlobal(engine, getPropertyByIndexfunction))); + auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); + JSHandle obj = factory->NewEmptyJSObject(); + int x = 213; + int y = 10; + + FastRuntimeStub::SetOwnElement(thread, obj.GetTaggedValue(), 1, JSTaggedValue(x)); + FastRuntimeStub::SetOwnElement(thread, obj.GetTaggedValue(), 10250, JSTaggedValue(y)); + + JSHandle strA(factory->NewFromCanBeCompressString("a")); + JSHandle strBig(factory->NewFromCanBeCompressString("biggest")); + JSHandle strDigit(factory->NewFromCanBeCompressString("10250")); + + FastRuntimeStub::SetPropertyByName(thread, obj.GetTaggedValue(), strA.GetTaggedValue(), JSTaggedValue(x)); + FastRuntimeStub::SetPropertyByName(thread, obj.GetTaggedValue(), strBig.GetTaggedValue(), JSTaggedValue(y)); + assembler.Disassemble(); + + JSTaggedValue resVal1 = getPropertyByNamePtr(thread, obj.GetTaggedValue().GetRawData(), + strA.GetTaggedValue().GetRawData()); + EXPECT_EQ(resVal1.GetNumber(), x); + JSTaggedValue resVal = getPropertyByValuePtr(thread, obj.GetTaggedValue().GetRawData(), + strA.GetTaggedValue().GetRawData()); + EXPECT_EQ(resVal.GetNumber(), x); + resVal = getPropertyByValuePtr(thread, obj.GetTaggedValue().GetRawData(), strBig.GetTaggedValue().GetRawData()); + EXPECT_EQ(resVal.GetNumber(), y); + resVal = getpropertyByIndexPtr(thread, obj.GetTaggedValue(), 1); + EXPECT_EQ(resVal.GetNumber(), x); + resVal = getPropertyByValuePtr(thread, obj.GetTaggedValue().GetRawData(), JSTaggedValue(10250).GetRawData()); + EXPECT_EQ(resVal.GetNumber(), y); + resVal = getPropertyByValuePtr(thread, obj.GetTaggedValue().GetRawData(), strDigit.GetTaggedValue().GetRawData()); + EXPECT_EQ(resVal.GetNumber(), y); + + JSHandle strHello(factory->NewFromCanBeCompressString("hello world")); + double key = 4.29497e+09; + resVal = getPropertyByValuePtr(thread, strHello.GetTaggedValue().GetRawData(), JSTaggedValue(key).GetRawData()); + EXPECT_EQ(resVal.GetRawData(), 0); +} + HWTEST_F_L0(StubTest, FastTypeOfTest) { auto module = stubModule.GetModule(); diff --git a/ecmascript/ecma_string.h b/ecmascript/ecma_string.h index 53fdd3a..453b2d1 100644 --- a/ecmascript/ecma_string.h +++ b/ecmascript/ecma_string.h @@ -45,6 +45,13 @@ public: static EcmaString *FastSubString(const JSHandle &src, uint32_t start, uint32_t utf16Len, const EcmaVM *vm); + static constexpr uint32_t STRING_COMPRESSED_BIT = 0x1; + static constexpr uint32_t STRING_INTERN_BIT = 0x2; + enum CompressedStatus { + STRING_COMPRESSED, + STRING_UNCOMPRESSED, + }; + template uint16_t At(int32_t index) const; @@ -285,12 +292,6 @@ private: static void CopyUtf16AsUtf8(const uint16_t *utf16From, uint8_t *utf8To, uint32_t utf16Len); static bool compressedStringsEnabled; - static constexpr uint32_t STRING_COMPRESSED_BIT = 0x1; - static constexpr uint32_t STRING_INTERN_BIT = 0x2; - enum CompressedStatus { - STRING_COMPRESSED, - STRING_UNCOMPRESSED, - }; static bool IsASCIICharacter(uint16_t data) { diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 7d5de2b..14321d3 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -168,6 +168,9 @@ bool EcmaVM::Initialize() globalEnv->SetTemplateMap(thread_, JSTaggedValue(TemplateMap::Create(thread_))); globalEnv->SetRegisterSymbols(GetJSThread(), JSTaggedValue(SymbolTable::Create(GetJSThread()))); + std::string moduleFile = options_.GetStubModuleFile(); + thread_->LoadFastStubModule(moduleFile.c_str()); + SetupRegExpResultCache(); microJobQueue_ = factory_->NewMicroJobQueue().GetTaggedValue(); diff --git a/ecmascript/interpreter/fast_runtime_stub-inl.h b/ecmascript/interpreter/fast_runtime_stub-inl.h index 055ba3b..88880a6 100644 --- a/ecmascript/interpreter/fast_runtime_stub-inl.h +++ b/ecmascript/interpreter/fast_runtime_stub-inl.h @@ -622,7 +622,10 @@ bool FastRuntimeStub::FastSetPropertyByIndex(JSThread *thread, JSTaggedValue rec JSTaggedValue value) { INTERPRETER_TRACE(thread, FastSetPropertyByIndex); - JSTaggedValue result = FastRuntimeStub::SetPropertyByIndex(thread, receiver, index, value); + auto *setPropertyByIndex = \ + reinterpret_cast \ + (reinterpret_cast(thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex)))); + JSTaggedValue result = setPropertyByIndex(thread, receiver, index, value); if (!result.IsHole()) { return result != JSTaggedValue::Exception(); } @@ -654,7 +657,9 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByName(JSThread *thread, JSTaggedV // Maybe moved by GC receiver = receiverHandler.GetTaggedValue(); } - JSTaggedValue result = FastRuntimeStub::GetPropertyByName(thread, receiver, key); + auto *getPropertyByNamePtr = reinterpret_cast( + thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName))); + JSTaggedValue result = getPropertyByNamePtr(thread, receiver, key); if (result.IsHole()) { return JSTaggedValue::GetProperty(thread, JSHandle(thread, receiver), JSHandle(thread, key)) @@ -681,7 +686,10 @@ template // UseHole is only for Array::Sort() which requires Hole JSTaggedValue FastRuntimeStub::FastGetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index) { INTERPRETER_TRACE(thread, FastGetPropertyByIndex); - JSTaggedValue result = GetPropertyByIndex(thread, receiver, index); + auto getPropertyByIndex = reinterpret_cast( + thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex))); + + JSTaggedValue result = getPropertyByIndex(thread, receiver, index); if (result.IsHole() && !UseHole) { return JSTaggedValue::GetProperty(thread, JSHandle(thread, receiver), index) .GetValue() diff --git a/ecmascript/interpreter/fast_runtime_stub.h b/ecmascript/interpreter/fast_runtime_stub.h index 271ac0f..8149d11 100644 --- a/ecmascript/interpreter/fast_runtime_stub.h +++ b/ecmascript/interpreter/fast_runtime_stub.h @@ -16,6 +16,7 @@ #ifndef ECMASCRIPT_INTERPRETER_FAST_RUNTIME_STUB_H #define ECMASCRIPT_INTERPRETER_FAST_RUNTIME_STUB_H +#include #include "ecmascript/js_tagged_value.h" namespace panda::ecmascript { @@ -24,6 +25,7 @@ class PropertyAttributes; class FastRuntimeStub { public: + using Address = uintptr_t; /* -------------- Common API Begin, Don't change those interface!!! ----------------- */ static inline JSTaggedValue FastAdd(JSTaggedValue left, JSTaggedValue right); static inline JSTaggedValue FastSub(JSTaggedValue left, JSTaggedValue right); diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index ad41ab5..3074da9 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -2439,7 +2439,9 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue receiver = GET_VREG_VALUE(v0); // fast path if (LIKELY(receiver.IsHeapObject())) { - JSTaggedValue res = FastRuntimeStub::GetPropertyByIndex(thread, receiver, idx); + auto getPropertyByIndex = reinterpret_cast( + thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex))); + JSTaggedValue res = getPropertyByIndex(thread, receiver, idx); if (!res.IsHole()) { INTERPRETER_RETURN_IF_ABRUPT(res); SET_ACC(res); @@ -2464,7 +2466,10 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool SAVE_ACC(); JSTaggedValue value = GET_ACC(); // fast path - JSTaggedValue res = FastRuntimeStub::SetPropertyByIndex(thread, receiver, index, value); + auto *setPropertyByIndex = \ + reinterpret_cast \ + (reinterpret_cast(thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex)))); + JSTaggedValue res = setPropertyByIndex(thread, receiver, index, value); if (!res.IsHole()) { INTERPRETER_RETURN_IF_ABRUPT(res); RESTORE_ACC(); @@ -2887,7 +2892,9 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool if (LIKELY(receiver.IsHeapObject())) { // fast path - JSTaggedValue res = FastRuntimeStub::GetPropertyByName(thread, receiver, propKey); + auto *getPropertyByNamePtr = reinterpret_cast( + thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName))); + JSTaggedValue res = getPropertyByNamePtr(thread, receiver, propKey); if (!res.IsHole()) { ASSERT(!res.IsAccessor()); INTERPRETER_RETURN_IF_ABRUPT(res); diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 3714389..f7c1559 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -170,6 +170,14 @@ public: return fastStubEntires_[id]; } + void SetFastStubEntry(uint32_t id, Address entry) + { + ASSERT(id < kungfu::FAST_STUB_MAXCOUNT); + fastStubEntires_[id] = entry; + } + + void InitializeFastRuntimeStubs(); + void LoadFastStubModule(const char *moduleFile); static uint32_t GetRuntimeFunctionsOffset() diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index b3c942e..17e4358 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -149,4 +149,11 @@ double RuntimeTrampolines::FloatMod(double left, double right) { return std::fmod(left, right); } + +uint64_t RuntimeTrampolines::NewInternalString(uint64_t argThread, uint64_t argKey) +{ + auto thread = reinterpret_cast(argThread); + JSHandle keyHandle(thread, JSTaggedValue(reinterpret_cast(argKey))); + return JSTaggedValue(thread->GetEcmaVM()->GetFactory()->InternString(keyHandle)).GetRawData(); +} } // namespace panda::ecmascript diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index a7c9e11..f68d32d 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -50,6 +50,7 @@ public: static uint32_t StringGetHashCode(uint64_t ecmaString); static uint64_t Execute(uint64_t argThread, uint64_t argFunc, uint64_t thisArg, uint32_t argc, uint64_t argArgv); static double FloatMod(double left, double right); + static uint64_t NewInternalString(uint64_t argThread, uint64_t argKey); }; class CallRuntimeTrampolinesScope { -- Gitee From e28d93cacc58442058bbca710af2c8e70b473924 Mon Sep 17 00:00:00 2001 From: getingke Date: Wed, 20 Oct 2021 16:52:03 +0800 Subject: [PATCH 079/115] fixed for optimized entry frame bug when CallInternal Change-Id: Ib82492657e54d0fa42874b93e8535d423bb03eb8 Signed-off-by: getingke --- ecmascript/compiler/fast_stub.cpp | 3 +- ecmascript/compiler/llvm_mcjit_engine.cpp | 2 +- ecmascript/interpreter/frame_handler.cpp | 41 +++++++++++++++++++++-- ecmascript/interpreter/frame_handler.h | 2 ++ ecmascript/interpreter/interpreter-inl.h | 25 +++++++++++--- ecmascript/js_thread.h | 11 ++++++ ecmascript/runtime_trampolines.cpp | 8 +++++ ecmascript/runtime_trampolines.h | 1 + 8 files changed, 83 insertions(+), 10 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 6fd646f..acdbfb4 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -918,7 +918,6 @@ void GetPropertyByNameStub::GenerateCircuit() Label notAccessor(env); Branch(IsAccessor(attr), &isAccessor, ¬Accessor); Bind(&isAccessor); - { Label isInternal(env); Label notInternal(env); @@ -983,7 +982,7 @@ void GetPropertyByNameStub::GenerateCircuit() { StubDescriptor *callGetter1 = GET_STUBDESCRIPTOR(CallGetter); Return(CallRuntime(callGetter1, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), - {thread, value, receiver,})); + {thread, value, receiver})); } } Bind(¬Accessor1); diff --git a/ecmascript/compiler/llvm_mcjit_engine.cpp b/ecmascript/compiler/llvm_mcjit_engine.cpp index c8afaed..3fb6d34 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.cpp +++ b/ecmascript/compiler/llvm_mcjit_engine.cpp @@ -104,7 +104,7 @@ void LLVMAssembler::BuildAndRunPasses() const LOG_ECMA(INFO) << "BuildAndRunPasses - "; LLVMPassManagerRef pass = LLVMCreatePassManager(); LLVMAddConstantPropagationPass(pass); - //LLVMAddInstructionCombiningPass(pass); + LLVMAddInstructionCombiningPass(pass); llvm::unwrap(pass)->add(llvm::createRewriteStatepointsForGCLegacyPass()); char *info = LLVMPrintModuleToString(module_); LOG_ECMA(INFO) << "Current Module: " << info; diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 4a17664..96ef0c5 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -42,9 +42,44 @@ bool InterpretedFrameHandler::IsBreakFrame() const void InterpretedFrameHandler::PrevFrame() { ASSERT(HasFrame()); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - FrameState *state = reinterpret_cast(sp_) - 1; - sp_ = state->base.prev; + auto type = GetFrameType(); + if (type == FrameType::INTERPRETER_FRAME) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + FrameState *state = reinterpret_cast(sp_) - 1; + sp_ = state->base.prev; + if (sp_ == nullptr) { + return; + } + type = GetFrameType(); + } + + while (type != FrameType::INTERPRETER_FRAME) { + switch(type) { + case FrameType::OPTIMIZED_FRAME: { + OptimizedFrameStateBase *state = reinterpret_cast( + reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedFrameStateBase, prev)); + sp_ = reinterpret_cast(state->prev); + } break; + case FrameType::OPTIMIZED_ENTRY_FRAME: { + OptimizedEntryFrameState *state = reinterpret_cast( + reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); + sp_ = reinterpret_cast(state->threadFp); + } break; + default: + UNREACHABLE(); + } + if (sp_ == nullptr) { + return; + } + type = GetFrameType(); + } +} + +FrameType InterpretedFrameHandler::GetFrameType() +{ + FrameType type = *(reinterpret_cast( + reinterpret_cast(sp_) + FrameConst::kFrameType)); + return type; } InterpretedFrameHandler InterpretedFrameHandler::GetPrevFrame() const diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index 0da418f..e23e36f 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -19,6 +19,7 @@ #include "ecmascript/js_method.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/heap_roots.h" +#include "ecmascript/frames.h" namespace panda { namespace ecmascript { @@ -66,6 +67,7 @@ public: } private: + FrameType GetFrameType(); JSTaggedType *sp_{nullptr}; }; diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 3074da9..2683016 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -206,7 +206,16 @@ namespace panda::ecmascript { JSTaggedValue EcmaInterpreter::ExecuteNative(JSThread *thread, const CallParams& params) { INTERPRETER_TRACE(thread, ExecuteNative); - JSTaggedType *sp = const_cast(thread->GetCurrentSPFrame()); + JSTaggedType *originalPrevSp = const_cast(thread->GetCurrentSPFrame()); + auto current = originalPrevSp; + FrameType type = *(reinterpret_cast( + reinterpret_cast(current) + FrameConst::kFrameType)); + JSTaggedType *sp = originalPrevSp; + if (type != FrameType::INTERPRETER_FRAME) { + JSTaggedType *lastSp = const_cast(thread->GetLastIFrameSp()); + sp = lastSp; + } + JSMethod *methodToCall = params.callTarget->GetCallTarget(); ASSERT(methodToCall->GetNumVregs() == 0); uint32_t numActualArgs = params.argc + RESERVED_CALL_ARGCOUNT; @@ -252,10 +261,18 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param } JSTaggedType *originalPrevSp = const_cast(thread->GetCurrentSPFrame()); - + auto current = originalPrevSp; + FrameType type = *(reinterpret_cast( + reinterpret_cast(current) + FrameConst::kFrameType)); + JSTaggedType *newSp = nullptr; + if (type != FrameType::INTERPRETER_FRAME) { + JSTaggedType *lastSp = const_cast(thread->GetLastIFrameSp()); + newSp = lastSp - FRAME_STATE_SIZE; + } else { + newSp = originalPrevSp - FRAME_STATE_SIZE; + } // push break state // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - JSTaggedType *newSp = originalPrevSp - FRAME_STATE_SIZE; if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) { return JSTaggedValue::Undefined(); } @@ -883,7 +900,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool } } HANDLE_OPCODE(HANDLE_RETURN_DYN) { - LOG_INST() << "return.dyn"; + LOG_INST() << "returnla "; FrameState *state = GET_FRAME(sp); LOG(DEBUG, INTERPRETER) << "Exit: Runtime Call " << std::hex << reinterpret_cast(state->sp) << " " << std::hex << reinterpret_cast(state->pc); diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index f7c1559..c888107 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -76,6 +76,16 @@ public: currentFrame_ = sp; } + const JSTaggedType *GetLastIFrameSp() const + { + return lastIFrame_; + } + + void SetLastIFrameSp(JSTaggedType *sp) + { + lastIFrame_ = sp; + } + bool DoStackOverflowCheck(const JSTaggedType *sp); bool IsEcmaInterpreter() const @@ -242,6 +252,7 @@ private: os::memory::Mutex initializationLock_; int nestedLevel_ = 0; JSTaggedType *currentFrame_ {nullptr}; + JSTaggedType *lastIFrame_ {nullptr}; JSTaggedType *frameBase_ {nullptr}; bool isSnapshotMode_ {false}; bool isEcmaInterpreter_ {false}; diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index 17e4358..ccd3c38 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -117,7 +117,11 @@ uint64_t RuntimeTrampolines::AccessorGetter(uint64_t argThread, uint64_t argGett int32_t RuntimeTrampolines::FindElementWithCache(uint64_t argThread, uint64_t hClass, uint64_t key, int32_t num) { + uintptr_t *curFp = nullptr; auto thread = reinterpret_cast(argThread); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); auto cls = reinterpret_cast(hClass); auto layoutInfo = LayoutInfo::Cast(cls->GetAttributes().GetTaggedObject()); return layoutInfo->FindElementWithCache(thread, cls, JSTaggedValue(key), num); @@ -152,7 +156,11 @@ double RuntimeTrampolines::FloatMod(double left, double right) uint64_t RuntimeTrampolines::NewInternalString(uint64_t argThread, uint64_t argKey) { + uintptr_t *curFp = nullptr; auto thread = reinterpret_cast(argThread); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); JSHandle keyHandle(thread, JSTaggedValue(reinterpret_cast(argKey))); return JSTaggedValue(thread->GetEcmaVM()->GetFactory()->InternString(keyHandle)).GetRawData(); } diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index f68d32d..95a257b 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -63,6 +63,7 @@ public: thread->SetLastOptCallRuntimePc(pc); JSTaggedType *cursp = const_cast(thread->GetCurrentSPFrame()); lastFp_ = static_cast(static_cast(cursp)); + thread->SetLastIFrameSp(cursp); JSTaggedType *newSp = static_cast(static_cast(newFp)); thread_->SetCurrentSPFrame(newSp); // print newfp and type for debug -- Gitee From bd40fc887aeaa5542f3ef60b4be6646b2519a9f8 Mon Sep 17 00:00:00 2001 From: getingke Date: Thu, 21 Oct 2021 17:36:50 +0800 Subject: [PATCH 080/115] fixed for machine code gc Signed-off-by: getingke Change-Id: Ie45f32af6278363c349924c93e88369344b13677 --- ecmascript/mem/machine_code.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ecmascript/mem/machine_code.h b/ecmascript/mem/machine_code.h index a9504f4..5021053 100644 --- a/ecmascript/mem/machine_code.h +++ b/ecmascript/mem/machine_code.h @@ -69,6 +69,11 @@ public: { return SIZE + this->GetInstructionSizeInBytes().GetInt(); } + + void VisitRangeSlot(const EcmaObjectRangeVisitor &v) + { + // no need to visit + } }; } // namespace ecmascript } // namespace panda -- Gitee From ed967332601512eae8fb3c9af96174beab9980a4 Mon Sep 17 00:00:00 2001 From: getingke Date: Fri, 22 Oct 2021 09:15:12 +0800 Subject: [PATCH 081/115] fixed for asan error Signed-off-by: getingke Change-Id: I6f302a0096667f0bac754182d0481a2f0645ae27 --- ecmascript/compiler/stub.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 9a112b8..6413fb2 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -807,7 +807,7 @@ AddrShift Stub::TaggedIsString(AddrShift obj) { auto env = GetEnvironment(); Label entry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + env->PushCurrentLabel(&entry); Label exit(env); DEFVARIABLE(result, BOOL_TYPE, FalseConstant()); Label isHeapObject(env); @@ -819,14 +819,16 @@ AddrShift Stub::TaggedIsString(AddrShift obj) Jump(&exit); } Bind(&exit); - return *result; + auto ret = *result; + env->PopCurrentLabel(); + return ret; } AddrShift Stub::TaggedIsStringOrSymbol(AddrShift obj) { auto env = GetEnvironment(); Label entry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + env->PushCurrentLabel(&entry); Label exit(env); DEFVARIABLE(result, BOOL_TYPE, FalseConstant()); Label isHeapObject(env); @@ -847,7 +849,9 @@ AddrShift Stub::TaggedIsStringOrSymbol(AddrShift obj) } } Bind(&exit); - return *result; + auto ret = *result; + env->PopCurrentLabel(); + return ret; } AddrShift Stub::IsUtf16String(AddrShift string) @@ -891,7 +895,7 @@ AddrShift Stub::StringToElementIndex(AddrShift string) { auto env = GetEnvironment(); Label entry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + env->PushCurrentLabel(&entry); Label exit(env); DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1)); Label greatThanZero(env); @@ -996,14 +1000,16 @@ AddrShift Stub::StringToElementIndex(AddrShift string) } } Bind(&exit); - return *result; + auto ret = *result; + env->PopCurrentLabel(); + return ret; } AddrShift Stub::TryToElementsIndex(AddrShift key) { auto env = GetEnvironment(); Label entry(env); - [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + env->PushCurrentLabel(&entry); Label exit(env); Label isKeyInt(env); Label notKeyInt(env); @@ -1044,6 +1050,8 @@ AddrShift Stub::TryToElementsIndex(AddrShift key) } } Bind(&exit); - return *resultKey; + auto ret = *resultKey; + env->PopCurrentLabel(); + return ret; } } // namespace kungfu \ No newline at end of file -- Gitee From 136e3f7b08795e2d4e8e5ebbd23294d6d5d156bf Mon Sep 17 00:00:00 2001 From: getingke Date: Mon, 25 Oct 2021 20:50:39 +0800 Subject: [PATCH 082/115] fixed 262 test case fail for getpropertybyvalue Signed-off-by: getingke Change-Id: I33b9d68efeb2d8ed19848699c98dedb984174296 --- ecmascript/compiler/circuit_builder.cpp | 36 +--------- ecmascript/compiler/circuit_builder.h | 7 +- ecmascript/compiler/fast_stub.cpp | 33 +++++----- ecmascript/compiler/gate.cpp | 11 ++-- ecmascript/compiler/gate.h | 5 +- ecmascript/compiler/llvm_ir_builder.cpp | 65 +++++++++++++------ ecmascript/compiler/llvm_ir_builder.h | 15 ++--- ecmascript/compiler/stub.cpp | 8 +-- ecmascript/compiler/stub.h | 25 ++++--- ecmascript/compiler/tests/stub_tests.cpp | 22 ++++--- ecmascript/ecma_vm.cpp | 7 +- .../interpreter/fast_runtime_stub-inl.h | 19 +++++- ecmascript/interpreter/interpreter-inl.h | 20 +++++- ecmascript/js_thread.h | 5 ++ 14 files changed, 159 insertions(+), 119 deletions(-) diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index 541311d..ba3c833 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -334,38 +334,9 @@ OpCode CircuitBuilder::GetCallOpCodeFromMachineType(MachineType type) } } -AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift target, +AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, std::initializer_list args) { - std::vector inputs; - auto dependEntry = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY)); - inputs.push_back(dependEntry); - inputs.push_back(target); - for (auto arg : args) { - inputs.push_back(arg); - } - OpCode opcode = GetCallOpCodeFromMachineType(descriptor->GetReturnType()); - - return circuit_->NewGate(opcode, args.size() + 1, inputs, TypeCode::JS_ANY); -} - -AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift target, AddrShift depend, - std::initializer_list args) -{ - std::vector inputs; - inputs.push_back(depend); - inputs.push_back(target); - for (auto arg : args) { - inputs.push_back(arg); - } - OpCode opcode = GetCallOpCodeFromMachineType(descriptor->GetReturnType()); - return circuit_->NewGate(opcode, args.size() + 1, inputs, TypeCode::JS_ANY); -} - -AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, - std::initializer_list args) -{ - ASSERT(descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB); std::vector inputs; auto dependEntry = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY)); inputs.push_back(dependEntry); @@ -379,10 +350,9 @@ AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShi return circuit_->NewGate(opcode, args.size() + 2, inputs, TypeCode::JS_ANY); } -AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, - AddrShift depend, std::initializer_list args) +AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, + AddrShift depend, std::initializer_list args) { - ASSERT(descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB); std::vector inputs; inputs.push_back(depend); inputs.push_back(target); diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index d027c77..11e1267 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -59,12 +59,9 @@ public: AddrShift NewArithMeticGate(OpCode opcode, AddrShift value); AddrShift NewLogicGate(OpCode opcode, AddrShift left, AddrShift right); AddrShift NewLogicGate(OpCode opcode, AddrShift value); - AddrShift NewCallGate(StubDescriptor *descriptor, AddrShift target, std::initializer_list args); - AddrShift NewCallGate(StubDescriptor *descriptor, AddrShift target, AddrShift depend, - std::initializer_list args); - AddrShift NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, + AddrShift NewCallGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, std::initializer_list args); - AddrShift NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, + AddrShift NewCallGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, AddrShift depend, std::initializer_list args); static OpCode GetLoadOpCodeFromMachineType(MachineType type); static OpCode GetStoreOpCodeFromMachineType(MachineType type); diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index acdbfb4..1047d89 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -74,7 +74,7 @@ void FastAddStub::GenerateCircuit() Bind(&xIsInt); { intX = TaggedCastToInt32(x); - doubleX = CastInt32ToFloat64(*intX); + doubleX = ChangeInt32ToFloat64(*intX); Jump(&xIsNumberAndyIsNumber); } Bind(&xNotInt); @@ -94,7 +94,7 @@ void FastAddStub::GenerateCircuit() Bind(&yIsInt); { intY = TaggedCastToInt32(y); - doubleY = CastInt32ToFloat64(*intY); + doubleY = ChangeInt32ToFloat64(*intY); Jump(&xIsDoubleAndyIsDouble); } Bind(&yNotInt); @@ -149,7 +149,7 @@ void FastSubStub::GenerateCircuit() Bind(&yNotInt); { doubleY = TaggedCastToDouble(y); - doubleX = CastInt32ToFloat64(*intX); + doubleX = ChangeInt32ToFloat64(*intX); Jump(&xNotIntOryNotInt); } } @@ -162,7 +162,7 @@ void FastSubStub::GenerateCircuit() Bind(&yIsInt); { intY = TaggedCastToInt32(y); - doubleY = CastInt32ToFloat64(*intY); + doubleY = ChangeInt32ToFloat64(*intY); Jump(&xNotIntOryNotInt); } Bind(&yNotInt); @@ -210,7 +210,7 @@ void FastMulStub::GenerateCircuit() Bind(&xIsInt); { intX = TaggedCastToInt32(x); - doubleX = CastInt32ToFloat64(*intX); + doubleX = ChangeInt32ToFloat64(*intX); Jump(&xIsNumberAndyIsNumber); } Bind(&xNotInt); @@ -230,7 +230,7 @@ void FastMulStub::GenerateCircuit() Bind(&yIsInt); { intY = TaggedCastToInt32(y); - doubleY = CastInt32ToFloat64(*intY); + doubleY = ChangeInt32ToFloat64(*intY); Jump(&xIsDoubleAndyIsDouble); } Bind(&yNotInt); @@ -271,7 +271,7 @@ void FastDivStub::GenerateCircuit() Bind(&xIsInt); { intX = TaggedCastToInt32(x); - doubleX = CastInt32ToFloat64(*intX); + doubleX = ChangeInt32ToFloat64(*intX); Jump(&xIsNumberAndyIsNumber); } Bind(&xNotInt); @@ -290,7 +290,7 @@ void FastDivStub::GenerateCircuit() Bind(&yIsInt); { intY = TaggedCastToInt32(y); - doubleY = CastInt32ToFloat64(*intY); + doubleY = ChangeInt32ToFloat64(*intY); Jump(&xIsDoubleAndyIsDouble); } Bind(&yNotInt); @@ -418,7 +418,8 @@ void GetElementStub::GenerateCircuit() AddrShift objPtr = ChangeInt64ToPointer(receiver); auto findOwnElementDescriptor = GET_STUBDESCRIPTOR(FindOwnElement); AddrShift callFindOwnElementVal = - CallStub(findOwnElementDescriptor, GetWord64Constant(FAST_STUB_ID(FindOwnElement)), {thread, objPtr, index}); + CallStub(findOwnElementDescriptor, thread, GetWord64Constant(FAST_STUB_ID(FindOwnElement)), + {thread, objPtr, index}); Branch(TaggedIsHole(callFindOwnElementVal), &isHole, ¬Hole); Bind(¬Hole); Return(callFindOwnElementVal); @@ -513,7 +514,7 @@ void SetElementStub::GenerateCircuit() AddrShift elements = GetElements(*holder); AddrShift isDictionary = IsDictionaryMode(elements); StubDescriptor *findOwnElemnt2 = GET_STUBDESCRIPTOR(FindOwnElement2); - AddrShift val = CallStub(findOwnElemnt2, GetWord64Constant(FAST_STUB_ID(FindOwnElement2)), + AddrShift val = CallStub(findOwnElemnt2, thread, GetWord64Constant(FAST_STUB_ID(FindOwnElement2)), {thread, elements, index, isDictionary, pattr, pindexOrEntry}); Label notHole(env); Label isHole(env); @@ -1071,7 +1072,7 @@ void FastModStub::GenerateCircuit() Bind(&xIfInt); { intX = TaggedCastToInt32(x); - doubleX = CastInt32ToFloat64(*intX); + doubleX = ChangeInt32ToFloat64(*intX); Jump(&xIsNumberAndyIsNumber); } Bind(&xIfNotInt); @@ -1090,7 +1091,7 @@ void FastModStub::GenerateCircuit() Bind(&yIfInt); { intY = TaggedCastToInt32(y); - doubleY = CastInt32ToFloat64(*intY); + doubleY = ChangeInt32ToFloat64(*intY); Jump(&xIsDoubleAndyIsDouble); } Bind(&yIfNotInt); @@ -1346,7 +1347,7 @@ void GetPropertyByValueStub::GenerateCircuit() Bind(&validIndex); { auto getPropertyByIndex = GET_STUBDESCRIPTOR(GetPropertyByIndex); - Return(CallStub(getPropertyByIndex, GetWord64Constant(FAST_STUB_ID(GetPropertyByIndex)), + Return(CallStub(getPropertyByIndex, thread, GetWord64Constant(FAST_STUB_ID(GetPropertyByIndex)), {thread, receiver, index})); } Bind(¬ValidIndex); @@ -1383,7 +1384,7 @@ void GetPropertyByValueStub::GenerateCircuit() Bind(&getByName); { auto getPropertyByName = GET_STUBDESCRIPTOR(GetPropertyByName); - Return(CallStub(getPropertyByName, GetWord64Constant(FAST_STUB_ID(GetPropertyByName)), + Return(CallStub(getPropertyByName, thread, GetWord64Constant(FAST_STUB_ID(GetPropertyByName)), {thread, receiver, *key})); } } @@ -1424,7 +1425,7 @@ void SetPropertyByValueStub::GenerateCircuit() Bind(&validIndex); { auto setPropertyByIndex = GET_STUBDESCRIPTOR(SetPropertyByIndex); - Return(CallStub(setPropertyByIndex, GetWord64Constant(FAST_STUB_ID(SetPropertyByIndex)), + Return(CallStub(setPropertyByIndex, thread, GetWord64Constant(FAST_STUB_ID(SetPropertyByIndex)), {thread, receiver, index, value})); } Bind(¬ValidIndex); @@ -1461,7 +1462,7 @@ void SetPropertyByValueStub::GenerateCircuit() Bind(&getByName); { auto setPropertyByName = GET_STUBDESCRIPTOR(SetPropertyByName); - Return(CallStub(setPropertyByName, GetWord64Constant(FAST_STUB_ID(SetPropertyByName)), + Return(CallStub(setPropertyByName, thread, GetWord64Constant(FAST_STUB_ID(SetPropertyByName)), {thread, receiver, *key, value})); } } diff --git a/ecmascript/compiler/gate.cpp b/ecmascript/compiler/gate.cpp index bcecfad..67f3cb1 100644 --- a/ecmascript/compiler/gate.cpp +++ b/ecmascript/compiler/gate.cpp @@ -298,9 +298,11 @@ Properties OpCode::GetProperties() const return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(FLOAT64, PtrValueCode()), NO_ROOT}; case INT32_TO_FLOAT64: return {FLOAT64, NO_STATE, NO_DEPEND, VALUE(INT32), NO_ROOT}; - case INT64_TO_FLOAT64: + case FLOAT64_TO_INT32: + return {INT32, NO_STATE, NO_DEPEND, VALUE(FLOAT64), NO_ROOT}; + case BITCAST_INT64_TO_FLOAT64: return {FLOAT64, NO_STATE, NO_DEPEND, VALUE(INT64), NO_ROOT}; - case FLOAT64_TO_INT64: + case BITCAST_FLOAT64_TO_INT64: return {INT64, NO_STATE, NO_DEPEND, VALUE(FLOAT64), NO_ROOT}; default: std::cerr << "Please complete OpCode properties (OpCode=" << this->op << ")" << std::endl; @@ -488,8 +490,9 @@ std::string OpCode::Str() const {FLOAT32_STORE, "FLOAT32_STORE"}, {FLOAT64_STORE, "FLOAT64_STORE"}, {INT32_TO_FLOAT64, "INT32_TO_FLOAT64"}, - {INT64_TO_FLOAT64, "INT64_TO_FLOAT64"}, - {FLOAT64_TO_INT64, "FLOAT64_TO_INT64"}, + {FLOAT64_TO_INT32, "FLOAT64_TO_INT32"}, + {BITCAST_INT64_TO_FLOAT64, "BITCAST_INT64_TO_FLOAT64"}, + {BITCAST_FLOAT64_TO_INT64, "BITCAST_FLOAT64_TO_INT64"}, }; if (strMap.count(this->op) > 0) { return strMap.at(this->op); diff --git a/ecmascript/compiler/gate.h b/ecmascript/compiler/gate.h index fbc99b7..cf9ff2d 100644 --- a/ecmascript/compiler/gate.h +++ b/ecmascript/compiler/gate.h @@ -228,8 +228,9 @@ public: FLOAT32_STORE, FLOAT64_STORE, INT32_TO_FLOAT64, - INT64_TO_FLOAT64, - FLOAT64_TO_INT64, + FLOAT64_TO_INT32, + BITCAST_INT64_TO_FLOAT64, + BITCAST_FLOAT64_TO_INT64, TAG64_TO_INT1, }; diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index ff7c55b..535c61d 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -142,9 +142,10 @@ void LLVMIRBuilder::AssignHandleMap() {OpCode::INT64_LOAD, &LLVMIRBuilder::HandleLoad}, {OpCode::INT32_STORE, &LLVMIRBuilder::HandleStore}, {OpCode::INT64_STORE, &LLVMIRBuilder::HandleStore}, - {OpCode::INT32_TO_FLOAT64, &LLVMIRBuilder::HandleCastInt32ToDouble}, - {OpCode::INT64_TO_FLOAT64, &LLVMIRBuilder::HandleCastInt64ToDouble}, - {OpCode::FLOAT64_TO_INT64, &LLVMIRBuilder::HandleCastDoubleToInt}, + {OpCode::INT32_TO_FLOAT64, &LLVMIRBuilder::HandleChangeInt32ToDouble}, + {OpCode::FLOAT64_TO_INT32, &LLVMIRBuilder::HandleChangeDoubleToInt32}, + {OpCode::BITCAST_INT64_TO_FLOAT64, &LLVMIRBuilder::HandleCastInt64ToDouble}, + {OpCode::BITCAST_FLOAT64_TO_INT64, &LLVMIRBuilder::HandleCastDoubleToInt}, {OpCode::INT32_LSL, &LLVMIRBuilder::HandleIntLsl}, {OpCode::INT64_LSL, &LLVMIRBuilder::HandleIntLsl}, {OpCode::FLOAT64_SMOD, &LLVMIRBuilder::HandleFloatMod}, @@ -405,24 +406,30 @@ void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inLi int index = circuit_->GetBitField(inList[1]); ASSERT(stubModule_ != nullptr); LLVMValueRef callee; + LLVMValueRef rtoffset; StubDescriptor *callee_descriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(index); + LLVMTypeRef rtfuncType = stubModule_->GetStubFunctionType(index); + LLVMTypeRef rtfuncTypePtr = LLVMPointerType(rtfuncType, 0); + LLVMValueRef thread = g_values[inList[2]]; // 2 : 2 means skip two input gates (target thread) // runtime case if (callee_descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB) { - LLVMTypeRef rtfuncType = stubModule_->GetExternalFunctionType(index); - LLVMTypeRef rtfuncTypePtr = LLVMPointerType(rtfuncType, 0); - LLVMValueRef thread = g_values[inList[2]]; // 2 : 2 means skip two input gates (target thread ) - LLVMValueRef rtoffset = LLVMConstInt(LLVMInt64Type(), + + rtoffset = LLVMConstInt(LLVMInt64Type(), panda::ecmascript::JSThread::GetRuntimeFunctionsOffset() + (index - FAST_STUB_MAXCOUNT) * sizeof(uintptr_t), 0); - LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, thread, rtoffset, ""); - LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(LLVMInt64Type(), 0), ""); - LLVMValueRef llvmAddr = LLVMBuildLoad(builder_, rtbaseAddr, ""); - callee = LLVMBuildIntToPtr(builder_, llvmAddr, rtfuncTypePtr, "cast"); - paraStartIndex += 1; + } else { - callee = stubModule_->GetStubFunction(index); + rtoffset = LLVMConstInt(LLVMInt64Type(), + panda::ecmascript::JSThread::GetFastStubEntryOffset() + + (index) * sizeof(uintptr_t), + 0); } + LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, thread, rtoffset, ""); + LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(LLVMInt64Type(), 0), ""); + LLVMValueRef llvmAddr = LLVMBuildLoad(builder_, rtbaseAddr, ""); + callee = LLVMBuildIntToPtr(builder_, llvmAddr, rtfuncTypePtr, "cast"); + paraStartIndex += 1; // 16 : params limit LLVMValueRef params[16]; for (size_t paraIdx = paraStartIndex; paraIdx < inList.size(); ++paraIdx) { @@ -1094,10 +1101,16 @@ void LLVMIRBuilder::HandleStore(AddrShift gate) } } -void LLVMIRBuilder::HandleCastInt32ToDouble(AddrShift gate) +void LLVMIRBuilder::HandleChangeInt32ToDouble(AddrShift gate) { std::vector ins = circuit_->GetInVector(gate); - VisitCastInt32ToDouble(gate, ins[0]); + VisitChangeInt32ToDouble(gate, ins[0]); +} + +void LLVMIRBuilder::HandleChangeDoubleToInt32(AddrShift gate) +{ + std::vector ins = circuit_->GetInVector(gate); + VisitChangeDoubleToInt32(gate, ins[0]); } void LLVMIRBuilder::VisitFloatSub(AddrShift gate, AddrShift e1, AddrShift e2) const @@ -1281,7 +1294,7 @@ void LLVMIRBuilder::VisitCastIntXToIntY(AddrShift gate, AddrShift e1, MachineRep LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitCastInt32ToDouble(AddrShift gate, AddrShift e1) const +void LLVMIRBuilder::VisitChangeInt32ToDouble(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "int cast2 double gate:" << gate; LLVMValueRef e1Value = g_values[e1]; @@ -1291,6 +1304,16 @@ void LLVMIRBuilder::VisitCastInt32ToDouble(AddrShift gate, AddrShift e1) const LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); } +void LLVMIRBuilder::VisitChangeDoubleToInt32(AddrShift gate, AddrShift e1) const +{ + LOG_ECMA(INFO) << "double cast2 int32 gate:" << gate; + LLVMValueRef e1Value = g_values[e1]; + LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + LLVMValueRef result = LLVMBuildFPToSI(builder_, e1Value, LLVMInt32Type(), ""); + g_values[gate] = result; + LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); +} + void LLVMIRBuilder::HandleCastInt64ToDouble(AddrShift gate) { std::vector ins = circuit_->GetInVector(gate); @@ -1338,12 +1361,12 @@ void LLVMStubModule::Initialize() stubFunctions_[i] = GetLLVMFunctionByStubDescriptor(stubDescriptor); } } - for (i = 0; i < MAX_EXTERNAL_FUNCTION_COUNT; i++) { - auto externalDescriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(i + EXTERNAL_FUNCTION_OFFSET); - if (!externalDescriptor->GetName().empty()) { - externalFunctionType_[i] = GetLLVMFunctionTypeStubDescriptor(externalDescriptor); + for (i = 0; i < MAX_STUB_FUNCTION_COUNT; i++) { + auto stubDescriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(i); + if (!stubDescriptor->GetName().empty()) { + stubFunctionType_[i] = GetLLVMFunctionTypeStubDescriptor(stubDescriptor); } - } + } for (i = 0; i < MAX_TEST_FUNCTION_COUNT; i++) { auto testFuncDescriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(i + TEST_FUNCTION_OFFSET); if (!testFuncDescriptor->GetName().empty()) { diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index 3bb6735..4b2d051 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -115,10 +115,10 @@ public: return module_; } - LLVMTypeRef GetExternalFunctionType(uint32_t index) const + LLVMTypeRef GetStubFunctionType(uint32_t index) const { - ASSERT(index - EXTERNAL_FUNCTION_OFFSET < MAX_EXTERNAL_FUNCTION_COUNT); - return externalFunctionType_[index - EXTERNAL_FUNCTION_OFFSET]; + ASSERT(index < MAX_STUB_FUNCTION_COUNT); + return stubFunctionType_[index]; } LLVMValueRef GetStubFunction(uint32_t index) @@ -137,13 +137,11 @@ private: LLVMValueRef GetLLVMFunctionByStubDescriptor(StubDescriptor *stubDescriptor); LLVMTypeRef GetLLVMFunctionTypeStubDescriptor(StubDescriptor *stubDescriptor); LLVMTypeRef ConvertLLVMTypeFromMachineType(MachineType type); - static constexpr uint32_t MAX_EXTERNAL_FUNCTION_COUNT = - kungfu::EXTERN_RUNTIME_STUB_MAXCOUNT - kungfu::EXTERNAL_RUNTIME_STUB_BEGIN - 1; - static constexpr uint32_t EXTERNAL_FUNCTION_OFFSET = kungfu::EXTERNAL_RUNTIME_STUB_BEGIN + 1; + static constexpr uint32_t MAX_STUB_FUNCTION_COUNT = kungfu::EXTERN_RUNTIME_STUB_MAXCOUNT; static constexpr uint32_t MAX_TEST_FUNCTION_COUNT = kungfu::TEST_FUNC_MAXCOUNT - kungfu::TEST_FUNC_BEGIN - 1; static constexpr uint32_t TEST_FUNCTION_OFFSET = kungfu::TEST_FUNC_BEGIN + 1; std::array stubFunctions_ {nullptr}; - std::array externalFunctionType_ {nullptr}; + std::array stubFunctionType_ {nullptr}; std::array testFunctions_ {nullptr}; LLVMModuleRef module_; }; @@ -182,7 +180,8 @@ private: V(Phi, (AddrShift gate, const std::vector &srcGates, MachineRep rep)) \ V(Return, (AddrShift gate, AddrShift popCount, const std::vector &operands) const ) \ V(CastIntXToIntY, (AddrShift gate, AddrShift e1, MachineRep rep) const ) \ - V(CastInt32ToDouble, (AddrShift gate, AddrShift e1) const ) \ + V(ChangeInt32ToDouble, (AddrShift gate, AddrShift e1) const ) \ + V(ChangeDoubleToInt32, (AddrShift gate, AddrShift e1) const ) \ V(CastInt64ToDouble, (AddrShift gate, AddrShift e1) const ) \ V(CastDoubleToInt, (AddrShift gate, AddrShift e1) const ) \ V(CastInt64ToPointer, (AddrShift gate, AddrShift e1) const ) \ diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 6413fb2..0a739c9 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -950,7 +950,7 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Label loopEnd(env); Label afterLoop(env); Bind(&isDigit); - Branch(Int32LessThan(*i, len), &loopHead, &exit); + Branch(Int32LessThan(*i, len), &loopHead, &afterLoop); LoopBegin(&loopHead); { Label isUtf16(env); @@ -1014,7 +1014,7 @@ AddrShift Stub::TryToElementsIndex(AddrShift key) Label isKeyInt(env); Label notKeyInt(env); - DEFVARIABLE(resultKey, INT32_TYPE, GetInteger32Constant(0)); + DEFVARIABLE(resultKey, INT32_TYPE, GetInteger32Constant(-1)); Branch(TaggedIsInt(key), &isKeyInt, ¬KeyInt); Bind(&isKeyInt); { @@ -1038,9 +1038,9 @@ AddrShift Stub::TryToElementsIndex(AddrShift key) Bind(&isDouble); { AddrShift number = TaggedCastToDouble(key); - AddrShift integer = ChangeInt64ToInt32(CastDoubleToInt64(number)); + AddrShift integer = ChangeFloat64ToInt32(number); Label isEqual(env); - Branch(DoubleEqual(number, CastInt64ToFloat64(SExtInt32ToInt64(integer))), &isEqual, &exit); + Branch(DoubleEqual(number, ChangeInt32ToFloat64(integer)), &isEqual, &exit); Bind(&isEqual); { resultKey = integer; diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 21ba2e2..20b92d9 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -554,17 +554,17 @@ public: void LoopEnd(Label *loopHead); // call operation - AddrShift CallStub(StubDescriptor *descriptor, AddrShift target, std::initializer_list args) + AddrShift CallStub(StubDescriptor *descriptor, AddrShift thread, AddrShift target, std::initializer_list args) { auto depend = env_.GetCurrentLabel()->GetDepend(); - AddrShift result = env_.GetCircuitBuilder().NewCallGate(descriptor, target, depend, args); + AddrShift result = env_.GetCircuitBuilder().NewCallGate(descriptor, thread, target, depend, args); env_.GetCurrentLabel()->SetDepend(result); return result; } - AddrShift CallStub(StubDescriptor *descriptor, AddrShift target, AddrShift depend, + AddrShift CallStub(StubDescriptor *descriptor, AddrShift thread, AddrShift target, AddrShift depend, std::initializer_list args) { - AddrShift result = env_.GetCircuitBuilder().NewCallGate(descriptor, target, depend, args); + AddrShift result = env_.GetCircuitBuilder().NewCallGate(descriptor, thread, target, depend, args); env_.GetCurrentLabel()->SetDepend(result); return result; } @@ -573,7 +573,7 @@ public: std::initializer_list args) { auto depend = env_.GetCurrentLabel()->GetDepend(); - AddrShift result = env_.GetCircuitBuilder().NewCallRuntimeGate(descriptor, thread, target, depend, args); + AddrShift result = env_.GetCircuitBuilder().NewCallGate(descriptor, thread, target, depend, args); env_.GetCurrentLabel()->SetDepend(result); return result; } @@ -581,7 +581,7 @@ public: AddrShift CallRuntime(StubDescriptor *descriptor, AddrShift thread, AddrShift target, AddrShift depend, std::initializer_list args) { - AddrShift result = env_.GetCircuitBuilder().NewCallRuntimeGate(descriptor, thread, target, depend, args); + AddrShift result = env_.GetCircuitBuilder().NewCallGate(descriptor, thread, target, depend, args); env_.GetCurrentLabel()->SetDepend(result); return result; } @@ -851,7 +851,7 @@ public: AddrShift GetNextPositionForHash(AddrShift last, AddrShift count, AddrShift size) { auto nextOffset = Word32LSR(Int32Mul(count, Int32Add(count, GetInteger32Constant(1))), - GetInteger32Constant(2)); + GetInteger32Constant(1)); return Word32And(Int32Add(last, nextOffset), Int32Sub(size, GetInteger32Constant(1))); } @@ -890,7 +890,7 @@ public: AddrShift CastDoubleToInt64(AddrShift x) { - return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::FLOAT64_TO_INT64), x); + return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::BITCAST_FLOAT64_TO_INT64), x); } // compare operation @@ -1364,14 +1364,19 @@ public: return CastInt64ToFloat64(val); } - AddrShift CastInt32ToFloat64(AddrShift x) + AddrShift ChangeInt32ToFloat64(AddrShift x) { return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_TO_FLOAT64), x); } + AddrShift ChangeFloat64ToInt32(AddrShift x) + { + return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::FLOAT64_TO_INT32), x); + } + AddrShift CastInt64ToFloat64(AddrShift x) { - return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT64_TO_FLOAT64), x); + return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::BITCAST_INT64_TO_FLOAT64), x); } AddrShift SExtInt32ToInt64(AddrShift x) diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 9274041..a8d01f1 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -1087,7 +1087,6 @@ void DoSafepoint() } } -#ifdef NDEBUG HWTEST_F_L0(StubTest, GetPropertyByIndexStub) { auto module = stubModule.GetModule(); @@ -1149,7 +1148,7 @@ HWTEST_F_L0(StubTest, SetPropertyByIndexStub) JSArray::FastGetPropertyByValue(thread, JSHandle::Cast(array), i).GetTaggedValue()); } } -#endif + HWTEST_F_L0(StubTest, GetPropertyByNameStub) { @@ -1185,10 +1184,10 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub) EXPECT_EQ(resVal.GetNumber(), y); } -HWTEST_F_L0(StubTest, FastGetPropertyByValueStub) +HWTEST_F_L0(StubTest, GetPropertyByValueStub) { auto module = stubModule.GetModule(); - LLVMValueRef getPropertyByIndexfunction = LLVMGetNamedFunction(module, "GetPropertyByIndex"); + LLVMValueRef getPropertyByIndexfunction = stubModule.GetStubFunction(FAST_STUB_ID(GetPropertyByIndex)); Circuit netOfGates2; GetPropertyByIndexStub getPropertyByIndexStub(&netOfGates2); getPropertyByIndexStub.GenerateCircuit(); @@ -1197,7 +1196,7 @@ HWTEST_F_L0(StubTest, FastGetPropertyByValueStub) LLVMIRBuilder llvmBuilder2(&cfg2, &netOfGates2, &stubModule, getPropertyByIndexfunction); llvmBuilder2.Build(); - LLVMValueRef getPropertyByNamefunction = LLVMGetNamedFunction(module, "GetPropertyByName"); + LLVMValueRef getPropertyByNamefunction = stubModule.GetStubFunction(FAST_STUB_ID(GetPropertyByName)); Circuit netOfGates1; GetPropertyByNameStub getPropertyByNameStub(&netOfGates1); getPropertyByNameStub.GenerateCircuit(); @@ -1207,7 +1206,7 @@ HWTEST_F_L0(StubTest, FastGetPropertyByValueStub) LLVMIRBuilder llvmBuilder1(&cfg1, &netOfGates1, &stubModule, getPropertyByNamefunction); llvmBuilder1.Build(); - LLVMValueRef function = LLVMGetNamedFunction(module, "GetPropertyByValue"); + LLVMValueRef function = stubModule.GetStubFunction(FAST_STUB_ID(GetPropertyByValue)); Circuit netOfGates; GetPropertyByValueStub optimizer(&netOfGates); optimizer.GenerateCircuit(); @@ -1226,13 +1225,16 @@ HWTEST_F_L0(StubTest, FastGetPropertyByValueStub) llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); auto *getPropertyByValuePtr = reinterpret_cast( - reinterpret_cast(LLVMGetPointerToGlobal(engine, function))); + reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function))); auto *getPropertyByNamePtr = reinterpret_cast( - reinterpret_cast(LLVMGetPointerToGlobal(engine, getPropertyByNamefunction))); + reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(getPropertyByNamefunction))); auto *getpropertyByIndexPtr = reinterpret_cast( - reinterpret_cast(LLVMGetPointerToGlobal(engine, getPropertyByIndexfunction))); + reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(getPropertyByIndexfunction))); + + thread->SetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex), reinterpret_cast(getpropertyByIndexPtr)); + thread->SetFastStubEntry(FAST_STUB_ID(GetPropertyByName), reinterpret_cast(getPropertyByNamePtr)); + auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); JSHandle obj = factory->NewEmptyJSObject(); int x = 213; diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 14321d3..eced42c 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -125,8 +125,6 @@ bool EcmaVM::Initialize() trace::ScopedTrace scoped_trace("EcmaVM::Initialize"); Platform::GetCurrentPlatform()->Initialize(); - RuntimeTrampolines::InitializeRuntimeTrampolines(thread_); - auto globalConst = const_cast(thread_->GlobalConstants()); propertiesCache_ = new PropertiesCache(); @@ -167,10 +165,11 @@ bool EcmaVM::Initialize() globalEnv->SetEmptyTaggedQueue(thread_, factory_->NewTaggedQueue(0)); globalEnv->SetTemplateMap(thread_, JSTaggedValue(TemplateMap::Create(thread_))); globalEnv->SetRegisterSymbols(GetJSThread(), JSTaggedValue(SymbolTable::Create(GetJSThread()))); - +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + RuntimeTrampolines::InitializeRuntimeTrampolines(thread_); std::string moduleFile = options_.GetStubModuleFile(); thread_->LoadFastStubModule(moduleFile.c_str()); - +#endif SetupRegExpResultCache(); microJobQueue_ = factory_->NewMicroJobQueue().GetTaggedValue(); diff --git a/ecmascript/interpreter/fast_runtime_stub-inl.h b/ecmascript/interpreter/fast_runtime_stub-inl.h index 88880a6..ab77a6b 100644 --- a/ecmascript/interpreter/fast_runtime_stub-inl.h +++ b/ecmascript/interpreter/fast_runtime_stub-inl.h @@ -622,10 +622,14 @@ bool FastRuntimeStub::FastSetPropertyByIndex(JSThread *thread, JSTaggedValue rec JSTaggedValue value) { INTERPRETER_TRACE(thread, FastSetPropertyByIndex); +#ifdef ECMASCRTPT_ENABLE_STUB_AOT auto *setPropertyByIndex = \ reinterpret_cast \ (reinterpret_cast(thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex)))); JSTaggedValue result = setPropertyByIndex(thread, receiver, index, value); +#else + JSTaggedValue result = FastRuntimeStub::SetPropertyByIndex(thread, receiver, index, value); +#endif if (!result.IsHole()) { return result != JSTaggedValue::Exception(); } @@ -657,9 +661,13 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByName(JSThread *thread, JSTaggedV // Maybe moved by GC receiver = receiverHandler.GetTaggedValue(); } +#ifdef ECMASCRTPT_ENABLE_STUB_AOT auto *getPropertyByNamePtr = reinterpret_cast( thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName))); JSTaggedValue result = getPropertyByNamePtr(thread, receiver, key); +#else + JSTaggedValue result = FastRuntimeStub::GetPropertyByName(thread, receiver, key); +#endif if (result.IsHole()) { return JSTaggedValue::GetProperty(thread, JSHandle(thread, receiver), JSHandle(thread, key)) @@ -672,7 +680,13 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByName(JSThread *thread, JSTaggedV JSTaggedValue FastRuntimeStub::FastGetPropertyByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key) { INTERPRETER_TRACE(thread, FastGetPropertyByValue); +#ifdef ECMASCRTPT_ENABLE_STUB_AOT + auto *getPropertyByValuePtr = reinterpret_cast( + thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue))); + JSTaggedValue result = getPropertyByValuePtr(thread, receiver.GetRawData(), key.GetRawData()); +#else JSTaggedValue result = FastRuntimeStub::GetPropertyByValue(thread, receiver, key); +#endif if (result.IsHole()) { return JSTaggedValue::GetProperty(thread, JSHandle(thread, receiver), JSHandle(thread, key)) @@ -686,10 +700,13 @@ template // UseHole is only for Array::Sort() which requires Hole JSTaggedValue FastRuntimeStub::FastGetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index) { INTERPRETER_TRACE(thread, FastGetPropertyByIndex); +#ifdef ECMASCRTPT_ENABLE_STUB_AOT auto getPropertyByIndex = reinterpret_cast( thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex))); - JSTaggedValue result = getPropertyByIndex(thread, receiver, index); +#else + JSTaggedValue result = FastRuntimeStub::GetPropertyByIndex(thread, receiver, index); +#endif if (result.IsHole() && !UseHole) { return JSTaggedValue::GetProperty(thread, JSHandle(thread, receiver), index) .GetValue() diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 2683016..7207ded 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -2456,9 +2456,13 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue receiver = GET_VREG_VALUE(v0); // fast path if (LIKELY(receiver.IsHeapObject())) { +#ifdef ECMASCRTPT_ENABLE_STUB_AOT auto getPropertyByIndex = reinterpret_cast( thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex))); JSTaggedValue res = getPropertyByIndex(thread, receiver, idx); +#else + JSTaggedValue res = FastRuntimeStub::GetPropertyByIndex(thread, receiver, idx); +#endif if (!res.IsHole()) { INTERPRETER_RETURN_IF_ABRUPT(res); SET_ACC(res); @@ -2483,10 +2487,14 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool SAVE_ACC(); JSTaggedValue value = GET_ACC(); // fast path +#ifdef ECMASCRTPT_ENABLE_STUB_AOT auto *setPropertyByIndex = \ reinterpret_cast \ (reinterpret_cast(thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex)))); JSTaggedValue res = setPropertyByIndex(thread, receiver, index, value); +#else + JSTaggedValue res = FastRuntimeStub::SetPropertyByIndex(thread, receiver, index, value); +#endif if (!res.IsHole()) { INTERPRETER_RETURN_IF_ABRUPT(res); RESTORE_ACC(); @@ -2514,7 +2522,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool #if ECMASCRIPT_ENABLE_IC auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp); - if (!profileTypeInfo.IsUndefined()) { + if (!profileTypeInfo.IsUndefined()) { uint16_t slotId = READ_INST_8_0(); auto profileTypeArray = ProfileTypeInfo::Cast(profileTypeInfo.GetTaggedObject()); JSTaggedValue firstValue = profileTypeArray->Get(slotId); @@ -2538,7 +2546,13 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool #endif // fast path if (LIKELY(receiver.IsHeapObject())) { +#ifdef ECMASCRTPT_ENABLE_STUB_AOT + auto *getPropertyByValuePtr = reinterpret_cast( + thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue))); + JSTaggedValue res = getPropertyByValuePtr(thread, receiver, propKey); +#else JSTaggedValue res = FastRuntimeStub::GetPropertyByValue(thread, receiver, propKey); +#endif if (!res.IsHole()) { ASSERT(!res.IsAccessor()); INTERPRETER_RETURN_IF_ABRUPT(res); @@ -2909,9 +2923,13 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool if (LIKELY(receiver.IsHeapObject())) { // fast path +#ifdef ECMASCRTPT_ENABLE_STUB_AOT auto *getPropertyByNamePtr = reinterpret_cast( thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName))); JSTaggedValue res = getPropertyByNamePtr(thread, receiver, propKey); +#else + JSTaggedValue res = FastRuntimeStub::GetPropertyByName(thread, receiver, propKey); +#endif if (!res.IsHole()) { ASSERT(!res.IsAccessor()); INTERPRETER_RETURN_IF_ABRUPT(res); diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index c888107..317954f 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -205,6 +205,11 @@ public: return MEMBER_OFFSET(JSThread, globalConst_); } + static uint64_t GetFastStubEntryOffset() + { + return MEMBER_OFFSET(JSThread, fastStubEntires_); + } + InternalCallParams *GetInternalCallParams() const { return internalCallParams_; -- Gitee From 27a544bf5675c3fc70b95b639936bff0bb3690aa Mon Sep 17 00:00:00 2001 From: getingke Date: Tue, 26 Oct 2021 18:52:26 +0800 Subject: [PATCH 083/115] fixed for review comment by wuzhefeng Signed-off-by: getingke Change-Id: Ie4b779dd73db792c4d8315ad3a051fb9692d0623 --- BUILD.gn | 3 + ecmascript/compiler/BUILD.gn | 1 - ecmascript/compiler/fast_stub.cpp | 2 +- ecmascript/compiler/llvm_codegen.cpp | 202 ++++++++++++++++++ ecmascript/compiler/llvm_codegen.h | 154 ++++++++++++- ecmascript/compiler/llvm_ir_builder.cpp | 2 +- ecmascript/compiler/llvm_mcjit_engine.cpp | 199 +---------------- ecmascript/compiler/llvm_mcjit_engine.h | 156 -------------- ecmascript/compiler/stub.cpp | 5 +- ecmascript/compiler/stub.h | 2 +- ecmascript/compiler/stub_descriptor.cpp | 21 +- ecmascript/compiler/tests/stub_tests.cpp | 8 +- ecmascript/ecma_vm.cpp | 2 +- .../interpreter/fast_runtime_stub-inl.h | 23 +- ecmascript/interpreter/fast_runtime_stub.h | 1 - ecmascript/interpreter/frame_handler.cpp | 8 +- ecmascript/interpreter/interpreter-inl.h | 49 ++--- ecmascript/interpreter/interpreter.h | 1 + ecmascript/mem/machine_code.h | 5 - js_runtime_config.gni | 1 + 20 files changed, 421 insertions(+), 424 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 042bdd5..da0e9f2 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -132,6 +132,9 @@ source_set("libark_js_intl_static") { config("ark_jsruntime_common_config") { defines = [ "PANDA_ENABLE_LTO" ] + if (enable_stub_aot) { + defines += [ "ECMASCRIPT_ENABLE_STUB_AOT" ] + } if (is_standard_system) { defines += [ "IS_STANDARD_SYSTEM" ] diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index 6c63f6d..a2884c9 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -46,7 +46,6 @@ source_set("libark_jsoptimizer_static") { "gate.cpp", "llvm_codegen.cpp", "llvm_ir_builder.cpp", - "llvm_mcjit_engine.cpp", "scheduler.cpp", "stub.cpp", "stub_descriptor.cpp", diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 1047d89..19c87b3 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -1308,7 +1308,7 @@ void FunctionCallInternalStub::GenerateCircuit() { Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcIsBuiltinsConstructorOrFuncNotClassConstructor); Bind(&funcIsClassConstructor); - ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(FunctionCallNotConstructor), FalseConstant()); + ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(FunctionCallNotConstructor), GetExceptionConstant()); } Bind(&funcIsBuiltinsConstructorOrFuncNotClassConstructor); StubDescriptor *execute = GET_STUBDESCRIPTOR(Execute); diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index d0c2606..8cd7e6b 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -14,8 +14,38 @@ */ #include "llvm_codegen.h" +#include #include "ecmascript/object_factory.h" #include "stub_descriptor.h" +#include "llvm/ADT/APInt.h" +#include "llvm/CodeGen/BuiltinGCs.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Verifier.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm-c/Analysis.h" +#include "llvm-c/Core.h" +#include "llvm-c/Disassembler.h" +#include "llvm-c/DisassemblerTypes.h" +#include "llvm-c/Target.h" +#include "llvm-c/Transforms/PassManagerBuilder.h" +#include "llvm-c/Transforms/Scalar.h" using namespace panda::ecmascript; namespace kungfu { @@ -45,4 +75,176 @@ void LLVMModuleAssembler::AssembleStubModule(StubModule *module) } assembler_.Disassemble(); } + +static uint8_t *RoundTripAllocateCodeSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, + [[maybe_unused]] unsigned sectionID, const char *sectionName) +{ + LOG_ECMA(INFO) << "RoundTripAllocateCodeSection object " << object << " - "; + struct CodeInfo& state = *static_cast(object); + uint8_t *addr = state.AllocaCodeSection(size, sectionName); + LOG_ECMA(INFO) << "RoundTripAllocateCodeSection addr:" << std::hex << reinterpret_cast(addr) << + addr << " size:0x" << size << " + "; + return addr; +} + +static uint8_t *RoundTripAllocateDataSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, + [[maybe_unused]] unsigned sectionID, const char *sectionName, + [[maybe_unused]] LLVMBool isReadOnly) +{ + struct CodeInfo& state = *static_cast(object); + return state.AllocaDataSection(size, sectionName); +} + +static LLVMBool RoundTripFinalizeMemory(void *object, [[maybe_unused]] char **errMsg) +{ + LOG_ECMA(INFO) << "RoundTripFinalizeMemory object " << object << " - "; + return 0; +} + +static void RoundTripDestroy(void *object) +{ + LOG_ECMA(INFO) << "RoundTripDestroy object " << object << " - "; +} + +void LLVMAssembler::UseRoundTripSectionMemoryManager() +{ + auto sectionMemoryManager = std::make_unique(); + options_.MCJMM = + LLVMCreateSimpleMCJITMemoryManager(&codeInfo_, RoundTripAllocateCodeSection, + RoundTripAllocateDataSection, RoundTripFinalizeMemory, RoundTripDestroy); +} + +bool LLVMAssembler::BuildMCJITEngine() +{ + LOG_ECMA(INFO) << " BuildMCJITEngine - "; + LLVMBool ret = LLVMCreateMCJITCompilerForModule(&engine_, module_, &options_, sizeof(options_), &error_); + if (ret) { + LOG_ECMA(ERROR) << "error_ : " << error_; + return false; + } + LOG_ECMA(INFO) << " BuildMCJITEngine + "; + return true; +} + +void LLVMAssembler::BuildAndRunPasses() const +{ + LOG_ECMA(INFO) << "BuildAndRunPasses - "; + LLVMPassManagerRef pass = LLVMCreatePassManager(); + LLVMAddConstantPropagationPass(pass); + LLVMAddInstructionCombiningPass(pass); + llvm::unwrap(pass)->add(llvm::createRewriteStatepointsForGCLegacyPass()); + char *info = LLVMPrintModuleToString(module_); + LOG_ECMA(INFO) << "Current Module: " << info; + LLVMDisposeMessage(info); + LLVMRunPassManager(pass, module_); + LLVMDisposePassManager(pass); + LOG_ECMA(INFO) << "BuildAndRunPasses + "; +} + +LLVMAssembler::LLVMAssembler(LLVMModuleRef module, const char* triple): module_(module), engine_(nullptr), + hostTriple_(triple), error_(nullptr) +{ + Initialize(); +} + +LLVMAssembler::~LLVMAssembler() +{ + module_ = nullptr; + if (engine_ != nullptr) { + LLVMDisposeExecutionEngine(engine_); + } + hostTriple_ = ""; + error_ = nullptr; +} + +void LLVMAssembler::Run() +{ + char *error = nullptr; + LLVMVerifyModule(module_, LLVMAbortProcessAction, &error); + LLVMDisposeMessage(error); + UseRoundTripSectionMemoryManager(); + if (!BuildMCJITEngine()) { + return; + } + BuildAndRunPasses(); +} + +void LLVMAssembler::Initialize() +{ + if (hostTriple_.compare(AMD64_TRIPLE) == 0) { + LLVMInitializeX86TargetInfo(); + LLVMInitializeX86TargetMC(); + LLVMInitializeX86Disassembler(); + /* this method must be called, ohterwise "Target does not support MC emission" */ + LLVMInitializeX86AsmPrinter(); + LLVMInitializeX86AsmParser(); + LLVMInitializeX86Target(); + } else if (hostTriple_.compare(ARM64_TRIPLE) == 0) { + LLVMInitializeAArch64TargetInfo(); + LLVMInitializeAArch64TargetMC(); + LLVMInitializeAArch64Disassembler(); + LLVMInitializeAArch64AsmPrinter(); + LLVMInitializeAArch64AsmParser(); + LLVMInitializeAArch64Target(); + } else if (hostTriple_.compare(ARM32_TRIPLE) == 0) { + LLVMInitializeARMTargetInfo(); + LLVMInitializeARMTargetMC(); + LLVMInitializeARMDisassembler(); + LLVMInitializeARMAsmPrinter(); + LLVMInitializeARMAsmParser(); + LLVMInitializeARMTarget(); + } else { + UNREACHABLE(); + } + llvm::linkAllBuiltinGCs(); + LLVMInitializeMCJITCompilerOptions(&options_, sizeof(options_)); + options_.OptLevel = 2; // opt level 2 + // Just ensure that this field still exists. + options_.NoFramePointerElim = true; +} + +static const char *SymbolLookupCallback([[maybe_unused]] void *disInfo, [[maybe_unused]] uint64_t referenceValue, + uint64_t *referenceType, [[maybe_unused]]uint64_t referencePC, + [[maybe_unused]] const char **referenceName) +{ + *referenceType = LLVMDisassembler_ReferenceType_InOut_None; + return nullptr; +} + +void LLVMAssembler::Disassemble(std::map addr2name) const +{ + LLVMDisasmContextRef dcr = LLVMCreateDisasm(hostTriple_.c_str(), nullptr, 0, nullptr, SymbolLookupCallback); + std::cout << "========================================================================" << std::endl; + for (auto it : codeInfo_.GetCodeInfo()) { + uint8_t *byteSp; + uintptr_t numBytes; + byteSp = it.first; + numBytes = it.second; + std::cout << " byteSp:" << std::hex << reinterpret_cast(byteSp) << " numBytes:0x" << numBytes + << std::endl; + + unsigned pc = 0; + const char outStringSize = 100; + char outString[outStringSize]; + while (numBytes != 0) { + size_t InstSize = LLVMDisasmInstruction(dcr, byteSp, numBytes, pc, outString, outStringSize); + if (InstSize == 0) { + fprintf(stderr, "%08x: %08x maybe constant\n", pc, *reinterpret_cast(byteSp)); + pc += 4; // 4 pc length + byteSp += 4; // 4 sp offset + numBytes -= 4; // 4 num bytes + } + uint64_t addr = reinterpret_cast(byteSp); + if (addr2name.find(addr) != addr2name.end()) { + std::cout << addr2name[addr].c_str() << ":" << std::endl; + } + (void)fprintf(stderr, "%08x: %08x %s\n", pc, *reinterpret_cast(byteSp), outString); + pc += InstSize; + byteSp += InstSize; + numBytes -= InstSize; + } + } + std::cout << "========================================================================" << std::endl; + LLVMDisasmDispose(dcr); +} } // namespace kungfu diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index 3fc988a..d303400 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -15,17 +15,169 @@ #ifndef ECMASCRIPT_COMPILER_LLVM_CODEGEN_H #define ECMASCRIPT_COMPILER_LLVM_CODEGEN_H +#include +#include +#include +#include +#include #include "code_generator.h" #include "ecmascript/compiler/llvm_ir_builder.h" -#include "ecmascript/compiler/llvm_mcjit_engine.h" +#include "ecmascript/ecma_macros.h" #include "ecmascript/js_thread.h" #include "ecmascript/stub_module.h" #include "llvm-c/Types.h" +#include "llvm-c/Analysis.h" +#include "llvm-c/Core.h" +#include "llvm-c/ExecutionEngine.h" +#include "llvm-c/Target.h" +#include "llvm-c/Transforms/PassManagerBuilder.h" +#include "llvm-c/Transforms/Scalar.h" #include "llvm/IR/Instructions.h" #include "llvm/Support/Host.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" namespace kungfu { +struct CodeInfo { + using ByteBuffer = std::vector; + using BufferList = std::list; + using StringList = std::list; + CodeInfo() : machineCode_(nullptr), codeBufferPos_(0), stackMapsSection_(nullptr) + { + Reset(); + static constexpr int prot = PROT_READ | PROT_WRITE | PROT_EXEC; // NOLINT(hicpp-signed-bitwise) + static constexpr int flags = MAP_ANONYMOUS | MAP_SHARED; // NOLINT(hicpp-signed-bitwise) + machineCode_ = static_cast(mmap(nullptr, MAX_MACHINE_CODE_SIZE, prot, flags, -1, 0)); + } + ~CodeInfo() + { + Reset(); + munmap(machineCode_, MAX_MACHINE_CODE_SIZE); + machineCode_ = nullptr; + } + uint8_t *AllocaCodeSection(uintptr_t size, const char *sectionName) + { + uint8_t *addr = nullptr; + if (codeBufferPos_ + size > MAX_MACHINE_CODE_SIZE) { + LOG_ECMA(INFO) << std::hex << "AllocaCodeSection failed alloc codeBufferPos_:" << codeBufferPos_ + << " size:" << size << " larger MAX_MACHINE_CODE_SIZE:" << MAX_MACHINE_CODE_SIZE; + return nullptr; + } + LOG_ECMA(INFO) << "AllocaCodeSection size:" << size; + std::vector codeBuffer(machineCode_[codeBufferPos_], size); + LOG_ECMA(INFO) << " codeBuffer size: " << codeBuffer.size(); + codeSectionNames_.push_back(sectionName); + addr = machineCode_ + codeBufferPos_; + LOG_ECMA(INFO) << "AllocaCodeSection addr:" << std::hex << reinterpret_cast(addr); + codeInfo_.push_back({addr, size}); + codeBufferPos_ += size; + return addr; + } + + uint8_t *AllocaDataSection(uintptr_t size, const char *sectionName) + { + uint8_t *addr = nullptr; + dataSectionList_.push_back(std::vector()); + dataSectionList_.back().resize(size); + dataSectionNames_.push_back(sectionName); + addr = static_cast(dataSectionList_.back().data()); + if (!strcmp(sectionName, ".llvm_stackmaps")) { + LOG_ECMA(INFO) << "llvm_stackmaps : " << addr; + stackMapsSection_ = addr; + } + return addr; + } + + void Reset() + { + stackMapsSection_ = nullptr; + codeInfo_.clear(); + dataSectionList_.clear(); + dataSectionNames_.clear(); + codeSectionNames_.clear(); + codeBufferPos_ = 0; + } + + uint8_t *GetStackMapsSection() const + { + return stackMapsSection_; + } + std::vector> GetCodeInfo() const + { + return codeInfo_; + } + + int GetCodeSize() const + { + return codeBufferPos_; + } + + uint8_t *GetCodeBuff() const + { + return machineCode_; + } + +private: + BufferList dataSectionList_ {}; + StringList dataSectionNames_ {}; + StringList codeSectionNames_ {}; + uint8_t *machineCode_; + const size_t MAX_MACHINE_CODE_SIZE = (1 << 20); // 1M + int codeBufferPos_ = 0; + /* for asssembler */ + std::vector> codeInfo_ {}; + /* stack map */ + uint8_t *stackMapsSection_ {nullptr}; +}; +class LLVMAssembler { +public: + explicit LLVMAssembler(LLVMModuleRef module, const char* triple); + virtual ~LLVMAssembler(); + void Run(); + const LLVMExecutionEngineRef &GetEngine() + { + return engine_; + } + void Disassemble(std::map addr2name = std::map()) const; + uint8_t *GetStackMapsSection() const + { + return codeInfo_.GetStackMapsSection(); + } + + int GetCodeSize() const + { + return codeInfo_.GetCodeSize(); + } + uint8_t *GetCodeBuffer() const + { + return codeInfo_.GetCodeBuff(); + } + + void *GetFuncPtrFromCompiledModule(LLVMValueRef function) + { + return LLVMGetPointerToGlobal(engine_, function); + } + const char *AMD64_TRIPLE = "x86_64-unknown-linux-gnu"; + const char *ARM64_TRIPLE = "aarch64-unknown-linux-gnu"; + const char *ARM32_TRIPLE = "arm-unknown-linux-gnu"; +private: + void UseRoundTripSectionMemoryManager(); + bool BuildMCJITEngine(); + void BuildAndRunPasses() const; + void BuildSimpleFunction(); + void Initialize(); + void InitMember(); + + LLVMMCJITCompilerOptions options_; + LLVMModuleRef module_; + LLVMExecutionEngineRef engine_; + std::string hostTriple_; + char *error_; + struct CodeInfo codeInfo_; +}; + class LLVMCodeGeneratorImpl : public CodeGeneratorImpl { public: explicit LLVMCodeGeneratorImpl(LLVMStubModule *module) : module_(module) {} diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 535c61d..4431d72 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -1366,7 +1366,7 @@ void LLVMStubModule::Initialize() if (!stubDescriptor->GetName().empty()) { stubFunctionType_[i] = GetLLVMFunctionTypeStubDescriptor(stubDescriptor); } - } + } for (i = 0; i < MAX_TEST_FUNCTION_COUNT; i++) { auto testFuncDescriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(i + TEST_FUNCTION_OFFSET); if (!testFuncDescriptor->GetName().empty()) { diff --git a/ecmascript/compiler/llvm_mcjit_engine.cpp b/ecmascript/compiler/llvm_mcjit_engine.cpp index 3fb6d34..782d31b 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.cpp +++ b/ecmascript/compiler/llvm_mcjit_engine.cpp @@ -13,208 +13,11 @@ * limitations under the License. */ -#include "llvm_mcjit_engine.h" -#include -#include "ecmascript/ecma_macros.h" -#include "llvm/ADT/APInt.h" -#include "llvm/CodeGen/BuiltinGCs.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/IR/Argument.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Verifier.h" -#include "llvm/IRReader/IRReader.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm-c/Analysis.h" -#include "llvm-c/Core.h" -#include "llvm-c/Disassembler.h" -#include "llvm-c/DisassemblerTypes.h" -#include "llvm-c/Target.h" -#include "llvm-c/Transforms/PassManagerBuilder.h" -#include "llvm-c/Transforms/Scalar.h" -namespace kungfu { -static uint8_t *RoundTripAllocateCodeSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, - [[maybe_unused]] unsigned sectionID, const char *sectionName) -{ - LOG_ECMA(INFO) << "RoundTripAllocateCodeSection object " << object << " - "; - struct CodeInfo& state = *static_cast(object); - uint8_t *addr = state.AllocaCodeSection(size, sectionName); - LOG_ECMA(INFO) << "RoundTripAllocateCodeSection addr:" << std::hex << reinterpret_cast(addr) << - addr << " size:0x" << size << " + "; - return addr; -} - -static uint8_t *RoundTripAllocateDataSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, - [[maybe_unused]] unsigned sectionID, const char *sectionName, - [[maybe_unused]] LLVMBool isReadOnly) -{ - struct CodeInfo& state = *static_cast(object); - return state.AllocaDataSection(size, sectionName); -} - -static LLVMBool RoundTripFinalizeMemory(void *object, [[maybe_unused]] char **errMsg) -{ - LOG_ECMA(INFO) << "RoundTripFinalizeMemory object " << object << " - "; - return 0; -} - -static void RoundTripDestroy(void *object) -{ - LOG_ECMA(INFO) << "RoundTripDestroy object " << object << " - "; -} - -void LLVMAssembler::UseRoundTripSectionMemoryManager() -{ - auto sectionMemoryManager = std::make_unique(); - options_.MCJMM = - LLVMCreateSimpleMCJITMemoryManager(&codeInfo_, RoundTripAllocateCodeSection, - RoundTripAllocateDataSection, RoundTripFinalizeMemory, RoundTripDestroy); -} - -bool LLVMAssembler::BuildMCJITEngine() -{ - LOG_ECMA(INFO) << " BuildMCJITEngine - "; - LLVMBool ret = LLVMCreateMCJITCompilerForModule(&engine_, module_, &options_, sizeof(options_), &error_); - if (ret) { - LOG_ECMA(ERROR) << "error_ : " << error_; - return false; - } - LOG_ECMA(INFO) << " BuildMCJITEngine + "; - return true; -} -void LLVMAssembler::BuildAndRunPasses() const -{ - LOG_ECMA(INFO) << "BuildAndRunPasses - "; - LLVMPassManagerRef pass = LLVMCreatePassManager(); - LLVMAddConstantPropagationPass(pass); - LLVMAddInstructionCombiningPass(pass); - llvm::unwrap(pass)->add(llvm::createRewriteStatepointsForGCLegacyPass()); - char *info = LLVMPrintModuleToString(module_); - LOG_ECMA(INFO) << "Current Module: " << info; - LLVMDisposeMessage(info); - LLVMRunPassManager(pass, module_); - LLVMDisposePassManager(pass); - LOG_ECMA(INFO) << "BuildAndRunPasses + "; -} -LLVMAssembler::LLVMAssembler(LLVMModuleRef module, const char* triple): module_(module), engine_(nullptr), - hostTriple_(triple), error_(nullptr) -{ - Initialize(); -} - -LLVMAssembler::~LLVMAssembler() -{ - module_ = nullptr; - if (engine_ != nullptr) { - LLVMDisposeExecutionEngine(engine_); - } - hostTriple_ = ""; - error_ = nullptr; -} - -void LLVMAssembler::Run() -{ - UseRoundTripSectionMemoryManager(); - if (!BuildMCJITEngine()) { - return; - } - BuildAndRunPasses(); -} - -void LLVMAssembler::Initialize() -{ - if (hostTriple_.compare(AMD64_TRIPLE) == 0) { - LLVMInitializeX86TargetInfo(); - LLVMInitializeX86TargetMC(); - LLVMInitializeX86Disassembler(); - /* this method must be called, ohterwise "Target does not support MC emission" */ - LLVMInitializeX86AsmPrinter(); - LLVMInitializeX86AsmParser(); - LLVMInitializeX86Target(); - } else if (hostTriple_.compare(ARM64_TRIPLE) == 0) { - LLVMInitializeAArch64TargetInfo(); - LLVMInitializeAArch64TargetMC(); - LLVMInitializeAArch64Disassembler(); - LLVMInitializeAArch64AsmPrinter(); - LLVMInitializeAArch64AsmParser(); - LLVMInitializeAArch64Target(); - } else if (hostTriple_.compare(ARM32_TRIPLE) == 0) { - LLVMInitializeARMTargetInfo(); - LLVMInitializeARMTargetMC(); - LLVMInitializeARMDisassembler(); - LLVMInitializeARMAsmPrinter(); - LLVMInitializeARMAsmParser(); - LLVMInitializeARMTarget(); - } else { - UNREACHABLE(); - } - llvm::linkAllBuiltinGCs(); - LLVMInitializeMCJITCompilerOptions(&options_, sizeof(options_)); - options_.OptLevel = 2; // opt level 2 - // Just ensure that this field still exists. - options_.NoFramePointerElim = true; -} - -static const char *SymbolLookupCallback([[maybe_unused]] void *disInfo, [[maybe_unused]] uint64_t referenceValue, - uint64_t *referenceType, [[maybe_unused]]uint64_t referencePC, - [[maybe_unused]] const char **referenceName) -{ - *referenceType = LLVMDisassembler_ReferenceType_InOut_None; - return nullptr; -} - -void LLVMAssembler::Disassemble(std::map addr2name) const -{ - LLVMDisasmContextRef dcr = LLVMCreateDisasm(hostTriple_.c_str(), nullptr, 0, nullptr, SymbolLookupCallback); - std::cout << "========================================================================" << std::endl; - for (auto it : codeInfo_.GetCodeInfo()) { - uint8_t *byteSp; - uintptr_t numBytes; - byteSp = it.first; - numBytes = it.second; - std::cout << " byteSp:" << std::hex << reinterpret_cast(byteSp) << " numBytes:0x" << numBytes - << std::endl; +namespace kungfu { - unsigned pc = 0; - const char outStringSize = 100; - char outString[outStringSize]; - while (numBytes != 0) { - size_t InstSize = LLVMDisasmInstruction(dcr, byteSp, numBytes, pc, outString, outStringSize); - if (InstSize == 0) { - fprintf(stderr, "%08x: %08x maybe constant\n", pc, *reinterpret_cast(byteSp)); - pc += 4; // 4 pc length - byteSp += 4; // 4 sp offset - numBytes -= 4; // 4 num bytes - } - uint64_t addr = reinterpret_cast(byteSp); - if (addr2name.find(addr) != addr2name.end()) { - std::cout << addr2name[addr].c_str() << ":" << std::endl; - } - (void)fprintf(stderr, "%08x: %08x %s\n", pc, *reinterpret_cast(byteSp), outString); - pc += InstSize; - byteSp += InstSize; - numBytes -= InstSize; - } - } - std::cout << "========================================================================" << std::endl; - LLVMDisasmDispose(dcr); -} } // namespace kungfu diff --git a/ecmascript/compiler/llvm_mcjit_engine.h b/ecmascript/compiler/llvm_mcjit_engine.h index feb851f..e1cd9c8 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.h +++ b/ecmascript/compiler/llvm_mcjit_engine.h @@ -16,161 +16,5 @@ #ifndef ECMASCRIPT_COMPILER_LLVM_MCJINT_ENGINE_H #define ECMASCRIPT_COMPILER_LLVM_MCJINT_ENGINE_H -#include -#include -#include -#include -#include - -#include "ecmascript/ecma_macros.h" -#include "llvm/ExecutionEngine/Interpreter.h" -#include "llvm/ExecutionEngine/MCJIT.h" -#include "llvm/ExecutionEngine/SectionMemoryManager.h" - -#include "llvm-c/Analysis.h" -#include "llvm-c/Core.h" -#include "llvm-c/ExecutionEngine.h" -#include "llvm-c/Target.h" -#include "llvm-c/Transforms/PassManagerBuilder.h" -#include "llvm-c/Transforms/Scalar.h" - -namespace kungfu { -struct CodeInfo { - using ByteBuffer = std::vector; - using BufferList = std::list; - using StringList = std::list; - CodeInfo() : machineCode_(nullptr), codeBufferPos_(0), stackMapsSection_(nullptr) - { - Reset(); - static constexpr int prot = PROT_READ | PROT_WRITE | PROT_EXEC; // NOLINT(hicpp-signed-bitwise) - static constexpr int flags = MAP_ANONYMOUS | MAP_SHARED; // NOLINT(hicpp-signed-bitwise) - machineCode_ = static_cast(mmap(nullptr, MAX_MACHINE_CODE_SIZE, prot, flags, -1, 0)); - } - ~CodeInfo() - { - Reset(); - munmap(machineCode_, MAX_MACHINE_CODE_SIZE); - machineCode_ = nullptr; - } - uint8_t *AllocaCodeSection(uintptr_t size, const char *sectionName) - { - uint8_t *addr = nullptr; - if (codeBufferPos_ + size > MAX_MACHINE_CODE_SIZE) { - LOG_ECMA(INFO) << std::hex << "AllocaCodeSection failed alloc codeBufferPos_:" << codeBufferPos_ - << " size:" << size << " larger MAX_MACHINE_CODE_SIZE:" << MAX_MACHINE_CODE_SIZE; - return nullptr; - } - LOG_ECMA(INFO) << "AllocaCodeSection size:" << size; - std::vector codeBuffer(machineCode_[codeBufferPos_], size); - LOG_ECMA(INFO) << " codeBuffer size: " << codeBuffer.size(); - codeSectionNames_.push_back(sectionName); - addr = machineCode_ + codeBufferPos_; - LOG_ECMA(INFO) << "AllocaCodeSection addr:" << std::hex << reinterpret_cast(addr); - codeInfo_.push_back({addr, size}); - codeBufferPos_ += size; - return addr; - } - - uint8_t *AllocaDataSection(uintptr_t size, const char *sectionName) - { - uint8_t *addr = nullptr; - dataSectionList_.push_back(std::vector()); - dataSectionList_.back().resize(size); - dataSectionNames_.push_back(sectionName); - addr = static_cast(dataSectionList_.back().data()); - if (!strcmp(sectionName, ".llvm_stackmaps")) { - LOG_ECMA(INFO) << "llvm_stackmaps : " << addr; - stackMapsSection_ = addr; - } - return addr; - } - - void Reset() - { - stackMapsSection_ = nullptr; - codeInfo_.clear(); - dataSectionList_.clear(); - dataSectionNames_.clear(); - codeSectionNames_.clear(); - codeBufferPos_ = 0; - } - - uint8_t *GetStackMapsSection() const - { - return stackMapsSection_; - } - std::vector> GetCodeInfo() const - { - return codeInfo_; - } - - int GetCodeSize() const - { - return codeBufferPos_; - } - - uint8_t *GetCodeBuff() const - { - return machineCode_; - } - -private: - BufferList dataSectionList_ {}; - StringList dataSectionNames_ {}; - StringList codeSectionNames_ {}; - uint8_t *machineCode_; - const size_t MAX_MACHINE_CODE_SIZE = (1 << 20); // 1M - int codeBufferPos_ = 0; - /* for asssembler */ - std::vector> codeInfo_ {}; - /* stack map */ - uint8_t *stackMapsSection_ {nullptr}; -}; -class LLVMAssembler { -public: - explicit LLVMAssembler(LLVMModuleRef module, const char* triple); - virtual ~LLVMAssembler(); - void Run(); - const LLVMExecutionEngineRef &GetEngine() - { - return engine_; - } - void Disassemble(std::map addr2name = std::map()) const; - uint8_t *GetStackMapsSection() const - { - return codeInfo_.GetStackMapsSection(); - } - - int GetCodeSize() const - { - return codeInfo_.GetCodeSize(); - } - uint8_t *GetCodeBuffer() const - { - return codeInfo_.GetCodeBuff(); - } - - void *GetFuncPtrFromCompiledModule(LLVMValueRef function) - { - return LLVMGetPointerToGlobal(engine_, function); - } - const char *AMD64_TRIPLE = "x86_64-unknown-linux-gnu"; - const char *ARM64_TRIPLE = "aarch64-unknown-linux-gnu"; - const char *ARM32_TRIPLE = "arm-unknown-linux-gnu"; -private: - void UseRoundTripSectionMemoryManager(); - bool BuildMCJITEngine(); - void BuildAndRunPasses() const; - void BuildSimpleFunction(); - void Initialize(); - void InitMember(); - - LLVMMCJITCompilerOptions options_; - LLVMModuleRef module_; - LLVMExecutionEngineRef engine_; - std::string hostTriple_; - char *error_; - struct CodeInfo codeInfo_; -}; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_LLVM_MCJINT_ENGINE_H diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 0a739c9..7e068c2 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -959,12 +959,13 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Branch(isUtf16String, &isUtf16, ¬Utf16); Bind(&isUtf16); { - c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, PtrMul(*i, GetPtrConstant(2)))); + c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, + PtrMul(ChangeInt32ToPointer(*i), GetPtrConstant(2)))); Jump(&getChar2); } Bind(¬Utf16); { - c = ZExtInt8ToInt32(Load(INT8_TYPE, dataUtf16, *i)); + c = ZExtInt8ToInt32(Load(INT8_TYPE, dataUtf16, ChangeInt32ToPointer(*i))); Jump(&getChar2); } Bind(&getChar2); diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 20b92d9..e9bad84 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -1304,7 +1304,7 @@ public: Int32Mul(entry, GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); AddrShift attributesIndex = Int32Add(arrayIndex, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); - return GetValueFromTaggedArray(elements, attributesIndex); + return TaggedCastToInt32(GetValueFromTaggedArray(elements, attributesIndex)); } AddrShift GetValueFromDictionary(AddrShift elements, AddrShift entry) diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index c742d19..c979661 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -248,7 +248,7 @@ CALL_STUB_INIT_DESCRIPTOR(SetPropertyByIndex) CALL_STUB_INIT_DESCRIPTOR(GetPropertyByValue) { // 3 : 3 input parameters - static StubDescriptor getPropertyByValue("GetPropertyByValue", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor getPropertyByValue("GetPropertyByValue", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); *descriptor = getPropertyByValue; // 3 : 3 input parameters std::array params = { @@ -261,17 +261,6 @@ CALL_STUB_INIT_DESCRIPTOR(GetPropertyByValue) CALL_STUB_INIT_DESCRIPTOR(SetPropertyByValue) { - // // 4 : 4 input parameters - // static StubDescriptor setPropertyByValue("SetPropertyByValue", 0, 4, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); - // *descriptor = setPropertyByValue; - // // 4 : 4 input parameters - // std::array params = { - // MachineType::UINT64_TYPE, - // MachineType::UINT64_TYPE, - // MachineType::UINT64_TYPE, - // MachineType::UINT64_TYPE, - // }; - // descriptor->SetParameters(params.data()); } @@ -292,7 +281,7 @@ CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) CALL_STUB_INIT_DESCRIPTOR(CallSetter) { // 5 : 5 input parameters - StubDescriptor callSetter("CallSetter", 0, 5, ArgumentsOrder::DEFAULT_ORDER, NONE_TYPE); + StubDescriptor callSetter("CallSetter", 0, 5, ArgumentsOrder::DEFAULT_ORDER, BOOL_TYPE); *descriptor = callSetter; // 5 : 5 input parameters std::array params = { @@ -306,7 +295,7 @@ CALL_STUB_INIT_DESCRIPTOR(CallSetter) CALL_STUB_INIT_DESCRIPTOR(CallGetter) { // 3 : 3 input parameters - StubDescriptor callGetter("CallGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, NONE_TYPE); + StubDescriptor callGetter("CallGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); *descriptor = callGetter; // 3 : 3 input parameters std::array params = { @@ -321,7 +310,7 @@ CALL_STUB_INIT_DESCRIPTOR(CallGetter) CALL_STUB_INIT_DESCRIPTOR(AccessorGetter) { // 3 : 3 input parameters - StubDescriptor accessorGetter("AccessorGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, NONE_TYPE); + StubDescriptor accessorGetter("AccessorGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); *descriptor = accessorGetter; // 3 : 3 input parameters std::array params = { @@ -437,7 +426,7 @@ CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) CALL_STUB_INIT_DESCRIPTOR(NewInternalString) { // 2 : 2 input parameters - static StubDescriptor stringGetHashCode("NewInternalString", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor stringGetHashCode("NewInternalString", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); *descriptor = stringGetHashCode; // 2 : 2 input parameters std::array params = { diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index a8d01f1..d74cbf6 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -19,8 +19,8 @@ #include "gtest/gtest.h" #include "ecmascript/builtins/builtins_promise_handler.h" #include "ecmascript/compiler/fast_stub.h" +#include "ecmascript/compiler/llvm_codegen.h" #include "ecmascript/compiler/llvm_ir_builder.h" -#include "ecmascript/compiler/llvm_mcjit_engine.h" #include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" #include "ecmascript/compiler/scheduler.h" #include "ecmascript/compiler/stub_descriptor.h" @@ -1087,6 +1087,7 @@ void DoSafepoint() } } +#ifdef NDEBUG HWTEST_F_L0(StubTest, GetPropertyByIndexStub) { auto module = stubModule.GetModule(); @@ -1149,7 +1150,6 @@ HWTEST_F_L0(StubTest, SetPropertyByIndexStub) } } - HWTEST_F_L0(StubTest, GetPropertyByNameStub) { auto module = stubModule.GetModule(); @@ -1231,7 +1231,7 @@ HWTEST_F_L0(StubTest, GetPropertyByValueStub) reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(getPropertyByNamefunction))); auto *getpropertyByIndexPtr = reinterpret_cast( reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(getPropertyByIndexfunction))); - + thread->SetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex), reinterpret_cast(getpropertyByIndexPtr)); thread->SetFastStubEntry(FAST_STUB_ID(GetPropertyByName), reinterpret_cast(getPropertyByNamePtr)); @@ -1271,6 +1271,7 @@ HWTEST_F_L0(StubTest, GetPropertyByValueStub) resVal = getPropertyByValuePtr(thread, strHello.GetTaggedValue().GetRawData(), JSTaggedValue(key).GetRawData()); EXPECT_EQ(resVal.GetRawData(), 0); } +#endif HWTEST_F_L0(StubTest, FastTypeOfTest) { @@ -1357,4 +1358,5 @@ HWTEST_F_L0(StubTest, FastTypeOfTest) EXPECT_EQ(resultVal9, globalConst->GetObjectString()); EXPECT_EQ(resultVal9, expectResult9); } + } // namespace panda::test diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index eced42c..761862a 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -124,6 +124,7 @@ bool EcmaVM::Initialize() { trace::ScopedTrace scoped_trace("EcmaVM::Initialize"); Platform::GetCurrentPlatform()->Initialize(); + RuntimeTrampolines::InitializeRuntimeTrampolines(thread_); auto globalConst = const_cast(thread_->GlobalConstants()); @@ -166,7 +167,6 @@ bool EcmaVM::Initialize() globalEnv->SetTemplateMap(thread_, JSTaggedValue(TemplateMap::Create(thread_))); globalEnv->SetRegisterSymbols(GetJSThread(), JSTaggedValue(SymbolTable::Create(GetJSThread()))); #ifdef ECMASCRIPT_ENABLE_STUB_AOT - RuntimeTrampolines::InitializeRuntimeTrampolines(thread_); std::string moduleFile = options_.GetStubModuleFile(); thread_->LoadFastStubModule(moduleFile.c_str()); #endif diff --git a/ecmascript/interpreter/fast_runtime_stub-inl.h b/ecmascript/interpreter/fast_runtime_stub-inl.h index ab77a6b..da87b2f 100644 --- a/ecmascript/interpreter/fast_runtime_stub-inl.h +++ b/ecmascript/interpreter/fast_runtime_stub-inl.h @@ -623,9 +623,9 @@ bool FastRuntimeStub::FastSetPropertyByIndex(JSThread *thread, JSTaggedValue rec { INTERPRETER_TRACE(thread, FastSetPropertyByIndex); #ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto *setPropertyByIndex = \ - reinterpret_cast \ - (reinterpret_cast(thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex)))); + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex); + typedef JSTaggedValue (*PFSetPropertyByIndex)(JSThread *, JSTaggedValue, uint32_t, JSTaggedValue); + auto setPropertyByIndex = reinterpret_cast(stubAddr); JSTaggedValue result = setPropertyByIndex(thread, receiver, index, value); #else JSTaggedValue result = FastRuntimeStub::SetPropertyByIndex(thread, receiver, index, value); @@ -662,8 +662,9 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByName(JSThread *thread, JSTaggedV receiver = receiverHandler.GetTaggedValue(); } #ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto *getPropertyByNamePtr = reinterpret_cast( - thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName))); + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName); + typedef JSTaggedValue (*PFGetPropertyByName)(JSThread *, JSTaggedValue, JSTaggedValue); + auto getPropertyByNamePtr = reinterpret_cast(stubAddr); JSTaggedValue result = getPropertyByNamePtr(thread, receiver, key); #else JSTaggedValue result = FastRuntimeStub::GetPropertyByName(thread, receiver, key); @@ -681,9 +682,10 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByValue(JSThread *thread, JSTagged { INTERPRETER_TRACE(thread, FastGetPropertyByValue); #ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto *getPropertyByValuePtr = reinterpret_cast( - thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue))); - JSTaggedValue result = getPropertyByValuePtr(thread, receiver.GetRawData(), key.GetRawData()); + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue); + typedef JSTaggedValue (*PFGetPropertyByValue)(JSThread *, JSTaggedValue, JSTaggedValue); + auto getPropertyByValuePtr = reinterpret_cast(stubAddr); + JSTaggedValue result = getPropertyByValuePtr(thread, receiver, key); #else JSTaggedValue result = FastRuntimeStub::GetPropertyByValue(thread, receiver, key); #endif @@ -701,8 +703,9 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByIndex(JSThread *thread, JSTagged { INTERPRETER_TRACE(thread, FastGetPropertyByIndex); #ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto getPropertyByIndex = reinterpret_cast( - thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex))); + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex); + typedef JSTaggedValue (*PFGetPropertyByIndex)(JSThread *, JSTaggedValue, uint32_t); + auto getPropertyByIndex = reinterpret_cast(stubAddr); JSTaggedValue result = getPropertyByIndex(thread, receiver, index); #else JSTaggedValue result = FastRuntimeStub::GetPropertyByIndex(thread, receiver, index); diff --git a/ecmascript/interpreter/fast_runtime_stub.h b/ecmascript/interpreter/fast_runtime_stub.h index 8149d11..2437bae 100644 --- a/ecmascript/interpreter/fast_runtime_stub.h +++ b/ecmascript/interpreter/fast_runtime_stub.h @@ -25,7 +25,6 @@ class PropertyAttributes; class FastRuntimeStub { public: - using Address = uintptr_t; /* -------------- Common API Begin, Don't change those interface!!! ----------------- */ static inline JSTaggedValue FastAdd(JSTaggedValue left, JSTaggedValue right); static inline JSTaggedValue FastSub(JSTaggedValue left, JSTaggedValue right); diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 96ef0c5..567d911 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -59,12 +59,14 @@ void InterpretedFrameHandler::PrevFrame() OptimizedFrameStateBase *state = reinterpret_cast( reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedFrameStateBase, prev)); sp_ = reinterpret_cast(state->prev); - } break; + break; + } case FrameType::OPTIMIZED_ENTRY_FRAME: { OptimizedEntryFrameState *state = reinterpret_cast( reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); sp_ = reinterpret_cast(state->threadFp); - } break; + break; + } default: UNREACHABLE(); } @@ -78,7 +80,7 @@ void InterpretedFrameHandler::PrevFrame() FrameType InterpretedFrameHandler::GetFrameType() { FrameType type = *(reinterpret_cast( - reinterpret_cast(sp_) + FrameConst::kFrameType)); + reinterpret_cast(sp_) + FrameConst::FRAME_TYPE_OFFSET)); return type; } diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 7207ded..1c1f736 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -203,18 +203,24 @@ namespace panda::ecmascript { #define GET_ACC() (acc) // NOLINT(cppcoreguidelines-macro-usage) #define SET_ACC(val) (acc = val); // NOLINT(cppcoreguidelines-macro-usage) -JSTaggedValue EcmaInterpreter::ExecuteNative(JSThread *thread, const CallParams& params) +JSTaggedType *EcmaInterpreter::GetCurrentInterPreterFrameSp(JSThread *thread) { - INTERPRETER_TRACE(thread, ExecuteNative); JSTaggedType *originalPrevSp = const_cast(thread->GetCurrentSPFrame()); auto current = originalPrevSp; FrameType type = *(reinterpret_cast( - reinterpret_cast(current) + FrameConst::kFrameType)); + reinterpret_cast(current) + FrameConst::FRAME_TYPE_OFFSET)); JSTaggedType *sp = originalPrevSp; if (type != FrameType::INTERPRETER_FRAME) { JSTaggedType *lastSp = const_cast(thread->GetLastIFrameSp()); sp = lastSp; } + return sp; +} + +JSTaggedValue EcmaInterpreter::ExecuteNative(JSThread *thread, const CallParams& params) +{ + INTERPRETER_TRACE(thread, ExecuteNative); + JSTaggedType *sp = GetCurrentInterPreterFrameSp(thread); JSMethod *methodToCall = params.callTarget->GetCallTarget(); ASSERT(methodToCall->GetNumVregs() == 0); @@ -259,18 +265,10 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param if (method->IsNative()) { return EcmaInterpreter::ExecuteNative(thread, params); } - JSTaggedType *originalPrevSp = const_cast(thread->GetCurrentSPFrame()); - auto current = originalPrevSp; - FrameType type = *(reinterpret_cast( - reinterpret_cast(current) + FrameConst::kFrameType)); - JSTaggedType *newSp = nullptr; - if (type != FrameType::INTERPRETER_FRAME) { - JSTaggedType *lastSp = const_cast(thread->GetLastIFrameSp()); - newSp = lastSp - FRAME_STATE_SIZE; - } else { - newSp = originalPrevSp - FRAME_STATE_SIZE; - } + + JSTaggedType *sp = GetCurrentInterPreterFrameSp(thread); + JSTaggedType *newSp = sp - FRAME_STATE_SIZE; // push break state // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) { @@ -2457,8 +2455,9 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool // fast path if (LIKELY(receiver.IsHeapObject())) { #ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto getPropertyByIndex = reinterpret_cast( - thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex))); + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex); + typedef JSTaggedValue (*PFGetPropertyByIndex)(JSThread *, JSTaggedValue, uint32_t); + auto getPropertyByIndex = reinterpret_cast(stubAddr); JSTaggedValue res = getPropertyByIndex(thread, receiver, idx); #else JSTaggedValue res = FastRuntimeStub::GetPropertyByIndex(thread, receiver, idx); @@ -2488,9 +2487,9 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue value = GET_ACC(); // fast path #ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto *setPropertyByIndex = \ - reinterpret_cast \ - (reinterpret_cast(thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex)))); + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex); + typedef JSTaggedValue (*PFSetPropertyByIndex)(JSThread *, JSTaggedValue, uint32_t, JSTaggedValue); + auto setPropertyByIndex = reinterpret_cast(stubAddr); JSTaggedValue res = setPropertyByIndex(thread, receiver, index, value); #else JSTaggedValue res = FastRuntimeStub::SetPropertyByIndex(thread, receiver, index, value); @@ -2522,7 +2521,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool #if ECMASCRIPT_ENABLE_IC auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp); - if (!profileTypeInfo.IsUndefined()) { + if (!profileTypeInfo.IsUndefined()) { uint16_t slotId = READ_INST_8_0(); auto profileTypeArray = ProfileTypeInfo::Cast(profileTypeInfo.GetTaggedObject()); JSTaggedValue firstValue = profileTypeArray->Get(slotId); @@ -2547,8 +2546,9 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool // fast path if (LIKELY(receiver.IsHeapObject())) { #ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto *getPropertyByValuePtr = reinterpret_cast( - thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue))); + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue); + typedef JSTaggedValue (*PFGetPropertyByValue)(JSThread *, JSTaggedValue, JSTaggedValue); + auto getPropertyByValuePtr = reinterpret_cast(stubAddr); JSTaggedValue res = getPropertyByValuePtr(thread, receiver, propKey); #else JSTaggedValue res = FastRuntimeStub::GetPropertyByValue(thread, receiver, propKey); @@ -2924,8 +2924,9 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool if (LIKELY(receiver.IsHeapObject())) { // fast path #ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto *getPropertyByNamePtr = reinterpret_cast( - thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName))); + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName); + typedef JSTaggedValue (*PFGetPropertyByName)(JSThread *, JSTaggedValue, JSTaggedValue); + auto getPropertyByNamePtr = reinterpret_cast(stubAddr); JSTaggedValue res = getPropertyByNamePtr(thread, receiver, propKey); #else JSTaggedValue res = FastRuntimeStub::GetPropertyByName(thread, receiver, propKey); diff --git a/ecmascript/interpreter/interpreter.h b/ecmascript/interpreter/interpreter.h index 1e119c3..84f0970 100644 --- a/ecmascript/interpreter/interpreter.h +++ b/ecmascript/interpreter/interpreter.h @@ -66,6 +66,7 @@ public: static inline JSTaggedValue Execute(JSThread *thread, const CallParams& params); static inline JSTaggedValue ExecuteNative(JSThread *thread, const CallParams& params); + static inline JSTaggedType *GetCurrentInterPreterFrameSp(JSThread *thread); static inline JSTaggedValue GeneratorReEnterInterpreter(JSThread *thread, JSHandle context); static inline void ChangeGenContext(JSThread *thread, JSHandle context); static inline void ResumeContext(JSThread *thread); diff --git a/ecmascript/mem/machine_code.h b/ecmascript/mem/machine_code.h index 5021053..a9504f4 100644 --- a/ecmascript/mem/machine_code.h +++ b/ecmascript/mem/machine_code.h @@ -69,11 +69,6 @@ public: { return SIZE + this->GetInstructionSizeInBytes().GetInt(); } - - void VisitRangeSlot(const EcmaObjectRangeVisitor &v) - { - // no need to visit - } }; } // namespace ecmascript } // namespace panda diff --git a/js_runtime_config.gni b/js_runtime_config.gni index bf6c093..df2bc82 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -15,6 +15,7 @@ ark_root = "//ark/runtime_core" js_root = "//ark/js_runtime" compile_llvm_online = false run_with_asan = false +enable_stub_aot = false asan_lib_path = "/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux" # For OpenHarmony build, always link with the static lib: -- Gitee From 839ad28e6adc9a61f94d4d5e668cb793573e6d3c Mon Sep 17 00:00:00 2001 From: getingke Date: Tue, 26 Oct 2021 20:05:25 +0800 Subject: [PATCH 084/115] fixed for code static check Signed-off-by: getingke Change-Id: I82acce47c83c72a2a9b0c316c4e339d5127e02f7 --- ecmascript/compiler/fast_stub.h | 10 ++++---- ecmascript/compiler/llvm_codegen.h | 2 +- ecmascript/compiler/llvm_ir_builder.cpp | 12 ++++------ ecmascript/compiler/stub.cpp | 26 ++++++++++---------- ecmascript/compiler/stub.h | 3 ++- ecmascript/interpreter/frame_handler.cpp | 30 ++++++++++++------------ 6 files changed, 40 insertions(+), 43 deletions(-) diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 68bbb4a..61d314e 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -85,7 +85,7 @@ public: // 3 : 3 means argument counts explicit GetElementStub(Circuit *circuit) : Stub("GetElement", 3, circuit) { - circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); } ~GetElementStub() = default; NO_MOVE_SEMANTIC(GetElementStub); @@ -118,7 +118,7 @@ public: // 3 : 3 means argument counts explicit GetPropertyByIndexStub(Circuit *circuit) : Stub("GetPropertyByIndex", 3, circuit) { - circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); } ~GetPropertyByIndexStub() = default; NO_MOVE_SEMANTIC(GetPropertyByIndexStub); @@ -131,7 +131,7 @@ public: // 4 : 4 means argument counts explicit SetPropertyByIndexStub(Circuit *circuit) : Stub("SetPropertyByIndex", 4, circuit) { - circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); } ~SetPropertyByIndexStub() = default; NO_MOVE_SEMANTIC(SetPropertyByIndexStub); @@ -144,7 +144,7 @@ public: // 3 : 3 means argument counts explicit GetPropertyByNameStub(Circuit *circuit) : Stub("GetPropertyByName", 3, circuit) { - circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); } ~GetPropertyByNameStub() = default; NO_MOVE_SEMANTIC(GetPropertyByNameStub); @@ -190,7 +190,7 @@ public: // 3 : 3 means argument counts explicit GetPropertyByValueStub(Circuit *circuit) : Stub("FastGetPropertyByValue", 3, circuit) { - circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); } ~GetPropertyByValueStub() = default; NO_MOVE_SEMANTIC(GetPropertyByValueStub); diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index d303400..e3d78fe 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -71,7 +71,7 @@ struct CodeInfo { codeSectionNames_.push_back(sectionName); addr = machineCode_ + codeBufferPos_; LOG_ECMA(INFO) << "AllocaCodeSection addr:" << std::hex << reinterpret_cast(addr); - codeInfo_.push_back({addr, size}); + codeInfo_.push_back({ addr, size }); codeBufferPos_ += size; return addr; } diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 4431d72..373550d 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -413,17 +413,13 @@ void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inLi LLVMValueRef thread = g_values[inList[2]]; // 2 : 2 means skip two input gates (target thread) // runtime case if (callee_descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB) { - rtoffset = LLVMConstInt(LLVMInt64Type(), - panda::ecmascript::JSThread::GetRuntimeFunctionsOffset() + - (index - FAST_STUB_MAXCOUNT) * sizeof(uintptr_t), - 0); - + panda::ecmascript::JSThread::GetRuntimeFunctionsOffset() + + (index - FAST_STUB_MAXCOUNT) * sizeof(uintptr_t), 0); } else { rtoffset = LLVMConstInt(LLVMInt64Type(), - panda::ecmascript::JSThread::GetFastStubEntryOffset() + - (index) * sizeof(uintptr_t), - 0); + panda::ecmascript::JSThread::GetFastStubEntryOffset() + + (index) * sizeof(uintptr_t), 0); } LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, thread, rtoffset, ""); LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(LLVMInt64Type(), 0), ""); diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 7e068c2..6d4c2e0 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -95,11 +95,9 @@ AddrShift Stub::Variable::TryRemoveTrivialPhi(AddrShift phiVal) if (IsSelector(out->GetGate())) { auto out_addr_shift = env_->GetCircuit()->SaveGatePtr(out->GetGate()); auto result = TryRemoveTrivialPhi(out_addr_shift); - if (same_addr_shift == out_addr_shift) - { + if (same_addr_shift == out_addr_shift) { same_addr_shift = result; } - } } return same_addr_shift; @@ -837,14 +835,14 @@ AddrShift Stub::TaggedIsStringOrSymbol(AddrShift obj) { AddrShift objType = GetObjectType(LoadHClass(obj)); result = Word32Equal(objType, - GetInteger32Constant(static_cast(panda::ecmascript::JSType::STRING))); + GetInteger32Constant(static_cast(panda::ecmascript::JSType::STRING))); Label isString(env); Label notString(env); Branch(*result, &exit, ¬String); Bind(¬String); { result = Word32Equal(objType, - GetInteger32Constant(static_cast(panda::ecmascript::JSType::SYMBOL))); + GetInteger32Constant(static_cast(panda::ecmascript::JSType::SYMBOL))); Jump(&exit); } } @@ -860,8 +858,8 @@ AddrShift Stub::IsUtf16String(AddrShift string) AddrShift len = Load(MachineType::UINT32_TYPE, string, GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); return Word32Equal( - Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)), - GetInteger32Constant(panda::ecmascript::EcmaString::STRING_UNCOMPRESSED)); + Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)), + GetInteger32Constant(panda::ecmascript::EcmaString::STRING_UNCOMPRESSED)); } AddrShift Stub::IsUtf8String(AddrShift string) @@ -870,8 +868,8 @@ AddrShift Stub::IsUtf8String(AddrShift string) AddrShift len = Load(MachineType::UINT32_TYPE, string, GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); return Word32Equal( - Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)), - GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED)); + Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)), + GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED)); } AddrShift Stub::IsInternalString(AddrShift string) @@ -880,8 +878,8 @@ AddrShift Stub::IsInternalString(AddrShift string) AddrShift len = Load(MachineType::UINT32_TYPE, string, GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); return Word32NotEqual( - Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_INTERN_BIT)), - GetInteger32Constant(0)); + Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_INTERN_BIT)), + GetInteger32Constant(0)); } AddrShift Stub::IsDigit(AddrShift ch) @@ -902,7 +900,7 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Label inRange(env); AddrShift len = Load(MachineType::UINT32_TYPE, string, GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); - len = Word32LSR(len, GetInteger32Constant(2)); + len = Word32LSR(len, GetInteger32Constant(2)); // 2 : 2 means len must be right shift 2 bits Branch(Word32Equal(len, GetInteger32Constant(0)), &exit, &greatThanZero); Bind(&greatThanZero); Branch(Int32GreaterThan(len, GetInteger32Constant(panda::ecmascript::MAX_INDEX_LEN)), &exit, &inRange); @@ -959,6 +957,7 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Branch(isUtf16String, &isUtf16, ¬Utf16); Bind(&isUtf16); { + // 2 : 2 means utf16 char width is two bytes c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, PtrMul(ChangeInt32ToPointer(*i), GetPtrConstant(2)))); Jump(&getChar2); @@ -975,8 +974,9 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Branch(IsDigit(*c), &isDigit2, ¬Digit2); Bind(&isDigit2); { + // 10 means the base of digit is 10. n = Int32Add(Int32Mul(*n, GetInteger32Constant(10)), - Int32Sub(*c, GetInteger32Constant('0'))); + Int32Sub(*c, GetInteger32Constant('0'))); i = Int32Add(*i, GetInteger32Constant(1)); Branch(Int32LessThan(*i, len), &loopEnd, &afterLoop); } diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index e9bad84..7133177 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -554,7 +554,8 @@ public: void LoopEnd(Label *loopHead); // call operation - AddrShift CallStub(StubDescriptor *descriptor, AddrShift thread, AddrShift target, std::initializer_list args) + AddrShift CallStub(StubDescriptor *descriptor, AddrShift thread, AddrShift target, + std::initializer_list args) { auto depend = env_.GetCurrentLabel()->GetDepend(); AddrShift result = env_.GetCircuitBuilder().NewCallGate(descriptor, thread, target, depend, args); diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 567d911..2cbfd07 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -54,21 +54,21 @@ void InterpretedFrameHandler::PrevFrame() } while (type != FrameType::INTERPRETER_FRAME) { - switch(type) { - case FrameType::OPTIMIZED_FRAME: { - OptimizedFrameStateBase *state = reinterpret_cast( - reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedFrameStateBase, prev)); - sp_ = reinterpret_cast(state->prev); - break; - } - case FrameType::OPTIMIZED_ENTRY_FRAME: { - OptimizedEntryFrameState *state = reinterpret_cast( - reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); - sp_ = reinterpret_cast(state->threadFp); - break; - } - default: - UNREACHABLE(); + switch (type) { + case FrameType::OPTIMIZED_FRAME: { + OptimizedFrameStateBase *state = reinterpret_cast( + reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedFrameStateBase, prev)); + sp_ = reinterpret_cast(state->prev); + break; + } + case FrameType::OPTIMIZED_ENTRY_FRAME: { + OptimizedEntryFrameState *state = reinterpret_cast( + reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); + sp_ = reinterpret_cast(state->threadFp); + break; + } + default: + UNREACHABLE(); } if (sp_ == nullptr) { return; -- Gitee From f0a82545a7f227eaefa28925a11f2d5079e1148c Mon Sep 17 00:00:00 2001 From: getingke Date: Tue, 26 Oct 2021 20:34:16 +0800 Subject: [PATCH 085/115] fixed for review comment by luochuhao Signed-off-by: getingke Change-Id: I74946948bdf127b88a032b16abf49ea890a80bf2 --- ecmascript/compiler/stub.h | 18 ++++-------------- ecmascript/interpreter/fast_runtime_stub-inl.h | 16 ++++++++-------- ecmascript/interpreter/interpreter-inl.h | 16 ++++++++-------- ecmascript/runtime_trampolines.h | 12 ------------ 4 files changed, 20 insertions(+), 42 deletions(-) diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 7133177..f7bc6f5 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -761,16 +761,6 @@ public: return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT64_REV), x); } - AddrShift WordLogicOr(AddrShift x, AddrShift y) - { - return env_.GetCircuitBuilder().NewLogicGate(OpCode(OpCode::INT32_OR), x, y); - } - - AddrShift WordLogicAnd(AddrShift x, AddrShift y) - { - return env_.GetCircuitBuilder().NewLogicGate(OpCode(OpCode::INT32_AND), x, y); - } - AddrShift Word32LSL(AddrShift x, AddrShift y) { return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_LSL), x, y); @@ -797,7 +787,7 @@ public: AddrShift TaggedIsDouble(AddrShift x) { - return Word32Equal(WordLogicOr(SExtInt1ToInt32(TaggedIsInt(x)), SExtInt1ToInt32(TaggedIsObject(x))), + return Word32Equal(Word32Or(SExtInt1ToInt32(TaggedIsInt(x)), SExtInt1ToInt32(TaggedIsObject(x))), GetInteger32Constant(0)); } @@ -809,7 +799,7 @@ public: AddrShift TaggedIsNumber(AddrShift x) { - return TruncInt32ToInt1(WordLogicOr(SExtInt1ToInt32(TaggedIsInt(x)), SExtInt1ToInt32(TaggedIsDouble(x)))); + return TruncInt32ToInt1(Word32Or(SExtInt1ToInt32(TaggedIsInt(x)), SExtInt1ToInt32(TaggedIsDouble(x)))); } AddrShift TaggedIsHole(AddrShift x) @@ -833,7 +823,7 @@ public: SExtInt1ToInt32( Word64Equal(Word64And(x, GetWord64Constant(~panda::ecmascript::JSTaggedValue::TAG_SPECIAL_MASK)), GetWord64Constant(0))), - WordLogicOr(SExtInt1ToInt32(Word64NotEqual( + Word32Or(SExtInt1ToInt32(Word64NotEqual( Word64And(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_SPECIAL_VALUE)), GetWord64Constant(0))), SExtInt1ToInt32(TaggedIsHole(x))))); } @@ -841,7 +831,7 @@ public: AddrShift TaggedIsHeapObject(AddrShift x) { return TruncInt32ToInt1( - WordLogicAnd(SExtInt1ToInt32(TaggedIsObject(x)), + Word32And(SExtInt1ToInt32(TaggedIsObject(x)), SExtInt1ToInt32(Word32Equal(SExtInt1ToInt32(TaggedIsSpecial(x)), GetInteger32Constant(0))))); } diff --git a/ecmascript/interpreter/fast_runtime_stub-inl.h b/ecmascript/interpreter/fast_runtime_stub-inl.h index da87b2f..239d2f7 100644 --- a/ecmascript/interpreter/fast_runtime_stub-inl.h +++ b/ecmascript/interpreter/fast_runtime_stub-inl.h @@ -622,8 +622,8 @@ bool FastRuntimeStub::FastSetPropertyByIndex(JSThread *thread, JSTaggedValue rec JSTaggedValue value) { INTERPRETER_TRACE(thread, FastSetPropertyByIndex); -#ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex)); typedef JSTaggedValue (*PFSetPropertyByIndex)(JSThread *, JSTaggedValue, uint32_t, JSTaggedValue); auto setPropertyByIndex = reinterpret_cast(stubAddr); JSTaggedValue result = setPropertyByIndex(thread, receiver, index, value); @@ -661,8 +661,8 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByName(JSThread *thread, JSTaggedV // Maybe moved by GC receiver = receiverHandler.GetTaggedValue(); } -#ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName)); typedef JSTaggedValue (*PFGetPropertyByName)(JSThread *, JSTaggedValue, JSTaggedValue); auto getPropertyByNamePtr = reinterpret_cast(stubAddr); JSTaggedValue result = getPropertyByNamePtr(thread, receiver, key); @@ -681,8 +681,8 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByName(JSThread *thread, JSTaggedV JSTaggedValue FastRuntimeStub::FastGetPropertyByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key) { INTERPRETER_TRACE(thread, FastGetPropertyByValue); -#ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue)); typedef JSTaggedValue (*PFGetPropertyByValue)(JSThread *, JSTaggedValue, JSTaggedValue); auto getPropertyByValuePtr = reinterpret_cast(stubAddr); JSTaggedValue result = getPropertyByValuePtr(thread, receiver, key); @@ -702,8 +702,8 @@ template // UseHole is only for Array::Sort() which requires Hole JSTaggedValue FastRuntimeStub::FastGetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index) { INTERPRETER_TRACE(thread, FastGetPropertyByIndex); -#ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex)); typedef JSTaggedValue (*PFGetPropertyByIndex)(JSThread *, JSTaggedValue, uint32_t); auto getPropertyByIndex = reinterpret_cast(stubAddr); JSTaggedValue result = getPropertyByIndex(thread, receiver, index); diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 1c1f736..e02d2dd 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -2454,8 +2454,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue receiver = GET_VREG_VALUE(v0); // fast path if (LIKELY(receiver.IsHeapObject())) { -#ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex)); typedef JSTaggedValue (*PFGetPropertyByIndex)(JSThread *, JSTaggedValue, uint32_t); auto getPropertyByIndex = reinterpret_cast(stubAddr); JSTaggedValue res = getPropertyByIndex(thread, receiver, idx); @@ -2486,8 +2486,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool SAVE_ACC(); JSTaggedValue value = GET_ACC(); // fast path -#ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex)); typedef JSTaggedValue (*PFSetPropertyByIndex)(JSThread *, JSTaggedValue, uint32_t, JSTaggedValue); auto setPropertyByIndex = reinterpret_cast(stubAddr); JSTaggedValue res = setPropertyByIndex(thread, receiver, index, value); @@ -2545,8 +2545,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool #endif // fast path if (LIKELY(receiver.IsHeapObject())) { -#ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue)); typedef JSTaggedValue (*PFGetPropertyByValue)(JSThread *, JSTaggedValue, JSTaggedValue); auto getPropertyByValuePtr = reinterpret_cast(stubAddr); JSTaggedValue res = getPropertyByValuePtr(thread, receiver, propKey); @@ -2923,8 +2923,8 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool if (LIKELY(receiver.IsHeapObject())) { // fast path -#ifdef ECMASCRTPT_ENABLE_STUB_AOT - auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName)); typedef JSTaggedValue (*PFGetPropertyByName)(JSThread *, JSTaggedValue, JSTaggedValue); auto getPropertyByNamePtr = reinterpret_cast(stubAddr); JSTaggedValue res = getPropertyByNamePtr(thread, receiver, propKey); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 95a257b..8870a57 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -66,21 +66,9 @@ public: thread->SetLastIFrameSp(cursp); JSTaggedType *newSp = static_cast(static_cast(newFp)); thread_->SetCurrentSPFrame(newSp); - // print newfp and type for debug - std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " lastFp_ : " << lastFp_ - << std::endl; - FrameType type = *(reinterpret_cast( - reinterpret_cast(newFp) + FrameConst::FRAME_TYPE_OFFSET)); - std::cout << __FUNCTION__ << " type = " << as_integer(type) << std::endl; } ~CallRuntimeTrampolinesScope() { - // print oldfp and type for debug - std::cout << "~CallRuntimeTrampolinesScope lastFp_: " << lastFp_ << - " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; - FrameType type = *(reinterpret_cast( - reinterpret_cast(lastFp_) + FrameConst::FRAME_TYPE_OFFSET)); - std::cout << __FUNCTION__ << "type = " << as_integer(type) << std::endl; JSTaggedType *oldSp = static_cast(static_cast(lastFp_)); thread_->SetCurrentSPFrame(oldSp); thread_->SetLastOptCallRuntimePc(lastOptCallRuntimePc_); -- Gitee From c8e2d2f6402cd9f01331b480613f256176871726 Mon Sep 17 00:00:00 2001 From: getingke Date: Tue, 26 Oct 2021 20:52:07 +0800 Subject: [PATCH 086/115] fixed for code static check Signed-off-by: getingke Change-Id: If651daa321e51f9d9daf022cdfc0bf1a5768f5c6 --- ecmascript/compiler/llvm_mcjit_engine.cpp | 23 ----------------------- ecmascript/compiler/llvm_mcjit_engine.h | 20 -------------------- ecmascript/compiler/stub.cpp | 4 ++-- 3 files changed, 2 insertions(+), 45 deletions(-) delete mode 100644 ecmascript/compiler/llvm_mcjit_engine.cpp delete mode 100644 ecmascript/compiler/llvm_mcjit_engine.h diff --git a/ecmascript/compiler/llvm_mcjit_engine.cpp b/ecmascript/compiler/llvm_mcjit_engine.cpp deleted file mode 100644 index 782d31b..0000000 --- a/ecmascript/compiler/llvm_mcjit_engine.cpp +++ /dev/null @@ -1,23 +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. - */ - - - - - - -namespace kungfu { - -} // namespace kungfu diff --git a/ecmascript/compiler/llvm_mcjit_engine.h b/ecmascript/compiler/llvm_mcjit_engine.h deleted file mode 100644 index e1cd9c8..0000000 --- a/ecmascript/compiler/llvm_mcjit_engine.h +++ /dev/null @@ -1,20 +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_COMPILER_LLVM_MCJINT_ENGINE_H -#define ECMASCRIPT_COMPILER_LLVM_MCJINT_ENGINE_H - -} // namespace kungfu -#endif // ECMASCRIPT_COMPILER_LLVM_MCJINT_ENGINE_H diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 6d4c2e0..b5e6cdb 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -957,9 +957,9 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Branch(isUtf16String, &isUtf16, ¬Utf16); Bind(&isUtf16); { - // 2 : 2 means utf16 char width is two bytes c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, - PtrMul(ChangeInt32ToPointer(*i), GetPtrConstant(2)))); + PtrMul(ChangeInt32ToPointer(*i), + GetPtrConstant(2)))); // 2 : 2 means utf16 char width is two bytes Jump(&getChar2); } Bind(¬Utf16); -- Gitee From 371ff7fced958ebbe6326065d9d8eff36e0f0fd1 Mon Sep 17 00:00:00 2001 From: getingke Date: Tue, 26 Oct 2021 21:57:02 +0800 Subject: [PATCH 087/115] fixed for code static check Signed-off-by: getingke Change-Id: I537a1ece719508c0a78b0481a62f34896bb65f5c --- ecmascript/compiler/llvm_codegen.h | 2 +- ecmascript/compiler/stub.cpp | 4 ++-- ecmascript/compiler/stub.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index e3d78fe..d303400 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -71,7 +71,7 @@ struct CodeInfo { codeSectionNames_.push_back(sectionName); addr = machineCode_ + codeBufferPos_; LOG_ECMA(INFO) << "AllocaCodeSection addr:" << std::hex << reinterpret_cast(addr); - codeInfo_.push_back({ addr, size }); + codeInfo_.push_back({addr, size}); codeBufferPos_ += size; return addr; } diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index b5e6cdb..aeffd8f 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -958,8 +958,8 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Bind(&isUtf16); { c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, - PtrMul(ChangeInt32ToPointer(*i), - GetPtrConstant(2)))); // 2 : 2 means utf16 char width is two bytes + PtrMul(ChangeInt32ToPointer(*i), + GetPtrConstant(2)))); // 2 : 2 means utf16 char width is two bytes Jump(&getChar2); } Bind(¬Utf16); diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index f7bc6f5..3a12f0b 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -832,7 +832,7 @@ public: { return TruncInt32ToInt1( Word32And(SExtInt1ToInt32(TaggedIsObject(x)), - SExtInt1ToInt32(Word32Equal(SExtInt1ToInt32(TaggedIsSpecial(x)), GetInteger32Constant(0))))); + SExtInt1ToInt32(Word32Equal(SExtInt1ToInt32(TaggedIsSpecial(x)), GetInteger32Constant(0))))); } AddrShift TaggedIsString(AddrShift obj); -- Gitee From eba840418b6781a0de5998a8461f533a3c811a08 Mon Sep 17 00:00:00 2001 From: getingke Date: Wed, 27 Oct 2021 11:06:05 +0800 Subject: [PATCH 088/115] fixed for add aot stub module options Signed-off-by: getingke Change-Id: I26fe4dae6492aa07f70d9337ae768ee901774c91 --- ecmascript/js_runtime_options.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index 5c13618..640d3bc 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -32,6 +32,9 @@ public: { RuntimeOptions::AddOptions(parser); parser->Add(&enable_ark_tools_); + parser->Add(&enable_stub_aot_); + parser->Add(&stub_module_file_); + } bool IsEnableArkTools() const @@ -49,8 +52,34 @@ public: return enable_ark_tools_.WasSet(); } + bool IsEnableStubAot() const { + return enable_stub_aot_.GetValue(); + } + + void SetEnableStubAot(bool value) { + enable_stub_aot_.SetValue(value); + } + + bool WasSetEnableStubAot() const { + return enable_stub_aot_.WasSet(); + } + + std::string GetStubModuleFile() const { + return stub_module_file_.GetValue(); + } + + void SetStubModuleFile(std::string value) { + stub_module_file_.SetValue(std::move(value)); + } + + bool WasSetStubModuleFile() const { + return stub_module_file_.WasSet(); + } + private: PandArg enable_ark_tools_{"enable-ark-tools", false, R"(Enable ark tools to debug. Default: false)"}; + PandArg enable_stub_aot_{"enable-stub-aot", false, R"(enable aot of fast stub. Default: false)"}; + PandArg stub_module_file_{"stub-module-file", R"(stub.m)", R"(Path to stub module file. Default: "stub.m")"}; }; } // namespace panda::ecmascript -- Gitee From 8b2b159e94ebfd4e7354abde9c53991ed1364a0e Mon Sep 17 00:00:00 2001 From: getingke Date: Wed, 27 Oct 2021 14:19:18 +0800 Subject: [PATCH 089/115] fixed for code static check Signed-off-by: getingke Change-Id: Ia58baf151cf0a161be73642ad339450b18fedec8 --- ecmascript/compiler/stub.cpp | 2 +- ecmascript/compiler/tests/stub_tests.cpp | 1 - ecmascript/js_runtime_options.h | 22 ++++++++++++++-------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index aeffd8f..889e48c 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -959,7 +959,7 @@ AddrShift Stub::StringToElementIndex(AddrShift string) { c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, PtrMul(ChangeInt32ToPointer(*i), - GetPtrConstant(2)))); // 2 : 2 means utf16 char width is two bytes + GetPtrConstant(2)))); // 2 : 2 means utf16 char width is two bytes Jump(&getChar2); } Bind(¬Utf16); diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index d74cbf6..3999065 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -1358,5 +1358,4 @@ HWTEST_F_L0(StubTest, FastTypeOfTest) EXPECT_EQ(resultVal9, globalConst->GetObjectString()); EXPECT_EQ(resultVal9, expectResult9); } - } // namespace panda::test diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index 640d3bc..fa4d7ac 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -34,7 +34,6 @@ public: parser->Add(&enable_ark_tools_); parser->Add(&enable_stub_aot_); parser->Add(&stub_module_file_); - } bool IsEnableArkTools() const @@ -52,34 +51,41 @@ public: return enable_ark_tools_.WasSet(); } - bool IsEnableStubAot() const { + bool IsEnableStubAot() const + { return enable_stub_aot_.GetValue(); } - void SetEnableStubAot(bool value) { + void SetEnableStubAot(bool value) + { enable_stub_aot_.SetValue(value); } - bool WasSetEnableStubAot() const { + bool WasSetEnableStubAot() const + { return enable_stub_aot_.WasSet(); } - std::string GetStubModuleFile() const { + std::string GetStubModuleFile() const + { return stub_module_file_.GetValue(); } - void SetStubModuleFile(std::string value) { + void SetStubModuleFile(std::string value) + { stub_module_file_.SetValue(std::move(value)); } - bool WasSetStubModuleFile() const { + bool WasSetStubModuleFile() const + { return stub_module_file_.WasSet(); } private: PandArg enable_ark_tools_{"enable-ark-tools", false, R"(Enable ark tools to debug. Default: false)"}; PandArg enable_stub_aot_{"enable-stub-aot", false, R"(enable aot of fast stub. Default: false)"}; - PandArg stub_module_file_{"stub-module-file", R"(stub.m)", R"(Path to stub module file. Default: "stub.m")"}; + PandArg stub_module_file_{"stub-module-file", R"(stub.m)", + R"(Path to stub module file. Default: "stub.m")"}; }; } // namespace panda::ecmascript -- Gitee From 0a44a3ea850f50abcace6e2aa3fc6830b8d9c411 Mon Sep 17 00:00:00 2001 From: DaiHN Date: Wed, 27 Oct 2021 16:34:20 +0800 Subject: [PATCH 090/115] C polymorphic optimization Signed-off-by: DaiHN --- ecmascript/interpreter/interpreter-inl.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 4896537..3a817a0 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -2502,7 +2502,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryLoadICByValue(thread, receiver, propKey, firstValue, secondValue); } - if (res.IsHole() && !firstValue.IsHole()) { //ic miss not mega + if (res.IsHole() && !firstValue.IsHole()) { res = ICRuntimeStub::LoadICByValue(thread, profileTypeArray, receiver, propKey, slotId); @@ -2554,7 +2554,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryStoreICByValue(thread, receiver, propKey, firstValue, secondValue, value); } - if (res.IsHole() && !firstValue.IsHole()) { //ic miss not mega + if (res.IsHole() && !firstValue.IsHole()) { res = ICRuntimeStub::StoreICByValue(thread, profileTypeArray, receiver, propKey, value, slotId); @@ -2867,7 +2867,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryLoadICByName(thread, receiver, firstValue, secondValue); } - if (res.IsHole() && !firstValue.IsHole()) { //ic miss not mega + if (res.IsHole() && !firstValue.IsHole()) { uint32_t stringId = READ_INST_32_1(); JSTaggedValue propKey = constpool->GetObjectFromCache(stringId); res = ICRuntimeStub::LoadICByName(thread, @@ -2922,7 +2922,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryStoreICByName(thread, receiver, firstValue, secondValue, value); } - if (res.IsHole() && !firstValue.IsHole()) { //ic miss not mega + if (res.IsHole() && !firstValue.IsHole()) { uint32_t stringId = READ_INST_32_1(); JSTaggedValue propKey = constpool->GetObjectFromCache(stringId); res = ICRuntimeStub::StoreICByName(thread, -- Gitee From 4c23de27c5b77b17489f912fac77656287ea280d Mon Sep 17 00:00:00 2001 From: guobingbing Date: Thu, 28 Oct 2021 11:27:15 +0800 Subject: [PATCH 091/115] save acc before gc Signed-off-by: guobingbing Change-Id: I04f33bd8306c8e9b27602551d86bca8132e9cd8b --- ecmascript/interpreter/interpreter-inl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index ad41ab5..af5e68e 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -1717,10 +1717,13 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSFunction *result = JSFunction::Cast(constpool->GetObjectFromCache(methodId).GetTaggedObject()); ASSERT(result != nullptr); if (result->IsResolved()) { + SAVE_ACC(); auto res = SlowRuntimeStub::DefineNCFuncDyn(thread, result); INTERPRETER_RETURN_IF_ABRUPT(res); result = JSFunction::Cast(res.GetTaggedObject()); result->SetConstantPool(thread, JSTaggedValue(constpool)); + RESTORE_ACC(); + homeObject = GET_ACC(); } else { result->SetResolved(thread); } -- Gitee From fb76b93355a4f5d460bd44be8c01dc3eb7e14de1 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Thu, 28 Oct 2021 11:41:44 +0800 Subject: [PATCH 092/115] frame.h refactor Signed-off-by: songzhengchao --- ecmascript/frames.h | 31 ++++++++++++------------ ecmascript/interpreter/frame_handler.cpp | 3 +-- ecmascript/interpreter/interpreter-inl.h | 20 +++++++-------- ecmascript/interpreter/interpreter.h | 1 - ecmascript/runtime_trampolines.cpp | 8 ++++-- ecmascript/runtime_trampolines.h | 19 +++++---------- ecmascript/tests/test_helper.h | 2 +- 7 files changed, 40 insertions(+), 44 deletions(-) diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 454368e..153b058 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -215,6 +215,8 @@ #ifndef ECMASCRIPT_FRAMES_H #define ECMASCRIPT_FRAMES_H +#include "ecmascript/js_tagged_value.h" + #ifdef PANDA_TARGET_AMD64 #define GET_CURRETN_FP(fp) asm("mov %%rbp, %0" : "=rm" (fp)) #define POINTER_CAST(fp, type) static_cast(static_cast(fp) @@ -226,6 +228,7 @@ #endif namespace panda::ecmascript { +using TaggedType = coretypes::TaggedType; class JSThread; enum class FrameType: uintptr_t { OPTIMIZED_FRAME = 0, @@ -233,34 +236,32 @@ enum class FrameType: uintptr_t { INTERPRETER_FRAME = 2, }; -template -auto as_integer(Enumeration const value) --> typename std::underlying_type::type -{ - return static_cast::type>(value); -} - class OptimizedFrameStateBase { public: - FrameType frameType; - uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + uintptr_t frameType; + TaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc }; class InterpretedFrameStateBase { public: - uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc - FrameType frameType; + TaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + uintptr_t frameType; }; class OptimizedEntryFrameState { public: - uint64_t *threadFp; // for gc + TaggedType *threadFp; // for gc OptimizedFrameStateBase base; }; -class FrameConst { +class Frame { public: - static constexpr size_t FRAME_TYPE_OFFSET = -sizeof(FrameType); + static FrameType GetFrameType(const TaggedType *current) + { + return *(reinterpret_cast(reinterpret_cast(current) + FRAME_TYPE_OFFSET)); + } +private: + static constexpr size_t FRAME_TYPE_OFFSET = -sizeof(uintptr_t); }; } // namespace panda::ecmascript -#endif // ECMASCRIPT_FRAMES_H \ No newline at end of file +#endif // ECMASCRIPT_FRAMES_H diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 4a17664..f17df97 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -238,8 +238,7 @@ void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) c { JSTaggedType *current = fp_; while (current) { - FrameType type = *(reinterpret_cast( - reinterpret_cast(current) + FrameConst::FRAME_TYPE_OFFSET)); + FrameType type = Frame::GetFrameType(current); if (type == FrameType::INTERPRETER_FRAME) { FrameState *state = reinterpret_cast(current) - 1; InterpretedFrameHandler(current).Iterate(v0, v1); diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index ad41ab5..86420fa 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -229,7 +229,7 @@ JSTaggedValue EcmaInterpreter::ExecuteNative(JSThread *thread, const CallParams& FrameState *state = GET_FRAME(newSp); state->base.prev = sp; - state->base.frameType = FrameType::INTERPRETER_FRAME; + state->base.frameType = static_cast(FrameType::INTERPRETER_FRAME); state->pc = nullptr; state->sp = newSp; state->method = methodToCall; @@ -263,7 +263,7 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param breakState->pc = nullptr; breakState->sp = nullptr; breakState->base.prev = originalPrevSp; - breakState->base.frameType = FrameType::INTERPRETER_FRAME; + breakState->base.frameType = static_cast(FrameType::INTERPRETER_FRAME); breakState->numActualArgs = 0; JSTaggedType *prevSp = newSp; @@ -303,7 +303,7 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param state->constpool = constpool; state->profileTypeInfo = thisFunc->GetProfileTypeInfo(); state->base.prev = prevSp; - state->base.frameType = FrameType::INTERPRETER_FRAME; + state->base.frameType = static_cast(FrameType::INTERPRETER_FRAME); state->numActualArgs = numActualArgs; JSTaggedValue env = thisFunc->GetLexicalEnv(); @@ -342,7 +342,7 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH breakState->pc = nullptr; breakState->sp = nullptr; breakState->base.prev = currentSp; - breakState->base.frameType = FrameType::INTERPRETER_FRAME; + breakState->base.frameType = static_cast(FrameType::INTERPRETER_FRAME); breakState->numActualArgs = 0; // create new frame and resume sp and pc @@ -373,7 +373,7 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH state->acc = context->GetAcc(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) state->base.prev = breakSp; - state->base.frameType = FrameType::INTERPRETER_FRAME; + state->base.frameType = static_cast(FrameType::INTERPRETER_FRAME); JSTaggedValue env = context->GetLexicalEnv(); state->env = env; // execute interpreter @@ -405,7 +405,7 @@ void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandlepc = nullptr; breakState->sp = nullptr; breakState->base.prev = currentSp; - breakState->base.frameType = FrameType::INTERPRETER_FRAME; + breakState->base.frameType = static_cast(FrameType::INTERPRETER_FRAME); // create new frame and resume sp and pc uint32_t nregs = context->GetNRegs().GetInt(); @@ -435,7 +435,7 @@ void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandleacc = context->GetAcc(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) state->base.prev = breakSp; - state->base.frameType = FrameType::INTERPRETER_FRAME; + state->base.frameType = static_cast(FrameType::INTERPRETER_FRAME); state->env = context->GetLexicalEnv(); thread->SetCurrentSPFrame(newSp); @@ -779,7 +779,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool FrameState *state = GET_FRAME(newSp); state->base.prev = sp; - state->base.frameType = FrameType::INTERPRETER_FRAME; + state->base.frameType = static_cast(FrameType::INTERPRETER_FRAME); state->pc = nullptr; state->sp = newSp; state->method = methodToCall; @@ -863,7 +863,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool FrameState *state = GET_FRAME(newSp); state->base.prev = sp; - state->base.frameType = FrameType::INTERPRETER_FRAME; + state->base.frameType = static_cast(FrameType::INTERPRETER_FRAME); state->pc = pc = JSMethod::Cast(methodToCall)->GetBytecodeArray(); state->sp = sp = newSp; state->method = methodToCall; @@ -3224,7 +3224,7 @@ void EcmaInterpreter::InitStackFrame(JSThread *thread) state->acc = JSTaggedValue::Hole(); state->constpool = nullptr; state->profileTypeInfo = JSTaggedValue::Undefined(); - state->base.frameType = FrameType::INTERPRETER_FRAME; + state->base.frameType = static_cast(FrameType::INTERPRETER_FRAME); state->base.prev = nullptr; state->numActualArgs = 0; } diff --git a/ecmascript/interpreter/interpreter.h b/ecmascript/interpreter/interpreter.h index 1e119c3..1e268f3 100644 --- a/ecmascript/interpreter/interpreter.h +++ b/ecmascript/interpreter/interpreter.h @@ -26,7 +26,6 @@ namespace panda::ecmascript { class ConstantPool; class ECMAObject; class GeneratorContext; -using TaggedType = coretypes::TaggedType; // align with 8 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index b3c942e..b848292 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -16,13 +16,13 @@ #include "runtime_trampolines.h" #include "ecmascript/accessor_data.h" #include "ecmascript/ecma_macros.h" +#include "ecmascript/frames.h" +#include "ecmascript/interpreter/interpreter-inl.h" #include "ecmascript/js_object.h" #include "ecmascript/js_proxy.h" -#include "ecmascript/frames.h" #include "ecmascript/layout_info.h" #include "ecmascript/message_string.h" #include "ecmascript/object_factory.h" -#include "ecmascript/interpreter/interpreter-inl.h" namespace panda::ecmascript { bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argReceiver, uint32_t argIndex, @@ -117,7 +117,11 @@ uint64_t RuntimeTrampolines::AccessorGetter(uint64_t argThread, uint64_t argGett int32_t RuntimeTrampolines::FindElementWithCache(uint64_t argThread, uint64_t hClass, uint64_t key, int32_t num) { + uintptr_t *curFp = nullptr; auto thread = reinterpret_cast(argThread); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); auto cls = reinterpret_cast(hClass); auto layoutInfo = LayoutInfo::Cast(cls->GetAttributes().GetTaggedObject()); return layoutInfo->FindElementWithCache(thread, cls, JSTaggedValue(key), num); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index a7c9e11..03ab72f 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -16,6 +16,7 @@ #ifndef ECMASCRIPT_RUNTIME_TRAMPOLINES_H #define ECMASCRIPT_RUNTIME_TRAMPOLINES_H #include "ecmascript/compiler/fast_stub_define.h" +#include "ecmascript/ecma_macros.h" #include "ecmascript/js_thread.h" namespace panda::ecmascript { @@ -64,23 +65,15 @@ public: lastFp_ = static_cast(static_cast(cursp)); JSTaggedType *newSp = static_cast(static_cast(newFp)); thread_->SetCurrentSPFrame(newSp); - // print newfp and type for debug - std::cout << "CallRuntimeTrampolinesScope newFp: " << newFp << " lastFp_ : " << lastFp_ - << std::endl; - FrameType type = *(reinterpret_cast( - reinterpret_cast(newFp) + FrameConst::FRAME_TYPE_OFFSET)); - std::cout << __FUNCTION__ << " type = " << as_integer(type) << std::endl; + LOG_ECMA(INFO) << "Sp: " << newSp << " type:" << + static_cast(Frame::GetFrameType(newSp)); } ~CallRuntimeTrampolinesScope() { - // print oldfp and type for debug - std::cout << "~CallRuntimeTrampolinesScope lastFp_: " << lastFp_ << - " thread_->fp:" << thread_->GetCurrentSPFrame() << std::endl; - FrameType type = *(reinterpret_cast( - reinterpret_cast(lastFp_) + FrameConst::FRAME_TYPE_OFFSET)); - std::cout << __FUNCTION__ << "type = " << as_integer(type) << std::endl; JSTaggedType *oldSp = static_cast(static_cast(lastFp_)); thread_->SetCurrentSPFrame(oldSp); + LOG_ECMA(INFO) << "Sp: " << oldSp << " type:" << + static_cast(Frame::GetFrameType(oldSp)); thread_->SetLastOptCallRuntimePc(lastOptCallRuntimePc_); } private: @@ -89,4 +82,4 @@ private: uintptr_t *lastOptCallRuntimePc_; }; } // namespace panda::ecmascript -#endif \ No newline at end of file +#endif diff --git a/ecmascript/tests/test_helper.h b/ecmascript/tests/test_helper.h index f65d77e..645a40c 100644 --- a/ecmascript/tests/test_helper.h +++ b/ecmascript/tests/test_helper.h @@ -65,7 +65,7 @@ public: JSTaggedType *newSp = sp - frameSize; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) FrameState *state = reinterpret_cast(newSp) - 1; - state->base.frameType = ecmascript::FrameType::INTERPRETER_FRAME; + state->base.frameType = static_cast(ecmascript::FrameType::INTERPRETER_FRAME); state->base.prev = sp; state->pc = nullptr; state->sp = newSp; -- Gitee From 33dd6a3dbf5cc221c9b583da8c3137a2f68a25b7 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Thu, 28 Oct 2021 14:54:24 +0800 Subject: [PATCH 093/115] code review Signed-off-by: songzhengchao --- ecmascript/frames.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 153b058..92757ed 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -228,7 +228,6 @@ #endif namespace panda::ecmascript { -using TaggedType = coretypes::TaggedType; class JSThread; enum class FrameType: uintptr_t { OPTIMIZED_FRAME = 0, @@ -239,18 +238,18 @@ enum class FrameType: uintptr_t { class OptimizedFrameStateBase { public: uintptr_t frameType; - TaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + JSTaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc }; class InterpretedFrameStateBase { public: - TaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + JSTaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc uintptr_t frameType; }; class OptimizedEntryFrameState { public: - TaggedType *threadFp; // for gc + JSTaggedType *threadFp; // for gc OptimizedFrameStateBase base; }; -- Gitee From c4c4d68a4f712b506eaaba5a46026698c1fc0447 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Thu, 28 Oct 2021 15:06:25 +0800 Subject: [PATCH 094/115] code review Signed-off-by: songzhengchao --- ecmascript/compiler/circuit.cpp | 5 + ecmascript/compiler/circuit.h | 1 + ecmascript/compiler/circuit_builder.cpp | 128 +++---- ecmascript/compiler/fast_stub.cpp | 181 +++++++--- ecmascript/compiler/fast_stub.h | 33 +- ecmascript/compiler/fast_stub_define.h | 10 +- ecmascript/compiler/gate.cpp | 11 + ecmascript/compiler/gate.h | 4 + .../compiler/llvm/llvm_stackmap_parser.cpp | 66 ++-- .../compiler/llvm/llvm_stackmap_parser.h | 74 ++-- ecmascript/compiler/llvm_codegen.cpp | 11 +- ecmascript/compiler/llvm_codegen.h | 4 + ecmascript/compiler/llvm_ir_builder.cpp | 40 +-- ecmascript/compiler/llvm_ir_builder.h | 2 - ecmascript/compiler/llvm_mcjit_engine.cpp | 22 +- ecmascript/compiler/llvm_mcjit_engine.h | 14 +- ecmascript/compiler/machine_type.h | 2 +- ecmascript/compiler/stub.cpp | 181 +++++++--- ecmascript/compiler/stub.h | 315 +++++++++++------- ecmascript/compiler/stub_aot_compiler.cpp | 3 +- ecmascript/compiler/stub_descriptor.cpp | 115 +++++-- ecmascript/compiler/stub_descriptor.h | 1 + ecmascript/compiler/tests/stub_tests.cpp | 64 ++-- ecmascript/compiler/type.h | 10 +- ecmascript/frames.h | 11 +- ecmascript/interpreter/frame_handler.cpp | 34 +- ecmascript/interpreter/frame_handler.h | 4 +- ecmascript/js_thread.cpp | 15 +- ecmascript/js_thread.h | 9 + ecmascript/runtime_call_id.h | 1 - ecmascript/runtime_trampolines.cpp | 62 ++++ ecmascript/runtime_trampolines.h | 7 +- ecmascript/stub_module.cpp | 43 ++- ecmascript/stub_module.h | 45 +++ js_runtime_config.gni | 2 +- 35 files changed, 1051 insertions(+), 479 deletions(-) diff --git a/ecmascript/compiler/circuit.cpp b/ecmascript/compiler/circuit.cpp index ab4a1c2..e469311 100644 --- a/ecmascript/compiler/circuit.cpp +++ b/ecmascript/compiler/circuit.cpp @@ -182,6 +182,11 @@ MarkCode Circuit::GetMark(AddrShift gate) const return this->LoadGatePtrConst(gate)->GetMark(this->GetTime()); } +TypeCode Circuit::GetTypeCode(AddrShift gate) const +{ + return this->LoadGatePtrConst(gate)->GetTypeCode(); +} + void Circuit::SetMark(AddrShift gate, MarkCode mark) const { const_cast(this->LoadGatePtrConst(gate))->SetMark(mark, this->GetTime()); diff --git a/ecmascript/compiler/circuit.h b/ecmascript/compiler/circuit.h index a331b55..51da2c1 100644 --- a/ecmascript/compiler/circuit.h +++ b/ecmascript/compiler/circuit.h @@ -72,6 +72,7 @@ public: [[nodiscard]] OpCode GetOpCode(AddrShift gate) const; [[nodiscard]] TimeStamp GetTime() const; [[nodiscard]] MarkCode GetMark(AddrShift gate) const; + [[nodiscard]] TypeCode GetTypeCode(AddrShift gate) const; void SetMark(AddrShift gate, MarkCode mark) const; [[nodiscard]] bool Verify(AddrShift gate) const; [[nodiscard]] Gate *LoadGatePtr(AddrShift shift); diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index 541311d..15d1f3a 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -155,30 +155,30 @@ AddrShift CircuitBuilder::NewDefaultCase(AddrShift switchBranch) OpCode CircuitBuilder::GetStoreOpCodeFromMachineType(MachineType type) { switch (type) { - case INT8_TYPE: + case MachineType::INT8_TYPE: return OpCode(OpCode::INT8_STORE); - case INT16_TYPE: + case MachineType::INT16_TYPE: return OpCode(OpCode::INT16_STORE); - case INT32_TYPE: + case MachineType::INT32_TYPE: return OpCode(OpCode::INT32_STORE); - case INT64_TYPE: + case MachineType::INT64_TYPE: return OpCode(OpCode::INT64_STORE); - case BOOL_TYPE: + case MachineType::BOOL_TYPE: return OpCode(OpCode::INT32_STORE); - case UINT8_TYPE: + case MachineType::UINT8_TYPE: return OpCode(OpCode::INT8_STORE); - case UINT16_TYPE: + case MachineType::UINT16_TYPE: return OpCode(OpCode::INT16_STORE); - case UINT32_TYPE: + case MachineType::UINT32_TYPE: return OpCode(OpCode::INT32_STORE); - case UINT64_TYPE: - case POINTER_TYPE: - case TAGGED_TYPE: - case TAGGED_POINTER_TYPE: + case MachineType::UINT64_TYPE: + case MachineType::POINTER_TYPE: + case MachineType::TAGGED_TYPE: + case MachineType::TAGGED_POINTER_TYPE: return OpCode(OpCode::INT64_STORE); - case FLOAT32_TYPE: + case MachineType::FLOAT32_TYPE: return OpCode(OpCode::FLOAT32_STORE); - case FLOAT64_TYPE: + case MachineType::FLOAT64_TYPE: return OpCode(OpCode::FLOAT64_STORE); default: UNREACHABLE(); @@ -188,30 +188,30 @@ OpCode CircuitBuilder::GetStoreOpCodeFromMachineType(MachineType type) OpCode CircuitBuilder::GetLoadOpCodeFromMachineType(MachineType type) { switch (type) { - case INT8_TYPE: + case MachineType::INT8_TYPE: return OpCode(OpCode::INT8_LOAD); - case INT16_TYPE: + case MachineType::INT16_TYPE: return OpCode(OpCode::INT16_LOAD); - case INT32_TYPE: + case MachineType::INT32_TYPE: return OpCode(OpCode::INT32_LOAD); - case INT64_TYPE: + case MachineType::INT64_TYPE: return OpCode(OpCode::INT64_LOAD); - case BOOL_TYPE: + case MachineType::BOOL_TYPE: return OpCode(OpCode::INT32_LOAD); - case UINT8_TYPE: + case MachineType::UINT8_TYPE: return OpCode(OpCode::INT8_LOAD); - case UINT16_TYPE: + case MachineType::UINT16_TYPE: return OpCode(OpCode::INT16_LOAD); - case UINT32_TYPE: + case MachineType::UINT32_TYPE: return OpCode(OpCode::INT32_LOAD); - case UINT64_TYPE: - case POINTER_TYPE: - case TAGGED_TYPE: - case TAGGED_POINTER_TYPE: + case MachineType::UINT64_TYPE: + case MachineType::POINTER_TYPE: + case MachineType::TAGGED_TYPE: + case MachineType::TAGGED_POINTER_TYPE: return OpCode(OpCode::INT64_LOAD); - case FLOAT32_TYPE: + case MachineType::FLOAT32_TYPE: return OpCode(OpCode::FLOAT32_LOAD); - case FLOAT64_TYPE: + case MachineType::FLOAT64_TYPE: return OpCode(OpCode::FLOAT64_LOAD); default: UNREACHABLE(); @@ -221,32 +221,32 @@ OpCode CircuitBuilder::GetLoadOpCodeFromMachineType(MachineType type) OpCode CircuitBuilder::GetSelectOpCodeFromMachineType(MachineType type) { switch (type) { - case NONE_TYPE: + case MachineType::NONE_TYPE: return OpCode(OpCode::DEPEND_SELECTOR); - case INT8_TYPE: + case MachineType::INT8_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT8); - case INT16_TYPE: + case MachineType::INT16_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT16); - case INT32_TYPE: + case MachineType::INT32_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT32); - case INT64_TYPE: + case MachineType::INT64_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT64); - case BOOL_TYPE: + case MachineType::BOOL_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT1); - case UINT8_TYPE: + case MachineType::UINT8_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT8); - case UINT16_TYPE: + case MachineType::UINT16_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT16); - case UINT32_TYPE: + case MachineType::UINT32_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT32); - case UINT64_TYPE: - case POINTER_TYPE: - case TAGGED_TYPE: - case TAGGED_POINTER_TYPE: + case MachineType::UINT64_TYPE: + case MachineType::POINTER_TYPE: + case MachineType::TAGGED_TYPE: + case MachineType::TAGGED_POINTER_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT64); - case FLOAT32_TYPE: + case MachineType::FLOAT32_TYPE: return OpCode(OpCode::VALUE_SELECTOR_FLOAT32); - case FLOAT64_TYPE: + case MachineType::FLOAT64_TYPE: return OpCode(OpCode::VALUE_SELECTOR_FLOAT64); default: UNREACHABLE(); @@ -270,13 +270,13 @@ AddrShift CircuitBuilder::NewDependAnd(std::initializer_list args) AddrShift CircuitBuilder::NewLoadGate(MachineType type, AddrShift val, AddrShift depend) { OpCode op = GetLoadOpCodeFromMachineType(type); - return circuit_->NewGate(op, type, {depend, val}, TypeCode::NOTYPE); + return circuit_->NewGate(op, static_cast(type), {depend, val}, TypeCode::NOTYPE); } AddrShift CircuitBuilder::NewStoreGate(MachineType type, AddrShift ptr, AddrShift val, AddrShift depend) { OpCode op = GetStoreOpCodeFromMachineType(type); - return circuit_->NewGate(op, type, {depend, val, ptr}, TypeCode::NOTYPE); + return circuit_->NewGate(op, static_cast(type), {depend, val, ptr}, TypeCode::NOTYPE); } AddrShift CircuitBuilder::NewArithMeticGate(OpCode opcode, AddrShift left, AddrShift right) @@ -291,43 +291,43 @@ AddrShift CircuitBuilder::NewArithMeticGate(OpCode opcode, AddrShift value) AddrShift CircuitBuilder::NewLogicGate(OpCode opcode, AddrShift left, AddrShift right) { - return circuit_->NewGate(opcode, MachineType::BOOL_TYPE, {left, right}, TypeCode::NOTYPE); + return circuit_->NewGate(opcode, static_cast(MachineType::BOOL_TYPE), {left, right}, TypeCode::NOTYPE); } AddrShift CircuitBuilder::NewLogicGate(OpCode opcode, AddrShift value) { - return circuit_->NewGate(opcode, MachineType::BOOL_TYPE, {value}, TypeCode::NOTYPE); + return circuit_->NewGate(opcode, static_cast(MachineType::BOOL_TYPE), {value}, TypeCode::NOTYPE); } OpCode CircuitBuilder::GetCallOpCodeFromMachineType(MachineType type) { switch (type) { - case NONE_TYPE: + case MachineType::NONE_TYPE: return OpCode(OpCode::CALL); - case INT8_TYPE: + case MachineType::INT8_TYPE: return OpCode(OpCode::INT8_CALL); - case INT16_TYPE: + case MachineType::INT16_TYPE: return OpCode(OpCode::INT16_CALL); - case INT32_TYPE: + case MachineType::INT32_TYPE: return OpCode(OpCode::INT32_CALL); - case INT64_TYPE: + case MachineType::INT64_TYPE: return OpCode(OpCode::INT64_CALL); - case BOOL_TYPE: + case MachineType::BOOL_TYPE: return OpCode(OpCode::INT1_CALL); - case UINT8_TYPE: + case MachineType::UINT8_TYPE: return OpCode(OpCode::INT8_CALL); - case UINT16_TYPE: + case MachineType::UINT16_TYPE: return OpCode(OpCode::INT16_CALL); - case UINT32_TYPE: + case MachineType::UINT32_TYPE: return OpCode(OpCode::INT32_CALL); - case UINT64_TYPE: - case POINTER_TYPE: - case TAGGED_TYPE: - case TAGGED_POINTER_TYPE: + case MachineType::UINT64_TYPE: + case MachineType::POINTER_TYPE: + case MachineType::TAGGED_TYPE: + case MachineType::TAGGED_POINTER_TYPE: return OpCode(OpCode::INT64_CALL); - case FLOAT32_TYPE: + case MachineType::FLOAT32_TYPE: return OpCode(OpCode::FLOAT32_CALL); - case FLOAT64_TYPE: + case MachineType::FLOAT64_TYPE: return OpCode(OpCode::FLOAT64_CALL); default: UNREACHABLE(); @@ -375,6 +375,10 @@ AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShi inputs.push_back(arg); } OpCode opcode = GetCallOpCodeFromMachineType(descriptor->GetReturnType()); + if (descriptor->GetReturnType() == MachineType::TAGGED_POINTER_TYPE) { + // 2 : 2 means extra two input gates (target thread ) + return circuit_->NewGate(opcode, args.size() + 2, inputs, TypeCode::TAGGED_POINTER_TYPE); + } // 2 : 2 means extra two input gates (target thread ) return circuit_->NewGate(opcode, args.size() + 2, inputs, TypeCode::JS_ANY); } diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 176c58e..4b0bc55 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -29,7 +29,7 @@ void FastArrayLoadElementStub::GenerateCircuit() AddrShift indexVal = Int32Argument(1); // load a.length - AddrShift lengthOffset = GetInteger32Constant(JSArray::GetArrayLengthOffset()); + AddrShift lengthOffset = GetInt32Constant(JSArray::GetArrayLengthOffset()); if (PtrValueCode() == ValueCode::INT64) { lengthOffset = SExtInt32ToInt64(lengthOffset); } else if (PtrValueCode() == ValueCode::INT32) { @@ -349,19 +349,18 @@ void FindOwnElementStub::GenerateCircuit() AddrShift thread = PtrArgument(0); AddrShift obj = PtrArgument(1); AddrShift index = Int32Argument(2); // 2: 3rd parameter - index - Label notDict(env); Label isDict(env); Label invalidValue(env); Label end(env); - AddrShift elements = Load(POINTER_TYPE, obj, GetPtrConstant(JSObject::ELEMENTS_OFFSET)); - + AddrShift elements = Load(MachineType::POINTER_TYPE, obj, GetPtrConstant(JSObject::ELEMENTS_OFFSET)); Branch(IsDictionaryMode(elements), &isDict, ¬Dict); Bind(¬Dict); { Label outOfArray(env); Label notOutOfArray(env); - AddrShift arrayLength = Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + AddrShift arrayLength = Load(MachineType::UINT32_TYPE, elements, + GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); Branch(Int32LessThanOrEqual(arrayLength, index), &outOfArray, ¬OutOfArray); Bind(&outOfArray); Jump(&invalidValue); @@ -369,7 +368,7 @@ void FindOwnElementStub::GenerateCircuit() { AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); AddrShift dataIndex = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - AddrShift value = Load(TAGGED_TYPE, elements, dataIndex); + AddrShift value = Load(MachineType::TAGGED_TYPE, elements, dataIndex); Label isHole1(env); Label notHole1(env); Branch(TaggedIsHole(value), &isHole1, ¬Hole1); @@ -388,7 +387,7 @@ void FindOwnElementStub::GenerateCircuit() AddrShift entry = FindElementFromNumberDictionary(thread, elements, taggedIndex); Label notNegtiveOne(env); Label negtiveOne(env); - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); Bind(¬NegtiveOne); { Return(GetValueFromDictionary(elements, entry)); @@ -423,7 +422,7 @@ void GetElementStub::GenerateCircuit() Bind(¬Hole); Return(callFindOwnElementVal); Bind(&isHole); - receiver = Load(TAGGED_TYPE, LoadHClass(objPtr), GetPtrConstant(JSHClass::PROTOTYPE_OFFSET)); + receiver = Load(MachineType::TAGGED_TYPE, LoadHClass(objPtr), GetPtrConstant(JSHClass::PROTOTYPE_OFFSET)); Branch(TaggedIsHeapObject(receiver), &loopEnd, ¬HeapObj); Bind(¬HeapObj); Return(GetUndefinedConstant()); @@ -444,11 +443,11 @@ void FindOwnElement2Stub::GenerateCircuit() Label notDictionary(env); Label isDictionary(env); Label end(env); - Branch(Word32Equal(isDict, GetInteger32Constant(0)), ¬Dictionary, &isDictionary); + Branch(Word32Equal(isDict, GetInt32Constant(0)), ¬Dictionary, &isDictionary); Bind(¬Dictionary); { AddrShift elementsLength = - Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + Load(MachineType::UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); Label outOfElements(env); Label notOutOfElements(env); Branch(Int32LessThanOrEqual(elementsLength, index), &outOfElements, ¬OutOfElements); @@ -466,9 +465,9 @@ void FindOwnElement2Stub::GenerateCircuit() Jump(&end); Bind(¬Hole); { - Store(UINT32_TYPE, attr, GetPtrConstant(0), - GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())); - Store(UINT32_TYPE, indexOrEntry, GetPtrConstant(0), index); + Store(MachineType::UINT32_TYPE, thread, attr, GetPtrConstant(0), + GetInt32Constant(PropertyAttributes::GetDefaultAttributes())); + Store(MachineType::UINT32_TYPE, thread, indexOrEntry, GetPtrConstant(0), index); Return(value); } } @@ -478,11 +477,12 @@ void FindOwnElement2Stub::GenerateCircuit() AddrShift entry = FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index)); Label notNegtiveOne(env); Label negtiveOne(env); - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); Bind(¬NegtiveOne); { - Store(UINT32_TYPE, attr, GetPtrConstant(0), GetAttributesFromDictionary(elements, entry)); - Store(UINT32_TYPE, indexOrEntry, GetPtrConstant(0), entry); + Store(MachineType::UINT32_TYPE, thread, attr, GetPtrConstant(0), + GetAttributesFromDictionary(elements, entry)); + Store(MachineType::UINT32_TYPE, thread, indexOrEntry, GetPtrConstant(0), entry); Return(GetValueFromDictionary(elements, entry)); } Bind(&negtiveOne); @@ -538,7 +538,7 @@ void SetElementStub::GenerateCircuit() { Label isThrow(env); Label notThrow(env); - Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw); + Branch(Word32NotEqual(mayThrow, GetInt32Constant(0)), &isThrow, ¬Throw); Bind(&isThrow); ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), FalseConstant()); Bind(¬Throw); @@ -548,11 +548,11 @@ void SetElementStub::GenerateCircuit() StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal); Return(CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)), {thread, receiver, index, value, - GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())})); + GetInt32Constant(PropertyAttributes::GetDefaultAttributes())})); } Bind(&afterOnProtoType); { - AddrShift attr = Load(INT32_TYPE, pattr); + AddrShift attr = Load(MachineType::INT32_TYPE, pattr); Label isAccessor(env); Label notAccessor(env); Branch(IsAccessor(attr), &isAccessor, ¬Accessor); @@ -566,17 +566,17 @@ void SetElementStub::GenerateCircuit() AddrShift elements = GetElements(receiver); Label isDict(env); Label notDict(env); - AddrShift indexOrEntry = Load(INT32_TYPE, pindexOrEntry); + AddrShift indexOrEntry = Load(MachineType::INT32_TYPE, pindexOrEntry); Branch(isDictionary, &isDict, ¬Dict); Bind(¬Dict); { - StoreElement(elements, indexOrEntry, value); + StoreElement(thread, elements, indexOrEntry, value); UpdateRepresention(LoadHClass(receiver), value); Return(TrueConstant()); } Bind(&isDict); { - UpdateValueAndAttributes(elements, indexOrEntry, value, attr); + UpdateValueAndAttributes(thread, elements, indexOrEntry, value, attr); Return(TrueConstant()); } } @@ -584,7 +584,7 @@ void SetElementStub::GenerateCircuit() { Label isThrow(env); Label notThrow(env); - Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw); + Branch(Word32NotEqual(mayThrow, GetInt32Constant(0)), &isThrow, ¬Throw); Bind(&isThrow); ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetReadOnlyProperty), FalseConstant()); Bind(¬Throw); @@ -619,7 +619,7 @@ void SetElementStub::GenerateCircuit() { Label isThrow(env); Label notThrow(env); - Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw); + Branch(Word32NotEqual(mayThrow, GetInt32Constant(0)), &isThrow, ¬Throw); Bind(&isThrow); ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), FalseConstant()); Bind(¬Throw); @@ -630,7 +630,7 @@ void SetElementStub::GenerateCircuit() StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal); Return(CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)), {thread, receiver, index, value, - GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())})); + GetInt32Constant(PropertyAttributes::GetDefaultAttributes())})); } } Bind(&isHeapObj); @@ -717,7 +717,7 @@ void GetPropertyByIndexStub::GenerateCircuit() FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index)); Label notNegtiveOne(env); Label negtiveOne(env); - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); Bind(¬NegtiveOne); { AddrShift attr = GetAttributesFromDictionary(elements, entry); @@ -735,13 +735,13 @@ void GetPropertyByIndexStub::GenerateCircuit() StubDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter); Return(CallRuntime(callAccessorGetter, thread, GetWord64Constant(FAST_STUB_ID(AccessorGetter)), - {thread, *holder, value})); + {thread, value, *holder})); } Bind(¬Internal); { StubDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter); Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), - {thread, receiver, value})); + {thread, value, receiver})); } } Bind(¬Accessor); @@ -813,7 +813,7 @@ void SetPropertyByIndexStub::GenerateCircuit() Branch(Word64NotEqual(value1, GetHoleConstant()), ¬Hole, &loopExit); Bind(¬Hole); { - StoreElement(elements, index, value); + StoreElement(thread, elements, index, value); Return(GetUndefinedConstant()); } } @@ -843,7 +843,7 @@ void SetPropertyByIndexStub::GenerateCircuit() AddrShift result = CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)), {thread, receiver, index, value, - GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())}); + GetInt32Constant(PropertyAttributes::GetDefaultAttributes())}); Label success(env); Label failed(env); Branch(result, &success, &failed); @@ -891,7 +891,7 @@ void GetPropertyByNameStub::GenerateCircuit() Label isDicMode(env); Label notDicMode(env); // if branch condition : LIKELY(!hclass->IsDictionaryMode()) - Branch(IsDictionaryElement(hClass), &isDicMode, ¬DicMode); + Branch(IsDictionaryModeByHClass(hClass), &isDicMode, ¬DicMode); Bind(¬DicMode); { // LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetAttributes().GetTaggedObject()) @@ -906,7 +906,7 @@ void GetPropertyByNameStub::GenerateCircuit() Label hasEntry(env); Label noEntry(env); // if branch condition : entry != -1 - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), &hasEntry, &noEntry); + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), &hasEntry, &noEntry); Bind(&hasEntry); { // PropertyAttributes attr(layoutInfo->GetAttr(entry)) @@ -927,13 +927,13 @@ void GetPropertyByNameStub::GenerateCircuit() StubDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter); Return(CallRuntime(callAccessorGetter, thread, GetWord64Constant(FAST_STUB_ID(AccessorGetter)), - {thread, *holder, value})); + {thread, value, *holder})); } Bind(¬Internal); { StubDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter); Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), - {thread, receiver, value})); + {thread, value, receiver})); } } Bind(¬Accessor); @@ -955,7 +955,7 @@ void GetPropertyByNameStub::GenerateCircuit() Label notNegtiveOne(env); Label negtiveOne(env); // if branch condition : entry != -1 - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); Bind(¬NegtiveOne); { // auto value = dict->GetValue(entry) @@ -976,13 +976,13 @@ void GetPropertyByNameStub::GenerateCircuit() StubDescriptor *callAccessorGetter1 = GET_STUBDESCRIPTOR(AccessorGetter); Return(CallRuntime(callAccessorGetter1, thread, GetWord64Constant(FAST_STUB_ID(AccessorGetter)), - {thread, *holder, value})); + {thread, value, *holder})); } Bind(¬Internal1); { StubDescriptor *callGetter1 = GET_STUBDESCRIPTOR(CallGetter); Return(CallRuntime(callGetter1, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), - {thread, receiver, value})); + {thread, value, receiver})); } } Bind(¬Accessor1); @@ -1039,10 +1039,10 @@ void FastModStub::GenerateCircuit() { Label xGtZero(env); Label xGtZeroAndyGtZero(env); - Branch(Int32GreaterThan(*intX, GetInteger32Constant(0)), &xGtZero, &xNotIntOryNotInt); + Branch(Int32GreaterThan(*intX, GetInt32Constant(0)), &xGtZero, &xNotIntOryNotInt); Bind(&xGtZero); { - Branch(Int32GreaterThan(*intY, GetInteger32Constant(0)), &xGtZeroAndyGtZero, &xNotIntOryNotInt); + Branch(Int32GreaterThan(*intY, GetInt32Constant(0)), &xGtZeroAndyGtZero, &xNotIntOryNotInt); Bind(&xGtZeroAndyGtZero); { intX = Int32Mod(*intX, *intY); @@ -1164,6 +1164,82 @@ void FastModStub::GenerateCircuit() } } +void FastMulGCStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + env->GetCircuit()->SetFrameType(FrameType::OPTIMIZED_ENTRY_FRAME); + AddrShift thread = PtrArgument(0); + (void)thread; + AddrShift x = Int64Argument(1); + AddrShift y = Int64Argument(2); + + DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); + DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); + DEFVARIABLE(intZ, MachineType::INT32_TYPE, 0); + DEFVARIABLE(valuePtr, MachineType::INT64_TYPE, 0); + DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); + DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xIsNumberAndyIsNumber(env); + Label xIsDoubleAndyIsDouble(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if right.IsNumber() + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt32(x); + doubleX = CastInt32ToFloat64(*intX); + Jump(&xIsNumberAndyIsNumber); + } + Bind(&xNotInt); + { + doubleX = TaggedCastToDouble(x); + Jump(&xIsNumberAndyIsNumber); + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant()); + Label yIsInt(env); + Label yNotInt(env); + Bind(&xIsNumberAndyIsNumber); + { + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + doubleY = CastInt32ToFloat64(*intY); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xIsDoubleAndyIsDouble); + } + } + Bind(&xIsDoubleAndyIsDouble); + doubleX = DoubleMul(*doubleX, *doubleY); + StubDescriptor *getTaggedArrayPtr = GET_STUBDESCRIPTOR(GetTaggedArrayPtr); + AddrShift ptr1 = CallRuntime(getTaggedArrayPtr, thread, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtr)), + {thread}); + AddrShift ptr2 = CallRuntime(getTaggedArrayPtr, thread, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtr)), + {thread}); + (void)ptr2; + auto value = Load(MachineType::INT64_TYPE, ptr1); + AddrShift value2 = CastInt64ToFloat64(value); + doubleX = DoubleMul(*doubleX, value2); + Return(DoubleBuildTagged(*doubleX)); +} + void FastTypeOfStub::GenerateCircuit() { auto env = GetEnvironment(); @@ -1172,14 +1248,14 @@ void FastTypeOfStub::GenerateCircuit() DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, obj); AddrShift gConstOffset = PtrAdd(thread, GetPtrConstant(panda::ecmascript::JSThread::GetGlobalConstantOffset())); AddrShift booleanIndex = GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX); - AddrShift gConstUndefindStr = Load(TAGGED_TYPE, gConstOffset, booleanIndex); + AddrShift gConstUndefindStr = Load(MachineType::TAGGED_TYPE, gConstOffset, booleanIndex); DEFVARIABLE(resultRep, MachineType::TAGGED_TYPE, gConstUndefindStr); Label objIsTrue(env); Label objNotTrue(env); Label exit(env); Label defaultLabel(env); AddrShift gConstBooleanStr = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX)); Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_TRUE)), &objIsTrue, &objNotTrue); Bind(&objIsTrue); { @@ -1204,7 +1280,8 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsNull); { resultRep = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); Jump(&exit); } Bind(&objNotNull); @@ -1215,7 +1292,7 @@ void FastTypeOfStub::GenerateCircuit() &objNotUndefined); Bind(&objIsUndefined); { - resultRep = Load(TAGGED_TYPE, gConstOffset, + resultRep = Load(MachineType::TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX)); Jump(&exit); } @@ -1237,7 +1314,8 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsString); { resultRep = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX)); Jump(&exit); } Bind(&objNotString); @@ -1247,7 +1325,7 @@ void FastTypeOfStub::GenerateCircuit() Branch(IsSymbol(obj), &objIsSymbol, &objNotSymbol); Bind(&objIsSymbol); { - resultRep = Load(TAGGED_TYPE, gConstOffset, + resultRep = Load(MachineType::TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::SYMBOL_STRING_INDEX)); Jump(&exit); } @@ -1259,13 +1337,15 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsCallable); { resultRep = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX)); Jump(&exit); } Bind(&objNotCallable); { resultRep = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); Jump(&exit); } } @@ -1279,7 +1359,8 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsNum); { resultRep = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX)); Jump(&exit); } Bind(&objNotNum); @@ -1307,11 +1388,11 @@ void FunctionCallInternalStub::GenerateCircuit() { Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcIsBuiltinsConstructorOrFuncNotClassConstructor); Bind(&funcIsClassConstructor); - ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(FunctionCallNotConstructor), FalseConstant()); + ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(FunctionCallNotConstructor), GetExceptionConstant()); } Bind(&funcIsBuiltinsConstructorOrFuncNotClassConstructor); StubDescriptor *execute = GET_STUBDESCRIPTOR(Execute); Return(CallRuntime(execute, thread, GetWord64Constant(FAST_STUB_ID(Execute)), {thread, func, thisArg, argc, argv})); } -} // namespace kungfu \ No newline at end of file +} // namespace kungfu diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 853628b..cef9e55 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -60,6 +60,16 @@ public: void GenerateCircuit() override; }; +class FastMulGCStub : public Stub { +public: + // 3 : 3 means argument counts + explicit FastMulGCStub(Circuit *circuit) : Stub("FastMulGC", 3, circuit) {} + ~FastMulGCStub() = default; + NO_MOVE_SEMANTIC(FastMulGCStub); + NO_COPY_SEMANTIC(FastMulGCStub); + void GenerateCircuit() override; +}; + class FastDivStub : public Stub { public: // 2 : 2 means argument counts @@ -83,7 +93,10 @@ public: class GetElementStub : public Stub { public: // 3 : 3 means argument counts - explicit GetElementStub(Circuit *circuit) : Stub("GetElement", 3, circuit) {} + explicit GetElementStub(Circuit *circuit) : Stub("GetElement", 3, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } ~GetElementStub() = default; NO_MOVE_SEMANTIC(GetElementStub); NO_COPY_SEMANTIC(GetElementStub); @@ -113,7 +126,10 @@ public: class GetPropertyByIndexStub : public Stub { public: // 3 : 3 means argument counts - explicit GetPropertyByIndexStub(Circuit *circuit) : Stub("GetPropertyByIndex", 3, circuit) {} + explicit GetPropertyByIndexStub(Circuit *circuit) : Stub("GetPropertyByIndex", 3, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } ~GetPropertyByIndexStub() = default; NO_MOVE_SEMANTIC(GetPropertyByIndexStub); NO_COPY_SEMANTIC(GetPropertyByIndexStub); @@ -123,7 +139,10 @@ public: class SetPropertyByIndexStub : public Stub { public: // 4 : 4 means argument counts - explicit SetPropertyByIndexStub(Circuit *circuit) : Stub("SetPropertyByIndex", 4, circuit) {} + explicit SetPropertyByIndexStub(Circuit *circuit) : Stub("SetPropertyByIndex", 4, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } ~SetPropertyByIndexStub() = default; NO_MOVE_SEMANTIC(SetPropertyByIndexStub); NO_COPY_SEMANTIC(SetPropertyByIndexStub); @@ -133,7 +152,10 @@ public: class GetPropertyByNameStub : public Stub { public: // 3 : 3 means argument counts - explicit GetPropertyByNameStub(Circuit *circuit) : Stub("GetPropertyByName", 3, circuit) {} + explicit GetPropertyByNameStub(Circuit *circuit) : Stub("GetPropertyByName", 3, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } ~GetPropertyByNameStub() = default; NO_MOVE_SEMANTIC(GetPropertyByNameStub); NO_COPY_SEMANTIC(GetPropertyByNameStub); @@ -173,4 +195,5 @@ public: void GenerateCircuit() override; }; } // namespace kungfu -#endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H \ No newline at end of file + +#endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index 1bc6e8c..44a6663 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -29,7 +29,9 @@ namespace kungfu { V(FindElementWithCache, 4) \ V(Execute, 5) \ V(StringGetHashCode, 1) \ - V(FloatMod, 2) + V(FloatMod, 2) \ + V(SetValueWithBarrier, 4) \ + V(GetTaggedArrayPtr, 1) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define FAST_RUNTIME_STUB_LIST(V) \ @@ -46,7 +48,6 @@ namespace kungfu { V(GetPropertyByName, 3) \ V(GetElement, 2) \ V(SetElement, 5) \ - V(SetPropertyByName, 5) \ V(SetGlobalOwnProperty, 5) \ V(GetGlobalOwnProperty, 3) \ V(SetOwnPropertyByName, 4) \ @@ -60,7 +61,8 @@ namespace kungfu { V(FindOwnElement2, 6) \ V(GetPropertyByIndex, 3) \ V(FunctionCallInternal, 5) \ - V(SetPropertyByIndex, 4) + V(SetPropertyByIndex, 4) \ + V(FastMulGC, 3) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define TEST_FUNC_LIST(V) \ @@ -89,4 +91,4 @@ enum CallStubId { // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define FAST_STUB_ID(name) kungfu::CallStubId::NAME_##name } // namespace kungfu -#endif // ECMASCRIPT_COMPILER_FASTSTUB_DEFINE_H \ No newline at end of file +#endif // ECMASCRIPT_COMPILER_FASTSTUB_DEFINE_H diff --git a/ecmascript/compiler/gate.cpp b/ecmascript/compiler/gate.cpp index f2e0983..b9a3ffd 100644 --- a/ecmascript/compiler/gate.cpp +++ b/ecmascript/compiler/gate.cpp @@ -381,6 +381,7 @@ std::string OpCode::Str() const {INT64_CALL, "INT64_CALL"}, {FLOAT32_CALL, "FLOAT32_CALL"}, {FLOAT64_CALL, "FLOAT64_CALL"}, + {TAGGED_POINTER_CALL, "TAGGED_POINTER_CALL"}, {ALLOCA, "ALLOCA"}, {INT1_ARG, "INT1_ARG"}, {INT8_ARG, "INT8_ARG"}, @@ -1249,6 +1250,11 @@ void Gate::SetMark(MarkCode mark, TimeStamp stamp) this->mark = mark; } +TypeCode Gate::GetTypeCode() const +{ + return type; +} + bool OpCode::IsRoot() const { return (this->GetProperties().states == OpCode::CIRCUIT_ROOT) || (this->op == OpCode::CIRCUIT_ROOT); @@ -1305,4 +1311,9 @@ bool OpCode::IsLoopHead() const { return (this->op == OpCode::LOOP_BEGIN); } + +bool OpCode::IsNop() const +{ + return (this->op == OpCode::NOP); +} } // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/gate.h b/ecmascript/compiler/gate.h index a112479..e38b93f 100644 --- a/ecmascript/compiler/gate.h +++ b/ecmascript/compiler/gate.h @@ -49,6 +49,7 @@ enum ValueCode { INT64, FLOAT32, FLOAT64, + TAGGED_POINTER, }; std::string ValueCodeToStr(ValueCode valueCode); @@ -128,6 +129,7 @@ public: INT64_CALL, FLOAT32_CALL, FLOAT64_CALL, + TAGGED_POINTER_CALL, ALLOCA, INT1_ARG, INT8_ARG, @@ -253,6 +255,7 @@ public: [[nodiscard]] bool IsCFGMerge() const; [[nodiscard]] bool IsControlCase() const; [[nodiscard]] bool IsLoopHead() const; + [[nodiscard]] bool IsNop() const; ~OpCode() = default; private: @@ -368,6 +371,7 @@ public: [[nodiscard]] bool Verify() const; [[nodiscard]] MarkCode GetMark(TimeStamp stamp) const; void SetMark(MarkCode mark, TimeStamp stamp); + TypeCode GetTypeCode() const; ~Gate() = default; private: diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index 0c4650c..1a0b539 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -41,8 +41,10 @@ bool LLVMStackMapParser::StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTyp { bool found = false; for (auto it: callSiteInfos_) { + LOG_ECMA(INFO) << __FUNCTION__ << std::hex << " addr:" << it.first << std::endl; if (it.first == funcAddr) { DwarfRegAndOffsetType info = it.second; + LOG_ECMA(INFO) << __FUNCTION__ << " info <" << info.first << " ," << info.second << " >" << std::endl; infos.push_back(info); found = true; } @@ -51,7 +53,7 @@ bool LLVMStackMapParser::StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTyp } bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t frameFp, - std::vector &slotAddrs) + std::set &slotAddrs) { DwarfRegAndOffsetTypeVector infos; if (!StackMapByAddr(funcAddr, infos)) { @@ -62,7 +64,7 @@ bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t fram for (auto &info: infos) { if (info.first == SP_DWARF_REG_NUM) { uintptr_t *rsp = fp + SP_OFFSET; - address = reinterpret_cast(reinterpret_cast(rsp) + info.second); + address = reinterpret_cast(reinterpret_cast(rsp) + info.second); } else if (info.first == FP_DWARF_REG_NUM) { fp = reinterpret_cast(*fp); address = reinterpret_cast(reinterpret_cast(fp) + info.second); @@ -70,10 +72,10 @@ bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t fram address = nullptr; abort(); } - std::cout << std::hex << "ref addr:" << address; - std::cout << " value:" << *address; - std::cout << " *value :" << **address << std::endl; - slotAddrs.push_back(reinterpret_cast(address)); + LOG_ECMA(INFO) << std::hex << "stackMap ref addr:" << address; + LOG_ECMA(INFO) << " value:" << *address; + LOG_ECMA(INFO) << " *value :" << **address << std::endl; + slotAddrs.insert(reinterpret_cast(address)); } return true; } @@ -83,24 +85,21 @@ void LLVMStackMapParser::CalcCallSite() uint64_t recordNum = 0; for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) { uintptr_t address = llvmStackMap_.StkSizeRecords[i].functionAddress; - std::cout << std::hex << "address " << address << std::endl; uint64_t recordCount = llvmStackMap_.StkSizeRecords[i].recordCount; - std::cout << std::hex << "recordCount " << recordCount << std::endl; - recordNum += recordCount; - std::cout << std::hex << "recordNum " << recordNum << std::endl; - struct StkMapRecordHeadTy recordHead = llvmStackMap_.StkMapRecord[recordNum - 1].head; - uint32_t instructionOffset = recordHead.InstructionOffset; - std::cout << std::hex << "instructionOffset " << instructionOffset << std::endl; - uintptr_t callsite = address + instructionOffset; - - for (int j = 0; j < recordHead.NumLocations; j++) { - struct LocationTy loc = llvmStackMap_.StkMapRecord[recordNum - 1].Locations[j]; - if (loc.location == LocationTy::Kind::INDIRECT) { - DwarfRegAndOffsetType info(loc.DwarfRegNum, loc.OffsetOrSmallConstant); - Fun2InfoType callSiteInfo {callsite, info}; - callSiteInfos_.push_back(callSiteInfo); + for (uint64_t k = 0; k < recordCount; k++) { + struct StkMapRecordHeadTy recordHead = llvmStackMap_.StkMapRecord[recordNum + k].head; + for (int j = 0; j < recordHead.NumLocations; j++) { + struct LocationTy loc = llvmStackMap_.StkMapRecord[recordNum + k].Locations[j]; + uint32_t instructionOffset = recordHead.InstructionOffset; + uintptr_t callsite = address + instructionOffset; + if (loc.location == LocationTy::Kind::INDIRECT) { + DwarfRegAndOffsetType info(loc.DwarfRegNum, loc.OffsetOrSmallConstant); + Fun2InfoType callSiteInfo {callsite, info}; + callSiteInfos_.push_back(callSiteInfo); + } } } + recordNum += recordCount; } } @@ -108,7 +107,7 @@ bool LLVMStackMapParser::CalculateStackMap(const uint8_t *stackMapAddr) { stackMapAddr_ = stackMapAddr; if (!stackMapAddr_) { - std::cerr << "stackMapAddr_ nullptr error ! " << std::endl; + LOG_ECMA(ERROR) << "stackMapAddr_ nullptr error ! " << std::endl; return false; } dataInfo_ = std::make_unique(stackMapAddr_); @@ -152,4 +151,25 @@ bool LLVMStackMapParser::CalculateStackMap(const uint8_t *stackMapAddr) CalcCallSite(); return true; } -} // namespace kungfu \ No newline at end of file + +bool LLVMStackMapParser::CalculateStackMap(const uint8_t *stackMapAddr, + uintptr_t hostCodeSectionAddr, uintptr_t deviceCodeSectionAddr) +{ + bool ret = CalculateStackMap(stackMapAddr); + if (!ret) { + return ret; + } + // update functionAddress from host side to device side + LOG_ECMA(INFO) << "stackmap calculate update funcitonaddress " << std::endl; + for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) { + uintptr_t hostAddr = llvmStackMap_.StkSizeRecords[i].functionAddress; + uintptr_t deviceAddr = hostAddr - hostCodeSectionAddr + deviceCodeSectionAddr; + llvmStackMap_.StkSizeRecords[i].functionAddress = deviceAddr; + LOG_ECMA(INFO) << std::dec << i << "th function " << std::hex << hostAddr << " ---> " << deviceAddr + << std::endl; + } + callSiteInfos_.clear(); + CalcCallSite(); + return true; +} +} // namespace kungfu diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.h b/ecmascript/compiler/llvm/llvm_stackmap_parser.h index 6e994e6..37b4afb 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.h +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.h @@ -18,8 +18,10 @@ #include #include -#include #include +#include +#include "ecmascript/common.h" +#include "ecmascript/ecma_macros.h" #ifdef PANDA_TARGET_AMD64 #define SP_DWARF_REG_NUM 7 @@ -44,9 +46,9 @@ struct Header { uint16_t Reserved1; // Reserved (expected to be 0) void Print() const { - std::cout << "----- head ----" << std::endl; - std::cout << " version:" << stackmapversion << std::endl; - std::cout << "+++++ head ++++" << std::endl; + LOG_ECMA(INFO) << "----- head ----" << std::endl; + LOG_ECMA(INFO) << " version:" << static_cast(stackmapversion) << std::endl; + LOG_ECMA(INFO) << "+++++ head ++++" << std::endl; } }; @@ -56,9 +58,9 @@ struct StkSizeRecordTy { uint64_t recordCount; void Print() const { - std::cout << " functionAddress:0x" << std::hex << functionAddress << std::endl; - std::cout << " stackSize:" << std::dec << stackSize << std::endl; - std::cout << " recordCount:" << std::dec << recordCount << std::endl; + LOG_ECMA(INFO) << " functionAddress:0x" << std::hex << functionAddress << std::endl; + LOG_ECMA(INFO) << " stackSize:" << std::dec << stackSize << std::endl; + LOG_ECMA(INFO) << " recordCount:" << std::dec << recordCount << std::endl; } }; @@ -66,7 +68,7 @@ struct ConstantsTy { uint64_t LargeConstant; void Print() const { - std::cout << " LargeConstant:" << LargeConstant << std::endl; + LOG_ECMA(INFO) << " LargeConstant:" << LargeConstant << std::endl; } }; @@ -77,14 +79,14 @@ struct StkMapRecordHeadTy { uint16_t NumLocations; void Print() const { - std::cout << " PatchPointID:" << std::hex << PatchPointID << std::endl; - std::cout << " instructionOffset:" << std::hex << InstructionOffset << std::endl; - std::cout << " Reserved:" << Reserved << std::endl; - std::cout << " NumLocations:" << NumLocations << std::endl; + LOG_ECMA(INFO) << " PatchPointID:" << std::hex << PatchPointID << std::endl; + LOG_ECMA(INFO) << " instructionOffset:" << std::hex << InstructionOffset << std::endl; + LOG_ECMA(INFO) << " Reserved:" << Reserved << std::endl; + LOG_ECMA(INFO) << " NumLocations:" << NumLocations << std::endl; } }; -struct LocationTy { +struct LocationTy { enum class Kind: uint8_t { REGISTER = 1, DIRECT = 2, @@ -99,14 +101,14 @@ struct LocationTy { uint16_t Reserved_1; OffsetType OffsetOrSmallConstant; - std::string TypeToString(Kind loc) const; + std::string PUBLIC_API TypeToString(Kind loc) const; void Print() const { - std::cout << TypeToString(location); - std::cout << ", size:" << std::dec << LocationSize; - std::cout << "\tDwarfRegNum:" << DwarfRegNum; - std::cout << "\t OffsetOrSmallConstant:" << OffsetOrSmallConstant << std::endl; + LOG_ECMA(INFO) << TypeToString(location); + LOG_ECMA(INFO) << ", size:" << std::dec << LocationSize; + LOG_ECMA(INFO) << "\tDwarfRegNum:" << DwarfRegNum; + LOG_ECMA(INFO) << "\t OffsetOrSmallConstant:" << OffsetOrSmallConstant << std::endl; } }; @@ -116,9 +118,9 @@ struct LiveOutsTy { uint8_t SizeinBytes; void Print() const { - std::cout << " Dwarf RegNum:" << DwarfRegNum << std::endl; - std::cout << " Reserved:" << Reserved << std::endl; - std::cout << " SizeinBytes:" << SizeinBytes << std::endl; + LOG_ECMA(INFO) << " Dwarf RegNum:" << DwarfRegNum << std::endl; + LOG_ECMA(INFO) << " Reserved:" << Reserved << std::endl; + LOG_ECMA(INFO) << " SizeinBytes:" << SizeinBytes << std::endl; } }; @@ -131,38 +133,38 @@ struct StkMapRecordTy { head.Print(); auto size = Locations.size(); for (size_t i = 0; i < size; i++) { - std::cout << " #" << std::dec << i << ":"; + LOG_ECMA(INFO) << " #" << std::dec << i << ":"; Locations[i].Print(); } size = LiveOuts.size(); for (size_t i = 0; i < size; i++) { - std::cout << " liveOuts[" << i << "] info:" << std::endl; + LOG_ECMA(INFO) << " liveOuts[" << i << "] info:" << std::endl; } } }; class DataInfo { public: - explicit DataInfo(const uint8_t *data): data_(data), offset(0) {} + explicit DataInfo(const uint8_t *data): data_(data), offset_(0) {} ~DataInfo() { data_ = nullptr; - offset = 0; + offset_ = 0; } template T Read() { - T t = *reinterpret_cast(data_ + offset); - offset += sizeof(T); + T t = *reinterpret_cast(data_ + offset_); + offset_ += sizeof(T); return t; } unsigned int GetOffset() const { - return offset; + return offset_; } private: const uint8_t *data_; - unsigned int offset; + unsigned int offset_; }; struct LLVMStackMap { @@ -174,15 +176,15 @@ struct LLVMStackMap { { head.Print(); for (size_t i = 0; i < StkSizeRecords.size(); i++) { - std::cout << "stkSizeRecord[" << i << "] info:" << std::endl; + LOG_ECMA(INFO) << "stkSizeRecord[" << i << "] info:" << std::endl; StkSizeRecords[i].Print(); } for (size_t i = 0; i < Constants.size(); i++) { - std::cout << "constants[" << i << "] info:" << std::endl; + LOG_ECMA(INFO) << "constants[" << i << "] info:" << std::endl; Constants[i].Print(); } for (size_t i = 0; i < StkMapRecord.size(); i++) { - std::cout << "StkMapRecord[" << i << "] info:" << std::endl; + LOG_ECMA(INFO) << "StkMapRecord[" << i << "] info:" << std::endl; StkMapRecord[i].Print(); } } @@ -195,14 +197,16 @@ public: static LLVMStackMapParser instance; return instance; } - bool CalculateStackMap(const uint8_t *stackMapAddr); - void Print() const + bool PUBLIC_API CalculateStackMap(const uint8_t *stackMapAddr); + bool PUBLIC_API CalculateStackMap(const uint8_t *stackMapAddr, + uintptr_t hostCodeSectionAddr, uintptr_t deviceCodeSectionAddr); + void PUBLIC_API Print() const { llvmStackMap_.Print(); } bool StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTypeVector &infos); bool StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t frameFp, - std::vector &slotAddrs); + std::set &slotAddrs); private: LLVMStackMapParser() { diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index d0c2606..363b161 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -14,6 +14,7 @@ */ #include "llvm_codegen.h" +#include "llvm/llvm_stackmap_parser.h" #include "ecmascript/object_factory.h" #include "stub_descriptor.h" @@ -36,13 +37,21 @@ void LLVMModuleAssembler::AssembleStubModule(StubModule *module) { auto codeBuff = reinterpret_cast
(assembler_.GetCodeBuffer()); auto engine = assembler_.GetEngine(); + std::map addr2name; for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { auto stubfunction = stubmodule_->GetStubFunction(i); + LOG_ECMA(INFO) << " AssembleStubModule :" << i << " th " << std::endl; if (stubfunction != nullptr) { Address stubEntry = reinterpret_cast
(LLVMGetPointerToGlobal(engine, stubfunction)); module->SetStubEntry(i, stubEntry - codeBuff); + addr2name[stubEntry] = GET_STUBDESCRIPTOR_BY_ID(i)->GetName(); + LOG_ECMA(INFO) << "name : " << addr2name[codeBuff] << std::endl; } } - assembler_.Disassemble(); + module->SetHostCodeSectionAddr(codeBuff); + // stackmaps ptr and size + module->SetStackMapAddr(reinterpret_cast
(assembler_.GetStackMapsSection())); + module->SetStackMapSize(assembler_.GetStackMapsSize()); + assembler_.Disassemble(addr2name); } } // namespace kungfu diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index 3fc988a..2d2460b 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -46,6 +46,10 @@ public: { return assembler_.GetCodeSize(); } + int GetStackMapsSize() const + { + return assembler_.GetStackMapsSize(); + } void CopyAssemblerToCode(panda::ecmascript::MachineCode *code) { code->SetData(reinterpret_cast(assembler_.GetCodeBuffer()), assembler_.GetCodeSize()); diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 4422c6e..7a7efcc 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -30,15 +30,6 @@ namespace kungfu { std::unordered_map g_values = {}; -LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, - LLVMModuleRef module, LLVMValueRef function) - : schedule_(schedule), circuit_(circuit), module_(module), function_(function) -{ - builder_ = LLVMCreateBuilder(); - context_ = LLVMGetGlobalContext(); - bbIdMapBb_.clear(); -} - LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, LLVMStubModule *module, LLVMValueRef function) : schedule_(schedule), circuit_(circuit), module_(module->GetModule()), @@ -46,6 +37,7 @@ LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule { builder_ = LLVMCreateBuilder(); context_ = LLVMGetGlobalContext(); + LLVMSetGC(function_, "statepoint-example"); bbIdMapBb_.clear(); } @@ -145,6 +137,7 @@ void LLVMIRBuilder::AssignHandleMap() {OpCode::INT64_LSL, &LLVMIRBuilder::HandleIntLsl}, {OpCode::FLOAT64_SMOD, &LLVMIRBuilder::HandleFloatMod}, {OpCode::INT32_SMOD, &LLVMIRBuilder::HandleIntMod}, + {OpCode::TAGGED_POINTER_CALL, &LLVMIRBuilder::HandleCall}, }; opCodeHandleIgnore= {OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY, @@ -186,8 +179,6 @@ void LLVMIRBuilder::Build() AddrShift gate = (*schedule_)[bbIdx][instIdx - 1]; std::vector ins = circuit_->GetInVector(gate); std::vector outs = circuit_->GetOutVector(gate); - std::cout << "instIdx :" << instIdx << std::endl; - circuit_->Print(gate); auto found = opCodeHandleMap_.find(circuit_->GetOpCode(gate)); if (found != opCodeHandleMap_.end()) { (this->*(found->second))(gate); @@ -1356,19 +1347,20 @@ LLVMTypeRef LLVMStubModule::GetLLVMFunctionTypeStubDescriptor(StubDescriptor *st LLVMTypeRef LLVMStubModule::ConvertLLVMTypeFromMachineType(MachineType type) { static std::map machineTypeMap = { - {MachineType::NONE_TYPE, LLVMVoidType()}, - {MachineType::BOOL_TYPE, LLVMInt1Type()}, - {MachineType::INT8_TYPE, LLVMInt8Type()}, - {MachineType::INT16_TYPE, LLVMInt16Type()}, - {MachineType::INT32_TYPE, LLVMInt32Type()}, - {MachineType::INT64_TYPE, LLVMInt64Type()}, - {MachineType::UINT8_TYPE, LLVMInt8Type()}, - {MachineType::UINT16_TYPE, LLVMInt16Type()}, - {MachineType::UINT32_TYPE, LLVMInt32Type()}, - {MachineType::UINT64_TYPE, LLVMInt64Type()}, - {MachineType::FLOAT32_TYPE, LLVMFloatType()}, - {MachineType::FLOAT64_TYPE, LLVMDoubleType()}, - {MachineType::TAGGED_TYPE, LLVMInt64Type()}, + {MachineType::NONE_TYPE, LLVMVoidType()}, + {MachineType::BOOL_TYPE, LLVMInt1Type()}, + {MachineType::INT8_TYPE, LLVMInt8Type()}, + {MachineType::INT16_TYPE, LLVMInt16Type()}, + {MachineType::INT32_TYPE, LLVMInt32Type()}, + {MachineType::INT64_TYPE, LLVMInt64Type()}, + {MachineType::UINT8_TYPE, LLVMInt8Type()}, + {MachineType::UINT16_TYPE, LLVMInt16Type()}, + {MachineType::UINT32_TYPE, LLVMInt32Type()}, + {MachineType::UINT64_TYPE, LLVMInt64Type()}, + {MachineType::FLOAT32_TYPE, LLVMFloatType()}, + {MachineType::FLOAT64_TYPE, LLVMDoubleType()}, + {MachineType::TAGGED_POINTER_TYPE, LLVMPointerType(LLVMInt64Type(), 1)}, + {MachineType::TAGGED_TYPE, LLVMInt64Type()}, }; return machineTypeMap[type]; } diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index 3bb6735..85a5612 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -193,8 +193,6 @@ private: class LLVMIRBuilder { public: - explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, - LLVMModuleRef module, LLVMValueRef function); explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, LLVMStubModule *module, LLVMValueRef function); ~LLVMIRBuilder(); diff --git a/ecmascript/compiler/llvm_mcjit_engine.cpp b/ecmascript/compiler/llvm_mcjit_engine.cpp index 3fb6d34..42fa270 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.cpp +++ b/ecmascript/compiler/llvm_mcjit_engine.cpp @@ -101,17 +101,18 @@ bool LLVMAssembler::BuildMCJITEngine() void LLVMAssembler::BuildAndRunPasses() const { - LOG_ECMA(INFO) << "BuildAndRunPasses - "; - LLVMPassManagerRef pass = LLVMCreatePassManager(); - LLVMAddConstantPropagationPass(pass); - LLVMAddInstructionCombiningPass(pass); - llvm::unwrap(pass)->add(llvm::createRewriteStatepointsForGCLegacyPass()); + std::cout << "BuildAndRunPasses - "; + LLVMPassManagerRef pm = LLVMCreatePassManager(); + LLVMAddConstantPropagationPass(pm); + LLVMAddInstructionCombiningPass(pm); + llvm::unwrap(pm)->add(llvm::createRewriteStatepointsForGCLegacyPass()); char *info = LLVMPrintModuleToString(module_); - LOG_ECMA(INFO) << "Current Module: " << info; + std::cout << "Current Module: " << info; + LLVMDumpModule(module_); LLVMDisposeMessage(info); - LLVMRunPassManager(pass, module_); - LLVMDisposePassManager(pass); - LOG_ECMA(INFO) << "BuildAndRunPasses + "; + LLVMRunPassManager(pm, module_); + LLVMDisposePassManager(pm); + std::cout << "BuildAndRunPasses + "; } LLVMAssembler::LLVMAssembler(LLVMModuleRef module, const char* triple): module_(module), engine_(nullptr), @@ -132,6 +133,9 @@ LLVMAssembler::~LLVMAssembler() void LLVMAssembler::Run() { + char *error = nullptr; + LLVMVerifyModule(module_, LLVMAbortProcessAction, &error); + LLVMDisposeMessage(error); UseRoundTripSectionMemoryManager(); if (!BuildMCJITEngine()) { return; diff --git a/ecmascript/compiler/llvm_mcjit_engine.h b/ecmascript/compiler/llvm_mcjit_engine.h index feb851f..8186a70 100644 --- a/ecmascript/compiler/llvm_mcjit_engine.h +++ b/ecmascript/compiler/llvm_mcjit_engine.h @@ -71,7 +71,7 @@ struct CodeInfo { return addr; } - uint8_t *AllocaDataSection(uintptr_t size, const char *sectionName) + uint8_t *AllocaDataSection(int size, const char *sectionName) { uint8_t *addr = nullptr; dataSectionList_.push_back(std::vector()); @@ -79,8 +79,9 @@ struct CodeInfo { dataSectionNames_.push_back(sectionName); addr = static_cast(dataSectionList_.back().data()); if (!strcmp(sectionName, ".llvm_stackmaps")) { - LOG_ECMA(INFO) << "llvm_stackmaps : " << addr; + LOG_ECMA(INFO) << "llvm_stackmaps : " << addr << " size:" << size << std::endl; stackMapsSection_ = addr; + stackMapsSize_ = size; } return addr; } @@ -99,6 +100,10 @@ struct CodeInfo { { return stackMapsSection_; } + int GetStackMapsSize() const + { + return stackMapsSize_; + } std::vector> GetCodeInfo() const { return codeInfo_; @@ -125,6 +130,7 @@ private: std::vector> codeInfo_ {}; /* stack map */ uint8_t *stackMapsSection_ {nullptr}; + int stackMapsSize_ = 0; }; class LLVMAssembler { public: @@ -140,6 +146,10 @@ public: { return codeInfo_.GetStackMapsSection(); } + int GetStackMapsSize() const + { + return codeInfo_.GetStackMapsSize(); + } int GetCodeSize() const { diff --git a/ecmascript/compiler/machine_type.h b/ecmascript/compiler/machine_type.h index 3530cd1..f17f608 100644 --- a/ecmascript/compiler/machine_type.h +++ b/ecmascript/compiler/machine_type.h @@ -17,7 +17,7 @@ #define ECMASCRIPT_COMPILER_MACHINE_TYPE_H namespace kungfu { -enum MachineType { +enum class MachineType { NONE_TYPE, BOOL_TYPE, INT8_TYPE, diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 4550be2..5e18de6 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -34,8 +34,10 @@ AddrShift Stub::Variable::AddPhiOperand(AddrShift val) Label label = env_->GetLabelFromSelector(val); size_t idx = 0; for (auto pred : label.GetPredecessors()) { + auto preVal = pred.ReadVariable(this); + ASSERT(!env_->GetCircuit()->GetOpCode(preVal).IsNop()); idx++; - val = AddOperandToSelector(val, idx, pred.ReadVariable(this)); + val = AddOperandToSelector(val, idx, preVal); } return TryRemoveTrivialPhi(val); @@ -66,7 +68,7 @@ AddrShift Stub::Variable::TryRemoveTrivialPhi(AddrShift phiVal) // the phi is unreachable or in the start block same = env_->GetCircuit()->LoadGatePtr(env_->GetCircuitBuilder().UndefineConstant()); } - + auto sameAddrShift = env_->GetCircuit()->SaveGatePtr(same); // remove the trivial phi // get all users of phi except self std::vector outs; @@ -91,11 +93,14 @@ AddrShift Stub::Variable::TryRemoveTrivialPhi(AddrShift phiVal) // try to recursiveby remove all phi users, which might have vecome trivial for (auto out : outs) { if (IsSelector(out->GetGate())) { - auto out_addr_shift = env_->GetCircuit()->SaveGatePtr(out->GetGate()); - TryRemoveTrivialPhi(out_addr_shift); + auto outAddrShift = env_->GetCircuit()->SaveGatePtr(out->GetGate()); + auto result = TryRemoveTrivialPhi(outAddrShift); + if (sameAddrShift == outAddrShift) { + sameAddrShift = result; + } } } - return env_->GetCircuit()->SaveGatePtr(same); + return sameAddrShift; } void Stub::Variable::RerouteOuts(const std::vector &outs, Gate *newGate) @@ -123,7 +128,10 @@ void LabelImpl::WriteVariable(Variable *var, AddrShift value) AddrShift LabelImpl::ReadVariable(Variable *var) { if (valueMap_.find(var) != valueMap_.end()) { - return valueMap_.at(var); + auto result = valueMap_.at(var); + if (!env_->GetCircuit()->GetOpCode(result).IsNop()) { + return result; + } } return ReadVariableRecursive(var); } @@ -358,7 +366,7 @@ AddrShift Stub::FixLoadType(AddrShift x) AddrShift Stub::LoadFromObject(MachineType type, AddrShift object, AddrShift offset) { - AddrShift elementsOffset = GetInteger32Constant(panda::ecmascript::JSObject::ELEMENTS_OFFSET); + AddrShift elementsOffset = GetInt32Constant(panda::ecmascript::JSObject::ELEMENTS_OFFSET); if (PtrValueCode() == ValueCode::INT64) { elementsOffset = SExtInt32ToInt64(elementsOffset); } @@ -366,8 +374,8 @@ AddrShift Stub::LoadFromObject(MachineType type, AddrShift object, AddrShift off AddrShift elements = Load(MachineType::UINT64_TYPE, object, elementsOffset); // load index in tagged array AddrShift dataOffset = - Int32Add(GetInteger32Constant(panda::coretypes::Array::GetDataOffset()), - Int32Mul(offset, GetInteger32Constant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()))); + Int32Add(GetInt32Constant(panda::coretypes::Array::GetDataOffset()), + Int32Mul(offset, GetInt32Constant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()))); if (PtrValueCode() == ValueCode::INT64) { dataOffset = SExtInt32ToInt64(dataOffset); } @@ -379,22 +387,22 @@ AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elem auto env = GetEnvironment(); Label subentry(env); env->PushCurrentLabel(&subentry); - DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1)); + DEFVARIABLE(result, MachineType::INT32_TYPE, GetInt32Constant(-1)); Label exit(env); AddrShift capcityoffset = PtrMul(GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()), GetPtrConstant(panda::ecmascript::TaggedHashTable::SIZE_INDEX)); AddrShift dataoffset = GetPtrConstant(panda::coretypes::Array::GetDataOffset()); - AddrShift capacity = TaggedCastToInt32(Load(TAGGED_TYPE, elements, PtrAdd(dataoffset, capcityoffset))); - DEFVARIABLE(count, INT32_TYPE, GetInteger32Constant(1)); + AddrShift capacity = TaggedCastToInt32(Load(MachineType::TAGGED_TYPE, elements, PtrAdd(dataoffset, capcityoffset))); + DEFVARIABLE(count, MachineType::INT32_TYPE, GetInt32Constant(1)); AddrShift pKey = Alloca(static_cast(MachineRep::K_WORD32)); - AddrShift keyStore = Store(INT32_TYPE, pKey, GetPtrConstant(0), TaggedCastToInt32(key)); + AddrShift keyStore = Store(MachineType::INT32_TYPE, thread, pKey, GetPtrConstant(0), TaggedCastToInt32(key)); StubDescriptor *getHash32Descriptor = GET_STUBDESCRIPTOR(GetHash32); - AddrShift len = GetInteger32Constant(sizeof(int) / sizeof(uint8_t)); + AddrShift len = GetInt32Constant(sizeof(int) / sizeof(uint8_t)); AddrShift hash = CallRuntime(getHash32Descriptor, thread, GetWord64Constant(FAST_STUB_ID(GetHash32)), keyStore, {pKey, len}); - DEFVARIABLE(entry, INT32_TYPE, Word32And(hash, Int32Sub(capacity, GetInteger32Constant(1)))); + DEFVARIABLE(entry, MachineType::INT32_TYPE, Word32And(hash, Int32Sub(capacity, GetInt32Constant(1)))); Label loopHead(env); Label loopEnd(env); Label afterLoop(env); @@ -411,7 +419,7 @@ AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elem Label notUndefined(env); Branch(TaggedIsUndefined(element), &isUndefined, ¬Undefined); Bind(&isUndefined); - result = GetInteger32Constant(-1); + result = GetInt32Constant(-1); Jump(&exit); Bind(¬Undefined); Label isMatch(env); @@ -423,8 +431,8 @@ AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elem Bind(¬Match); Jump(&loopEnd); Bind(&loopEnd); - entry = Word32And(Int32Add(*entry, *count), Int32Sub(capacity, GetInteger32Constant(1))); - count = Int32Add(*count, GetInteger32Constant(1)); + entry = GetNextPositionForHash(*entry, *count, capacity); + count = Int32Add(*count, GetInt32Constant(1)); LoopEnd(&loopHead); Bind(&exit); auto ret = *result; @@ -438,7 +446,7 @@ AddrShift Stub::IsMatchInNumberDictionary(AddrShift key, AddrShift other) Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(result, BOOL_TYPE, FalseConstant()); + DEFVARIABLE(result, MachineType::BOOL_TYPE, FalseConstant()); Label isHole(env); Label notHole(env); Label isUndefined(env); @@ -477,16 +485,17 @@ AddrShift Stub::GetKeyFromNumberDictionary(AddrShift elements, AddrShift entry) Label subentry(env); env->PushCurrentLabel(&subentry); Label exit(env); - DEFVARIABLE(result, TAGGED_TYPE, GetUndefinedConstant()); + DEFVARIABLE(result, MachineType::TAGGED_TYPE, GetUndefinedConstant()); Label ltZero(env); Label notLtZero(env); Label gtLength(env); Label notGtLength(env); - AddrShift dictionaryLength = Load(INT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + AddrShift dictionaryLength = + Load(MachineType::INT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); AddrShift arrayIndex = - Int32Add(GetInteger32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), - Int32Mul(entry, GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); - Branch(Int32LessThan(arrayIndex, GetInteger32Constant(0)), <Zero, ¬LtZero); + Int32Add(GetInt32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), + Int32Mul(entry, GetInt32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); + Branch(Int32LessThan(arrayIndex, GetInt32Constant(0)), <Zero, ¬LtZero); Bind(<Zero); Jump(&exit); Bind(¬LtZero); @@ -509,14 +518,14 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements Label funcEntry(env); env->PushCurrentLabel(&funcEntry); Label exit(env); - DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1)); + DEFVARIABLE(result, MachineType::INT32_TYPE, GetInt32Constant(-1)); AddrShift capcityoffset = PtrMul(GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()), GetPtrConstant(panda::ecmascript::TaggedHashTable::SIZE_INDEX)); AddrShift dataoffset = GetPtrConstant(panda::coretypes::Array::GetDataOffset()); - AddrShift capacity = TaggedCastToInt32(Load(TAGGED_TYPE, elements, PtrAdd(dataoffset, capcityoffset))); - DEFVARIABLE(count, INT32_TYPE, GetInteger32Constant(1)); - DEFVARIABLE(hash, INT32_TYPE, GetInteger32Constant(0)); + AddrShift capacity = TaggedCastToInt32(Load(MachineType::TAGGED_TYPE, elements, PtrAdd(dataoffset, capcityoffset))); + DEFVARIABLE(count, MachineType::INT32_TYPE, GetInt32Constant(1)); + DEFVARIABLE(hash, MachineType::INT32_TYPE, GetInt32Constant(0)); // NameDictionary::hash Label isSymbol(env); Label notSymbol(env); @@ -527,7 +536,8 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements Branch(IsSymbol(key), &isSymbol, ¬Symbol); Bind(&isSymbol); { - hash = TaggedCastToInt32(Load(TAGGED_TYPE, key, GetPtrConstant(panda::ecmascript::JSSymbol::HASHFIELD_OFFSET))); + hash = TaggedCastToInt32(Load(MachineType::TAGGED_TYPE, key, + GetPtrConstant(panda::ecmascript::JSSymbol::HASHFIELD_OFFSET))); Jump(&beforeDefineHash); } Bind(¬Symbol); @@ -548,7 +558,7 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements } Bind(&beforeDefineHash); // GetFirstPosition(hash, size) - DEFVARIABLE(entry, INT32_TYPE, Word32And(*hash, Int32Sub(capacity, GetInteger32Constant(1)))); + DEFVARIABLE(entry, MachineType::INT32_TYPE, Word32And(*hash, Int32Sub(capacity, GetInt32Constant(1)))); Jump(&loopHead); LoopBegin(&loopHead); { @@ -569,7 +579,7 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements { Bind(&isUndefined); { - result = GetInteger32Constant(-1); + result = GetInt32Constant(-1); Jump(&exit); } Bind(¬Undefined); @@ -594,8 +604,8 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements } Bind(&loopEnd); { - entry = Word32And(Int32Add(*entry, *count), Int32Sub(capacity, GetInteger32Constant(1))); - count = Int32Add(*count, GetInteger32Constant(1)); + entry = GetNextPositionForHash(*entry, *count, capacity); + count = Int32Add(*count, GetInt32Constant(1)); LoopEnd(&loopHead); } } @@ -611,10 +621,10 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(result, TAGGED_TYPE, GetUndefinedConstant()); + DEFVARIABLE(result, MachineType::TAGGED_TYPE, GetUndefinedConstant()); Label inlinedProp(env); Label notInlinedProp(env); - AddrShift attrOffset = PropAttrGetOffset(attr); + AddrShift attrOffset = GetOffsetFieldInPropAttr(attr); Branch(IsInlinedProperty(attr), &inlinedProp, ¬InlinedProp); { Bind(&inlinedProp); @@ -624,17 +634,18 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a AddrShift propOffset = Int32Sub( ChangeInt64ToInt32(hClassObjectSize), Int32Mul(Int32Sub( - GetInteger32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS), attrOffset), - GetInteger32Constant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()))); - result = Int64BuildTagged(Load(UINT64_TYPE, obj, ZExtInt32ToInt64(propOffset))); + GetInt32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS), attrOffset), + GetInt32Constant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()))); + result = Load(MachineType::UINT64_TYPE, obj, ZExtInt32ToInt64(propOffset)); Jump(&exit); } Bind(¬InlinedProp); { // compute outOfLineProp offset, get it and return - AddrShift array = Load(UINT64_TYPE, obj, GetPtrConstant(panda::ecmascript::JSObject::PROPERTIES_OFFSET)); + AddrShift array = + Load(MachineType::UINT64_TYPE, obj, GetPtrConstant(panda::ecmascript::JSObject::PROPERTIES_OFFSET)); result = GetValueFromTaggedArray(array, Int32Sub(attrOffset, - GetInteger32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS))); + GetInt32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS))); Jump(&exit); } } @@ -644,12 +655,48 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a return ret; } +AddrShift Stub::ShouldCallSetter(AddrShift receiver, AddrShift holder, AddrShift accessor, AddrShift attr) +{ + auto env = GetEnvironment(); + Label subEntry(env); + env->PushCurrentLabel(&subEntry); + Label exit(env); + DEFVARIABLE(result, MachineType::BOOL_TYPE, TrueConstant()); + Label isInternal(env); + Label notInternal(env); + Branch(IsAccessorInternal(accessor), &isInternal, ¬Internal); + Bind(&isInternal); + { + Label receiverEqualsHolder(env); + Label receiverNotEqualsHolder(env); + Branch(Word64Equal(receiver, holder), &receiverEqualsHolder, &receiverNotEqualsHolder); + Bind(&receiverEqualsHolder); + { + result = IsWritable(attr); + Jump(&exit); + } + Bind(&receiverNotEqualsHolder); + { + result = FalseConstant(); + Jump(&exit); + } + } + Bind(¬Internal); + { + result = TrueConstant(); + Jump(&exit); + } + Bind(&exit); + auto ret = *result; + env->PopCurrentLabel(); + return ret; +} + void Stub::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val) { - AddrShift taggedId = GetInteger32Constant(messageId); + AddrShift taggedId = GetInt32Constant(messageId); StubDescriptor *throwTypeError = GET_STUBDESCRIPTOR(ThrowTypeError); - CallRuntime(throwTypeError, thread, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), - {thread, taggedId}); + CallRuntime(throwTypeError, thread, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), {thread, taggedId}); Return(val); } @@ -659,7 +706,7 @@ AddrShift Stub::TaggedToRepresentation(AddrShift value) Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(resultRep, INT64_TYPE, + DEFVARIABLE(resultRep, MachineType::INT64_TYPE, GetWord64Constant(static_cast(panda::ecmascript::Representation::OBJECT))); Label isInt(env); Label notInt(env); @@ -698,7 +745,7 @@ AddrShift Stub::UpdateRepresention(AddrShift oldRep, AddrShift value) Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(resultRep, INT64_TYPE, oldRep); + DEFVARIABLE(resultRep, MachineType::INT64_TYPE, oldRep); Label isMixedRep(env); Label notMiexedRep(env); Branch(Word64Equal(oldRep, GetWord64Constant(static_cast(panda::ecmascript::Representation::MIXED))), @@ -788,9 +835,45 @@ AddrShift Stub::UpdateRepresention(AddrShift oldRep, AddrShift value) return ret; } -void Stub::UpdateAndStoreRepresention(AddrShift hclass, AddrShift value) +AddrShift Stub::Store(MachineType type, AddrShift thread, AddrShift base, AddrShift offset, AddrShift value) +{ + auto depend = env_.GetCurrentLabel()->GetDepend(); + AddrShift result; + if (PtrValueCode() == ValueCode::INT64) { + AddrShift ptr = Int64Add(base, offset); + result = env_.GetCircuitBuilder().NewStoreGate(type, ptr, value, depend); + env_.GetCurrentLabel()->SetDepend(result); + } else if (PtrValueCode() == ValueCode::INT32) { + AddrShift ptr = Int32Add(base, offset); + result = env_.GetCircuitBuilder().NewStoreGate(type, ptr, value, depend); + env_.GetCurrentLabel()->SetDepend(result); + } else { + UNREACHABLE(); + } + // write barrier + if (type == MachineType::TAGGED_POINTER_TYPE || type == MachineType::TAGGED_TYPE) { + StubDescriptor *setValueWithBarrier = GET_STUBDESCRIPTOR(SetValueWithBarrier); + CallRuntime(setValueWithBarrier, thread, GetWord64Constant(FAST_STUB_ID(SetValueWithBarrier)), + {thread, base, offset, value}); + } + + return result; +} +AddrShift Stub::Store(MachineType type, AddrShift base, AddrShift offset, AddrShift value) { - AddrShift newRep = UpdateRepresention(GetElementRepresentation(hclass), value); - SetElementRepresentation(hclass, newRep); + auto depend = env_.GetCurrentLabel()->GetDepend(); + AddrShift result; + if (PtrValueCode() == ValueCode::INT64) { + AddrShift ptr = Int64Add(base, offset); + result = env_.GetCircuitBuilder().NewStoreGate(type, ptr, value, depend); + env_.GetCurrentLabel()->SetDepend(result); + } else if (PtrValueCode() == ValueCode::INT32) { + AddrShift ptr = Int32Add(base, offset); + result = env_.GetCircuitBuilder().NewStoreGate(type, ptr, value, depend); + env_.GetCurrentLabel()->SetDepend(result); + } else { + UNREACHABLE(); + } + return result; } -} // namespace kungfu \ No newline at end of file +} // namespace kungfu diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 8b011f5..f6fe601 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -21,11 +21,13 @@ #include "ecmascript/compiler/circuit.h" #include "ecmascript/compiler/circuit_builder.h" #include "ecmascript/compiler/gate.h" +#include "ecmascript/compiler/machine_type.h" #include "ecmascript/compiler/stub_descriptor.h" #include "ecmascript/js_function.h" #include "ecmascript/js_object.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/layout_info.h" +#include "ecmascript/message_string.h" #include "ecmascript/tagged_dictionary.h" namespace kungfu { @@ -394,7 +396,7 @@ public: return &env_; } // constant - AddrShift GetInteger32Constant(int32_t value) + AddrShift GetInt32Constant(int32_t value) { return env_.GetCircuitBuilder().NewIntegerConstant(value); }; @@ -409,13 +411,13 @@ public: return GetWord64Constant(value); #endif #ifdef PANDA_TARGET_X86 - return GetInteger32Constant(value); + return GetInt32Constant(value); #endif #ifdef PANDA_TARGET_ARM64 return GetWord64Constant(value); #endif #ifdef PANDA_TARGET_ARM32 - return GetInteger32Constant(value); + return GetInt32Constant(value); #endif } @@ -437,12 +439,12 @@ public: AddrShift TrueConstant() { - return TruncInt32ToInt1(GetInteger32Constant(1)); + return TruncInt32ToInt1(GetInt32Constant(1)); } AddrShift FalseConstant() { - return TruncInt32ToInt1(GetInteger32Constant(0)); + return TruncInt32ToInt1(GetInt32Constant(0)); } AddrShift GetBooleanConstant(bool value) @@ -615,23 +617,9 @@ public: AddrShift LoadFromObject(MachineType type, AddrShift object, AddrShift offset); - AddrShift Store(MachineType type, AddrShift base, AddrShift offset, AddrShift value) - { - auto depend = env_.GetCurrentLabel()->GetDepend(); - if (PtrValueCode() == ValueCode::INT64) { - AddrShift ptr = Int64Add(base, offset); - AddrShift result = env_.GetCircuitBuilder().NewStoreGate(type, ptr, value, depend); - env_.GetCurrentLabel()->SetDepend(result); - return result; - } - if (PtrValueCode() == ValueCode::INT32) { - AddrShift ptr = Int32Add(base, offset); - AddrShift result = env_.GetCircuitBuilder().NewStoreGate(type, ptr, value, depend); - env_.GetCurrentLabel()->SetDepend(result); - return result; - } - UNREACHABLE(); - } + AddrShift Store(MachineType type, AddrShift thread, AddrShift base, AddrShift offset, AddrShift value); + + AddrShift Store(MachineType type, AddrShift base, AddrShift offset, AddrShift value); // arithmetic AddrShift Int32Add(AddrShift x, AddrShift y) @@ -722,6 +710,12 @@ public: { return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_AND), x, y); } + + AddrShift Word32Not(AddrShift x) + { + return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_REV), x); + } + AddrShift Word32Xor(AddrShift x, AddrShift y); AddrShift FixLoadType(AddrShift x); @@ -741,31 +735,11 @@ public: return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT64_XOR), x, y); } - AddrShift Word32Not(AddrShift x) - { - return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_REV), x); - } - AddrShift Word64Not(AddrShift x) { return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT64_REV), x); } - AddrShift WordLogicOr(AddrShift x, AddrShift y) - { - return env_.GetCircuitBuilder().NewLogicGate(OpCode(OpCode::INT32_OR), x, y); - } - - AddrShift WordLogicAnd(AddrShift x, AddrShift y) - { - return env_.GetCircuitBuilder().NewLogicGate(OpCode(OpCode::INT32_AND), x, y); - } - - AddrShift WordLogicNot(AddrShift x) - { - return env_.GetCircuitBuilder().NewLogicGate(OpCode(OpCode::INT32_REV), x); - } - AddrShift Word32LSL(AddrShift x, AddrShift y) { return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_LSL), x, y); @@ -792,8 +766,8 @@ public: AddrShift TaggedIsDouble(AddrShift x) { - return Word32Equal(WordLogicOr(SExtInt1ToInt32(TaggedIsInt(x)), SExtInt1ToInt32(TaggedIsObject(x))), - GetInteger32Constant(0)); + return Word32Equal(Word32Or(SExtInt1ToInt32(TaggedIsInt(x)), SExtInt1ToInt32(TaggedIsObject(x))), + GetInt32Constant(0)); } AddrShift TaggedIsObject(AddrShift x) @@ -804,7 +778,7 @@ public: AddrShift TaggedIsNumber(AddrShift x) { - return TruncInt32ToInt1(WordLogicOr(SExtInt1ToInt32(TaggedIsInt(x)), SExtInt1ToInt32(TaggedIsDouble(x)))); + return TruncInt32ToInt1(Word32Or(SExtInt1ToInt32(TaggedIsInt(x)), SExtInt1ToInt32(TaggedIsDouble(x)))); } AddrShift TaggedIsHole(AddrShift x) @@ -839,10 +813,17 @@ public: Word32And(SExtInt1ToInt32(TaggedIsObject(x)), Word32Not(SExtInt1ToInt32(TaggedIsSpecial(x))))); } + AddrShift GetNextPositionForHash(AddrShift last, AddrShift count, AddrShift size) + { + auto nextOffset = Word32LSR(Int32Mul(count, Int32Add(count, GetInt32Constant(1))), + GetInt32Constant(1)); + return Word32And(Int32Add(last, nextOffset), Int32Sub(size, GetInt32Constant(1))); + } + AddrShift DoubleIsNAN(AddrShift x) { AddrShift diff = DoubleEqual(x, x); - return Word32Equal(SExtInt1ToInt32(diff), GetInteger32Constant(0)); + return Word32Equal(SExtInt1ToInt32(diff), GetInt32Constant(0)); } AddrShift DoubleIsINF(AddrShift x) @@ -851,8 +832,8 @@ public: AddrShift negativeInfinity = GetDoubleConstant(-base::POSITIVE_INFINITY); AddrShift diff1 = DoubleEqual(x, infinity); AddrShift diff2 = DoubleEqual(x, negativeInfinity); - return TruncInt32ToInt1(Word32Or(Word32Equal(SExtInt1ToInt32(diff1), GetInteger32Constant(1)), - Word32Equal(SExtInt1ToInt32(diff2), GetInteger32Constant(1)))); + return TruncInt32ToInt1(Word32Or(Word32Equal(SExtInt1ToInt32(diff1), GetInt32Constant(1)), + Word32Equal(SExtInt1ToInt32(diff2), GetInt32Constant(1)))); } AddrShift IntBuildTagged(AddrShift x) @@ -1016,7 +997,7 @@ public: AddrShift GetElements(AddrShift object) { - AddrShift elementsOffset = GetInteger32Constant(panda::ecmascript::JSObject::ELEMENTS_OFFSET); + AddrShift elementsOffset = GetInt32Constant(panda::ecmascript::JSObject::ELEMENTS_OFFSET); if (PtrValueCode() == ValueCode::INT64) { elementsOffset = SExtInt32ToInt64(elementsOffset); } @@ -1026,7 +1007,7 @@ public: AddrShift GetProperties(AddrShift object) { - AddrShift propertiesOffset = GetInteger32Constant(panda::ecmascript::JSObject::PROPERTIES_OFFSET); + AddrShift propertiesOffset = GetInt32Constant(panda::ecmascript::JSObject::PROPERTIES_OFFSET); if (PtrValueCode() == ValueCode::INT64) { propertiesOffset = SExtInt32ToInt64(propertiesOffset); } @@ -1034,39 +1015,58 @@ public: return Load(MachineType::UINT64_TYPE, object, propertiesOffset); } + // setProperties in js_object.h + void setProperties(AddrShift thread, AddrShift object, AddrShift value) + { + AddrShift propertiesOffset = GetInt32Constant(panda::ecmascript::JSObject::PROPERTIES_OFFSET); + if (PtrValueCode() == ValueCode::INT64) { + propertiesOffset = SExtInt32ToInt64(propertiesOffset); + } + Store(MachineType::UINT64_TYPE, thread, object, propertiesOffset, value); + } + AddrShift GetLengthofElements(AddrShift elements) { - return Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + return Load(MachineType::UINT32_TYPE, elements, + GetPtrConstant(panda::ecmascript::TaggedArray::GetLengthOffset())); } // object operation AddrShift LoadHClass(AddrShift object) { - return ChangeInt32ToPointer(Load(UINT32_TYPE, object)); + return ChangeInt32ToPointer(Load(MachineType::UINT32_TYPE, object)); } - AddrShift GetObjectType(AddrShift hclass) + AddrShift GetObjectType(AddrShift hClass) { AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); - + AddrShift bitfield = Load(MachineType::UINT64_TYPE, hClass, bitfieldOffset); return ChangeInt64ToInt32( Word64And(bitfield, GetWord64Constant((1LLU << panda::ecmascript::JSHClass::ObjectTypeBits::SIZE) - 1))); } AddrShift IsDictionaryMode(AddrShift object) { - return Word32NotEqual(Word32And(Load(UINT32_TYPE, LoadHClass(object), GetPtrConstant(0)), - GetInteger32Constant(panda::HClass::IS_DICTIONARY_ARRAY)), - GetInteger32Constant(0)); + AddrShift objectType = GetObjectType(LoadHClass(object)); + return Word32Equal(objectType, + GetInt32Constant(static_cast(panda::ecmascript::JSType::TAGGED_DICTIONARY))); } - AddrShift IsDictionaryElement(AddrShift hclass) + AddrShift IsDictionaryModeByHClass(AddrShift hClass) { AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); + return Word64NotEqual( + Word64And( + Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::IsDictionaryBit::START_BIT)), + GetWord64Constant((1LLU << panda::ecmascript::JSHClass::IsDictionaryBit::SIZE) - 1)), + GetWord64Constant(0)); + } - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift IsDictionaryElement(AddrShift hClass) + { + AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); // decode return Word64NotEqual( Word64And( @@ -1080,7 +1080,7 @@ public: AddrShift hclass = LoadHClass(object); AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hclass, bitfieldOffset); // decode return Word64Equal( Word64And( @@ -1106,10 +1106,10 @@ public: AddrShift IsExtensible(AddrShift object) { - AddrShift hclass = LoadHClass(object); + AddrShift hClass = LoadHClass(object); AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); // decode return Word64NotEqual( Word64And(Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::ExtensibleBit::START_BIT)), @@ -1120,70 +1120,111 @@ public: AddrShift IsSymbol(AddrShift obj) { AddrShift objectType = GetObjectType(LoadHClass(obj)); - return Word32Equal(objectType, GetInteger32Constant(static_cast(panda::ecmascript::JSType::SYMBOL))); + return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::SYMBOL))); } AddrShift IsString(AddrShift obj) { AddrShift objectType = GetObjectType(LoadHClass(obj)); - return Word32Equal(objectType, GetInteger32Constant(static_cast(panda::ecmascript::JSType::STRING))); + return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::STRING))); } AddrShift IsJsProxy(AddrShift obj) { AddrShift objectType = GetObjectType(LoadHClass(obj)); - return Word32Equal(objectType, GetInteger32Constant(static_cast(panda::ecmascript::JSType::JS_PROXY))); + return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::JS_PROXY))); + } + + AddrShift IsJsArray(AddrShift obj) + { + AddrShift objectType = GetObjectType(LoadHClass(obj)); + return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::JS_ARRAY))); } AddrShift IsWritable(AddrShift attr) { return Word32NotEqual( Word32And( - Word32LSR(attr, GetInteger32Constant(panda::ecmascript::PropertyAttributes::WritableField::START_BIT)), - GetInteger32Constant((1LLU << panda::ecmascript::PropertyAttributes::WritableField::SIZE) - 1)), - GetInteger32Constant(0)); + Word32LSR(attr, GetInt32Constant(panda::ecmascript::PropertyAttributes::WritableField::START_BIT)), + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::WritableField::SIZE) - 1)), + GetInt32Constant(0)); } AddrShift IsAccessor(AddrShift attr) { return Word32NotEqual( Word32And(Word32LSR(attr, - GetInteger32Constant(panda::ecmascript::PropertyAttributes::IsAccessorField::START_BIT)), - GetInteger32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsAccessorField::SIZE) - 1)), - GetInteger32Constant(0)); + GetInt32Constant(panda::ecmascript::PropertyAttributes::IsAccessorField::START_BIT)), + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsAccessorField::SIZE) - 1)), + GetInt32Constant(0)); } AddrShift IsInlinedProperty(AddrShift attr) { return Word32NotEqual( Word32And(Word32LSR(attr, - GetInteger32Constant(panda::ecmascript::PropertyAttributes::IsInlinedPropsField::START_BIT)), - GetInteger32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsInlinedPropsField::SIZE) - 1)), - GetInteger32Constant(0)); + GetInt32Constant(panda::ecmascript::PropertyAttributes::IsInlinedPropsField::START_BIT)), + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsInlinedPropsField::SIZE) - 1)), + GetInt32Constant(0)); } - AddrShift PropAttrGetOffset(AddrShift attr) + // GetOffset func in property_attribute.h + AddrShift GetOffsetFieldInPropAttr(AddrShift attr) { return Word32And( - Word32LSR(attr, GetInteger32Constant(panda::ecmascript::PropertyAttributes::OffsetField::START_BIT)), - GetInteger32Constant((1LLU << panda::ecmascript::PropertyAttributes::OffsetField::SIZE) - 1)); + Word32LSR(attr, GetInt32Constant(panda::ecmascript::PropertyAttributes::OffsetField::START_BIT)), + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::OffsetField::SIZE) - 1)); + } + + // SetOffset func in property_attribute.h + AddrShift SetOffsetFieldInPropAttr(AddrShift attr, AddrShift value) + { + AddrShift mask = Word32LSL( + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::OffsetField::SIZE) - 1), + GetInt32Constant(panda::ecmascript::PropertyAttributes::OffsetField::START_BIT)); + AddrShift newVal = Word32Or(Word32And(attr, Word32Not(mask)), + Word32LSL(value, GetInt32Constant(panda::ecmascript::PropertyAttributes::OffsetField::START_BIT))); + return newVal; + } + + // SetIsInlinedProps func in property_attribute.h + AddrShift SetIsInlinePropsFieldInPropAttr(AddrShift attr, AddrShift value) + { + AddrShift mask = Word32LSL( + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsInlinedPropsField::SIZE) - 1), + GetInt32Constant(panda::ecmascript::PropertyAttributes::IsInlinedPropsField::START_BIT)); + AddrShift newVal = Word32Or(Word32And(attr, Word32Not(mask)), + Word32LSL(value, GetInt32Constant(panda::ecmascript::PropertyAttributes::IsInlinedPropsField::START_BIT))); + return newVal; } - AddrShift GetPrototypeFromHClass(AddrShift hclass) + // SetDictionaryOrder func in property_attribute.h + AddrShift SetDictionaryOrderFieldInPropAttr(AddrShift attr, AddrShift value) + { + AddrShift mask = Word32LSL( + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::DictionaryOrderField::SIZE) - 1), + GetInt32Constant(panda::ecmascript::PropertyAttributes::DictionaryOrderField::START_BIT)); + AddrShift newVal = Word32Or(Word32And(attr, Word32Not(mask)), + Word32LSL(value, GetInt32Constant(panda::ecmascript::PropertyAttributes::DictionaryOrderField::START_BIT))); + return newVal; + } + + AddrShift GetPrototypeFromHClass(AddrShift hClass) { AddrShift protoOffset = GetPtrConstant(panda::ecmascript::JSHClass::PROTOTYPE_OFFSET); - return Load(TAGGED_TYPE, hclass, protoOffset); + return Load(MachineType::TAGGED_TYPE, hClass, protoOffset); } - AddrShift GetAttributesFromHclass(AddrShift hclass) + AddrShift GetAttributesFromHclass(AddrShift hClass) { AddrShift attrOffset = GetPtrConstant(panda::ecmascript::JSHClass::ATTRIBUTES_OFFSET); - return Load(TAGGED_TYPE, hclass, attrOffset); + return Load(MachineType::TAGGED_TYPE, hClass, attrOffset); } - AddrShift GetPropertiesNumberFromHClass(AddrShift hclass) + AddrShift GetPropertiesNumberFromHClass(AddrShift hClass) { - AddrShift bitfield = Load(INT64_TYPE, hclass, GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET)); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, + GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET)); AddrShift unusedNonInlinedProps = Word64And(Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::NumberOfUnusedNonInlinedPropsBits::START_BIT)), GetWord64Constant((1LLU << panda::ecmascript::JSHClass::NumberOfUnusedNonInlinedPropsBits::SIZE) - 1)); @@ -1196,9 +1237,29 @@ public: unusedInlinedProps); } - AddrShift GetObjectSizeFromHClass(AddrShift hclass) // NOTE: need to add special case for string and TAGGED_ARRAY + AddrShift GetObjectSizeFromHClass(AddrShift hClass) // NOTE: need to add special case for string and TAGGED_ARRAY + { + return Load(MachineType::UINT64_TYPE, hClass, GetPtrConstant(panda::ecmascript::JSHClass::OBJECT_SIZE_OFFSET)); + } + + void SetHasConstructorToHClass(AddrShift hClass, AddrShift value) { - return Load(UINT64_TYPE, hclass, GetPtrConstant(panda::ecmascript::JSHClass::OBJECT_SIZE_OFFSET)); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, + GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET)); + AddrShift mask = Word64LSL( + GetWord64Constant((1LLU << panda::ecmascript::JSHClass::HasConstructorBits::SIZE) - 1), + GetWord64Constant(panda::ecmascript::JSHClass::HasConstructorBits::START_BIT)); + AddrShift newVal = Word64Or(Word64And(bitfield, Word64Not(mask)), + Word64LSL(value, GetWord64Constant(panda::ecmascript::JSHClass::HasConstructorBits::START_BIT))); + Store(MachineType::UINT64_TYPE, hClass, GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET), newVal); + } + + void StoreElement(AddrShift thread, AddrShift elements, AddrShift index, AddrShift value) + { + AddrShift offset = + PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())); + AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); + Store(MachineType::TAGGED_TYPE, thread, elements, dataOffset, value); } void StoreElement(AddrShift elements, AddrShift index, AddrShift value) @@ -1206,7 +1267,7 @@ public: AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())); AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - Store(TAGGED_TYPE, elements, dataOffset, value); + Store(MachineType::TAGGED_TYPE, elements, dataOffset, value); } void ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val); @@ -1216,40 +1277,60 @@ public: AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())); AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - return Load(TAGGED_TYPE, elements, dataOffset); + return Load(MachineType::TAGGED_TYPE, elements, dataOffset); + } + + AddrShift SetValueToTaggedArray(AddrShift elements, AddrShift index, AddrShift val) + { + // NOTE: need to translate MarkingBarrier + AddrShift offset = + PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())); + AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); + return Store(MachineType::TAGGED_TYPE, elements, dataOffset, val); } AddrShift TaggedToRepresentation(AddrShift value); - AddrShift GetElementRepresentation(AddrShift hclass) + AddrShift GetElementRepresentation(AddrShift hClass) { AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); return Word64And( Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::ElementRepresentationBits::START_BIT)), GetWord64Constant(((1LLU << panda::ecmascript::JSHClass::ElementRepresentationBits::SIZE) - 1))); } - void SetElementRepresentation(AddrShift hclass, AddrShift value) + void SetElementRepresentation(AddrShift hClass, AddrShift value) { AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift oldValue = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift oldValue = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); AddrShift oldWithMask = Word64And(oldValue, GetWord64Constant(~panda::ecmascript::JSHClass::ElementRepresentationBits::Mask())); AddrShift newValue = Word64LSR(value, GetWord64Constant( panda::ecmascript::JSHClass::ElementRepresentationBits::START_BIT)); - Store(INT64_TYPE, hclass, bitfieldOffset, Word64Or(oldWithMask, newValue)); + Store(MachineType::INT64_TYPE, hClass, bitfieldOffset, Word64Or(oldWithMask, newValue)); } - void UpdateValueAndAttributes(AddrShift elements, AddrShift index, AddrShift value, AddrShift attr) + void UpdateValueInDict(AddrShift elements, AddrShift index, AddrShift value) { AddrShift arrayIndex = - Int32Add(GetInteger32Constant(panda::ecmascript::NameDictionary::TABLE_HEADER_SIZE), - Int32Mul(index, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_SIZE))); + Int32Add(GetInt32Constant(panda::ecmascript::NameDictionary::TABLE_HEADER_SIZE), + Int32Mul(index, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_SIZE))); AddrShift valueIndex = - Int32Add(arrayIndex, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); + Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); + StoreElement(elements, valueIndex, value); + } + + void UpdateValueAndAttributes(AddrShift thread, AddrShift elements, AddrShift index, + AddrShift value, AddrShift attr) + { + AddrShift arrayIndex = + Int32Add(GetInt32Constant(panda::ecmascript::NameDictionary::TABLE_HEADER_SIZE), + Int32Mul(index, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_SIZE))); + AddrShift valueIndex = + Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); AddrShift attributesIndex = - Int32Add(arrayIndex, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); + Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); StoreElement(elements, valueIndex, value); StoreElement(elements, attributesIndex, IntBuildTagged(attr)); } @@ -1257,36 +1338,36 @@ public: AddrShift IsSpecialIndexedObj(AddrShift jsType) { return Int32GreaterThan(jsType, - GetInteger32Constant(static_cast(panda::ecmascript::JSType::JS_ARRAY))); + GetInt32Constant(static_cast(panda::ecmascript::JSType::JS_ARRAY))); } AddrShift IsAccessorInternal(AddrShift value) { return Word32Equal(GetObjectType(LoadHClass(value)), - GetInteger32Constant(static_cast(panda::ecmascript::JSType::INTERNAL_ACCESSOR))); + GetInt32Constant(static_cast(panda::ecmascript::JSType::INTERNAL_ACCESSOR))); } - void UpdateAndStoreRepresention(AddrShift hclass, AddrShift value); + void UpdateAndStoreRepresention(AddrShift hClass, AddrShift value); AddrShift UpdateRepresention(AddrShift oldRep, AddrShift value); AddrShift GetAttributesFromDictionary(AddrShift elements, AddrShift entry) { AddrShift arrayIndex = - Int32Add(GetInteger32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), - Int32Mul(entry, GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); + Int32Add(GetInt32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), + Int32Mul(entry, GetInt32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); AddrShift attributesIndex = - Int32Add(arrayIndex, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); - return GetValueFromTaggedArray(elements, attributesIndex); + Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); + return TaggedCastToInt32(GetValueFromTaggedArray(elements, attributesIndex)); } AddrShift GetValueFromDictionary(AddrShift elements, AddrShift entry) { AddrShift arrayIndex = - Int32Add(GetInteger32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), - Int32Mul(entry, GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); + Int32Add(GetInt32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), + Int32Mul(entry, GetInt32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); AddrShift valueIndex = - Int32Add(arrayIndex, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); + Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); return GetValueFromTaggedArray(elements, valueIndex); } @@ -1295,9 +1376,9 @@ public: AddrShift GetPropAttrFromLayoutInfo(AddrShift layout, AddrShift entry) { AddrShift index = Int32Add( - Int32Add(GetInteger32Constant(panda::ecmascript::LayoutInfo::ELEMENTS_START_INDEX), - Word32LSL(entry, GetInteger32Constant(1))), - GetInteger32Constant(1)); + Int32Add(GetInt32Constant(panda::ecmascript::LayoutInfo::ELEMENTS_START_INDEX), + Word32LSL(entry, GetInt32Constant(1))), + GetInt32Constant(1)); return GetValueFromTaggedArray(layout, index); } @@ -1309,6 +1390,14 @@ public: AddrShift JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift propAttr); + AddrShift ShouldCallSetter(AddrShift receiver, AddrShift holder, AddrShift accessor, AddrShift attr); + + AddrShift CallSetterUtil(AddrShift thread, AddrShift holder, AddrShift accessor, AddrShift value); + + AddrShift SetHasConstructorCondition(AddrShift thread, AddrShift receiver, AddrShift key); + + AddrShift AddPropertyByName(AddrShift thread, AddrShift receiver, AddrShift key, AddrShift value); + AddrShift TaggedCastToInt64(AddrShift x) { return Word64And(x, GetWord64Constant(~panda::ecmascript::JSTaggedValue::TAG_MASK)); @@ -1405,7 +1494,7 @@ public: AddrShift hclass = LoadHClass(obj); AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hclass, bitfieldOffset); // decode return Word64NotEqual( Word64And(Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::CallableBit::START_BIT)), diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index 92665e9..fba77f7 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -145,12 +145,11 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri kungfu::Circuit name##Circuit; \ kungfu::name##Stub name##Stub(& name##Circuit); \ module.SetStub(FAST_STUB_ID(name), & name##Stub); - - #define SET_ALL_STUB_TO_MODEULE(module) \ SET_STUB_TO_MODULE(module, FastAdd) \ SET_STUB_TO_MODULE(module, FastSub) \ SET_STUB_TO_MODULE(module, FastMul) \ + SET_STUB_TO_MODULE(module, FastMulGC) \ SET_STUB_TO_MODULE(module, FastDiv) \ SET_STUB_TO_MODULE(module, FastMod) \ SET_STUB_TO_MODULE(module, FastTypeOf) \ diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 6a7b0c1..1e5a43e 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -26,11 +26,10 @@ namespace kungfu { static void Initialize(StubDescriptor *descriptor); \ }; \ void Stub##name##InterfaceDescriptor::Initialize(StubDescriptor *descriptor) - CALL_STUB_INIT_DESCRIPTOR(FastAdd) { // 2 : 2 input parameters - StubDescriptor fastAdd("FastAdd", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastAdd("FastAdd", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastAdd; // 2 : 2 input parameters std::array params = { @@ -43,7 +42,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastAdd) CALL_STUB_INIT_DESCRIPTOR(FastSub) { // 2 : 2 input parameters - StubDescriptor fastSub("FastSub", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastSub("FastSub", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastSub; // 2 : 2 input parameters std::array params = { @@ -56,7 +55,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastSub) CALL_STUB_INIT_DESCRIPTOR(FastMul) { // 2 : 2 input parameters - StubDescriptor fastMul("FastMul", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastMul("FastMul", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastMul; // 2 : 2 input parameters std::array params = { @@ -66,10 +65,24 @@ CALL_STUB_INIT_DESCRIPTOR(FastMul) descriptor->SetParameters(params.data()); } +CALL_STUB_INIT_DESCRIPTOR(FastMulGC) +{ + // 3 : 3 input parameters + static StubDescriptor fastMulGC("FastMulGC", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); + *descriptor = fastMulGC; + // 3 : 3 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); +} + CALL_STUB_INIT_DESCRIPTOR(FastDiv) { // 2 : 2 input parameters - StubDescriptor fastDiv("FastDiv", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastDiv("FastDiv", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastDiv; // 2 : 2 input parameters std::array params = { @@ -82,7 +95,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastDiv) CALL_STUB_INIT_DESCRIPTOR(FastMod) { // 3 : 3 input parameters - StubDescriptor fastMod("FastMod", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastMod("FastMod", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastMod; // 3 : 3 input parameters std::array params = { @@ -96,7 +109,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastMod) CALL_STUB_INIT_DESCRIPTOR(FloatMod) { // 2 : 2 input parameters - StubDescriptor floatMod("FloatMod", 0, 2, ArgumentsOrder::DEFAULT_ORDER, FLOAT64_TYPE); + StubDescriptor floatMod("FloatMod", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::FLOAT64_TYPE); *descriptor = floatMod; // 2 : 2 input parameters std::array params = { @@ -112,7 +125,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastEqual) {} CALL_STUB_INIT_DESCRIPTOR(FastTypeOf) { // 2 input parameters - StubDescriptor fastTypeOf("FastTypeOf", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastTypeOf("FastTypeOf", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastTypeOf; // 2 input parameters std::array params = { @@ -131,7 +144,7 @@ CALL_STUB_INIT_DESCRIPTOR(IsSpecialIndexedObjForGet) {} CALL_STUB_INIT_DESCRIPTOR(GetElement) { // 3 : 3 input parameters - StubDescriptor getElement("GetElement", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor getElement("GetElement", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = getElement; // 3 : 3 input parameters std::array params = { @@ -145,7 +158,7 @@ CALL_STUB_INIT_DESCRIPTOR(GetElement) CALL_STUB_INIT_DESCRIPTOR(SetElement) { // 5 : 5 input parameters - StubDescriptor setElement("SetElement", 0, 5, ArgumentsOrder::DEFAULT_ORDER, BOOL_TYPE); + StubDescriptor setElement("SetElement", 0, 5, ArgumentsOrder::DEFAULT_ORDER, MachineType::BOOL_TYPE); *descriptor = setElement; // 5 : 5 input parameters std::array params = { @@ -155,18 +168,15 @@ CALL_STUB_INIT_DESCRIPTOR(SetElement) descriptor->SetParameters(params.data()); } -CALL_STUB_INIT_DESCRIPTOR(SetPropertyByName) {} - CALL_STUB_INIT_DESCRIPTOR(GetPropertyByName) { // 3 : 3 input parameters - StubDescriptor getPropertyByName("GetPropertyByName", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor getPropertyByName("GetPropertyByName", 0, 3, ArgumentsOrder::DEFAULT_ORDER, + MachineType::UINT64_TYPE); *descriptor = getPropertyByName; // 3 : 3 input parameters std::array params = { - MachineType::UINT64_TYPE, - MachineType::UINT64_TYPE, - MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, }; descriptor->SetParameters(params.data()); } @@ -188,7 +198,7 @@ CALL_STUB_INIT_DESCRIPTOR(FindOwnProperty) {} CALL_STUB_INIT_DESCRIPTOR(FindOwnElement) { // 3 : 3 input parameters - StubDescriptor findOwnElement("FindOwnElement", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor findOwnElement("FindOwnElement", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = findOwnElement; // 3 : 3 input parameters std::array params = { @@ -206,7 +216,7 @@ CALL_STUB_INIT_DESCRIPTOR(FindOwnProperty2) {} CALL_STUB_INIT_DESCRIPTOR(FindOwnElement2) { // 6 : 6 input parameters - StubDescriptor findOwnElement2("FindOwnElement2", 0, 6, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor findOwnElement2("FindOwnElement2", 0, 6, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = findOwnElement2; // 6 : 6 input parameters std::array params = { @@ -219,7 +229,8 @@ CALL_STUB_INIT_DESCRIPTOR(FindOwnElement2) CALL_STUB_INIT_DESCRIPTOR(GetPropertyByIndex) { // 3 : 3 input parameters - StubDescriptor getPropertyByIndex("GetPropertyByIndex", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor getPropertyByIndex("GetPropertyByIndex", 0, 3, ArgumentsOrder::DEFAULT_ORDER, + MachineType::UINT64_TYPE); *descriptor = getPropertyByIndex; // 3 : 3 input parameters std::array params = { @@ -233,7 +244,8 @@ CALL_STUB_INIT_DESCRIPTOR(GetPropertyByIndex) CALL_STUB_INIT_DESCRIPTOR(SetPropertyByIndex) { // 4 : 4 input parameters - StubDescriptor setPropertyByIndex("SetPropertyByIndex", 0, 4, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor setPropertyByIndex("SetPropertyByIndex", 0, 4, ArgumentsOrder::DEFAULT_ORDER, + MachineType::UINT64_TYPE); *descriptor = setPropertyByIndex; // 4 : 4 input parameters std::array params = { @@ -248,7 +260,8 @@ CALL_STUB_INIT_DESCRIPTOR(SetPropertyByIndex) CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) { // 5 : 5 input parameters - StubDescriptor addElementInternal("AddElementInternal", 0, 5, ArgumentsOrder::DEFAULT_ORDER, BOOL_TYPE); + StubDescriptor addElementInternal("AddElementInternal", 0, 5, ArgumentsOrder::DEFAULT_ORDER, + MachineType::BOOL_TYPE); *descriptor = addElementInternal; // 5 : 5 input parameters std::array params = { @@ -259,10 +272,22 @@ CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } +CALL_STUB_INIT_DESCRIPTOR(GetTaggedArrayPtr) +{ + static StubDescriptor getTaggedArrayPtr("GetTaggedArrayPtr", 0, 1, ArgumentsOrder::DEFAULT_ORDER, + MachineType::TAGGED_POINTER_TYPE); + *descriptor = getTaggedArrayPtr; + std::array params = { + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + CALL_STUB_INIT_DESCRIPTOR(CallSetter) { // 5 : 5 input parameters - StubDescriptor callSetter("CallSetter", 0, 5, ArgumentsOrder::DEFAULT_ORDER, NONE_TYPE); + StubDescriptor callSetter("CallSetter", 0, 5, ArgumentsOrder::DEFAULT_ORDER, MachineType::BOOL_TYPE); *descriptor = callSetter; // 5 : 5 input parameters std::array params = { @@ -276,7 +301,7 @@ CALL_STUB_INIT_DESCRIPTOR(CallSetter) CALL_STUB_INIT_DESCRIPTOR(CallGetter) { // 3 : 3 input parameters - StubDescriptor callGetter("CallGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, NONE_TYPE); + StubDescriptor callGetter("CallGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = callGetter; // 3 : 3 input parameters std::array params = { @@ -291,7 +316,7 @@ CALL_STUB_INIT_DESCRIPTOR(CallGetter) CALL_STUB_INIT_DESCRIPTOR(AccessorGetter) { // 3 : 3 input parameters - StubDescriptor accessorGetter("AccessorGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, NONE_TYPE); + StubDescriptor accessorGetter("AccessorGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = accessorGetter; // 3 : 3 input parameters std::array params = { @@ -306,7 +331,7 @@ CALL_STUB_INIT_DESCRIPTOR(AccessorGetter) CALL_STUB_INIT_DESCRIPTOR(ThrowTypeError) { // 2 : 2 input parameters - StubDescriptor throwTypeError("ThrowTypeError", 0, 2, ArgumentsOrder::DEFAULT_ORDER, NONE_TYPE); + StubDescriptor throwTypeError("ThrowTypeError", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::BOOL_TYPE); *descriptor = throwTypeError; // 2 : 2 input parameters std::array params = { @@ -320,7 +345,8 @@ CALL_STUB_INIT_DESCRIPTOR(ThrowTypeError) CALL_STUB_INIT_DESCRIPTOR(JSProxySetProperty) { // 6 : 6 input parameters - StubDescriptor jsproxySetproperty("JSProxySetProperty", 0, 6, ArgumentsOrder::DEFAULT_ORDER, BOOL_TYPE); + StubDescriptor jsproxySetproperty("JSProxySetProperty", 0, 6, + ArgumentsOrder::DEFAULT_ORDER, MachineType::BOOL_TYPE); *descriptor = jsproxySetproperty; // 6 : 6 input parameters std::array params = { @@ -334,7 +360,7 @@ CALL_STUB_INIT_DESCRIPTOR(JSProxySetProperty) CALL_STUB_INIT_DESCRIPTOR(GetHash32) { // 2 : 2 input parameters - StubDescriptor getHash32("GetHash32", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + StubDescriptor getHash32("GetHash32", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT32_TYPE); *descriptor = getHash32; // 2 : 2 input parameters std::array params = { @@ -348,7 +374,8 @@ CALL_STUB_INIT_DESCRIPTOR(GetHash32) CALL_STUB_INIT_DESCRIPTOR(FindElementWithCache) { // 4 : 4 input parameters - StubDescriptor findElementWithCache("FindElementWithCache", 0, 4, ArgumentsOrder::DEFAULT_ORDER, INT32_TYPE); + StubDescriptor findElementWithCache("FindElementWithCache", 0, 4, + ArgumentsOrder::DEFAULT_ORDER, MachineType::INT32_TYPE); *descriptor = findElementWithCache; std::array params = { // 4 : 4 input parameters MachineType::UINT64_TYPE, @@ -363,7 +390,7 @@ CALL_STUB_INIT_DESCRIPTOR(FindElementWithCache) CALL_STUB_INIT_DESCRIPTOR(Execute) { // 5 : 5 input parameters - StubDescriptor execute("Execute", 0, 5, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor execute("Execute", 0, 5, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = execute; std::array params = { // 5 : 5 input parameters MachineType::UINT64_TYPE, @@ -380,7 +407,7 @@ CALL_STUB_INIT_DESCRIPTOR(FunctionCallInternal) { // 5 : 5 input parameters StubDescriptor functionCallInternal("FunctionCallInternal", 0, 5, - ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = functionCallInternal; std::array params = { // 5 : 5 input parameters MachineType::UINT64_TYPE, @@ -395,7 +422,8 @@ CALL_STUB_INIT_DESCRIPTOR(FunctionCallInternal) CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) { - StubDescriptor stringGetHashCode("StringGetHashCode", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + StubDescriptor stringGetHashCode("StringGetHashCode", 0, 1, + ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT32_TYPE); *descriptor = stringGetHashCode; std::array params = { MachineType::UINT64_TYPE, @@ -404,10 +432,27 @@ CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } +CALL_STUB_INIT_DESCRIPTOR(SetValueWithBarrier) +{ + // 4 : 4 input parameters + static StubDescriptor SetValueWithBarrier("SetValueWithBarrier", 0, 4, + ArgumentsOrder::DEFAULT_ORDER, MachineType::NONE_TYPE); + *descriptor = SetValueWithBarrier; + // 4 : 4 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + CALL_STUB_INIT_DESCRIPTOR(FastLoadElement) { // 2 : 2 input parameters - StubDescriptor fastLoadElement("FastLoadElement", 0, 2, ArgumentsOrder::DEFAULT_ORDER, TAGGED_TYPE); + StubDescriptor fastLoadElement("FastLoadElement", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::TAGGED_TYPE); *descriptor = fastLoadElement; std::array params = { // 2 : 2 input parameters MachineType::UINT64_TYPE, @@ -419,7 +464,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastLoadElement) CALL_STUB_INIT_DESCRIPTOR(PhiGateTest) { - StubDescriptor phiGateTest("PhiGateTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + StubDescriptor phiGateTest("PhiGateTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT32_TYPE); *descriptor = phiGateTest; std::array params = { MachineType::UINT32_TYPE, @@ -430,7 +475,7 @@ CALL_STUB_INIT_DESCRIPTOR(PhiGateTest) CALL_STUB_INIT_DESCRIPTOR(LoopTest) { - StubDescriptor loopTest("LoopTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + StubDescriptor loopTest("LoopTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT32_TYPE); *descriptor = loopTest; std::array params = { MachineType::UINT32_TYPE, @@ -441,7 +486,7 @@ CALL_STUB_INIT_DESCRIPTOR(LoopTest) CALL_STUB_INIT_DESCRIPTOR(LoopTest1) { - StubDescriptor loopTest1("LoopTest1", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + StubDescriptor loopTest1("LoopTest1", 0, 1, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT32_TYPE); *descriptor = loopTest1; std::array params = { MachineType::UINT32_TYPE, diff --git a/ecmascript/compiler/stub_descriptor.h b/ecmascript/compiler/stub_descriptor.h index 57823d8..8ab63d2 100644 --- a/ecmascript/compiler/stub_descriptor.h +++ b/ecmascript/compiler/stub_descriptor.h @@ -142,6 +142,7 @@ private: // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define GET_STUBDESCRIPTOR(name) FastStubDescriptors::GetInstance().GetStubDescriptor(FAST_STUB_ID(name)) +#define GET_STUBDESCRIPTOR_BY_ID(id) FastStubDescriptors::GetInstance().GetStubDescriptor(id) class FastStubDescriptors { public: diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 4e170fe..c7dd9b8 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -74,6 +74,7 @@ public: LLVMStubModule stubModule {"fast_stub", "x86_64-unknown-linux-gnu"}; }; + HWTEST_F_L0(StubTest, FastLoadElement) { auto module = stubModule.GetModule(); @@ -114,22 +115,19 @@ public: void GenerateCircuit() override { auto env = GetEnvironment(); - DEFVARIABLE(z, MachineType::INT32_TYPE, GetInteger32Constant(0)); + DEFVARIABLE(z, MachineType::INT32_TYPE, GetInt32Constant(0)); DEFVARIABLE(x, MachineType::INT32_TYPE, Int32Argument(0)); Label ifTrue(env); Label ifFalse(env); Label next(env); - Branch(Word32Equal(*x, GetInteger32Constant(10)), &ifTrue, &ifFalse); // 10 : size of entry + + Branch(Word32Equal(*x, GetInt32Constant(10)), &ifTrue, &ifFalse); // 10 : size of entry Bind(&ifTrue); - { - z = Int32Add(*x, GetInteger32Constant(10)); // 10 : size of entry - Jump(&next); - } + z = Int32Add(*x, GetInt32Constant(10)); // 10 : size of entry + Jump(&next); Bind(&ifFalse); - { - z = Int32Add(*x, GetInteger32Constant(100)); // 100 : size of entry - Jump(&next); - } + z = Int32Add(*x, GetInt32Constant(100)); // 100 : size of entry + Jump(&next); Bind(&next); Return(*z); } @@ -166,27 +164,27 @@ public: void GenerateCircuit() override { auto env = GetEnvironment(); - DEFVARIABLE(z, MachineType::INT32_TYPE, GetInteger32Constant(0)); + DEFVARIABLE(z, MachineType::INT32_TYPE, GetInt32Constant(0)); DEFVARIABLE(y, MachineType::INT32_TYPE, Int32Argument(0)); Label loopHead(env); Label loopEnd(env); Label afterLoop(env); - Branch(Int32LessThan(*y, GetInteger32Constant(10)), &loopHead, &afterLoop); // 10 : size of entry + Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopHead, &afterLoop); // 10 : size of entry LoopBegin(&loopHead); Label ifTrue(env); Label ifFalse(env); Label next(env); - Branch(Word32Equal(Int32Argument(0), GetInteger32Constant(9)), &ifTrue, &ifFalse); // 9 : size of entry + Branch(Word32Equal(Int32Argument(0), GetInt32Constant(9)), &ifTrue, &ifFalse); // 9 : size of entry Bind(&ifTrue); - z = Int32Add(*y, GetInteger32Constant(10)); // 10 : size of entry - y = Int32Add(*z, GetInteger32Constant(1)); + z = Int32Add(*y, GetInt32Constant(10)); // 10 : size of entry + y = Int32Add(*z, GetInt32Constant(1)); Jump(&next); Bind(&ifFalse); - z = Int32Add(*y, GetInteger32Constant(100)); // 100 : size of entry + z = Int32Add(*y, GetInt32Constant(100)); // 100 : size of entry Jump(&next); Bind(&next); - y = Int32Add(*y, GetInteger32Constant(1)); - Branch(Int32LessThan(*y, GetInteger32Constant(10)), &loopEnd, &afterLoop); // 10 : size of entry + y = Int32Add(*y, GetInt32Constant(1)); + Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopEnd, &afterLoop); // 10 : size of entry Bind(&loopEnd); LoopEnd(&loopHead); Bind(&afterLoop); @@ -204,7 +202,7 @@ HWTEST_F_L0(StubTest, LoopTest) netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); PrintCircuitByBasicBlock(cfg, netOfGates); - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); @@ -233,18 +231,18 @@ public: Label loopHead(env); Label loopEnd(env); Label afterLoop(env); - Branch(Int32LessThan(*y, GetInteger32Constant(10)), &loopHead, &afterLoop); // 10 : size of entry + Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopHead, &afterLoop); // 10 : size of entry LoopBegin(&loopHead); - x = Int32Add(*z, GetInteger32Constant(3)); // 3 : size of entry + x = Int32Add(*z, GetInt32Constant(3)); // 3 : size of entry Label ifTrue(env); Label next(env); - Branch(Word32Equal(*x, GetInteger32Constant(9)), &ifTrue, &next); // 9 : size of entry + Branch(Word32Equal(*x, GetInt32Constant(9)), &ifTrue, &next); // 9 : size of entry Bind(&ifTrue); y = Int32Add(*z, *x); Jump(&next); Bind(&next); - y = Int32Add(*y, GetInteger32Constant(1)); - Branch(Int32LessThan(*y, GetInteger32Constant(10)), &loopEnd, &afterLoop); // 10 : size of entry + y = Int32Add(*y, GetInt32Constant(1)); + Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopEnd, &afterLoop); // 10 : size of entry Bind(&loopEnd); LoopEnd(&loopHead); Bind(&afterLoop); @@ -255,8 +253,7 @@ public: HWTEST_F_L0(StubTest, LoopTest1) { - LLVMModuleRef module = LLVMModuleCreateWithName("simple_module"); - LLVMSetTarget(module, "x86_64-unknown-linux-gnu"); + auto module = stubModule.GetModule(); LLVMTypeRef paramTys[] = { LLVMInt32Type(), }; @@ -267,7 +264,7 @@ HWTEST_F_L0(StubTest, LoopTest1) netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); PrintCircuitByBasicBlock(cfg, netOfGates); - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); @@ -801,8 +798,8 @@ HWTEST_F_L0(StubTest, JSEntryTest) entryBb = LLVMAppendBasicBlock(stub2, "entry"); LLVMPositionBuilderAtEnd(builder, entryBb); LLVMValueRef value2 = LLVMGetParam(stub2, 0); - /* struct ThreadTy fpInfo; - fpInfo.fp = calling frame address + /* ThreadTy fpInfo struct; + fpInfo.fp assign calling frame address */ gep2 = LLVMBuildGEP2(builder, threadTy, value2, indexes2.data(), indexes2.size(), "fpAddr"); frameAddr = LLVMCallingFp(module, builder); @@ -831,8 +828,8 @@ HWTEST_F_L0(StubTest, JSEntryTest) entryBb = LLVMAppendBasicBlock(stub3, "entry"); LLVMPositionBuilderAtEnd(builder, entryBb); LLVMValueRef value3 = LLVMGetParam(stub3, 0); - /* struct ThreadTy fpInfo; - fpInfo.fp = calling frame address + /* ThreadTy fpInfo + fpInfo.fp set calling frame address */ gep2 = LLVMBuildGEP2(builder, threadTy, value3, indexes2.data(), indexes2.size(), "fpAddr"); /* current frame @@ -1033,6 +1030,7 @@ HWTEST_F_L0(StubTest, LoadGCIRTest) std::unique_ptr rawModule = parseIRFile(inputFilename, err, context); if (!rawModule) { std::cout << "parseIRFile :" << inputFilename.data() << " failed !" << std::endl; + err.print("parseIRFile ", llvm::errs()); return; } LLVMModuleRef module = LLVMCloneModule(wrap(rawModule.get())); @@ -1087,7 +1085,6 @@ void DoSafepoint() } } -#ifdef NDEBUG HWTEST_F_L0(StubTest, GetPropertyByIndexStub) { auto module = stubModule.GetModule(); @@ -1149,7 +1146,6 @@ HWTEST_F_L0(StubTest, SetPropertyByIndexStub) JSArray::FastGetPropertyByValue(thread, JSHandle::Cast(array), i).GetTaggedValue()); } } -#endif HWTEST_F_L0(StubTest, GetPropertyByNameStub) { @@ -1171,7 +1167,7 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub) reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function))); auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); JSHandle obj = factory->NewEmptyJSObject(); - int x = 213; + int x = 256; int y = 10; JSHandle strA(factory->NewFromCanBeCompressString("a")); JSHandle strBig(factory->NewFromCanBeCompressString("biggest")); diff --git a/ecmascript/compiler/type.h b/ecmascript/compiler/type.h index 399d6cf..3525788 100644 --- a/ecmascript/compiler/type.h +++ b/ecmascript/compiler/type.h @@ -20,8 +20,8 @@ namespace kungfu { using GateType = uint8_t; -enum TypeCode : GateType { - // for HIR +enum class TypeCode : GateType { + // for AOT NOTYPE, JS_ANY, JS_NULL, @@ -42,9 +42,9 @@ enum TypeCode : GateType { JS_UINT32ARRAY, JS_FLOAT32ARRAY, JS_FLOAT64ARRAY, - // for MIR - IS_REFERENCE, - NOT_REFERENCE, + // for Stub + POINTER_TYPE, + TAGGED_POINTER_TYPE, }; class Type { diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 92757ed..c31d39b 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -228,6 +228,7 @@ #endif namespace panda::ecmascript { +using TaggedType = coretypes::TaggedType; class JSThread; enum class FrameType: uintptr_t { OPTIMIZED_FRAME = 0, @@ -238,29 +239,29 @@ enum class FrameType: uintptr_t { class OptimizedFrameStateBase { public: uintptr_t frameType; - JSTaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + TaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc }; class InterpretedFrameStateBase { public: - JSTaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + TaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc uintptr_t frameType; }; class OptimizedEntryFrameState { public: - JSTaggedType *threadFp; // for gc + TaggedType *threadFp; // for gc OptimizedFrameStateBase base; }; class Frame { +private: + static constexpr size_t FRAME_TYPE_OFFSET = -sizeof(uintptr_t); public: static FrameType GetFrameType(const TaggedType *current) { return *(reinterpret_cast(reinterpret_cast(current) + FRAME_TYPE_OFFSET)); } -private: - static constexpr size_t FRAME_TYPE_OFFSET = -sizeof(uintptr_t); }; } // namespace panda::ecmascript #endif // ECMASCRIPT_FRAMES_H diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index f17df97..294232b 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -199,8 +199,9 @@ void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisito uintptr_t *current = fp_; if (current != nullptr) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - std::vector slotAddrs; + std::set slotAddrs; auto returnAddr = reinterpret_cast(*(current + 1)); + LOG_ECMA(INFO) << __FUNCTION__ << " returnAddr :" << returnAddr << std::endl; bool ret = kungfu::LLVMStackMapParser::GetInstance().StackMapByFuncAddrFp( returnAddr, reinterpret_cast(fp_), @@ -214,31 +215,48 @@ void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisito } } -void OptimizedEntryFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const +void OptimizedEntryFrameHandler::Iterate([[maybe_unused]] const RootVisitor &v0, + [[maybe_unused]] const RootRangeVisitor &v1) const { - uintptr_t *current = fp_; - if (current != nullptr) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - std::vector slotAddrs; - auto returnAddr = *(current + 1); + // Entry Frame return address's callsite already visited by OptimizedFrameHandler + // or HandleRuntimeTrampolines +} + +void FrameIterator::HandleRuntimeTrampolines(const RootVisitor &v0, const RootRangeVisitor &v1) const +{ + if (thread_) { + uintptr_t *fp = thread_->GetLastOptCallRuntimePc(); + if (fp == nullptr) { + return; + } + std::set slotAddrs; + auto returnAddr = *(fp + 1); + LOG_ECMA(INFO) << __FUNCTION__ << " returnAddr :" << returnAddr << " fp: " << fp << std::endl; bool ret = kungfu::LLVMStackMapParser::GetInstance().StackMapByFuncAddrFp( reinterpret_cast(returnAddr), - reinterpret_cast(fp_), + reinterpret_cast(fp), slotAddrs); if (ret == false) { + LOG_ECMA(INFO) << " stackmap don't found returnAddr " << std::endl; return; } for (auto &address: slotAddrs) { + LOG_ECMA(INFO) << "stackmap address : " << std::hex << address << std::endl; v0(Root::ROOT_FRAME, ObjectSlot(address)); } } } + void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const { JSTaggedType *current = fp_; + // handle runtimeTrampolines Frame in order get stub returnAddress which used by + // stackMap + HandleRuntimeTrampolines(v0, v1); while (current) { FrameType type = Frame::GetFrameType(current); + LOG_ECMA(INFO) << __FUNCTION__ << "type = " << static_cast(type) << std::endl; if (type == FrameType::INTERPRETER_FRAME) { FrameState *state = reinterpret_cast(current) - 1; InterpretedFrameHandler(current).Iterate(v0, v1); diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index 0da418f..103ec7d 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -91,11 +91,13 @@ private: class FrameIterator { public: - explicit FrameIterator(JSTaggedType *fp) : fp_(fp) {} + explicit FrameIterator(JSTaggedType *fp, const JSThread *thread) : fp_(fp), thread_(thread) {} ~FrameIterator() = default; void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; + void HandleRuntimeTrampolines(const RootVisitor &v0, const RootRangeVisitor &v1) const; private: JSTaggedType *fp_ {nullptr}; + const JSThread *thread_ {nullptr}; }; } // namespace ecmascript } // namespace panda diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index d8fefaf..3e8b9dc 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" #include "ecmascript/global_env_constants-inl.h" #include "ecmascript/internal_call_params.h" #include "ecmascript/interpreter/interpreter-inl.h" @@ -89,12 +90,15 @@ void JSThread::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) if (!stubCode_.IsHole()) { v0(Root::ROOT_VM, ObjectSlot(ToUintPtr(&stubCode_))); } + if (!stubStackMap_.IsHole()) { + v0(Root::ROOT_VM, ObjectSlot(ToUintPtr(&stubStackMap_))); + } // visit global Constant globalConst_.VisitRangeSlot(v1); // visit stack roots - FrameIterator iterator(currentFrame_); + FrameIterator iterator(currentFrame_, this); iterator.Iterate(v0, v1); - // visit internal call params + // visit internal call params; internalCallParams_->Iterate(v1); // visit tagged handle storage roots if (currentHandleStorageIndex_ != -1) { @@ -222,6 +226,13 @@ void JSThread::LoadFastStubModule(const char *moduleFile) for (int i = 0; i < kungfu::FAST_STUB_MAXCOUNT; i++) { fastStubEntires_[i] = stubModule.GetStubEntry(i); } + uint8_t *ptr = reinterpret_cast(stubModule.GetStackMapAddr()); + Address hostCodeSectionAddr = stubModule.GetHostCodeSectionAddr(); + uintptr_t deviceCodeSectionAddr = stubModule.GetDeviceCodeSectionAddr(); + kungfu::LLVMStackMapParser::GetInstance().CalculateStackMap(ptr, hostCodeSectionAddr, deviceCodeSectionAddr); + kungfu::LLVMStackMapParser::GetInstance().Print(); + stubCode_ = stubModule.GetCode(); + stubStackMap_ = stubModule.GetData(); } } // namespace panda::ecmascript diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 3714389..9bed495 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -170,6 +170,14 @@ public: return fastStubEntires_[id]; } + void SetFastStubEntry(uint32_t id, Address entry) + { + ASSERT(id < kungfu::FAST_STUB_MAXCOUNT); + fastStubEntires_[id] = entry; + } + + void InitializeFastRuntimeStubs(); + void LoadFastStubModule(const char *moduleFile); static uint32_t GetRuntimeFunctionsOffset() @@ -228,6 +236,7 @@ private: Address runtimeFunctions_[MAX_RUNTIME_FUNCTIONS]; Address fastStubEntires_[kungfu::FAST_STUB_MAXCOUNT]; JSTaggedValue stubCode_ {JSTaggedValue::Hole()}; + JSTaggedValue stubStackMap_ {JSTaggedValue::Hole()}; EcmaGlobalStorage *globalStorage_ {nullptr}; os::memory::ConditionVariable initializationVar_ GUARDED_BY(initializationLock_); diff --git a/ecmascript/runtime_call_id.h b/ecmascript/runtime_call_id.h index a981643..359dfa1 100644 --- a/ecmascript/runtime_call_id.h +++ b/ecmascript/runtime_call_id.h @@ -153,7 +153,6 @@ namespace panda::ecmascript { V(AddPropertyByIndex) \ V(GetPropertyByIndex) \ V(GetPropertyByValue) \ - V(SetPropertyByName) \ V(SetPropertyByIndex) \ V(SetPropertyByValue) \ V(FastTypeOf) \ diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index b848292..cc77f3f 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -23,6 +23,7 @@ #include "ecmascript/layout_info.h" #include "ecmascript/message_string.h" #include "ecmascript/object_factory.h" +#include "ecmascript/tagged_dictionary.h" namespace panda::ecmascript { bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argReceiver, uint32_t argIndex, @@ -133,6 +134,56 @@ uint32_t RuntimeTrampolines::StringGetHashCode(uint64_t ecmaString) return string->GetHashcode(); } +TaggedArray* RuntimeTrampolines::GetTaggedArrayPtr(uint64_t argThread) +{ + uintptr_t *curFp = nullptr; + auto thread = reinterpret_cast(argThread); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); + // this case static static JSHandle arr don't free in first call + // second call trigger gc. + // don't call EcmaHandleScope handleScope(thread); + auto current = thread->GetCurrentSPFrame(); + FrameType type = Frame::GetFrameType(current); + LOG_ECMA(INFO) << __FUNCTION__ << "type = " << static_cast(type) << std::endl; + + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + static int i = 0; + static JSHandle arr = factory->NewTaggedArray(2); + if (i == 0) { + arr->Set(thread, 0, JSTaggedValue(3)); // 3: first element + arr->Set(thread, 1, JSTaggedValue(4)); // 4: second element + } + + thread->GetEcmaVM()->GetHeap()->GetNewSpace()->EnumerateRegions([](Region *current) { + LOG_ECMA(INFO) << "semispace region: " << current << std::endl; + }); + + thread->GetEcmaVM()->GetHeap()->GetOldSpace()->EnumerateRegions([](Region *current) { + LOG_ECMA(INFO) << "GetOldSpace region: " << current << std::endl; + }); + + thread->GetEcmaVM()->GetHeap()->GetNonMovableSpace()->EnumerateRegions([](Region *current) { + LOG_ECMA(INFO) << "GetNonMovableSpace region: " << current << std::endl; + }); + + thread->GetEcmaVM()->GetHeap()->GetMachineCodeSpace()->EnumerateRegions([](Region *current) { + LOG_ECMA(INFO) << "GetMachineCodeSpace region: " << current << std::endl; + }); + + LOG_ECMA(INFO) << " arr->GetData() " << std::dec << __LINE__ << + std::hex << " " << arr->GetData() << std::endl; + if (i != 0) { + LOG_ECMA(INFO) << " trigger GC : " << std::endl; + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::COMPRESS_FULL_GC); + LOG_ECMA(INFO) << " arr->GetData() " << std::dec << __LINE__ << + std::hex << " " << arr->GetData() << std::endl; + } + i++; + LOG_ECMA(INFO) << " **arr " << *(reinterpret_cast(*arr)) << std::endl; + return *arr; +} uint64_t RuntimeTrampolines::Execute(uint64_t argThread, uint64_t argFunc, uint64_t thisArg, uint32_t argc, uint64_t argArgv) { @@ -149,6 +200,17 @@ uint64_t RuntimeTrampolines::Execute(uint64_t argThread, uint64_t argFunc, return EcmaInterpreter::Execute(thread, params).GetRawData(); } +void RuntimeTrampolines::SetValueWithBarrier(uint64_t argThread, uint64_t argAddr, uint64_t argOffset, + uint64_t argValue) +{ + auto thread = reinterpret_cast(argThread); + auto addr = reinterpret_cast(argAddr); + auto offset = static_cast(argOffset); + auto value = static_cast(argValue); + + SET_VALUE_WITH_BARRIER(thread, addr, offset, value); +} + double RuntimeTrampolines::FloatMod(double left, double right) { return std::fmod(left, right); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 03ab72f..cb4caa5 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -49,7 +49,9 @@ public: static uint32_t GetHash32(uint64_t key, uint64_t len); static int32_t FindElementWithCache(uint64_t argThread, uint64_t hClass, uint64_t key, int32_t num); static uint32_t StringGetHashCode(uint64_t ecmaString); + static TaggedArray* GetTaggedArrayPtr(uint64_t argThread); static uint64_t Execute(uint64_t argThread, uint64_t argFunc, uint64_t thisArg, uint32_t argc, uint64_t argArgv); + static void SetValueWithBarrier(uint64_t argThread, uint64_t argAddr, uint64_t argOffset, uint64_t argValue); static double FloatMod(double left, double right); }; @@ -66,14 +68,15 @@ public: JSTaggedType *newSp = static_cast(static_cast(newFp)); thread_->SetCurrentSPFrame(newSp); LOG_ECMA(INFO) << "Sp: " << newSp << " type:" << - static_cast(Frame::GetFrameType(newSp)); + static_cast(Frame::GetFrameType(newSp)) << std::endl; + } ~CallRuntimeTrampolinesScope() { JSTaggedType *oldSp = static_cast(static_cast(lastFp_)); thread_->SetCurrentSPFrame(oldSp); LOG_ECMA(INFO) << "Sp: " << oldSp << " type:" << - static_cast(Frame::GetFrameType(oldSp)); + static_cast(Frame::GetFrameType(oldSp)) << std::endl; thread_->SetLastOptCallRuntimePc(lastOptCallRuntimePc_); } private: diff --git a/ecmascript/stub_module.cpp b/ecmascript/stub_module.cpp index 62e7ce4..a9f28ea 100644 --- a/ecmascript/stub_module.cpp +++ b/ecmascript/stub_module.cpp @@ -15,6 +15,7 @@ #include "stub_module.h" #include "ecmascript/object_factory.h" +#include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" namespace panda::ecmascript { void StubModule::Save(const std::string &filename) @@ -23,11 +24,27 @@ void StubModule::Save(const std::string &filename) std::ofstream modulefile(filename.c_str(), std::ofstream::binary); /* write stub entries offset */ modulefile.write(reinterpret_cast(fastStubEntries_.data()), - sizeof(uintptr_t) * kungfu::FAST_STUB_MAXCOUNT); - /* write code length & code buff */ + sizeof(uintptr_t) * (kungfu::FAST_STUB_MAXCOUNT)); int codeSize = code_->GetInstructionSizeInBytes().GetInt(); + /* write host code section start addr */ + modulefile.write(reinterpret_cast(&hostCodeSectionAddr_), sizeof(hostCodeSectionAddr_)); + /* write stackmap offset */ + int stackmapOffset = sizeof(uintptr_t) * (kungfu::FAST_STUB_MAXCOUNT) + 2*sizeof(int) + + codeSize; + modulefile.write(reinterpret_cast(&stackmapOffset), + sizeof(int)); + /* write code length & code buff */ modulefile.write(reinterpret_cast(&codeSize), sizeof(codeSize)); modulefile.write(reinterpret_cast(code_->GetDataOffsetAddress()), codeSize); + /* write stackmap buff */ + int stackmapSize = GetStackMapSize(); + LOG_ECMA(INFO) << "stackmap host addr:" << GetStackMapAddr() << " stackmapSize:" << stackmapSize << std::endl; + modulefile.write(reinterpret_cast(&stackmapSize), sizeof(stackmapSize)); + modulefile.write(reinterpret_cast(GetStackMapAddr()), stackmapSize); + + uint8_t *ptr = reinterpret_cast(GetStackMapAddr()); + kungfu::LLVMStackMapParser::GetInstance().CalculateStackMap(ptr); + modulefile.close(); } } @@ -35,13 +52,33 @@ void StubModule::Save(const std::string &filename) void StubModule::Load(JSThread *thread, const std::string &filename) { std::ifstream modulefile(filename.c_str(), std::ofstream::binary); - modulefile.read(reinterpret_cast(fastStubEntries_.data()), sizeof(uintptr_t) * kungfu::FAST_STUB_MAXCOUNT); + modulefile.read(reinterpret_cast(fastStubEntries_.data()), + sizeof(uintptr_t) * (kungfu::FAST_STUB_MAXCOUNT)); + /* read host code section start addr */ + modulefile.read(reinterpret_cast(&hostCodeSectionAddr_), sizeof(hostCodeSectionAddr_)); + int stackmapOffset; + modulefile.read(reinterpret_cast(&stackmapOffset), sizeof(stackmapOffset)); int codeSize = 0; modulefile.read(reinterpret_cast(&codeSize), sizeof(codeSize)); auto factory = thread->GetEcmaVM()->GetFactory(); auto codeHandle = factory->NewMachineCodeObject(codeSize, nullptr); modulefile.read(reinterpret_cast(codeHandle->GetDataOffsetAddress()), codeSize); SetCode(*codeHandle); + LOG_ECMA(INFO) << "codeSection adress for device:" << std::hex << codeHandle->GetDataOffsetAddress() << + " codeSize:" << codeSize << std::endl; + SetDeviceCodeSectionAddr(codeHandle->GetDataOffsetAddress()); + /* read stackmap */ + + int stackmapSize; + modulefile.read(reinterpret_cast(&stackmapSize), sizeof(stackmapSize)); + SetStackMapSize(stackmapSize); + + auto dataHandle = factory->NewMachineCodeObject(stackmapSize, nullptr); + modulefile.read(reinterpret_cast(dataHandle->GetDataOffsetAddress()), stackmapSize); + SetData(*dataHandle); + LOG_ECMA(INFO) << "stackmapSize adress for device:" << std::hex << dataHandle->GetDataOffsetAddress() + << " stackmapSize:"<< stackmapSize << std::endl; + SetStackMapAddr(reinterpret_cast
(dataHandle->GetDataOffsetAddress())); modulefile.close(); } } // namespace panda::ecmascript \ No newline at end of file diff --git a/ecmascript/stub_module.h b/ecmascript/stub_module.h index a48b841..2785524 100644 --- a/ecmascript/stub_module.h +++ b/ecmascript/stub_module.h @@ -35,18 +35,63 @@ public: { code_ = code; } + void SetData(MachineCode *data) + { + data_ = data; + } void SetStubEntry(int index, Address offset) { fastStubEntries_[index] = offset; } + void SetHostCodeSectionAddr(Address addr) + { + hostCodeSectionAddr_ = addr; + } + Address GetHostCodeSectionAddr() + { + return hostCodeSectionAddr_; + } + void SetDeviceCodeSectionAddr(uintptr_t addr) + { + DevicesCodeSectionAddr_ = addr; + } + uintptr_t GetDeviceCodeSectionAddr() + { + return DevicesCodeSectionAddr_; + } JSTaggedValue GetCode() { return JSTaggedValue(code_); } + JSTaggedValue GetData() + { + return JSTaggedValue(data_); + } + void SetStackMapAddr(Address addr) + { + stackMapAddr_ = addr; + } + Address GetStackMapAddr() + { + return stackMapAddr_; + } + void SetStackMapSize(int len) + { + stackMapSize_ = len; + } + int GetStackMapSize() + { + return stackMapSize_; + } private: std::array fastStubEntries_ {-1}; + Address hostCodeSectionAddr_ = 0; + uintptr_t DevicesCodeSectionAddr_ = 0; MachineCode *code_ {nullptr}; + MachineCode *data_ {nullptr}; + Address stackMapAddr_ = 0; + int stackMapSize_ = 0; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_STUB_MODULE_H \ No newline at end of file diff --git a/js_runtime_config.gni b/js_runtime_config.gni index bf6c093..c1af8d2 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -13,7 +13,7 @@ ark_root = "//ark/runtime_core" js_root = "//ark/js_runtime" -compile_llvm_online = false +compile_llvm_online = true run_with_asan = false asan_lib_path = "/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux" -- Gitee From bc69122046adc290d8f904d0e46184d8cf7c9b87 Mon Sep 17 00:00:00 2001 From: getingke Date: Thu, 28 Oct 2021 16:28:40 +0800 Subject: [PATCH 095/115] increase base class FrameHandler for iterator stack frame Signed-off-by: getingke Change-Id: I5643f176c169a2d3a754b6ead66698a0a8e33351 --- ecmascript/base/error_helper.cpp | 6 +- ecmascript/compiler/llvm_codegen.h | 2 + ecmascript/dump.cpp | 4 +- ecmascript/ecma_language_context.cpp | 7 +- ecmascript/interpreter/frame_handler.cpp | 97 +++++++++---------- ecmascript/interpreter/frame_handler.h | 59 ++++++++--- ecmascript/interpreter/interpreter-inl.h | 14 +-- ecmascript/interpreter/interpreter.h | 2 +- .../interpreter/slow_runtime_helper.cpp | 9 +- ecmascript/interpreter/slow_runtime_stub.cpp | 10 +- ecmascript/interpreter/slow_runtime_stub.h | 1 + ecmascript/js_thread.h | 1 - ecmascript/object_factory.cpp | 4 +- ecmascript/tooling/interface/debugger_api.cpp | 22 +++-- 14 files changed, 143 insertions(+), 95 deletions(-) diff --git a/ecmascript/base/error_helper.cpp b/ecmascript/base/error_helper.cpp index eb3ca02..05dcc8a 100644 --- a/ecmascript/base/error_helper.cpp +++ b/ecmascript/base/error_helper.cpp @@ -19,6 +19,7 @@ #include "ecmascript/ecma_macros.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/global_env.h" +#include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/interpreter/interpreter.h" #include "ecmascript/js_object-inl.h" #include "ecmascript/js_tagged_value-inl.h" @@ -192,8 +193,9 @@ CString ErrorHelper::BuildNativeEcmaStackTrace(JSThread *thread) { auto ecmaVm = thread->GetEcmaVM(); CString data; - InterpretedFrameHandler frameHandler(thread); - for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { + auto sp = const_cast(thread->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); + for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { if (frameHandler.IsBreakFrame()) { continue; } diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index d303400..5df45dc 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -15,6 +15,7 @@ #ifndef ECMASCRIPT_COMPILER_LLVM_CODEGEN_H #define ECMASCRIPT_COMPILER_LLVM_CODEGEN_H + #include #include #include @@ -131,6 +132,7 @@ private: /* stack map */ uint8_t *stackMapsSection_ {nullptr}; }; + class LLVMAssembler { public: explicit LLVMAssembler(LLVMModuleRef module, const char* triple); diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index 77df22a..f9b93c2 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -27,6 +27,7 @@ #include "ecmascript/ic/ic_handler.h" #include "ecmascript/ic/proto_change_details.h" #include "ecmascript/ic/property_box.h" +#include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/jobs/micro_job_queue.h" #include "ecmascript/jobs/pending_job.h" #include "ecmascript/js_array.h" @@ -687,7 +688,8 @@ void JSTaggedValue::DumpVal(JSThread *thread, JSTaggedType val) void JSThread::DumpStack() { - InterpretedFrameHandler handler(this); + JSTaggedType *sp = const_cast(this->GetCurrentSPFrame()); + InterpretedFrameHandler handler(sp); handler.DumpStack(std::cout); } diff --git a/ecmascript/ecma_language_context.cpp b/ecmascript/ecma_language_context.cpp index 8a59b2e..d937ec5 100644 --- a/ecmascript/ecma_language_context.cpp +++ b/ecmascript/ecma_language_context.cpp @@ -17,6 +17,7 @@ #include "ecmascript/ecma_class_linker_extension.h" #include "ecmascript/ecma_exceptions.h" +#include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/js_method.h" #include "ecmascript/js_object.h" #include "ecmascript/js_tagged_value.h" @@ -25,6 +26,7 @@ #include "include/tooling/pt_lang_extension.h" namespace panda { +using ecmascript::JSTaggedType; using ecmascript::InterpretedFrameHandler; using ecmascript::EcmaVM; using ecmascript::JSThread; @@ -34,8 +36,9 @@ std::pair EcmaLanguageContext::GetCatchMethodAndOffset(Metho Method *catchMethod = method; uint32_t catchOffset = 0; auto jsThread = static_cast(thread); - InterpretedFrameHandler frameHandler(jsThread); - for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { + auto sp = const_cast(jsThread->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); + for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { if (frameHandler.IsBreakFrame()) { continue; } diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 2cbfd07..c93889f 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -14,74 +14,51 @@ */ #include "ecmascript/interpreter/frame_handler.h" -#include "ecmascript/interpreter/interpreter.h" #include "ecmascript/js_thread.h" #include "libpandafile/bytecode_instruction-inl.h" #include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" namespace panda::ecmascript { -InterpretedFrameHandler::InterpretedFrameHandler(const JSThread *thread) -{ - sp_ = const_cast(thread->GetCurrentSPFrame()); -} - -bool InterpretedFrameHandler::HasFrame() const -{ - // Breakframe also is a frame - return sp_ != nullptr; -} - -bool InterpretedFrameHandler::IsBreakFrame() const -{ - ASSERT(HasFrame()); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - FrameState *state = reinterpret_cast(sp_) - 1; - return state->sp == nullptr; -} - -void InterpretedFrameHandler::PrevFrame() +void FrameHandler::PrevFrame() { ASSERT(HasFrame()); auto type = GetFrameType(); - if (type == FrameType::INTERPRETER_FRAME) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - FrameState *state = reinterpret_cast(sp_) - 1; - sp_ = state->base.prev; - if (sp_ == nullptr) { - return; + switch(type) { + case FrameType::OPTIMIZED_FRAME: { + auto framehandle = + reinterpret_cast(this); + framehandle->PrevFrame(); + break; } - type = GetFrameType(); - } - - while (type != FrameType::INTERPRETER_FRAME) { - switch (type) { - case FrameType::OPTIMIZED_FRAME: { - OptimizedFrameStateBase *state = reinterpret_cast( - reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedFrameStateBase, prev)); - sp_ = reinterpret_cast(state->prev); - break; - } - case FrameType::OPTIMIZED_ENTRY_FRAME: { - OptimizedEntryFrameState *state = reinterpret_cast( - reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); - sp_ = reinterpret_cast(state->threadFp); - break; - } - default: - UNREACHABLE(); + case FrameType::OPTIMIZED_ENTRY_FRAME: { + auto framehandle = + reinterpret_cast(this); + framehandle->PrevFrame(); + break; } - if (sp_ == nullptr) { - return; + case FrameType::INTERPRETER_FRAME: { + auto framehandle = + reinterpret_cast(this); + framehandle->PrevFrame(); + break; } - type = GetFrameType(); + default: + UNREACHABLE(); } } -FrameType InterpretedFrameHandler::GetFrameType() +void InterpretedFrameHandler::PrevFrame() +{ + ASSERT(HasFrame()); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + FrameState *state = reinterpret_cast(sp_) - 1; + sp_ = state->base.prev; +} + +void InterpretedFrameHandler::PrevInterpretedFrame() { - FrameType type = *(reinterpret_cast( - reinterpret_cast(sp_) + FrameConst::FRAME_TYPE_OFFSET)); - return type; + FrameHandler::PrevFrame(); + for(;HasFrame() && GetFrameType() != FrameType::INTERPRETER_FRAME; FrameHandler::PrevFrame()); } InterpretedFrameHandler InterpretedFrameHandler::GetPrevFrame() const @@ -231,6 +208,13 @@ void InterpretedFrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const os << "offset: " << offset << "\n"; } +void OptimizedFrameHandler::PrevFrame() +{ + OptimizedFrameStateBase *state = reinterpret_cast( + reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedFrameStateBase, prev)); + sp_ = reinterpret_cast(state->prev); +} + void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const { uintptr_t *current = fp_; @@ -251,6 +235,13 @@ void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisito } } +void OptimizedEntryFrameHandler::PrevFrame() +{ + OptimizedEntryFrameState *state = reinterpret_cast( + reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); + sp_ = reinterpret_cast(state->threadFp); +} + void OptimizedEntryFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const { uintptr_t *current = fp_; diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index e23e36f..bbdd119 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -16,6 +16,7 @@ #ifndef ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H #define ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H +#include "ecmascript/interpreter/interpreter.h" #include "ecmascript/js_method.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/heap_roots.h" @@ -27,17 +28,49 @@ class JSThread; class JSFunction; class ConstantPool; -class InterpretedFrameHandler { +class FrameHandler { public: - explicit InterpretedFrameHandler(JSTaggedType *sp) : sp_(sp) {} - explicit InterpretedFrameHandler(const JSThread *thread); - ~InterpretedFrameHandler() = default; + explicit FrameHandler(JSTaggedType *sp) : sp_(sp) {} + ~FrameHandler() = default; + DEFAULT_COPY_SEMANTIC(FrameHandler); + DEFAULT_MOVE_SEMANTIC(FrameHandler); + bool HasFrame() const + { + // Breakframe also is a frame + return sp_ != nullptr; + } + bool IsBreakFrame() const + { + ASSERT(HasFrame()); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + FrameState *state = reinterpret_cast(sp_) - 1; + return state->sp == nullptr; + } + void PrevFrame(); + + FrameType GetFrameType() const + { + ASSERT(HasFrame()); + FrameType type = *(reinterpret_cast( + reinterpret_cast(sp_) + FrameConst::FRAME_TYPE_OFFSET)); + return type; + } + JSTaggedType *GetCurrentSp() { return sp_; } +private: + friend class InterpretedFrameHandler; + friend class OptimizedFrameHandler; + friend class OptimizedEntryFrameHandler; + JSTaggedType *sp_{nullptr}; +}; + +class InterpretedFrameHandler : public FrameHandler { +public: + explicit InterpretedFrameHandler(JSTaggedType *sp) : FrameHandler(sp) {} DEFAULT_COPY_SEMANTIC(InterpretedFrameHandler); DEFAULT_MOVE_SEMANTIC(InterpretedFrameHandler); - bool HasFrame() const; - bool IsBreakFrame() const; void PrevFrame(); + void PrevInterpretedFrame(); InterpretedFrameHandler GetPrevFrame() const; JSTaggedValue GetVRegValue(size_t index) const; @@ -65,27 +98,25 @@ public: { DumpPC(std::cout, pc); } - -private: - FrameType GetFrameType(); - JSTaggedType *sp_{nullptr}; }; -class OptimizedFrameHandler { +class OptimizedFrameHandler : public FrameHandler { public: - explicit OptimizedFrameHandler(uintptr_t *fp) : fp_(fp) {} + explicit OptimizedFrameHandler(uintptr_t *fp) : FrameHandler(fp), fp_(fp) {} explicit OptimizedFrameHandler(const JSThread *thread); ~OptimizedFrameHandler() = default; + void PrevFrame(); void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; private: uintptr_t *fp_ {nullptr}; }; -class OptimizedEntryFrameHandler { +class OptimizedEntryFrameHandler : public FrameHandler { public: - explicit OptimizedEntryFrameHandler(uintptr_t *fp) : fp_(fp) {} + explicit OptimizedEntryFrameHandler(uintptr_t *fp) : FrameHandler(fp), fp_(fp) {} explicit OptimizedEntryFrameHandler(const JSThread *thread); ~OptimizedEntryFrameHandler() = default; + void PrevFrame(); void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; private: uintptr_t *fp_ {nullptr}; diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index e02d2dd..42521cf 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -23,6 +23,7 @@ #include "ecmascript/ic/ic_runtime_stub-inl.h" #include "ecmascript/interpreter/fast_runtime_stub-inl.h" #include "ecmascript/interpreter/interpreter.h" +#include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/interpreter/slow_runtime_stub.h" #include "ecmascript/js_generator_object.h" #include "ecmascript/js_tagged_value.h" @@ -203,7 +204,7 @@ namespace panda::ecmascript { #define GET_ACC() (acc) // NOLINT(cppcoreguidelines-macro-usage) #define SET_ACC(val) (acc = val); // NOLINT(cppcoreguidelines-macro-usage) -JSTaggedType *EcmaInterpreter::GetCurrentInterPreterFrameSp(JSThread *thread) +JSTaggedType *EcmaInterpreter::GetCurrentInterpretedFrameSp(JSThread *thread) { JSTaggedType *originalPrevSp = const_cast(thread->GetCurrentSPFrame()); auto current = originalPrevSp; @@ -220,7 +221,7 @@ JSTaggedType *EcmaInterpreter::GetCurrentInterPreterFrameSp(JSThread *thread) JSTaggedValue EcmaInterpreter::ExecuteNative(JSThread *thread, const CallParams& params) { INTERPRETER_TRACE(thread, ExecuteNative); - JSTaggedType *sp = GetCurrentInterPreterFrameSp(thread); + JSTaggedType *sp = GetCurrentInterpretedFrameSp(thread); JSMethod *methodToCall = params.callTarget->GetCallTarget(); ASSERT(methodToCall->GetNumVregs() == 0); @@ -267,7 +268,7 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& param } JSTaggedType *originalPrevSp = const_cast(thread->GetCurrentSPFrame()); - JSTaggedType *sp = GetCurrentInterPreterFrameSp(thread); + JSTaggedType *sp = GetCurrentInterpretedFrameSp(thread); JSTaggedType *newSp = sp - FRAME_STATE_SIZE; // push break state // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -465,8 +466,9 @@ void EcmaInterpreter::ResumeContext(JSThread *thread) void EcmaInterpreter::NotifyBytecodePcChanged(JSThread *thread) { - InterpretedFrameHandler frameHandler(thread); - for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { + JSTaggedType *sp = const_cast(thread->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); + for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { if (frameHandler.IsBreakFrame()) { continue; } @@ -3228,7 +3230,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool InterpretedFrameHandler frameHandler(sp); uint32_t pcOffset = panda_file::INVALID_OFFSET; - for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { + for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { if (frameHandler.IsBreakFrame()) { return; } diff --git a/ecmascript/interpreter/interpreter.h b/ecmascript/interpreter/interpreter.h index 84f0970..fcea0ac 100644 --- a/ecmascript/interpreter/interpreter.h +++ b/ecmascript/interpreter/interpreter.h @@ -66,7 +66,7 @@ public: static inline JSTaggedValue Execute(JSThread *thread, const CallParams& params); static inline JSTaggedValue ExecuteNative(JSThread *thread, const CallParams& params); - static inline JSTaggedType *GetCurrentInterPreterFrameSp(JSThread *thread); + static inline JSTaggedType *GetCurrentInterpretedFrameSp(JSThread *thread); static inline JSTaggedValue GeneratorReEnterInterpreter(JSThread *thread, JSHandle context); static inline void ChangeGenContext(JSThread *thread, JSHandle context); static inline void ResumeContext(JSThread *thread); diff --git a/ecmascript/interpreter/slow_runtime_helper.cpp b/ecmascript/interpreter/slow_runtime_helper.cpp index 1d9a9a8..9f73d66 100644 --- a/ecmascript/interpreter/slow_runtime_helper.cpp +++ b/ecmascript/interpreter/slow_runtime_helper.cpp @@ -82,7 +82,8 @@ JSTaggedValue SlowRuntimeHelper::NewObject(JSThread *thread, JSHandle context) { - InterpretedFrameHandler frameHandler(thread); + auto sp = const_cast(thread->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); uint32_t nregs = frameHandler.GetSize(); JSHandle regsArray = factory->NewTaggedArray(nregs); @@ -122,7 +123,8 @@ JSTaggedValue ConstructGeneric(JSThread *thread, JSHandle ctor, JSHa } // Add the input parameter - InterpretedFrameHandler frameHandler(thread); + auto sp = const_cast(thread->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); CallParams params; params.callTarget = ECMAObject::Cast(*ctor); params.newTarget = newTgt.GetTaggedType(); @@ -221,7 +223,8 @@ JSTaggedValue ConstructProxy(JSThread *thread, JSHandle ctor, JSHandle< args->Set(thread, i, value); } } - InterpretedFrameHandler frameHandler(thread); + auto sp = const_cast(thread->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); for (array_size_t i = 0; i < argsCount; ++i) { JSTaggedValue value = frameHandler.GetVRegValue(baseArgLocation + i); args->Set(thread, i + preArgsSize, value); diff --git a/ecmascript/interpreter/slow_runtime_stub.cpp b/ecmascript/interpreter/slow_runtime_stub.cpp index 0731b5f..0212e64 100644 --- a/ecmascript/interpreter/slow_runtime_stub.cpp +++ b/ecmascript/interpreter/slow_runtime_stub.cpp @@ -23,6 +23,7 @@ #include "ecmascript/ic/profile_type_info.h" #include "ecmascript/internal_call_params.h" #include "ecmascript/interpreter/fast_runtime_stub-inl.h" +#include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/interpreter/slow_runtime_helper.h" #include "ecmascript/js_arguments.h" #include "ecmascript/js_array.h" @@ -439,7 +440,8 @@ JSTaggedValue SlowRuntimeStub::CreateObjectWithExcludedKeys(JSThread *thread, ui JSHandle obj(thread, objVal); array_size_t numExcludedKeys = 0; JSHandle excludedKeys = factory->NewTaggedArray(numKeys + 1); - InterpretedFrameHandler frameHandler(thread); + auto sp = const_cast(thread->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); JSTaggedValue excludedKey = frameHandler.GetVRegValue(firstArgRegIdx); if (!excludedKey.IsUndefined()) { numExcludedKeys = numKeys + 1; @@ -1732,7 +1734,8 @@ JSTaggedValue SlowRuntimeStub::SuperCall(JSThread *thread, JSTaggedValue func, J INTERPRETER_TRACE(thread, SuperCall); [[maybe_unused]] EcmaHandleScope handleScope(thread); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - InterpretedFrameHandler frameHandler(thread); + auto sp = const_cast(thread->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); JSHandle funcHandle(thread, func); JSHandle newTargetHandle(thread, newTarget); @@ -1757,7 +1760,8 @@ JSTaggedValue SlowRuntimeStub::SuperCallSpread(JSThread *thread, JSTaggedValue f { INTERPRETER_TRACE(thread, SuperCallSpread); [[maybe_unused]] EcmaHandleScope handleScope(thread); - InterpretedFrameHandler frameHandler(thread); + auto sp = const_cast(thread->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); JSHandle funcHandle(thread, func); JSHandle newTargetHandle(thread, newTarget); diff --git a/ecmascript/interpreter/slow_runtime_stub.h b/ecmascript/interpreter/slow_runtime_stub.h index afa120f..48bb088 100644 --- a/ecmascript/interpreter/slow_runtime_stub.h +++ b/ecmascript/interpreter/slow_runtime_stub.h @@ -16,6 +16,7 @@ #ifndef ECMASCRIPT_INTERPRETER_SLOW_RUNTIME_STUB_H #define ECMASCRIPT_INTERPRETER_SLOW_RUNTIME_STUB_H +#include "ecmascript/class_linker/program_object.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/js_thread.h" diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 317954f..85590ca 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -19,7 +19,6 @@ #include "ecmascript/compiler/fast_stub_define.h" #include "ecmascript/ecma_global_storage.h" #include "ecmascript/global_env_constants.h" -#include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/mem/heap_roots.h" #include "include/thread.h" #include "ecmascript/frames.h" diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index 669d0e9..bce11ed 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -31,6 +31,7 @@ #include "ecmascript/ic/profile_type_info.h" #include "ecmascript/ic/property_box.h" #include "ecmascript/ic/proto_change_details.h" +#include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/internal_call_params.h" #include "ecmascript/jobs/micro_job_queue.h" #include "ecmascript/jobs/pending_job.h" @@ -2090,7 +2091,8 @@ JSHandle ObjectFactory::NewEmptyJSObject() EcmaString *ObjectFactory::ResolveString(uint32_t stringId) { - JSMethod *caller = InterpretedFrameHandler(thread_).GetMethod(); + auto sp = const_cast(thread_->GetCurrentSPFrame()); + JSMethod *caller = InterpretedFrameHandler(sp).GetMethod(); auto *pf = caller->GetPandaFile(); auto id = panda_file::File::EntityId(stringId); auto foundStr = pf->GetStringData(id); diff --git a/ecmascript/tooling/interface/debugger_api.cpp b/ecmascript/tooling/interface/debugger_api.cpp index 84ec85a..d4313df 100644 --- a/ecmascript/tooling/interface/debugger_api.cpp +++ b/ecmascript/tooling/interface/debugger_api.cpp @@ -53,8 +53,9 @@ CString DebuggerApi::ConvertToString(const std::string &str) uint32_t DebuggerApi::GetStackDepth(const EcmaVM *ecmaVm) { uint32_t count = 0; - InterpretedFrameHandler frameHandler(ecmaVm->GetJSThread()); - for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { + JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); + for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { if (frameHandler.IsBreakFrame()) { continue; } @@ -65,8 +66,9 @@ uint32_t DebuggerApi::GetStackDepth(const EcmaVM *ecmaVm) bool DebuggerApi::StackWalker(const EcmaVM *ecmaVm, std::function func) { - InterpretedFrameHandler frameHandler(ecmaVm->GetJSThread()); - for (; frameHandler.HasFrame(); frameHandler.PrevFrame()) { + JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); + InterpretedFrameHandler frameHandler(sp); + for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { if (frameHandler.IsBreakFrame()) { continue; } @@ -84,24 +86,28 @@ bool DebuggerApi::StackWalker(const EcmaVM *ecmaVm, std::functionGetJSThread()).GetBytecodeOffset(); + JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); + return InterpretedFrameHandler(sp).GetBytecodeOffset(); } JSMethod *DebuggerApi::GetMethod(const EcmaVM *ecmaVm) { - return InterpretedFrameHandler(ecmaVm->GetJSThread()).GetMethod(); + JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); + return InterpretedFrameHandler(sp).GetMethod(); } Local DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm, size_t index) { - auto value = InterpretedFrameHandler(ecmaVm->GetJSThread()).GetVRegValue(index); + JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); + auto value = InterpretedFrameHandler(sp).GetVRegValue(index); JSHandle handledValue(ecmaVm->GetJSThread(), value); return JSNApiHelper::ToLocal(handledValue); } void DebuggerApi::SetVRegValue(const EcmaVM *ecmaVm, size_t index, Local value) { - return InterpretedFrameHandler(ecmaVm->GetJSThread()).SetVRegValue(index, JSNApiHelper::ToJSTaggedValue(*value)); + JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); + return InterpretedFrameHandler(sp).SetVRegValue(index, JSNApiHelper::ToJSTaggedValue(*value)); } uint32_t DebuggerApi::GetBytecodeOffset(const InterpretedFrameHandler *frameHandler) -- Gitee From 92001a9e41c8fdc52a28f18b246326bd8b538b26 Mon Sep 17 00:00:00 2001 From: getingke Date: Thu, 28 Oct 2021 16:50:26 +0800 Subject: [PATCH 096/115] fixed for code static check Signed-off-by: getingke Change-Id: Ie7117dc84b7c837abaa547c87015634aafa4934f --- ecmascript/interpreter/frame_handler.cpp | 4 ++-- ecmascript/interpreter/frame_handler.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index c93889f..239b284 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -23,7 +23,7 @@ void FrameHandler::PrevFrame() { ASSERT(HasFrame()); auto type = GetFrameType(); - switch(type) { + switch (type) { case FrameType::OPTIMIZED_FRAME: { auto framehandle = reinterpret_cast(this); @@ -58,7 +58,7 @@ void InterpretedFrameHandler::PrevFrame() void InterpretedFrameHandler::PrevInterpretedFrame() { FrameHandler::PrevFrame(); - for(;HasFrame() && GetFrameType() != FrameType::INTERPRETER_FRAME; FrameHandler::PrevFrame()); + for (;HasFrame() && GetFrameType() != FrameType::INTERPRETER_FRAME; FrameHandler::PrevFrame()); } InterpretedFrameHandler InterpretedFrameHandler::GetPrevFrame() const diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index bbdd119..11ed828 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -55,7 +55,6 @@ public: reinterpret_cast(sp_) + FrameConst::FRAME_TYPE_OFFSET)); return type; } - JSTaggedType *GetCurrentSp() { return sp_; } private: friend class InterpretedFrameHandler; friend class OptimizedFrameHandler; -- Gitee From aef57e484be50cae78d6e10120eefe52707f1b8b Mon Sep 17 00:00:00 2001 From: getingke Date: Thu, 28 Oct 2021 20:59:19 +0800 Subject: [PATCH 097/115] fixed for review by wuzhefeng Signed-off-by: getingke Change-Id: I7ceab6e9cc8b42ba73255813419baa3619381676 --- ecmascript/dump.cpp | 3 +-- ecmascript/ecma_language_context.cpp | 3 +-- ecmascript/frames.h | 14 +++++++++++--- ecmascript/interpreter/frame_handler.cpp | 9 +++++++-- ecmascript/interpreter/frame_handler.h | 3 ++- ecmascript/interpreter/interpreter-inl.h | 5 ++--- ecmascript/interpreter/slow_runtime_helper.cpp | 9 +++------ ecmascript/interpreter/slow_runtime_stub.cpp | 9 +++------ ecmascript/js_thread.h | 2 +- ecmascript/object_factory.cpp | 3 +-- ecmascript/tooling/interface/debugger_api.cpp | 18 ++++++------------ 11 files changed, 38 insertions(+), 40 deletions(-) diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index f9b93c2..7498809 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -688,8 +688,7 @@ void JSTaggedValue::DumpVal(JSThread *thread, JSTaggedType val) void JSThread::DumpStack() { - JSTaggedType *sp = const_cast(this->GetCurrentSPFrame()); - InterpretedFrameHandler handler(sp); + InterpretedFrameHandler handler(this); handler.DumpStack(std::cout); } diff --git a/ecmascript/ecma_language_context.cpp b/ecmascript/ecma_language_context.cpp index d937ec5..df8d367 100644 --- a/ecmascript/ecma_language_context.cpp +++ b/ecmascript/ecma_language_context.cpp @@ -36,8 +36,7 @@ std::pair EcmaLanguageContext::GetCatchMethodAndOffset(Metho Method *catchMethod = method; uint32_t catchOffset = 0; auto jsThread = static_cast(thread); - auto sp = const_cast(jsThread->GetCurrentSPFrame()); - InterpretedFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(jsThread); for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { if (frameHandler.IsBreakFrame()) { continue; diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 454368e..16a9fcc 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -243,19 +243,27 @@ auto as_integer(Enumeration const value) class OptimizedFrameStateBase { public: FrameType frameType; - uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + uintptr_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + static size_t GetFrameStateOffsetFromSp() + { + return MEMBER_OFFSET(OptimizedFrameStateBase, prev); + } }; class InterpretedFrameStateBase { public: - uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + uintptr_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc FrameType frameType; }; class OptimizedEntryFrameState { public: - uint64_t *threadFp; // for gc + uintptr_t *threadFp; // for gc OptimizedFrameStateBase base; + static size_t GetFrameStateOffsetFromSp() + { + return MEMBER_OFFSET(OptimizedEntryFrameState, base.prev); + } }; class FrameConst { diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 239b284..7ae466a 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -47,6 +47,11 @@ void FrameHandler::PrevFrame() } } +InterpretedFrameHandler::InterpretedFrameHandler(JSThread *thread) + : FrameHandler(const_cast(thread->GetCurrentSPFrame())) +{ +} + void InterpretedFrameHandler::PrevFrame() { ASSERT(HasFrame()); @@ -211,7 +216,7 @@ void InterpretedFrameHandler::DumpPC(std::ostream &os, const uint8_t *pc) const void OptimizedFrameHandler::PrevFrame() { OptimizedFrameStateBase *state = reinterpret_cast( - reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedFrameStateBase, prev)); + reinterpret_cast(sp_) - OptimizedFrameStateBase::GetFrameStateOffsetFromSp()); sp_ = reinterpret_cast(state->prev); } @@ -238,7 +243,7 @@ void OptimizedFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisito void OptimizedEntryFrameHandler::PrevFrame() { OptimizedEntryFrameState *state = reinterpret_cast( - reinterpret_cast(sp_) - MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); + reinterpret_cast(sp_) - OptimizedEntryFrameState::GetFrameStateOffsetFromSp()); sp_ = reinterpret_cast(state->threadFp); } diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index 11ed828..afba3ec 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -52,7 +52,7 @@ public: { ASSERT(HasFrame()); FrameType type = *(reinterpret_cast( - reinterpret_cast(sp_) + FrameConst::FRAME_TYPE_OFFSET)); + reinterpret_cast(sp_) + FrameConst::FRAME_TYPE_OFFSET)); return type; } private: @@ -64,6 +64,7 @@ private: class InterpretedFrameHandler : public FrameHandler { public: + explicit InterpretedFrameHandler(JSThread *thread); explicit InterpretedFrameHandler(JSTaggedType *sp) : FrameHandler(sp) {} DEFAULT_COPY_SEMANTIC(InterpretedFrameHandler); DEFAULT_MOVE_SEMANTIC(InterpretedFrameHandler); diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 42521cf..c49b790 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -212,7 +212,7 @@ JSTaggedType *EcmaInterpreter::GetCurrentInterpretedFrameSp(JSThread *thread) reinterpret_cast(current) + FrameConst::FRAME_TYPE_OFFSET)); JSTaggedType *sp = originalPrevSp; if (type != FrameType::INTERPRETER_FRAME) { - JSTaggedType *lastSp = const_cast(thread->GetLastIFrameSp()); + JSTaggedType *lastSp = const_cast(thread->GetLastInterpretedFrameSp()); sp = lastSp; } return sp; @@ -466,8 +466,7 @@ void EcmaInterpreter::ResumeContext(JSThread *thread) void EcmaInterpreter::NotifyBytecodePcChanged(JSThread *thread) { - JSTaggedType *sp = const_cast(thread->GetCurrentSPFrame()); - InterpretedFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(thread); for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { if (frameHandler.IsBreakFrame()) { continue; diff --git a/ecmascript/interpreter/slow_runtime_helper.cpp b/ecmascript/interpreter/slow_runtime_helper.cpp index 9f73d66..1d9a9a8 100644 --- a/ecmascript/interpreter/slow_runtime_helper.cpp +++ b/ecmascript/interpreter/slow_runtime_helper.cpp @@ -82,8 +82,7 @@ JSTaggedValue SlowRuntimeHelper::NewObject(JSThread *thread, JSHandle context) { - auto sp = const_cast(thread->GetCurrentSPFrame()); - InterpretedFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(thread); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); uint32_t nregs = frameHandler.GetSize(); JSHandle regsArray = factory->NewTaggedArray(nregs); @@ -123,8 +122,7 @@ JSTaggedValue ConstructGeneric(JSThread *thread, JSHandle ctor, JSHa } // Add the input parameter - auto sp = const_cast(thread->GetCurrentSPFrame()); - InterpretedFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(thread); CallParams params; params.callTarget = ECMAObject::Cast(*ctor); params.newTarget = newTgt.GetTaggedType(); @@ -223,8 +221,7 @@ JSTaggedValue ConstructProxy(JSThread *thread, JSHandle ctor, JSHandle< args->Set(thread, i, value); } } - auto sp = const_cast(thread->GetCurrentSPFrame()); - InterpretedFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(thread); for (array_size_t i = 0; i < argsCount; ++i) { JSTaggedValue value = frameHandler.GetVRegValue(baseArgLocation + i); args->Set(thread, i + preArgsSize, value); diff --git a/ecmascript/interpreter/slow_runtime_stub.cpp b/ecmascript/interpreter/slow_runtime_stub.cpp index 0212e64..c12cb3b 100644 --- a/ecmascript/interpreter/slow_runtime_stub.cpp +++ b/ecmascript/interpreter/slow_runtime_stub.cpp @@ -440,8 +440,7 @@ JSTaggedValue SlowRuntimeStub::CreateObjectWithExcludedKeys(JSThread *thread, ui JSHandle obj(thread, objVal); array_size_t numExcludedKeys = 0; JSHandle excludedKeys = factory->NewTaggedArray(numKeys + 1); - auto sp = const_cast(thread->GetCurrentSPFrame()); - InterpretedFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(thread); JSTaggedValue excludedKey = frameHandler.GetVRegValue(firstArgRegIdx); if (!excludedKey.IsUndefined()) { numExcludedKeys = numKeys + 1; @@ -1734,8 +1733,7 @@ JSTaggedValue SlowRuntimeStub::SuperCall(JSThread *thread, JSTaggedValue func, J INTERPRETER_TRACE(thread, SuperCall); [[maybe_unused]] EcmaHandleScope handleScope(thread); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - auto sp = const_cast(thread->GetCurrentSPFrame()); - InterpretedFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(thread); JSHandle funcHandle(thread, func); JSHandle newTargetHandle(thread, newTarget); @@ -1760,8 +1758,7 @@ JSTaggedValue SlowRuntimeStub::SuperCallSpread(JSThread *thread, JSTaggedValue f { INTERPRETER_TRACE(thread, SuperCallSpread); [[maybe_unused]] EcmaHandleScope handleScope(thread); - auto sp = const_cast(thread->GetCurrentSPFrame()); - InterpretedFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(thread); JSHandle funcHandle(thread, func); JSHandle newTargetHandle(thread, newTarget); diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 85590ca..826bbd3 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -75,7 +75,7 @@ public: currentFrame_ = sp; } - const JSTaggedType *GetLastIFrameSp() const + const JSTaggedType *GetLastInterpretedFrameSp() const { return lastIFrame_; } diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index bce11ed..8a2aeac 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -2091,8 +2091,7 @@ JSHandle ObjectFactory::NewEmptyJSObject() EcmaString *ObjectFactory::ResolveString(uint32_t stringId) { - auto sp = const_cast(thread_->GetCurrentSPFrame()); - JSMethod *caller = InterpretedFrameHandler(sp).GetMethod(); + JSMethod *caller = InterpretedFrameHandler(thread_).GetMethod(); auto *pf = caller->GetPandaFile(); auto id = panda_file::File::EntityId(stringId); auto foundStr = pf->GetStringData(id); diff --git a/ecmascript/tooling/interface/debugger_api.cpp b/ecmascript/tooling/interface/debugger_api.cpp index d4313df..683bd3f 100644 --- a/ecmascript/tooling/interface/debugger_api.cpp +++ b/ecmascript/tooling/interface/debugger_api.cpp @@ -53,8 +53,7 @@ CString DebuggerApi::ConvertToString(const std::string &str) uint32_t DebuggerApi::GetStackDepth(const EcmaVM *ecmaVm) { uint32_t count = 0; - JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); - InterpretedFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(ecmaVm->GetJSThread()); for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { if (frameHandler.IsBreakFrame()) { continue; @@ -66,8 +65,7 @@ uint32_t DebuggerApi::GetStackDepth(const EcmaVM *ecmaVm) bool DebuggerApi::StackWalker(const EcmaVM *ecmaVm, std::function func) { - JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); - InterpretedFrameHandler frameHandler(sp); + InterpretedFrameHandler frameHandler(ecmaVm->GetJSThread()); for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { if (frameHandler.IsBreakFrame()) { continue; @@ -86,28 +84,24 @@ bool DebuggerApi::StackWalker(const EcmaVM *ecmaVm, std::function(ecmaVm->GetJSThread()->GetCurrentSPFrame()); - return InterpretedFrameHandler(sp).GetBytecodeOffset(); + return InterpretedFrameHandler(ecmaVm->GetJSThread()).GetBytecodeOffset(); } JSMethod *DebuggerApi::GetMethod(const EcmaVM *ecmaVm) { - JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); - return InterpretedFrameHandler(sp).GetMethod(); + return InterpretedFrameHandler(ecmaVm->GetJSThread()).GetMethod(); } Local DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm, size_t index) { - JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); - auto value = InterpretedFrameHandler(sp).GetVRegValue(index); + auto value = InterpretedFrameHandler(ecmaVm->GetJSThread()).GetVRegValue(index); JSHandle handledValue(ecmaVm->GetJSThread(), value); return JSNApiHelper::ToLocal(handledValue); } void DebuggerApi::SetVRegValue(const EcmaVM *ecmaVm, size_t index, Local value) { - JSTaggedType *sp = const_cast(ecmaVm->GetJSThread()->GetCurrentSPFrame()); - return InterpretedFrameHandler(sp).SetVRegValue(index, JSNApiHelper::ToJSTaggedValue(*value)); + return InterpretedFrameHandler(ecmaVm->GetJSThread()).SetVRegValue(index, JSNApiHelper::ToJSTaggedValue(*value)); } uint32_t DebuggerApi::GetBytecodeOffset(const InterpretedFrameHandler *frameHandler) -- Gitee From e94bc6d49855e9d0944aec9d71b792f781074c42 Mon Sep 17 00:00:00 2001 From: getingke Date: Thu, 28 Oct 2021 21:32:52 +0800 Subject: [PATCH 098/115] fixed for code static check Signed-off-by: getingke Change-Id: I84f242650a1054eba4a5f6d2ea1f0a1515917aff --- ecmascript/compiler/stub.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 889e48c..2da08e6 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -957,9 +957,9 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Branch(isUtf16String, &isUtf16, ¬Utf16); Bind(&isUtf16); { - c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, - PtrMul(ChangeInt32ToPointer(*i), - GetPtrConstant(2)))); // 2 : 2 means utf16 char width is two bytes + // 2 : 2 means utf16 char width is two bytes + auto charOffset = PtrMul(ChangeInt32ToPointer(*i), GetPtrConstant(2)); + c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, charOffset)); Jump(&getChar2); } Bind(¬Utf16); -- Gitee From 5c0158629011d99c483c122480dc869cca301282 Mon Sep 17 00:00:00 2001 From: getingke Date: Fri, 29 Oct 2021 11:39:36 +0800 Subject: [PATCH 099/115] fixed for compiler error Signed-off-by: getingke Change-Id: I945a818ba775b64f0aa887475cadb280b41ad207 --- ecmascript/frames.h | 6 +++--- ecmascript/interpreter/frame_handler.h | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 16a9fcc..02acf67 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -243,7 +243,7 @@ auto as_integer(Enumeration const value) class OptimizedFrameStateBase { public: FrameType frameType; - uintptr_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc static size_t GetFrameStateOffsetFromSp() { return MEMBER_OFFSET(OptimizedFrameStateBase, prev); @@ -252,13 +252,13 @@ public: class InterpretedFrameStateBase { public: - uintptr_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + uint64_t *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc FrameType frameType; }; class OptimizedEntryFrameState { public: - uintptr_t *threadFp; // for gc + uint64_t *threadFp; // for gc OptimizedFrameStateBase base; static size_t GetFrameStateOffsetFromSp() { diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index afba3ec..ed00916 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -102,7 +102,8 @@ public: class OptimizedFrameHandler : public FrameHandler { public: - explicit OptimizedFrameHandler(uintptr_t *fp) : FrameHandler(fp), fp_(fp) {} + explicit OptimizedFrameHandler(uintptr_t *fp) + : FrameHandler(reinterpret_cast(fp)), fp_(fp) {} explicit OptimizedFrameHandler(const JSThread *thread); ~OptimizedFrameHandler() = default; void PrevFrame(); @@ -113,7 +114,8 @@ private: class OptimizedEntryFrameHandler : public FrameHandler { public: - explicit OptimizedEntryFrameHandler(uintptr_t *fp) : FrameHandler(fp), fp_(fp) {} + explicit OptimizedEntryFrameHandler(uintptr_t *fp) + : FrameHandler(reinterpret_cast(fp)), fp_(fp) {} explicit OptimizedEntryFrameHandler(const JSThread *thread); ~OptimizedEntryFrameHandler() = default; void PrevFrame(); -- Gitee From 9ddc634cebb817c7529d73482f6e3fdff7122f9d Mon Sep 17 00:00:00 2001 From: DaiHN Date: Fri, 29 Oct 2021 14:57:33 +0800 Subject: [PATCH 100/115] IC polymorphic optimization Signed-off-by: DaiHN --- ecmascript/interpreter/interpreter-inl.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 3a817a0..49f3183 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -2502,6 +2502,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryLoadICByValue(thread, receiver, propKey, firstValue, secondValue); } + // IC miss and not enter the megamorphic state, store as polymorphic if (res.IsHole() && !firstValue.IsHole()) { res = ICRuntimeStub::LoadICByValue(thread, profileTypeArray, @@ -2554,6 +2555,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryStoreICByValue(thread, receiver, propKey, firstValue, secondValue, value); } + // IC miss and not enter the megamorphic state, store as polymorphic if (res.IsHole() && !firstValue.IsHole()) { res = ICRuntimeStub::StoreICByValue(thread, profileTypeArray, @@ -2867,6 +2869,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryLoadICByName(thread, receiver, firstValue, secondValue); } + // IC miss and not enter the megamorphic state, store as polymorphic if (res.IsHole() && !firstValue.IsHole()) { uint32_t stringId = READ_INST_32_1(); JSTaggedValue propKey = constpool->GetObjectFromCache(stringId); @@ -2922,6 +2925,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1); res = ICRuntimeStub::TryStoreICByName(thread, receiver, firstValue, secondValue, value); } + // IC miss and not enter the megamorphic state, store as polymorphic if (res.IsHole() && !firstValue.IsHole()) { uint32_t stringId = READ_INST_32_1(); JSTaggedValue propKey = constpool->GetObjectFromCache(stringId); -- Gitee From 753f285c6a63cea6627c9d07bc42a3de22c7d78c Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 29 Oct 2021 16:53:10 +0800 Subject: [PATCH 101/115] conflict Signed-off-by: songzhengchao --- ecmascript/compiler/fast_stub_define.h | 2 +- ecmascript/compiler/stub_descriptor.cpp | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index 25de64c..b7ab275 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -48,6 +48,7 @@ namespace kungfu { V(IsSpecialIndexedObjForGet, 1) \ V(GetPropertyByName, 3) \ V(GetElement, 2) \ + V(SetPropertyByName, 5) \ V(SetElement, 5) \ V(SetGlobalOwnProperty, 5) \ V(GetGlobalOwnProperty, 3) \ @@ -65,7 +66,6 @@ namespace kungfu { V(SetPropertyByIndex, 4) \ V(GetPropertyByValue, 3) \ V(SetPropertyByValue, 4) \ - V(SetPropertyByName, 4) \ V(FastMulGC, 3) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index feb37d6..44044c5 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -461,10 +461,17 @@ CALL_STUB_INIT_DESCRIPTOR(SetValueWithBarrier) std::array params = { MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + CALL_STUB_INIT_DESCRIPTOR(NewInternalString) { // 2 : 2 input parameters - StubDescriptor stringGetHashCode("NewInternalString", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor stringGetHashCode("NewInternalString", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = stringGetHashCode; // 2 : 2 input parameters std::array params = { @@ -532,5 +539,4 @@ void FastStubDescriptors::InitializeStubDescriptors() #undef INITIALIZE_CALL_STUB_DESCRIPTOR #undef DEF_CALL_STUB } -} } // namespace kungfu -- Gitee From 15e6848c0e58495c08f5fffdab1d0db6a960c40d Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Fri, 29 Oct 2021 17:03:38 +0800 Subject: [PATCH 102/115] conflict Signed-off-by: songzhengchao --- ecmascript/compiler/fast_stub.cpp | 9 ++++----- ecmascript/compiler/stub_descriptor.cpp | 2 ++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 6f5e0ff..8f52909 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -1174,9 +1174,8 @@ void FastMulGCStub::GenerateCircuit() AddrShift x = Int64Argument(1); AddrShift y = Int64Argument(2); - DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); - DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); - DEFVARIABLE(intZ, MachineType::INT32_TYPE, 0); + DEFVARIABLE(intX, MachineType::INT64_TYPE, 0); + DEFVARIABLE(intY, MachineType::INT64_TYPE, 0); DEFVARIABLE(valuePtr, MachineType::INT64_TYPE, 0); DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); @@ -1197,7 +1196,7 @@ void FastMulGCStub::GenerateCircuit() Branch(TaggedIsInt(x), &xIsInt, &xNotInt); Bind(&xIsInt); { - intX = TaggedCastToInt32(x); + intX = TaggedCastToInt64(x); doubleX = CastInt64ToFloat64(*intX); Jump(&xIsNumberAndyIsNumber); } @@ -1217,7 +1216,7 @@ void FastMulGCStub::GenerateCircuit() Branch(TaggedIsInt(y), &yIsInt, &yNotInt); Bind(&yIsInt); { - intY = TaggedCastToInt32(y); + intY = TaggedCastToInt64(y); doubleY = CastInt64ToFloat64(*intY); Jump(&xIsDoubleAndyIsDouble); } diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 44044c5..6a33651 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -168,6 +168,8 @@ CALL_STUB_INIT_DESCRIPTOR(SetElement) descriptor->SetParameters(params.data()); } +CALL_STUB_INIT_DESCRIPTOR(SetPropertyByName) {} + CALL_STUB_INIT_DESCRIPTOR(GetPropertyByName) { // 3 : 3 input parameters -- Gitee From 1c54a8d5922b28d2eb6eaffc393dde323b98da45 Mon Sep 17 00:00:00 2001 From: linxiang Date: Fri, 29 Oct 2021 16:41:13 +0800 Subject: [PATCH 103/115] When the L2 development board executes the use case, it does not have the read-write permission of the file, resulting in the use case failed Signed-off-by: linxiang Change-Id: Ie1f4aa6d3776eb7e6a2a87b94e1fcea9418fa695 --- ecmascript/hprof/tests/BUILD.gn | 10 +- ecmascript/hprof/tests/hprof_test.cpp | 498 ----------------------- ecmascript/tests/dump_test.cpp | 547 ++++++++++++++++++++++++++ 3 files changed, 549 insertions(+), 506 deletions(-) diff --git a/ecmascript/hprof/tests/BUILD.gn b/ecmascript/hprof/tests/BUILD.gn index 04ca908..269c551 100644 --- a/ecmascript/hprof/tests/BUILD.gn +++ b/ecmascript/hprof/tests/BUILD.gn @@ -73,16 +73,10 @@ host_unittest_action("HprofTest") { group("unittest") { testonly = true - deps = [ - ":HeapTrackerTest", - ":HprofTest", - ] + deps = [ ":HeapTrackerTest" ] } group("host_unittest") { testonly = true - deps = [ - ":HeapTrackerTestAction", - ":HprofTestAction", - ] + deps = [ ":HeapTrackerTestAction" ] } diff --git a/ecmascript/hprof/tests/hprof_test.cpp b/ecmascript/hprof/tests/hprof_test.cpp index d602165..97ef0d8 100644 --- a/ecmascript/hprof/tests/hprof_test.cpp +++ b/ecmascript/hprof/tests/hprof_test.cpp @@ -388,502 +388,4 @@ HWTEST_F_L0(HProfTest, ContrastTraceFunctionInfoCount) tester.ExtractCountFromPayload("\"trace_function_infos\":")); ASSERT_TRUE(tester.RemoveExistingFile()); } - -static JSHandle NewJSMap(JSThread *thread, ObjectFactory *factory, JSHandle proto) -{ - JSHandle mapClass = factory->NewEcmaDynClass(JSMap::SIZE, JSType::JS_MAP, proto); - JSHandle jsMap = JSHandle::Cast(factory->NewJSObject(mapClass)); - JSHandle linkedMap(thread, LinkedHashMap::Create(thread)); - jsMap->SetLinkedMap(thread, linkedMap); - return jsMap; -} - -static JSHandle NewJSSet(JSThread *thread, ObjectFactory *factory, JSHandle proto) -{ - JSHandle setClass = factory->NewEcmaDynClass(JSSet::SIZE, JSType::JS_SET, proto); - JSHandle jsSet = JSHandle::Cast(factory->NewJSObject(setClass)); - JSHandle linkedSet(thread, LinkedHashSet::Create(thread)); - jsSet->SetLinkedSet(thread, linkedSet); - return jsSet; -} - -static JSHandle NewJSObject(JSThread *thread, ObjectFactory *factory, JSHandle globalEnv) -{ - JSFunction *jsFunc = globalEnv->GetObjectFunction().GetObject(); - JSHandle jsFunc1(thread, jsFunc); - JSHandle jsObj = factory->NewJSObjectByConstructor(JSHandle(jsFunc1), jsFunc1); - return jsObj; -} - -HWTEST_F_L0(HProfTest, Dump) -{ - [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread); - auto factory = thread->GetEcmaVM()->GetFactory(); - auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); - auto globalConst = const_cast(thread->GlobalConstants()); - JSHandle proto = globalEnv->GetFunctionPrototype(); - std::vector> snapshotVector; - -#define DUMP_FOR_HANDLE(dumpHandle) \ - dumpHandle.GetTaggedValue().Dump(thread); \ - dumpHandle.GetTaggedValue().DumpForSnapshot(thread, snapshotVector); - -#define NEW_OBJECT_AND_DUMP(ClassName, TypeName) \ - JSHandle class##ClassName = \ - factory->NewEcmaDynClass(ClassName::SIZE, JSType::TypeName, proto); \ - JSHandle object##ClassName = factory->NewJSObject(class##ClassName); \ - object##ClassName.GetTaggedValue().Dump(thread); \ - object##ClassName.GetTaggedValue().DumpForSnapshot(thread, snapshotVector); - - for (JSType type = JSType::JS_OBJECT; type <= JSType::JS_TYPE_LAST; type = JSType(static_cast(type) + 1)) { - switch (type) { - case JSType::JS_ERROR: - case JSType::JS_EVAL_ERROR: - case JSType::JS_RANGE_ERROR: - case JSType::JS_TYPE_ERROR: - case JSType::JS_REFERENCE_ERROR: - case JSType::JS_URI_ERROR: - case JSType::JS_SYNTAX_ERROR: - case JSType::JS_OBJECT: { - CHECK_DUMP_FILEDS(ECMAObject::SIZE, JSObject::SIZE, 2) - JSHandle jsObj = NewJSObject(thread, factory, globalEnv); - DUMP_FOR_HANDLE(jsObj) - break; - } - case JSType::JS_REALM: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSRealm::SIZE, 2) - JSHandle jsRealm = factory->NewJSRealm(); - DUMP_FOR_HANDLE(jsRealm) - break; - } - case JSType::JS_FUNCTION_BASE: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSFunctionBase::SIZE, 1) - break; - } - case JSType::JS_FUNCTION: { - CHECK_DUMP_FILEDS(JSFunctionBase::SIZE, JSFunction::SIZE, 7) - JSHandle jsFunc = globalEnv->GetFunctionFunction(); - DUMP_FOR_HANDLE(jsFunc) - break; - } - case JSType::JS_PROXY_REVOC_FUNCTION: { - CHECK_DUMP_FILEDS(JSFunction::SIZE, JSProxyRevocFunction::SIZE, 1) - JSHandle proxyRevocClass = - JSHandle::Cast(globalEnv->GetProxyRevocFunctionClass()); - JSHandle proxyRevocFunc = factory->NewJSObject(proxyRevocClass); - DUMP_FOR_HANDLE(proxyRevocFunc) - break; - } - case JSType::JS_PROMISE_REACTIONS_FUNCTION: { - CHECK_DUMP_FILEDS(JSFunction::SIZE, JSPromiseReactionsFunction::SIZE, 2) - JSHandle promiseReactClass = - JSHandle::Cast(globalEnv->GetPromiseReactionFunctionClass()); - JSHandle promiseReactFunc = factory->NewJSObject(promiseReactClass); - DUMP_FOR_HANDLE(promiseReactFunc) - break; - } - case JSType::JS_PROMISE_EXECUTOR_FUNCTION: { - CHECK_DUMP_FILEDS(JSFunction::SIZE, JSPromiseExecutorFunction::SIZE, 1) - JSHandle promiseExeClass = - JSHandle::Cast(globalEnv->GetPromiseExecutorFunctionClass()); - JSHandle promiseExeFunc = factory->NewJSObject(promiseExeClass); - DUMP_FOR_HANDLE(promiseExeFunc) - break; - } - case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION: { - CHECK_DUMP_FILEDS(JSFunction::SIZE, JSPromiseAllResolveElementFunction::SIZE, 5) - JSHandle promiseAllClass = - JSHandle::Cast(globalEnv->GetPromiseAllResolveElementFunctionClass()); - JSHandle promiseAllFunc = factory->NewJSObject(promiseAllClass); - DUMP_FOR_HANDLE(promiseAllFunc) - break; - } - case JSType::JS_GENERATOR_FUNCTION: { - CHECK_DUMP_FILEDS(JSFunction::SIZE, JSGeneratorFunction::SIZE, 0) - break; - } - case JSType::JS_ASYNC_FUNCTION: { - CHECK_DUMP_FILEDS(JSFunction::SIZE, JSAsyncFunction::SIZE, 0) - break; - } - case JSType::JS_INTL_BOUND_FUNCTION: { - CHECK_DUMP_FILEDS(JSFunction::SIZE, JSIntlBoundFunction::SIZE, 3) - JSHandle intlBoundFunc = factory->NewJSIntlBoundFunction(); - DUMP_FOR_HANDLE(intlBoundFunc) - break; - } - case JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION: { - CHECK_DUMP_FILEDS(JSFunction::SIZE, JSAsyncAwaitStatusFunction::SIZE, 1) - JSHandle asyncAwaitFunc = factory->NewJSAsyncAwaitStatusFunction(); - DUMP_FOR_HANDLE(asyncAwaitFunc) - break; - } - case JSType::JS_BOUND_FUNCTION: { - CHECK_DUMP_FILEDS(JSFunctionBase::SIZE, JSBoundFunction::SIZE, 3) - NEW_OBJECT_AND_DUMP(JSBoundFunction, JS_BOUND_FUNCTION) - break; - } - case JSType::JS_REG_EXP: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSRegExp::SIZE, 5) - NEW_OBJECT_AND_DUMP(JSRegExp, JS_REG_EXP) - break; - } - case JSType::JS_SET: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSSet::SIZE, 1) - JSHandle jsSet = NewJSSet(thread, factory, proto); - DUMP_FOR_HANDLE(jsSet) - break; - } - case JSType::JS_MAP: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSMap::SIZE, 1) - JSHandle jsMap = NewJSMap(thread, factory, proto); - DUMP_FOR_HANDLE(jsMap) - break; - } - case JSType::JS_WEAK_MAP: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSWeakMap::SIZE, 1) - JSHandle weakMapClass = factory->NewEcmaDynClass(JSWeakMap::SIZE, JSType::JS_WEAK_MAP, proto); - JSHandle jsWeakMap = JSHandle::Cast(factory->NewJSObject(weakMapClass)); - JSHandle weakLinkedMap(thread, LinkedHashMap::Create(thread)); - jsWeakMap->SetLinkedMap(thread, weakLinkedMap); - DUMP_FOR_HANDLE(jsWeakMap) - break; - } - case JSType::JS_WEAK_SET: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSWeakSet::SIZE, 1) - JSHandle weakSetClass = factory->NewEcmaDynClass(JSWeakSet::SIZE, JSType::JS_WEAK_SET, proto); - JSHandle jsWeakSet = JSHandle::Cast(factory->NewJSObject(weakSetClass)); - JSHandle weakLinkedSet(thread, LinkedHashSet::Create(thread)); - jsWeakSet->SetLinkedSet(thread, weakLinkedSet); - DUMP_FOR_HANDLE(jsWeakSet) - break; - } - case JSType::JS_DATE: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSDate::SIZE, 2) - JSHandle dateClass = factory->NewEcmaDynClass(JSDate::SIZE, JSType::JS_DATE, proto); - JSHandle date = JSHandle::Cast(factory->NewJSObject(dateClass)); - date->SetTimeValue(thread, JSTaggedValue(0.0)); - date->SetLocalOffset(thread, JSTaggedValue(0.0)); - DUMP_FOR_HANDLE(date) - break; - } - case JSType::JS_ITERATOR: - // JS Iterate is a tool class, so we don't need to check it. - break; - case JSType::JS_FORIN_ITERATOR: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSForInIterator::SIZE, 4) - JSHandle array(thread, factory->NewJSArray().GetTaggedValue()); - JSHandle forInIter = factory->NewJSForinIterator(array); - DUMP_FOR_HANDLE(forInIter) - break; - } - case JSType::JS_MAP_ITERATOR: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSMapIterator::SIZE, 3) - JSHandle jsMapIter = - factory->NewJSMapIterator(NewJSMap(thread, factory, proto), IterationKind::KEY); - DUMP_FOR_HANDLE(jsMapIter) - break; - } - case JSType::JS_SET_ITERATOR: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSSetIterator::SIZE, 3) - JSHandle jsSetIter = - factory->NewJSSetIterator(NewJSSet(thread, factory, proto), IterationKind::KEY); - DUMP_FOR_HANDLE(jsSetIter) - break; - } - case JSType::JS_ARRAY_ITERATOR: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSArrayIterator::SIZE, 3) - JSHandle arrayIter = - factory->NewJSArrayIterator(JSHandle::Cast(factory->NewJSArray()), IterationKind::KEY); - DUMP_FOR_HANDLE(arrayIter) - break; - } - case JSType::JS_STRING_ITERATOR: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSStringIterator::SIZE, 2) - JSHandle stringIter = globalEnv->GetStringIterator(); - DUMP_FOR_HANDLE(stringIter) - break; - } - case JSType::JS_INTL: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSIntl::SIZE, 1) - NEW_OBJECT_AND_DUMP(JSIntl, JS_INTL) - break; - } - case JSType::JS_LOCALE: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSLocale::SIZE, 1) - NEW_OBJECT_AND_DUMP(JSLocale, JS_LOCALE) - break; - } - case JSType::JS_DATE_TIME_FORMAT: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSDateTimeFormat::SIZE, 11) - NEW_OBJECT_AND_DUMP(JSDateTimeFormat, JS_DATE_TIME_FORMAT) - break; - } - case JSType::JS_RELATIVE_TIME_FORMAT: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSRelativeTimeFormat::SIZE, 7) - NEW_OBJECT_AND_DUMP(JSRelativeTimeFormat, JS_RELATIVE_TIME_FORMAT) - break; - } - case JSType::JS_NUMBER_FORMAT: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSNumberFormat::SIZE, 20) - NEW_OBJECT_AND_DUMP(JSNumberFormat, JS_NUMBER_FORMAT) - break; - } - case JSType::JS_COLLATOR: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSCollator::SIZE, 9) - NEW_OBJECT_AND_DUMP(JSCollator, JS_COLLATOR) - break; - } - case JSType::JS_PLURAL_RULES: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSPluralRules::SIZE, 11) - NEW_OBJECT_AND_DUMP(JSPluralRules, JS_PLURAL_RULES) - break; - } - case JSType::JS_ARRAY_BUFFER: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSArrayBuffer::SIZE, 3) - NEW_OBJECT_AND_DUMP(JSArrayBuffer, JS_ARRAY_BUFFER) - break; - } - case JSType::JS_PROMISE: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSPromise::SIZE, 5) - NEW_OBJECT_AND_DUMP(JSPromise, JS_PROMISE) - break; - } - case JSType::JS_DATA_VIEW: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSDataView::SIZE, 4) - NEW_OBJECT_AND_DUMP(JSDataView, JS_DATA_VIEW) - break; - } - case JSType::JS_ARGUMENTS: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSArguments::SIZE, 1) - NEW_OBJECT_AND_DUMP(JSArguments, JS_ARGUMENTS) - break; - } - case JSType::JS_GENERATOR_OBJECT: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSGeneratorObject::SIZE, 4) - NEW_OBJECT_AND_DUMP(JSGeneratorObject, JS_GENERATOR_OBJECT) - break; - } - case JSType::JS_ASYNC_FUNC_OBJECT: { - CHECK_DUMP_FILEDS(JSGeneratorObject::SIZE, JSAsyncFuncObject::SIZE, 1) - JSHandle asyncFuncObject = factory->NewJSAsyncFuncObject(); - DUMP_FOR_HANDLE(asyncFuncObject) - break; - } - case JSType::JS_ARRAY: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSArray::SIZE, 1) - JSHandle jsArray = factory->NewJSArray(); - DUMP_FOR_HANDLE(jsArray) - break; - } - case JSType::JS_TYPED_ARRAY: - case JSType::JS_INT8_ARRAY: - case JSType::JS_UINT8_ARRAY: - case JSType::JS_UINT8_CLAMPED_ARRAY: - case JSType::JS_INT16_ARRAY: - case JSType::JS_UINT16_ARRAY: - case JSType::JS_INT32_ARRAY: - case JSType::JS_UINT32_ARRAY: - case JSType::JS_FLOAT32_ARRAY: - case JSType::JS_FLOAT64_ARRAY: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSTypedArray::SIZE, 5) - NEW_OBJECT_AND_DUMP(JSTypedArray, JS_TYPED_ARRAY) - break; - } - case JSType::JS_PRIMITIVE_REF: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSPrimitiveRef::SIZE, 1) - NEW_OBJECT_AND_DUMP(JSPrimitiveRef, JS_PRIMITIVE_REF) - break; - } - case JSType::JS_GLOBAL_OBJECT: { - CHECK_DUMP_FILEDS(JSObject::SIZE, JSGlobalObject::SIZE, 0) - JSHandle globalObject = globalEnv->GetJSGlobalObject(); - DUMP_FOR_HANDLE(globalObject) - break; - } - case JSType::JS_PROXY: { - CHECK_DUMP_FILEDS(ECMAObject::SIZE, JSProxy::SIZE, 3) - JSHandle emptyObj(thread, NewJSObject(thread, factory, globalEnv).GetTaggedValue()); - JSHandle proxy = factory->NewJSProxy(emptyObj, emptyObj); - DUMP_FOR_HANDLE(proxy) - break; - } - case JSType::HCLASS: { - CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSHClass::SIZE, 9) - JSHandle hclass = factory->NewEcmaDynClass(JSHClass::SIZE, JSType::HCLASS, proto); - DUMP_FOR_HANDLE(hclass) - break; - } - case JSType::STRING: { - DUMP_FOR_HANDLE(globalEnv->GetObjectFunction()) - break; - } - case JSType::TAGGED_ARRAY: { - JSHandle taggedArray = factory->NewTaggedArray(4); - DUMP_FOR_HANDLE(taggedArray) - break; - } - case JSType::TAGGED_DICTIONARY: { - JSHandle dict = factory->NewDictionaryArray(4); - DUMP_FOR_HANDLE(dict) - break; - } - case JSType::FREE_OBJECT_WITH_ONE_FIELD: - case JSType::FREE_OBJECT_WITH_NONE_FIELD: - case JSType::FREE_OBJECT_WITH_TWO_FIELD: - { - break; - } - case JSType::JS_NATIVE_POINTER: { - break; - } - case JSType::GLOBAL_ENV: { - DUMP_FOR_HANDLE(globalEnv) - break; - } - case JSType::ACCESSOR_DATA: - case JSType::INTERNAL_ACCESSOR: { - CHECK_DUMP_FILEDS(Record::SIZE, AccessorData::SIZE, 2) - JSHandle accessor = factory->NewAccessorData(); - DUMP_FOR_HANDLE(accessor) - break; - } - case JSType::SYMBOL: { - CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSSymbol::SIZE, 3) - JSHandle symbol = factory->NewJSSymbol(); - DUMP_FOR_HANDLE(symbol) - break; - } - case JSType::JS_GENERATOR_CONTEXT: { - CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), GeneratorContext::SIZE, 7) - JSHandle genContext = factory->NewGeneratorContext(); - DUMP_FOR_HANDLE(genContext) - break; - } - case JSType::PROTOTYPE_HANDLER: { - CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), PrototypeHandler::SIZE, 3) - JSHandle protoHandler = factory->NewPrototypeHandler(); - DUMP_FOR_HANDLE(protoHandler) - break; - } - case JSType::TRANSITION_HANDLER: { - CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), TransitionHandler::SIZE, 2) - JSHandle transitionHandler = factory->NewTransitionHandler(); - DUMP_FOR_HANDLE(transitionHandler) - break; - } - case JSType::PROPERTY_BOX: { - CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), PropertyBox::SIZE, 1) - JSHandle PropertyBox = factory->NewPropertyBox(globalEnv->GetEmptyArray()); - DUMP_FOR_HANDLE(PropertyBox) - break; - } - case JSType::PROTO_CHANGE_MARKER: { - CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), ProtoChangeMarker::SIZE, 1) - JSHandle protoMaker = factory->NewProtoChangeMarker(); - DUMP_FOR_HANDLE(protoMaker) - break; - } - case JSType::PROTOTYPE_INFO: { - CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), ProtoChangeDetails::SIZE, 2) - JSHandle protoDetails = factory->NewProtoChangeDetails(); - DUMP_FOR_HANDLE(protoDetails) - break; - } - case JSType::TEMPLATE_MAP: { - JSHandle templateMap = globalEnv->GetTemplateMap(); - DUMP_FOR_HANDLE(templateMap) - break; - } - case JSType::PROGRAM: { - CHECK_DUMP_FILEDS(ECMAObject::SIZE, Program::SIZE, 5) - JSHandle program = factory->NewProgram(); - DUMP_FOR_HANDLE(program) - break; - } - case JSType::LEXICAL_FUNCTION: { - CHECK_DUMP_FILEDS(ECMAObject::SIZE, LexicalFunction::SIZE, 5) - // unused - break; - } - case JSType::PROMISE_CAPABILITY: { - CHECK_DUMP_FILEDS(Record::SIZE, PromiseCapability::SIZE, 3) - JSHandle promiseCapa = factory->NewPromiseCapability(); - DUMP_FOR_HANDLE(promiseCapa) - break; - } - case JSType::PROMISE_RECORD: { - CHECK_DUMP_FILEDS(Record::SIZE, PromiseRecord::SIZE, 1) - JSHandle promiseRecord = factory->NewPromiseRecord(); - DUMP_FOR_HANDLE(promiseRecord) - break; - } - case JSType::RESOLVING_FUNCTIONS_RECORD: { - CHECK_DUMP_FILEDS(Record::SIZE, ResolvingFunctionsRecord::SIZE, 2) - JSHandle ResolvingFunc = factory->NewResolvingFunctionsRecord(); - DUMP_FOR_HANDLE(ResolvingFunc) - break; - } - case JSType::PROMISE_REACTIONS: { - CHECK_DUMP_FILEDS(Record::SIZE, PromiseReaction::SIZE, 3) - JSHandle promiseReact = factory->NewPromiseReaction(); - DUMP_FOR_HANDLE(promiseReact) - break; - } - case JSType::PROMISE_ITERATOR_RECORD: { - CHECK_DUMP_FILEDS(Record::SIZE, PromiseIteratorRecord::SIZE, 2) - JSHandle emptyObj(thread, NewJSObject(thread, factory, globalEnv).GetTaggedValue()); - JSHandle promiseIter = factory->NewPromiseIteratorRecord(emptyObj, emptyObj); - DUMP_FOR_HANDLE(promiseIter) - break; - } - case JSType::MICRO_JOB_QUEUE: { - CHECK_DUMP_FILEDS(Record::SIZE, MicroJobQueue::SIZE, 2) - JSHandle microJob = factory->NewMicroJobQueue(); - DUMP_FOR_HANDLE(microJob) - break; - } - case JSType::PENDING_JOB: { - CHECK_DUMP_FILEDS(Record::SIZE, PendingJob::SIZE, 2) - JSHandle pendingClass(thread, - JSHClass::Cast(globalConst->GetPendingJobClass().GetTaggedObject())); - JSHandle pendingJob(thread, factory->NewDynObject(pendingClass)); - DUMP_FOR_HANDLE(pendingJob) - break; - } - case JSType::FUNCTION_EXTRA_INFO: { - CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSFunctionExtraInfo::SIZE, 2) - JSHandle funcExtraClass(thread, - JSHClass::Cast(globalConst->GetFunctionExtraInfoClass().GetTaggedObject())); - JSHandle funcInfo(thread, factory->NewDynObject(funcExtraClass)); - DUMP_FOR_HANDLE(funcInfo) - break; - } - case JSType::COMPLETION_RECORD: { - CHECK_DUMP_FILEDS(Record::SIZE, CompletionRecord::SIZE, 2) - JSHandle comRecord = factory->NewCompletionRecord(0, globalEnv->GetEmptyArray()); - DUMP_FOR_HANDLE(comRecord) - break; - } - case JSType::MACHINE_CODE_OBJECT: { - CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), MachineCode::DATA_OFFSET, 1) - JSHandle machineCode = factory->NewMachineCodeObject(16, nullptr); - DUMP_FOR_HANDLE(machineCode) - break; - } - case JSType::ECMA_MODULE: { - CHECK_DUMP_FILEDS(ECMAObject::SIZE, EcmaModule::SIZE, 1) - JSHandle ecmaModule = factory->NewEmptyEcmaModule(); - DUMP_FOR_HANDLE(ecmaModule) - break; - } - default: - LOG_ECMA_MEM(ERROR) << "JSType " << static_cast(type) << " cannot be dumped."; - UNREACHABLE(); - break; - } - } -#undef NEW_OBJECT_AND_DUMP -#undef DUMP_FOR_HANDLE -} } // namespace panda::test diff --git a/ecmascript/tests/dump_test.cpp b/ecmascript/tests/dump_test.cpp index b7142c4..604f06b 100644 --- a/ecmascript/tests/dump_test.cpp +++ b/ecmascript/tests/dump_test.cpp @@ -13,23 +13,72 @@ * limitations under the License. */ +#include "ecmascript/accessor_data.h" +#include "ecmascript/class_linker/program_object-inl.h" +#include "ecmascript/ecma_module.h" #include "ecmascript/ecma_vm.h" +#include "ecmascript/global_dictionary-inl.h" #include "ecmascript/global_env.h" +#include "ecmascript/hprof/heap_profiler.h" +#include "ecmascript/hprof/heap_profiler_interface.h" +#include "ecmascript/hprof/heap_snapshot.h" +#include "ecmascript/hprof/heap_snapshot_json_serializer.h" +#include "ecmascript/hprof/string_hashmap.h" +#include "ecmascript/ic/ic_handler.h" +#include "ecmascript/ic/proto_change_details.h" +#include "ecmascript/ic/property_box.h" +#include "ecmascript/jobs/micro_job_queue.h" +#include "ecmascript/jobs/pending_job.h" +#include "ecmascript/js_arguments.h" #include "ecmascript/js_array.h" +#include "ecmascript/js_array_iterator.h" +#include "ecmascript/js_arraybuffer.h" +#include "ecmascript/js_async_function.h" +#include "ecmascript/js_collator.h" +#include "ecmascript/js_dataview.h" #include "ecmascript/js_date.h" +#include "ecmascript/js_date_time_format.h" +#include "ecmascript/js_for_in_iterator.h" #include "ecmascript/js_function.h" +#include "ecmascript/js_function_extra_info.h" +#include "ecmascript/js_generator_object.h" +#include "ecmascript/js_global_object.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/js_intl.h" +#include "ecmascript/js_locale.h" #include "ecmascript/js_map.h" +#include "ecmascript/js_map_iterator.h" +#include "ecmascript/js_number_format.h" #include "ecmascript/js_object-inl.h" +#include "ecmascript/js_plural_rules.h" #include "ecmascript/js_primitive_ref.h" +#include "ecmascript/js_promise.h" +#include "ecmascript/js_realm.h" #include "ecmascript/js_regexp.h" +#include "ecmascript/js_relative_time_format.h" #include "ecmascript/js_set.h" +#include "ecmascript/js_set_iterator.h" +#include "ecmascript/js_string_iterator.h" +#include "ecmascript/js_tagged_number.h" #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/js_thread.h" +#include "ecmascript/js_typed_array.h" +#include "ecmascript/js_weak_container.h" +#include "ecmascript/layout_info-inl.h" +#include "ecmascript/lexical_env.h" #include "ecmascript/linked_hash_table-inl.h" +#include "ecmascript/mem/assert_scope-inl.h" +#include "ecmascript/mem/c_containers.h" +#include "ecmascript/mem/machine_code.h" #include "ecmascript/object_factory.h" +#include "ecmascript/tagged_array.h" +#include "ecmascript/tagged_dictionary.h" +#include "ecmascript/template_map.h" #include "ecmascript/tests/test_helper.h" +#include "ecmascript/transitions_dictionary.h" using namespace panda::ecmascript; +using namespace panda::ecmascript::base; namespace panda::test { class EcmaDumpTest : public testing::Test { @@ -77,4 +126,502 @@ HWTEST_F_L0(EcmaDumpTest, Dump) objFunc.Dump(jsThread); } #endif // #ifndef NDEBUG + +static JSHandle NewJSMap(JSThread *thread, ObjectFactory *factory, JSHandle proto) +{ + JSHandle mapClass = factory->NewEcmaDynClass(JSMap::SIZE, JSType::JS_MAP, proto); + JSHandle jsMap = JSHandle::Cast(factory->NewJSObject(mapClass)); + JSHandle linkedMap(thread, LinkedHashMap::Create(thread)); + jsMap->SetLinkedMap(thread, linkedMap); + return jsMap; +} + +static JSHandle NewJSSet(JSThread *thread, ObjectFactory *factory, JSHandle proto) +{ + JSHandle setClass = factory->NewEcmaDynClass(JSSet::SIZE, JSType::JS_SET, proto); + JSHandle jsSet = JSHandle::Cast(factory->NewJSObject(setClass)); + JSHandle linkedSet(thread, LinkedHashSet::Create(thread)); + jsSet->SetLinkedSet(thread, linkedSet); + return jsSet; +} + +static JSHandle NewJSObject(JSThread *thread, ObjectFactory *factory, JSHandle globalEnv) +{ + JSFunction *jsFunc = globalEnv->GetObjectFunction().GetObject(); + JSHandle jsFunc1(thread, jsFunc); + JSHandle jsObj = factory->NewJSObjectByConstructor(JSHandle(jsFunc1), jsFunc1); + return jsObj; +} + +HWTEST_F_L0(EcmaDumpTest, HeapProfileDump) +{ + [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread); + auto factory = thread->GetEcmaVM()->GetFactory(); + auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); + auto globalConst = const_cast(thread->GlobalConstants()); + JSHandle proto = globalEnv->GetFunctionPrototype(); + std::vector> snapshotVector; + +#define DUMP_FOR_HANDLE(dumpHandle) \ + dumpHandle.GetTaggedValue().Dump(thread); \ + dumpHandle.GetTaggedValue().DumpForSnapshot(thread, snapshotVector); + +#define NEW_OBJECT_AND_DUMP(ClassName, TypeName) \ + JSHandle class##ClassName = \ + factory->NewEcmaDynClass(ClassName::SIZE, JSType::TypeName, proto); \ + JSHandle object##ClassName = factory->NewJSObject(class##ClassName); \ + object##ClassName.GetTaggedValue().Dump(thread); \ + object##ClassName.GetTaggedValue().DumpForSnapshot(thread, snapshotVector); + + for (JSType type = JSType::JS_OBJECT; type <= JSType::JS_TYPE_LAST; type = JSType(static_cast(type) + 1)) { + switch (type) { + case JSType::JS_ERROR: + case JSType::JS_EVAL_ERROR: + case JSType::JS_RANGE_ERROR: + case JSType::JS_TYPE_ERROR: + case JSType::JS_REFERENCE_ERROR: + case JSType::JS_URI_ERROR: + case JSType::JS_SYNTAX_ERROR: + case JSType::JS_OBJECT: { + CHECK_DUMP_FILEDS(ECMAObject::SIZE, JSObject::SIZE, 2) + JSHandle jsObj = NewJSObject(thread, factory, globalEnv); + DUMP_FOR_HANDLE(jsObj) + break; + } + case JSType::JS_REALM: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSRealm::SIZE, 2) + JSHandle jsRealm = factory->NewJSRealm(); + DUMP_FOR_HANDLE(jsRealm) + break; + } + case JSType::JS_FUNCTION_BASE: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSFunctionBase::SIZE, 1) + break; + } + case JSType::JS_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunctionBase::SIZE, JSFunction::SIZE, 7) + JSHandle jsFunc = globalEnv->GetFunctionFunction(); + DUMP_FOR_HANDLE(jsFunc) + break; + } + case JSType::JS_PROXY_REVOC_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSProxyRevocFunction::SIZE, 1) + JSHandle proxyRevocClass = + JSHandle::Cast(globalEnv->GetProxyRevocFunctionClass()); + JSHandle proxyRevocFunc = factory->NewJSObject(proxyRevocClass); + DUMP_FOR_HANDLE(proxyRevocFunc) + break; + } + case JSType::JS_PROMISE_REACTIONS_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSPromiseReactionsFunction::SIZE, 2) + JSHandle promiseReactClass = + JSHandle::Cast(globalEnv->GetPromiseReactionFunctionClass()); + JSHandle promiseReactFunc = factory->NewJSObject(promiseReactClass); + DUMP_FOR_HANDLE(promiseReactFunc) + break; + } + case JSType::JS_PROMISE_EXECUTOR_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSPromiseExecutorFunction::SIZE, 1) + JSHandle promiseExeClass = + JSHandle::Cast(globalEnv->GetPromiseExecutorFunctionClass()); + JSHandle promiseExeFunc = factory->NewJSObject(promiseExeClass); + DUMP_FOR_HANDLE(promiseExeFunc) + break; + } + case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSPromiseAllResolveElementFunction::SIZE, 5) + JSHandle promiseAllClass = + JSHandle::Cast(globalEnv->GetPromiseAllResolveElementFunctionClass()); + JSHandle promiseAllFunc = factory->NewJSObject(promiseAllClass); + DUMP_FOR_HANDLE(promiseAllFunc) + break; + } + case JSType::JS_GENERATOR_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSGeneratorFunction::SIZE, 0) + break; + } + case JSType::JS_ASYNC_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSAsyncFunction::SIZE, 0) + break; + } + case JSType::JS_INTL_BOUND_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSIntlBoundFunction::SIZE, 3) + JSHandle intlBoundFunc = factory->NewJSIntlBoundFunction(); + DUMP_FOR_HANDLE(intlBoundFunc) + break; + } + case JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunction::SIZE, JSAsyncAwaitStatusFunction::SIZE, 1) + JSHandle asyncAwaitFunc = factory->NewJSAsyncAwaitStatusFunction(); + DUMP_FOR_HANDLE(asyncAwaitFunc) + break; + } + case JSType::JS_BOUND_FUNCTION: { + CHECK_DUMP_FILEDS(JSFunctionBase::SIZE, JSBoundFunction::SIZE, 3) + NEW_OBJECT_AND_DUMP(JSBoundFunction, JS_BOUND_FUNCTION) + break; + } + case JSType::JS_REG_EXP: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSRegExp::SIZE, 5) + NEW_OBJECT_AND_DUMP(JSRegExp, JS_REG_EXP) + break; + } + case JSType::JS_SET: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSSet::SIZE, 1) + JSHandle jsSet = NewJSSet(thread, factory, proto); + DUMP_FOR_HANDLE(jsSet) + break; + } + case JSType::JS_MAP: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSMap::SIZE, 1) + JSHandle jsMap = NewJSMap(thread, factory, proto); + DUMP_FOR_HANDLE(jsMap) + break; + } + case JSType::JS_WEAK_MAP: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSWeakMap::SIZE, 1) + JSHandle weakMapClass = factory->NewEcmaDynClass(JSWeakMap::SIZE, JSType::JS_WEAK_MAP, proto); + JSHandle jsWeakMap = JSHandle::Cast(factory->NewJSObject(weakMapClass)); + JSHandle weakLinkedMap(thread, LinkedHashMap::Create(thread)); + jsWeakMap->SetLinkedMap(thread, weakLinkedMap); + DUMP_FOR_HANDLE(jsWeakMap) + break; + } + case JSType::JS_WEAK_SET: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSWeakSet::SIZE, 1) + JSHandle weakSetClass = factory->NewEcmaDynClass(JSWeakSet::SIZE, JSType::JS_WEAK_SET, proto); + JSHandle jsWeakSet = JSHandle::Cast(factory->NewJSObject(weakSetClass)); + JSHandle weakLinkedSet(thread, LinkedHashSet::Create(thread)); + jsWeakSet->SetLinkedSet(thread, weakLinkedSet); + DUMP_FOR_HANDLE(jsWeakSet) + break; + } + case JSType::JS_DATE: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSDate::SIZE, 2) + JSHandle dateClass = factory->NewEcmaDynClass(JSDate::SIZE, JSType::JS_DATE, proto); + JSHandle date = JSHandle::Cast(factory->NewJSObject(dateClass)); + date->SetTimeValue(thread, JSTaggedValue(0.0)); + date->SetLocalOffset(thread, JSTaggedValue(0.0)); + DUMP_FOR_HANDLE(date) + break; + } + case JSType::JS_ITERATOR: + // JS Iterate is a tool class, so we don't need to check it. + break; + case JSType::JS_FORIN_ITERATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSForInIterator::SIZE, 4) + JSHandle array(thread, factory->NewJSArray().GetTaggedValue()); + JSHandle forInIter = factory->NewJSForinIterator(array); + DUMP_FOR_HANDLE(forInIter) + break; + } + case JSType::JS_MAP_ITERATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSMapIterator::SIZE, 3) + JSHandle jsMapIter = + factory->NewJSMapIterator(NewJSMap(thread, factory, proto), IterationKind::KEY); + DUMP_FOR_HANDLE(jsMapIter) + break; + } + case JSType::JS_SET_ITERATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSSetIterator::SIZE, 3) + JSHandle jsSetIter = + factory->NewJSSetIterator(NewJSSet(thread, factory, proto), IterationKind::KEY); + DUMP_FOR_HANDLE(jsSetIter) + break; + } + case JSType::JS_ARRAY_ITERATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSArrayIterator::SIZE, 3) + JSHandle arrayIter = + factory->NewJSArrayIterator(JSHandle::Cast(factory->NewJSArray()), IterationKind::KEY); + DUMP_FOR_HANDLE(arrayIter) + break; + } + case JSType::JS_STRING_ITERATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSStringIterator::SIZE, 2) + JSHandle stringIter = globalEnv->GetStringIterator(); + DUMP_FOR_HANDLE(stringIter) + break; + } + case JSType::JS_INTL: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSIntl::SIZE, 1) + NEW_OBJECT_AND_DUMP(JSIntl, JS_INTL) + break; + } + case JSType::JS_LOCALE: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSLocale::SIZE, 1) + NEW_OBJECT_AND_DUMP(JSLocale, JS_LOCALE) + break; + } + case JSType::JS_DATE_TIME_FORMAT: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSDateTimeFormat::SIZE, 11) + NEW_OBJECT_AND_DUMP(JSDateTimeFormat, JS_DATE_TIME_FORMAT) + break; + } + case JSType::JS_RELATIVE_TIME_FORMAT: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSRelativeTimeFormat::SIZE, 7) + NEW_OBJECT_AND_DUMP(JSRelativeTimeFormat, JS_RELATIVE_TIME_FORMAT) + break; + } + case JSType::JS_NUMBER_FORMAT: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSNumberFormat::SIZE, 20) + NEW_OBJECT_AND_DUMP(JSNumberFormat, JS_NUMBER_FORMAT) + break; + } + case JSType::JS_COLLATOR: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSCollator::SIZE, 9) + NEW_OBJECT_AND_DUMP(JSCollator, JS_COLLATOR) + break; + } + case JSType::JS_PLURAL_RULES: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSPluralRules::SIZE, 11) + NEW_OBJECT_AND_DUMP(JSPluralRules, JS_PLURAL_RULES) + break; + } + case JSType::JS_ARRAY_BUFFER: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSArrayBuffer::SIZE, 3) + NEW_OBJECT_AND_DUMP(JSArrayBuffer, JS_ARRAY_BUFFER) + break; + } + case JSType::JS_PROMISE: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSPromise::SIZE, 5) + NEW_OBJECT_AND_DUMP(JSPromise, JS_PROMISE) + break; + } + case JSType::JS_DATA_VIEW: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSDataView::SIZE, 4) + NEW_OBJECT_AND_DUMP(JSDataView, JS_DATA_VIEW) + break; + } + case JSType::JS_ARGUMENTS: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSArguments::SIZE, 1) + NEW_OBJECT_AND_DUMP(JSArguments, JS_ARGUMENTS) + break; + } + case JSType::JS_GENERATOR_OBJECT: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSGeneratorObject::SIZE, 4) + NEW_OBJECT_AND_DUMP(JSGeneratorObject, JS_GENERATOR_OBJECT) + break; + } + case JSType::JS_ASYNC_FUNC_OBJECT: { + CHECK_DUMP_FILEDS(JSGeneratorObject::SIZE, JSAsyncFuncObject::SIZE, 1) + JSHandle asyncFuncObject = factory->NewJSAsyncFuncObject(); + DUMP_FOR_HANDLE(asyncFuncObject) + break; + } + case JSType::JS_ARRAY: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSArray::SIZE, 1) + JSHandle jsArray = factory->NewJSArray(); + DUMP_FOR_HANDLE(jsArray) + break; + } + case JSType::JS_TYPED_ARRAY: + case JSType::JS_INT8_ARRAY: + case JSType::JS_UINT8_ARRAY: + case JSType::JS_UINT8_CLAMPED_ARRAY: + case JSType::JS_INT16_ARRAY: + case JSType::JS_UINT16_ARRAY: + case JSType::JS_INT32_ARRAY: + case JSType::JS_UINT32_ARRAY: + case JSType::JS_FLOAT32_ARRAY: + case JSType::JS_FLOAT64_ARRAY: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSTypedArray::SIZE, 5) + NEW_OBJECT_AND_DUMP(JSTypedArray, JS_TYPED_ARRAY) + break; + } + case JSType::JS_PRIMITIVE_REF: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSPrimitiveRef::SIZE, 1) + NEW_OBJECT_AND_DUMP(JSPrimitiveRef, JS_PRIMITIVE_REF) + break; + } + case JSType::JS_GLOBAL_OBJECT: { + CHECK_DUMP_FILEDS(JSObject::SIZE, JSGlobalObject::SIZE, 0) + JSHandle globalObject = globalEnv->GetJSGlobalObject(); + DUMP_FOR_HANDLE(globalObject) + break; + } + case JSType::JS_PROXY: { + CHECK_DUMP_FILEDS(ECMAObject::SIZE, JSProxy::SIZE, 3) + JSHandle emptyObj(thread, NewJSObject(thread, factory, globalEnv).GetTaggedValue()); + JSHandle proxy = factory->NewJSProxy(emptyObj, emptyObj); + DUMP_FOR_HANDLE(proxy) + break; + } + case JSType::HCLASS: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSHClass::SIZE, 9) + JSHandle hclass = factory->NewEcmaDynClass(JSHClass::SIZE, JSType::HCLASS, proto); + DUMP_FOR_HANDLE(hclass) + break; + } + case JSType::STRING: { + DUMP_FOR_HANDLE(globalEnv->GetObjectFunction()) + break; + } + case JSType::TAGGED_ARRAY: { + JSHandle taggedArray = factory->NewTaggedArray(4); + DUMP_FOR_HANDLE(taggedArray) + break; + } + case JSType::TAGGED_DICTIONARY: { + JSHandle dict = factory->NewDictionaryArray(4); + DUMP_FOR_HANDLE(dict) + break; + } + case JSType::FREE_OBJECT_WITH_ONE_FIELD: + case JSType::FREE_OBJECT_WITH_NONE_FIELD: + case JSType::FREE_OBJECT_WITH_TWO_FIELD: + { + break; + } + case JSType::JS_NATIVE_POINTER: { + break; + } + case JSType::GLOBAL_ENV: { + DUMP_FOR_HANDLE(globalEnv) + break; + } + case JSType::ACCESSOR_DATA: + case JSType::INTERNAL_ACCESSOR: { + CHECK_DUMP_FILEDS(Record::SIZE, AccessorData::SIZE, 2) + JSHandle accessor = factory->NewAccessorData(); + DUMP_FOR_HANDLE(accessor) + break; + } + case JSType::SYMBOL: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSSymbol::SIZE, 3) + JSHandle symbol = factory->NewJSSymbol(); + DUMP_FOR_HANDLE(symbol) + break; + } + case JSType::JS_GENERATOR_CONTEXT: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), GeneratorContext::SIZE, 7) + JSHandle genContext = factory->NewGeneratorContext(); + DUMP_FOR_HANDLE(genContext) + break; + } + case JSType::PROTOTYPE_HANDLER: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), PrototypeHandler::SIZE, 3) + JSHandle protoHandler = factory->NewPrototypeHandler(); + DUMP_FOR_HANDLE(protoHandler) + break; + } + case JSType::TRANSITION_HANDLER: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), TransitionHandler::SIZE, 2) + JSHandle transitionHandler = factory->NewTransitionHandler(); + DUMP_FOR_HANDLE(transitionHandler) + break; + } + case JSType::PROPERTY_BOX: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), PropertyBox::SIZE, 1) + JSHandle PropertyBox = factory->NewPropertyBox(globalEnv->GetEmptyArray()); + DUMP_FOR_HANDLE(PropertyBox) + break; + } + case JSType::PROTO_CHANGE_MARKER: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), ProtoChangeMarker::SIZE, 1) + JSHandle protoMaker = factory->NewProtoChangeMarker(); + DUMP_FOR_HANDLE(protoMaker) + break; + } + case JSType::PROTOTYPE_INFO: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), ProtoChangeDetails::SIZE, 2) + JSHandle protoDetails = factory->NewProtoChangeDetails(); + DUMP_FOR_HANDLE(protoDetails) + break; + } + case JSType::TEMPLATE_MAP: { + JSHandle templateMap = globalEnv->GetTemplateMap(); + DUMP_FOR_HANDLE(templateMap) + break; + } + case JSType::PROGRAM: { + CHECK_DUMP_FILEDS(ECMAObject::SIZE, Program::SIZE, 5) + JSHandle program = factory->NewProgram(); + DUMP_FOR_HANDLE(program) + break; + } + case JSType::LEXICAL_FUNCTION: { + CHECK_DUMP_FILEDS(ECMAObject::SIZE, LexicalFunction::SIZE, 5) + // unused + break; + } + case JSType::PROMISE_CAPABILITY: { + CHECK_DUMP_FILEDS(Record::SIZE, PromiseCapability::SIZE, 3) + JSHandle promiseCapa = factory->NewPromiseCapability(); + DUMP_FOR_HANDLE(promiseCapa) + break; + } + case JSType::PROMISE_RECORD: { + CHECK_DUMP_FILEDS(Record::SIZE, PromiseRecord::SIZE, 1) + JSHandle promiseRecord = factory->NewPromiseRecord(); + DUMP_FOR_HANDLE(promiseRecord) + break; + } + case JSType::RESOLVING_FUNCTIONS_RECORD: { + CHECK_DUMP_FILEDS(Record::SIZE, ResolvingFunctionsRecord::SIZE, 2) + JSHandle ResolvingFunc = factory->NewResolvingFunctionsRecord(); + DUMP_FOR_HANDLE(ResolvingFunc) + break; + } + case JSType::PROMISE_REACTIONS: { + CHECK_DUMP_FILEDS(Record::SIZE, PromiseReaction::SIZE, 3) + JSHandle promiseReact = factory->NewPromiseReaction(); + DUMP_FOR_HANDLE(promiseReact) + break; + } + case JSType::PROMISE_ITERATOR_RECORD: { + CHECK_DUMP_FILEDS(Record::SIZE, PromiseIteratorRecord::SIZE, 2) + JSHandle emptyObj(thread, NewJSObject(thread, factory, globalEnv).GetTaggedValue()); + JSHandle promiseIter = factory->NewPromiseIteratorRecord(emptyObj, emptyObj); + DUMP_FOR_HANDLE(promiseIter) + break; + } + case JSType::MICRO_JOB_QUEUE: { + CHECK_DUMP_FILEDS(Record::SIZE, ecmascript::job::MicroJobQueue::SIZE, 2) + JSHandle microJob = factory->NewMicroJobQueue(); + DUMP_FOR_HANDLE(microJob) + break; + } + case JSType::PENDING_JOB: { + CHECK_DUMP_FILEDS(Record::SIZE, ecmascript::job::PendingJob::SIZE, 2) + JSHandle pendingClass(thread, + JSHClass::Cast(globalConst->GetPendingJobClass().GetTaggedObject())); + JSHandle pendingJob(thread, factory->NewDynObject(pendingClass)); + DUMP_FOR_HANDLE(pendingJob) + break; + } + case JSType::FUNCTION_EXTRA_INFO: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSFunctionExtraInfo::SIZE, 2) + JSHandle funcExtraClass(thread, + JSHClass::Cast(globalConst->GetFunctionExtraInfoClass().GetTaggedObject())); + JSHandle funcInfo(thread, factory->NewDynObject(funcExtraClass)); + DUMP_FOR_HANDLE(funcInfo) + break; + } + case JSType::COMPLETION_RECORD: { + CHECK_DUMP_FILEDS(Record::SIZE, CompletionRecord::SIZE, 2) + JSHandle comRecord = factory->NewCompletionRecord(0, globalEnv->GetEmptyArray()); + DUMP_FOR_HANDLE(comRecord) + break; + } + case JSType::MACHINE_CODE_OBJECT: { + CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), MachineCode::DATA_OFFSET, 1) + JSHandle machineCode = factory->NewMachineCodeObject(16, nullptr); + DUMP_FOR_HANDLE(machineCode) + break; + } + case JSType::ECMA_MODULE: { + CHECK_DUMP_FILEDS(ECMAObject::SIZE, EcmaModule::SIZE, 1) + JSHandle ecmaModule = factory->NewEmptyEcmaModule(); + DUMP_FOR_HANDLE(ecmaModule) + break; + } + default: + LOG_ECMA_MEM(ERROR) << "JSType " << static_cast(type) << " cannot be dumped."; + UNREACHABLE(); + break; + } + } +#undef NEW_OBJECT_AND_DUMP +#undef DUMP_FOR_HANDLE +} } // namespace panda::test -- Gitee From 0592ed021e0a227bcff514ac935ef736dc714d78 Mon Sep 17 00:00:00 2001 From: Gongyuhang <517563583@qq.com> Date: Fri, 29 Oct 2021 19:09:17 +0800 Subject: [PATCH 104/115] add js_typed_array_test.cpp for JSTypedArray class Signed-off-by: Gongyuhang <517563583@qq.com> --- ecmascript/tests/BUILD.gn | 29 + ecmascript/tests/js_typed_array_test.cpp | 1332 ++++++++++++++++++++++ 2 files changed, 1361 insertions(+) create mode 100644 ecmascript/tests/js_typed_array_test.cpp diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index ce53651..bb90ff4 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -610,6 +610,33 @@ host_unittest_action("JsTaggedQueueTest") { } } +host_unittest_action("JsTypedArrayTest") { + module_out_path = module_output_path + + sources = [ + # test file + "js_typed_array_test.cpp", + ] + + configs = [ + "//ark/js_runtime:ecma_test_config", + "//ark/js_runtime:ark_jsruntime_public_config", # should add before + # arkruntime_public_config + "//ark/js_runtime:ark_jsruntime_common_config", + "$ark_root/runtime:arkruntime_public_config", + ] + + deps = [ + "$ark_root/libpandabase:libarkbase", + "//ark/js_runtime:libark_jsruntime_test", + sdk_libc_secshared_dep, + ] + + if (!is_standard_system) { + deps += [ "$ark_root/runtime:libarkruntime" ] + } +} + host_unittest_action("JsVerificationTest") { module_out_path = module_output_path @@ -993,6 +1020,7 @@ group("unittest") { ":JsSetTest", ":JsSymbolTest", ":JsTaggedQueueTest", + ":JsTypedArrayTest", ":JsVerificationTest", ":LexicalEnvTest", ":LinkedHashTableTest", @@ -1036,6 +1064,7 @@ group("host_unittest") { ":JsSetTestAction", ":JsSymbolTestAction", ":JsTaggedQueueTestAction", + ":JsTypedArrayTestAction", ":JsVerificationTestAction", ":LexicalEnvTestAction", ":LinkedHashTableTestAction", diff --git a/ecmascript/tests/js_typed_array_test.cpp b/ecmascript/tests/js_typed_array_test.cpp new file mode 100644 index 0000000..0d287d7 --- /dev/null +++ b/ecmascript/tests/js_typed_array_test.cpp @@ -0,0 +1,1332 @@ +/* + * 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/base/typed_array_helper-inl.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class JSTypedArrayTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + PandaVM *instance {nullptr}; + EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; + + const CVector cVecJSType { + JSType::JS_INT8_ARRAY, JSType::JS_UINT8_ARRAY, JSType::JS_UINT8_CLAMPED_ARRAY, + JSType::JS_INT16_ARRAY, JSType::JS_UINT16_ARRAY, + JSType::JS_INT32_ARRAY, JSType::JS_UINT32_ARRAY, + JSType::JS_FLOAT32_ARRAY, JSType::JS_FLOAT64_ARRAY}; + + // CVector pushed with JSTaggedValue made from compatible input value for the JSType + const CVector cVecHandleTagValValueForTypedArray { + // Use "(S)(...)" cast to make v in "JSTaggedValue(T v) : coretypes::TaggedValue(v) {}" compatible with S + JSTaggedValue((int8_t)(-111)), JSTaggedValue((uint8_t)(222)), JSTaggedValue((uint8_t)(222)), + JSTaggedValue((int16_t)(-31111)), JSTaggedValue((uint16_t)(61111)), + // int32 : -2147483648->2147483647, uint32 : 0->4294967295 + JSTaggedValue((int32_t)(2111111111)), JSTaggedValue((uint32_t)(4111111111)), + JSTaggedValue((float)(4321.1234)), JSTaggedValue((double)(987654321.123456789))}; +}; + +JSHandle CreateNumberTypedArray(JSThread *thread, JSType jsType) +{ + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + + JSHandle handleTagValFunc = env->GetInt8ArrayFunction(); + switch (jsType) { + case JSType::JS_INT8_ARRAY: + break; + case JSType::JS_UINT8_ARRAY: + handleTagValFunc = env->GetUint8ArrayFunction(); + break; + case JSType::JS_UINT8_CLAMPED_ARRAY: + handleTagValFunc = env->GetUint8ClampedArrayFunction(); + break; + case JSType::JS_INT16_ARRAY: + handleTagValFunc = env->GetInt16ArrayFunction(); + break; + case JSType::JS_UINT16_ARRAY: + handleTagValFunc = env->GetUint16ArrayFunction(); + break; + case JSType::JS_INT32_ARRAY: + handleTagValFunc = env->GetInt32ArrayFunction(); + break; + case JSType::JS_UINT32_ARRAY: + handleTagValFunc = env->GetUint32ArrayFunction(); + break; + case JSType::JS_FLOAT32_ARRAY: + handleTagValFunc = env->GetFloat32ArrayFunction(); + break; + case JSType::JS_FLOAT64_ARRAY: + handleTagValFunc = env->GetFloat64ArrayFunction(); + break; + default: + ASSERT_PRINT(false, "the second argument is a wrong JSType for CreateNumberTypedArray function"); + break; + } + + return JSHandle::Cast( + factory->NewJSObjectByConstructor(JSHandle::Cast(handleTagValFunc), handleTagValFunc)); +} + +/* + * Feature: JSTypedArray + * Function: ToPropKey + * SubFunction: EcmaString::GetCString + * FunctionPoints: TaggedType Signs To EcmaString Signs + * CaseDescription: Check whether the EcmaStrings transformed through calling ToPropKey function from TaggedTypes are + * within expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, ToPropKey_001) +{ + JSHandle handleUndefined(thread, JSTaggedValue::Undefined()); + JSHandle handleHole(thread, JSTaggedValue::Hole()); + JSHandle hnadleTagValEcmaStrPropKeyTo1 = JSTypedArray::ToPropKey(thread, handleUndefined); + JSHandle hnadleTagValEcmaStrPropKeyTo2 = JSTypedArray::ToPropKey(thread, handleHole); + JSHandle handleEcmaStrPropKeyTo1 = JSHandle::Cast(hnadleTagValEcmaStrPropKeyTo1); + JSHandle handleEcmaStrPropKeyTo2 = JSHandle::Cast(hnadleTagValEcmaStrPropKeyTo2); + EXPECT_NE(0, sizeof(handleUndefined)); + EXPECT_NE(0, sizeof(handleHole)); + std::unique_ptr uniCharArrTo1(handleEcmaStrPropKeyTo1->GetCString()); + std::unique_ptr uniCharArrTo2(handleEcmaStrPropKeyTo2->GetCString()); + EXPECT_EQ(uniCharArrTo1[0], 'u'); + EXPECT_EQ(uniCharArrTo1[1], 'n'); + EXPECT_EQ(uniCharArrTo1[2], 'd'); + EXPECT_EQ(uniCharArrTo1[3], 'e'); + EXPECT_EQ(uniCharArrTo1[4], 'f'); + EXPECT_EQ(uniCharArrTo1[5], 'i'); + EXPECT_EQ(uniCharArrTo1[6], 'n'); + EXPECT_EQ(uniCharArrTo1[7], 'e'); + EXPECT_EQ(uniCharArrTo1[8], 'd'); + EXPECT_EQ(uniCharArrTo1[9], 0); // "undefined" + EXPECT_EQ(uniCharArrTo2[0], 0); // "" +} + +/* + * Feature: JSTypedArray + * Function: ToPropKey + * SubFunction: EcmaString::GetCString + * FunctionPoints: Number Signs To EcmaString Signs + * CaseDescription: Check whether the EcmaStrings transformed through calling ToPropKey function from Numbers are + * within expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, ToPropKey_002) +{ + JSHandle handleTagVal1(thread, JSTaggedValue(0)); + JSHandle handleTagVal2(thread, JSTaggedValue(-1)); + JSHandle handleTagVal3(thread, JSTaggedValue(1.789)); + JSHandle handleTagVal4(thread, JSTaggedValue(-789.1)); + JSHandle hnadleTagValEcmaStrPropKeyTo1 = JSTypedArray::ToPropKey(thread, handleTagVal1); + JSHandle hnadleTagValEcmaStrPropKeyTo2 = JSTypedArray::ToPropKey(thread, handleTagVal2); + JSHandle hnadleTagValEcmaStrPropKeyTo3 = JSTypedArray::ToPropKey(thread, handleTagVal3); + JSHandle hnadleTagValEcmaStrPropKeyTo4 = JSTypedArray::ToPropKey(thread, handleTagVal4); + JSHandle handleEcmaStrPropKeyTo1 = JSHandle::Cast(hnadleTagValEcmaStrPropKeyTo1); + JSHandle handleEcmaStrPropKeyTo2 = JSHandle::Cast(hnadleTagValEcmaStrPropKeyTo2); + JSHandle handleEcmaStrPropKeyTo3 = JSHandle::Cast(hnadleTagValEcmaStrPropKeyTo3); + JSHandle handleEcmaStrPropKeyTo4 = JSHandle::Cast(hnadleTagValEcmaStrPropKeyTo4); + std::unique_ptr uniCharArrTo1(handleEcmaStrPropKeyTo1->GetCString()); + std::unique_ptr uniCharArrTo2(handleEcmaStrPropKeyTo2->GetCString()); + std::unique_ptr uniCharArrTo3(handleEcmaStrPropKeyTo3->GetCString()); + std::unique_ptr uniCharArrTo4(handleEcmaStrPropKeyTo4->GetCString()); + EXPECT_EQ(uniCharArrTo1[0], '0'); + EXPECT_EQ(uniCharArrTo1[1], 0); // "0" + EXPECT_EQ(uniCharArrTo2[0], '-'); + EXPECT_EQ(uniCharArrTo2[1], '1'); + EXPECT_EQ(uniCharArrTo2[2], 0); // "-1" + EXPECT_EQ(uniCharArrTo3[0], '1'); + EXPECT_EQ(uniCharArrTo3[1], '.'); + EXPECT_EQ(uniCharArrTo3[2], '7'); + EXPECT_EQ(uniCharArrTo3[3], '8'); + EXPECT_EQ(uniCharArrTo3[4], '9'); + EXPECT_EQ(uniCharArrTo3[5], 0); // "1.789" + EXPECT_EQ(uniCharArrTo4[0], '-'); + EXPECT_EQ(uniCharArrTo4[1], '7'); + EXPECT_EQ(uniCharArrTo4[2], '8'); + EXPECT_EQ(uniCharArrTo4[3], '9'); + EXPECT_EQ(uniCharArrTo4[4], '.'); + EXPECT_EQ(uniCharArrTo4[5], '1'); + EXPECT_EQ(uniCharArrTo4[6], 0); // "-789.1" +} + +/* + * Feature: JSTypedArray + * Function: CreateJSTypedArray(GlobalEnv::GetInt8ArrayFunction.../ObjectFactory::NewJSObjectByConstructor) + * SubFunction: JSTaggedValue::IsTypedArray/IsJSInt8Array... + * FunctionPoints: Create JSTypedArray(JSInt8Array...) + * CaseDescription: Check whether the bools returned through calling IsTypedArray/IsInt8Array... functions from the + * JSTypedArrays created through calling NewJSObjectByConstructor function are within expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, TypedArrayCreate) +{ + JSHandle handleInt8Array = CreateNumberTypedArray(thread, JSType::JS_INT8_ARRAY); + JSHandle handleTagValInt8Array = JSHandle::Cast(handleInt8Array); + EXPECT_TRUE(handleTagValInt8Array->IsJSInt8Array() && handleTagValInt8Array->IsTypedArray()); + + JSHandle handleUint8Array = CreateNumberTypedArray(thread, JSType::JS_UINT8_ARRAY); + JSHandle handleTagValUint8Array = JSHandle::Cast(handleUint8Array); + EXPECT_TRUE(handleTagValUint8Array->IsJSUint8Array() && handleTagValUint8Array->IsTypedArray()); + + JSHandle handleUint8ClampedArray = CreateNumberTypedArray(thread, JSType::JS_UINT8_CLAMPED_ARRAY); + JSHandle handleTagValUint8ClampedArray = JSHandle::Cast(handleUint8ClampedArray); + EXPECT_TRUE(handleTagValUint8ClampedArray->IsJSUint8ClampedArray() && + handleTagValUint8ClampedArray->IsTypedArray()); + + JSHandle handleInt16Array = CreateNumberTypedArray(thread, JSType::JS_INT16_ARRAY); + JSHandle handleTagValInt16Array = JSHandle::Cast(handleInt16Array); + EXPECT_TRUE(handleTagValInt16Array->IsJSInt16Array() && handleTagValInt16Array->IsTypedArray()); + + JSHandle handleUint16Array = CreateNumberTypedArray(thread, JSType::JS_UINT16_ARRAY); + JSHandle handleTagValUint16Array = JSHandle::Cast(handleUint16Array); + EXPECT_TRUE(handleTagValUint16Array->IsJSUint16Array() && handleTagValUint16Array->IsTypedArray()); + + JSHandle handleInt32Array = CreateNumberTypedArray(thread, JSType::JS_INT32_ARRAY); + JSHandle handleTagValInt32Array = JSHandle::Cast(handleInt32Array); + EXPECT_TRUE(handleTagValInt32Array->IsJSInt32Array() && handleTagValInt32Array->IsTypedArray()); + + JSHandle handleUint32Array = CreateNumberTypedArray(thread, JSType::JS_UINT32_ARRAY); + JSHandle handleTagValUint32Array = JSHandle::Cast(handleUint32Array); + EXPECT_TRUE(handleTagValUint32Array->IsJSUint32Array() && handleTagValUint32Array->IsTypedArray()); + + JSHandle handleFloat32Array = CreateNumberTypedArray(thread, JSType::JS_FLOAT32_ARRAY); + JSHandle handleTagValFloat32Array = JSHandle::Cast(handleFloat32Array); + EXPECT_TRUE(handleTagValFloat32Array->IsJSFloat32Array() && handleTagValFloat32Array->IsTypedArray()); + + JSHandle handleFloat64Array = CreateNumberTypedArray(thread, JSType::JS_FLOAT64_ARRAY); + JSHandle handleTagValFloat64Array = JSHandle::Cast(handleFloat64Array); + EXPECT_TRUE(handleTagValFloat64Array->IsJSFloat64Array() && handleTagValFloat64Array->IsTypedArray()); +} + +/* + * Feature: JSTypedArray + * Function: SetViewedArrayBuffer + * SubFunction: GetViewedArrayBuffer/ObjectFactory::NewJSArrayBuffer + * FunctionPoints: Set ViewedArrayBuffer + * CaseDescription: Check whether the JSArrayBuffer returned through calling GetViewedArrayBuffer function from the + * JSTypedArray changed through calling SetViewedArrayBuffer function is within expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, SetViewedArrayBuffer) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleArrayBufferFrom = factory->NewJSArrayBuffer(10); + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast(handleArrayBufferFrom); + + for (int i = 0; i < cVecJSType.size(); i++) { + JSHandle handleTypedArray = CreateNumberTypedArray(thread, cVecJSType.at(i)); + + EXPECT_EQ(handleTypedArray->GetViewedArrayBuffer(), JSTaggedValue::Undefined()); + handleTypedArray->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + EXPECT_EQ(handleTypedArray->GetViewedArrayBuffer(), handleTagValArrayBufferFrom.GetTaggedValue()); + } +} + +/* + * Feature: JSTypedArray + * Function: SetTypedArrayName + * SubFunction: GetTypedArrayName + * FunctionPoints: Set TypedArrayName + * CaseDescription: Check whether the JSTaggedValue returned through calling GetTypedArrayName function from the + * JSTypedArray changed through calling SetTypedArrayName function is within expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, SetTypedArrayName) +{ + CString cStrName = "cStrName"; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleEcmaStrNameFrom = factory->NewFromString(cStrName); + JSHandle handleTagValEcmaStrNameFrom = JSHandle::Cast(handleEcmaStrNameFrom); + + for (int i = 0; i < cVecJSType.size(); i++) { + JSHandle handleTypedArray = CreateNumberTypedArray(thread, cVecJSType.at(i)); + + EXPECT_EQ(handleTypedArray->GetTypedArrayName(), JSTaggedValue::Undefined()); + handleTypedArray->SetTypedArrayName(thread, handleTagValEcmaStrNameFrom); + EXPECT_EQ(handleTypedArray->GetTypedArrayName(), handleTagValEcmaStrNameFrom.GetTaggedValue()); + } +} + +/* + * Feature: JSTypedArray + * Function: SetByteLength + * SubFunction: GetByteLength + * FunctionPoints: Set ByteLength + * CaseDescription: Check whether the Number returned through calling GetByteLength function from the JSTypedArray + * changed through calling SetByteLength function is within expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, SetByteLength) +{ + uint32_t u32ByteLength = 2; + JSHandle handleTagValByteLengthFrom(thread, JSTaggedValue(u32ByteLength)); + + for (int i = 0; i < cVecJSType.size(); i++) { + JSHandle handleTypedArray = CreateNumberTypedArray(thread, cVecJSType.at(i)); + + EXPECT_EQ(handleTypedArray->GetByteLength(), JSTaggedValue(0)); + handleTypedArray->SetByteLength(thread, handleTagValByteLengthFrom); + EXPECT_EQ(handleTypedArray->GetByteLength(), handleTagValByteLengthFrom.GetTaggedValue()); + } +} + +/* + * Feature: JSTypedArray + * Function: SetByteOffset + * SubFunction: GetByteOffset + * FunctionPoints: Set ByteOffset + * CaseDescription: Check whether the Number returned through calling GetByteOffset function from the JSTypedArray + * changed through calling SetByteOffset function is within expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, SetByteOffset) +{ + uint32_t u32ByteOffset = 2; + JSHandle handleTagValByteOffsetFrom(thread, JSTaggedValue(u32ByteOffset)); + + for (int i = 0; i < cVecJSType.size(); i++) { + JSHandle handleTypedArray = CreateNumberTypedArray(thread, cVecJSType.at(i)); + + EXPECT_EQ(handleTypedArray->GetByteOffset(), JSTaggedValue(0)); + handleTypedArray->SetByteOffset(thread, handleTagValByteOffsetFrom); + EXPECT_EQ(handleTypedArray->GetByteOffset(), handleTagValByteOffsetFrom.GetTaggedValue()); + } +} + +/* + * Feature: JSTypedArray + * Function: SetArrayLength + * SubFunction: GetArrayLength + * FunctionPoints: Set ArrayLength + * CaseDescription: Check whether the Number returned through calling GetArrayLength function from the JSTypedArray + * changed through calling SetArrayLength function is within expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, SetArrayLength) +{ + uint32_t u32ArrayLength = 2; + JSHandle handleTagValArrayLengthFrom(thread, JSTaggedValue(u32ArrayLength)); + + for (int i = 0; i < cVecJSType.size(); i++) { + JSHandle handleTypedArray = CreateNumberTypedArray(thread, cVecJSType.at(i)); + + EXPECT_EQ(handleTypedArray->GetArrayLength(), JSTaggedValue(0)); + handleTypedArray->SetArrayLength(thread, handleTagValArrayLengthFrom); + EXPECT_EQ(handleTypedArray->GetArrayLength(), handleTagValArrayLengthFrom.GetTaggedValue()); + } +} + +/* + * Feature: JSTypedArray + * Function: IntegerIndexedElementSet + * SubFunction: IntegerIndexedElementGet + * FunctionPoints: Set Element At Integer Index(JSTaggedValue) Of JSTypedArray + * CaseDescription: Check whether the OperationResults returned through calling IntegerIndexedElementGet function from + * the JSTypedArray changed through calling IntegerIndexedElementSet function are within expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Int8Array_001) +{ + uint32_t numElementsInt8Array = 256; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleInt8Array = CreateNumberTypedArray(thread, JSType::JS_INT8_ARRAY); + JSHandle handleTagValInt8Array = JSHandle::Cast(handleInt8Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleInt8Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsInt8Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleInt8Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleInt8Array->SetArrayLength(thread, JSTaggedValue(numElementsInt8Array)); + + CVector cVecOpResult = {}; + for (int32_t i = 0; i < numElementsInt8Array; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt8Array, JSTaggedValue(i), + JSHandle(thread, JSTaggedValue(std::numeric_limits::min() + i)))); + OperationResult opResult = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt8Array, + JSTaggedValue(i)); + cVecOpResult.push_back(opResult); + } + for (int32_t i = 0; i < numElementsInt8Array; i++) { + EXPECT_EQ(cVecOpResult.at(i).GetValue().GetTaggedValue().GetNumber(), std::numeric_limits::min() + i); + } + cVecOpResult.clear(); + + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt8Array, + JSTaggedValue(-1)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt8Array, + JSTaggedValue(-0.0)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt8Array, + JSTaggedValue(1.1)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt8Array, + JSTaggedValue(numElementsInt8Array)); + EXPECT_EQ(opResult1.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult2.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult3.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult4.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt8Array, JSTaggedValue(-1), + JSHandle(thread, JSTaggedValue(0)))); + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt8Array, + JSTaggedValue(numElementsInt8Array), JSHandle(thread, JSTaggedValue(0)))); +} + +// Nonstandard input value for Int8Array +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Int8Array_002) +{ + uint32_t numElementsInt8Array = 16; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleInt8Array = CreateNumberTypedArray(thread, JSType::JS_INT8_ARRAY); + JSHandle handleTagValInt8Array = JSHandle::Cast(handleInt8Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleInt8Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsInt8Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleInt8Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleInt8Array->SetArrayLength(thread, JSTaggedValue(numElementsInt8Array)); + + int64_t value1 = -129; // to int8 : 127 + int64_t value2 = 128; // to int8 : -128 + double value3 = 13.4; // to int8 : 13 + double value4 = 13.6; // to int8 : 13 + JSHandle handleTagValValueSet1(thread, JSTaggedValue(value1)); + JSHandle handleTagValValueSet2(thread, JSTaggedValue(value2)); + JSHandle handleTagValValueSet3(thread, JSTaggedValue(value3)); + JSHandle handleTagValValueSet4(thread, JSTaggedValue(value4)); + + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt8Array, JSTaggedValue(0), + handleTagValValueSet1)); + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt8Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt8Array, JSTaggedValue(0), + handleTagValValueSet2)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt8Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt8Array, JSTaggedValue(0), + handleTagValValueSet3)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt8Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt8Array, JSTaggedValue(0), + handleTagValValueSet4)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt8Array, + JSTaggedValue(0)); + + EXPECT_NE(value1, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value2, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value3, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value4, opResult4.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(127, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(-128, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult4.GetValue().GetTaggedValue().GetNumber()); +} + +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Uint8Array_001) +{ + uint32_t numElementsUint8Array = 256; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleUint8Array = CreateNumberTypedArray(thread, JSType::JS_UINT8_ARRAY); + JSHandle handleTagValUint8Array = JSHandle::Cast(handleUint8Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleUint8Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsUint8Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleUint8Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleUint8Array->SetArrayLength(thread, JSTaggedValue(numElementsUint8Array)); + + CVector cVecOpResult = {}; + for (uint32_t i = 0; i < numElementsUint8Array; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8Array, JSTaggedValue(i), + JSHandle(thread, JSTaggedValue(std::numeric_limits::min() + i)))); + OperationResult opResult = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8Array, + JSTaggedValue(i)); + cVecOpResult.push_back(opResult); + } + for (uint32_t i = 0; i < numElementsUint8Array; i++) { + EXPECT_EQ(cVecOpResult.at(i).GetValue().GetTaggedValue().GetNumber(), std::numeric_limits::min() + i); + } + cVecOpResult.clear(); + + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8Array, + JSTaggedValue(-1)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8Array, + JSTaggedValue(-0.0)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8Array, + JSTaggedValue(1.1)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8Array, + JSTaggedValue(numElementsUint8Array)); + EXPECT_EQ(opResult1.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult2.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult3.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult4.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8Array, JSTaggedValue(-1), + JSHandle(thread, JSTaggedValue(0)))); + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8Array, + JSTaggedValue(numElementsUint8Array), JSHandle(thread, JSTaggedValue(0)))); +} + +// Nonstandard input value for Uint8Array +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Uint8Array_002) +{ + uint32_t numElementsUint8Array = 16; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleUint8Array = CreateNumberTypedArray(thread, JSType::JS_UINT8_ARRAY); + JSHandle handleTagValUint8Array = JSHandle::Cast(handleUint8Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleUint8Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsUint8Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleUint8Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleUint8Array->SetArrayLength(thread, JSTaggedValue(numElementsUint8Array)); + + int64_t value1 = -1; // to uint8 : 255 + int64_t value2 = 256; // to uint8 : 0 + double value3 = 13.4; // to uint8 : 13 + double value4 = 13.6; // to uint8 : 13 + JSHandle handleTagValValueSet1(thread, JSTaggedValue(value1)); + JSHandle handleTagValValueSet2(thread, JSTaggedValue(value2)); + JSHandle handleTagValValueSet3(thread, JSTaggedValue(value3)); + JSHandle handleTagValValueSet4(thread, JSTaggedValue(value4)); + + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8Array, JSTaggedValue(0), + handleTagValValueSet1)); + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8Array, JSTaggedValue(0), + handleTagValValueSet2)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8Array, JSTaggedValue(0), + handleTagValValueSet3)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8Array, JSTaggedValue(0), + handleTagValValueSet4)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8Array, + JSTaggedValue(0)); + + EXPECT_NE(value1, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value2, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value3, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value4, opResult4.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(255, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(0, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult4.GetValue().GetTaggedValue().GetNumber()); +} + +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Uint8ClampedArray_001) +{ + uint32_t numElementsUint8ClampedArray = 256; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleUint8ClampedArray = CreateNumberTypedArray(thread, JSType::JS_UINT8_CLAMPED_ARRAY); + JSHandle handleTagValUint8ClampedArray = JSHandle::Cast(handleUint8ClampedArray); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleUint8ClampedArray)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsUint8ClampedArray; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleUint8ClampedArray->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleUint8ClampedArray->SetArrayLength(thread, JSTaggedValue(numElementsUint8ClampedArray)); + + CVector cVecOpResult = {}; + for (uint32_t i = 0; i < numElementsUint8ClampedArray; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8ClampedArray, JSTaggedValue(i), + JSHandle(thread, JSTaggedValue(std::numeric_limits::min() + i)))); + OperationResult opResult = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8ClampedArray, + JSTaggedValue(i)); + cVecOpResult.push_back(opResult); + } + for (uint32_t i = 0; i < numElementsUint8ClampedArray; i++) { + EXPECT_EQ(cVecOpResult.at(i).GetValue().GetTaggedValue().GetNumber(), std::numeric_limits::min() + i); + } + cVecOpResult.clear(); + + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8ClampedArray, + JSTaggedValue(-1)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8ClampedArray, + JSTaggedValue(-0.0)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8ClampedArray, + JSTaggedValue(1.1)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8ClampedArray, + JSTaggedValue(numElementsUint8ClampedArray)); + EXPECT_EQ(opResult1.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult2.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult3.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult4.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8ClampedArray, JSTaggedValue(-1), + JSHandle(thread, JSTaggedValue(0)))); + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8ClampedArray, + JSTaggedValue(numElementsUint8ClampedArray), JSHandle(thread, JSTaggedValue(0)))); +} + +// Nonstandard input value for Uint8ClampedArray +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Uint8ClampedArray_002) +{ + uint32_t numElementsUint8ClampedArray = 16; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleUint8ClampedArray = CreateNumberTypedArray(thread, JSType::JS_UINT8_CLAMPED_ARRAY); + JSHandle handleTagValUint8ClampedArray = JSHandle::Cast(handleUint8ClampedArray); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleUint8ClampedArray)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsUint8ClampedArray; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleUint8ClampedArray->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleUint8ClampedArray->SetArrayLength(thread, JSTaggedValue(numElementsUint8ClampedArray)); + + int64_t value1 = -1; // to uint8_clamped : 0 + int64_t value2 = 256; // to uint8_clamped : 255 + double value3 = 13.4; // to uint8_clamped : 13 + double value4 = 13.6; // to uint8_clamped : 14 + JSHandle handleTagValValueSet1(thread, JSTaggedValue(value1)); + JSHandle handleTagValValueSet2(thread, JSTaggedValue(value2)); + JSHandle handleTagValValueSet3(thread, JSTaggedValue(value3)); + JSHandle handleTagValValueSet4(thread, JSTaggedValue(value4)); + + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8ClampedArray, JSTaggedValue(0), + handleTagValValueSet1)); + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8ClampedArray, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8ClampedArray, JSTaggedValue(0), + handleTagValValueSet2)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8ClampedArray, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8ClampedArray, JSTaggedValue(0), + handleTagValValueSet3)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8ClampedArray, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint8ClampedArray, JSTaggedValue(0), + handleTagValValueSet4)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint8ClampedArray, + JSTaggedValue(0)); + + EXPECT_NE(value1, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value2, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value3, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value4, opResult4.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(0, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(255, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(14, opResult4.GetValue().GetTaggedValue().GetNumber()); +} + +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Int16Array_001) +{ + uint32_t numElementsInt16Array = 100; + int16_t scaleForInt16ValueSet = 100; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleInt16Array = CreateNumberTypedArray(thread, JSType::JS_INT16_ARRAY); + JSHandle handleTagValInt16Array = JSHandle::Cast(handleInt16Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleInt16Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsInt16Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleInt16Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleInt16Array->SetArrayLength(thread, JSTaggedValue(numElementsInt16Array)); + + CVector cVecOpResult = {}; + for (int32_t i = 0; i < numElementsInt16Array; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt16Array, JSTaggedValue(i), + JSHandle(thread, + JSTaggedValue(std::numeric_limits::min() + i * scaleForInt16ValueSet)))); + OperationResult opResult = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt16Array, + JSTaggedValue(i)); + cVecOpResult.push_back(opResult); + } + for (int32_t i = 0; i < numElementsInt16Array; i++) { + EXPECT_EQ(cVecOpResult.at(i).GetValue().GetTaggedValue().GetNumber(), + std::numeric_limits::min() + i * scaleForInt16ValueSet); + } + cVecOpResult.clear(); + + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt16Array, + JSTaggedValue(-1)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt16Array, + JSTaggedValue(-0.0)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt16Array, + JSTaggedValue(1.1)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt16Array, + JSTaggedValue(numElementsInt16Array)); + EXPECT_EQ(opResult1.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult2.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult3.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult4.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt16Array, JSTaggedValue(-1), + JSHandle(thread, JSTaggedValue(0)))); + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt16Array, + JSTaggedValue(numElementsInt16Array), JSHandle(thread, JSTaggedValue(0)))); +} + +// Nonstandard input value for Int16Array +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Int16Array_002) +{ + uint32_t numElementsInt16Array = 16; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleInt16Array = CreateNumberTypedArray(thread, JSType::JS_INT16_ARRAY); + JSHandle handleTagValInt16Array = JSHandle::Cast(handleInt16Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleInt16Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsInt16Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleInt16Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleInt16Array->SetArrayLength(thread, JSTaggedValue(numElementsInt16Array)); + + int64_t value1 = -32769; // to int16 : 32767 + int64_t value2 = 32768; // to int16 : -32768 + double value3 = 13.4; // to int16 : 13 + double value4 = 13.6; // to int16 : 13 + JSHandle handleTagValValueSet1(thread, JSTaggedValue(value1)); + JSHandle handleTagValValueSet2(thread, JSTaggedValue(value2)); + JSHandle handleTagValValueSet3(thread, JSTaggedValue(value3)); + JSHandle handleTagValValueSet4(thread, JSTaggedValue(value4)); + + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt16Array, JSTaggedValue(0), + handleTagValValueSet1)); + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt16Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt16Array, JSTaggedValue(0), + handleTagValValueSet2)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt16Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt16Array, JSTaggedValue(0), + handleTagValValueSet3)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt16Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt16Array, JSTaggedValue(0), + handleTagValValueSet4)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt16Array, + JSTaggedValue(0)); + + EXPECT_NE(value1, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value2, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value3, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value4, opResult4.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(32767, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(-32768, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult4.GetValue().GetTaggedValue().GetNumber()); +} + +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Uint16Array_001) +{ + uint32_t numElementsUint16Array = 100; + uint32_t scaleForUint16ValueSet = 100; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleUint16Array = CreateNumberTypedArray(thread, JSType::JS_UINT16_ARRAY); + JSHandle handleTagValUint16Array = JSHandle::Cast(handleUint16Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleUint16Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsUint16Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleUint16Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleUint16Array->SetArrayLength(thread, JSTaggedValue(numElementsUint16Array)); + + CVector cVecOpResult = {}; + for (uint32_t i = 0; i < numElementsUint16Array; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint16Array, JSTaggedValue(i), + JSHandle(thread, + JSTaggedValue(std::numeric_limits::min() + i * scaleForUint16ValueSet)))); + OperationResult opResult = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint16Array, + JSTaggedValue(i)); + cVecOpResult.push_back(opResult); + } + for (uint32_t i = 0; i < numElementsUint16Array; i++) { + EXPECT_EQ(cVecOpResult.at(i).GetValue().GetTaggedValue().GetNumber(), + std::numeric_limits::min() + i * scaleForUint16ValueSet); + } + cVecOpResult.clear(); + + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint16Array, + JSTaggedValue(-1)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint16Array, + JSTaggedValue(-0.0)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint16Array, + JSTaggedValue(1.1)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint16Array, + JSTaggedValue(numElementsUint16Array)); + EXPECT_EQ(opResult1.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult2.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult3.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult4.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint16Array, JSTaggedValue(-1), + JSHandle(thread, JSTaggedValue(0)))); + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint16Array, + JSTaggedValue(numElementsUint16Array), JSHandle(thread, JSTaggedValue(0)))); +} + +// Nonstandard input value for Uint16Array +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Uint16Array_002) +{ + uint32_t numElementsUint16Array = 16; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleUint16Array = CreateNumberTypedArray(thread, JSType::JS_UINT16_ARRAY); + JSHandle handleTagValUint16Array = JSHandle::Cast(handleUint16Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleUint16Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsUint16Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleUint16Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleUint16Array->SetArrayLength(thread, JSTaggedValue(numElementsUint16Array)); + + int64_t value1 = -1; // to uint16 : 65535 + int64_t value2 = 65536; // to uint16 : 0 + double value3 = 13.4; // to uint16 : 13 + double value4 = 13.6; // to uint16 : 13 + JSHandle handleTagValValueSet1(thread, JSTaggedValue(value1)); + JSHandle handleTagValValueSet2(thread, JSTaggedValue(value2)); + JSHandle handleTagValValueSet3(thread, JSTaggedValue(value3)); + JSHandle handleTagValValueSet4(thread, JSTaggedValue(value4)); + + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint16Array, JSTaggedValue(0), + handleTagValValueSet1)); + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint16Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint16Array, JSTaggedValue(0), + handleTagValValueSet2)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint16Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint16Array, JSTaggedValue(0), + handleTagValValueSet3)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint16Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint16Array, JSTaggedValue(0), + handleTagValValueSet4)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint16Array, + JSTaggedValue(0)); + + EXPECT_NE(value1, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value2, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value3, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value4, opResult4.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(65535, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(0, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult4.GetValue().GetTaggedValue().GetNumber()); +} + +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Int32Array_001) +{ + uint32_t numElementsInt32Array = 100; + int32_t scaleForInt32ValueSet = 100000; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleInt32Array = CreateNumberTypedArray(thread, JSType::JS_INT32_ARRAY); + JSHandle handleTagValInt32Array = JSHandle::Cast(handleInt32Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleInt32Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsInt32Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleInt32Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleInt32Array->SetArrayLength(thread, JSTaggedValue(numElementsInt32Array)); + + CVector cVecOpResult = {}; + for (int32_t i = 0; i < numElementsInt32Array; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt32Array, JSTaggedValue(i), + JSHandle(thread, + JSTaggedValue(std::numeric_limits::min() + i * scaleForInt32ValueSet)))); + OperationResult opResult = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt32Array, + JSTaggedValue(i)); + cVecOpResult.push_back(opResult); + } + for (int32_t i = 0; i < numElementsInt32Array; i++) { + EXPECT_EQ(cVecOpResult.at(i).GetValue().GetTaggedValue().GetNumber(), + std::numeric_limits::min() + i * scaleForInt32ValueSet); + } + cVecOpResult.clear(); + + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt32Array, + JSTaggedValue(-1)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt32Array, + JSTaggedValue(-0.0)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt32Array, + JSTaggedValue(1.1)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt32Array, + JSTaggedValue(numElementsInt32Array)); + EXPECT_EQ(opResult1.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult2.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult3.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult4.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt32Array, JSTaggedValue(-1), + JSHandle(thread, JSTaggedValue(0)))); + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt32Array, + JSTaggedValue(numElementsInt32Array), JSHandle(thread, JSTaggedValue(0)))); +} + +// Nonstandard input value for Int32Array +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Int32Array_002) +{ + uint32_t numElementsInt32Array = 16; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleInt32Array = CreateNumberTypedArray(thread, JSType::JS_INT32_ARRAY); + JSHandle handleTagValInt32Array = JSHandle::Cast(handleInt32Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleInt32Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsInt32Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleInt32Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleInt32Array->SetArrayLength(thread, JSTaggedValue(numElementsInt32Array)); + + int64_t value1 = -2147483649; // to int32 : 2147483647 + int64_t value2 = 2147483648; // to int32 : -2147483648 + double value3 = 13.4; // to int32 : 13 + double value4 = 13.6; // to int32 : 13 + JSHandle handleTagValValueSet1(thread, JSTaggedValue(value1)); + JSHandle handleTagValValueSet2(thread, JSTaggedValue(value2)); + JSHandle handleTagValValueSet3(thread, JSTaggedValue(value3)); + JSHandle handleTagValValueSet4(thread, JSTaggedValue(value4)); + + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt32Array, JSTaggedValue(0), + handleTagValValueSet1)); + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt32Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt32Array, JSTaggedValue(0), + handleTagValValueSet2)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt32Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt32Array, JSTaggedValue(0), + handleTagValValueSet3)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt32Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValInt32Array, JSTaggedValue(0), + handleTagValValueSet4)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValInt32Array, + JSTaggedValue(0)); + + EXPECT_NE(value1, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value2, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value3, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value4, opResult4.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(2147483647, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(-2147483648, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult4.GetValue().GetTaggedValue().GetNumber()); +} + +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Uint32Array_001) +{ + uint32_t numElementsUint32Array = 100; + uint32_t scaleForUint32ValueSet = 100000; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleUint32Array = CreateNumberTypedArray(thread, JSType::JS_UINT32_ARRAY); + JSHandle handleTagValUint32Array = JSHandle::Cast(handleUint32Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleUint32Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsUint32Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleUint32Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleUint32Array->SetArrayLength(thread, JSTaggedValue(numElementsUint32Array)); + + CVector cVecOpResult = {}; + for (uint32_t i = 0; i < numElementsUint32Array; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint32Array, JSTaggedValue(i), + JSHandle(thread, + JSTaggedValue(std::numeric_limits::min() + i * scaleForUint32ValueSet)))); + OperationResult opResult = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint32Array, + JSTaggedValue(i)); + cVecOpResult.push_back(opResult); + } + for (uint32_t i = 0; i < numElementsUint32Array; i++) { + EXPECT_EQ(cVecOpResult.at(i).GetValue().GetTaggedValue().GetNumber(), + std::numeric_limits::min() + i * scaleForUint32ValueSet); + } + cVecOpResult.clear(); + + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint32Array, + JSTaggedValue(-1)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint32Array, + JSTaggedValue(-0.0)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint32Array, + JSTaggedValue(1.1)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint32Array, + JSTaggedValue(numElementsUint32Array)); + EXPECT_EQ(opResult1.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult2.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult3.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult4.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint32Array, JSTaggedValue(-1), + JSHandle(thread, JSTaggedValue(0)))); + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint32Array, + JSTaggedValue(numElementsUint32Array), JSHandle(thread, JSTaggedValue(0)))); +} + +// Nonstandard input value for Uint32Array +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Uint32Array_002) +{ + int32_t numElementsUint32Array = 16; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleUint32Array = CreateNumberTypedArray(thread, JSType::JS_UINT32_ARRAY); + JSHandle handleTagValUint32Array = JSHandle::Cast(handleUint32Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleUint32Array)); + int32_t byteLengthViewdArrayBuffer = sizeElement * numElementsUint32Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleUint32Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleUint32Array->SetArrayLength(thread, JSTaggedValue(numElementsUint32Array)); + + int64_t value1 = -1; // to uint32 : 4294967295 + int64_t value2 = 4294967296; // to uint32 : 0 + double value3 = 13.4; // to uint32 : 13 + double value4 = 13.6; // to uint32 : 13 + JSHandle handleTagValValueSet1(thread, JSTaggedValue(value1)); + JSHandle handleTagValValueSet2(thread, JSTaggedValue(value2)); + JSHandle handleTagValValueSet3(thread, JSTaggedValue(value3)); + JSHandle handleTagValValueSet4(thread, JSTaggedValue(value4)); + + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint32Array, JSTaggedValue(0), + handleTagValValueSet1)); + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint32Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint32Array, JSTaggedValue(0), + handleTagValValueSet2)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint32Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint32Array, JSTaggedValue(0), + handleTagValValueSet3)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint32Array, + JSTaggedValue(0)); + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValUint32Array, JSTaggedValue(0), + handleTagValValueSet4)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValUint32Array, + JSTaggedValue(0)); + + EXPECT_NE(value1, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value2, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value3, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_NE(value4, opResult4.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(4294967295, opResult1.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(0, opResult2.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult3.GetValue().GetTaggedValue().GetNumber()); + EXPECT_EQ(13, opResult4.GetValue().GetTaggedValue().GetNumber()); +} + +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Float32Array) +{ + uint32_t numElementsFloat32Array = 100; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleFloat32Array = CreateNumberTypedArray(thread, JSType::JS_FLOAT32_ARRAY); + JSHandle handleTagValFloat32Array = JSHandle::Cast(handleFloat32Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleFloat32Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsFloat32Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleFloat32Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleFloat32Array->SetArrayLength(thread, JSTaggedValue(numElementsFloat32Array)); + + CVector cVecOpResult = {}; + float floatMaxValue = std::numeric_limits::max(); + for (uint32_t i = 0; i < numElementsFloat32Array; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValFloat32Array, JSTaggedValue(i), + JSHandle(thread, + JSTaggedValue(floatMaxValue - (i * (floatMaxValue / numElementsFloat32Array)))))); + OperationResult opResult = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValFloat32Array, + JSTaggedValue(i)); + cVecOpResult.push_back(opResult); + } + for (uint32_t i = 0; i < numElementsFloat32Array; i++) { + EXPECT_EQ(cVecOpResult.at(i).GetValue().GetTaggedValue().GetNumber(), + floatMaxValue - (i * (floatMaxValue / numElementsFloat32Array))); + } + cVecOpResult.clear(); + + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValFloat32Array, + JSTaggedValue(-1)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValFloat32Array, + JSTaggedValue(-0.0)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValFloat32Array, + JSTaggedValue(1.1)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValFloat32Array, + JSTaggedValue(numElementsFloat32Array)); + EXPECT_EQ(opResult1.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult2.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult3.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult4.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValFloat32Array, JSTaggedValue(-1), + JSHandle(thread, JSTaggedValue(0)))); + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValFloat32Array, + JSTaggedValue(numElementsFloat32Array), JSHandle(thread, JSTaggedValue(0)))); +} + +HWTEST_F_L0(JSTypedArrayTest, IntegerIndexedElementSet_Float64Array) +{ + uint32_t numElementsFloat64Array = 100; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleFloat64Array = CreateNumberTypedArray(thread, JSType::JS_FLOAT64_ARRAY); + JSHandle handleTagValFloat64Array = JSHandle::Cast(handleFloat64Array); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleFloat64Array)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsFloat64Array; + JSHandle handleTagValArrayBufferFrom = JSHandle::Cast( + factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleFloat64Array->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleFloat64Array->SetArrayLength(thread, JSTaggedValue(numElementsFloat64Array)); + + CVector cVecOpResult = {}; + double doubleMaxValue = std::numeric_limits::max(); + for (uint32_t i = 0; i < numElementsFloat64Array; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValFloat64Array, JSTaggedValue(i), + JSHandle(thread, JSTaggedValue( + doubleMaxValue - (i * (doubleMaxValue / numElementsFloat64Array)))))); + OperationResult opResult = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValFloat64Array, + JSTaggedValue(i)); + cVecOpResult.push_back(opResult); + } + for (uint32_t i = 0; i < numElementsFloat64Array; i++) { + EXPECT_EQ(cVecOpResult.at(i).GetValue().GetTaggedValue().GetNumber(), + doubleMaxValue - (i * (doubleMaxValue / numElementsFloat64Array))); + } + cVecOpResult.clear(); + + OperationResult opResult1 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValFloat64Array, + JSTaggedValue(-1)); + OperationResult opResult2 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValFloat64Array, + JSTaggedValue(-0.0)); + OperationResult opResult3 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValFloat64Array, + JSTaggedValue(1.1)); + OperationResult opResult4 = JSTypedArray::IntegerIndexedElementGet(thread, handleTagValFloat64Array, + JSTaggedValue(numElementsFloat64Array)); + EXPECT_EQ(opResult1.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult2.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult3.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult4.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValFloat64Array, JSTaggedValue(-1), + JSHandle(thread, JSTaggedValue(0)))); + EXPECT_FALSE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValFloat64Array, + JSTaggedValue(numElementsFloat64Array), JSHandle(thread, JSTaggedValue(0)))); +} + +/* + * Feature: JSTypedArray + * Function: FastElementGet + * SubFunction: IntegerIndexedElementSet + * FunctionPoints: Get Element At Index(uint32_t) Of JSTypedArray + * CaseDescription: Check whether the OperationResults returned through calling FastElementGet function from the + * JSTypedArray changed through calling IntegerIndexedElementSet function are within expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, FastElementGet_TypedArray) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + + for (uint32_t j = 0; j < cVecJSType.size(); j++) { + uint32_t numElementsTypedArray = 10; + JSHandle handleTypedArray = CreateNumberTypedArray(thread, cVecJSType.at(j)); + JSHandle handleTagValTypedArray = JSHandle::Cast(handleTypedArray); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleTypedArray)); + uint32_t byteLengthViewdArrayBuffer = sizeElement * numElementsTypedArray; + JSHandle handleTagValArrayBufferFrom = + JSHandle::Cast(factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleTypedArray->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleTypedArray->SetArrayLength(thread, JSTaggedValue(numElementsTypedArray)); + + JSHandle handleTagValValueSet(thread, JSTaggedValue(cVecHandleTagValValueForTypedArray.at(j))); + for (uint32_t i = 0; i < numElementsTypedArray; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValTypedArray, JSTaggedValue(i), + handleTagValValueSet)); + } + for (uint32_t i = 0; i < numElementsTypedArray; i++) { + OperationResult opResult = JSTypedArray::FastElementGet(thread, handleTagValTypedArray, i); + EXPECT_EQ(opResult.GetValue().GetTaggedValue().GetNumber(), + handleTagValValueSet.GetTaggedValue().GetNumber()); + } + + OperationResult opResult1 = JSTypedArray::FastElementGet(thread, handleTagValTypedArray, -1); + OperationResult opResult2 = JSTypedArray::FastElementGet(thread, handleTagValTypedArray, + numElementsTypedArray); + EXPECT_EQ(opResult1.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(opResult2.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()); + } +} + +/* + * Feature: JSTypedArray + * Function: DefineOwnProperty + * SubFunction: GetOwnProperty/HasProperty + * PropertyDescriptor::HasWritable/HasEnumerable/HasConfigurable/IsWritable/IsEnumerable/IsConfigurable + * FunctionPoints: Define Own Property For Element At Index(JSTaggedValue) Of JSTypedArray + * CaseDescription: Call DefineOwnProperty function with a JSTypedArray, a index(JSTaggedValue) and a source + * PropertyDescriptor, check whether the bool returned through calling HasProperty function with the + * JSTypedArray and the index(JSTaggedValue) is within expectations, check whether the target + * PropertyDescriptor changed through GetOwnProperty function is with expectations. + */ +HWTEST_F_L0(JSTypedArrayTest, DefineOwnProperty_TypedArray) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + + for (int j = 0; j < cVecJSType.size(); j++) { + int32_t numElementsTypedArray = 10; + JSHandle handleTagValValueDef(thread, cVecHandleTagValValueForTypedArray.at(j)); + PropertyDescriptor descFrom1(thread, handleTagValValueDef, true, true, true); + JSHandle handleTypedArray = CreateNumberTypedArray(thread, cVecJSType.at(j)); + JSHandle handleTagValTypedArray = JSHandle::Cast(handleTypedArray); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleTypedArray)); + int32_t byteLengthViewdArrayBuffer = sizeElement * numElementsTypedArray; + JSHandle handleTagValArrayBufferFrom = + JSHandle::Cast(factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleTypedArray->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleTypedArray->SetArrayLength(thread, JSTaggedValue(numElementsTypedArray)); + + for (uint32_t i = 0; i < numElementsTypedArray; i++) { + JSHandle handleTagValKey(thread, JSTaggedValue(i)); + EXPECT_FALSE(JSTypedArray::HasProperty(thread, handleTagValTypedArray, handleTagValKey)); + EXPECT_TRUE(JSTypedArray::DefineOwnProperty(thread, handleTagValTypedArray, handleTagValKey, descFrom1)); + EXPECT_TRUE(JSTypedArray::HasProperty(thread, handleTagValTypedArray, handleTagValKey)); + EXPECT_TRUE(JSTaggedValue::StrictEqual(thread, handleTagValValueDef, + JSTypedArray::GetProperty(thread, handleTagValTypedArray, handleTagValKey).GetValue())); + + PropertyDescriptor descTo1(thread); + EXPECT_FALSE(descTo1.HasWritable() || descTo1.HasEnumerable() || descTo1.HasConfigurable()); + EXPECT_TRUE(JSTypedArray::GetOwnProperty(thread, handleTagValTypedArray, handleTagValKey, descTo1)); + EXPECT_TRUE(descTo1.HasWritable() && descTo1.HasEnumerable() && descTo1.HasConfigurable()); + EXPECT_TRUE(descTo1.IsWritable() && descTo1.IsEnumerable() && descTo1.IsConfigurable()); + EXPECT_TRUE(JSTaggedValue::StrictEqual(thread, descTo1.GetValue(), handleTagValValueDef)); + } + } +} + +/* + * Feature: JSTypedArray + * Function: SetProperty + * SubFunction: GetProperty/HasProperty + * FunctionPoints: Set Property For Element At Index(JSTaggedValue) Of JSTypedArray + * CaseDescription: Call SetProperty function with a JSTypedArray, a index(JSTaggedValue) and a source + * value(JSTaggedValue), check whether the bool returned through calling HasProperty function with the + * JSTypedArray and the index(JSTaggedValue) is within expectations, check whether the + * value(JSTaggedValue) of the OperationResult returned through calling GetProperty function with the + * JSTypedArray and the index(JSTaggedValue) is the same with the source value(JSTaggedValue). + */ +HWTEST_F_L0(JSTypedArrayTest, SetProperty_TypedArray) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + + for (int j = 0; j < cVecJSType.size(); j++) { + int32_t numElementsTypedArray = 10; + JSHandle handleTagValValueSet(thread, cVecHandleTagValValueForTypedArray.at(j)); + JSHandle handleTypedArray = CreateNumberTypedArray(thread, cVecJSType.at(j)); + JSHandle handleTagValTypedArray = JSHandle::Cast(handleTypedArray); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleTypedArray)); + int32_t byteLengthViewdArrayBuffer = sizeElement * numElementsTypedArray; + JSHandle handleTagValArrayBufferFrom = + JSHandle::Cast(factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + handleTypedArray->SetViewedArrayBuffer(thread, handleTagValArrayBufferFrom); + handleTypedArray->SetArrayLength(thread, JSTaggedValue(numElementsTypedArray)); + + for (uint32_t i = 0; i < numElementsTypedArray; i++) { + JSHandle handleTagValKey(thread, JSTaggedValue(i)); + EXPECT_FALSE(JSTypedArray::HasProperty(thread, handleTagValTypedArray, handleTagValKey)); + EXPECT_TRUE(JSTypedArray::SetProperty(thread, handleTagValTypedArray, handleTagValKey, + handleTagValValueSet)); + EXPECT_TRUE(JSTypedArray::HasProperty(thread, handleTagValTypedArray, handleTagValKey)); + EXPECT_TRUE(JSTaggedValue::StrictEqual(thread, handleTagValValueSet, + JSTypedArray::GetProperty(thread, handleTagValTypedArray, handleTagValKey).GetValue())); + } + } +} + +/* + * Feature: JSTypedArray + * Function: FastCopyElementToArray + * SubFunction: IntegerIndexedElementSet/TaggedArray::Get + * FunctionPoints: Copy All Elements Of JSTypedArray To TaggedArray Fast + * CaseDescription: Create a source JSTypedArray and a target TaggedArray, init the elements of the source JSTypedArray + * with a certain value(JSTaggedValue) through calling IntegerIndexedElementSet function. Call + * FastCopyElementToArray function with the source JSTypedArray and the target TaggedArray. Check + * whether the values(JSTaggedValue) returned through Get(TaggedArray) function are the same with the + * certain value(JSTaggedValue). + */ +HWTEST_F_L0(JSTypedArrayTest, FastCopyElementToArray_TypedArray) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + + for (int j = 0; j < cVecJSType.size(); j++) { + int32_t numElementsTypedArray = 10; + JSHandle handleTagValValueSet(thread, cVecHandleTagValValueForTypedArray.at(j)); + JSHandle handleTypedArrayFrom = + CreateNumberTypedArray(thread, cVecJSType.at(j)); + JSHandle handleTagValTypedArrayFrom = JSHandle::Cast(handleTypedArrayFrom); + + uint32_t sizeElement = ecmascript::base::TypedArrayHelper::GetElementSize( + JSHandle::Cast(handleTypedArrayFrom)); + int32_t byteLengthViewdArrayBuffer = sizeElement * numElementsTypedArray; + JSHandle handleTagValArrayBuffer = + JSHandle::Cast(factory->NewJSArrayBuffer(byteLengthViewdArrayBuffer)); + JSHandle handleTagArrTo = factory->NewTaggedArray(byteLengthViewdArrayBuffer); + handleTypedArrayFrom->SetViewedArrayBuffer(thread, handleTagValArrayBuffer); + handleTypedArrayFrom->SetArrayLength(thread, JSTaggedValue(numElementsTypedArray)); + + for (uint32_t i = 0; i < numElementsTypedArray; i++) { + EXPECT_TRUE(JSTypedArray::IntegerIndexedElementSet(thread, handleTagValTypedArrayFrom, JSTaggedValue(i), + handleTagValValueSet)); + } + EXPECT_TRUE(JSTypedArray::FastCopyElementToArray(thread, handleTagValTypedArrayFrom, handleTagArrTo)); + for (uint32_t i = 0; i < numElementsTypedArray; i++) { + EXPECT_EQ(handleTagArrTo->Get(i), handleTagValValueSet.GetTaggedValue()); + } + } +} +} // namespace panda::test -- Gitee From 9d975faeb6b014a13ec2d6b33b198982be48ee34 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Sat, 30 Oct 2021 10:04:58 +0800 Subject: [PATCH 105/115] enum MachineType replace with enum class MachineType GetInteger32Constant replace with GetInt32Constant Signed-off-by: songzhengchao --- ecmascript/compiler/circuit_builder.cpp | 124 +++++++++--------- ecmascript/compiler/fast_stub.cpp | 90 +++++++------ ecmascript/compiler/llvm_ir_builder.cpp | 26 ++-- ecmascript/compiler/machine_type.h | 2 +- ecmascript/compiler/stub.cpp | 137 +++++++++---------- ecmascript/compiler/stub.h | 160 ++++++++++++----------- ecmascript/compiler/stub_descriptor.cpp | 103 ++++++++++----- ecmascript/compiler/tests/stub_tests.cpp | 51 ++++---- 8 files changed, 368 insertions(+), 325 deletions(-) diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index ba3c833..d0bcab1 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -155,30 +155,30 @@ AddrShift CircuitBuilder::NewDefaultCase(AddrShift switchBranch) OpCode CircuitBuilder::GetStoreOpCodeFromMachineType(MachineType type) { switch (type) { - case INT8_TYPE: + case MachineType::INT8_TYPE: return OpCode(OpCode::INT8_STORE); - case INT16_TYPE: + case MachineType::INT16_TYPE: return OpCode(OpCode::INT16_STORE); - case INT32_TYPE: + case MachineType::INT32_TYPE: return OpCode(OpCode::INT32_STORE); - case INT64_TYPE: + case MachineType::INT64_TYPE: return OpCode(OpCode::INT64_STORE); - case BOOL_TYPE: + case MachineType::BOOL_TYPE: return OpCode(OpCode::INT32_STORE); - case UINT8_TYPE: + case MachineType::UINT8_TYPE: return OpCode(OpCode::INT8_STORE); - case UINT16_TYPE: + case MachineType::UINT16_TYPE: return OpCode(OpCode::INT16_STORE); - case UINT32_TYPE: + case MachineType::UINT32_TYPE: return OpCode(OpCode::INT32_STORE); - case UINT64_TYPE: - case POINTER_TYPE: - case TAGGED_TYPE: - case TAGGED_POINTER_TYPE: + case MachineType::UINT64_TYPE: + case MachineType::POINTER_TYPE: + case MachineType::TAGGED_TYPE: + case MachineType::TAGGED_POINTER_TYPE: return OpCode(OpCode::INT64_STORE); - case FLOAT32_TYPE: + case MachineType::FLOAT32_TYPE: return OpCode(OpCode::FLOAT32_STORE); - case FLOAT64_TYPE: + case MachineType::FLOAT64_TYPE: return OpCode(OpCode::FLOAT64_STORE); default: UNREACHABLE(); @@ -188,30 +188,30 @@ OpCode CircuitBuilder::GetStoreOpCodeFromMachineType(MachineType type) OpCode CircuitBuilder::GetLoadOpCodeFromMachineType(MachineType type) { switch (type) { - case INT8_TYPE: + case MachineType::INT8_TYPE: return OpCode(OpCode::INT8_LOAD); - case INT16_TYPE: + case MachineType::INT16_TYPE: return OpCode(OpCode::INT16_LOAD); - case INT32_TYPE: + case MachineType::INT32_TYPE: return OpCode(OpCode::INT32_LOAD); - case INT64_TYPE: + case MachineType::INT64_TYPE: return OpCode(OpCode::INT64_LOAD); - case BOOL_TYPE: + case MachineType::BOOL_TYPE: return OpCode(OpCode::INT32_LOAD); - case UINT8_TYPE: + case MachineType::UINT8_TYPE: return OpCode(OpCode::INT8_LOAD); - case UINT16_TYPE: + case MachineType::UINT16_TYPE: return OpCode(OpCode::INT16_LOAD); - case UINT32_TYPE: + case MachineType::UINT32_TYPE: return OpCode(OpCode::INT32_LOAD); - case UINT64_TYPE: - case POINTER_TYPE: - case TAGGED_TYPE: - case TAGGED_POINTER_TYPE: + case MachineType::UINT64_TYPE: + case MachineType::POINTER_TYPE: + case MachineType::TAGGED_TYPE: + case MachineType::TAGGED_POINTER_TYPE: return OpCode(OpCode::INT64_LOAD); - case FLOAT32_TYPE: + case MachineType::FLOAT32_TYPE: return OpCode(OpCode::FLOAT32_LOAD); - case FLOAT64_TYPE: + case MachineType::FLOAT64_TYPE: return OpCode(OpCode::FLOAT64_LOAD); default: UNREACHABLE(); @@ -221,32 +221,32 @@ OpCode CircuitBuilder::GetLoadOpCodeFromMachineType(MachineType type) OpCode CircuitBuilder::GetSelectOpCodeFromMachineType(MachineType type) { switch (type) { - case NONE_TYPE: + case MachineType::NONE_TYPE: return OpCode(OpCode::DEPEND_SELECTOR); - case INT8_TYPE: + case MachineType::INT8_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT8); - case INT16_TYPE: + case MachineType::INT16_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT16); - case INT32_TYPE: + case MachineType::INT32_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT32); - case INT64_TYPE: + case MachineType::INT64_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT64); - case BOOL_TYPE: + case MachineType::BOOL_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT1); - case UINT8_TYPE: + case MachineType::UINT8_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT8); - case UINT16_TYPE: + case MachineType::UINT16_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT16); - case UINT32_TYPE: + case MachineType::UINT32_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT32); - case UINT64_TYPE: - case POINTER_TYPE: - case TAGGED_TYPE: - case TAGGED_POINTER_TYPE: + case MachineType::UINT64_TYPE: + case MachineType::POINTER_TYPE: + case MachineType::TAGGED_TYPE: + case MachineType::TAGGED_POINTER_TYPE: return OpCode(OpCode::VALUE_SELECTOR_INT64); - case FLOAT32_TYPE: + case MachineType::FLOAT32_TYPE: return OpCode(OpCode::VALUE_SELECTOR_FLOAT32); - case FLOAT64_TYPE: + case MachineType::FLOAT64_TYPE: return OpCode(OpCode::VALUE_SELECTOR_FLOAT64); default: UNREACHABLE(); @@ -270,13 +270,13 @@ AddrShift CircuitBuilder::NewDependAnd(std::initializer_list args) AddrShift CircuitBuilder::NewLoadGate(MachineType type, AddrShift val, AddrShift depend) { OpCode op = GetLoadOpCodeFromMachineType(type); - return circuit_->NewGate(op, type, {depend, val}, TypeCode::NOTYPE); + return circuit_->NewGate(op, static_cast(type), {depend, val}, TypeCode::NOTYPE); } AddrShift CircuitBuilder::NewStoreGate(MachineType type, AddrShift ptr, AddrShift val, AddrShift depend) { OpCode op = GetStoreOpCodeFromMachineType(type); - return circuit_->NewGate(op, type, {depend, val, ptr}, TypeCode::NOTYPE); + return circuit_->NewGate(op, static_cast(type), {depend, val, ptr}, TypeCode::NOTYPE); } AddrShift CircuitBuilder::NewArithMeticGate(OpCode opcode, AddrShift left, AddrShift right) @@ -291,43 +291,43 @@ AddrShift CircuitBuilder::NewArithMeticGate(OpCode opcode, AddrShift value) AddrShift CircuitBuilder::NewLogicGate(OpCode opcode, AddrShift left, AddrShift right) { - return circuit_->NewGate(opcode, MachineType::BOOL_TYPE, {left, right}, TypeCode::NOTYPE); + return circuit_->NewGate(opcode, static_cast(MachineType::BOOL_TYPE), {left, right}, TypeCode::NOTYPE); } AddrShift CircuitBuilder::NewLogicGate(OpCode opcode, AddrShift value) { - return circuit_->NewGate(opcode, MachineType::BOOL_TYPE, {value}, TypeCode::NOTYPE); + return circuit_->NewGate(opcode, static_cast(MachineType::BOOL_TYPE), {value}, TypeCode::NOTYPE); } OpCode CircuitBuilder::GetCallOpCodeFromMachineType(MachineType type) { switch (type) { - case NONE_TYPE: + case MachineType::NONE_TYPE: return OpCode(OpCode::CALL); - case INT8_TYPE: + case MachineType::INT8_TYPE: return OpCode(OpCode::INT8_CALL); - case INT16_TYPE: + case MachineType::INT16_TYPE: return OpCode(OpCode::INT16_CALL); - case INT32_TYPE: + case MachineType::INT32_TYPE: return OpCode(OpCode::INT32_CALL); - case INT64_TYPE: + case MachineType::INT64_TYPE: return OpCode(OpCode::INT64_CALL); - case BOOL_TYPE: + case MachineType::BOOL_TYPE: return OpCode(OpCode::INT1_CALL); - case UINT8_TYPE: + case MachineType::UINT8_TYPE: return OpCode(OpCode::INT8_CALL); - case UINT16_TYPE: + case MachineType::UINT16_TYPE: return OpCode(OpCode::INT16_CALL); - case UINT32_TYPE: + case MachineType::UINT32_TYPE: return OpCode(OpCode::INT32_CALL); - case UINT64_TYPE: - case POINTER_TYPE: - case TAGGED_TYPE: - case TAGGED_POINTER_TYPE: + case MachineType::UINT64_TYPE: + case MachineType::POINTER_TYPE: + case MachineType::TAGGED_TYPE: + case MachineType::TAGGED_POINTER_TYPE: return OpCode(OpCode::INT64_CALL); - case FLOAT32_TYPE: + case MachineType::FLOAT32_TYPE: return OpCode(OpCode::FLOAT32_CALL); - case FLOAT64_TYPE: + case MachineType::FLOAT64_TYPE: return OpCode(OpCode::FLOAT64_CALL); default: UNREACHABLE(); diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 19c87b3..3951277 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -29,7 +29,7 @@ void FastArrayLoadElementStub::GenerateCircuit() AddrShift indexVal = Int32Argument(1); // load a.length - AddrShift lengthOffset = GetInteger32Constant(JSArray::GetArrayLengthOffset()); + AddrShift lengthOffset = GetInt32Constant(JSArray::GetArrayLengthOffset()); if (PtrValueCode() == ValueCode::INT64) { lengthOffset = SExtInt32ToInt64(lengthOffset); } else if (PtrValueCode() == ValueCode::INT32) { @@ -349,19 +349,18 @@ void FindOwnElementStub::GenerateCircuit() AddrShift thread = PtrArgument(0); AddrShift obj = PtrArgument(1); AddrShift index = Int32Argument(2); // 2: 3rd parameter - index - Label notDict(env); Label isDict(env); Label invalidValue(env); Label end(env); - AddrShift elements = Load(POINTER_TYPE, obj, GetPtrConstant(JSObject::ELEMENTS_OFFSET)); - + AddrShift elements = Load(MachineType::POINTER_TYPE, obj, GetPtrConstant(JSObject::ELEMENTS_OFFSET)); Branch(IsDictionaryMode(elements), &isDict, ¬Dict); Bind(¬Dict); { Label outOfArray(env); Label notOutOfArray(env); - AddrShift arrayLength = Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + AddrShift arrayLength = Load(MachineType::UINT32_TYPE, elements, + GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); Branch(Int32LessThanOrEqual(arrayLength, index), &outOfArray, ¬OutOfArray); Bind(&outOfArray); Jump(&invalidValue); @@ -369,7 +368,7 @@ void FindOwnElementStub::GenerateCircuit() { AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); AddrShift dataIndex = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - AddrShift value = Load(TAGGED_TYPE, elements, dataIndex); + AddrShift value = Load(MachineType::TAGGED_TYPE, elements, dataIndex); Label isHole1(env); Label notHole1(env); Branch(TaggedIsHole(value), &isHole1, ¬Hole1); @@ -388,7 +387,7 @@ void FindOwnElementStub::GenerateCircuit() AddrShift entry = FindElementFromNumberDictionary(thread, elements, taggedIndex); Label notNegtiveOne(env); Label negtiveOne(env); - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); Bind(¬NegtiveOne); { Return(GetValueFromDictionary(elements, entry)); @@ -424,7 +423,7 @@ void GetElementStub::GenerateCircuit() Bind(¬Hole); Return(callFindOwnElementVal); Bind(&isHole); - receiver = Load(TAGGED_TYPE, LoadHClass(objPtr), GetPtrConstant(JSHClass::PROTOTYPE_OFFSET)); + receiver = Load(MachineType::TAGGED_TYPE, LoadHClass(objPtr), GetPtrConstant(JSHClass::PROTOTYPE_OFFSET)); Branch(TaggedIsHeapObject(receiver), &loopEnd, ¬HeapObj); Bind(¬HeapObj); Return(GetUndefinedConstant()); @@ -445,11 +444,11 @@ void FindOwnElement2Stub::GenerateCircuit() Label notDictionary(env); Label isDictionary(env); Label end(env); - Branch(Word32Equal(isDict, GetInteger32Constant(0)), ¬Dictionary, &isDictionary); + Branch(Word32Equal(isDict, GetInt32Constant(0)), ¬Dictionary, &isDictionary); Bind(¬Dictionary); { AddrShift elementsLength = - Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + Load(MachineType::UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); Label outOfElements(env); Label notOutOfElements(env); Branch(Int32LessThanOrEqual(elementsLength, index), &outOfElements, ¬OutOfElements); @@ -467,9 +466,9 @@ void FindOwnElement2Stub::GenerateCircuit() Jump(&end); Bind(¬Hole); { - Store(UINT32_TYPE, attr, GetPtrConstant(0), - GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())); - Store(UINT32_TYPE, indexOrEntry, GetPtrConstant(0), index); + Store(MachineType::UINT32_TYPE, attr, GetPtrConstant(0), + GetInt32Constant(PropertyAttributes::GetDefaultAttributes())); + Store(MachineType::UINT32_TYPE, indexOrEntry, GetPtrConstant(0), index); Return(value); } } @@ -479,11 +478,11 @@ void FindOwnElement2Stub::GenerateCircuit() AddrShift entry = FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index)); Label notNegtiveOne(env); Label negtiveOne(env); - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); Bind(¬NegtiveOne); { - Store(UINT32_TYPE, attr, GetPtrConstant(0), GetAttributesFromDictionary(elements, entry)); - Store(UINT32_TYPE, indexOrEntry, GetPtrConstant(0), entry); + Store(MachineType::UINT32_TYPE, attr, GetPtrConstant(0), GetAttributesFromDictionary(elements, entry)); + Store(MachineType::UINT32_TYPE, indexOrEntry, GetPtrConstant(0), entry); Return(GetValueFromDictionary(elements, entry)); } Bind(&negtiveOne); @@ -539,7 +538,7 @@ void SetElementStub::GenerateCircuit() { Label isThrow(env); Label notThrow(env); - Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw); + Branch(Word32NotEqual(mayThrow, GetInt32Constant(0)), &isThrow, ¬Throw); Bind(&isThrow); ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), FalseConstant()); Bind(¬Throw); @@ -549,11 +548,11 @@ void SetElementStub::GenerateCircuit() StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal); Return(CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)), {thread, receiver, index, value, - GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())})); + GetInt32Constant(PropertyAttributes::GetDefaultAttributes())})); } Bind(&afterOnProtoType); { - AddrShift attr = Load(INT32_TYPE, pattr); + AddrShift attr = Load(MachineType::INT32_TYPE, pattr); Label isAccessor(env); Label notAccessor(env); Branch(IsAccessor(attr), &isAccessor, ¬Accessor); @@ -567,7 +566,7 @@ void SetElementStub::GenerateCircuit() AddrShift elements = GetElements(receiver); Label isDict(env); Label notDict(env); - AddrShift indexOrEntry = Load(INT32_TYPE, pindexOrEntry); + AddrShift indexOrEntry = Load(MachineType::INT32_TYPE, pindexOrEntry); Branch(isDictionary, &isDict, ¬Dict); Bind(¬Dict); { @@ -585,7 +584,7 @@ void SetElementStub::GenerateCircuit() { Label isThrow(env); Label notThrow(env); - Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw); + Branch(Word32NotEqual(mayThrow, GetInt32Constant(0)), &isThrow, ¬Throw); Bind(&isThrow); ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetReadOnlyProperty), FalseConstant()); Bind(¬Throw); @@ -620,7 +619,7 @@ void SetElementStub::GenerateCircuit() { Label isThrow(env); Label notThrow(env); - Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw); + Branch(Word32NotEqual(mayThrow, GetInt32Constant(0)), &isThrow, ¬Throw); Bind(&isThrow); ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), FalseConstant()); Bind(¬Throw); @@ -631,7 +630,7 @@ void SetElementStub::GenerateCircuit() StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal); Return(CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)), {thread, receiver, index, value, - GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())})); + GetInt32Constant(PropertyAttributes::GetDefaultAttributes())})); } } Bind(&isHeapObj); @@ -718,7 +717,7 @@ void GetPropertyByIndexStub::GenerateCircuit() FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index)); Label notNegtiveOne(env); Label negtiveOne(env); - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); Bind(¬NegtiveOne); { AddrShift attr = GetAttributesFromDictionary(elements, entry); @@ -844,7 +843,7 @@ void SetPropertyByIndexStub::GenerateCircuit() AddrShift result = CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)), {thread, receiver, index, value, - GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())}); + GetInt32Constant(PropertyAttributes::GetDefaultAttributes())}); Label success(env); Label failed(env); Branch(result, &success, &failed); @@ -907,7 +906,7 @@ void GetPropertyByNameStub::GenerateCircuit() Label hasEntry(env); Label noEntry(env); // if branch condition : entry != -1 - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), &hasEntry, &noEntry); + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), &hasEntry, &noEntry); Bind(&hasEntry); { // PropertyAttributes attr(layoutInfo->GetAttr(entry)) @@ -956,7 +955,7 @@ void GetPropertyByNameStub::GenerateCircuit() Label notNegtiveOne(env); Label negtiveOne(env); // if branch condition : entry != -1 - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); Bind(¬NegtiveOne); { // auto value = dict->GetValue(entry) @@ -1040,10 +1039,10 @@ void FastModStub::GenerateCircuit() { Label xGtZero(env); Label xGtZeroAndyGtZero(env); - Branch(Int32GreaterThan(*intX, GetInteger32Constant(0)), &xGtZero, &xNotIntOryNotInt); + Branch(Int32GreaterThan(*intX, GetInt32Constant(0)), &xGtZero, &xNotIntOryNotInt); Bind(&xGtZero); { - Branch(Int32GreaterThan(*intY, GetInteger32Constant(0)), &xGtZeroAndyGtZero, &xNotIntOryNotInt); + Branch(Int32GreaterThan(*intY, GetInt32Constant(0)), &xGtZeroAndyGtZero, &xNotIntOryNotInt); Bind(&xGtZeroAndyGtZero); { intX = Int32Mod(*intX, *intY); @@ -1173,14 +1172,14 @@ void FastTypeOfStub::GenerateCircuit() DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, obj); AddrShift gConstOffset = PtrAdd(thread, GetPtrConstant(panda::ecmascript::JSThread::GetGlobalConstantOffset())); AddrShift booleanIndex = GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX); - AddrShift gConstUndefindStr = Load(TAGGED_TYPE, gConstOffset, booleanIndex); + AddrShift gConstUndefindStr = Load(MachineType::TAGGED_TYPE, gConstOffset, booleanIndex); DEFVARIABLE(resultRep, MachineType::TAGGED_TYPE, gConstUndefindStr); Label objIsTrue(env); Label objNotTrue(env); Label exit(env); Label defaultLabel(env); AddrShift gConstBooleanStr = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX)); Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_TRUE)), &objIsTrue, &objNotTrue); Bind(&objIsTrue); { @@ -1205,7 +1204,8 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsNull); { resultRep = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); Jump(&exit); } Bind(&objNotNull); @@ -1216,7 +1216,7 @@ void FastTypeOfStub::GenerateCircuit() &objNotUndefined); Bind(&objIsUndefined); { - resultRep = Load(TAGGED_TYPE, gConstOffset, + resultRep = Load(MachineType::TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX)); Jump(&exit); } @@ -1238,7 +1238,8 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsString); { resultRep = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX)); Jump(&exit); } Bind(&objNotString); @@ -1248,7 +1249,7 @@ void FastTypeOfStub::GenerateCircuit() Branch(IsSymbol(obj), &objIsSymbol, &objNotSymbol); Bind(&objIsSymbol); { - resultRep = Load(TAGGED_TYPE, gConstOffset, + resultRep = Load(MachineType::TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::SYMBOL_STRING_INDEX)); Jump(&exit); } @@ -1260,13 +1261,15 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsCallable); { resultRep = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX)); Jump(&exit); } Bind(&objNotCallable); { resultRep = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); Jump(&exit); } } @@ -1280,7 +1283,8 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsNum); { resultRep = Load( - TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX)); + MachineType::TAGGED_TYPE, gConstOffset, + GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX)); Jump(&exit); } Bind(&objNotNum); @@ -1321,7 +1325,7 @@ void GetPropertyByValueStub::GenerateCircuit() auto env = GetEnvironment(); AddrShift thread = PtrArgument(0); AddrShift receiver = PtrArgument(1); - DEFVARIABLE(key, TAGGED_TYPE, PtrArgument(2)); /* 2 : 3rd parameter is key */ + DEFVARIABLE(key, MachineType::TAGGED_TYPE, PtrArgument(2)); /* 2 : 3rd parameter is key */ Label isNumberOrStringSymbol(env); Label notNumber(env); @@ -1343,7 +1347,7 @@ void GetPropertyByValueStub::GenerateCircuit() AddrShift index = TryToElementsIndex(*key); Label validIndex(env); Label notValidIndex(env); - Branch(Int32GreaterThanOrEqual(index, GetInteger32Constant(0)), &validIndex, ¬ValidIndex); + Branch(Int32GreaterThanOrEqual(index, GetInt32Constant(0)), &validIndex, ¬ValidIndex); Bind(&validIndex); { auto getPropertyByIndex = GET_STUBDESCRIPTOR(GetPropertyByIndex); @@ -1398,7 +1402,7 @@ void SetPropertyByValueStub::GenerateCircuit() auto env = GetEnvironment(); AddrShift thread = PtrArgument(0); AddrShift receiver = PtrArgument(1); - DEFVARIABLE(key, TAGGED_TYPE, PtrArgument(2)); /* 2 : 3rd parameter is key */ + DEFVARIABLE(key, MachineType::TAGGED_TYPE, PtrArgument(2)); /* 2 : 3rd parameter is key */ AddrShift value = Int64Argument(3); /* 3 : 4th parameter is value */ Label isNumberOrStringSymbol(env); @@ -1421,7 +1425,7 @@ void SetPropertyByValueStub::GenerateCircuit() AddrShift index = TryToElementsIndex(*key); Label validIndex(env); Label notValidIndex(env); - Branch(Int32GreaterThanOrEqual(index, GetInteger32Constant(0)), &validIndex, ¬ValidIndex); + Branch(Int32GreaterThanOrEqual(index, GetInt32Constant(0)), &validIndex, ¬ValidIndex); Bind(&validIndex); { auto setPropertyByIndex = GET_STUBDESCRIPTOR(SetPropertyByIndex); @@ -1470,4 +1474,4 @@ void SetPropertyByValueStub::GenerateCircuit() Bind(&exit); Return(GetHoleConstant()); } -} // namespace kungfu \ No newline at end of file +} // namespace kungfu diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 373550d..13de635 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -1393,19 +1393,19 @@ LLVMTypeRef LLVMStubModule::GetLLVMFunctionTypeStubDescriptor(StubDescriptor *st LLVMTypeRef LLVMStubModule::ConvertLLVMTypeFromMachineType(MachineType type) { static std::map machineTypeMap = { - {MachineType::NONE_TYPE, LLVMVoidType()}, - {MachineType::BOOL_TYPE, LLVMInt1Type()}, - {MachineType::INT8_TYPE, LLVMInt8Type()}, - {MachineType::INT16_TYPE, LLVMInt16Type()}, - {MachineType::INT32_TYPE, LLVMInt32Type()}, - {MachineType::INT64_TYPE, LLVMInt64Type()}, - {MachineType::UINT8_TYPE, LLVMInt8Type()}, - {MachineType::UINT16_TYPE, LLVMInt16Type()}, - {MachineType::UINT32_TYPE, LLVMInt32Type()}, - {MachineType::UINT64_TYPE, LLVMInt64Type()}, - {MachineType::FLOAT32_TYPE, LLVMFloatType()}, - {MachineType::FLOAT64_TYPE, LLVMDoubleType()}, - {MachineType::TAGGED_TYPE, LLVMInt64Type()}, + {MachineType::NONE_TYPE, LLVMVoidType()}, + {MachineType::BOOL_TYPE, LLVMInt1Type()}, + {MachineType::INT8_TYPE, LLVMInt8Type()}, + {MachineType::INT16_TYPE, LLVMInt16Type()}, + {MachineType::INT32_TYPE, LLVMInt32Type()}, + {MachineType::INT64_TYPE, LLVMInt64Type()}, + {MachineType::UINT8_TYPE, LLVMInt8Type()}, + {MachineType::UINT16_TYPE, LLVMInt16Type()}, + {MachineType::UINT32_TYPE, LLVMInt32Type()}, + {MachineType::UINT64_TYPE, LLVMInt64Type()}, + {MachineType::FLOAT32_TYPE, LLVMFloatType()}, + {MachineType::FLOAT64_TYPE, LLVMDoubleType()}, + {MachineType::TAGGED_TYPE, LLVMInt64Type()}, }; return machineTypeMap[type]; } diff --git a/ecmascript/compiler/machine_type.h b/ecmascript/compiler/machine_type.h index 3530cd1..f17f608 100644 --- a/ecmascript/compiler/machine_type.h +++ b/ecmascript/compiler/machine_type.h @@ -17,7 +17,7 @@ #define ECMASCRIPT_COMPILER_MACHINE_TYPE_H namespace kungfu { -enum MachineType { +enum class MachineType { NONE_TYPE, BOOL_TYPE, INT8_TYPE, diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 2da08e6..004977d 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -366,7 +366,7 @@ AddrShift Stub::FixLoadType(AddrShift x) AddrShift Stub::LoadFromObject(MachineType type, AddrShift object, AddrShift offset) { - AddrShift elementsOffset = GetInteger32Constant(panda::ecmascript::JSObject::ELEMENTS_OFFSET); + AddrShift elementsOffset = GetInt32Constant(panda::ecmascript::JSObject::ELEMENTS_OFFSET); if (PtrValueCode() == ValueCode::INT64) { elementsOffset = SExtInt32ToInt64(elementsOffset); } @@ -374,8 +374,8 @@ AddrShift Stub::LoadFromObject(MachineType type, AddrShift object, AddrShift off AddrShift elements = Load(MachineType::UINT64_TYPE, object, elementsOffset); // load index in tagged array AddrShift dataOffset = - Int32Add(GetInteger32Constant(panda::coretypes::Array::GetDataOffset()), - Int32Mul(offset, GetInteger32Constant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()))); + Int32Add(GetInt32Constant(panda::coretypes::Array::GetDataOffset()), + Int32Mul(offset, GetInt32Constant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()))); if (PtrValueCode() == ValueCode::INT64) { dataOffset = SExtInt32ToInt64(dataOffset); } @@ -387,22 +387,22 @@ AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elem auto env = GetEnvironment(); Label subentry(env); env->PushCurrentLabel(&subentry); - DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1)); + DEFVARIABLE(result, MachineType::INT32_TYPE, GetInt32Constant(-1)); Label exit(env); AddrShift capcityoffset = PtrMul(GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()), GetPtrConstant(panda::ecmascript::TaggedHashTable::SIZE_INDEX)); AddrShift dataoffset = GetPtrConstant(panda::coretypes::Array::GetDataOffset()); - AddrShift capacity = TaggedCastToInt32(Load(TAGGED_TYPE, elements, PtrAdd(dataoffset, capcityoffset))); - DEFVARIABLE(count, INT32_TYPE, GetInteger32Constant(1)); + AddrShift capacity = TaggedCastToInt32(Load(MachineType::TAGGED_TYPE, elements, PtrAdd(dataoffset, capcityoffset))); + DEFVARIABLE(count, MachineType::INT32_TYPE, GetInt32Constant(1)); AddrShift pKey = Alloca(static_cast(MachineRep::K_WORD32)); - AddrShift keyStore = Store(INT32_TYPE, pKey, GetPtrConstant(0), TaggedCastToInt32(key)); + AddrShift keyStore = Store(MachineType::INT32_TYPE, pKey, GetPtrConstant(0), TaggedCastToInt32(key)); StubDescriptor *getHash32Descriptor = GET_STUBDESCRIPTOR(GetHash32); - AddrShift len = GetInteger32Constant(sizeof(int) / sizeof(uint8_t)); + AddrShift len = GetInt32Constant(sizeof(int) / sizeof(uint8_t)); AddrShift hash = CallRuntime(getHash32Descriptor, thread, GetWord64Constant(FAST_STUB_ID(GetHash32)), keyStore, {pKey, len}); - DEFVARIABLE(entry, INT32_TYPE, Word32And(hash, Int32Sub(capacity, GetInteger32Constant(1)))); + DEFVARIABLE(entry, MachineType::INT32_TYPE, Word32And(hash, Int32Sub(capacity, GetInt32Constant(1)))); Label loopHead(env); Label loopEnd(env); Label afterLoop(env); @@ -419,7 +419,7 @@ AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elem Label notUndefined(env); Branch(TaggedIsUndefined(element), &isUndefined, ¬Undefined); Bind(&isUndefined); - result = GetInteger32Constant(-1); + result = GetInt32Constant(-1); Jump(&exit); Bind(¬Undefined); Label isMatch(env); @@ -432,7 +432,7 @@ AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elem Jump(&loopEnd); Bind(&loopEnd); entry = GetNextPositionForHash(*entry, *count, capacity); - count = Int32Add(*count, GetInteger32Constant(1)); + count = Int32Add(*count, GetInt32Constant(1)); LoopEnd(&loopHead); Bind(&exit); auto ret = *result; @@ -446,7 +446,7 @@ AddrShift Stub::IsMatchInNumberDictionary(AddrShift key, AddrShift other) Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(result, BOOL_TYPE, FalseConstant()); + DEFVARIABLE(result, MachineType::BOOL_TYPE, FalseConstant()); Label isHole(env); Label notHole(env); Label isUndefined(env); @@ -485,16 +485,17 @@ AddrShift Stub::GetKeyFromNumberDictionary(AddrShift elements, AddrShift entry) Label subentry(env); env->PushCurrentLabel(&subentry); Label exit(env); - DEFVARIABLE(result, TAGGED_TYPE, GetUndefinedConstant()); + DEFVARIABLE(result, MachineType::TAGGED_TYPE, GetUndefinedConstant()); Label ltZero(env); Label notLtZero(env); Label gtLength(env); Label notGtLength(env); - AddrShift dictionaryLength = Load(INT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + AddrShift dictionaryLength = + Load(MachineType::INT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); AddrShift arrayIndex = - Int32Add(GetInteger32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), - Int32Mul(entry, GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); - Branch(Int32LessThan(arrayIndex, GetInteger32Constant(0)), <Zero, ¬LtZero); + Int32Add(GetInt32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), + Int32Mul(entry, GetInt32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); + Branch(Int32LessThan(arrayIndex, GetInt32Constant(0)), <Zero, ¬LtZero); Bind(<Zero); Jump(&exit); Bind(¬LtZero); @@ -517,14 +518,14 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements Label funcEntry(env); env->PushCurrentLabel(&funcEntry); Label exit(env); - DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1)); + DEFVARIABLE(result, MachineType::INT32_TYPE, GetInt32Constant(-1)); AddrShift capcityoffset = PtrMul(GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()), GetPtrConstant(panda::ecmascript::TaggedHashTable::SIZE_INDEX)); AddrShift dataoffset = GetPtrConstant(panda::coretypes::Array::GetDataOffset()); - AddrShift capacity = TaggedCastToInt32(Load(TAGGED_TYPE, elements, PtrAdd(dataoffset, capcityoffset))); - DEFVARIABLE(count, INT32_TYPE, GetInteger32Constant(1)); - DEFVARIABLE(hash, INT32_TYPE, GetInteger32Constant(0)); + AddrShift capacity = TaggedCastToInt32(Load(MachineType::TAGGED_TYPE, elements, PtrAdd(dataoffset, capcityoffset))); + DEFVARIABLE(count, MachineType::INT32_TYPE, GetInt32Constant(1)); + DEFVARIABLE(hash, MachineType::INT32_TYPE, GetInt32Constant(0)); // NameDictionary::hash Label isSymbol(env); Label notSymbol(env); @@ -535,7 +536,8 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements Branch(IsSymbol(key), &isSymbol, ¬Symbol); Bind(&isSymbol); { - hash = TaggedCastToInt32(Load(TAGGED_TYPE, key, GetPtrConstant(panda::ecmascript::JSSymbol::HASHFIELD_OFFSET))); + hash = TaggedCastToInt32(Load(MachineType::TAGGED_TYPE, key, + GetPtrConstant(panda::ecmascript::JSSymbol::HASHFIELD_OFFSET))); Jump(&beforeDefineHash); } Bind(¬Symbol); @@ -556,7 +558,7 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements } Bind(&beforeDefineHash); // GetFirstPosition(hash, size) - DEFVARIABLE(entry, INT32_TYPE, Word32And(*hash, Int32Sub(capacity, GetInteger32Constant(1)))); + DEFVARIABLE(entry, MachineType::INT32_TYPE, Word32And(*hash, Int32Sub(capacity, GetInt32Constant(1)))); Jump(&loopHead); LoopBegin(&loopHead); { @@ -577,7 +579,7 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements { Bind(&isUndefined); { - result = GetInteger32Constant(-1); + result = GetInt32Constant(-1); Jump(&exit); } Bind(¬Undefined); @@ -603,7 +605,7 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements Bind(&loopEnd); { entry = GetNextPositionForHash(*entry, *count, capacity); - count = Int32Add(*count, GetInteger32Constant(1)); + count = Int32Add(*count, GetInt32Constant(1)); LoopEnd(&loopHead); } } @@ -619,7 +621,7 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(result, TAGGED_TYPE, GetUndefinedConstant()); + DEFVARIABLE(result, MachineType::TAGGED_TYPE, GetUndefinedConstant()); Label inlinedProp(env); Label notInlinedProp(env); AddrShift attrOffset = PropAttrGetOffset(attr); @@ -632,17 +634,18 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a AddrShift propOffset = Int32Sub( ChangeInt64ToInt32(hClassObjectSize), Int32Mul(Int32Sub( - GetInteger32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS), attrOffset), - GetInteger32Constant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()))); - result = Load(UINT64_TYPE, obj, ZExtInt32ToInt64(propOffset)); + GetInt32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS), attrOffset), + GetInt32Constant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()))); + result = Load(MachineType::UINT64_TYPE, obj, ZExtInt32ToInt64(propOffset)); Jump(&exit); } Bind(¬InlinedProp); { // compute outOfLineProp offset, get it and return - AddrShift array = Load(UINT64_TYPE, obj, GetPtrConstant(panda::ecmascript::JSObject::PROPERTIES_OFFSET)); + AddrShift array = + Load(MachineType::UINT64_TYPE, obj, GetPtrConstant(panda::ecmascript::JSObject::PROPERTIES_OFFSET)); result = GetValueFromTaggedArray(array, Int32Sub(attrOffset, - GetInteger32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS))); + GetInt32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS))); Jump(&exit); } } @@ -655,7 +658,7 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a void Stub::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val) { StubDescriptor *throwTypeError = GET_STUBDESCRIPTOR(ThrowTypeError); - AddrShift msgIntId = GetInteger32Constant(messageId); + AddrShift msgIntId = GetInt32Constant(messageId); CallRuntime(throwTypeError, thread, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), {thread, msgIntId}); Return(val); } @@ -666,7 +669,7 @@ AddrShift Stub::TaggedToRepresentation(AddrShift value) Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(resultRep, INT64_TYPE, + DEFVARIABLE(resultRep, MachineType::INT64_TYPE, GetWord64Constant(static_cast(panda::ecmascript::Representation::OBJECT))); Label isInt(env); Label notInt(env); @@ -705,7 +708,7 @@ AddrShift Stub::UpdateRepresention(AddrShift oldRep, AddrShift value) Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(resultRep, INT64_TYPE, oldRep); + DEFVARIABLE(resultRep, MachineType::INT64_TYPE, oldRep); Label isMixedRep(env); Label notMiexedRep(env); Branch(Word64Equal(oldRep, GetWord64Constant(static_cast(panda::ecmascript::Representation::MIXED))), @@ -807,13 +810,13 @@ AddrShift Stub::TaggedIsString(AddrShift obj) Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(result, BOOL_TYPE, FalseConstant()); + DEFVARIABLE(result, MachineType::BOOL_TYPE, FalseConstant()); Label isHeapObject(env); Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit); Bind(&isHeapObject); { result = Word32Equal(GetObjectType(LoadHClass(obj)), - GetInteger32Constant(static_cast(panda::ecmascript::JSType::STRING))); + GetInt32Constant(static_cast(panda::ecmascript::JSType::STRING))); Jump(&exit); } Bind(&exit); @@ -828,21 +831,21 @@ AddrShift Stub::TaggedIsStringOrSymbol(AddrShift obj) Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(result, BOOL_TYPE, FalseConstant()); + DEFVARIABLE(result, MachineType::BOOL_TYPE, FalseConstant()); Label isHeapObject(env); Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit); Bind(&isHeapObject); { AddrShift objType = GetObjectType(LoadHClass(obj)); result = Word32Equal(objType, - GetInteger32Constant(static_cast(panda::ecmascript::JSType::STRING))); + GetInt32Constant(static_cast(panda::ecmascript::JSType::STRING))); Label isString(env); Label notString(env); Branch(*result, &exit, ¬String); Bind(¬String); { result = Word32Equal(objType, - GetInteger32Constant(static_cast(panda::ecmascript::JSType::SYMBOL))); + GetInt32Constant(static_cast(panda::ecmascript::JSType::SYMBOL))); Jump(&exit); } } @@ -858,8 +861,8 @@ AddrShift Stub::IsUtf16String(AddrShift string) AddrShift len = Load(MachineType::UINT32_TYPE, string, GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); return Word32Equal( - Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)), - GetInteger32Constant(panda::ecmascript::EcmaString::STRING_UNCOMPRESSED)); + Word32And(len, GetInt32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)), + GetInt32Constant(panda::ecmascript::EcmaString::STRING_UNCOMPRESSED)); } AddrShift Stub::IsUtf8String(AddrShift string) @@ -868,8 +871,8 @@ AddrShift Stub::IsUtf8String(AddrShift string) AddrShift len = Load(MachineType::UINT32_TYPE, string, GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); return Word32Equal( - Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)), - GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED)); + Word32And(len, GetInt32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)), + GetInt32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED)); } AddrShift Stub::IsInternalString(AddrShift string) @@ -878,15 +881,15 @@ AddrShift Stub::IsInternalString(AddrShift string) AddrShift len = Load(MachineType::UINT32_TYPE, string, GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); return Word32NotEqual( - Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_INTERN_BIT)), - GetInteger32Constant(0)); + Word32And(len, GetInt32Constant(panda::ecmascript::EcmaString::STRING_INTERN_BIT)), + GetInt32Constant(0)); } AddrShift Stub::IsDigit(AddrShift ch) { return TruncInt32ToInt1( - Word32And(SExtInt1ToInt32(Int32LessThanOrEqual(ch, GetInteger32Constant('9'))), - SExtInt1ToInt32(Int32GreaterThanOrEqual(ch, GetInteger32Constant('0'))))); + Word32And(SExtInt1ToInt32(Int32LessThanOrEqual(ch, GetInt32Constant('9'))), + SExtInt1ToInt32(Int32GreaterThanOrEqual(ch, GetInt32Constant('0'))))); } AddrShift Stub::StringToElementIndex(AddrShift string) @@ -895,19 +898,19 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Label entry(env); env->PushCurrentLabel(&entry); Label exit(env); - DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1)); + DEFVARIABLE(result, MachineType::INT32_TYPE, GetInt32Constant(-1)); Label greatThanZero(env); Label inRange(env); AddrShift len = Load(MachineType::UINT32_TYPE, string, GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset())); - len = Word32LSR(len, GetInteger32Constant(2)); // 2 : 2 means len must be right shift 2 bits - Branch(Word32Equal(len, GetInteger32Constant(0)), &exit, &greatThanZero); + len = Word32LSR(len, GetInt32Constant(2)); // 2 : 2 means len must be right shift 2 bits + Branch(Word32Equal(len, GetInt32Constant(0)), &exit, &greatThanZero); Bind(&greatThanZero); - Branch(Int32GreaterThan(len, GetInteger32Constant(panda::ecmascript::MAX_INDEX_LEN)), &exit, &inRange); + Branch(Int32GreaterThan(len, GetInt32Constant(panda::ecmascript::MAX_INDEX_LEN)), &exit, &inRange); Bind(&inRange); { AddrShift dataUtf16 = PtrAdd(string, GetPtrConstant(panda::ecmascript::EcmaString::GetDataOffset())); - DEFVARIABLE(c, UINT32_TYPE, GetInteger32Constant(0)); + DEFVARIABLE(c, MachineType::UINT32_TYPE, GetInt32Constant(0)); Label isUtf16(env); Label isUtf8(env); Label getChar1(env); @@ -915,34 +918,34 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Branch(isUtf16String, &isUtf16, &isUtf8); Bind(&isUtf16); { - c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16)); + c = ZExtInt16ToInt32(Load(MachineType::INT16_TYPE, dataUtf16)); Jump(&getChar1); } Bind(&isUtf8); { - c = ZExtInt8ToInt32(Load(INT8_TYPE, dataUtf16)); + c = ZExtInt8ToInt32(Load(MachineType::INT8_TYPE, dataUtf16)); Jump(&getChar1); } Bind(&getChar1); { Label isDigitZero(env); Label notDigitZero(env); - Branch(Word32Equal(*c, GetInteger32Constant('0')), &isDigitZero, ¬DigitZero); + Branch(Word32Equal(*c, GetInt32Constant('0')), &isDigitZero, ¬DigitZero); Bind(&isDigitZero); { Label lengthIsOne(env); - Branch(Word32Equal(len, GetInteger32Constant(1)), &lengthIsOne, &exit); + Branch(Word32Equal(len, GetInt32Constant(1)), &lengthIsOne, &exit); Bind(&lengthIsOne); { - result = GetInteger32Constant(0); + result = GetInt32Constant(0); Jump(&exit); } } Bind(¬DigitZero); { Label isDigit(env); - DEFVARIABLE(i, UINT32_TYPE, GetInteger32Constant(1)); - DEFVARIABLE(n, UINT32_TYPE, Int32Sub(*c, GetInteger32Constant('0'))); + DEFVARIABLE(i, MachineType::UINT32_TYPE, GetInt32Constant(1)); + DEFVARIABLE(n, MachineType::UINT32_TYPE, Int32Sub(*c, GetInt32Constant('0'))); Branch(IsDigit(*c), &isDigit, &exit); Label loopHead(env); Label loopEnd(env); @@ -959,12 +962,12 @@ AddrShift Stub::StringToElementIndex(AddrShift string) { // 2 : 2 means utf16 char width is two bytes auto charOffset = PtrMul(ChangeInt32ToPointer(*i), GetPtrConstant(2)); - c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, charOffset)); + c = ZExtInt16ToInt32(Load(MachineType::INT16_TYPE, dataUtf16, charOffset)); Jump(&getChar2); } Bind(¬Utf16); { - c = ZExtInt8ToInt32(Load(INT8_TYPE, dataUtf16, ChangeInt32ToPointer(*i))); + c = ZExtInt8ToInt32(Load(MachineType::INT8_TYPE, dataUtf16, ChangeInt32ToPointer(*i))); Jump(&getChar2); } Bind(&getChar2); @@ -975,9 +978,9 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Bind(&isDigit2); { // 10 means the base of digit is 10. - n = Int32Add(Int32Mul(*n, GetInteger32Constant(10)), - Int32Sub(*c, GetInteger32Constant('0'))); - i = Int32Add(*i, GetInteger32Constant(1)); + n = Int32Add(Int32Mul(*n, GetInt32Constant(10)), + Int32Sub(*c, GetInt32Constant('0'))); + i = Int32Add(*i, GetInt32Constant(1)); Branch(Int32LessThan(*i, len), &loopEnd, &afterLoop); } Bind(¬Digit2); @@ -989,7 +992,7 @@ AddrShift Stub::StringToElementIndex(AddrShift string) Bind(&afterLoop); { Label lessThanMaxIndex(env); - Branch(Word32LessThan(*n, GetInteger32Constant(panda::ecmascript::JSObject::MAX_ELEMENT_INDEX)), + Branch(Word32LessThan(*n, GetInt32Constant(panda::ecmascript::JSObject::MAX_ELEMENT_INDEX)), &lessThanMaxIndex, &exit); Bind(&lessThanMaxIndex); { @@ -1015,7 +1018,7 @@ AddrShift Stub::TryToElementsIndex(AddrShift key) Label isKeyInt(env); Label notKeyInt(env); - DEFVARIABLE(resultKey, INT32_TYPE, GetInteger32Constant(-1)); + DEFVARIABLE(resultKey, MachineType::INT32_TYPE, GetInt32Constant(-1)); Branch(TaggedIsInt(key), &isKeyInt, ¬KeyInt); Bind(&isKeyInt); { @@ -1055,4 +1058,4 @@ AddrShift Stub::TryToElementsIndex(AddrShift key) env->PopCurrentLabel(); return ret; } -} // namespace kungfu \ No newline at end of file +} // namespace kungfu diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 3a12f0b..a4ae182 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -21,11 +21,13 @@ #include "ecmascript/compiler/circuit.h" #include "ecmascript/compiler/circuit_builder.h" #include "ecmascript/compiler/gate.h" +#include "ecmascript/compiler/machine_type.h" #include "ecmascript/compiler/stub_descriptor.h" #include "ecmascript/js_function.h" #include "ecmascript/js_object.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/layout_info.h" +#include "ecmascript/message_string.h" #include "ecmascript/tagged_dictionary.h" namespace kungfu { @@ -394,7 +396,7 @@ public: return &env_; } // constant - AddrShift GetInteger32Constant(int32_t value) + AddrShift GetInt32Constant(int32_t value) { return env_.GetCircuitBuilder().NewIntegerConstant(value); }; @@ -409,13 +411,13 @@ public: return GetWord64Constant(value); #endif #ifdef PANDA_TARGET_X86 - return GetInteger32Constant(value); + return GetInt32Constant(value); #endif #ifdef PANDA_TARGET_ARM64 return GetWord64Constant(value); #endif #ifdef PANDA_TARGET_ARM32 - return GetInteger32Constant(value); + return GetInt32Constant(value); #endif } @@ -437,12 +439,12 @@ public: AddrShift TrueConstant() { - return TruncInt32ToInt1(GetInteger32Constant(1)); + return TruncInt32ToInt1(GetInt32Constant(1)); } AddrShift FalseConstant() { - return TruncInt32ToInt1(GetInteger32Constant(0)); + return TruncInt32ToInt1(GetInt32Constant(0)); } AddrShift GetBooleanConstant(bool value) @@ -788,7 +790,7 @@ public: AddrShift TaggedIsDouble(AddrShift x) { return Word32Equal(Word32Or(SExtInt1ToInt32(TaggedIsInt(x)), SExtInt1ToInt32(TaggedIsObject(x))), - GetInteger32Constant(0)); + GetInt32Constant(0)); } AddrShift TaggedIsObject(AddrShift x) @@ -832,7 +834,7 @@ public: { return TruncInt32ToInt1( Word32And(SExtInt1ToInt32(TaggedIsObject(x)), - SExtInt1ToInt32(Word32Equal(SExtInt1ToInt32(TaggedIsSpecial(x)), GetInteger32Constant(0))))); + SExtInt1ToInt32(Word32Equal(SExtInt1ToInt32(TaggedIsSpecial(x)), GetInt32Constant(0))))); } AddrShift TaggedIsString(AddrShift obj); @@ -841,15 +843,15 @@ public: AddrShift GetNextPositionForHash(AddrShift last, AddrShift count, AddrShift size) { - auto nextOffset = Word32LSR(Int32Mul(count, Int32Add(count, GetInteger32Constant(1))), - GetInteger32Constant(1)); - return Word32And(Int32Add(last, nextOffset), Int32Sub(size, GetInteger32Constant(1))); + auto nextOffset = Word32LSR(Int32Mul(count, Int32Add(count, GetInt32Constant(1))), + GetInt32Constant(1)); + return Word32And(Int32Add(last, nextOffset), Int32Sub(size, GetInt32Constant(1))); } AddrShift DoubleIsNAN(AddrShift x) { AddrShift diff = DoubleEqual(x, x); - return Word32Equal(SExtInt1ToInt32(diff), GetInteger32Constant(0)); + return Word32Equal(SExtInt1ToInt32(diff), GetInt32Constant(0)); } AddrShift DoubleIsINF(AddrShift x) @@ -858,8 +860,8 @@ public: AddrShift negativeInfinity = GetDoubleConstant(-base::POSITIVE_INFINITY); AddrShift diff1 = DoubleEqual(x, infinity); AddrShift diff2 = DoubleEqual(x, negativeInfinity); - return TruncInt32ToInt1(Word32Or(Word32Equal(SExtInt1ToInt32(diff1), GetInteger32Constant(1)), - Word32Equal(SExtInt1ToInt32(diff2), GetInteger32Constant(1)))); + return TruncInt32ToInt1(Word32Or(Word32Equal(SExtInt1ToInt32(diff1), GetInt32Constant(1)), + Word32Equal(SExtInt1ToInt32(diff2), GetInt32Constant(1)))); } AddrShift IntBuildTagged(AddrShift x) @@ -1023,7 +1025,7 @@ public: AddrShift GetElements(AddrShift object) { - AddrShift elementsOffset = GetInteger32Constant(panda::ecmascript::JSObject::ELEMENTS_OFFSET); + AddrShift elementsOffset = GetInt32Constant(panda::ecmascript::JSObject::ELEMENTS_OFFSET); if (PtrValueCode() == ValueCode::INT64) { elementsOffset = SExtInt32ToInt64(elementsOffset); } @@ -1033,7 +1035,7 @@ public: AddrShift GetProperties(AddrShift object) { - AddrShift propertiesOffset = GetInteger32Constant(panda::ecmascript::JSObject::PROPERTIES_OFFSET); + AddrShift propertiesOffset = GetInt32Constant(panda::ecmascript::JSObject::PROPERTIES_OFFSET); if (PtrValueCode() == ValueCode::INT64) { propertiesOffset = SExtInt32ToInt64(propertiesOffset); } @@ -1043,36 +1045,34 @@ public: AddrShift GetLengthofElements(AddrShift elements) { - return Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + return Load(MachineType::UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); } // object operation AddrShift LoadHClass(AddrShift object) { - return ChangeInt32ToPointer(Load(UINT32_TYPE, object)); + return ChangeInt32ToPointer(Load(MachineType::UINT32_TYPE, object)); } - AddrShift GetObjectType(AddrShift hclass) + AddrShift GetObjectType(AddrShift hClass) { AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); - + AddrShift bitfield = Load(MachineType::UINT64_TYPE, hClass, bitfieldOffset); return ChangeInt64ToInt32( Word64And(bitfield, GetWord64Constant((1LLU << panda::ecmascript::JSHClass::ObjectTypeBits::SIZE) - 1))); } AddrShift IsDictionaryMode(AddrShift object) { - return Word32NotEqual(Word32And(Load(UINT32_TYPE, LoadHClass(object), GetPtrConstant(0)), - GetInteger32Constant(panda::HClass::IS_DICTIONARY_ARRAY)), - GetInteger32Constant(0)); + return Word32NotEqual(Word32And(Load(MachineType::UINT32_TYPE, LoadHClass(object), GetPtrConstant(0)), + GetInt32Constant(panda::HClass::IS_DICTIONARY_ARRAY)), + GetInt32Constant(0)); } AddrShift IsDictionaryModeByHClass(AddrShift hClass) { AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift bitfield = Load(INT64_TYPE, hClass, bitfieldOffset); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); return Word64NotEqual( Word64And( Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::IsDictionaryBit::START_BIT)), @@ -1080,11 +1080,10 @@ public: GetWord64Constant(0)); } - AddrShift IsDictionaryElement(AddrShift hclass) + AddrShift IsDictionaryElement(AddrShift hClass) { AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); // decode return Word64NotEqual( Word64And( @@ -1098,7 +1097,7 @@ public: AddrShift hclass = LoadHClass(object); AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hclass, bitfieldOffset); // decode return Word64Equal( Word64And( @@ -1124,10 +1123,10 @@ public: AddrShift IsExtensible(AddrShift object) { - AddrShift hclass = LoadHClass(object); + AddrShift hClass = LoadHClass(object); AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); // decode return Word64NotEqual( Word64And(Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::ExtensibleBit::START_BIT)), @@ -1138,70 +1137,77 @@ public: AddrShift IsSymbol(AddrShift obj) { AddrShift objectType = GetObjectType(LoadHClass(obj)); - return Word32Equal(objectType, GetInteger32Constant(static_cast(panda::ecmascript::JSType::SYMBOL))); + return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::SYMBOL))); } AddrShift IsString(AddrShift obj) { AddrShift objectType = GetObjectType(LoadHClass(obj)); - return Word32Equal(objectType, GetInteger32Constant(static_cast(panda::ecmascript::JSType::STRING))); + return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::STRING))); } AddrShift IsJsProxy(AddrShift obj) { AddrShift objectType = GetObjectType(LoadHClass(obj)); - return Word32Equal(objectType, GetInteger32Constant(static_cast(panda::ecmascript::JSType::JS_PROXY))); + return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::JS_PROXY))); + } + + AddrShift IsJsArray(AddrShift obj) + { + AddrShift objectType = GetObjectType(LoadHClass(obj)); + return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::JS_ARRAY))); } AddrShift IsWritable(AddrShift attr) { return Word32NotEqual( Word32And( - Word32LSR(attr, GetInteger32Constant(panda::ecmascript::PropertyAttributes::WritableField::START_BIT)), - GetInteger32Constant((1LLU << panda::ecmascript::PropertyAttributes::WritableField::SIZE) - 1)), - GetInteger32Constant(0)); + Word32LSR(attr, GetInt32Constant(panda::ecmascript::PropertyAttributes::WritableField::START_BIT)), + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::WritableField::SIZE) - 1)), + GetInt32Constant(0)); } AddrShift IsAccessor(AddrShift attr) { return Word32NotEqual( Word32And(Word32LSR(attr, - GetInteger32Constant(panda::ecmascript::PropertyAttributes::IsAccessorField::START_BIT)), - GetInteger32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsAccessorField::SIZE) - 1)), - GetInteger32Constant(0)); + GetInt32Constant(panda::ecmascript::PropertyAttributes::IsAccessorField::START_BIT)), + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsAccessorField::SIZE) - 1)), + GetInt32Constant(0)); } AddrShift IsInlinedProperty(AddrShift attr) { return Word32NotEqual( Word32And(Word32LSR(attr, - GetInteger32Constant(panda::ecmascript::PropertyAttributes::IsInlinedPropsField::START_BIT)), - GetInteger32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsInlinedPropsField::SIZE) - 1)), - GetInteger32Constant(0)); + GetInt32Constant(panda::ecmascript::PropertyAttributes::IsInlinedPropsField::START_BIT)), + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsInlinedPropsField::SIZE) - 1)), + GetInt32Constant(0)); } AddrShift PropAttrGetOffset(AddrShift attr) { return Word32And( - Word32LSR(attr, GetInteger32Constant(panda::ecmascript::PropertyAttributes::OffsetField::START_BIT)), - GetInteger32Constant((1LLU << panda::ecmascript::PropertyAttributes::OffsetField::SIZE) - 1)); + Word32LSR(attr, GetInt32Constant(panda::ecmascript::PropertyAttributes::OffsetField::START_BIT)), + GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::OffsetField::SIZE) - 1)); } - AddrShift GetPrototypeFromHClass(AddrShift hclass) + AddrShift GetPrototypeFromHClass(AddrShift hClass) { AddrShift protoOffset = GetPtrConstant(panda::ecmascript::JSHClass::PROTOTYPE_OFFSET); - return Load(TAGGED_TYPE, hclass, protoOffset); + return Load(MachineType::TAGGED_TYPE, hClass, protoOffset); } - AddrShift GetAttributesFromHclass(AddrShift hclass) + AddrShift GetAttributesFromHclass(AddrShift hClass) { AddrShift attrOffset = GetPtrConstant(panda::ecmascript::JSHClass::ATTRIBUTES_OFFSET); - return Load(TAGGED_TYPE, hclass, attrOffset); + return Load(MachineType::TAGGED_TYPE, hClass, attrOffset); } - AddrShift GetPropertiesNumberFromHClass(AddrShift hclass) + AddrShift GetPropertiesNumberFromHClass(AddrShift hClass) { - AddrShift bitfield = Load(INT64_TYPE, hclass, GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET)); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, + GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET)); AddrShift unusedNonInlinedProps = Word64And(Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::NumberOfUnusedNonInlinedPropsBits::START_BIT)), GetWord64Constant((1LLU << panda::ecmascript::JSHClass::NumberOfUnusedNonInlinedPropsBits::SIZE) - 1)); @@ -1214,9 +1220,9 @@ public: unusedInlinedProps); } - AddrShift GetObjectSizeFromHClass(AddrShift hclass) // NOTE: need to add special case for string and TAGGED_ARRAY + AddrShift GetObjectSizeFromHClass(AddrShift hClass) // NOTE: need to add special case for string and TAGGED_ARRAY { - return Load(UINT64_TYPE, hclass, GetPtrConstant(panda::ecmascript::JSHClass::OBJECT_SIZE_OFFSET)); + return Load(MachineType::UINT64_TYPE, hClass, GetPtrConstant(panda::ecmascript::JSHClass::OBJECT_SIZE_OFFSET)); } void StoreElement(AddrShift elements, AddrShift index, AddrShift value) @@ -1224,7 +1230,7 @@ public: AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())); AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - Store(TAGGED_TYPE, elements, dataOffset, value); + Store(MachineType::TAGGED_TYPE, elements, dataOffset, value); } void ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val); @@ -1234,40 +1240,40 @@ public: AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())); AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - return Load(TAGGED_TYPE, elements, dataOffset); + return Load(MachineType::TAGGED_TYPE, elements, dataOffset); } AddrShift TaggedToRepresentation(AddrShift value); - AddrShift GetElementRepresentation(AddrShift hclass) + AddrShift GetElementRepresentation(AddrShift hClass) { AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); return Word64And( Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::ElementRepresentationBits::START_BIT)), GetWord64Constant(((1LLU << panda::ecmascript::JSHClass::ElementRepresentationBits::SIZE) - 1))); } - void SetElementRepresentation(AddrShift hclass, AddrShift value) + void SetElementRepresentation(AddrShift hClass, AddrShift value) { AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift oldValue = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift oldValue = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); AddrShift oldWithMask = Word64And(oldValue, GetWord64Constant(~panda::ecmascript::JSHClass::ElementRepresentationBits::Mask())); AddrShift newValue = Word64LSR(value, GetWord64Constant( panda::ecmascript::JSHClass::ElementRepresentationBits::START_BIT)); - Store(INT64_TYPE, hclass, bitfieldOffset, Word64Or(oldWithMask, newValue)); + Store(MachineType::INT64_TYPE, hClass, bitfieldOffset, Word64Or(oldWithMask, newValue)); } void UpdateValueAndAttributes(AddrShift elements, AddrShift index, AddrShift value, AddrShift attr) { AddrShift arrayIndex = - Int32Add(GetInteger32Constant(panda::ecmascript::NameDictionary::TABLE_HEADER_SIZE), - Int32Mul(index, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_SIZE))); + Int32Add(GetInt32Constant(panda::ecmascript::NameDictionary::TABLE_HEADER_SIZE), + Int32Mul(index, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_SIZE))); AddrShift valueIndex = - Int32Add(arrayIndex, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); + Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); AddrShift attributesIndex = - Int32Add(arrayIndex, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); + Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); StoreElement(elements, valueIndex, value); StoreElement(elements, attributesIndex, IntBuildTagged(attr)); } @@ -1275,36 +1281,36 @@ public: AddrShift IsSpecialIndexedObj(AddrShift jsType) { return Int32GreaterThan(jsType, - GetInteger32Constant(static_cast(panda::ecmascript::JSType::JS_ARRAY))); + GetInt32Constant(static_cast(panda::ecmascript::JSType::JS_ARRAY))); } AddrShift IsAccessorInternal(AddrShift value) { return Word32Equal(GetObjectType(LoadHClass(value)), - GetInteger32Constant(static_cast(panda::ecmascript::JSType::INTERNAL_ACCESSOR))); + GetInt32Constant(static_cast(panda::ecmascript::JSType::INTERNAL_ACCESSOR))); } - void UpdateAndStoreRepresention(AddrShift hclass, AddrShift value); + void UpdateAndStoreRepresention(AddrShift hClass, AddrShift value); AddrShift UpdateRepresention(AddrShift oldRep, AddrShift value); AddrShift GetAttributesFromDictionary(AddrShift elements, AddrShift entry) { AddrShift arrayIndex = - Int32Add(GetInteger32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), - Int32Mul(entry, GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); + Int32Add(GetInt32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), + Int32Mul(entry, GetInt32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); AddrShift attributesIndex = - Int32Add(arrayIndex, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); + Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); return TaggedCastToInt32(GetValueFromTaggedArray(elements, attributesIndex)); } AddrShift GetValueFromDictionary(AddrShift elements, AddrShift entry) { AddrShift arrayIndex = - Int32Add(GetInteger32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), - Int32Mul(entry, GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); + Int32Add(GetInt32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), + Int32Mul(entry, GetInt32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); AddrShift valueIndex = - Int32Add(arrayIndex, GetInteger32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); + Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); return GetValueFromTaggedArray(elements, valueIndex); } @@ -1313,9 +1319,9 @@ public: AddrShift GetPropAttrFromLayoutInfo(AddrShift layout, AddrShift entry) { AddrShift index = Int32Add( - Int32Add(GetInteger32Constant(panda::ecmascript::LayoutInfo::ELEMENTS_START_INDEX), - Word32LSL(entry, GetInteger32Constant(1))), - GetInteger32Constant(1)); + Int32Add(GetInt32Constant(panda::ecmascript::LayoutInfo::ELEMENTS_START_INDEX), + Word32LSL(entry, GetInt32Constant(1))), + GetInt32Constant(1)); return GetValueFromTaggedArray(layout, index); } @@ -1450,7 +1456,7 @@ public: AddrShift hclass = LoadHClass(obj); AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + AddrShift bitfield = Load(MachineType::INT64_TYPE, hclass, bitfieldOffset); // decode return Word64NotEqual( Word64And(Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::CallableBit::START_BIT)), diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index c979661..7e04dee 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -26,11 +26,10 @@ namespace kungfu { static void Initialize(StubDescriptor *descriptor); \ }; \ void Stub##name##InterfaceDescriptor::Initialize(StubDescriptor *descriptor) - CALL_STUB_INIT_DESCRIPTOR(FastAdd) { // 2 : 2 input parameters - StubDescriptor fastAdd("FastAdd", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastAdd("FastAdd", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastAdd; // 2 : 2 input parameters std::array params = { @@ -43,7 +42,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastAdd) CALL_STUB_INIT_DESCRIPTOR(FastSub) { // 2 : 2 input parameters - StubDescriptor fastSub("FastSub", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastSub("FastSub", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastSub; // 2 : 2 input parameters std::array params = { @@ -56,7 +55,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastSub) CALL_STUB_INIT_DESCRIPTOR(FastMul) { // 2 : 2 input parameters - StubDescriptor fastMul("FastMul", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastMul("FastMul", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastMul; // 2 : 2 input parameters std::array params = { @@ -69,7 +68,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastMul) CALL_STUB_INIT_DESCRIPTOR(FastDiv) { // 2 : 2 input parameters - StubDescriptor fastDiv("FastDiv", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastDiv("FastDiv", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastDiv; // 2 : 2 input parameters std::array params = { @@ -82,7 +81,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastDiv) CALL_STUB_INIT_DESCRIPTOR(FastMod) { // 3 : 3 input parameters - StubDescriptor fastMod("FastMod", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastMod("FastMod", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastMod; // 3 : 3 input parameters std::array params = { @@ -96,7 +95,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastMod) CALL_STUB_INIT_DESCRIPTOR(FloatMod) { // 2 : 2 input parameters - StubDescriptor floatMod("FloatMod", 0, 2, ArgumentsOrder::DEFAULT_ORDER, FLOAT64_TYPE); + StubDescriptor floatMod("FloatMod", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::FLOAT64_TYPE); *descriptor = floatMod; // 2 : 2 input parameters std::array params = { @@ -112,7 +111,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastEqual) {} CALL_STUB_INIT_DESCRIPTOR(FastTypeOf) { // 2 input parameters - StubDescriptor fastTypeOf("FastTypeOf", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor fastTypeOf("FastTypeOf", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastTypeOf; // 2 input parameters std::array params = { @@ -131,7 +130,7 @@ CALL_STUB_INIT_DESCRIPTOR(IsSpecialIndexedObjForGet) {} CALL_STUB_INIT_DESCRIPTOR(GetElement) { // 3 : 3 input parameters - StubDescriptor getElement("GetElement", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor getElement("GetElement", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = getElement; // 3 : 3 input parameters std::array params = { @@ -145,7 +144,7 @@ CALL_STUB_INIT_DESCRIPTOR(GetElement) CALL_STUB_INIT_DESCRIPTOR(SetElement) { // 5 : 5 input parameters - StubDescriptor setElement("SetElement", 0, 5, ArgumentsOrder::DEFAULT_ORDER, BOOL_TYPE); + StubDescriptor setElement("SetElement", 0, 5, ArgumentsOrder::DEFAULT_ORDER, MachineType::BOOL_TYPE); *descriptor = setElement; // 5 : 5 input parameters std::array params = { @@ -160,13 +159,12 @@ CALL_STUB_INIT_DESCRIPTOR(SetPropertyByName) {} CALL_STUB_INIT_DESCRIPTOR(GetPropertyByName) { // 3 : 3 input parameters - StubDescriptor getPropertyByName("GetPropertyByName", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor getPropertyByName("GetPropertyByName", 0, 3, ArgumentsOrder::DEFAULT_ORDER, + MachineType::UINT64_TYPE); *descriptor = getPropertyByName; // 3 : 3 input parameters std::array params = { - MachineType::UINT64_TYPE, - MachineType::UINT64_TYPE, - MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, }; descriptor->SetParameters(params.data()); } @@ -188,7 +186,7 @@ CALL_STUB_INIT_DESCRIPTOR(FindOwnProperty) {} CALL_STUB_INIT_DESCRIPTOR(FindOwnElement) { // 3 : 3 input parameters - StubDescriptor findOwnElement("FindOwnElement", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor findOwnElement("FindOwnElement", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = findOwnElement; // 3 : 3 input parameters std::array params = { @@ -206,7 +204,7 @@ CALL_STUB_INIT_DESCRIPTOR(FindOwnProperty2) {} CALL_STUB_INIT_DESCRIPTOR(FindOwnElement2) { // 6 : 6 input parameters - StubDescriptor findOwnElement2("FindOwnElement2", 0, 6, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor findOwnElement2("FindOwnElement2", 0, 6, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = findOwnElement2; // 6 : 6 input parameters std::array params = { @@ -219,7 +217,8 @@ CALL_STUB_INIT_DESCRIPTOR(FindOwnElement2) CALL_STUB_INIT_DESCRIPTOR(GetPropertyByIndex) { // 3 : 3 input parameters - StubDescriptor getPropertyByIndex("GetPropertyByIndex", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor getPropertyByIndex("GetPropertyByIndex", 0, 3, ArgumentsOrder::DEFAULT_ORDER, + MachineType::UINT64_TYPE); *descriptor = getPropertyByIndex; // 3 : 3 input parameters std::array params = { @@ -233,7 +232,8 @@ CALL_STUB_INIT_DESCRIPTOR(GetPropertyByIndex) CALL_STUB_INIT_DESCRIPTOR(SetPropertyByIndex) { // 4 : 4 input parameters - StubDescriptor setPropertyByIndex("SetPropertyByIndex", 0, 4, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor setPropertyByIndex("SetPropertyByIndex", 0, 4, ArgumentsOrder::DEFAULT_ORDER, + MachineType::UINT64_TYPE); *descriptor = setPropertyByIndex; // 4 : 4 input parameters std::array params = { @@ -248,7 +248,7 @@ CALL_STUB_INIT_DESCRIPTOR(SetPropertyByIndex) CALL_STUB_INIT_DESCRIPTOR(GetPropertyByValue) { // 3 : 3 input parameters - StubDescriptor getPropertyByValue("GetPropertyByValue", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor getPropertyByValue("GetPropertyByValue", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = getPropertyByValue; // 3 : 3 input parameters std::array params = { @@ -267,7 +267,8 @@ CALL_STUB_INIT_DESCRIPTOR(SetPropertyByValue) CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) { // 5 : 5 input parameters - StubDescriptor addElementInternal("AddElementInternal", 0, 5, ArgumentsOrder::DEFAULT_ORDER, BOOL_TYPE); + StubDescriptor addElementInternal("AddElementInternal", 0, 5, ArgumentsOrder::DEFAULT_ORDER, + MachineType::BOOL_TYPE); *descriptor = addElementInternal; // 5 : 5 input parameters std::array params = { @@ -278,10 +279,22 @@ CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } +CALL_STUB_INIT_DESCRIPTOR(GetTaggedArrayPtr) +{ + static StubDescriptor getTaggedArrayPtr("GetTaggedArrayPtr", 0, 1, ArgumentsOrder::DEFAULT_ORDER, + MachineType::TAGGED_POINTER_TYPE); + *descriptor = getTaggedArrayPtr; + std::array params = { + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + CALL_STUB_INIT_DESCRIPTOR(CallSetter) { // 5 : 5 input parameters - StubDescriptor callSetter("CallSetter", 0, 5, ArgumentsOrder::DEFAULT_ORDER, BOOL_TYPE); + StubDescriptor callSetter("CallSetter", 0, 5, ArgumentsOrder::DEFAULT_ORDER, MachineType::BOOL_TYPE); *descriptor = callSetter; // 5 : 5 input parameters std::array params = { @@ -295,7 +308,7 @@ CALL_STUB_INIT_DESCRIPTOR(CallSetter) CALL_STUB_INIT_DESCRIPTOR(CallGetter) { // 3 : 3 input parameters - StubDescriptor callGetter("CallGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor callGetter("CallGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = callGetter; // 3 : 3 input parameters std::array params = { @@ -310,7 +323,7 @@ CALL_STUB_INIT_DESCRIPTOR(CallGetter) CALL_STUB_INIT_DESCRIPTOR(AccessorGetter) { // 3 : 3 input parameters - StubDescriptor accessorGetter("AccessorGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor accessorGetter("AccessorGetter", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = accessorGetter; // 3 : 3 input parameters std::array params = { @@ -325,7 +338,7 @@ CALL_STUB_INIT_DESCRIPTOR(AccessorGetter) CALL_STUB_INIT_DESCRIPTOR(ThrowTypeError) { // 2 : 2 input parameters - StubDescriptor throwTypeError("ThrowTypeError", 0, 2, ArgumentsOrder::DEFAULT_ORDER, NONE_TYPE); + StubDescriptor throwTypeError("ThrowTypeError", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::BOOL_TYPE); *descriptor = throwTypeError; // 2 : 2 input parameters std::array params = { @@ -339,7 +352,8 @@ CALL_STUB_INIT_DESCRIPTOR(ThrowTypeError) CALL_STUB_INIT_DESCRIPTOR(JSProxySetProperty) { // 6 : 6 input parameters - StubDescriptor jsproxySetproperty("JSProxySetProperty", 0, 6, ArgumentsOrder::DEFAULT_ORDER, BOOL_TYPE); + StubDescriptor jsproxySetproperty("JSProxySetProperty", 0, 6, + ArgumentsOrder::DEFAULT_ORDER, MachineType::BOOL_TYPE); *descriptor = jsproxySetproperty; // 6 : 6 input parameters std::array params = { @@ -353,7 +367,7 @@ CALL_STUB_INIT_DESCRIPTOR(JSProxySetProperty) CALL_STUB_INIT_DESCRIPTOR(GetHash32) { // 2 : 2 input parameters - StubDescriptor getHash32("GetHash32", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + StubDescriptor getHash32("GetHash32", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT32_TYPE); *descriptor = getHash32; // 2 : 2 input parameters std::array params = { @@ -367,7 +381,8 @@ CALL_STUB_INIT_DESCRIPTOR(GetHash32) CALL_STUB_INIT_DESCRIPTOR(FindElementWithCache) { // 4 : 4 input parameters - StubDescriptor findElementWithCache("FindElementWithCache", 0, 4, ArgumentsOrder::DEFAULT_ORDER, INT32_TYPE); + StubDescriptor findElementWithCache("FindElementWithCache", 0, 4, + ArgumentsOrder::DEFAULT_ORDER, MachineType::INT32_TYPE); *descriptor = findElementWithCache; std::array params = { // 4 : 4 input parameters MachineType::UINT64_TYPE, @@ -382,7 +397,7 @@ CALL_STUB_INIT_DESCRIPTOR(FindElementWithCache) CALL_STUB_INIT_DESCRIPTOR(Execute) { // 5 : 5 input parameters - StubDescriptor execute("Execute", 0, 5, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor execute("Execute", 0, 5, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = execute; std::array params = { // 5 : 5 input parameters MachineType::UINT64_TYPE, @@ -399,7 +414,7 @@ CALL_STUB_INIT_DESCRIPTOR(FunctionCallInternal) { // 5 : 5 input parameters StubDescriptor functionCallInternal("FunctionCallInternal", 0, 5, - ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = functionCallInternal; std::array params = { // 5 : 5 input parameters MachineType::UINT64_TYPE, @@ -414,7 +429,8 @@ CALL_STUB_INIT_DESCRIPTOR(FunctionCallInternal) CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) { - StubDescriptor stringGetHashCode("StringGetHashCode", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + StubDescriptor stringGetHashCode("StringGetHashCode", 0, 1, + ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT32_TYPE); *descriptor = stringGetHashCode; std::array params = { MachineType::UINT64_TYPE, @@ -423,10 +439,27 @@ CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } +CALL_STUB_INIT_DESCRIPTOR(SetValueWithBarrier) +{ + // 4 : 4 input parameters + static StubDescriptor SetValueWithBarrier("SetValueWithBarrier", 0, 4, + ArgumentsOrder::DEFAULT_ORDER, MachineType::NONE_TYPE); + *descriptor = SetValueWithBarrier; + // 4 : 4 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + CALL_STUB_INIT_DESCRIPTOR(NewInternalString) { // 2 : 2 input parameters - StubDescriptor stringGetHashCode("NewInternalString", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + StubDescriptor stringGetHashCode("NewInternalString", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = stringGetHashCode; // 2 : 2 input parameters std::array params = { @@ -440,7 +473,7 @@ CALL_STUB_INIT_DESCRIPTOR(NewInternalString) CALL_STUB_INIT_DESCRIPTOR(FastLoadElement) { // 2 : 2 input parameters - StubDescriptor fastLoadElement("FastLoadElement", 0, 2, ArgumentsOrder::DEFAULT_ORDER, TAGGED_TYPE); + StubDescriptor fastLoadElement("FastLoadElement", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::TAGGED_TYPE); *descriptor = fastLoadElement; std::array params = { // 2 : 2 input parameters MachineType::UINT64_TYPE, @@ -452,7 +485,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastLoadElement) CALL_STUB_INIT_DESCRIPTOR(PhiGateTest) { - StubDescriptor phiGateTest("PhiGateTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + StubDescriptor phiGateTest("PhiGateTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT32_TYPE); *descriptor = phiGateTest; std::array params = { MachineType::UINT32_TYPE, @@ -463,7 +496,7 @@ CALL_STUB_INIT_DESCRIPTOR(PhiGateTest) CALL_STUB_INIT_DESCRIPTOR(LoopTest) { - StubDescriptor loopTest("LoopTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + StubDescriptor loopTest("LoopTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT32_TYPE); *descriptor = loopTest; std::array params = { MachineType::UINT32_TYPE, @@ -474,7 +507,7 @@ CALL_STUB_INIT_DESCRIPTOR(LoopTest) CALL_STUB_INIT_DESCRIPTOR(LoopTest1) { - StubDescriptor loopTest1("LoopTest1", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); + StubDescriptor loopTest1("LoopTest1", 0, 1, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT32_TYPE); *descriptor = loopTest1; std::array params = { MachineType::UINT32_TYPE, diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 3999065..ffa7d7c 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -114,22 +114,19 @@ public: void GenerateCircuit() override { auto env = GetEnvironment(); - DEFVARIABLE(z, MachineType::INT32_TYPE, GetInteger32Constant(0)); + DEFVARIABLE(z, MachineType::INT32_TYPE, GetInt32Constant(0)); DEFVARIABLE(x, MachineType::INT32_TYPE, Int32Argument(0)); Label ifTrue(env); Label ifFalse(env); Label next(env); - Branch(Word32Equal(*x, GetInteger32Constant(10)), &ifTrue, &ifFalse); // 10 : size of entry + + Branch(Word32Equal(*x, GetInt32Constant(10)), &ifTrue, &ifFalse); // 10 : size of entry Bind(&ifTrue); - { - z = Int32Add(*x, GetInteger32Constant(10)); // 10 : size of entry - Jump(&next); - } + z = Int32Add(*x, GetInt32Constant(10)); // 10 : size of entry + Jump(&next); Bind(&ifFalse); - { - z = Int32Add(*x, GetInteger32Constant(100)); // 100 : size of entry - Jump(&next); - } + z = Int32Add(*x, GetInt32Constant(100)); // 100 : size of entry + Jump(&next); Bind(&next); Return(*z); } @@ -166,27 +163,27 @@ public: void GenerateCircuit() override { auto env = GetEnvironment(); - DEFVARIABLE(z, MachineType::INT32_TYPE, GetInteger32Constant(0)); + DEFVARIABLE(z, MachineType::INT32_TYPE, GetInt32Constant(0)); DEFVARIABLE(y, MachineType::INT32_TYPE, Int32Argument(0)); Label loopHead(env); Label loopEnd(env); Label afterLoop(env); - Branch(Int32LessThan(*y, GetInteger32Constant(10)), &loopHead, &afterLoop); // 10 : size of entry + Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopHead, &afterLoop); // 10 : size of entry LoopBegin(&loopHead); Label ifTrue(env); Label ifFalse(env); Label next(env); - Branch(Word32Equal(Int32Argument(0), GetInteger32Constant(9)), &ifTrue, &ifFalse); // 9 : size of entry + Branch(Word32Equal(Int32Argument(0), GetInt32Constant(9)), &ifTrue, &ifFalse); // 9 : size of entry Bind(&ifTrue); - z = Int32Add(*y, GetInteger32Constant(10)); // 10 : size of entry - y = Int32Add(*z, GetInteger32Constant(1)); + z = Int32Add(*y, GetInt32Constant(10)); // 10 : size of entry + y = Int32Add(*z, GetInt32Constant(1)); Jump(&next); Bind(&ifFalse); - z = Int32Add(*y, GetInteger32Constant(100)); // 100 : size of entry + z = Int32Add(*y, GetInt32Constant(100)); // 100 : size of entry Jump(&next); Bind(&next); - y = Int32Add(*y, GetInteger32Constant(1)); - Branch(Int32LessThan(*y, GetInteger32Constant(10)), &loopEnd, &afterLoop); // 10 : size of entry + y = Int32Add(*y, GetInt32Constant(1)); + Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopEnd, &afterLoop); // 10 : size of entry Bind(&loopEnd); LoopEnd(&loopHead); Bind(&afterLoop); @@ -204,7 +201,7 @@ HWTEST_F_L0(StubTest, LoopTest) netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); PrintCircuitByBasicBlock(cfg, netOfGates); - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); @@ -233,18 +230,18 @@ public: Label loopHead(env); Label loopEnd(env); Label afterLoop(env); - Branch(Int32LessThan(*y, GetInteger32Constant(10)), &loopHead, &afterLoop); // 10 : size of entry + Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopHead, &afterLoop); // 10 : size of entry LoopBegin(&loopHead); - x = Int32Add(*z, GetInteger32Constant(3)); // 3 : size of entry + x = Int32Add(*z, GetInt32Constant(3)); // 3 : size of entry Label ifTrue(env); Label next(env); - Branch(Word32Equal(*x, GetInteger32Constant(9)), &ifTrue, &next); // 9 : size of entry + Branch(Word32Equal(*x, GetInt32Constant(9)), &ifTrue, &next); // 9 : size of entry Bind(&ifTrue); y = Int32Add(*z, *x); Jump(&next); Bind(&next); - y = Int32Add(*y, GetInteger32Constant(1)); - Branch(Int32LessThan(*y, GetInteger32Constant(10)), &loopEnd, &afterLoop); // 10 : size of entry + y = Int32Add(*y, GetInt32Constant(1)); + Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopEnd, &afterLoop); // 10 : size of entry Bind(&loopEnd); LoopEnd(&loopHead); Bind(&afterLoop); @@ -255,8 +252,7 @@ public: HWTEST_F_L0(StubTest, LoopTest1) { - LLVMModuleRef module = LLVMModuleCreateWithName("simple_module"); - LLVMSetTarget(module, "x86_64-unknown-linux-gnu"); + auto module = stubModule.GetModule(); LLVMTypeRef paramTys[] = { LLVMInt32Type(), }; @@ -267,7 +263,7 @@ HWTEST_F_L0(StubTest, LoopTest1) netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); PrintCircuitByBasicBlock(cfg, netOfGates); - LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, function); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); @@ -1033,6 +1029,7 @@ HWTEST_F_L0(StubTest, LoadGCIRTest) std::unique_ptr rawModule = parseIRFile(inputFilename, err, context); if (!rawModule) { std::cout << "parseIRFile :" << inputFilename.data() << " failed !" << std::endl; + err.print("parseIRFile ", llvm::errs()); return; } LLVMModuleRef module = LLVMCloneModule(wrap(rawModule.get())); -- Gitee From 0f0321fac300525cf0ef8c2d84c80b26f5c4f5a7 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Sat, 30 Oct 2021 10:40:31 +0800 Subject: [PATCH 106/115] code review Signed-off-by: songzhengchao --- ecmascript/compiler/fast_stub.cpp | 11 +++++------ ecmascript/compiler/stub_descriptor.cpp | 18 ++++-------------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 3951277..7c1aaa3 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -380,7 +380,6 @@ void FindOwnElementStub::GenerateCircuit() Bind(&invalidValue); Return(GetHoleConstant()); } - // IsDictionary Bind(&isDict); { AddrShift taggedIndex = IntBuildTagged(index); @@ -1205,7 +1204,7 @@ void FastTypeOfStub::GenerateCircuit() { resultRep = Load( MachineType::TAGGED_TYPE, gConstOffset, - GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); + GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); Jump(&exit); } Bind(&objNotNull); @@ -1239,7 +1238,7 @@ void FastTypeOfStub::GenerateCircuit() { resultRep = Load( MachineType::TAGGED_TYPE, gConstOffset, - GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX)); + GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX)); Jump(&exit); } Bind(&objNotString); @@ -1262,14 +1261,14 @@ void FastTypeOfStub::GenerateCircuit() { resultRep = Load( MachineType::TAGGED_TYPE, gConstOffset, - GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX)); + GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX)); Jump(&exit); } Bind(&objNotCallable); { resultRep = Load( MachineType::TAGGED_TYPE, gConstOffset, - GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); + GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); Jump(&exit); } } @@ -1284,7 +1283,7 @@ void FastTypeOfStub::GenerateCircuit() { resultRep = Load( MachineType::TAGGED_TYPE, gConstOffset, - GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX)); + GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX)); Jump(&exit); } Bind(&objNotNum); diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 7e04dee..cda345c 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -248,7 +248,8 @@ CALL_STUB_INIT_DESCRIPTOR(SetPropertyByIndex) CALL_STUB_INIT_DESCRIPTOR(GetPropertyByValue) { // 3 : 3 input parameters - StubDescriptor getPropertyByValue("GetPropertyByValue", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); + StubDescriptor getPropertyByValue("GetPropertyByValue", 0, 3, + ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = getPropertyByValue; // 3 : 3 input parameters std::array params = { @@ -279,18 +280,6 @@ CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } -CALL_STUB_INIT_DESCRIPTOR(GetTaggedArrayPtr) -{ - static StubDescriptor getTaggedArrayPtr("GetTaggedArrayPtr", 0, 1, ArgumentsOrder::DEFAULT_ORDER, - MachineType::TAGGED_POINTER_TYPE); - *descriptor = getTaggedArrayPtr; - std::array params = { - MachineType::UINT64_TYPE, - }; - descriptor->SetParameters(params.data()); - descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); -} - CALL_STUB_INIT_DESCRIPTOR(CallSetter) { // 5 : 5 input parameters @@ -459,7 +448,8 @@ CALL_STUB_INIT_DESCRIPTOR(SetValueWithBarrier) CALL_STUB_INIT_DESCRIPTOR(NewInternalString) { // 2 : 2 input parameters - StubDescriptor stringGetHashCode("NewInternalString", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); + StubDescriptor stringGetHashCode("NewInternalString", 0, 2, + ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = stringGetHashCode; // 2 : 2 input parameters std::array params = { -- Gitee From b975e6fd95cd01b987357fc0accc6dfdb09297c9 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Sat, 30 Oct 2021 14:25:13 +0800 Subject: [PATCH 107/115] code review Signed-off-by: songzhengchao --- ecmascript/compiler/stub.cpp | 39 +----------------------- ecmascript/compiler/stub.h | 59 +----------------------------------- 2 files changed, 2 insertions(+), 96 deletions(-) diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index ea59218..f2cf0f0 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -624,7 +624,7 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a DEFVARIABLE(result, MachineType::TAGGED_TYPE, GetUndefinedConstant()); Label inlinedProp(env); Label notInlinedProp(env); - AddrShift attrOffset = GetOffsetFieldInPropAttr(attr); + AddrShift attrOffset = PropAttrGetOffset(attr); Branch(IsInlinedProperty(attr), &inlinedProp, ¬InlinedProp); { Bind(&inlinedProp); @@ -655,43 +655,6 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a return ret; } -AddrShift Stub::ShouldCallSetter(AddrShift receiver, AddrShift holder, AddrShift accessor, AddrShift attr) -{ - auto env = GetEnvironment(); - Label subEntry(env); - env->PushCurrentLabel(&subEntry); - Label exit(env); - DEFVARIABLE(result, MachineType::BOOL_TYPE, TrueConstant()); - Label isInternal(env); - Label notInternal(env); - Branch(IsAccessorInternal(accessor), &isInternal, ¬Internal); - Bind(&isInternal); - { - Label receiverEqualsHolder(env); - Label receiverNotEqualsHolder(env); - Branch(Word64Equal(receiver, holder), &receiverEqualsHolder, &receiverNotEqualsHolder); - Bind(&receiverEqualsHolder); - { - result = IsWritable(attr); - Jump(&exit); - } - Bind(&receiverNotEqualsHolder); - { - result = FalseConstant(); - Jump(&exit); - } - } - Bind(¬Internal); - { - result = TrueConstant(); - Jump(&exit); - } - Bind(&exit); - auto ret = *result; - env->PopCurrentLabel(); - return ret; -} - void Stub::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val) { StubDescriptor *throwTypeError = GET_STUBDESCRIPTOR(ThrowTypeError); diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 0032901..3116a7e 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -1182,36 +1182,13 @@ public: GetInt32Constant(0)); } - // GetOffset func in property_attribute.h - AddrShift GetOffsetFieldInPropAttr(AddrShift attr) + AddrShift PropAttrGetOffset(AddrShift attr) { return Word32And( Word32LSR(attr, GetInt32Constant(panda::ecmascript::PropertyAttributes::OffsetField::START_BIT)), GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::OffsetField::SIZE) - 1)); } - // SetOffset func in property_attribute.h - AddrShift SetOffsetFieldInPropAttr(AddrShift attr, AddrShift value) - { - AddrShift mask = Word32LSL( - GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::OffsetField::SIZE) - 1), - GetInt32Constant(panda::ecmascript::PropertyAttributes::OffsetField::START_BIT)); - AddrShift newVal = Word32Or(Word32And(attr, Word32Not(mask)), - Word32LSL(value, GetInt32Constant(panda::ecmascript::PropertyAttributes::OffsetField::START_BIT))); - return newVal; - } - - // SetIsInlinedProps func in property_attribute.h - AddrShift SetIsInlinePropsFieldInPropAttr(AddrShift attr, AddrShift value) - { - AddrShift mask = Word32LSL( - GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsInlinedPropsField::SIZE) - 1), - GetInt32Constant(panda::ecmascript::PropertyAttributes::IsInlinedPropsField::START_BIT)); - AddrShift newVal = Word32Or(Word32And(attr, Word32Not(mask)), - Word32LSL(value, GetInt32Constant(panda::ecmascript::PropertyAttributes::IsInlinedPropsField::START_BIT))); - return newVal; - } - // SetDictionaryOrder func in property_attribute.h AddrShift SetDictionaryOrderFieldInPropAttr(AddrShift attr, AddrShift value) { @@ -1256,18 +1233,6 @@ public: return Load(MachineType::UINT64_TYPE, hClass, GetPtrConstant(panda::ecmascript::JSHClass::OBJECT_SIZE_OFFSET)); } - void SetHasConstructorToHClass(AddrShift hClass, AddrShift value) - { - AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, - GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET)); - AddrShift mask = Word64LSL( - GetWord64Constant((1LLU << panda::ecmascript::JSHClass::HasConstructorBits::SIZE) - 1), - GetWord64Constant(panda::ecmascript::JSHClass::HasConstructorBits::START_BIT)); - AddrShift newVal = Word64Or(Word64And(bitfield, Word64Not(mask)), - Word64LSL(value, GetWord64Constant(panda::ecmascript::JSHClass::HasConstructorBits::START_BIT))); - Store(MachineType::UINT64_TYPE, hClass, GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET), newVal); - } - void StoreElement(AddrShift thread, AddrShift elements, AddrShift index, AddrShift value) { AddrShift offset = @@ -1294,15 +1259,6 @@ public: return Load(MachineType::TAGGED_TYPE, elements, dataOffset); } - AddrShift SetValueToTaggedArray(AddrShift elements, AddrShift index, AddrShift val) - { - // NOTE: need to translate MarkingBarrier - AddrShift offset = - PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())); - AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - return Store(MachineType::TAGGED_TYPE, elements, dataOffset, val); - } - AddrShift TaggedToRepresentation(AddrShift value); AddrShift GetElementRepresentation(AddrShift hClass) @@ -1325,16 +1281,6 @@ public: Store(MachineType::INT64_TYPE, hClass, bitfieldOffset, Word64Or(oldWithMask, newValue)); } - void UpdateValueInDict(AddrShift elements, AddrShift index, AddrShift value) - { - AddrShift arrayIndex = - Int32Add(GetInt32Constant(panda::ecmascript::NameDictionary::TABLE_HEADER_SIZE), - Int32Mul(index, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_SIZE))); - AddrShift valueIndex = - Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); - StoreElement(elements, valueIndex, value); - } - void UpdateValueAndAttributes(AddrShift thread, AddrShift elements, AddrShift index, AddrShift value, AddrShift attr) { @@ -1404,9 +1350,6 @@ public: AddrShift JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift propAttr); - AddrShift ShouldCallSetter(AddrShift receiver, AddrShift holder, - AddrShift accessor, AddrShift attr); - AddrShift IsUtf16String(AddrShift string); AddrShift IsUtf8String(AddrShift string); -- Gitee From 31969332ab349fa60a0809e2b41ef4a9eb70a012 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Sat, 30 Oct 2021 14:39:01 +0800 Subject: [PATCH 108/115] code review Signed-off-by: songzhengchao --- ecmascript/compiler/llvm_codegen.cpp | 10 +++++++--- ecmascript/compiler/stub_descriptor.cpp | 4 ++-- ecmascript/compiler/tests/stub_tests.cpp | 3 +-- js_runtime_config.gni | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index 3f5532a..9b8e440 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -83,7 +83,9 @@ void LLVMModuleAssembler::AssembleStubModule(StubModule *module) // stackmaps ptr and size module->SetStackMapAddr(reinterpret_cast
(assembler_.GetStackMapsSection())); module->SetStackMapSize(assembler_.GetStackMapsSize()); +#ifndef NDEBUG assembler_.Disassemble(addr2name); +#endif } static uint8_t *RoundTripAllocateCodeSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, @@ -138,18 +140,20 @@ bool LLVMAssembler::BuildMCJITEngine() void LLVMAssembler::BuildAndRunPasses() const { - std::cout << "BuildAndRunPasses - "; + LOG_ECMA(INFO) << "BuildAndRunPasses - "; LLVMPassManagerRef pm = LLVMCreatePassManager(); LLVMAddConstantPropagationPass(pm); LLVMAddInstructionCombiningPass(pm); llvm::unwrap(pm)->add(llvm::createRewriteStatepointsForGCLegacyPass()); +#ifndef NDEBUG char *info = LLVMPrintModuleToString(module_); - std::cout << "Current Module: " << info; + LOG_ECMA(INFO) << "Current Module: " << info; LLVMDumpModule(module_); LLVMDisposeMessage(info); +#endif LLVMRunPassManager(pm, module_); LLVMDisposePassManager(pm); - std::cout << "BuildAndRunPasses + "; + LOG_ECMA(INFO) << "BuildAndRunPasses + "; } LLVMAssembler::LLVMAssembler(LLVMModuleRef module, const char* triple): module_(module), engine_(nullptr), diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 8d61a51..b8a8081 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -68,7 +68,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastMul) CALL_STUB_INIT_DESCRIPTOR(FastMulGC) { // 3 : 3 input parameters - static StubDescriptor fastMulGC("FastMulGC", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); + StubDescriptor fastMulGC("FastMulGC", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastMulGC; // 3 : 3 input parameters std::array params = { @@ -296,7 +296,7 @@ CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) CALL_STUB_INIT_DESCRIPTOR(GetTaggedArrayPtr) { - static StubDescriptor getTaggedArrayPtr("GetTaggedArrayPtr", 0, 1, ArgumentsOrder::DEFAULT_ORDER, + StubDescriptor getTaggedArrayPtr("GetTaggedArrayPtr", 0, 1, ArgumentsOrder::DEFAULT_ORDER, MachineType::TAGGED_POINTER_TYPE); *descriptor = getTaggedArrayPtr; std::array params = { diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 8f5bea8..8e65692 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -1167,7 +1167,7 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub) reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function))); auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); JSHandle obj = factory->NewEmptyJSObject(); - int x = 256; + int x = 213; int y = 10; JSHandle strA(factory->NewFromCanBeCompressString("a")); JSHandle strBig(factory->NewFromCanBeCompressString("biggest")); @@ -1268,7 +1268,6 @@ HWTEST_F_L0(StubTest, GetPropertyByValueStub) resVal = getPropertyByValuePtr(thread, strHello.GetTaggedValue().GetRawData(), JSTaggedValue(key).GetRawData()); EXPECT_EQ(resVal.GetRawData(), 0); } -#endif HWTEST_F_L0(StubTest, FastTypeOfTest) { diff --git a/js_runtime_config.gni b/js_runtime_config.gni index 2ca7bd4..df2bc82 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -13,7 +13,7 @@ ark_root = "//ark/runtime_core" js_root = "//ark/js_runtime" -compile_llvm_online = true +compile_llvm_online = false run_with_asan = false enable_stub_aot = false asan_lib_path = "/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux" -- Gitee From baa25ddebe96bf72c734d58c2262decf0c2a9f02 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Sat, 30 Oct 2021 16:43:57 +0800 Subject: [PATCH 109/115] code review Signed-off-by: songzhengchao --- .../compiler/llvm/llvm_stackmap_parser.cpp | 19 ++++---- ecmascript/compiler/llvm_codegen.cpp | 2 +- ecmascript/compiler/stub.cpp | 1 + ecmascript/interpreter/frame_handler.cpp | 13 +++--- ecmascript/interpreter/frame_handler.h | 1 - ecmascript/runtime_trampolines.cpp | 46 +++++++++---------- ecmascript/runtime_trampolines.h | 1 + ecmascript/stub_module.cpp | 6 +++ ecmascript/stub_module.h | 8 ++-- 9 files changed, 51 insertions(+), 46 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index 1a0b539..9df1b06 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -83,13 +83,10 @@ bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t fram void LLVMStackMapParser::CalcCallSite() { uint64_t recordNum = 0; - for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) { - uintptr_t address = llvmStackMap_.StkSizeRecords[i].functionAddress; - uint64_t recordCount = llvmStackMap_.StkSizeRecords[i].recordCount; - for (uint64_t k = 0; k < recordCount; k++) { - struct StkMapRecordHeadTy recordHead = llvmStackMap_.StkMapRecord[recordNum + k].head; - for (int j = 0; j < recordHead.NumLocations; j++) { - struct LocationTy loc = llvmStackMap_.StkMapRecord[recordNum + k].Locations[j]; + auto calStkMapRecordFunc = [this, &recordNum](uintptr_t address, int recordId) { + struct StkMapRecordHeadTy recordHead = llvmStackMap_.StkMapRecord[recordNum + recordId].head; + for (int j = 0; j < recordHead.NumLocations; j++) { + struct LocationTy loc = llvmStackMap_.StkMapRecord[recordNum + recordId].Locations[j]; uint32_t instructionOffset = recordHead.InstructionOffset; uintptr_t callsite = address + instructionOffset; if (loc.location == LocationTy::Kind::INDIRECT) { @@ -97,7 +94,13 @@ void LLVMStackMapParser::CalcCallSite() Fun2InfoType callSiteInfo {callsite, info}; callSiteInfos_.push_back(callSiteInfo); } - } + } + }; + for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) { + uintptr_t address = llvmStackMap_.StkSizeRecords[i].functionAddress; + uint64_t recordCount = llvmStackMap_.StkSizeRecords[i].recordCount; + for (uint64_t k = 0; k < recordCount; k++) { + calStkMapRecordFunc(address, k); } recordNum += recordCount; } diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index 9b8e440..ee8069c 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -14,7 +14,6 @@ */ #include "llvm_codegen.h" -#include "llvm/llvm_stackmap_parser.h" #include #include "ecmascript/object_factory.h" #include "stub_descriptor.h" @@ -41,6 +40,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/Host.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/llvm_stackmap_parser.h" #include "llvm-c/Analysis.h" #include "llvm-c/Core.h" #include "llvm-c/Disassembler.h" diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index f2cf0f0..1da0498 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -822,6 +822,7 @@ AddrShift Stub::Store(MachineType type, AddrShift thread, AddrShift base, AddrSh return result; } + AddrShift Stub::Store(MachineType type, AddrShift base, AddrShift offset, AddrShift value) { auto depend = env_.GetCurrentLabel()->GetDepend(); diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index d6ed5b0..d276f13 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -248,12 +248,6 @@ void OptimizedEntryFrameHandler::PrevFrame() sp_ = reinterpret_cast(state->threadFp); } -void OptimizedEntryFrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const -{ - // Entry Frame return address's callsite already visited by OptimizedFrameHandler - // or HandleRuntimeTrampolines -} - void FrameIterator::HandleRuntimeTrampolines(const RootVisitor &v0, const RootRangeVisitor &v1) const { if (thread_) { @@ -263,17 +257,23 @@ void FrameIterator::HandleRuntimeTrampolines(const RootVisitor &v0, const RootRa } std::set slotAddrs; auto returnAddr = *(fp + 1); +#ifndef NDEBUG LOG_ECMA(INFO) << __FUNCTION__ << " returnAddr :" << returnAddr << " fp: " << fp << std::endl; +#endif bool ret = kungfu::LLVMStackMapParser::GetInstance().StackMapByFuncAddrFp( reinterpret_cast(returnAddr), reinterpret_cast(fp), slotAddrs); if (ret == false) { +#ifndef NDEBUG LOG_ECMA(INFO) << " stackmap don't found returnAddr " << std::endl; +#endif return; } for (auto &address: slotAddrs) { +#ifndef NDEBUG LOG_ECMA(INFO) << "stackmap address : " << std::hex << address << std::endl; +#endif v0(Root::ROOT_FRAME, ObjectSlot(address)); } } @@ -304,7 +304,6 @@ void FrameIterator::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) c OptimizedEntryFrameState *state = reinterpret_cast( reinterpret_cast(current) - MEMBER_OFFSET(OptimizedEntryFrameState, base.prev)); - OptimizedEntryFrameHandler(reinterpret_cast(current)).Iterate(v0, v1); current = reinterpret_cast(state->threadFp); } } diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index f69721f..870f48a 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -119,7 +119,6 @@ public: explicit OptimizedEntryFrameHandler(const JSThread *thread); ~OptimizedEntryFrameHandler() = default; void PrevFrame(); - void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; private: uintptr_t *fp_ {nullptr}; }; diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index 95e483b..cb4c9cc 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -134,6 +134,23 @@ uint32_t RuntimeTrampolines::StringGetHashCode(uint64_t ecmaString) return string->GetHashcode(); } +void RuntimeTrampolines::PrintHeapReginInfo(uint64_t argThread) +{ + auto thread = reinterpret_cast(argThread); + thread->GetEcmaVM()->GetHeap()->GetNewSpace()->EnumerateRegions([](Region *current) { + LOG_ECMA(INFO) << "semispace region: " << current << std::endl; + }); + thread->GetEcmaVM()->GetHeap()->GetOldSpace()->EnumerateRegions([](Region *current) { + LOG_ECMA(INFO) << "GetOldSpace region: " << current << std::endl; + }); + thread->GetEcmaVM()->GetHeap()->GetNonMovableSpace()->EnumerateRegions([](Region *current) { + LOG_ECMA(INFO) << "GetNonMovableSpace region: " << current << std::endl; + }); + thread->GetEcmaVM()->GetHeap()->GetMachineCodeSpace()->EnumerateRegions([](Region *current) { + LOG_ECMA(INFO) << "GetMachineCodeSpace region: " << current << std::endl; + }); +} + TaggedArray* RuntimeTrampolines::GetTaggedArrayPtr(uint64_t argThread) { uintptr_t *curFp = nullptr; @@ -144,8 +161,6 @@ TaggedArray* RuntimeTrampolines::GetTaggedArrayPtr(uint64_t argThread) // this case static static JSHandle arr don't free in first call // second call trigger gc. // don't call EcmaHandleScope handleScope(thread); - // auto current = thread->GetCurrentSPFrame(); - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); static int i = 0; static JSHandle arr = factory->NewTaggedArray(2); @@ -153,33 +168,14 @@ TaggedArray* RuntimeTrampolines::GetTaggedArrayPtr(uint64_t argThread) arr->Set(thread, 0, JSTaggedValue(3)); // 3: first element arr->Set(thread, 1, JSTaggedValue(4)); // 4: second element } - - thread->GetEcmaVM()->GetHeap()->GetNewSpace()->EnumerateRegions([](Region *current) { - LOG_ECMA(INFO) << "semispace region: " << current << std::endl; - }); - - thread->GetEcmaVM()->GetHeap()->GetOldSpace()->EnumerateRegions([](Region *current) { - LOG_ECMA(INFO) << "GetOldSpace region: " << current << std::endl; - }); - - thread->GetEcmaVM()->GetHeap()->GetNonMovableSpace()->EnumerateRegions([](Region *current) { - LOG_ECMA(INFO) << "GetNonMovableSpace region: " << current << std::endl; - }); - - thread->GetEcmaVM()->GetHeap()->GetMachineCodeSpace()->EnumerateRegions([](Region *current) { - LOG_ECMA(INFO) << "GetMachineCodeSpace region: " << current << std::endl; - }); - - LOG_ECMA(INFO) << " arr->GetData() " << std::dec << __LINE__ << - std::hex << " " << arr->GetData() << std::endl; +#ifndef NDEBUG + PrintHeapReginInfo(argThread); +#endif if (i != 0) { - LOG_ECMA(INFO) << " trigger GC : " << std::endl; thread->GetEcmaVM()->CollectGarbage(TriggerGCType::COMPRESS_FULL_GC); - LOG_ECMA(INFO) << " arr->GetData() " << std::dec << __LINE__ << - std::hex << " " << arr->GetData() << std::endl; } + LOG_ECMA(INFO) << " arr->GetData() " << std::hex << " " << arr->GetData(); i++; - LOG_ECMA(INFO) << " **arr " << *(reinterpret_cast(*arr)) << std::endl; return *arr; } uint64_t RuntimeTrampolines::Execute(uint64_t argThread, uint64_t argFunc, diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 6eb33fa..b0e814e 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -55,6 +55,7 @@ public: static void SetValueWithBarrier(uint64_t argThread, uint64_t argAddr, uint64_t argOffset, uint64_t argValue); static double FloatMod(double left, double right); static uint64_t NewInternalString(uint64_t argThread, uint64_t argKey); + static void PrintHeapReginInfo(uint64_t argThread); }; class CallRuntimeTrampolinesScope { diff --git a/ecmascript/stub_module.cpp b/ecmascript/stub_module.cpp index a9f28ea..c371565 100644 --- a/ecmascript/stub_module.cpp +++ b/ecmascript/stub_module.cpp @@ -38,7 +38,9 @@ void StubModule::Save(const std::string &filename) modulefile.write(reinterpret_cast(code_->GetDataOffsetAddress()), codeSize); /* write stackmap buff */ int stackmapSize = GetStackMapSize(); +#ifndef NDEBUG LOG_ECMA(INFO) << "stackmap host addr:" << GetStackMapAddr() << " stackmapSize:" << stackmapSize << std::endl; +#endif modulefile.write(reinterpret_cast(&stackmapSize), sizeof(stackmapSize)); modulefile.write(reinterpret_cast(GetStackMapAddr()), stackmapSize); @@ -64,8 +66,10 @@ void StubModule::Load(JSThread *thread, const std::string &filename) auto codeHandle = factory->NewMachineCodeObject(codeSize, nullptr); modulefile.read(reinterpret_cast(codeHandle->GetDataOffsetAddress()), codeSize); SetCode(*codeHandle); +#ifndef NDEBUG LOG_ECMA(INFO) << "codeSection adress for device:" << std::hex << codeHandle->GetDataOffsetAddress() << " codeSize:" << codeSize << std::endl; +#endif SetDeviceCodeSectionAddr(codeHandle->GetDataOffsetAddress()); /* read stackmap */ @@ -76,8 +80,10 @@ void StubModule::Load(JSThread *thread, const std::string &filename) auto dataHandle = factory->NewMachineCodeObject(stackmapSize, nullptr); modulefile.read(reinterpret_cast(dataHandle->GetDataOffsetAddress()), stackmapSize); SetData(*dataHandle); +#ifndef NDEBUG LOG_ECMA(INFO) << "stackmapSize adress for device:" << std::hex << dataHandle->GetDataOffsetAddress() << " stackmapSize:"<< stackmapSize << std::endl; +#endif SetStackMapAddr(reinterpret_cast
(dataHandle->GetDataOffsetAddress())); modulefile.close(); } diff --git a/ecmascript/stub_module.h b/ecmascript/stub_module.h index 2785524..654bd79 100644 --- a/ecmascript/stub_module.h +++ b/ecmascript/stub_module.h @@ -53,11 +53,11 @@ public: } void SetDeviceCodeSectionAddr(uintptr_t addr) { - DevicesCodeSectionAddr_ = addr; + devicesCodeSectionAddr_ = addr; } - uintptr_t GetDeviceCodeSectionAddr() + uintptr_t GetDeviceCodeSectionAddr() const { - return DevicesCodeSectionAddr_; + return devicesCodeSectionAddr_; } JSTaggedValue GetCode() { @@ -87,7 +87,7 @@ public: private: std::array fastStubEntries_ {-1}; Address hostCodeSectionAddr_ = 0; - uintptr_t DevicesCodeSectionAddr_ = 0; + uintptr_t devicesCodeSectionAddr_ = 0; MachineCode *code_ {nullptr}; MachineCode *data_ {nullptr}; Address stackMapAddr_ = 0; -- Gitee From 0c38b6b94dbd69bc0f5618dfe6e67627430b36ae Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Sat, 30 Oct 2021 18:58:52 +0800 Subject: [PATCH 110/115] code review Signed-off-by: songzhengchao --- ecmascript/compiler/fast_stub.cpp | 8 ++--- ecmascript/compiler/fast_stub.h | 10 +++--- ecmascript/compiler/fast_stub_define.h | 4 +-- .../compiler/llvm/llvm_stackmap_parser.cpp | 10 ++++++ ecmascript/compiler/llvm_codegen.cpp | 12 ++++--- ecmascript/compiler/stub.cpp | 2 +- ecmascript/compiler/stub_aot_compiler.cpp | 2 +- ecmascript/compiler/stub_aot_compiler.h | 1 - ecmascript/compiler/stub_descriptor.cpp | 8 ++--- ecmascript/compiler/stub_descriptor.h | 1 - ecmascript/frames.h | 5 ++- ecmascript/js_thread.cpp | 2 +- ecmascript/mem/machine_code.h | 7 +++-- ecmascript/runtime_trampolines.cpp | 2 +- ecmascript/runtime_trampolines.h | 2 +- ecmascript/stub_module.cpp | 4 +-- ecmascript/stub_module.h | 31 +++++++++---------- 17 files changed, 61 insertions(+), 50 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 437e297..b99536c 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -1163,7 +1163,7 @@ void FastModStub::GenerateCircuit() } } -void FastMulGCStub::GenerateCircuit() +void FastMulGCTestStub::GenerateCircuit() { auto env = GetEnvironment(); env->GetCircuit()->SetFrameType(FrameType::OPTIMIZED_ENTRY_FRAME); @@ -1226,10 +1226,10 @@ void FastMulGCStub::GenerateCircuit() } Bind(&xIsDoubleAndyIsDouble); doubleX = DoubleMul(*doubleX, *doubleY); - StubDescriptor *getTaggedArrayPtr = GET_STUBDESCRIPTOR(GetTaggedArrayPtr); - AddrShift ptr1 = CallRuntime(getTaggedArrayPtr, thread, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtr)), + StubDescriptor *getTaggedArrayPtr = GET_STUBDESCRIPTOR(GetTaggedArrayPtrTest); + AddrShift ptr1 = CallRuntime(getTaggedArrayPtr, thread, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), {thread}); - AddrShift ptr2 = CallRuntime(getTaggedArrayPtr, thread, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtr)), + AddrShift ptr2 = CallRuntime(getTaggedArrayPtr, thread, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), {thread}); (void)ptr2; auto value = Load(MachineType::INT64_TYPE, ptr1); diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 4bd212b..0b37583 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -60,13 +60,13 @@ public: void GenerateCircuit() override; }; -class FastMulGCStub : public Stub { +class FastMulGCTestStub : public Stub { public: // 3 : 3 means argument counts - explicit FastMulGCStub(Circuit *circuit) : Stub("FastMulGC", 3, circuit) {} - ~FastMulGCStub() = default; - NO_MOVE_SEMANTIC(FastMulGCStub); - NO_COPY_SEMANTIC(FastMulGCStub); + explicit FastMulGCTestStub(Circuit *circuit) : Stub("FastMulGCTest", 3, circuit) {} + ~FastMulGCTestStub() = default; + NO_MOVE_SEMANTIC(FastMulGCTestStub); + NO_COPY_SEMANTIC(FastMulGCTestStub); void GenerateCircuit() override; }; diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index b7ab275..821f2d2 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -31,7 +31,7 @@ namespace kungfu { V(StringGetHashCode, 1) \ V(FloatMod, 2) \ V(SetValueWithBarrier, 4) \ - V(GetTaggedArrayPtr, 1) \ + V(GetTaggedArrayPtrTest, 1) \ V(NewInternalString, 2) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) @@ -66,7 +66,7 @@ namespace kungfu { V(SetPropertyByIndex, 4) \ V(GetPropertyByValue, 3) \ V(SetPropertyByValue, 4) \ - V(FastMulGC, 3) + V(FastMulGCTest, 3) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define TEST_FUNC_LIST(V) \ diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index 9df1b06..df7c452 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -41,10 +41,14 @@ bool LLVMStackMapParser::StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTyp { bool found = false; for (auto it: callSiteInfos_) { +#ifndef NDEBUG LOG_ECMA(INFO) << __FUNCTION__ << std::hex << " addr:" << it.first << std::endl; +#endif if (it.first == funcAddr) { DwarfRegAndOffsetType info = it.second; +#ifndef NDEBUG LOG_ECMA(INFO) << __FUNCTION__ << " info <" << info.first << " ," << info.second << " >" << std::endl; +#endif infos.push_back(info); found = true; } @@ -72,9 +76,11 @@ bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t fram address = nullptr; abort(); } +#ifndef NDEBUG LOG_ECMA(INFO) << std::hex << "stackMap ref addr:" << address; LOG_ECMA(INFO) << " value:" << *address; LOG_ECMA(INFO) << " *value :" << **address << std::endl; +#endif slotAddrs.insert(reinterpret_cast(address)); } return true; @@ -163,13 +169,17 @@ bool LLVMStackMapParser::CalculateStackMap(const uint8_t *stackMapAddr, return ret; } // update functionAddress from host side to device side +#ifndef NDEBUG LOG_ECMA(INFO) << "stackmap calculate update funcitonaddress " << std::endl; +#endif for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) { uintptr_t hostAddr = llvmStackMap_.StkSizeRecords[i].functionAddress; uintptr_t deviceAddr = hostAddr - hostCodeSectionAddr + deviceCodeSectionAddr; llvmStackMap_.StkSizeRecords[i].functionAddress = deviceAddr; +#ifndef NDEBUG LOG_ECMA(INFO) << std::dec << i << "th function " << std::hex << hostAddr << " ---> " << deviceAddr << std::endl; +#endif } callSiteInfos_.clear(); CalcCallSite(); diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index ee8069c..973343f 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -66,22 +66,26 @@ void LLVMModuleAssembler::AssembleModule() void LLVMModuleAssembler::AssembleStubModule(StubModule *module) { - auto codeBuff = reinterpret_cast
(assembler_.GetCodeBuffer()); + auto codeBuff = reinterpret_cast(assembler_.GetCodeBuffer()); auto engine = assembler_.GetEngine(); std::map addr2name; for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { auto stubfunction = stubmodule_->GetStubFunction(i); +#ifndef NDEBUG LOG_ECMA(INFO) << " AssembleStubModule :" << i << " th " << std::endl; +#endif if (stubfunction != nullptr) { - Address stubEntry = reinterpret_cast
(LLVMGetPointerToGlobal(engine, stubfunction)); + uintptr_t stubEntry = reinterpret_cast(LLVMGetPointerToGlobal(engine, stubfunction)); module->SetStubEntry(i, stubEntry - codeBuff); - addr2name[stubEntry] = GET_STUBDESCRIPTOR_BY_ID(i)->GetName(); + addr2name[stubEntry] = FastStubDescriptors::GetInstance().GetStubDescriptor(i)->GetName(); +#ifndef NDEBUG LOG_ECMA(INFO) << "name : " << addr2name[codeBuff] << std::endl; +#endif } } module->SetHostCodeSectionAddr(codeBuff); // stackmaps ptr and size - module->SetStackMapAddr(reinterpret_cast
(assembler_.GetStackMapsSection())); + module->SetStackMapAddr(reinterpret_cast(assembler_.GetStackMapsSection())); module->SetStackMapSize(assembler_.GetStackMapsSize()); #ifndef NDEBUG assembler_.Disassemble(addr2name); diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 1da0498..0e9264d 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -813,7 +813,7 @@ AddrShift Stub::Store(MachineType type, AddrShift thread, AddrShift base, AddrSh } else { UNREACHABLE(); } - // write barrier + // write barrier will implemented in IR later if (type == MachineType::TAGGED_POINTER_TYPE || type == MachineType::TAGGED_TYPE) { StubDescriptor *setValueWithBarrier = GET_STUBDESCRIPTOR(SetValueWithBarrier); CallRuntime(setValueWithBarrier, thread, GetWord64Constant(FAST_STUB_ID(SetValueWithBarrier)), diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index 38a77fa..b7bd26b 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -149,7 +149,7 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri SET_STUB_TO_MODULE(module, FastAdd) \ SET_STUB_TO_MODULE(module, FastSub) \ SET_STUB_TO_MODULE(module, FastMul) \ - SET_STUB_TO_MODULE(module, FastMulGC) \ + SET_STUB_TO_MODULE(module, FastMulGCTest) \ SET_STUB_TO_MODULE(module, FastDiv) \ SET_STUB_TO_MODULE(module, FastMod) \ SET_STUB_TO_MODULE(module, FastTypeOf) \ diff --git a/ecmascript/compiler/stub_aot_compiler.h b/ecmascript/compiler/stub_aot_compiler.h index 1bf0062..3588b1c 100644 --- a/ecmascript/compiler/stub_aot_compiler.h +++ b/ecmascript/compiler/stub_aot_compiler.h @@ -22,7 +22,6 @@ namespace kungfu { class Stub; class circuit; -using Address = uintptr_t; class StubAotCompiler { public: StubAotCompiler() diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index b8a8081..232897f 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -65,10 +65,10 @@ CALL_STUB_INIT_DESCRIPTOR(FastMul) descriptor->SetParameters(params.data()); } -CALL_STUB_INIT_DESCRIPTOR(FastMulGC) +CALL_STUB_INIT_DESCRIPTOR(FastMulGCTest) { // 3 : 3 input parameters - StubDescriptor fastMulGC("FastMulGC", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); + StubDescriptor fastMulGC("FastMulGCTest", 0, 3, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = fastMulGC; // 3 : 3 input parameters std::array params = { @@ -294,9 +294,9 @@ CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } -CALL_STUB_INIT_DESCRIPTOR(GetTaggedArrayPtr) +CALL_STUB_INIT_DESCRIPTOR(GetTaggedArrayPtrTest) { - StubDescriptor getTaggedArrayPtr("GetTaggedArrayPtr", 0, 1, ArgumentsOrder::DEFAULT_ORDER, + StubDescriptor getTaggedArrayPtr("GetTaggedArrayPtrTest", 0, 1, ArgumentsOrder::DEFAULT_ORDER, MachineType::TAGGED_POINTER_TYPE); *descriptor = getTaggedArrayPtr; std::array params = { diff --git a/ecmascript/compiler/stub_descriptor.h b/ecmascript/compiler/stub_descriptor.h index 8ab63d2..57823d8 100644 --- a/ecmascript/compiler/stub_descriptor.h +++ b/ecmascript/compiler/stub_descriptor.h @@ -142,7 +142,6 @@ private: // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define GET_STUBDESCRIPTOR(name) FastStubDescriptors::GetInstance().GetStubDescriptor(FAST_STUB_ID(name)) -#define GET_STUBDESCRIPTOR_BY_ID(id) FastStubDescriptors::GetInstance().GetStubDescriptor(id) class FastStubDescriptors { public: diff --git a/ecmascript/frames.h b/ecmascript/frames.h index ba56f2d..6b29276 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -228,7 +228,6 @@ #endif namespace panda::ecmascript { -using TaggedType = coretypes::TaggedType; class JSThread; enum class FrameType: uintptr_t { OPTIMIZED_FRAME = 0, @@ -248,13 +247,13 @@ public: class InterpretedFrameStateBase { public: - TaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc + JSTaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc uintptr_t frameType; }; class OptimizedEntryFrameState { public: - TaggedType *threadFp; // for gc + JSTaggedType *threadFp; // for gc OptimizedFrameStateBase base; static size_t GetFrameStateOffsetFromSp() { diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index 3e8b9dc..f2fc47e 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -233,6 +233,6 @@ void JSThread::LoadFastStubModule(const char *moduleFile) kungfu::LLVMStackMapParser::GetInstance().Print(); stubCode_ = stubModule.GetCode(); - stubStackMap_ = stubModule.GetData(); + stubStackMap_ = stubModule.GetStackMapData(); } } // namespace panda::ecmascript diff --git a/ecmascript/mem/machine_code.h b/ecmascript/mem/machine_code.h index a9504f4..ad4217c 100644 --- a/ecmascript/mem/machine_code.h +++ b/ecmascript/mem/machine_code.h @@ -43,18 +43,19 @@ public: return reinterpret_cast(this) + DATA_OFFSET; } - void SetData(const uint8_t *codeData, size_t codeLength) + void SetData(const uint8_t *stackMapData, size_t codeLength) { - if (codeData == nullptr) { + if (stackMapData == nullptr) { LOG_ECMA_MEM(ERROR) << "data is null in creating new code object"; return; } if (memcpy_s(reinterpret_cast(this->GetDataOffsetAddress()), - this->GetInstructionSizeInBytes().GetInt(), codeData, codeLength) != EOK) { + this->GetInstructionSizeInBytes().GetInt(), stackMapData, codeLength) != EOK) { LOG_ECMA_MEM(ERROR) << "memcpy fail in creating new code object "; return; } } + void VisitRangeSlot(const EcmaObjectRangeVisitor &v) { // left blank deliberately,only need to visit TaggedObject type object. diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index cb4c9cc..ad76986 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -151,7 +151,7 @@ void RuntimeTrampolines::PrintHeapReginInfo(uint64_t argThread) }); } -TaggedArray* RuntimeTrampolines::GetTaggedArrayPtr(uint64_t argThread) +TaggedArray* RuntimeTrampolines::GetTaggedArrayPtrTest(uint64_t argThread) { uintptr_t *curFp = nullptr; auto thread = reinterpret_cast(argThread); diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index b0e814e..c6396b2 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -50,7 +50,7 @@ public: static uint32_t GetHash32(uint64_t key, uint64_t len); static int32_t FindElementWithCache(uint64_t argThread, uint64_t hClass, uint64_t key, int32_t num); static uint32_t StringGetHashCode(uint64_t ecmaString); - static TaggedArray* GetTaggedArrayPtr(uint64_t argThread); + static TaggedArray* GetTaggedArrayPtrTest(uint64_t argThread); static uint64_t Execute(uint64_t argThread, uint64_t argFunc, uint64_t thisArg, uint32_t argc, uint64_t argArgv); static void SetValueWithBarrier(uint64_t argThread, uint64_t argAddr, uint64_t argOffset, uint64_t argValue); static double FloatMod(double left, double right); diff --git a/ecmascript/stub_module.cpp b/ecmascript/stub_module.cpp index c371565..033f26a 100644 --- a/ecmascript/stub_module.cpp +++ b/ecmascript/stub_module.cpp @@ -79,12 +79,12 @@ void StubModule::Load(JSThread *thread, const std::string &filename) auto dataHandle = factory->NewMachineCodeObject(stackmapSize, nullptr); modulefile.read(reinterpret_cast(dataHandle->GetDataOffsetAddress()), stackmapSize); - SetData(*dataHandle); + SetStackMapData(*dataHandle); #ifndef NDEBUG LOG_ECMA(INFO) << "stackmapSize adress for device:" << std::hex << dataHandle->GetDataOffsetAddress() << " stackmapSize:"<< stackmapSize << std::endl; #endif - SetStackMapAddr(reinterpret_cast
(dataHandle->GetDataOffsetAddress())); + SetStackMapAddr(reinterpret_cast(dataHandle->GetDataOffsetAddress())); modulefile.close(); } } // namespace panda::ecmascript \ No newline at end of file diff --git a/ecmascript/stub_module.h b/ecmascript/stub_module.h index 654bd79..0160f71 100644 --- a/ecmascript/stub_module.h +++ b/ecmascript/stub_module.h @@ -22,10 +22,9 @@ #include "libpandabase/macros.h" namespace panda::ecmascript { -using Address = uintptr_t; class PUBLIC_API StubModule { public: - Address GetStubEntry(int index) + uintptr_t GetStubEntry(int index) { return code_->GetDataOffsetAddress() + fastStubEntries_[index]; } @@ -35,19 +34,19 @@ public: { code_ = code; } - void SetData(MachineCode *data) + void SetStackMapData(MachineCode *stackMapData) { - data_ = data; + stackMapData_ = stackMapData; } - void SetStubEntry(int index, Address offset) + void SetStubEntry(int index, uintptr_t offset) { fastStubEntries_[index] = offset; } - void SetHostCodeSectionAddr(Address addr) + void SetHostCodeSectionAddr(uintptr_t addr) { hostCodeSectionAddr_ = addr; } - Address GetHostCodeSectionAddr() + uintptr_t GetHostCodeSectionAddr() const { return hostCodeSectionAddr_; } @@ -63,15 +62,15 @@ public: { return JSTaggedValue(code_); } - JSTaggedValue GetData() + JSTaggedValue GetStackMapData() const { - return JSTaggedValue(data_); + return JSTaggedValue(stackMapData_); } - void SetStackMapAddr(Address addr) + void SetStackMapAddr(uintptr_t addr) { stackMapAddr_ = addr; } - Address GetStackMapAddr() + uintptr_t GetStackMapAddr() const { return stackMapAddr_; } @@ -79,18 +78,18 @@ public: { stackMapSize_ = len; } - int GetStackMapSize() + int GetStackMapSize() const { return stackMapSize_; } private: - std::array fastStubEntries_ {-1}; - Address hostCodeSectionAddr_ = 0; + std::array fastStubEntries_ {-1}; + uintptr_t hostCodeSectionAddr_ = 0; uintptr_t devicesCodeSectionAddr_ = 0; MachineCode *code_ {nullptr}; - MachineCode *data_ {nullptr}; - Address stackMapAddr_ = 0; + MachineCode *stackMapData_ {nullptr}; + uintptr_t stackMapAddr_ = 0; int stackMapSize_ = 0; }; } // namespace panda::ecmascript -- Gitee From 4dd6036e6999e4374531d9ea98de769ebcdebebd Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Mon, 1 Nov 2021 09:17:44 +0800 Subject: [PATCH 111/115] code review Signed-off-by: songzhengchao --- ecmascript/compiler/fast_stub_define.h | 2 +- ecmascript/compiler/stub_aot_compiler.cpp | 32 +++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index 821f2d2..c94c34d 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -31,7 +31,7 @@ namespace kungfu { V(StringGetHashCode, 1) \ V(FloatMod, 2) \ V(SetValueWithBarrier, 4) \ - V(GetTaggedArrayPtrTest, 1) \ + V(GetTaggedArrayPtrTest, 1) \ V(NewInternalString, 2) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index b7bd26b..3493009 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -145,22 +145,22 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri kungfu::Circuit name##Circuit; \ kungfu::name##Stub name##Stub(& name##Circuit); \ module.SetStub(FAST_STUB_ID(name), & name##Stub); -#define SET_ALL_STUB_TO_MODEULE(module) \ - SET_STUB_TO_MODULE(module, FastAdd) \ - SET_STUB_TO_MODULE(module, FastSub) \ - SET_STUB_TO_MODULE(module, FastMul) \ - SET_STUB_TO_MODULE(module, FastMulGCTest) \ - SET_STUB_TO_MODULE(module, FastDiv) \ - SET_STUB_TO_MODULE(module, FastMod) \ - SET_STUB_TO_MODULE(module, FastTypeOf) \ - SET_STUB_TO_MODULE(module, FindOwnElement) \ - SET_STUB_TO_MODULE(module, GetElement) \ - SET_STUB_TO_MODULE(module, FindOwnElement2) \ - SET_STUB_TO_MODULE(module, SetElement) \ - SET_STUB_TO_MODULE(module, GetPropertyByIndex) \ - SET_STUB_TO_MODULE(module, SetPropertyByIndex) \ - SET_STUB_TO_MODULE(module, FunctionCallInternal) \ - SET_STUB_TO_MODULE(module, GetPropertyByName) \ +#define SET_ALL_STUB_TO_MODEULE(module) \ + SET_STUB_TO_MODULE(module, FastAdd) \ + SET_STUB_TO_MODULE(module, FastSub) \ + SET_STUB_TO_MODULE(module, FastMul) \ + SET_STUB_TO_MODULE(module, FastMulGCTest) \ + SET_STUB_TO_MODULE(module, FastDiv) \ + SET_STUB_TO_MODULE(module, FastMod) \ + SET_STUB_TO_MODULE(module, FastTypeOf) \ + SET_STUB_TO_MODULE(module, FindOwnElement) \ + SET_STUB_TO_MODULE(module, GetElement) \ + SET_STUB_TO_MODULE(module, FindOwnElement2) \ + SET_STUB_TO_MODULE(module, SetElement) \ + SET_STUB_TO_MODULE(module, GetPropertyByIndex) \ + SET_STUB_TO_MODULE(module, SetPropertyByIndex) \ + SET_STUB_TO_MODULE(module, FunctionCallInternal) \ + SET_STUB_TO_MODULE(module, GetPropertyByName) \ SET_STUB_TO_MODULE(module, GetPropertyByValue) int main(const int argc, const char **argv) -- Gitee From bde47ee986fcc1ad867db775378511b332a8a508 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Mon, 1 Nov 2021 11:00:16 +0800 Subject: [PATCH 112/115] code review Signed-off-by: songzhengchao --- ecmascript/compiler/circuit_builder.cpp | 8 ++++---- ecmascript/compiler/fast_stub.cpp | 2 ++ ecmascript/compiler/stub_aot_compiler.cpp | 10 ++++++++-- ecmascript/compiler/stub_descriptor.cpp | 4 ++++ ecmascript/js_thread.cpp | 3 ++- ecmascript/stub_module.cpp | 8 +++++++- ecmascript/stub_module.h | 8 ++++---- 7 files changed, 31 insertions(+), 12 deletions(-) diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index 5e1857b..ff9f0ba 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -338,6 +338,8 @@ AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift thre std::initializer_list args) { std::vector inputs; + // 2 means extra two input gates (target thread) + const size_t extraparamCnt = 2; auto dependEntry = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY)); inputs.push_back(dependEntry); inputs.push_back(target); @@ -347,11 +349,9 @@ AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift thre } OpCode opcode = GetCallOpCodeFromMachineType(descriptor->GetReturnType()); if (descriptor->GetReturnType() == MachineType::TAGGED_POINTER_TYPE) { - // 2 : 2 means extra two input gates (target thread ) - return circuit_->NewGate(opcode, args.size() + 2, inputs, TypeCode::TAGGED_POINTER_TYPE); + return circuit_->NewGate(opcode, args.size() + extraparamCnt, inputs, TypeCode::TAGGED_POINTER_TYPE); } - // 2 : 2 means extra two input gates (target thread ) - return circuit_->NewGate(opcode, args.size() + 2, inputs, TypeCode::JS_ANY); + return circuit_->NewGate(opcode, args.size() + extraparamCnt, inputs, TypeCode::JS_ANY); } AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index b99536c..46ff241 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -1163,6 +1163,7 @@ void FastModStub::GenerateCircuit() } } +#ifndef NDEBUG void FastMulGCTestStub::GenerateCircuit() { auto env = GetEnvironment(); @@ -1237,6 +1238,7 @@ void FastMulGCTestStub::GenerateCircuit() doubleX = DoubleMul(*doubleX, value2); Return(DoubleBuildTagged(*doubleX)); } +#endif void FastTypeOfStub::GenerateCircuit() { diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index 3493009..d6b30c8 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -149,7 +149,6 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri SET_STUB_TO_MODULE(module, FastAdd) \ SET_STUB_TO_MODULE(module, FastSub) \ SET_STUB_TO_MODULE(module, FastMul) \ - SET_STUB_TO_MODULE(module, FastMulGCTest) \ SET_STUB_TO_MODULE(module, FastDiv) \ SET_STUB_TO_MODULE(module, FastMod) \ SET_STUB_TO_MODULE(module, FastTypeOf) \ @@ -163,6 +162,11 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri SET_STUB_TO_MODULE(module, GetPropertyByName) \ SET_STUB_TO_MODULE(module, GetPropertyByValue) +#ifndef NDEBUG +#define SET_TEST_STUB_TO_MODEULE(module) \ + SET_STUB_TO_MODULE(module, FastMulGCTest) +#endif + int main(const int argc, const char **argv) { panda::Span sp(argv, argc); @@ -189,7 +193,9 @@ int main(const int argc, const char **argv) kungfu::StubAotCompiler mouldeBuilder; SET_ALL_STUB_TO_MODEULE(mouldeBuilder); - +#ifndef NDEBUG + SET_TEST_STUB_TO_MODEULE(mouldeBuilder); +#endif panda::ecmascript::StubModule stubModule; mouldeBuilder.BuildStubModuleAndSave(tripes.c_str(), &stubModule, moduleFilename); diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 232897f..90b0a39 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -65,6 +65,7 @@ CALL_STUB_INIT_DESCRIPTOR(FastMul) descriptor->SetParameters(params.data()); } +#ifndef NDEBUG CALL_STUB_INIT_DESCRIPTOR(FastMulGCTest) { // 3 : 3 input parameters @@ -78,6 +79,9 @@ CALL_STUB_INIT_DESCRIPTOR(FastMulGCTest) }; descriptor->SetParameters(params.data()); } +#else +CALL_STUB_INIT_DESCRIPTOR(FastMulGCTest) {} +#endif CALL_STUB_INIT_DESCRIPTOR(FastDiv) { diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index f2fc47e..5a1879d 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -230,8 +230,9 @@ void JSThread::LoadFastStubModule(const char *moduleFile) Address hostCodeSectionAddr = stubModule.GetHostCodeSectionAddr(); uintptr_t deviceCodeSectionAddr = stubModule.GetDeviceCodeSectionAddr(); kungfu::LLVMStackMapParser::GetInstance().CalculateStackMap(ptr, hostCodeSectionAddr, deviceCodeSectionAddr); +#ifdef NDEBUG kungfu::LLVMStackMapParser::GetInstance().Print(); - +#endif stubCode_ = stubModule.GetCode(); stubStackMap_ = stubModule.GetStackMapData(); } diff --git a/ecmascript/stub_module.cpp b/ecmascript/stub_module.cpp index 033f26a..9449ac3 100644 --- a/ecmascript/stub_module.cpp +++ b/ecmascript/stub_module.cpp @@ -53,6 +53,13 @@ void StubModule::Save(const std::string &filename) void StubModule::Load(JSThread *thread, const std::string &filename) { +#ifndef NDEBUG + Logger::SetLevel(Logger::Level::INFO); +#endif + // now MachineCode is non movable, code and stackmap sperately is saved to MachineCode + // by calling NewMachineCodeObject. + // then MachineCode will support movable, code is saved to MachineCode and stackmap is saved + // to different heap which will be freed when stackmap is parsed by EcmaVM is started. std::ifstream modulefile(filename.c_str(), std::ofstream::binary); modulefile.read(reinterpret_cast(fastStubEntries_.data()), sizeof(uintptr_t) * (kungfu::FAST_STUB_MAXCOUNT)); @@ -76,7 +83,6 @@ void StubModule::Load(JSThread *thread, const std::string &filename) int stackmapSize; modulefile.read(reinterpret_cast(&stackmapSize), sizeof(stackmapSize)); SetStackMapSize(stackmapSize); - auto dataHandle = factory->NewMachineCodeObject(stackmapSize, nullptr); modulefile.read(reinterpret_cast(dataHandle->GetDataOffsetAddress()), stackmapSize); SetStackMapData(*dataHandle); diff --git a/ecmascript/stub_module.h b/ecmascript/stub_module.h index 0160f71..5594be6 100644 --- a/ecmascript/stub_module.h +++ b/ecmascript/stub_module.h @@ -85,12 +85,12 @@ public: private: std::array fastStubEntries_ {-1}; - uintptr_t hostCodeSectionAddr_ = 0; - uintptr_t devicesCodeSectionAddr_ = 0; + uintptr_t hostCodeSectionAddr_ {0}; + uintptr_t devicesCodeSectionAddr_ {0}; MachineCode *code_ {nullptr}; MachineCode *stackMapData_ {nullptr}; - uintptr_t stackMapAddr_ = 0; - int stackMapSize_ = 0; + uintptr_t stackMapAddr_ {0}; + int stackMapSize_ {0}; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_STUB_MODULE_H \ No newline at end of file -- Gitee From a7d9430e54b02ccc5054f3013e7887237a2342b1 Mon Sep 17 00:00:00 2001 From: hjzhangcm <845154910@qq.com> Date: Mon, 1 Nov 2021 19:01:30 +0800 Subject: [PATCH 113/115] add js_set_iterator_test.cpp Signed-off-by: hjzhangcm <845154910@qq.com> --- ecmascript/tests/BUILD.gn | 29 +++++ ecmascript/tests/js_set_iterator_test.cpp | 149 ++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 ecmascript/tests/js_set_iterator_test.cpp diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index bb90ff4..893a2c5 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -529,6 +529,33 @@ host_unittest_action("JsProxyTest") { } } +host_unittest_action("JsSetIteratorTest") { + module_out_path = module_output_path + + sources = [ + # test file + "js_set_iterator_test.cpp", + ] + + configs = [ + "//ark/js_runtime:ecma_test_config", + "//ark/js_runtime:ark_jsruntime_public_config", # should add before + # arkruntime_public_config + "//ark/js_runtime:ark_jsruntime_common_config", + "$ark_root/runtime:arkruntime_public_config", + ] + + deps = [ + "$ark_root/libpandabase:libarkbase", + "//ark/js_runtime:libark_jsruntime_test", + sdk_libc_secshared_dep, + ] + + if (!is_standard_system) { + deps += [ "$ark_root/runtime:libarkruntime" ] + } +} + host_unittest_action("JsSetTest") { module_out_path = module_output_path @@ -1017,6 +1044,7 @@ group("unittest") { ":JsPromiseTest", ":JsProxyTest", ":JsSerializerTest", + ":JsSetIteratorTest", ":JsSetTest", ":JsSymbolTest", ":JsTaggedQueueTest", @@ -1061,6 +1089,7 @@ group("host_unittest") { ":JsPromiseTestAction", ":JsProxyTestAction", ":JsSerializerTestAction", + ":JsSetIteratorTestAction", ":JsSetTestAction", ":JsSymbolTestAction", ":JsTaggedQueueTestAction", diff --git a/ecmascript/tests/js_set_iterator_test.cpp b/ecmascript/tests/js_set_iterator_test.cpp new file mode 100644 index 0000000..594060f --- /dev/null +++ b/ecmascript/tests/js_set_iterator_test.cpp @@ -0,0 +1,149 @@ +/* + * 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/js_set_iterator.h" +#include "ecmascript/js_set.h" +#include "ecmascript/global_env.h" +#include "ecmascript/linked_hash_table-inl.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class JSSetIteratorTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + ecmascript::EcmaHandleScope *scope {nullptr}; + PandaVM *instance {nullptr}; + JSThread *thread {nullptr}; +}; + +JSSet *CreateSet(JSThread *thread) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + + JSHandle constructor = env->GetBuiltinsSetFunction(); + JSHandle set = + JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(constructor), constructor)); + LinkedHashSet *hashSet = LinkedHashSet::Cast(LinkedHashSet::Create(thread).GetTaggedObject()); + set->SetLinkedSet(thread, JSTaggedValue(hashSet)); + return JSSet::Cast(set.GetTaggedValue().GetTaggedObject()); +} + +/* + * Feature: JSSetIterator + * Function: CreateSetIterator + * SubFunction: GetIterationKind,GetNextIndex + * FunctionPoints: Create SetIterator + * CaseDescription: Check whether the returned value through "CreateSetIterator" function is within expectations. + */ +HWTEST_F_L0(JSSetIteratorTest, CreateSetIterator) +{ + JSHandle jsSet(thread, CreateSet(thread)); + EXPECT_TRUE(*jsSet != nullptr); + + JSHandle setIteratorValue1 = + JSSetIterator::CreateSetIterator(thread, JSHandle(jsSet), IterationKind::KEY); + + EXPECT_EQ(setIteratorValue1->IsJSSetIterator(), true); + JSHandle setIterator1(setIteratorValue1); + EXPECT_EQ(JSTaggedValue::SameValue(setIterator1->GetIteratedSet(), jsSet->GetLinkedSet()), true); + EXPECT_EQ(setIterator1->GetNextIndex().GetInt(), 0); + + JSTaggedValue iterationKind1 = setIterator1->GetIterationKind(); + EXPECT_EQ(JSTaggedValue::SameValue(iterationKind1, JSTaggedValue(static_cast(IterationKind::KEY))), true); + + JSHandle setIteratorValue2 = + JSSetIterator::CreateSetIterator(thread, JSHandle(jsSet), IterationKind::VALUE); + + EXPECT_EQ(setIteratorValue2->IsJSSetIterator(), true); + JSHandle setIterator2(setIteratorValue2); + EXPECT_EQ(JSTaggedValue::SameValue(setIterator2->GetIteratedSet(), jsSet->GetLinkedSet()), true); + EXPECT_EQ(setIterator2->GetNextIndex().GetInt(), 0); + + JSTaggedValue iterationKind2 = setIterator2->GetIterationKind(); + EXPECT_EQ(JSTaggedValue::SameValue(iterationKind2, JSTaggedValue(static_cast(IterationKind::VALUE))), true); +} + +/* + * Feature: JSSetIterator + * Function: next + * SubFunction: IteratorValue + * FunctionPoints: get the next value in setiterator + * CaseDescription: Check whether the return value obtained by the function is the next value in the array element. + */ +HWTEST_F_L0(JSSetIteratorTest, Next) +{ + JSHandle jsSet(thread, CreateSet(thread)); + EXPECT_TRUE(*jsSet != nullptr); + + for (int i = 0; i < 3; i++) { + JSHandle key(thread, JSTaggedValue(i)); + JSSet::Add(thread, jsSet, key); + } + + // set IterationKind(key or value) + JSHandle setIteratorValue = + JSSetIterator::CreateSetIterator(thread, JSHandle(jsSet), IterationKind::KEY); + JSHandle setIterator(setIteratorValue); + + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(setIteratorValue.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue::Undefined()); + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + + JSTaggedValue result1 = JSSetIterator::Next(ecmaRuntimeCallInfo.get()); + EXPECT_EQ(setIterator->GetNextIndex().GetInt(), 1); + JSHandle resultObj1(thread, result1); + EXPECT_EQ(0, JSIterator::IteratorValue(thread, resultObj1)->GetInt()); + + JSTaggedValue result2 = JSSetIterator::Next(ecmaRuntimeCallInfo.get()); + EXPECT_EQ(setIterator->GetNextIndex().GetInt(), 2); + JSHandle resultObj2(thread, result2); + EXPECT_EQ(1, JSIterator::IteratorValue(thread, resultObj2)->GetInt()); + + JSTaggedValue result3 = JSSetIterator::Next(ecmaRuntimeCallInfo.get()); + EXPECT_EQ(setIterator->GetNextIndex().GetInt(), 3); + JSHandle resultObj3(thread, result3); + EXPECT_EQ(2, JSIterator::IteratorValue(thread, resultObj3)->GetInt()); + + JSTaggedValue result4 = JSSetIterator::Next(ecmaRuntimeCallInfo.get()); + JSHandle resultObj4(thread, result4); + EXPECT_EQ(JSIterator::IteratorValue(thread, resultObj4).GetTaggedValue(), JSTaggedValue::Undefined()); + + TestHelper::TearDownFrame(thread, prev); +} +} // namespace panda::test \ No newline at end of file -- Gitee From e818a0ba9eec54bdb802a1e5d51a1f84ccded894 Mon Sep 17 00:00:00 2001 From: xujie Date: Mon, 1 Nov 2021 20:00:38 +0800 Subject: [PATCH 114/115] Add FastEqual Stub Signed-off-by: xujie --- ecmascript/compiler/fast_stub.cpp | 83 +++++++++++++++++++++++ ecmascript/compiler/fast_stub.h | 10 +++ ecmascript/compiler/stub.h | 35 ++++++++++ ecmascript/compiler/stub_aot_compiler.cpp | 1 + ecmascript/compiler/stub_descriptor.cpp | 15 +++- ecmascript/compiler/tests/stub_tests.cpp | 69 +++++++++++++++++++ ecmascript/interpreter/interpreter-inl.h | 23 ++++++- 7 files changed, 233 insertions(+), 3 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 46ff241..9e125fa 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -1550,4 +1550,87 @@ void SetPropertyByValueStub::GenerateCircuit() Bind(&exit); Return(GetHoleConstant()); } + +void FastEqualStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift x = Int64Argument(0); + AddrShift y = Int64Argument(1); + DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); + Label xIsEqualy(env); + Label xIsNotEqualy(env); + Branch(Word64Equal(x, y), &xIsEqualy, &xIsNotEqualy); + Bind(&xIsEqualy); + { + Label xIsDouble(env); + Label xNotDoubleOrxNotNan(env); + Branch(TaggedIsDouble(x), &xIsDouble, &xNotDoubleOrxNotNan); + Bind(&xIsDouble); + { + AddrShift doubleX = TaggedCastToDouble(x); + Label xIsNan(env); + Branch(DoubleIsNAN(doubleX), &xIsNan, &xNotDoubleOrxNotNan); + Bind(&xIsNan); + Return(TaggedFalse()); + } + Bind(&xNotDoubleOrxNotNan); + Return(TaggedTrue()); + } + Bind(&xIsNotEqualy); + { + Label xIsNumber(env); + Label xNotNumberAndxNotIntAndyNotInt(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberAndxNotIntAndyNotInt); + Bind(&xIsNumber); + { + Label xIsInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotNumberAndxNotIntAndyNotInt); + Bind(&xIsInt); + { + Label yIsInt(env); + Branch(TaggedIsInt(y), &yIsInt, &xNotNumberAndxNotIntAndyNotInt); + Bind(&yIsInt); + Return(TaggedFalse()); + } + } + Bind(&xNotNumberAndxNotIntAndyNotInt); + { + Label yIsUndefinedOrNull(env); + Label xyNotUndefinedAndNull(env); + Branch(TaggedIsUndefinedOrNull(y), &yIsUndefinedOrNull, &xyNotUndefinedAndNull); + Bind(&yIsUndefinedOrNull); + { + Label xIsHeapObject(env); + Label xNotHeapObject(env); + Branch(TaggedIsHeapObject(x), &xIsHeapObject, &xNotHeapObject); + Bind(&xIsHeapObject); + Return(TaggedFalse()); + Bind(&xNotHeapObject); + { + Label xIsUndefinedOrNull(env); + Branch(TaggedIsUndefinedOrNull(x), &xIsUndefinedOrNull, &xyNotUndefinedAndNull); + Bind(&xIsUndefinedOrNull); + Return(TaggedTrue()); + } + } + Bind(&xyNotUndefinedAndNull); + { + Label xIsBoolean(env); + Label xNotBooleanAndyNotSpecial(env); + Branch(TaggedIsBoolean(x), &xIsBoolean, &xNotBooleanAndyNotSpecial); + Bind(&xIsBoolean); + { + Label yIsSpecial(env); + Branch(TaggedIsSpecial(y), &yIsSpecial, &xNotBooleanAndyNotSpecial); + Bind(&yIsSpecial); + Return(TaggedFalse()); + } + Bind(&xNotBooleanAndyNotSpecial); + { + Return(GetHoleConstant()); + } + } + } + } +} } // namespace kungfu diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 0b37583..23f2de6 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -220,6 +220,16 @@ public: NO_COPY_SEMANTIC(SetPropertyByValueStub); void GenerateCircuit() override; }; + +class FastEqualStub : public Stub { +public: + // 2 means argument counts + explicit FastEqualStub(Circuit *circuit) : Stub("FastEqual", 2, circuit) {} + ~FastEqualStub() = default; + NO_MOVE_SEMANTIC(FastEqualStub); + NO_COPY_SEMANTIC(FastEqualStub); + void GenerateCircuit() override; +}; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 3116a7e..6bce838 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -851,6 +851,31 @@ public: Word32Equal(SExtInt1ToInt32(diff2), GetInt32Constant(1)))); } + AddrShift TaggedIsNull(AddrShift x) + { + return Word64Equal(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::VALUE_NULL)); + } + + AddrShift TaggedIsUndefinedOrNull(AddrShift x) + { + return TruncInt32ToInt1(Word32Or(SExtInt1ToInt32(TaggedIsUndefined(x)), SExtInt1ToInt32(TaggedIsNull(x)))); + } + + AddrShift TaggedIsTrue(AddrShift x) + { + return Word64Equal(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::VALUE_TRUE)); + } + + AddrShift TaggedIsFalse(AddrShift x) + { + return Word64Equal(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::VALUE_FALSE)); + } + + AddrShift TaggedIsBoolean(AddrShift x) + { + return TruncInt32ToInt1(Word32Or(SExtInt1ToInt32(TaggedIsTrue(x)), SExtInt1ToInt32(TaggedIsFalse(x)))); + } + AddrShift IntBuildTagged(AddrShift x) { AddrShift val = ZExtInt32ToInt64(x); @@ -873,6 +898,16 @@ public: return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::BITCAST_FLOAT64_TO_INT64), x); } + AddrShift TaggedTrue() + { + return GetWord64Constant(panda::ecmascript::JSTaggedValue::VALUE_TRUE); + } + + AddrShift TaggedFalse() + { + return GetWord64Constant(panda::ecmascript::JSTaggedValue::VALUE_FALSE); + } + // compare operation AddrShift Word32Equal(AddrShift x, AddrShift y) { diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index d6b30c8..7403ee7 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -152,6 +152,7 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri SET_STUB_TO_MODULE(module, FastDiv) \ SET_STUB_TO_MODULE(module, FastMod) \ SET_STUB_TO_MODULE(module, FastTypeOf) \ + SET_STUB_TO_MODULE(module, FastEqual) \ SET_STUB_TO_MODULE(module, FindOwnElement) \ SET_STUB_TO_MODULE(module, GetElement) \ SET_STUB_TO_MODULE(module, FindOwnElement2) \ diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 90b0a39..11e1768 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -124,8 +124,6 @@ CALL_STUB_INIT_DESCRIPTOR(FloatMod) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } -CALL_STUB_INIT_DESCRIPTOR(FastEqual) {} - CALL_STUB_INIT_DESCRIPTOR(FastTypeOf) { // 2 input parameters @@ -139,6 +137,19 @@ CALL_STUB_INIT_DESCRIPTOR(FastTypeOf) descriptor->SetParameters(params.data()); } +CALL_STUB_INIT_DESCRIPTOR(FastEqual) +{ + // 2 input parameters + StubDescriptor fastEqual("FastEqual", 0, 2, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); + *descriptor = fastEqual; + // 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); +} + CALL_STUB_INIT_DESCRIPTOR(FastStrictEqual) {} CALL_STUB_INIT_DESCRIPTOR(IsSpecialIndexedObjForSet) {} diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 8e65692..0ad470c 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -1354,4 +1354,73 @@ HWTEST_F_L0(StubTest, FastTypeOfTest) EXPECT_EQ(resultVal9, globalConst->GetObjectString()); EXPECT_EQ(resultVal9, expectResult9); } + +HWTEST_F_L0(StubTest, FastEqualTest) +{ + auto module = stubModule.GetModule(); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(FastEqual)); + Circuit netOfGates; + FastEqualStub optimizer(&netOfGates); + optimizer.GenerateCircuit(); + netOfGates.PrintAllGates(); + auto cfg = Scheduler::Run(&netOfGates); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); + llvmBuilder.Build(); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); + assembler.Run(); + LLVMDumpModule(module); + auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); + // test for 1 == 1 + auto resA = fn(JSTaggedValue(1).GetRawData(), JSTaggedValue(1).GetRawData()); + auto expectA = FastRuntimeStub::FastEqual(JSTaggedValue(1), JSTaggedValue(1)); + EXPECT_EQ(resA, expectA); + + // test for nan == nan + double nan = std::numeric_limits::quiet_NaN(); + auto resB = fn(JSTaggedValue(nan).GetRawData(), JSTaggedValue(nan).GetRawData()); + auto expectB = FastRuntimeStub::FastEqual(JSTaggedValue(nan), JSTaggedValue(nan)); + EXPECT_EQ(resB, expectB); + + // test for undefined == null + auto resC = fn(JSTaggedValue::Undefined().GetRawData(), JSTaggedValue::Null().GetRawData()); + auto expectC = FastRuntimeStub::FastEqual(JSTaggedValue::Undefined(), JSTaggedValue::Null()); + EXPECT_EQ(resC, expectC); + + // test for "hello world" == undefined + auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); + auto str = factory->NewFromStdString("hello world"); + auto resD = fn(str.GetTaggedValue().GetRawData(), JSTaggedValue::Undefined().GetRawData()); + auto expectD = FastRuntimeStub::FastEqual(str.GetTaggedValue(), JSTaggedValue::Undefined()); + EXPECT_EQ(resD, expectD); + + // test for true == hole + auto resE = fn(JSTaggedValue::True().GetRawData(), JSTaggedValue::Hole().GetRawData()); + auto expectE = FastRuntimeStub::FastEqual(JSTaggedValue::True(), JSTaggedValue::Hole()); + EXPECT_EQ(resE, expectE); + + // test for "hello world" == "hello world" + auto resF = fn(str.GetTaggedValue().GetRawData(), str.GetTaggedValue().GetRawData()); + auto expectF = FastRuntimeStub::FastEqual(str.GetTaggedValue(), str.GetTaggedValue()); + EXPECT_EQ(resF, expectF); + + // test for 5.2 == 5.2 + auto resG = fn(JSTaggedValue(5.2).GetRawData(), JSTaggedValue(5.2).GetRawData()); + auto expectG = FastRuntimeStub::FastEqual(JSTaggedValue(5.2), JSTaggedValue(5.2)); + EXPECT_EQ(resG, expectG); + + // test for false == false + auto resH = fn(JSTaggedValue::False().GetRawData(), JSTaggedValue::False().GetRawData()); + auto expectH = FastRuntimeStub::FastEqual(JSTaggedValue::False(), JSTaggedValue::False()); + EXPECT_EQ(resH, expectH); + + // test for obj == obj + JSHandle obj1 = factory->NewEmptyJSObject(); + JSHandle obj2 = factory->NewEmptyJSObject(); + FastRuntimeStub::SetOwnElement(thread, obj1.GetTaggedValue(), 1, JSTaggedValue(1)); + FastRuntimeStub::SetOwnElement(thread, obj2.GetTaggedValue(), 1, JSTaggedValue(1)); + auto resI = fn(obj1.GetTaggedValue().GetRawData(), obj2.GetTaggedValue().GetRawData()); + auto expectI = FastRuntimeStub::FastEqual(obj1.GetTaggedValue(), obj2.GetTaggedValue()); + EXPECT_EQ(resI, expectI); +} } // namespace panda::test diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 4155580..a92d165 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -1138,7 +1138,14 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool } HANDLE_OPCODE(HANDLE_TYPEOFDYN_PREF) { LOG_INST() << "intrinsics::typeofdyn"; +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(FastTypeOf)); + typedef JSTaggedValue (*PFFastTypeOf)(JSThread *, JSTaggedValue); + auto fastTypeOfPtr = reinterpret_cast(stubAddr); + JSTaggedValue res = fastTypeOfPtr(thread, GET_ACC()); +#else JSTaggedValue res = FastRuntimeStub::FastTypeOf(thread, GET_ACC()); +#endif SET_ACC(res); DISPATCH(BytecodeInstruction::Format::PREF_NONE); } @@ -1331,8 +1338,15 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool << " v" << vs; JSTaggedValue left = GET_VREG_VALUE(vs); JSTaggedValue right = GET_ACC(); - // fast path + +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(FastMod)); + typedef JSTaggedValue (*PFFastMod)(JSTaggedValue, JSTaggedValue); + auto fastModPtr = reinterpret_cast(stubAddr); + JSTaggedValue res = fastModPtr(left, right); +#else JSTaggedValue res = FastRuntimeStub::FastMod(left, right); +#endif if (!res.IsHole()) { SET_ACC(res); } else { @@ -1350,7 +1364,14 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool << " v" << v0; JSTaggedValue left = GET_VREG_VALUE(v0); JSTaggedValue right = acc; +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(FastEqual)); + typedef JSTaggedValue (*PFFastEqual)(JSTaggedValue, JSTaggedValue); + auto fastEqualPtr = reinterpret_cast(stubAddr); + JSTaggedValue res = fastEqualPtr(left, right); +#else JSTaggedValue res = FastRuntimeStub::FastEqual(left, right); +#endif if (!res.IsHole()) { SET_ACC(res); } else { -- Gitee From b4f467350209b1f4d8c632280cc1891c194ac1e0 Mon Sep 17 00:00:00 2001 From: hjzhangcm <845154910@qq.com> Date: Tue, 2 Nov 2021 18:39:03 +0800 Subject: [PATCH 115/115] add js_string_iterator_test.cpp Signed-off-by: hjzhangcm <845154910@qq.com> --- ecmascript/tests/BUILD.gn | 29 ++++ ecmascript/tests/js_string_iterator_test.cpp | 138 +++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 ecmascript/tests/js_string_iterator_test.cpp diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index 893a2c5..1db99fe 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -583,6 +583,33 @@ host_unittest_action("JsSetTest") { } } +host_unittest_action("JsStringIteratorTest") { + module_out_path = module_output_path + + sources = [ + # test file + "js_string_iterator_test.cpp", + ] + + configs = [ + "//ark/js_runtime:ecma_test_config", + "//ark/js_runtime:ark_jsruntime_public_config", # should add before + # arkruntime_public_config + "//ark/js_runtime:ark_jsruntime_common_config", + "$ark_root/runtime:arkruntime_public_config", + ] + + deps = [ + "$ark_root/libpandabase:libarkbase", + "//ark/js_runtime:libark_jsruntime_test", + sdk_libc_secshared_dep, + ] + + if (!is_standard_system) { + deps += [ "$ark_root/runtime:libarkruntime" ] + } +} + host_unittest_action("JsSymbolTest") { module_out_path = module_output_path @@ -1046,6 +1073,7 @@ group("unittest") { ":JsSerializerTest", ":JsSetIteratorTest", ":JsSetTest", + ":JsStringIteratorTest", ":JsSymbolTest", ":JsTaggedQueueTest", ":JsTypedArrayTest", @@ -1091,6 +1119,7 @@ group("host_unittest") { ":JsSerializerTestAction", ":JsSetIteratorTestAction", ":JsSetTestAction", + ":JsStringIteratorTestAction", ":JsSymbolTestAction", ":JsTaggedQueueTestAction", ":JsTypedArrayTestAction", diff --git a/ecmascript/tests/js_string_iterator_test.cpp b/ecmascript/tests/js_string_iterator_test.cpp new file mode 100644 index 0000000..831038f --- /dev/null +++ b/ecmascript/tests/js_string_iterator_test.cpp @@ -0,0 +1,138 @@ +/* + * 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/js_string_iterator.h" +#include "ecmascript/ecma_string.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class JSStringIteratorTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + PandaVM *instance {nullptr}; + ecmascript::EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; +}; + +/* + * Feature: JSStringIterator + * Function: CreateStringIterator + * SubFunction: IsStringIterator + * FunctionPoints: Create String Iterator + * CaseDescription: Call the "CreateStringIterator" function, check whether the result tagged value returned by + * "IsStringIterator" function from the JSArrayIterator is within expectations. + */ +HWTEST_F_L0(JSStringIteratorTest, CreateStringIterator) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + + char array1[] = "x"; + JSHandle iteratorString1 = factory->NewFromCanBeCompressString(array1); + EXPECT_TRUE(JSStringIterator::CreateStringIterator(thread, iteratorString1).GetTaggedValue().IsStringIterator()); + + char array2[] = "1"; + JSHandle iteratorString2 = factory->NewFromCanBeCompressString(array2); + EXPECT_TRUE(JSStringIterator::CreateStringIterator(thread, iteratorString2).GetTaggedValue().IsStringIterator()); +} + +/* + * Feature: JSStringIterator + * Function: SetIteratedString + * SubFunction: GetIteratedString + * FunctionPoints: Set Iterated String + * CaseDescription: Call the "SetIteratedString" function, check whether the result returned through "GetIteratedString" + * function from the JSArrayIterator is within expectations. + */ +HWTEST_F_L0(JSStringIteratorTest, SetIteratedString) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + char array1[] = "12345"; + + JSHandle iteratorString1 = factory->NewFromCanBeCompressString(array1); + JSTaggedValue iteratorStringValue1 = iteratorString1.GetTaggedValue(); + JSHandle stringIterator1 = JSStringIterator::CreateStringIterator(thread, iteratorString1); + + JSTaggedValue handString1 = stringIterator1->GetIteratedString(); + JSHandle resultHandleString1(thread, reinterpret_cast(handString1.GetRawData())); + EXPECT_EQ(resultHandleString1->Compare(reinterpret_cast(iteratorStringValue1.GetRawData())), 5); + + char array2[] = "abcd"; + JSHandle iteratorString2 = factory->NewFromCanBeCompressString(array2); + JSTaggedValue iteratorStringValue2 = iteratorString2.GetTaggedValue(); + JSHandle stringIterator2 = JSStringIterator::CreateStringIterator(thread, iteratorString2); + + JSTaggedValue handString2 = stringIterator2->GetIteratedString(); + JSHandle resultHandleString2(thread, reinterpret_cast(handString2.GetRawData())); + EXPECT_EQ(resultHandleString2->Compare(reinterpret_cast(iteratorStringValue2.GetRawData())), 4); +} + +/* + * Feature: JSStringIterator + * Function: SetStringIteratorNextIndex + * SubFunction: GetStringIteratorNextIndex + * FunctionPoints: Set String Iterator Next Index + * CaseDescription: Call the "SetStringIteratorNextIndex" function, check whether the result returned through + * "GetStringIteratorNextIndex" function from the JSArrayIterator is within expectations. + */ +HWTEST_F_L0(JSStringIteratorTest, SetStringIteratorNextIndex) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + char array1[] = "12345"; + uint32_t arrayLength1 = sizeof(array1) - 1; + + JSHandle iteratorString1 = factory->NewFromCanBeCompressString(array1); + JSHandle stringIterator1 = JSStringIterator::CreateStringIterator(thread, iteratorString1); + EXPECT_EQ(stringIterator1->GetStringIteratorNextIndex().GetInt(), 0); + + for (int i = 1; i <= arrayLength1; i++) { + JSHandle handleTagStringIteratorNextIndex1(thread, JSTaggedValue(i)); + stringIterator1->SetStringIteratorNextIndex(thread, handleTagStringIteratorNextIndex1); + EXPECT_EQ(stringIterator1->GetStringIteratorNextIndex().GetNumber(), i); + } + + char array2[] = "abcde"; + uint32_t arrayLength2 = sizeof(array2) - 1; + + JSHandle iteratorString2 = factory->NewFromCanBeCompressString(array2); + JSHandle stringIterator2 = JSStringIterator::CreateStringIterator(thread, iteratorString2); + EXPECT_EQ(stringIterator2->GetStringIteratorNextIndex().GetInt(), 0); + + for (int i = 1; i <= arrayLength2; i++) { + JSHandle handleTagStringIteratorNextIndex2(thread, JSTaggedValue(i)); + stringIterator2->SetStringIteratorNextIndex(thread, handleTagStringIteratorNextIndex2); + EXPECT_EQ(stringIterator2->GetStringIteratorNextIndex().GetNumber(), i); + } +} +} // namespace panda::ecmascript \ No newline at end of file -- Gitee