diff --git a/.gitignore b/.gitignore index cd55219032ca5e568337a256576cbce0678e2834..619d3270867573c5a5309ba6d969c90e4e0171df 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ tags *.abc *.ll *.m +test/regresstest/__pycache__/ +test/regresstest/ark-regress/ \ No newline at end of file diff --git a/BUILD.gn b/BUILD.gn index 7503dc8780c225405cc58119a67bf796a8504d4d..6fb624ff8d728da72e75e27cd5cf867b7e3ba84b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -19,9 +19,11 @@ group("ark_js_packages") { deps = [] deps += [ + ":js_type_metadata", ":libark_jsruntime", "ecmascript/compiler:stub.an", "ecmascript/dfx/hprof:ark_js_heap_snapshot_tool", + "ecmascript/dfx/hprof/rawheap_translate:rawheap_translator", "ecmascript/js_vm:ark_js_vm", "ecmascript/quick_fix:quick_fix", ] @@ -107,6 +109,7 @@ group("ark_js_unittest") { "ecmascript/dfx/stackinfo/tests:unittest", "ecmascript/extractortool/tests:unittest", "ecmascript/ic/tests:unittest", + "ecmascript/jit/tests:unittest", "ecmascript/jobs/tests:unittest", "ecmascript/jspandafile/tests:unittest", "ecmascript/module/tests:unittest", @@ -147,6 +150,7 @@ group("ark_unittest") { "ecmascript/dfx/stackinfo/tests:host_unittest", "ecmascript/extractortool/tests:host_unittest", "ecmascript/ic/tests:host_unittest", + "ecmascript/jit/tests:host_unittest", "ecmascript/jobs/tests:host_unittest", "ecmascript/jspandafile/tests:host_unittest", "ecmascript/module/tests:host_unittest", @@ -718,9 +722,8 @@ ecma_source = [ "ecmascript/async_generator_helper.cpp", "ecmascript/global_env.cpp", "ecmascript/global_env_constants.cpp", + "ecmascript/ic/ic_handler.cpp", "ecmascript/ic/ic_runtime.cpp", - "ecmascript/ic/ic_compare_op.cpp", - "ecmascript/ic/invoke_cache.cpp", "ecmascript/ic/profile_type_info.cpp", "ecmascript/ic/property_box.cpp", "ecmascript/ic/proto_change_details.cpp", @@ -730,9 +733,11 @@ ecma_source = [ "ecmascript/interpreter/interpreter-inl.cpp", "ecmascript/interpreter/slow_runtime_stub.cpp", "ecmascript/intl/locale_helper.cpp", + "ecmascript/jit/compile_decision.cpp", "ecmascript/jit/jit.cpp", "ecmascript/jit/jit_dfx.cpp", "ecmascript/jit/jit_task.cpp", + "ecmascript/jit/jit_resources.cpp", "ecmascript/jit/jit_thread.cpp", "ecmascript/jit/jit_profiler.cpp", "ecmascript/jobs/micro_job_queue.cpp", @@ -1385,3 +1390,253 @@ ohos_prebuilt_etc("app_aot_jit_enable_list") { part_name = "ets_runtime" subsystem_name = "arkcompiler" } + +js_type_metadata_sources = [ + "ecmascript/js_type_metadata/accessor_data.json", + "ecmascript/js_type_metadata/aot_literal_info.json", + "ecmascript/js_type_metadata/async_generator_request.json", + "ecmascript/js_type_metadata/async_iterator_record.json", + "ecmascript/js_type_metadata/bigint.json", + "ecmascript/js_type_metadata/byte_array.json", + "ecmascript/js_type_metadata/cell_record.json", + "ecmascript/js_type_metadata/class_info_extractor.json", + "ecmascript/js_type_metadata/class_literal.json", + "ecmascript/js_type_metadata/completion_record.json", + "ecmascript/js_type_metadata/constant_pool.json", + "ecmascript/js_type_metadata/constant_string.json", + "ecmascript/js_type_metadata/cow_mutant_tagged_array.json", + "ecmascript/js_type_metadata/cow_tagged_array.json", + "ecmascript/js_type_metadata/dictionary_layout.json", + "ecmascript/js_type_metadata/ecma_object.json", + "ecmascript/js_type_metadata/ecma_string.json", + "ecmascript/js_type_metadata/extra_profile_type_info.json", + "ecmascript/js_type_metadata/function_template.json", + "ecmascript/js_type_metadata/global_env.json", + "ecmascript/js_type_metadata/hclass.json", + "ecmascript/js_type_metadata/importentry_record.json", + "ecmascript/js_type_metadata/indirect_exportentry_record.json", + "ecmascript/js_type_metadata/internal_accessor.json", + "ecmascript/js_type_metadata/js_aggregate_error.json", + "ecmascript/js_type_metadata/js_api_array_list.json", + "ecmascript/js_type_metadata/js_api_arraylist_iterator.json", + "ecmascript/js_type_metadata/js_api_bitvector.json", + "ecmascript/js_type_metadata/js_api_bitvector_iterator.json", + "ecmascript/js_type_metadata/js_api_deque.json", + "ecmascript/js_type_metadata/js_api_deque_iterator.json", + "ecmascript/js_type_metadata/js_api_hash_map.json", + "ecmascript/js_type_metadata/js_api_hash_set.json", + "ecmascript/js_type_metadata/js_api_hashmap_iterator.json", + "ecmascript/js_type_metadata/js_api_hashset_iterator.json", + "ecmascript/js_type_metadata/js_api_light_weight_map.json", + "ecmascript/js_type_metadata/js_api_light_weight_map_iterator.json", + "ecmascript/js_type_metadata/js_api_light_weight_set.json", + "ecmascript/js_type_metadata/js_api_light_weight_set_iterator.json", + "ecmascript/js_type_metadata/js_api_linked_list.json", + "ecmascript/js_type_metadata/js_api_linked_list_iterator.json", + "ecmascript/js_type_metadata/js_api_list.json", + "ecmascript/js_type_metadata/js_api_list_iterator.json", + "ecmascript/js_type_metadata/js_api_plain_array.json", + "ecmascript/js_type_metadata/js_api_plain_array_iterator.json", + "ecmascript/js_type_metadata/js_api_queue.json", + "ecmascript/js_type_metadata/js_api_queue_iterator.json", + "ecmascript/js_type_metadata/js_api_stack.json", + "ecmascript/js_type_metadata/js_api_stack_iterator.json", + "ecmascript/js_type_metadata/js_api_tree_map.json", + "ecmascript/js_type_metadata/js_api_tree_set.json", + "ecmascript/js_type_metadata/js_api_treemap_iterator.json", + "ecmascript/js_type_metadata/js_api_treeset_iterator.json", + "ecmascript/js_type_metadata/js_api_vector.json", + "ecmascript/js_type_metadata/js_api_vector_iterator.json", + "ecmascript/js_type_metadata/js_arguments.json", + "ecmascript/js_type_metadata/js_array.json", + "ecmascript/js_type_metadata/js_array_buffer.json", + "ecmascript/js_type_metadata/js_array_iterator.json", + "ecmascript/js_type_metadata/js_async_await_status_function.json", + "ecmascript/js_type_metadata/js_async_from_sync_iter_unwarp_function.json", + "ecmascript/js_type_metadata/js_async_from_sync_iterator.json", + "ecmascript/js_type_metadata/js_async_func_object.json", + "ecmascript/js_type_metadata/js_async_function.json", + "ecmascript/js_type_metadata/js_async_generator_function.json", + "ecmascript/js_type_metadata/js_async_generator_object.json", + "ecmascript/js_type_metadata/js_async_generator_resume_next.json", + "ecmascript/js_type_metadata/js_async_module_fulfilled_function.json", + "ecmascript/js_type_metadata/js_async_module_rejected_function.json", + "ecmascript/js_type_metadata/js_asynciterator.json", + "ecmascript/js_type_metadata/js_bigint64_array.json", + "ecmascript/js_type_metadata/js_biguint64_array.json", + "ecmascript/js_type_metadata/js_bound_function.json", + "ecmascript/js_type_metadata/js_cjs_exports.json", + "ecmascript/js_type_metadata/js_cjs_module.json", + "ecmascript/js_type_metadata/js_cjs_require.json", + "ecmascript/js_type_metadata/js_collator.json", + "ecmascript/js_type_metadata/js_data_view.json", + "ecmascript/js_type_metadata/js_date.json", + "ecmascript/js_type_metadata/js_date_time_format.json", + "ecmascript/js_type_metadata/js_displaynames.json", + "ecmascript/js_type_metadata/js_error.json", + "ecmascript/js_type_metadata/js_eval_error.json", + "ecmascript/js_type_metadata/js_finalization_registry.json", + "ecmascript/js_type_metadata/js_float32_array.json", + "ecmascript/js_type_metadata/js_float64_array.json", + "ecmascript/js_type_metadata/js_forin_iterator.json", + "ecmascript/js_type_metadata/js_function.json", + "ecmascript/js_type_metadata/js_function_base.json", + "ecmascript/js_type_metadata/js_generator_context.json", + "ecmascript/js_type_metadata/js_generator_function.json", + "ecmascript/js_type_metadata/js_generator_object.json", + "ecmascript/js_type_metadata/js_global_object.json", + "ecmascript/js_type_metadata/js_int16_array.json", + "ecmascript/js_type_metadata/js_int32_array.json", + "ecmascript/js_type_metadata/js_int8_array.json", + "ecmascript/js_type_metadata/js_intl.json", + "ecmascript/js_type_metadata/js_intl_bound_function.json", + "ecmascript/js_type_metadata/js_iterator.json", + "ecmascript/js_type_metadata/js_list_format.json", + "ecmascript/js_type_metadata/js_locale.json", + "ecmascript/js_type_metadata/js_map.json", + "ecmascript/js_type_metadata/js_map_iterator.json", + "ecmascript/js_type_metadata/js_module_namespace.json", + "ecmascript/js_type_metadata/js_native_pointer.json", + "ecmascript/js_type_metadata/js_number_format.json", + "ecmascript/js_type_metadata/js_object.json", + "ecmascript/js_type_metadata/js_oom_error.json", + "ecmascript/js_type_metadata/js_plural_rules.json", + "ecmascript/js_type_metadata/js_primitive_ref.json", + "ecmascript/js_type_metadata/js_promise.json", + "ecmascript/js_type_metadata/js_promise_all_resolve_element_function.json", + "ecmascript/js_type_metadata/js_promise_all_settled_element_function.json", + "ecmascript/js_type_metadata/js_promise_any_reject_element_function.json", + "ecmascript/js_type_metadata/js_promise_executor_function.json", + "ecmascript/js_type_metadata/js_promise_finally_function.json", + "ecmascript/js_type_metadata/js_promise_reactions_function.json", + "ecmascript/js_type_metadata/js_promise_value_thunk_or_thrower_function.json", + "ecmascript/js_type_metadata/js_proxy.json", + "ecmascript/js_type_metadata/js_proxy_revoc_function.json", + "ecmascript/js_type_metadata/js_range_error.json", + "ecmascript/js_type_metadata/js_realm.json", + "ecmascript/js_type_metadata/js_reference_error.json", + "ecmascript/js_type_metadata/js_reg_exp.json", + "ecmascript/js_type_metadata/js_reg_exp_iterator.json", + "ecmascript/js_type_metadata/js_relative_time_format.json", + "ecmascript/js_type_metadata/js_segment_iterator.json", + "ecmascript/js_type_metadata/js_segmenter.json", + "ecmascript/js_type_metadata/js_segments.json", + "ecmascript/js_type_metadata/js_sendable_array_buffer.json", + "ecmascript/js_type_metadata/js_set.json", + "ecmascript/js_type_metadata/js_set_iterator.json", + "ecmascript/js_type_metadata/js_shared_array.json", + "ecmascript/js_type_metadata/js_shared_array_buffer.json", + "ecmascript/js_type_metadata/js_shared_array_iterator.json", + "ecmascript/js_type_metadata/js_shared_async_function.json", + "ecmascript/js_type_metadata/js_shared_bigint64_array.json", + "ecmascript/js_type_metadata/js_shared_biguint64_array.json", + "ecmascript/js_type_metadata/js_shared_float32_array.json", + "ecmascript/js_type_metadata/js_shared_float64_array.json", + "ecmascript/js_type_metadata/js_shared_function.json", + "ecmascript/js_type_metadata/js_shared_int16_array.json", + "ecmascript/js_type_metadata/js_shared_int32_array.json", + "ecmascript/js_type_metadata/js_shared_int8_array.json", + "ecmascript/js_type_metadata/js_shared_map.json", + "ecmascript/js_type_metadata/js_shared_map_iterator.json", + "ecmascript/js_type_metadata/js_shared_object.json", + "ecmascript/js_type_metadata/js_shared_set.json", + "ecmascript/js_type_metadata/js_shared_set_iterator.json", + "ecmascript/js_type_metadata/js_shared_typed_array.json", + "ecmascript/js_type_metadata/js_shared_uint16_array.json", + "ecmascript/js_type_metadata/js_shared_uint32_array.json", + "ecmascript/js_type_metadata/js_shared_uint8_array.json", + "ecmascript/js_type_metadata/js_shared_uint8_clamped_array.json", + "ecmascript/js_type_metadata/js_string_iterator.json", + "ecmascript/js_type_metadata/js_syntax_error.json", + "ecmascript/js_type_metadata/js_termination_error.json", + "ecmascript/js_type_metadata/js_type_error.json", + "ecmascript/js_type_metadata/js_typed_array.json", + "ecmascript/js_type_metadata/js_uint16_array.json", + "ecmascript/js_type_metadata/js_uint32_array.json", + "ecmascript/js_type_metadata/js_uint8_array.json", + "ecmascript/js_type_metadata/js_uint8_clamped_array.json", + "ecmascript/js_type_metadata/js_uri_error.json", + "ecmascript/js_type_metadata/js_weak_map.json", + "ecmascript/js_type_metadata/js_weak_ref.json", + "ecmascript/js_type_metadata/js_weak_set.json", + "ecmascript/js_type_metadata/lexical_env.json", + "ecmascript/js_type_metadata/line_string.json", + "ecmascript/js_type_metadata/linked_node.json", + "ecmascript/js_type_metadata/local_exportentry_record.json", + "ecmascript/js_type_metadata/machine_code_object.json", + "ecmascript/js_type_metadata/marker_cell.json", + "ecmascript/js_type_metadata/method.json", + "ecmascript/js_type_metadata/micro_job_queue.json", + "ecmascript/js_type_metadata/module_record.json", + "ecmascript/js_type_metadata/mutant_tagged_array.json", + "ecmascript/js_type_metadata/native_module_failure_info.json", + "ecmascript/js_type_metadata/pending_job.json", + "ecmascript/js_type_metadata/profile_type_info.json", + "ecmascript/js_type_metadata/profile_type_info_cell_0.json", + "ecmascript/js_type_metadata/profile_type_info_cell_1.json", + "ecmascript/js_type_metadata/profile_type_info_cell_n.json", + "ecmascript/js_type_metadata/program.json", + "ecmascript/js_type_metadata/promise_capability.json", + "ecmascript/js_type_metadata/promise_iterator_record.json", + "ecmascript/js_type_metadata/promise_reactions.json", + "ecmascript/js_type_metadata/promise_record.json", + "ecmascript/js_type_metadata/property_box.json", + "ecmascript/js_type_metadata/proto_change_marker.json", + "ecmascript/js_type_metadata/prototype_handler.json", + "ecmascript/js_type_metadata/prototype_info.json", + "ecmascript/js_type_metadata/rb_treenode.json", + "ecmascript/js_type_metadata/record.json", + "ecmascript/js_type_metadata/resolvedbinding_record.json", + "ecmascript/js_type_metadata/resolvedindexbinding_record.json", + "ecmascript/js_type_metadata/resolvedrecordbinding_record.json", + "ecmascript/js_type_metadata/resolvedrecordindexbinding_record.json", + "ecmascript/js_type_metadata/resolving_functions_record.json", + "ecmascript/js_type_metadata/sendable_env.json", + "ecmascript/js_type_metadata/sliced_string.json", + "ecmascript/js_type_metadata/source_text_module_record.json", + "ecmascript/js_type_metadata/star_exportentry_record.json", + "ecmascript/js_type_metadata/store_ts_handler.json", + "ecmascript/js_type_metadata/symbol.json", + "ecmascript/js_type_metadata/tagged_array.json", + "ecmascript/js_type_metadata/tagged_dictionary.json", + "ecmascript/js_type_metadata/tagged_node.json", + "ecmascript/js_type_metadata/tagged_object.json", + "ecmascript/js_type_metadata/template_map.json", + "ecmascript/js_type_metadata/track_info.json", + "ecmascript/js_type_metadata/trans_with_proto_handler.json", + "ecmascript/js_type_metadata/transition_handler.json", + "ecmascript/js_type_metadata/tree_string.json", + "ecmascript/js_type_metadata/type_enums.json", + "ecmascript/js_type_metadata/type_range.json", + "ecmascript/js_type_metadata/vtable.json", +] + +action("gen_js_type_metadata") { + inputs = js_type_metadata_sources + + script = "$js_root/script/metadata_generate.py" + + metadata_file_gen_dir = "$root_gen_dir/arkcompiler/ets_runtime" + + args = [ + "--enum", + rebase_path("$js_root/ecmascript/js_type_metadata/type_enums.json"), + "--metadata", + rebase_path("$js_root/ecmascript/js_type_metadata"), + "--output", + rebase_path("$metadata_file_gen_dir/metadata.json"), + "--version", + "1.0.0", + ] + + outputs = [ "$metadata_file_gen_dir/metadata.json" ] +} + +ohos_prebuilt_shared_library("js_type_metadata") { + deps = [ ":gen_js_type_metadata" ] + source = "$root_gen_dir/arkcompiler/ets_runtime/metadata.json" + + relative_install_dir = arkcompiler_relative_lib_path + part_name = "ets_runtime" + subsystem_name = "arkcompiler" +} diff --git a/compiler_service/BUILD.gn b/compiler_service/BUILD.gn index e1e850c9e080c599cdeb4493bf2c13bcbfe3ed42..ede1a95506913caef3023ee2730f0480a09d3cde 100644 --- a/compiler_service/BUILD.gn +++ b/compiler_service/BUILD.gn @@ -74,6 +74,12 @@ ohos_shared_library("libcompiler_service") { defines += [ "CODE_SIGN_ENABLE" ] } + if (!ark_standalone_build && !(defined(is_arkui_x) && is_arkui_x) && + is_ohos && is_standard_system) { + external_deps += [ "init:libbegetutil" ] + defines += [ "ENABLE_COMPILER_SERVICE_GET_PARAMETER" ] + } + install_enable = true install_images = [ "system" ] diff --git a/compiler_service/include/aot_compiler_constants.h b/compiler_service/include/aot_compiler_constants.h index a8fe7c5be358f06269ead70f82fa101fb491792f..a53a766140d3579426033166647cc507463d37bc 100644 --- a/compiler_service/include/aot_compiler_constants.h +++ b/compiler_service/include/aot_compiler_constants.h @@ -35,6 +35,8 @@ const std::string APP_SIGNATURE = "appIdentifier"; const std::string ABC_PATH = "ABC-Path"; const std::string TARGET_COMPILER_MODE = "target-compiler-mode"; const std::string COMPILER_PKG_INFO = "compiler-pkg-info"; +const std::string COMPILER_ENABLE_AOT_CODE_COMMENT = "compiler-enable-aot-code-comment"; +const std::string COMPILER_LOG_OPT = "compiler-log"; } // namespace ArgsIdx diff --git a/compiler_service/src/aot_compiler_impl.cpp b/compiler_service/src/aot_compiler_impl.cpp index 89e484b88eb38ce9ab447fb14cf63f37e899ba1a..2ce721d91ded8efa93ff195f1e7f159dc8ddc5a2 100644 --- a/compiler_service/src/aot_compiler_impl.cpp +++ b/compiler_service/src/aot_compiler_impl.cpp @@ -35,6 +35,9 @@ #ifdef CODE_SIGN_ENABLE #include "local_code_sign_kit.h" #endif +#ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER +#include "base/startup/init/interfaces/innerkits/include/syspara/parameters.h" +#endif #include "system_ability_definition.h" namespace OHOS::ArkCompiler { @@ -96,6 +99,15 @@ int32_t AotCompilerImpl::PrepareArgs(const std::unordered_map sigData; size_t offset = 0; // check if there is enough data - if (offset + sizeof(int16_t) > size) { + if (offset + sizeof(int16_t) >= size) { return false; } uint8_t numberOfArgs = static_cast(data[offset]); @@ -39,25 +39,25 @@ bool DoSomethingInterestingWithMyAPI(const char* data, size_t size) offset += sizeof(uint8_t); for (uint8_t i = 0; i < numberOfArgs && offset < size; ++i) { // read the key length - if (offset + sizeof(int16_t) > size) { + if (offset + sizeof(int16_t) >= size) { break; } uint8_t keyLength = static_cast(data[offset]); offset += sizeof(uint8_t); // read the key - if (offset + keyLength > size) { + if (offset + keyLength >= size) { break; } std::string key(&data[offset], keyLength); offset += keyLength; // read the value length - if (offset + sizeof(uint8_t) > size) { + if (offset + sizeof(uint8_t) >= size) { break; } uint8_t valueLength = static_cast(data[offset]); offset += sizeof(uint8_t); // read the value - if (offset + valueLength > size) { + if (offset + valueLength >= size) { break; } std::string value(&data[offset], valueLength); @@ -66,7 +66,7 @@ bool DoSomethingInterestingWithMyAPI(const char* data, size_t size) } // parse sigData - while (offset + sizeof(int16_t) <= size) { + while (offset + sizeof(int16_t) < size) { int16_t signalValue; std::copy_n(&data[offset], sizeof(int16_t), &signalValue); sigData.push_back(signalValue); diff --git a/compiler_service/test/fuzztest/compilerinterfacestub_fuzzer/BUILD.gn b/compiler_service/test/fuzztest/compilerinterfacestub_fuzzer/BUILD.gn index 84baf67e818771fc46e9063a95ebb117f960beca..45843ab97d4655f23fbe636bb04f67871fbfa7ba 100644 --- a/compiler_service/test/fuzztest/compilerinterfacestub_fuzzer/BUILD.gn +++ b/compiler_service/test/fuzztest/compilerinterfacestub_fuzzer/BUILD.gn @@ -27,6 +27,7 @@ ohos_fuzztest("CompilerInterfaceStubFuzzTest") { include_dirs = compiler_service_include_dirs sources = aot_compiler_service_sources external_deps = [ + "ability_base:want", "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "c_utils:utils", diff --git a/compiler_service/test/fuzztest/compilerinterfacestub_fuzzer/compilerinterfacestub_fuzzer.cpp b/compiler_service/test/fuzztest/compilerinterfacestub_fuzzer/compilerinterfacestub_fuzzer.cpp index 235633ef4cf305fa591ddb9963ba135fc936eeea..e8134265e7fab7e3a638c117949ab52fea2bcb5f 100644 --- a/compiler_service/test/fuzztest/compilerinterfacestub_fuzzer/compilerinterfacestub_fuzzer.cpp +++ b/compiler_service/test/fuzztest/compilerinterfacestub_fuzzer/compilerinterfacestub_fuzzer.cpp @@ -31,7 +31,6 @@ constexpr int DATA_THREE = 3; constexpr size_t OFFSET_ONE = 8; constexpr size_t OFFSET_TWO = 16; constexpr size_t OFFSET_THREE = 24; -constexpr size_t FOO_MAX_LEN = 1024; constexpr size_t MESSAGE_SIZE = MIN_TRANSACTION_ID + 4; // 4 code methods OnRemoteRequest constexpr size_t U32_AT_SIZE = 4; static AotCompilerService compilerService(AOT_COMPILER_SERVICE_ID, false); @@ -69,11 +68,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) return 0; } - /* Validate the length of size */ - if (size > OHOS::FOO_MAX_LEN) { - return 0; - } - char* dataPtr = static_cast(malloc(size + 1)); if (dataPtr == nullptr) { return 0; diff --git a/compiler_service/test/unittest/aotcompilerimpl_unit/aotcompilerimpl_unit.cpp b/compiler_service/test/unittest/aotcompilerimpl_unit/aotcompilerimpl_unit.cpp index d4f35c3a05845edeea36083a4757e88b696122fb..fd7b069b26fc77ae292b93f5c7af2d4d365e8d17 100644 --- a/compiler_service/test/unittest/aotcompilerimpl_unit/aotcompilerimpl_unit.cpp +++ b/compiler_service/test/unittest/aotcompilerimpl_unit/aotcompilerimpl_unit.cpp @@ -111,7 +111,7 @@ public: { #ifdef CODE_SIGN_ENABLE if (!allowAotCompiler_) { - return ERR_AOT_COMPILER_CONNECT_FAILED; + return ERR_AOT_COMPILER_CALL_CANCELLED; } if (argsMap.empty() || (PrepareArgs(argsMap) != ERR_OK)) { return ERR_AOT_COMPILER_PARAM_FAILED; @@ -557,7 +557,7 @@ HWTEST_F(AotCompilerImplTest, AotCompilerImplTest_022, TestSize.Level0) #ifdef CODE_SIGN_ENABLE aotImplMock.PauseAotCompilerMock(); ret = aotImplMock.EcmascriptAotCompiler(argsMap, sigData); - EXPECT_EQ(ret, ERR_AOT_COMPILER_CONNECT_FAILED); + EXPECT_EQ(ret, ERR_AOT_COMPILER_CALL_CANCELLED); aotImplMock.AllowAotCompilerMock(); ret = aotImplMock.EcmascriptAotCompiler(argsMap, sigData); diff --git a/ecmascript/base/atomic_helper.cpp b/ecmascript/base/atomic_helper.cpp index 7fd67717571c6d8fe7b10bf294998e952dc61e36..80d7ad14e70825ef2daf7b3f2fc956a891bf8b2c 100644 --- a/ecmascript/base/atomic_helper.cpp +++ b/ecmascript/base/atomic_helper.cpp @@ -63,32 +63,27 @@ uint32_t AtomicHelper::ValidateAtomicAccess(JSThread *thread, const JSHandle typedArrayObj(typedArray); JSHandle srcObj(typedArray); - int32_t length = static_cast(srcObj->GetArrayLength()); + uint32_t length = srcObj->GetArrayLength(); // 3. Let accessIndex be ? ToIndex(requestIndex). JSTaggedNumber accessIndex = JSTaggedValue::ToIndex(thread, requestIndex); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0); - int32_t index = base::NumberHelper::DoubleInRangeInt32(accessIndex.GetNumber()); - - // 4. Assert: accessIndex ≥ 0. - ASSERT(index >= 0); - - // 5. If accessIndex ≥ length, throw a RangeError exception. + uint64_t index = base::NumberHelper::DoubleToUInt64(accessIndex.GetNumber()); + // 4. If accessIndex ≥ length, throw a RangeError exception. if (index >= length) { THROW_RANGE_ERROR_AND_RETURN(thread, "Index is overflow.", 0); } - // 6. Let arrayTypeName be typedArray.[[TypedArrayName]]. - // 7. Let elementSize be the Element Size value specified in Table 60 for arrayTypeName. - // 8. Let offset be typedArray.[[ByteOffset]]. + // 5. Let arrayTypeName be typedArray.[[TypedArrayName]]. + // 6. Let elementSize be the Element Size value specified in Table 60 for arrayTypeName. + // 7. Let offset be typedArray.[[ByteOffset]]. JSHandle arrayTypeName(thread, JSTypedArray::Cast(*typedArrayObj)->GetTypedArrayName()); DataViewType elementType = JSTypedArray::GetTypeFromName(thread, arrayTypeName); uint32_t elementSize = TypedArrayHelper::GetSizeFromType(elementType); uint32_t offset = srcObj->GetByteOffset(); - // 9. Return (accessIndex × elementSize) + offset. - ASSERT((static_cast(index) * static_cast(elementSize) + - static_cast(offset)) <= static_cast(UINT32_MAX)); - uint32_t allOffset = static_cast(index) * elementSize + offset; + // 8. Return (accessIndex × elementSize) + offset. + ASSERT(index * elementSize + offset <= UINT32_MAX); + uint32_t allOffset = static_cast(index * elementSize + offset); return allOffset; } diff --git a/ecmascript/base/config.h b/ecmascript/base/config.h index 718a28e6738752f2fc9e376315fa9fd2172c9bb2..ac19edff4fc212d480bc286af9b17c4a7228c2ef 100644 --- a/ecmascript/base/config.h +++ b/ecmascript/base/config.h @@ -34,6 +34,9 @@ namespace panda::ecmascript { #define ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER 0 #define ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC 0 #define ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 0 +#define ECMASCRIPT_ENABLE_TRACE_IC 0 + +#define ENABLE_NEXT_OPTIMIZATION 1 #ifndef NDEBUG #define ECMASCRIPT_ENABLE_INTERPRETER_LOG 1 @@ -42,6 +45,8 @@ namespace panda::ecmascript { #define ECMASCRIPT_ENABLE_BUILTINS_RUNTIME_STAT 1 #define ECMASCRIPT_ENABLE_ALLOCATE_AND_GC_RUNTIME_STAT 1 #define ECMASCRIPT_ENABLE_THREAD_STATE_CHECK 1 +#define ECMASCRIPT_ENABLE_COLLECTING_OPCODES 1 +#define ECMASCRIPT_ENABLE_INTERPRETER_ARKUINAITVE_TRACE 1 #else #define ECMASCRIPT_ENABLE_INTERPRETER_LOG 0 #define ECMASCRIPT_ENABLE_BASELINE_LOG 0 @@ -50,6 +55,8 @@ namespace panda::ecmascript { #define ECMASCRIPT_ENABLE_BUILTINS_RUNTIME_STAT 0 #define ECMASCRIPT_ENABLE_ALLOCATE_AND_GC_RUNTIME_STAT 0 #define ECMASCRIPT_ENABLE_THREAD_STATE_CHECK 0 +#define ECMASCRIPT_ENABLE_COLLECTING_OPCODES 0 +#define ECMASCRIPT_ENABLE_INTERPRETER_ARKUINAITVE_TRACE 0 #endif /* * 1. close ic diff --git a/ecmascript/base/dtoa_helper.cpp b/ecmascript/base/dtoa_helper.cpp index ca544cccd950aba5a8f4f0ec14c7b29018aef45b..d796e957f2ff66822521be90dcdf2962b6f44572 100644 --- a/ecmascript/base/dtoa_helper.cpp +++ b/ecmascript/base/dtoa_helper.cpp @@ -60,6 +60,8 @@ DtoaHelper::DiyFp DtoaHelper::GetCachedPowerByIndex(size_t index) -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066}; + ASSERT_PRINT(index < sizeof(kCachedPowers_F) / sizeof(kCachedPowers_F[0]) && + index < sizeof(kCachedPowers_E) / sizeof(kCachedPowers_E[0]), "invalid index: " << index); return DtoaHelper::DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); } diff --git a/ecmascript/base/json_stringifier.h b/ecmascript/base/json_stringifier.h index ad7914a9e8899ef55216a593b0110cb129520323..a37d184b67a2de16cdd2bed66e4ab33b572ab915 100644 --- a/ecmascript/base/json_stringifier.h +++ b/ecmascript/base/json_stringifier.h @@ -50,6 +50,7 @@ private: bool SerializeJSONObject(const JSHandle &value, const JSHandle &replacer); bool SerializeJSArray(const JSHandle &value, const JSHandle &replacer); + bool SerializeJSProxy(const JSHandle &object, const JSHandle &replacer); void SerializePrimitiveRef(const JSHandle &primitiveRef); diff --git a/ecmascript/base/number_helper.cpp b/ecmascript/base/number_helper.cpp index 096c7cb9d7592c2756864d80c5088f7aa7f7f320..a648bf6cf36715d57c6466f0ab4bfdc00bdc8f35 100644 --- a/ecmascript/base/number_helper.cpp +++ b/ecmascript/base/number_helper.cpp @@ -830,6 +830,13 @@ int64_t NumberHelper::DoubleToInt64(double d) return static_cast(d); } +uint64_t NumberHelper::DoubleToUInt64(double d) +{ + ASSERT(d <= static_cast(std::numeric_limits::max()) && + d >= static_cast(std::numeric_limits::min())); + return static_cast(d); +} + bool NumberHelper::IsDigitalString(const uint8_t *start, const uint8_t *end) { int len = end - start; @@ -1140,15 +1147,23 @@ int32_t NumberHelper::DoubleToInt(double d, size_t bits) int32_t NumberHelper::DoubleInRangeInt32(double d) { - if (d > INT_MAX) { + if (d >= static_cast(INT_MAX)) { return INT_MAX; } - if (d < INT_MIN) { + if (d <= static_cast(INT_MIN)) { return INT_MIN; } return base::NumberHelper::DoubleToInt(d, base::INT32_BITS); } +int32_t NumberHelper::SaturateTruncDoubleToInt32(double d) +{ + if (std::isnan(d) || d == -base::POSITIVE_INFINITY) { + return 0; + } + return base::NumberHelper::DoubleInRangeInt32(d); +} + JSTaggedValue NumberHelper::StringToBigInt(JSThread *thread, JSHandle strVal) { auto strObj = static_cast(strVal->GetTaggedObject()); diff --git a/ecmascript/base/number_helper.h b/ecmascript/base/number_helper.h index 15c0c17220b740f847ad3efaf8c9200406be84ee..2c5218edb268ee1259f48e57094e93f236784554 100644 --- a/ecmascript/base/number_helper.h +++ b/ecmascript/base/number_helper.h @@ -168,6 +168,7 @@ public: static JSHandle NumberToString(const JSThread *thread, JSTaggedValue number); static double PUBLIC_API TruncateDouble(double d); static int64_t DoubleToInt64(double d); + static uint64_t DoubleToUInt64(double d); static bool IsDigitalString(const uint8_t *start, const uint8_t *end); static int StringToInt(const uint8_t *start, const uint8_t *end); static std::pair FastStringToNumber(const uint8_t *start, @@ -175,6 +176,7 @@ public: static double StringToDouble(const uint8_t *start, const uint8_t *end, uint8_t radix, uint32_t flags = NO_FLAGS); static int32_t DoubleToInt(double d, size_t bits); static int32_t PUBLIC_API DoubleInRangeInt32(double d); + static int32_t PUBLIC_API SaturateTruncDoubleToInt32(double d); static JSTaggedValue StringToNumber(EcmaString *string, int32_t radix); static JSTaggedValue StringToDoubleWithRadix(const uint8_t *start, const uint8_t *end, int radix, bool *negative); static CString IntToString(int number); diff --git a/ecmascript/base/tests/BUILD.gn b/ecmascript/base/tests/BUILD.gn index eda2c8f53fefd379f42c4b9149aed934f1f45ac4..5037cf3c9e60af1778c617dd214581cac567325d 100644 --- a/ecmascript/base/tests/BUILD.gn +++ b/ecmascript/base/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("Base_001_Test") { module_out_path = module_output_path diff --git a/ecmascript/base/tests/ason_test.cpp b/ecmascript/base/tests/ason_test.cpp index b38dd6cd5cc25c5f5ee5e5e8a43ea10a31f31959..b10bf02f86b34b44c7a4f8a609b2fdfd8973b471 100644 --- a/ecmascript/base/tests/ason_test.cpp +++ b/ecmascript/base/tests/ason_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/ecmascript/base/utf_helper.cpp b/ecmascript/base/utf_helper.cpp index 3814200fa73b52b13d93497bbc1d865797dfaaf5..354ebd3f27dd827f4895e8f757722d5247591292 100644 --- a/ecmascript/base/utf_helper.cpp +++ b/ecmascript/base/utf_helper.cpp @@ -98,12 +98,8 @@ inline size_t UTF8Length(uint32_t codepoint) } // Methods for encode unicode to unicode -size_t EncodeUTF8(uint32_t codepoint, uint8_t* utf8, size_t len, size_t index) +size_t EncodeUTF8(uint32_t codepoint, uint8_t* utf8, size_t index, size_t size) { - size_t size = UTF8Length(codepoint); - if (index + size > len) { - return 0; - } for (size_t j = size - 1; j > 0; j--) { uint8_t cont = ((codepoint | byteMark) & byteMask); utf8[index + j] = cont; @@ -282,7 +278,11 @@ size_t ConvertRegionUtf16ToUtf8(const uint16_t *utf16In, uint8_t *utf8Out, size_ } continue; } - utf8Pos += EncodeUTF8(codepoint, utf8Out, utf8Len, utf8Pos); + size_t size = UTF8Length(codepoint); + if (utf8Pos + size > utf8Len) { + break; + } + utf8Pos += EncodeUTF8(codepoint, utf8Out, utf8Pos, size); } return utf8Pos; } @@ -309,7 +309,11 @@ size_t DebuggerConvertRegionUtf16ToUtf8(const uint16_t *utf16In, uint8_t *utf8Ou } continue; } - utf8Pos += EncodeUTF8(codepoint, utf8Out, utf8Len, utf8Pos); + size_t size = UTF8Length(codepoint); + if (utf8Pos + size > utf8Len) { + break; + } + utf8Pos += EncodeUTF8(codepoint, utf8Out, utf8Pos, size); } return utf8Pos; } diff --git a/ecmascript/base/utf_helper.h b/ecmascript/base/utf_helper.h index 7216b8e54813f36456af495b487855c6c4b8b5f7..ee25e0d846e55e475f1dbac99825c916a6a47b46 100644 --- a/ecmascript/base/utf_helper.h +++ b/ecmascript/base/utf_helper.h @@ -102,7 +102,7 @@ static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF uint32_t DecodeUTF16(uint16_t const *utf16, size_t len, size_t *index, bool cesu8 = false); -size_t EncodeUTF8(uint32_t codepoint, uint8_t* utf8, size_t len, size_t index); +size_t EncodeUTF8(uint32_t codepoint, uint8_t* utf8, size_t index, size_t size); uint32_t UTF16Decode(uint16_t lead, uint16_t trail); diff --git a/ecmascript/builtins/builtins.cpp b/ecmascript/builtins/builtins.cpp index 5081416951b49e43194658a9394e5681291de048..e8e3adafa3fdb85d3900f922321780eb68ee1625 100644 --- a/ecmascript/builtins/builtins.cpp +++ b/ecmascript/builtins/builtins.cpp @@ -1196,7 +1196,8 @@ void Builtins::SetErrorWithRealm(const JSHandle &realm, const JSType realm->SetTerminationErrorFunction(thread_, nativeErrorFunction); break; default: - break; + LOG_ECMA(FATAL) << "this branch is unreachable, errorTag: " << static_cast(errorTag); + UNREACHABLE(); } PropertyDescriptor descriptor(thread_, nativeErrorFunction, true, false, true); JSObject::DefineOwnProperty(thread_, globalObject, nameString, descriptor); @@ -2151,7 +2152,9 @@ void Builtins::InitializeArray(const JSHandle &env, const JSHandle arrBaseFuncInstanceHClass = factory_->CreateJSArrayInstanceClass( objFuncPrototypeVal, BuiltinsArray::GetNumPrototypeInlinedProperties()); - + // Since we don't want the operations on the array prototype to go through the IR code. + // Specially we set the bit of the array prototype to true. + arrBaseFuncInstanceHClass->SetIsJSArrayPrototypeModified(true); // Array.prototype JSHandle arrFuncPrototype = factory_->NewJSObjectWithInit(arrBaseFuncInstanceHClass); JSHandle::Cast(arrFuncPrototype)->SetLength(FunctionLength::ZERO); diff --git a/ecmascript/builtins/builtins.h b/ecmascript/builtins/builtins.h index 8236c41b1d300b2e2c79f8022b659a060d609f7e..447dc9faa5d22acfd8da0a6e7a7985447eaa1b75 100644 --- a/ecmascript/builtins/builtins.h +++ b/ecmascript/builtins/builtins.h @@ -48,6 +48,9 @@ public: void Initialize(const JSHandle &env, JSThread *thread, bool lazyInit = false, bool isRealm = false); void InitializeForSnapshot(JSThread *thread); + void InitializeSharedBitVector(const JSHandle &env, + const JSHandle &sObjPrototype, + const JSHandle &sFuncPrototype) const; private: JSThread *thread_{nullptr}; ObjectFactory *factory_{nullptr}; @@ -443,7 +446,9 @@ private: JSHandle CreateSSetPrototypeHClass(const JSHandle &sObjPrototype) const; JSHandle CreateSSetFunctionHClass(const JSHandle &sFuncPrototype) const; JSHandle CreateSMapPrototypeHClass(const JSHandle &sObjPrototype) const; + JSHandle CreateBitVectorPrototypeHClass(const JSHandle &sObjPrototype) const; JSHandle CreateSMapFunctionHClass(const JSHandle &sFuncPrototype) const; + JSHandle CreateBitVectorFunctionHClass(const JSHandle &sFuncPrototype) const; JSHandle CreateSArrayPrototypeHClass(const JSHandle &sObjPrototype) const; JSHandle CreateSArrayFunctionHClass(const JSHandle &sFuncPrototype) const; JSHandle CreateSTypedArrayPrototypeHClass(const JSHandle &sObjPrototype) const; diff --git a/ecmascript/builtins/builtins_ark_tools.cpp b/ecmascript/builtins/builtins_ark_tools.cpp index f319e48639fb0702fdeabbd7f458d7fd8f83dcc1..0a374bffe52be4544363267061f150f9f7822383 100644 --- a/ecmascript/builtins/builtins_ark_tools.cpp +++ b/ecmascript/builtins/builtins_ark_tools.cpp @@ -122,8 +122,8 @@ JSTaggedValue BuiltinsArkTools::IsTSHClass(EcmaRuntimeCallInfo *info) ASSERT(info->GetArgsNumber() == 1); JSHandle object = GetCallArg(info, 0); JSHClass *hclass = object->GetTaggedObject()->GetClass(); - bool isTSHClass = hclass->IsTS(); - return GetTaggedBoolean(isTSHClass); + bool isAOTHClass = hclass->IsAOT(); + return GetTaggedBoolean(isAOTHClass); } JSTaggedValue BuiltinsArkTools::GetHClass(EcmaRuntimeCallInfo *info) @@ -151,9 +151,23 @@ JSTaggedValue BuiltinsArkTools::IsSlicedString(EcmaRuntimeCallInfo *info) return GetTaggedBoolean(str->IsSlicedString()); } +JSTaggedValue BuiltinsArkTools::IsStableJsArray(EcmaRuntimeCallInfo *info) +{ + DISALLOW_GARBAGE_COLLECTION; + ASSERT(info); + JSThread *thread = info->GetThread(); + RETURN_IF_DISALLOW_ARKTOOLS(thread); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + ASSERT(info->GetArgsNumber() == 1); + JSHandle object = GetCallArg(info, 0); + return (object->IsStableJSArray(thread)) ? + GetTaggedBoolean(true) : GetTaggedBoolean(false); +} + JSTaggedValue BuiltinsArkTools::IsNotHoleProperty(EcmaRuntimeCallInfo *info) { - [[maybe_unused]] DisallowGarbageCollection noGc; + DISALLOW_GARBAGE_COLLECTION; ASSERT(info); JSThread *thread = info->GetThread(); RETURN_IF_DISALLOW_ARKTOOLS(thread); @@ -173,7 +187,7 @@ JSTaggedValue BuiltinsArkTools::IsNotHoleProperty(EcmaRuntimeCallInfo *info) JSTaggedValue BuiltinsArkTools::HiddenStackSourceFile(EcmaRuntimeCallInfo *info) { - [[maybe_unused]] DisallowGarbageCollection noGc; + DISALLOW_GARBAGE_COLLECTION; ASSERT(info); JSThread *thread = info->GetThread(); RETURN_IF_DISALLOW_ARKTOOLS(thread); @@ -623,6 +637,38 @@ JSTaggedValue BuiltinsArkTools::TimeInUs([[maybe_unused]] EcmaRuntimeCallInfo *i return JSTaggedValue(scope.GetCurTime()); } +#if ECMASCRIPT_ENABLE_COLLECTING_OPCODES +JSTaggedValue BuiltinsArkTools::StartCollectingOpcodes([[maybe_unused]] EcmaRuntimeCallInfo *info) +{ + std::unordered_map bytecodeStatsMap; + [[maybe_unused]] JSThread *thread = info->GetThread(); + RETURN_IF_DISALLOW_ARKTOOLS(thread); + EcmaVM *vm = thread->GetEcmaVM(); + vm->SetBytecodeStatsStack(bytecodeStatsMap); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle str = JSTaggedValue::ToString(thread, GetCallArg(info, 0)); + auto msg = EcmaStringAccessor(str).ToCString(); + LOG_ECMA(ERROR) << msg.c_str(); + return JSTaggedValue::Undefined(); +} + +JSTaggedValue BuiltinsArkTools::StopCollectingOpcodes([[maybe_unused]] EcmaRuntimeCallInfo *info) +{ + [[maybe_unused]] JSThread *thread = info->GetThread(); + RETURN_IF_DISALLOW_ARKTOOLS(thread); + EcmaVM *vm = thread->GetEcmaVM(); + vm->PrintCollectedByteCode(); + std::stack> &bytecodeStatsStack_ = + vm->GetBytecodeStatsStack(); + bytecodeStatsStack_.pop(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle str = JSTaggedValue::ToString(thread, GetCallArg(info, 0)); + auto msg = EcmaStringAccessor(str).ToCString(); + LOG_ECMA(ERROR) << msg.c_str(); + return JSTaggedValue::Undefined(); +} +#endif + #if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT JSTaggedValue BuiltinsArkTools::StartScopeLockStats(EcmaRuntimeCallInfo *info) { @@ -1322,8 +1368,8 @@ JSTaggedValue BuiltinsArkTools::JitCompileSync(EcmaRuntimeCallInfo *info) return JSTaggedValue::False(); } JSHandle jsFunction(thisValue); - Jit::Compile(thread->GetEcmaVM(), jsFunction, CompilerTier::FAST, - MachineCode::INVALID_OSR_OFFSET, JitCompileMode::SYNC); + Jit::Compile(thread->GetEcmaVM(), jsFunction, CompilerTier::Tier::FAST, + MachineCode::INVALID_OSR_OFFSET, JitCompileMode::Mode::SYNC); return JSTaggedValue::True(); } @@ -1338,8 +1384,8 @@ JSTaggedValue BuiltinsArkTools::JitCompileAsync(EcmaRuntimeCallInfo *info) return JSTaggedValue::False(); } JSHandle jsFunction(thisValue); - Jit::Compile(thread->GetEcmaVM(), jsFunction, CompilerTier::FAST, - MachineCode::INVALID_OSR_OFFSET, JitCompileMode::ASYNC); + Jit::Compile(thread->GetEcmaVM(), jsFunction, CompilerTier::Tier::FAST, + MachineCode::INVALID_OSR_OFFSET, JitCompileMode::Mode::ASYNC); return JSTaggedValue::True(); } @@ -1359,10 +1405,7 @@ JSTaggedValue BuiltinsArkTools::WaitJitCompileFinish(EcmaRuntimeCallInfo *info) if (!jit->IsEnableFastJit()) { return JSTaggedValue::False(); } - if (jsFunction->GetMachineCode() == JSTaggedValue::Undefined()) { - return JSTaggedValue::False(); - } - while (jsFunction->GetMachineCode() == JSTaggedValue::Hole()) { + while (!jsFunction->GetMachineCode().IsMachineCodeObject()) { // just spin check thread->CheckSafepoint(); } diff --git a/ecmascript/builtins/builtins_ark_tools.h b/ecmascript/builtins/builtins_ark_tools.h index 1c34c4e68c07f7a373fb96491187639bed548e79..45dcc125f6becabd0ab71f8be9d82418d682ca1d 100644 --- a/ecmascript/builtins/builtins_ark_tools.h +++ b/ecmascript/builtins/builtins_ark_tools.h @@ -85,6 +85,7 @@ V("isSmi", IsSmi, 1, INVALID) \ V("createPrivateSymbol", CreatePrivateSymbol, 1, INVALID) \ V("isArray", IsArray, 1, INVALID) \ + V("isStableJsArray", IsStableJsArray, 1, INVALID) \ V("createDataProperty", CreateDataProperty, 3, INVALID) \ V("functionGetInferredName", FunctionGetInferredName, 1, INVALID) \ V("stringLessThan", StringLessThan, 2, INVALID) \ @@ -155,12 +156,21 @@ #define BUILTIN_ARK_TOOLS_FUNCTIONS_CPUPROFILER(V) // Nothing #endif +#if ECMASCRIPT_ENABLE_COLLECTING_OPCODES +#define BUILTIN_ARK_TOOLS_FUNCTIONS_COLLECTING_OPCODES(V) \ + V("startCollectingOpcodes", StartCollectingOpcodes, 1, INVALID) \ + V("stopCollectingOpcodes", StopCollectingOpcodes, 1, INVALID) +#else +#define BUILTIN_ARK_TOOLS_FUNCTIONS_COLLECTING_OPCODES(V) // Nothing +#endif + #define BUILTIN_ARK_TOOLS_FUNCTIONS(V) \ BUILTIN_ARK_TOOLS_FUNCTIONS_COMMON(V) \ BUILTIN_ARK_TOOLS_FUNCTIONS_CPUPROFILER(V) \ BUILTIN_ARK_TOOLS_FUNCTIONS_REGRESS(V) \ BUILTIN_ARK_TOOLS_FUNCTIONS_SCOPE_LOCK_STATS(V) \ - BUILTIN_ARK_TOOLS_FUNCTIONS_JITCOMPILE(V) + BUILTIN_ARK_TOOLS_FUNCTIONS_JITCOMPILE(V) \ + BUILTIN_ARK_TOOLS_FUNCTIONS_COLLECTING_OPCODES(V) namespace panda::ecmascript::builtins { class BuiltinsArkTools : public base::BuiltinsBase { @@ -177,13 +187,15 @@ public: static JSTaggedValue DumpHClass(EcmaRuntimeCallInfo *info); - // return whether the hclass used for object is created by static ts type + // return whether the hclass used for object is created by AOT static JSTaggedValue IsTSHClass(EcmaRuntimeCallInfo *info); static JSTaggedValue GetHClass(EcmaRuntimeCallInfo *info); static JSTaggedValue IsSlicedString(EcmaRuntimeCallInfo *info); + static JSTaggedValue IsStableJsArray(EcmaRuntimeCallInfo *info); + static JSTaggedValue IsNotHoleProperty(EcmaRuntimeCallInfo *info); static JSTaggedValue ForcePartialGC(EcmaRuntimeCallInfo *info); @@ -247,6 +259,12 @@ public: static JSTaggedValue TimeInUs(EcmaRuntimeCallInfo *info); +#if ECMASCRIPT_ENABLE_COLLECTING_OPCODES + static JSTaggedValue StartCollectingOpcodes([[maybe_unused]] EcmaRuntimeCallInfo *info); + + static JSTaggedValue StopCollectingOpcodes([[maybe_unused]] EcmaRuntimeCallInfo *info); +#endif + #if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT static JSTaggedValue StartScopeLockStats(EcmaRuntimeCallInfo *info); diff --git a/ecmascript/builtins/builtins_array.cpp b/ecmascript/builtins/builtins_array.cpp index 06f39bf9dd23a8679c38550ec9570ec6a56a1598..f41f141f0b8c33a52ed801e85e20574f395e3f21 100644 --- a/ecmascript/builtins/builtins_array.cpp +++ b/ecmascript/builtins/builtins_array.cpp @@ -19,6 +19,7 @@ #include "ecmascript/base/typed_array_helper-inl.h" #include "ecmascript/interpreter/interpreter.h" +#include "ecmascript/js_array.h" #include "ecmascript/js_map_iterator.h" #include "ecmascript/js_stable_array.h" #include "ecmascript/object_fast_operator-inl.h" @@ -52,10 +53,20 @@ JSTaggedValue BuiltinsArray::ArrayConstructor(EcmaRuntimeCallInfo *argv) // In NewJSObjectByConstructor(), will get prototype. // 5. ReturnIfAbrupt(proto). + auto CheckAndSetPrototypeModified = [] (JSThread* thread, const JSHandle& newArrayHandle) { + if (!JSArray::IsProtoNotChangeJSArray(thread, newArrayHandle)) { + newArrayHandle->GetJSHClass()->SetIsJSArrayPrototypeModified(true); + } + }; + // 22.1.1.1 Array ( ) if (argc == 0) { // 6. Return ArrayCreate(0, proto). - return JSArray::ArrayCreate(thread, JSTaggedNumber(0), newTarget).GetTaggedValue(); + auto arrayHandle = JSArray::ArrayCreate(thread, JSTaggedNumber(0), newTarget); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + auto newArrayHandle = JSHandle::Cast(arrayHandle); + CheckAndSetPrototypeModified(thread, newArrayHandle); + return newArrayHandle.GetTaggedValue(); } // 22.1.1.2 Array(len) @@ -88,6 +99,7 @@ JSTaggedValue BuiltinsArray::ArrayConstructor(EcmaRuntimeCallInfo *argv) JSArray::SetCapacity(thread, newArrayHandle, 0, newLen, true); // 11. Return array. + CheckAndSetPrototypeModified(thread, newArrayHandle); return newArrayHandle.GetTaggedValue(); } @@ -149,6 +161,7 @@ JSTaggedValue BuiltinsArray::ArrayConstructor(EcmaRuntimeCallInfo *argv) // 11. Assert: the value of array’s length property is numberOfArgs. // 12. Return array. JSArray::Cast(*newArrayHandle)->SetArrayLength(thread, argc); + CheckAndSetPrototypeModified(thread, newArrayHandle); return newArrayHandle.GetTaggedValue(); } @@ -505,6 +518,7 @@ JSTaggedValue BuiltinsArray::Concat(EcmaRuntimeCallInfo *argv) JSMutableHandle ele(thread, JSTaggedValue::Undefined()); JSMutableHandle fromKey(thread, JSTaggedValue::Undefined()); JSMutableHandle toKey(thread, JSTaggedValue::Undefined()); + JSMutableHandle valHandle(thread, JSTaggedValue::Undefined()); // 4. Prepend O to items. // 5. For each element E of items, do for (int i = -1; i < argc; i++) { @@ -532,6 +546,14 @@ JSTaggedValue BuiltinsArray::Concat(EcmaRuntimeCallInfo *argv) JSStableArray::Concat(thread, newArrayHandle, JSHandle::Cast(ele), k, n); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } + #if ENABLE_NEXT_OPTIMIZATION + else if (JSArray::IsProtoNotModifiedDictionaryJSArray(thread, JSHandle::Cast(ele))) { + JSArray::FastConcatDictionaryArray(thread, JSHandle::Cast(ele), newArrayHandle, + valHandle, toKey, n); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + continue; + } + #endif // iv. Repeat, while k < len, while (k < len) { // 1. Let P be ToString(k). @@ -869,12 +891,16 @@ JSTaggedValue BuiltinsArray::Fill(EcmaRuntimeCallInfo *argv) } else { end = argEnd < len ? argEnd : len; } + + if (start < end) { + thread->NotifyArrayPrototypeChangedGuardians(thisObjHandle); + } + // 11. Repeat, while k < final // a. Let Pk be ToString(k). // b. Let setStatus be Set(O, Pk, value, true). // c. ReturnIfAbrupt(setStatus). // d. Increase k by 1. - if (thisObjVal->IsStableJSArray(thread) && !startArg->IsJSObject() && !endArg->IsJSObject()) { return JSStableArray::Fill(thread, thisObjHandle, value, start, end, len); } @@ -1651,26 +1677,29 @@ JSTaggedValue BuiltinsArray::Push(EcmaRuntimeCallInfo *argv) JSHandle thisHandle = GetThis(argv); // 1. Let O be ToObject(this value). JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + // 2. Let argCount be the number of elements in items. + uint32_t argc = argv->GetArgsNumber(); + if (argc > 0) { + thread->NotifyArrayPrototypeChangedGuardians(thisObjHandle); + } if (thisHandle->IsStableJSArray(thread) && JSObject::IsArrayLengthWritable(thread, thisObjHandle)) { return JSStableArray::Push(JSHandle::Cast(thisHandle), argv); } - // 6. Let argCount be the number of elements in items. - uint32_t argc = argv->GetArgsNumber(); - - // 2. ReturnIfAbrupt(O). + // 3. ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle thisObjVal(thisObjHandle); - // 3. Let len be ToLength(Get(O, "length")). + // 4. Let len be ToLength(Get(O, "length")). int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); - // 4. ReturnIfAbrupt(len). + // 5. ReturnIfAbrupt(len). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - // 7. If len + argCount > 253-1, throw a TypeError exception. + // 6. If len + argCount > 253-1, throw a TypeError exception. if ((len + static_cast(argc)) > base::MAX_SAFE_INTEGER) { THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); } - // 8. Repeat, while items is not empty + // 7. Repeat, while items is not empty // a. Remove the first element from items and let E be the value of the element. // b. Let setStatus be Set(O, ToString(len), E, true). // c. ReturnIfAbrupt(setStatus). @@ -1686,14 +1715,14 @@ JSTaggedValue BuiltinsArray::Push(EcmaRuntimeCallInfo *argv) len++; } - // 9. Let setStatus be Set(O, "length", len, true). + // 8. Let setStatus be Set(O, "length", len, true). JSHandle lengthKey = thread->GlobalConstants()->GetHandledLengthString(); key.Update(JSTaggedValue(len)); JSTaggedValue::SetProperty(thread, thisObjVal, lengthKey, key, true); - // 10. ReturnIfAbrupt(setStatus). + // 9. ReturnIfAbrupt(setStatus). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - // 11. Return len. + // 10. Return len. return GetTaggedDouble(len); } @@ -2374,12 +2403,20 @@ JSTaggedValue BuiltinsArray::Sort(EcmaRuntimeCallInfo *argv) RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // Array sort +#if ENABLE_NEXT_OPTIMIZATION + if (thisHandle->IsStableJSArray(thread)) { + JSStableArray::Sort(thread, thisHandle, callbackFnHandle); + } else { + JSArray::Sort(thread, JSHandle::Cast(thisObjHandle), callbackFnHandle); + } +#else if (thisHandle->IsStableJSArray(thread) && callbackFnHandle->IsUndefined()) { - JSStableArray::Sort(thread, thisObjHandle, callbackFnHandle); + JSArray::SortElementsByObject(thread, thisObjHandle, callbackFnHandle); } else { JSArray::Sort(thread, JSHandle::Cast(thisObjHandle), callbackFnHandle); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } +#endif + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return thisObjHandle.GetTaggedValue(); } @@ -2436,6 +2473,7 @@ JSTaggedValue BuiltinsArray::Splice(EcmaRuntimeCallInfo *argv) // c. ReturnIfAbrupt(dc). // d. Let actualDeleteCount be min(max(dc,0), len – actualStart). if (argc > 1) { + thread->NotifyArrayPrototypeChangedGuardians(thisObjHandle); insertCount = argc - 2; // 2:2 means there are two arguments before the insert items. JSHandle msg1 = GetCallArg(argv, 1); JSTaggedNumber argDeleteCount = JSTaggedValue::ToInteger(thread, msg1); @@ -2720,7 +2758,6 @@ JSTaggedValue BuiltinsArray::ToString(EcmaRuntimeCallInfo *argv) JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisObjVal, undefined, 0); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return JSFunction::Call(info); } @@ -2734,19 +2771,16 @@ JSTaggedValue BuiltinsArray::Unshift(EcmaRuntimeCallInfo *argv) // 5. Let argCount be the number of actual arguments. int64_t argc = argv->GetArgsNumber(); - // 1. Let O be ToObject(this value). JSHandle thisHandle = GetThis(argv); JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); // 2. ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle thisObjVal(thisObjHandle); - // 3. Let len be ToLength(Get(O, "length")). int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); // 4. ReturnIfAbrupt(len). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - // 6. If argCount > 0, then // a. If len+ argCount > 253-1, throw a TypeError exception. // b. Let k be len. @@ -2768,6 +2802,7 @@ JSTaggedValue BuiltinsArray::Unshift(EcmaRuntimeCallInfo *argv) if (len + argc > base::MAX_SAFE_INTEGER) { THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); } + thread->NotifyArrayPrototypeChangedGuardians(thisObjHandle); JSMutableHandle fromKey(thread, JSTaggedValue::Undefined()); JSMutableHandle toKey(thread, JSTaggedValue::Undefined()); int64_t k = len; diff --git a/ecmascript/builtins/builtins_array.h b/ecmascript/builtins/builtins_array.h index 42bc99362b99a947da5af3e9354e3bd112ad34c5..ef58d18d6f7904583d9c112b16dcc861727377d7 100644 --- a/ecmascript/builtins/builtins_array.h +++ b/ecmascript/builtins/builtins_array.h @@ -253,7 +253,6 @@ private: BUILTIN_ARRAY_PROTOTYPE_FUNCTIONS(BUILTIN_ARRAY_FUNCTION_ENTRY) }; #undef BUILTIN_ARRAY_FUNCTION_ENTRY - static JSTaggedValue IndexOfStable( EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle &thisHandle); static JSTaggedValue IndexOfSlowPath( diff --git a/ecmascript/builtins/builtins_async_from_sync_iterator.cpp b/ecmascript/builtins/builtins_async_from_sync_iterator.cpp index 3fb6a992fdc69690a2604452caeb00c3f5959593..633fba4ae9964a97850b6b4f4ab5bf3646d707ba 100644 --- a/ecmascript/builtins/builtins_async_from_sync_iterator.cpp +++ b/ecmascript/builtins/builtins_async_from_sync_iterator.cpp @@ -90,6 +90,7 @@ JSTaggedValue BuiltinsAsyncFromSyncIterator::Throw(EcmaRuntimeCallInfo *argv) JSHandle reject(thread, pcap->GetReject()); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefinedValue, undefinedValue, 1); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); info->SetCallArg(iterResult.GetTaggedValue()); return pcap->GetPromise(); } @@ -98,7 +99,6 @@ JSTaggedValue BuiltinsAsyncFromSyncIterator::Throw(EcmaRuntimeCallInfo *argv) if (value->IsNull()) { EcmaRuntimeCallInfo *callInfo = EcmaInterpreter::NewRuntimeCallInfo(thread, throwResult, syncIterator, undefinedValue, 0); - RETURN_REJECT_PROMISE_IF_ABRUPT(thread, throwResult, pcap); ret = JSFunction::Call(callInfo); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } else { @@ -119,6 +119,7 @@ JSTaggedValue BuiltinsAsyncFromSyncIterator::Throw(EcmaRuntimeCallInfo *argv) JSHandle reject(thread, pcap->GetReject()); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefinedValue, undefinedValue, 1); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); info->SetCallArg(resolutionError.GetTaggedValue()); JSFunction::Call(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -167,6 +168,7 @@ JSTaggedValue BuiltinsAsyncFromSyncIterator::Return(EcmaRuntimeCallInfo *argv) JSHandle resolve(thread, pcap->GetResolve()); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, resolve, undefinedValue, undefinedValue, 1); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); info->SetCallArg(its.GetTaggedValue()); JSHandle promise(thread, pcap->GetPromise()); return promise.GetTaggedValue(); @@ -176,7 +178,6 @@ JSTaggedValue BuiltinsAsyncFromSyncIterator::Return(EcmaRuntimeCallInfo *argv) if (value->IsNull()) { EcmaRuntimeCallInfo *callInfo = EcmaInterpreter::NewRuntimeCallInfo(thread, returnResult, syncIterator, undefinedValue, 0); - RETURN_REJECT_PROMISE_IF_ABRUPT(thread, returnResult, pcap); ret = JSFunction::Call(callInfo); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } else { @@ -197,6 +198,7 @@ JSTaggedValue BuiltinsAsyncFromSyncIterator::Return(EcmaRuntimeCallInfo *argv) JSHandle reject(thread, pcap->GetReject()); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefinedValue, undefinedValue, 1); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); info->SetCallArg(rstErr.GetTaggedValue()); JSFunction::Call(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); diff --git a/ecmascript/builtins/builtins_dataview.cpp b/ecmascript/builtins/builtins_dataview.cpp index 103b6f850280c39168a1f4d71d385cb2c281e650..a2376e822e995333b2400520ca5b882de9578b5e 100644 --- a/ecmascript/builtins/builtins_dataview.cpp +++ b/ecmascript/builtins/builtins_dataview.cpp @@ -42,30 +42,25 @@ JSTaggedValue BuiltinsDataView::DataViewConstructor(EcmaRuntimeCallInfo *argv) THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is not ArrayBuffer", JSTaggedValue::Exception()); } JSHandle offsetHandle = GetCallArg(argv, 1); - // 4. Let numberOffset be ToNumber(byteOffset). - JSTaggedNumber offsetNumber = JSTaggedValue::ToNumber(thread, offsetHandle); + // 4. Let numberOffset be ToIndex(byteOffset). + JSTaggedNumber offsetNumber = JSTaggedValue::ToIndex(thread, offsetHandle); // 6. ReturnIfAbrupt(offset). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - int32_t offsetInt = base::NumberHelper::DoubleInRangeInt32(offsetNumber.GetNumber()); - // 7. If numberOffset ≠ offset or offset < 0, throw a RangeError exception. - if (offsetInt < 0) { - THROW_RANGE_ERROR_AND_RETURN(thread, "Offset out of range", JSTaggedValue::Exception()); - } - uint32_t offset = static_cast(offsetInt); - // 8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. + uint64_t offset = base::NumberHelper::DoubleToUInt64(offsetNumber.GetNumber()); + // 7. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. if (BuiltinsArrayBuffer::IsDetachedBuffer(bufferHandle.GetTaggedValue())) { THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is Detached Buffer", JSTaggedValue::Exception()); } - // 9. Let bufferByteLength be the value of buffer’s [[ArrayBufferByteLength]] internal slot. + // 8. Let bufferByteLength be the value of buffer’s [[ArrayBufferByteLength]] internal slot. JSHandle arrBufHandle(bufferHandle); uint32_t bufByteLen = arrBufHandle->GetArrayBufferByteLength(); - // 10. If offset > bufferByteLength, throw a RangeError exception. + // 9. If offset > bufferByteLength, throw a RangeError exception. if (offset > bufByteLen) { THROW_RANGE_ERROR_AND_RETURN(thread, "offset > bufferByteLength", JSTaggedValue::Exception()); } - uint32_t viewByteLen = 0; + uint64_t viewByteLen = 0; JSHandle byteLenHandle = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); - // 11. If byteLength is undefined, then Let viewByteLength be bufferByteLength – offset. + // 10. If byteLength is undefined, then Let viewByteLength be bufferByteLength – offset. if (byteLenHandle->IsUndefined()) { viewByteLen = bufByteLen - offset; } else { @@ -73,28 +68,28 @@ JSTaggedValue BuiltinsDataView::DataViewConstructor(EcmaRuntimeCallInfo *argv) JSTaggedNumber byteLen = JSTaggedValue::ToIndex(thread, byteLenHandle); // ReturnIfAbrupt(viewByteLength). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - viewByteLen = static_cast(byteLen.ToInt32()); + viewByteLen = base::NumberHelper::DoubleToUInt64(byteLen.GetNumber()); // If offset+viewByteLength > bufferByteLength, throw a RangeError exception. if (offset + viewByteLen > bufByteLen) { THROW_RANGE_ERROR_AND_RETURN(thread, "offset + viewByteLen > bufByteLen", JSTaggedValue::Exception()); } } - // 13. Let O be OrdinaryCreateFromConstructor OrdinaryCreateFromConstructor(NewTarget, "%DataViewPrototype%", + // 11. Let O be OrdinaryCreateFromConstructor OrdinaryCreateFromConstructor(NewTarget, "%DataViewPrototype%", // «[[DataView]],[[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]]» ). ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle obj = factory->NewJSObjectByConstructor(JSHandle(ctor), newTarget); - // 14. ReturnIfAbrupt(O). + // 12. ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle dataView(obj); - // 15. Set O’s [[DataView]] internal slot to true. + // 13. Set O’s [[DataView]] internal slot to true. dataView->SetDataView(thread, JSTaggedValue::True()); - // 16. Set O’s [[ViewedArrayBuffer]] internal slot to buffer. + // 14. Set O’s [[ViewedArrayBuffer]] internal slot to buffer. dataView->SetViewedArrayBuffer(thread, bufferHandle.GetTaggedValue()); - // 17. Set O’s [[ByteLength]] internal slot to viewByteLength. - dataView->SetByteLength(viewByteLen); - // 18. Set O’s [[ByteOffset]] internal slot to offset. - dataView->SetByteOffset(offset); - // 19. Return O. + // 15. Set O’s [[ByteLength]] internal slot to viewByteLength. + dataView->SetByteLength(static_cast(viewByteLen)); + // 16. Set O’s [[ByteOffset]] internal slot to offset. + dataView->SetByteOffset(static_cast(offset)); + // 17. Return O. return JSTaggedValue(dataView.GetTaggedValue()); } @@ -355,22 +350,21 @@ JSTaggedValue BuiltinsDataView::GetViewValue(JSThread *thread, const JSHandleIsInt()) { // fast get index if requestIndex is int - indexInt = requestIndex->GetInt(); + auto indexInt = requestIndex->GetInt(); + if (indexInt < 0) { + THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex < 0", JSTaggedValue::Exception()); + } + index = static_cast(indexInt); } else { - // 3. Let numberIndex be ToNumber(requestIndex). - JSTaggedNumber numberIndex = JSTaggedValue::ToNumber(thread, requestIndex); + // 3. Let numberIndex be ToIndex(requestIndex). + JSTaggedNumber numberIndex = JSTaggedValue::ToIndex(thread, requestIndex); // 5. ReturnIfAbrupt(getIndex). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - indexInt = base::NumberHelper::DoubleInRangeInt32(numberIndex.GetNumber()); + index = base::NumberHelper::DoubleToUInt64(numberIndex.GetNumber()); } - // 6. If numberIndex ≠ getIndex or getIndex < 0, throw a RangeError exception. - if (indexInt < 0) { - THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex < 0", JSTaggedValue::Exception()); - } - uint32_t index = static_cast(indexInt); // 7. Let isLittleEndian be ToBoolean(isLittleEndian). bool isLittleEndian = false; if (littleEndian->IsUndefined()) { @@ -396,7 +390,7 @@ JSTaggedValue BuiltinsDataView::GetViewValue(JSThread *thread, const JSHandle viewSize", JSTaggedValue::Exception()); } // 14. Let bufferIndex be getIndex + viewOffset. - uint32_t bufferIndex = index + offset; + uint32_t bufferIndex = static_cast(index + offset); // 15. Return GetValueFromBuffer(buffer, bufferIndex, type, isLittleEndian). return BuiltinsArrayBuffer::GetValueFromBuffer(thread, buffer, bufferIndex, type, isLittleEndian); } @@ -416,20 +410,21 @@ JSTaggedValue BuiltinsDataView::SetViewValue(JSThread *thread, const JSHandleIsDataView()) { THROW_TYPE_ERROR_AND_RETURN(thread, "view is not dataview", JSTaggedValue::Exception()); } - int64_t index = 0; + uint64_t index = 0; if (requestIndex->IsInt()) { // fast get index if requestIndex is int - index = requestIndex->GetInt(); + auto indexInt = requestIndex->GetInt(); + // If numberIndex ≠ getIndex or getIndex < 0, throw a RangeError exception. + if (indexInt < 0) { + THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex < 0", JSTaggedValue::Exception()); + } + index = static_cast(indexInt); } else { // 3. Let numberIndex be ToNumber(requestIndex). JSTaggedNumber numberIndex = JSTaggedValue::ToIndex(thread, requestIndex); // 5. ReturnIfAbrupt(getIndex). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - index = base::NumberHelper::DoubleInRangeInt32(numberIndex.GetNumber()); - } - // 6. If numberIndex ≠ getIndex or getIndex < 0, throw a RangeError exception. - if (index < 0) { - THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex < 0", JSTaggedValue::Exception()); + index = base::NumberHelper::DoubleToUInt64(numberIndex.GetNumber()); } JSMutableHandle numValueHandle = JSMutableHandle(thread, value); if (!value->IsNumber()) { @@ -457,11 +452,11 @@ JSTaggedValue BuiltinsDataView::SetViewValue(JSThread *thread, const JSHandle viewSize, throw a RangeError exception. - if (static_cast(index) + elementSize > size) { + if (index + elementSize > size) { THROW_RANGE_ERROR_AND_RETURN(thread, "getIndex +elementSize > viewSize", JSTaggedValue::Exception()); } // 14. Let bufferIndex be getIndex + viewOffset. - uint32_t bufferIndex = static_cast(index) + offset; + uint32_t bufferIndex = static_cast(index + offset); // 15. Return SetValueFromBuffer(buffer, bufferIndex, type, value, isLittleEndian). return BuiltinsArrayBuffer::SetValueInBuffer(thread, buffer, bufferIndex, type, numValueHandle, isLittleEndian); } diff --git a/ecmascript/builtins/builtins_date.cpp b/ecmascript/builtins/builtins_date.cpp index f2a7f53cebe3bc66a2c451967480115c1642cb12..3aea902e35dbd1a4b60fa1f1f80dcce358028ec5 100644 --- a/ecmascript/builtins/builtins_date.cpp +++ b/ecmascript/builtins/builtins_date.cpp @@ -39,7 +39,7 @@ JSTaggedValue BuiltinsDate::DateConstructor(EcmaRuntimeCallInfo *argv) JSHandle newTarget = GetNewTarget(argv); if (newTarget->IsUndefined()) { double now = JSDate::Now().GetDouble(); - CString str = JSDate::ToDateString(now); + CString str = JSDate::ToDateString(thread, now); return GetTaggedString(thread, str.c_str()); } diff --git a/ecmascript/builtins/builtins_gc.cpp b/ecmascript/builtins/builtins_gc.cpp index 995067e8ba44bb49b0d7f6a6f11632b2939843be..2af7453e935dd85dfe2814a8e46d9be20669000c 100644 --- a/ecmascript/builtins/builtins_gc.cpp +++ b/ecmascript/builtins/builtins_gc.cpp @@ -194,7 +194,7 @@ JSTaggedValue BuiltinsGc::AllocateArrayObject(EcmaRuntimeCallInfo *info) sizeInBytes = 0; } - uint32_t numElements = sizeInBytes / sizeof(TaggedType); + uint32_t numElements = static_cast(sizeInBytes / sizeof(TaggedType)); auto array = factory->NewJSArray(); if (numElements > 0) { diff --git a/ecmascript/builtins/builtins_global.cpp b/ecmascript/builtins/builtins_global.cpp index 94e838601620175b29b2eae3e5ce6e188539140c..55c33e575ac8415e4807e935a7505aa022ad2dc3 100644 --- a/ecmascript/builtins/builtins_global.cpp +++ b/ecmascript/builtins/builtins_global.cpp @@ -369,6 +369,7 @@ EcmaString *BuiltinsGlobal::StringPad(JSThread *thread, const JSHandle stringFiller = vm->GetFactory()->NewFromStdString(std::string("\0")); for (uint32_t k = 0; k < repeatTimes; ++k) { p = EcmaStringAccessor::Concat(vm, stringFiller, fillString); + RETURN_VALUE_IF_ABRUPT(thread, *vm->GetFactory()->GetEmptyString()); stringFiller = JSHandle(thread, p); } JSHandle truncatedStringFiller(thread, diff --git a/ecmascript/builtins/builtins_regexp.cpp b/ecmascript/builtins/builtins_regexp.cpp index b63df51bbcf0af5c63cee909e9be02d38e37c22c..b04a0a938792d2f5735986f7eba6712deae4c768 100644 --- a/ecmascript/builtins/builtins_regexp.cpp +++ b/ecmascript/builtins/builtins_regexp.cpp @@ -15,6 +15,7 @@ #include "ecmascript/builtins/builtins_regexp.h" #include "ecmascript/builtins/builtins_regexp-inl.h" +#include "ecmascript/checkpoint/thread_state_transition.h" #include @@ -52,8 +53,6 @@ JSTaggedValue BuiltinsRegExp::RegExpConstructor(EcmaRuntimeCallInfo *argv) } else { auto ecmaVm = thread->GetEcmaVM(); JSHandle env = ecmaVm->GetGlobalEnv(); - // disable gc - [[maybe_unused]] DisallowGarbageCollection noGc; // 4.a Let newTarget be the active function object. newTarget = env->GetRegExpFunction(); JSHandle constructorString = globalConst->GetHandledConstructorString(); @@ -94,8 +93,6 @@ JSTaggedValue BuiltinsRegExp::RegExpConstructor(EcmaRuntimeCallInfo *argv) } else if (patternIsRegExp) { JSHandle sourceString(globalConst->GetHandledSourceString()); JSHandle flagsString(globalConst->GetHandledFlagsString()); - // disable gc - [[maybe_unused]] DisallowGarbageCollection noGc; // 6.a Let P be Get(pattern, "source"). patternTemp = JSObject::GetProperty(thread, pattern, sourceString).GetValue(); // 6.b ReturnIfAbrupt(P). @@ -159,7 +156,7 @@ JSTaggedValue BuiltinsRegExp::Exec(EcmaRuntimeCallInfo *argv) } bool useCache = true; - bool isFastPath = IsFastRegExp(thread, thisObj); + bool isFastPath = IsFastRegExp(thread, thisObj.GetTaggedValue()); JSHandle cacheTable(thread->GetCurrentEcmaContext()->GetRegExpCache()); if (!isFastPath || cacheTable->GetLargeStrCount() == 0 || cacheTable->GetConflictCount() == 0) { useCache = false; @@ -190,7 +187,7 @@ JSTaggedValue BuiltinsRegExp::Test(EcmaRuntimeCallInfo *argv) RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle string = JSHandle::Cast(stringHandle); // test fast path - if (IsFastRegExp(thread, thisObj)) { + if (IsFastRegExp(thread, thisObj.GetTaggedValue())) { return RegExpTestFast(thread, thisObj, string, true); } @@ -202,19 +199,20 @@ JSTaggedValue BuiltinsRegExp::Test(EcmaRuntimeCallInfo *argv) return GetTaggedBoolean(!matchResult.IsNull()); } -bool BuiltinsRegExp::IsFastRegExp(JSThread *thread, JSHandle regexp, +bool BuiltinsRegExp::IsFastRegExp(JSThread *thread, JSTaggedValue regexp, RegExpSymbol symbolTag) { + DISALLOW_GARBAGE_COLLECTION; JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); - JSHClass *hclass = JSHandle::Cast(regexp)->GetJSHClass(); + JSHClass *hclass = JSObject::Cast(regexp)->GetJSHClass(); JSHClass *originHClass = JSHClass::Cast(globalConst->GetJSRegExpClass().GetTaggedObject()); // regexp instance hclass if (hclass != originHClass) { return false; } // lastIndex type is Int - JSTaggedValue lastIndex = JSHandle::Cast(regexp)->GetPropertyInlinedProps(LAST_INDEX_OFFSET); + JSTaggedValue lastIndex = JSObject::Cast(regexp)->GetPropertyInlinedProps(LAST_INDEX_OFFSET); if (!lastIndex.IsInt() || lastIndex.GetInt() < 0) { return false; } @@ -329,7 +327,7 @@ JSTaggedValue BuiltinsRegExp::ToString(EcmaRuntimeCallInfo *argv) JSMutableHandle getFlags(thread, JSTaggedValue::Undefined()); JSHandle sourceStrHandle; JSHandle flagsStrHandle; - if (IsFastRegExp(thread, thisObj)) { + if (IsFastRegExp(thread, thisObj.GetTaggedValue())) { JSHandle regexp(thread, JSRegExp::Cast(thisObj->GetTaggedObject())); // 3. Let pattern be ToString(Get(R, "source")). getSource.Update(regexp->GetOriginalSource()); @@ -373,7 +371,7 @@ JSTaggedValue BuiltinsRegExp::GetFlags(EcmaRuntimeCallInfo *argv) } // 3. Let result be the empty String. // 4. ~ 19. - if (!IsFastRegExp(thread, thisObj)) { + if (!IsFastRegExp(thread, thisObj.GetTaggedValue())) { return GetAllFlagsInternal(thread, thisObj); } uint8_t flagsBits = static_cast(JSRegExp::Cast(thisObj->GetTaggedObject())->GetOriginalFlags().GetInt()); @@ -602,7 +600,7 @@ JSTaggedValue BuiltinsRegExp::Match(EcmaRuntimeCallInfo *argv) // 2. If Type(rx) is not Object, throw a TypeError exception. THROW_TYPE_ERROR_AND_RETURN(thread, "this is not Object", JSTaggedValue::Exception()); } - bool isFastPath = IsFastRegExp(thread, thisObj); + bool isFastPath = IsFastRegExp(thread, thisObj.GetTaggedValue()); return RegExpMatch(thread, thisObj, string, isFastPath); } @@ -750,7 +748,7 @@ JSTaggedValue BuiltinsRegExp::MatchAll(EcmaRuntimeCallInfo *argv) JSHandle inputString = GetCallArg(argv, 0); JSHandle stringHandle = JSTaggedValue::ToString(thread, inputString); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - bool isFastPath = IsFastRegExp(thread, thisObj); + bool isFastPath = IsFastRegExp(thread, thisObj.GetTaggedValue()); return RegExpMatchAll(thread, thisObj, stringHandle, isFastPath); } @@ -1021,7 +1019,7 @@ JSTaggedValue BuiltinsRegExp::ReplaceInternal(JSThread *thread, ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); bool isGlobal = false; bool fullUnicode = false; - bool isFastPath = IsFastRegExp(thread, thisObj); + bool isFastPath = IsFastRegExp(thread, thisObj.GetTaggedValue()); if (isFastPath) { isGlobal = GetOriginalFlag(thread, thisObj, RegExpParser::FLAG_GLOBAL); fullUnicode = GetOriginalFlag(thread, thisObj, RegExpParser::FLAG_UTF16); @@ -1153,8 +1151,9 @@ JSTaggedValue BuiltinsRegExp::ReplaceInternal(JSThread *thread, bool isUtf8 = true; uint32_t resultStrLength = 0; uint32_t resultArrayLength = (static_cast(resultsIndex) + 1) * 2; - JSHandle resultArray = factory->NewTaggedArray(resultArrayLength); + CVector> resultArray(resultArrayLength, globalConst->GetHandledHole()); std::vector resultLengthArray(resultArrayLength); + CVector> capturesList; // 15. Let nextSourcePosition be 0. uint32_t nextSourcePosition = 0; JSMutableHandle getMatchString(thread, JSTaggedValue::Undefined()); @@ -1202,14 +1201,12 @@ JSTaggedValue BuiltinsRegExp::ReplaceInternal(JSThread *thread, } // i. Let position be max(min(position, lengthS), 0). position = std::max(std::min(position, length), 0); - // j. Let n be 1. - uint32_t index = 1; - // k. Let captures be an empty List. - JSHandle capturesList = factory->NewTaggedArray(ncaptures); - // l. Repeat while n ≤ nCaptures - while (index <= ncaptures) { + // j. Let captures be an empty List. + capturesList.resize(ncaptures); + // l. Repeat while n < nCaptures + for (uint32_t index = 0; index < ncaptures; index++) { // i. Let capN be Get(result, ToString(n)). - capN.Update(ObjectFastOperator::FastGetPropertyByIndex(thread, resultValues.GetTaggedValue(), index)); + capN.Update(ObjectFastOperator::FastGetPropertyByIndex(thread, resultValues.GetTaggedValue(), index + 1)); // ii. ReturnIfAbrupt(capN). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // iii. If capN is not undefined, then @@ -1218,16 +1215,12 @@ JSTaggedValue BuiltinsRegExp::ReplaceInternal(JSThread *thread, JSHandle capNStr = JSTaggedValue::ToString(thread, capN); // 2. ReturnIfAbrupt(capN). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle capnStr = JSHandle::Cast(capNStr); - capturesList->Set(thread, index - 1, capnStr); + capturesList[index] = JSHandle(thread, capNStr.GetTaggedValue()); } else { // iv. Append capN as the last element of captures. - capturesList->Set(thread, index - 1, capN); + capturesList[index] = JSHandle(thread, capN.GetTaggedValue()); } - // v. Let n be n+1 - ++index; } - // j. Let namedCaptures be ? Get(result, "groups"). JSTaggedValue named = GetExecResultGroups(thread, resultValues, isFastPath); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -1240,29 +1233,26 @@ JSTaggedValue BuiltinsRegExp::ReplaceInternal(JSThread *thread, } else { emptyArrLength = 4; // 4: «matched, pos, string, and groups» } - JSHandle replacerArgs = - factory->NewTaggedArray(emptyArrLength + capturesList->GetLength()); if (functionalReplace) { + // Let replValue be Call(replaceValue, undefined, replacerArgs). + EcmaRuntimeCallInfo *info = + EcmaInterpreter::NewRuntimeCallInfo(thread, + inputReplaceValue, undefined, undefined, emptyArrLength + ncaptures); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + // i. Let replacerArgs be «matched». - replacerArgs->Set(thread, 0, getMatchString.GetTaggedValue()); + info->SetCallArg(0, getMatchString.GetTaggedValue()); // ii. Append in list order the elements of captures to the end of the List replacerArgs. - // iii. Append position and S as the last two elements of replacerArgs. - index = 0; - while (index < capturesList->GetLength()) { - replacerArgs->Set(thread, index + 1, capturesList->Get(index)); - ++index; + for (uint32_t index = 0; index < ncaptures; index++) { + info->SetCallArg(index + 1, capturesList[index].GetTaggedValue()); } - replacerArgs->Set(thread, index + 1, JSTaggedValue(position)); - replacerArgs->Set(thread, index + 2, inputStr.GetTaggedValue()); // 2: position of string + // iii. Append position and S as the last two elements of replacerArgs. + info->SetCallArg(ncaptures + EXEC_RESULT_INDEX_OFFSET, JSTaggedValue(position)); + info->SetCallArg(ncaptures + EXEC_RESULT_INPUT_OFFSET, inputStr.GetTaggedValue()); if (!namedCaptures->IsUndefined()) { - replacerArgs->Set(thread, index + 3, namedCaptures.GetTaggedValue()); // 3: position of groups + // iv. position of groups + info->SetCallArg(ncaptures + EXEC_RESULT_GROUPS_OFFSET, namedCaptures.GetTaggedValue()); } - // iv. Let replValue be Call(replaceValue, undefined, replacerArgs). - const uint32_t argsLength = replacerArgs->GetLength(); - EcmaRuntimeCallInfo *info = - EcmaInterpreter::NewRuntimeCallInfo(thread, inputReplaceValue, undefined, undefined, argsLength); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - info->SetCallArg(argsLength, replacerArgs); JSTaggedValue replaceResult = JSFunction::Call(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle replValue(thread, replaceResult); @@ -1272,32 +1262,37 @@ JSTaggedValue BuiltinsRegExp::ReplaceInternal(JSThread *thread, RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } else { // n. Else, + JSHandle capturesArray = factory->NewTaggedArray(ncaptures); if (!namedCaptures->IsUndefined()) { JSHandle namedCapturesObj = JSTaggedValue::ToObject(thread, namedCaptures); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); namedCaptures = JSHandle::Cast(namedCapturesObj); } + for (uint32_t index = 0; index < ncaptures; index++) { + capturesArray->Set(thread, index, capturesList[index]); + } replacementString.Update(BuiltinsString::GetSubstitution(thread, matchString, srcString, - position, capturesList, namedCaptures, replaceValueHandle)); + position, capturesArray, namedCaptures, replaceValueHandle)); } // p. If position ≥ nextSourcePosition, then if (position >= nextSourcePosition) { + ASSERT(REPLACE_RESULT_VAL * i + 1 < resultArray.size()); // ii. Let accumulatedResult be the String formed by concatenating the code units of the current value // of accumulatedResult with the substring of S consisting of the code units from nextSourcePosition // (inclusive) up to position (exclusive) and with the code units of replacement. // store undefined in resultArray - resultArray->Set(thread, REPLACE_RESULT_VAL * i, JSTaggedValue::Undefined()); + resultArray[REPLACE_RESULT_VAL * i] = globalConst->GetHandledUndefined(); uint64_t bits = 0; bits |= ReplaceLengthField::Encode(position - nextSourcePosition); bits |= ReplacePositionField::Encode(nextSourcePosition); // store position and length bits in resultLengthArray resultLengthArray[REPLACE_RESULT_VAL * i] = bits; resultStrLength += (position - nextSourcePosition); - auto subString = EcmaStringAccessor::FastSubString( + isUtf8 &= EcmaStringAccessor::SubStringIsUtf8( thread->GetEcmaVM(), srcString, nextSourcePosition, position - nextSourcePosition); - isUtf8 &= EcmaStringAccessor(subString).IsUtf8(); // store replacement string in resultArray - resultArray->Set(thread, REPLACE_RESULT_VAL * i + 1, replacementString.GetTaggedValue()); + resultArray[REPLACE_RESULT_VAL * i + 1] = + JSHandle(thread, replacementString.GetTaggedValue()); uint32_t replacementLength = EcmaStringAccessor(replacementString).GetLength(); // store length of replacement string in resultLengthArray resultLengthArray[REPLACE_RESULT_VAL * i + 1] = static_cast(replacementLength); @@ -1311,13 +1306,12 @@ JSTaggedValue BuiltinsRegExp::ReplaceInternal(JSThread *thread, // 17. If nextSourcePosition ≥ lengthS, return accumulatedResult. if (nextSourcePosition < length) { // store undefined in resultArray - resultArray->Set(thread, REPLACE_RESULT_VAL * resultsIndex, JSTaggedValue::Undefined()); + resultArray[REPLACE_RESULT_VAL * resultsIndex] = globalConst->GetHandledUndefined(); uint64_t bits = 0; bits |= ReplaceLengthField::Encode(length - nextSourcePosition); bits |= ReplacePositionField::Encode(nextSourcePosition); - auto subStringEnd = EcmaStringAccessor::FastSubString( + isUtf8 &= EcmaStringAccessor::SubStringIsUtf8( thread->GetEcmaVM(), srcString, nextSourcePosition, length - nextSourcePosition); - isUtf8 &= EcmaStringAccessor(subStringEnd).IsUtf8(); // store position and length bits in resultLengthArray resultLengthArray[REPLACE_RESULT_VAL * resultsIndex] = bits; resultStrLength += (length - nextSourcePosition); @@ -1362,7 +1356,7 @@ JSTaggedValue BuiltinsRegExp::RegExpSearch(JSThread *thread, const JSHandle regexp, const JSHandle string) { - bool isFastPath = IsFastRegExp(thread, regexp); + bool isFastPath = IsFastRegExp(thread, regexp.GetTaggedValue()); if (isFastPath) { return RegExpSearchFast(thread, regexp, string); } @@ -1652,7 +1646,7 @@ JSTaggedValue BuiltinsRegExp::Split(EcmaRuntimeCallInfo *argv) // 2. If Type(rx) is not Object, throw a TypeError exception. THROW_TYPE_ERROR_AND_RETURN(thread, "this is not Object", JSTaggedValue::Exception()); } - bool isFastPath = IsFastRegExp(thread, thisObj); + bool isFastPath = IsFastRegExp(thread, thisObj.GetTaggedValue()); return RegExpSplit(thread, thisObj, jsString, limit, isFastPath); } @@ -1806,7 +1800,23 @@ bool BuiltinsRegExp::RegExpExecInternal(JSThread *thread, const JSHandleGetTaggedObject())->GetOriginalSource(); + uint32_t regexpLength = EcmaStringAccessor(regexpSource).GetLength(); + if (UNLIKELY(regexpLength > MIN_REGEXP_PATTERN_LENGTH_EXECUTE_WITH_OFFHEAP_STRING && stringLength > 0)) { + size_t utf8Len = LineEcmaString::DataSize(flatStrInfo.GetString()); + ASSERT(utf8Len > 0); + uint8_t *offHeapString = new uint8_t[utf8Len]; + if (memcpy_s(offHeapString, utf8Len, strBuffer, utf8Len) != EOK) { + LOG_FULL(FATAL) << "memcpy_s failed"; + UNREACHABLE(); + } + isSuccess = Matcher(thread, regexp, offHeapString, stringLength, lastIndex, isUtf16, + StringSource::OFFHEAP_STRING); + delete[] offHeapString; + } else { + isSuccess = Matcher(thread, regexp, strBuffer, stringLength, lastIndex, isUtf16, StringSource::ONHEAP_STRING); + } if (isSuccess) { JSHandle globalTable(thread->GetCurrentEcmaContext()->GetRegExpGlobalResult()); globalTable->ResetDollar(thread); @@ -1818,7 +1828,7 @@ bool BuiltinsRegExp::RegExpExecInternal(JSThread *thread, const JSHandle regexp, const uint8_t *buffer, size_t length, int32_t lastIndex, - bool isUtf16) + bool isUtf16, StringSource source) { BUILTINS_API_TRACE(thread, RegExp, Matcher); // get bytecode @@ -1831,7 +1841,16 @@ bool BuiltinsRegExp::Matcher(JSThread *thread, const JSHandle reg if (lastIndex < 0) { lastIndex = 0; } - bool ret = executor.Execute(buffer, lastIndex, static_cast(length), bytecodeBuffer, isUtf16); + bool ret = false; + if (UNLIKELY(source == StringSource::OFFHEAP_STRING)) { +#ifndef NDEBUG + SharedHeap::GetInstance()->PostGCTaskForTest(thread); +#endif + ThreadNativeScope scope(thread); + ret = executor.Execute(buffer, lastIndex, static_cast(length), bytecodeBuffer, isUtf16); + } else { + ret = executor.Execute(buffer, lastIndex, static_cast(length), bytecodeBuffer, isUtf16); + } if (ret) { executor.GetResult(thread); } @@ -1998,9 +2017,9 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle JSHandle inputString = JSHandle::Cast(inputStr); JSHandle globalTable(thread->GetCurrentEcmaContext()->GetRegExpGlobalResult()); uint32_t capturesSize = static_cast(globalTable->GetTotalCaptureCounts().GetInt()); - JSHandle results(JSArray::ArrayCreate(thread, JSTaggedNumber(capturesSize))); + JSHandle results(JSArray::ArrayCreate(thread, JSTaggedNumber(capturesSize), ArrayMode::LITERAL)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - const GlobalEnvConstants *globalConst = thread->GlobalConstants(); + auto globalConst = thread->GlobalConstants(); JSHandle indexValue(thread, globalTable->GetStartOfCaptureIndex(0)); if (isIntermediateResult) { // inlined intermediate result @@ -2016,36 +2035,24 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle } // 27. Perform CreateDataProperty(A, "0", matched_substr). + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle resultElements = factory->NewTaggedArray(capturesSize); uint32_t startIndex = static_cast(globalTable->GetStartOfCaptureIndex(0).GetInt()); uint32_t len = static_cast(globalTable->GetEndOfCaptureIndex(0).GetInt()) - startIndex; JSHandle zeroValue(thread, JSTaggedValue(EcmaStringAccessor::FastSubString( thread->GetEcmaVM(), inputString, startIndex, len))); - TaggedArray *srcElements = TaggedArray::Cast(results->GetElements().GetTaggedObject()); - JSHandle resultElements(thread, srcElements); resultElements->Set(thread, 0, zeroValue); - - // Let indices be a new empty List. - // Let groupNames be a new empty List. - // Append match to indices. - uint32_t endIndex = globalTable->GetEndIndex().GetInt(); - std::vector> indices; - std::vector> groupNames; - indices.emplace_back(std::make_pair(globalTable->GetStartOfCaptureIndex(0), JSTaggedValue(endIndex))); // If R contains any GroupName, then // a. Let groups be OrdinaryObjectCreate(null). // b. Let hasGroups be true. // Else, // a. Let groups be undefined. // b. Let hasGroups be false. - JSHandle regexpObj(regexp); - JSHandle groupName(thread, regexpObj->GetGroupName()); + JSHandle groupName(thread, JSHandle::Cast(regexp)->GetGroupName()); JSMutableHandle groups(thread, JSTaggedValue::Undefined()); bool hasGroups = false; if (!groupName->IsUndefined()) { - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle nullHandle(thread, JSTaggedValue::Null()); - JSHandle nullObj = factory->OrdinaryNewJSObjectCreate(nullHandle); - groups.Update(nullObj.GetTaggedValue()); + groups.Update(factory->CreateNullJSObject().GetTaggedValue()); hasGroups = true; } if (isIntermediateResult) { @@ -2056,6 +2063,14 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle JSHandle groupsKey = globalConst->GetHandledGroupsString(); JSObject::CreateDataProperty(thread, results, groupsKey, groups); } + // Append match to indices + uint32_t endIndex = globalTable->GetEndIndex().GetInt(); + std::vector> indices; + indices.reserve(capturesSize); + indices.emplace_back(globalTable->GetStartOfCaptureIndex(0), JSTaggedValue(endIndex)); + std::vector> groupNames; + groupNames.reserve(capturesSize); + // Create a new RegExp on global uint32_t captureIndex = 1; JSMutableHandle iValue(thread, JSTaggedValue::Undefined()); @@ -2067,11 +2082,11 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle int32_t subStrLen = captureEndIndex - captureStartIndex; if (subStrLen < 0) { iValue.Update(JSTaggedValue::Undefined()); - indices.emplace_back(std::make_pair(JSTaggedValue::Undefined(), JSTaggedValue::Undefined())); + indices.emplace_back(JSTaggedValue::Undefined(), JSTaggedValue::Undefined()); } else { iValue.Update(JSTaggedValue(EcmaStringAccessor::FastSubString( thread->GetEcmaVM(), inputString, captureStartIndex, subStrLen))); - indices.emplace_back(std::make_pair(captureStartIndex, captureEndIndex)); + indices.emplace_back(JSTaggedValue(captureStartIndex), JSTaggedValue(captureEndIndex)); } // add to RegExp.$i and i must <= 9 if (captureIndex <= REGEXP_GLOBAL_ARRAY_SIZE) { @@ -2081,7 +2096,7 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle resultElements->Set(thread, captureIndex, iValue); if (!groupName->IsUndefined()) { JSHandle groupObject = JSHandle::Cast(groups); - TaggedArray *groupArray = TaggedArray::Cast(regexpObj->GetGroupName().GetTaggedObject()); + TaggedArray *groupArray = TaggedArray::Cast(groupName->GetTaggedObject()); if (groupArray->GetLength() > captureIndex - 1) { JSHandle skey(thread, groupArray->Get(captureIndex - 1)); JSObject::CreateDataProperty(thread, groupObject, skey, iValue); @@ -2093,6 +2108,7 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle groupNames.emplace_back(undefined); } } + results->SetElements(thread, resultElements); // If hasIndices is true, then // a. Let indicesArray be MakeMatchIndicesIndexPairArray(S, indices, groupNames, hasGroups). // b. Perform ! CreateDataPropertyOrThrow(A, "indices", indicesArray). @@ -2431,11 +2447,17 @@ EcmaString *BuiltinsRegExp::EscapeRegExpPattern(JSThread *thread, const JSHandle if (srcStdStr.empty()) { srcStdStr = "(?:)"; } - // "/" -> "\/" - srcStdStr = base::StringHelper::ReplaceAll(srcStdStr, "/", "\\/"); - // "\\" -> "\" - srcStdStr = base::StringHelper::ReplaceAll(srcStdStr, "\\", "\\"); - + bool escapeChar = false; + for (size_t i = 0; i < srcStdStr.size(); i++) { + if (srcStdStr[i] == '\\') { + escapeChar=!escapeChar; + } else if (!escapeChar && srcStdStr[i]=='/') { + srcStdStr.insert(i, "\\"); + i++; + } else { + escapeChar = false; + } + } return *factory->NewFromUtf8(srcStdStr); } @@ -2885,20 +2907,21 @@ JSTaggedValue BuiltinsRegExp::GetExecResultGroups(JSThread *thread, const JSHand } JSHandle BuiltinsRegExp::CreateStringFromResultArray(JSThread *thread, - const JSHandle resultArray, const std::vector &resultLengthArray, + const CVector> &resultArray, + const std::vector &resultLengthArray, JSHandle srcString, uint32_t resultStrLength, bool isUtf8) { JSHandle result = JSHandle(thread, EcmaStringAccessor::CreateLineString(thread->GetEcmaVM(), resultStrLength, isUtf8)); - FlatStringInfo resultInfo = FlatStringInfo(*result, 0, resultStrLength); FlatStringInfo flatStrInfo = EcmaStringAccessor::FlattenAllString(thread->GetEcmaVM(), srcString); if (EcmaStringAccessor(srcString).IsTreeString()) { // use flattenedString as srcString srcString = JSHandle(thread, flatStrInfo.GetString()); } + FlatStringInfo resultInfo = FlatStringInfo(*result, 0, resultStrLength); uint32_t nextPos = 0; - uint32_t resultArrayLength = resultArray->GetLength(); - for (int i = 0; i < static_cast(resultArrayLength); i++) { - JSTaggedValue substrValue = resultArray->Get(thread, i); + uint32_t resultArrayLength = resultArray.size(); + for (uint32_t i = 0; i < resultArrayLength; i++) { + JSTaggedValue substrValue = resultArray[i].GetTaggedValue(); if (substrValue.IsHole()) { continue; } diff --git a/ecmascript/builtins/builtins_regexp.h b/ecmascript/builtins/builtins_regexp.h index 56440f4b8b99b816feb56d9dc51258f8a028aef0..c1c7d79ea9091ab3d037695cf6d8e1b44c12efac 100644 --- a/ecmascript/builtins/builtins_regexp.h +++ b/ecmascript/builtins/builtins_regexp.h @@ -90,7 +90,7 @@ public: JSHandle string, JSHandle inputReplaceValue); static JSTaggedValue GetAllFlagsInternal(JSThread *thread, JSHandle &thisObj); - static bool IsFastRegExp(JSThread *thread, JSHandle regexp, + static bool IsFastRegExp(JSThread *thread, JSTaggedValue regexp, RegExpSymbol symbolTag = RegExpSymbol::UNKNOWN); static bool GetFlag(JSThread *thread, const JSHandle regexp, uint32_t flag, bool isFastPath); static bool GetOriginalFlag(JSThread *thread, const JSHandle regexp, uint32_t flag); @@ -145,6 +145,13 @@ public: V(REPLACE, Replace) private: + // Execution with a huge RegExp pattern may cost much time and block other thread SuspendAll, so copy an + // OffHeap string and pass it to RegExpExecutor, thus we could transition to native before we do this execution. + enum class StringSource { + ONHEAP_STRING, + OFFHEAP_STRING, + }; + static constexpr uint32_t MIN_REGEXP_PATTERN_LENGTH_EXECUTE_WITH_OFFHEAP_STRING = 4000; static constexpr uint32_t MIN_REPLACE_STRING_LENGTH = 1000; static constexpr uint32_t MAX_SPLIT_LIMIT = 0xFFFFFFFFu; static constexpr uint32_t REGEXP_GLOBAL_ARRAY_SIZE = 9; @@ -160,7 +167,7 @@ private: using ReplacePositionField = ReplaceLengthField::NextField; // 60 static bool Matcher(JSThread *thread, const JSHandle regexp, - const uint8_t *buffer, size_t length, int32_t lastindex, bool isUtf16); + const uint8_t *buffer, size_t length, int32_t lastindex, bool isUtf16, StringSource source); static JSTaggedValue GetFlagsInternal(JSThread *thread, const JSHandle &obj, const JSHandle &constructor, const uint8_t mask); @@ -196,7 +203,8 @@ private: JSHandle inputString, int32_t lastIndex); static JSTaggedValue RegExpSplitFast(JSThread *thread, const JSHandle regexp, JSHandle string, uint32_t limit, bool useCache); - static JSHandle CreateStringFromResultArray(JSThread *thread, const JSHandle resultArray, + static JSHandle CreateStringFromResultArray(JSThread *thread, + const CVector> &resultArray, const std::vector &resultLengthArray, JSHandle srcString, uint32_t resultStrLength, bool isUtf8); }; diff --git a/ecmascript/builtins/builtins_shared_array.cpp b/ecmascript/builtins/builtins_shared_array.cpp index 5fce2a35c2c49eb008619b9b0e257f8f219e3d66..2ab88beaf70a1eb63e779d3145386bfb477f55e5 100644 --- a/ecmascript/builtins/builtins_shared_array.cpp +++ b/ecmascript/builtins/builtins_shared_array.cpp @@ -314,7 +314,7 @@ JSTaggedValue BuiltinsSharedArray::From(EcmaRuntimeCallInfo *argv) JSTaggedValue BuiltinsSharedArray::Create(EcmaRuntimeCallInfo *argv) { ASSERT(argv); - BUILTINS_API_TRACE(argv->GetThread(), SharedArray, From); + BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Create); JSThread *thread = argv->GetThread(); [[maybe_unused]] EcmaHandleScope handleScope(thread); if (argv->GetArgsNumber() < COUNT_LENGTH_AND_INIT) { @@ -385,7 +385,8 @@ JSTaggedValue BuiltinsSharedArray::Species(EcmaRuntimeCallInfo *argv) { ASSERT(argv); BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Species); - return BuiltinsArray::Species(argv); + // 1. Return the this value. + return GetThis(argv).GetTaggedValue(); } // 22.1.3.1 Array.prototype.concat ( ...arguments ) @@ -404,7 +405,6 @@ JSTaggedValue BuiltinsSharedArray::Concat(EcmaRuntimeCallInfo *argv) JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); [[maybe_unused]] ConcurrentApiScope scope(thread, thisHandle); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle thisObjVal(thisObjHandle); // 2. Let A be ArraySpeciesCreate(O, 0). uint32_t arrayLen = 0; @@ -419,8 +419,8 @@ JSTaggedValue BuiltinsSharedArray::Concat(EcmaRuntimeCallInfo *argv) // 3. Let n be 0. int64_t n = 0; JSMutableHandle ele(thread, JSTaggedValue::Undefined()); - JSMutableHandle fromKey(thread, JSTaggedValue::Undefined()); JSMutableHandle toKey(thread, JSTaggedValue::Undefined()); + JSMutableHandle kValue(thread, JSTaggedValue::Undefined()); // 4. Prepend O to items. // 5. For each element E of items, do for (int i = -1; i < argc; i++) { @@ -437,50 +437,7 @@ JSTaggedValue BuiltinsSharedArray::Concat(EcmaRuntimeCallInfo *argv) bool isSpreadable = ArrayHelper::IsConcatSpreadable(thread, ele); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // b. If spreadable is true, then - if (isSpreadable) { - // i. Let k be 0. - // ii. Let len be ? LengthOfArrayLike(E). - // iii. If n + len > 253 - 1, throw a TypeError exception. - int64_t len = ArrayHelper::GetArrayLength(thread, ele); - int64_t k = 0; - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (n + len > base::MAX_SAFE_INTEGER) { - THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); - } - - if (ele->IsStableJSArray(thread)) { - JSStableArray::Concat(thread, newArrayHandle, JSHandle::Cast(ele), k, n); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - } - // iv. Repeat, while k < len, - while (k < len) { - // 1. Let P be ToString(k). - // 2. Let exists be HasProperty(E, P). - // 3. If exists is true, then - fromKey.Update(JSTaggedValue::ToString(thread, JSTaggedValue(k))); - toKey.Update(JSTaggedValue(n)); - bool exists = JSTaggedValue::HasProperty(thread, ele, fromKey); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (exists) { - // a. Let subElement be Get(E, P). - JSHandle fromValHandle = - JSSharedArray::FastGetPropertyByValue(thread, ele, fromKey); - if (!fromValHandle->IsSharedType()) { - auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); - THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); - } - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - // b. Perform ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), subElement). - JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toKey, fromValHandle, SCheckMode::SKIP); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - } - // 4. Set n to n + 1. - // 5. Set k to k + 1. - n++; - k++; - } - //c. Else - } else { + if (!isSpreadable) { // ii. If n ≥ 253 - 1, throw a TypeError exception. if (n >= base::MAX_SAFE_INTEGER) { THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); @@ -490,6 +447,35 @@ JSTaggedValue BuiltinsSharedArray::Concat(EcmaRuntimeCallInfo *argv) JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, n, ele, SCheckMode::SKIP); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); n++; + continue; + } + + // i. Let k be 0. + // ii. Let len be ? LengthOfArrayLike(E). + // iii. If n + len > 253 - 1, throw a TypeError exception. + int64_t len = ArrayHelper::GetArrayLength(thread, ele); + int64_t k = 0; + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (n + len > base::MAX_SAFE_INTEGER) { + THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); + } + + JSHandle eleObj = JSTaggedValue::ToObject(thread, ele); + while (k < len) { + toKey.Update(JSTaggedValue(n)); + kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, eleObj, k)); + + if (!kValue->IsSharedType()) { + auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + } + + if (!kValue->IsHole()) { + JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toKey, kValue, SCheckMode::SKIP); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + } + n++; + k++; } } // 6. Perform ? Set(A, "length", 𝔽(n), true). @@ -521,11 +507,9 @@ JSTaggedValue BuiltinsSharedArray::Entries(EcmaRuntimeCallInfo *argv) JSHandle iter(factory->NewJSSharedArrayIterator(self, IterationKind::KEY_AND_VALUE)); return iter.GetTaggedValue(); } -JSTaggedValue BuiltinsSharedArray::CheckElementForEvery(JSThread *thread, - JSHandle &thisObjVal, - JSHandle &callbackFnHandle, - JSHandle &thisArgHandle, - uint32_t &k) +JSTaggedValue BuiltinsSharedArray::CheckElementMeetReq(JSThread *thread, + JSHandle &thisObjVal, + JSHandle &callbackFnHandle, bool isSome) { JSMutableHandle key(thread, JSTaggedValue::Undefined()); JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); @@ -536,28 +520,32 @@ JSTaggedValue BuiltinsSharedArray::CheckElementForEvery(JSThread *thread, uint64_t len = static_cast(ArrayHelper::GetArrayLength(thread, thisObjVal)); // ReturnIfAbrupt(len). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + uint32_t k = 0; + JSMutableHandle kValue(thread, JSTaggedValue::Undefined()); + JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisObjVal); while (k < len) { - bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k); + kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (exists) { - JSHandle kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - key.Update(JSTaggedValue(k)); - EcmaRuntimeCallInfo *info = - EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - ASSERT(info != nullptr); - info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); - callResult = JSFunction::Call(info); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (!callResult.ToBoolean()) { - return GetTaggedBoolean(false); - } + key.Update(JSTaggedValue(k)); + EcmaRuntimeCallInfo *info = + EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, undefined, undefined, argsLength); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + ASSERT(info != nullptr); + info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); + callResult = JSFunction::Call(info); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // isSome && callResult.ToBoolean() return true(callResult) + // !isSome && !callResult.ToBoolean() return false(callResult) + if (!(isSome ^ callResult.ToBoolean())) { + return GetTaggedBoolean(callResult.ToBoolean()); } + k++; thread->CheckSafepointIfSuspended(); } - return GetTaggedBoolean(true); + + return GetTaggedBoolean(!isSome); } // Array.prototype.every ( callbackfn [ , thisArg] ) @@ -572,11 +560,8 @@ JSTaggedValue BuiltinsSharedArray::Every(EcmaRuntimeCallInfo *argv) // thisHandle variable declare this Macro ARRAY_CHECK_SHARED_ARRAY("The every method cannot be bound.") - JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); // 2. ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle thisObjVal(thisObjHandle); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. JSHandle callbackFnHandle = GetCallArg(argv, 0); @@ -584,9 +569,6 @@ JSTaggedValue BuiltinsSharedArray::Every(EcmaRuntimeCallInfo *argv) THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception()); } - // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. - JSHandle thisArgHandle = GetCallArg(argv, 1); - // 5. Let k be 0. // 6. Repeat, while k < len // a. Let Pk be ToString(k). @@ -599,16 +581,8 @@ JSTaggedValue BuiltinsSharedArray::Every(EcmaRuntimeCallInfo *argv) // iv. ReturnIfAbrupt(testResult). // v. If testResult is false, return false. // e. Increase k by 1. - uint32_t k = 0; - JSTaggedValue callResult = GetTaggedBoolean(true); - if (thisObjVal->IsStableJSArray(thread)) { - callResult = JSStableArray::HandleEveryOfStable(thread, thisObjHandle, callbackFnHandle, thisArgHandle, k); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (!callResult.ToBoolean()) { - return GetTaggedBoolean(false); - } - } - return CheckElementForEvery(thread, thisObjVal, callbackFnHandle, thisArgHandle, k); + + return CheckElementMeetReq(thread, thisHandle, callbackFnHandle, false); } // Array.prototype.some ( callbackfn [ , thisArg ] ) @@ -623,15 +597,8 @@ JSTaggedValue BuiltinsSharedArray::Some(EcmaRuntimeCallInfo *argv) // thisHandle variable declare this Macro ARRAY_CHECK_SHARED_ARRAY("The some method cannot be bound.") - JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); // 2. ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle thisObjVal(thisObjHandle); - - // 3. Let len be ToLength(Get(O, "length")). - int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); - // 4. ReturnIfAbrupt(len). - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 5. If IsCallable(callbackfn) is false, throw a TypeError exception. JSHandle callbackFnHandle = GetCallArg(argv, 0); @@ -639,59 +606,7 @@ JSTaggedValue BuiltinsSharedArray::Some(EcmaRuntimeCallInfo *argv) THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception()); } - // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. - JSHandle thisArgHandle = GetCallArg(argv, 1); - - // 7. Let k be 0. - // 8. Repeat, while k < len - // a. Let Pk be ToString(k). - // b. Let kPresent be HasProperty(O, Pk). - // c. ReturnIfAbrupt(kPresent). - // d. If kPresent is true, then - // i. Let kValue be Get(O, Pk). - // ii. ReturnIfAbrupt(kValue). - // iii. Let testResult be ToBoolean(Call(callbackfn, T, «kValue, k, and O»)). - // iv. ReturnIfAbrupt(testResult). - // v. If testResult is true, return true. - // e. Increase k by 1. - JSMutableHandle key(thread, JSTaggedValue::Undefined()); - JSMutableHandle kValue(thread, JSTaggedValue::Undefined()); - uint32_t k = 0; - JSTaggedValue callResult = GetTaggedBoolean(false); - if (thisObjVal->IsStableJSArray(thread)) { - callResult = JSStableArray::HandleSomeOfStable(thread, thisObjHandle, callbackFnHandle, thisArgHandle, k); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (callResult.ToBoolean()) { - return GetTaggedBoolean(true); - } - } - while (k < len) { - bool exists = (thisHandle->IsTypedArray() || thisHandle->IsSharedTypedArray() || - JSTaggedValue::HasProperty(thread, thisObjVal, k)); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (exists) { - key.Update(JSTaggedValue(k)); - kValue.Update(JSArray::FastGetPropertyByValue(thread, thisObjVal, key)); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - const uint32_t argsLength = 3; // 3: «kValue, k, O» - JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); - EcmaRuntimeCallInfo *info = - EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - ASSERT(info != nullptr); - info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); - callResult = JSFunction::Call(info); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (callResult.ToBoolean()) { - return GetTaggedBoolean(true); - } - } - k++; - thread->CheckSafepointIfSuspended(); - } - - // 9. Return false. - return GetTaggedBoolean(false); + return CheckElementMeetReq(thread, thisHandle, callbackFnHandle, true); } // 22.1.3.6 Array.prototype.fill (value [ , start [ , end ] ] ) @@ -708,17 +623,6 @@ JSTaggedValue BuiltinsSharedArray::Fill(EcmaRuntimeCallInfo *argv) JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); [[maybe_unused]] ConcurrentApiScope scope(thread, thisHandle); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (thisHandle->IsJSSharedArray()) { - bool isDictionary = thisObjHandle->GetJSHClass()->IsDictionaryElement(); - if (isDictionary) { - uint32_t length = JSSharedArray::Cast(*thisObjHandle)->GetLength(); - uint32_t size = thisObjHandle->GetNumberOfElements(); - if (length - size > JSObject::MAX_GAP) { - JSObject::TryOptimizeAsFastElements(thread, thisObjHandle); - } - } - } // 2. ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -728,15 +632,6 @@ JSTaggedValue BuiltinsSharedArray::Fill(EcmaRuntimeCallInfo *argv) auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } - if (thisHandle->IsTypedArray() || thisHandle->IsSharedTypedArray()) { - ContentType contentType = JSHandle::Cast(thisHandle)->GetContentType(); - if (contentType == ContentType::BigInt) { - value = JSHandle(thread, JSTaggedValue::ToBigInt(thread, value)); - } else { - value = JSHandle(thread, JSTaggedValue::ToNumber(thread, value)); - } - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - } // 3. Let len be ToLength(Get(O, "length")). int64_t len = ArrayHelper::GetLength(thread, thisHandle); @@ -745,10 +640,14 @@ JSTaggedValue BuiltinsSharedArray::Fill(EcmaRuntimeCallInfo *argv) // 5. Let relativeStart be ToInteger(start). JSHandle startArg = GetCallArg(argv, 1); - JSTaggedNumber argStartTemp = JSTaggedValue::ToInteger(thread, startArg); - // 6. ReturnIfAbrupt(relativeStart). - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - double argStart = argStartTemp.GetNumber(); + double argStart = 0; + if (!startArg->IsUndefined()) { + JSTaggedNumber argStartTemp = JSTaggedValue::ToInteger(thread, startArg); + // 6. ReturnIfAbrupt(relativeStart). + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + argStart = argStartTemp.GetNumber(); + } + // 7. If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len). int64_t start = 0; if (argStart < 0) { @@ -787,14 +686,6 @@ JSTaggedValue BuiltinsSharedArray::Fill(EcmaRuntimeCallInfo *argv) return opResult; } - if (thisHandle->IsTypedArray() || thisHandle->IsSharedTypedArray()) { - bool result = JSTypedArray::FastTypedArrayFill(thread, thisHandle, value, start, end); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (result) { - return thisObjHandle.GetTaggedValue(); - } - } - int64_t k = start; JSMutableHandle key(thread, JSTaggedValue::Undefined()); while (k < end) { @@ -808,8 +699,8 @@ JSTaggedValue BuiltinsSharedArray::Fill(EcmaRuntimeCallInfo *argv) return thisObjHandle.GetTaggedValue(); } -JSTaggedValue BuiltinsSharedArray::FilterUnStableJSArray(JSThread *thread, JSHandle &thisArgHandle, - JSHandle &thisObjVal, int64_t k, int64_t len, uint32_t toIndex, JSHandle newArrayHandle, +JSTaggedValue BuiltinsSharedArray::FilterArray(JSThread *thread, JSHandle &thisArgHandle, + JSHandle &thisObjVal, JSHandle newArrayHandle, JSHandle &callbackFnHandle) { JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); @@ -817,25 +708,29 @@ JSTaggedValue BuiltinsSharedArray::FilterUnStableJSArray(JSThread *thread, JSHan JSTaggedValue callResult = GetTaggedBoolean(true); JSMutableHandle key(thread, JSTaggedValue::Undefined()); JSMutableHandle toIndexHandle(thread, JSTaggedValue::Undefined()); + int64_t k = 0; + // 3. Let len be ToLength(Get(O, "length")). + int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); + // 4. ReturnIfAbrupt(len). + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + uint32_t toIndex = 0; + JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisObjVal); + JSMutableHandle kValue(thread, JSTaggedValue::Undefined()); while (k < len) { - bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k); + kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (exists) { - JSHandle kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - key.Update(JSTaggedValue(k)); - EcmaRuntimeCallInfo *info = - EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); - callResult = JSFunction::Call(info); + key.Update(JSTaggedValue(k)); + EcmaRuntimeCallInfo *info = + EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); + callResult = JSFunction::Call(info); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (callResult.ToBoolean()) { + toIndexHandle.Update(JSTaggedValue(toIndex)); + JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toIndexHandle, kValue, SCheckMode::SKIP); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (callResult.ToBoolean()) { - toIndexHandle.Update(JSTaggedValue(toIndex)); - JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toIndexHandle, kValue, SCheckMode::SKIP); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - toIndex++; - } + toIndex++; } k++; } @@ -858,12 +753,6 @@ JSTaggedValue BuiltinsSharedArray::Filter(EcmaRuntimeCallInfo *argv) [[maybe_unused]] ConcurrentApiScope scope(thread, thisHandle); // 2. ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle thisObjVal(thisObjHandle); - - // 3. Let len be ToLength(Get(O, "length")). - uint64_t len = static_cast(ArrayHelper::GetArrayLength(thread, thisObjVal)); - // 4. ReturnIfAbrupt(len). - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 5. If IsCallable(callbackfn) is false, throw a TypeError exception. JSHandle callbackFnHandle = GetCallArg(argv, 0); @@ -875,8 +764,7 @@ JSTaggedValue BuiltinsSharedArray::Filter(EcmaRuntimeCallInfo *argv) JSHandle thisArgHandle = GetCallArg(argv, 1); // 7. Let A be ArraySpeciesCreate(O, 0). - int32_t arrayLen = 0; - JSTaggedValue newArray = JSSharedArray::ArraySpeciesCreate(thread, thisObjHandle, JSTaggedNumber(arrayLen)); + JSTaggedValue newArray = JSSharedArray::ArraySpeciesCreate(thread, thisObjHandle, JSTaggedNumber(0)); // 8. ReturnIfAbrupt(A). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle newArrayHandle(thread, newArray); @@ -897,16 +785,8 @@ JSTaggedValue BuiltinsSharedArray::Filter(EcmaRuntimeCallInfo *argv) // 2. ReturnIfAbrupt(status). // 3. Increase to by 1. // e. Increase k by 1. - uint32_t toIndex = 0; - JSMutableHandle key(thread, JSTaggedValue::Undefined()); - JSMutableHandle toIndexHandle(thread, JSTaggedValue::Undefined()); - uint32_t k = 0; - if (thisObjVal->IsStableJSArray(thread)) { - JSStableArray::Filter(newArrayHandle, thisObjHandle, argv, k, toIndex); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - } auto opResult = - FilterUnStableJSArray(thread, thisArgHandle, thisObjVal, k, len, toIndex, newArrayHandle, callbackFnHandle); + FilterArray(thread, thisArgHandle, thisHandle, newArrayHandle, callbackFnHandle); return opResult; } @@ -927,10 +807,9 @@ JSTaggedValue BuiltinsSharedArray::Find(EcmaRuntimeCallInfo *argv) [[maybe_unused]] ConcurrentApiScope scope(thread, thisHandle); // 2. ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle thisObjVal(thisObjHandle); // 3. Let len be ToLength(Get(O, "length")). - int64_t len = ArrayHelper::GetLength(thread, thisObjVal); + int64_t len = ArrayHelper::GetLength(thread, thisHandle); // 4. ReturnIfAbrupt(len). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -953,9 +832,10 @@ JSTaggedValue BuiltinsSharedArray::Find(EcmaRuntimeCallInfo *argv) // f. If testResult is true, return kValue. // g. Increase k by 1. JSMutableHandle key(thread, JSTaggedValue::Undefined()); + JSMutableHandle kValue(thread, JSTaggedValue::Undefined()); int64_t k = 0; while (k < len) { - JSHandle kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); + kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); key.Update(JSTaggedValue(k)); const uint32_t argsLength = 3; // 3: «kValue, k, O» @@ -963,7 +843,7 @@ JSTaggedValue BuiltinsSharedArray::Find(EcmaRuntimeCallInfo *argv) EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); + info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue()); JSTaggedValue callResult = JSFunction::Call(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); if (callResult.ToBoolean()) { @@ -976,6 +856,33 @@ JSTaggedValue BuiltinsSharedArray::Find(EcmaRuntimeCallInfo *argv) return JSTaggedValue::Undefined(); } +JSTaggedValue BuiltinsSharedArray::GetElementByKey(JSThread *thread, JSHandle& thisObjHandle, uint32_t index) +{ + JSTaggedValue val = ElementAccessor::Get(thisObjHandle, index); + if (val.IsHole()) { + JSHandle thisObjVal(thisObjHandle); + // dependent on Prototype, SharedArray have not Prototype,Can be optimized + auto res = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, index).GetTaggedValue(); + if (res.IsHole()) { + return JSTaggedValue::Undefined(); + } else { + return res; + } + } + + return val; +} + +void BuiltinsSharedArray::SetElementValue(JSThread *thread, JSHandle arrHandle, uint32_t key, + const JSHandle &value) +{ + if (UNLIKELY(!value->IsSharedType())) { + auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); + THROW_NEW_ERROR_AND_RETURN(thread, error); + } + ElementAccessor::Set(thread, arrHandle, key, value, false); +} + // 22.1.3.9 Array.prototype.findIndex ( predicate [ , thisArg ] ) JSTaggedValue BuiltinsSharedArray::FindIndex(EcmaRuntimeCallInfo *argv) { @@ -992,10 +899,9 @@ JSTaggedValue BuiltinsSharedArray::FindIndex(EcmaRuntimeCallInfo *argv) [[maybe_unused]] ConcurrentApiScope scope(thread, thisHandle); // 2. ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle thisObjVal(thisObjHandle); // 3. Let len be ToLength(Get(O, "length")). - uint64_t len = static_cast(ArrayHelper::GetLength(thread, thisObjVal)); + uint64_t len = static_cast(ArrayHelper::GetLength(thread, thisHandle)); // 4. ReturnIfAbrupt(len). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -1005,9 +911,13 @@ JSTaggedValue BuiltinsSharedArray::FindIndex(EcmaRuntimeCallInfo *argv) THROW_TYPE_ERROR_AND_RETURN(thread, "the predicate is not callable.", JSTaggedValue::Exception()); } - // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. - JSHandle thisArgHandle = GetCallArg(argv, 1); + if (UNLIKELY(ElementAccessor::GetElementsLength(thisObjHandle) < len)) { + len = ElementAccessor::GetElementsLength(thisObjHandle); + } + const int32_t argsLength = 3; // 3: ?kValue, k, O? + JSMutableHandle kValue(thread, JSTaggedValue::Undefined()); + uint32_t k = 0; // 7. Let k be 0. // 8. Repeat, while k < len // a. Let Pk be ToString(k). @@ -1017,28 +927,15 @@ JSTaggedValue BuiltinsSharedArray::FindIndex(EcmaRuntimeCallInfo *argv) // e. ReturnIfAbrupt(testResult). // f. If testResult is true, return k. // g. Increase k by 1. - uint32_t k = 0; - JSTaggedValue callResult = GetTaggedBoolean(true); - if (thisObjVal->IsStableJSArray(thread)) { - callResult = JSStableArray::HandleFindIndexOfStable(thread, thisObjHandle, callbackFnHandle, thisArgHandle, k); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (callResult.ToBoolean()) { - return GetTaggedDouble(k); - } - } - JSMutableHandle key(thread, JSTaggedValue::Undefined()); - JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); - const uint32_t argsLength = 3; // 3: «kValue, k, O» while (k < len) { - JSHandle kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - key.Update(JSTaggedValue(k)); + kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k)); EcmaRuntimeCallInfo *info = - EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); - callResult = JSFunction::Call(info); + EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle.GetTaggedValue(), + JSTaggedValue::Undefined(), JSTaggedValue::Undefined(), argsLength); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + info->SetCallArg(kValue.GetTaggedValue(), JSTaggedValue(k), thisHandle.GetTaggedValue()); + auto callResult = JSFunction::Call(info); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, callResult); if (callResult.ToBoolean()) { return GetTaggedDouble(k); } @@ -1065,10 +962,9 @@ JSTaggedValue BuiltinsSharedArray::ForEach(EcmaRuntimeCallInfo *argv) [[maybe_unused]] ConcurrentApiScope scope(thread, thisHandle); // 2. ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle thisObjVal(thisObjHandle); // 3. Let len be ToLength(Get(O, "length")). - uint64_t len = static_cast(ArrayHelper::GetArrayLength(thread, thisObjVal)); + uint64_t len = static_cast(ArrayHelper::GetArrayLength(thread, thisHandle)); // 4. ReturnIfAbrupt(len). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -1094,26 +990,18 @@ JSTaggedValue BuiltinsSharedArray::ForEach(EcmaRuntimeCallInfo *argv) // e. Increase k by 1. JSMutableHandle key(thread, JSTaggedValue::Undefined()); uint32_t k = 0; - if (thisObjVal->IsStableJSArray(thread)) { - JSStableArray::HandleforEachOfStable(thread, thisObjHandle, callbackFnHandle, thisArgHandle, len, k); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - } const uint32_t argsLength = 3; // 3: «kValue, k, O» JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); + JSMutableHandle kValue(thread, JSTaggedValue::Undefined()); while (k < len) { - bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k); + kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k)); + key.Update(JSTaggedValue(k)); + EcmaRuntimeCallInfo *info = + EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (exists) { - JSHandle kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - key.Update(JSTaggedValue(k)); - EcmaRuntimeCallInfo *info = - EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); - JSTaggedValue funcResult = JSFunction::Call(info); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult); - } + info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue()); + JSTaggedValue funcResult = JSFunction::Call(info); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult); k++; } @@ -1803,7 +1691,7 @@ JSTaggedValue BuiltinsSharedArray::Sort(EcmaRuntimeCallInfo *argv) // Array sort if (thisHandle->IsStableJSArray(thread) && callbackFnHandle->IsUndefined()) { - JSStableArray::Sort(thread, thisObjHandle, callbackFnHandle); + JSStableArray::Sort(thread, thisHandle, callbackFnHandle); } else { JSSharedArray::Sort(thread, JSHandle::Cast(thisObjHandle), callbackFnHandle); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -2534,4 +2422,180 @@ JSTaggedValue BuiltinsSharedArray::LastIndexOf(EcmaRuntimeCallInfo *argv) return LastIndexOfSlowPath(argv, thread, thisHandle); } +// Array.of ( ...items ) +JSTaggedValue BuiltinsSharedArray::Of(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Of); + JSThread *thread = argv->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + const GlobalEnvConstants *globalConst = thread->GlobalConstants(); + + // 1. Let len be the actual number of arguments passed to this function. + uint32_t argc = argv->GetArgsNumber(); + + // 3. Let C be the this value. + // thisHandle variable declare this Macro + JSHandle thisHandle = GetThis(argv); + + // 4. If IsConstructor(C) is true, then + // a. Let A be Construct(C, «len»). + // 5. Else, + // a. Let A be ArrayCreate(len). + // 6. ReturnIfAbrupt(A). + JSHandle newArray; + if (thisHandle->IsConstructor()) { + JSHandle undefined = globalConst->GetHandledUndefined(); + EcmaRuntimeCallInfo *info = + EcmaInterpreter::NewRuntimeCallInfo(thread, thisHandle, undefined, undefined, 1); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + info->SetCallArg(JSTaggedValue(argc)); + JSTaggedValue taggedArray = JSFunction::Construct(info); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + newArray = JSHandle(thread, taggedArray); + } else { + newArray = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(argc)); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + } + + if (!newArray->IsJSSharedArray()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to create Object.", JSTaggedValue::Exception()); + } + + JSHandle newArrayHandle(newArray); + TaggedArray *elements = TaggedArray::Cast(newArrayHandle->GetElements().GetTaggedObject()); + if (UNLIKELY(argc > ElementAccessor::GetElementsLength(newArrayHandle))) { + elements = *JSObject::GrowElementsCapacity(thread, JSHandle::Cast(newArrayHandle), argc, true); + } + + // 7. Let k be 0. + // 8. Repeat, while k < len + // a. Let kValue be items[k]. + // b. Let Pk be ToString(k). + // c. Let defineStatus be CreateDataPropertyOrThrow(A,Pk, kValue). + // d. ReturnIfAbrupt(defineStatus). + // e. Increase k by 1. + for (uint32_t k = 0; k < argc; k++) { + JSHandle value = argv->GetCallArg(k); + BuiltinsSharedArray::SetElementValue(thread, newArrayHandle, k, value); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + } + JSSharedArray::Cast(*newArrayHandle)->SetArrayLength(thread, argc); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + return newArrayHandle.GetTaggedValue(); +} + +uint64_t BuiltinsSharedArray::ConvertTagValueToInteger(JSThread *thread, JSHandle& number, int64_t len) +{ + JSTaggedNumber targetTemp = JSTaggedValue::ToInteger(thread, number); + double target = targetTemp.GetNumber(); + // If relativeTarget < 0, let to be max((len + relativeTarget),0); else let to be min(relativeTarget, len). + if (target < 0) { + return target + len > 0 ? static_cast(target + len) : 0; + } else { + return target < len ? static_cast(target) : len; + } +} + +uint64_t BuiltinsSharedArray::GetNumberArgVal(JSThread *thread, EcmaRuntimeCallInfo *argv, uint32_t idx, int64_t len, + int64_t defVal) +{ + JSHandle argValue = GetCallArg(argv, idx); + + return argValue->IsUndefined() ? defVal : BuiltinsSharedArray::ConvertTagValueToInteger(thread, argValue, len); +} + +uint64_t BuiltinsSharedArray::GetNumberArgValThrow(JSThread *thread, EcmaRuntimeCallInfo *argv, uint32_t idx, + int64_t len, const char* err) +{ + JSHandle argValue = GetCallArg(argv, idx); + if (UNLIKELY(argValue->IsUndefined())) { + auto error = ContainerError::BindError(thread, err); + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, 0); + } + + return BuiltinsSharedArray::ConvertTagValueToInteger(thread, argValue, len); +} + +// Array.prototype.copyWithin (target, start [ , end ] ) +JSTaggedValue BuiltinsSharedArray::CopyWithin(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + BUILTINS_API_TRACE(argv->GetThread(), SharedArray, CopyWithin); + JSThread *thread = argv->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + // 1. Let O be ToObject(this value). + // 3. Let C be the this value. + // thisHandle variable declare this Macro + ARRAY_CHECK_SHARED_ARRAY("The CopyWithin method cannot be bound.") + + JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); + // 2. ReturnIfAbrupt(O). + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 3. Let len be ToLength(Get(O, "length")). + int64_t len = ArrayHelper::GetLength(thread, thisHandle); + // 4. ReturnIfAbrupt(len). + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + int64_t copyTo = GetNumberArgValThrow(thread, argv, 0, len, "Target index cannot be undefined."); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 5. Let relativeStart be ToInteger(start). + int64_t copyFrom = GetNumberArgVal(thread, argv, 1, len, 0); + // 6. ReturnIfAbrupt(relativeStart). + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 7. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end). + int64_t copyEnd = GetNumberArgVal(thread, argv, 2, len, len); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 14. Let count be min(final-from, len-to). + int64_t count = std::min(copyEnd - copyFrom, len - copyTo); + + // 15. If from 0 + // a. Let fromKey be ToString(from). + // b. Let toKey be ToString(to). + // c. Let fromPresent be HasProperty(O, fromKey). + // d. ReturnIfAbrupt(fromPresent). + // e. If fromPresent is true, then + // i. Let fromVal be Get(O, fromKey). + // ii. ReturnIfAbrupt(fromVal). + // iii. Let setStatus be Set(O, toKey, fromVal, true). + // iv. ReturnIfAbrupt(setStatus). + // f. Else fromPresent is false, + // i. Let deleteStatus be DeletePropertyOrThrow(O, toKey). + // ii. ReturnIfAbrupt(deleteStatus). + // g. Let from be from + direction. + // h. Let to be to + direction. + // i. Let count be count − 1. + JSMutableHandle kValue(thread, JSTaggedValue::Undefined()); + while (count > 0) { + kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, copyFrom)); + BuiltinsSharedArray::SetElementValue(thread, thisObjHandle, copyTo, kValue); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + copyFrom = copyFrom + direction; + copyTo = copyTo + direction; + count--; + } + + // 18. Return O. + return thisObjHandle.GetTaggedValue(); +} + } // namespace panda::ecmascript::builtins diff --git a/ecmascript/builtins/builtins_shared_array.h b/ecmascript/builtins/builtins_shared_array.h index 2539d9a6f368530e3293fd2c0d62074022685ece..81da0c71c2c734c22bd9cf4e20d5bf7371dbce17 100644 --- a/ecmascript/builtins/builtins_shared_array.h +++ b/ecmascript/builtins/builtins_shared_array.h @@ -28,6 +28,7 @@ V("create", Create, 2, INVALID) \ /* SendableArray.isArray ( arg ) */ \ V("isArray", IsArray, 1, INVALID) \ + V("of", Of, 1, INVALID) \ // fixme(hzzhouzebin) Support later. // /* SharedArray.of ( ...items ) */ \ // V("of", Of, 0, INVALID) @@ -89,7 +90,8 @@ /* SharedArray.prototype.some ( callbackfn [ , thisArg ] ) */ \ V("some", Some, 1, INVALID) \ /* SendableArray.prototype.lastIndexOf ( searchElement [ , fromIndex ] ) */ \ - V("lastIndexOf", LastIndexOf, 1, INVALID) + V("lastIndexOf", LastIndexOf, 1, INVALID) \ + V("copyWithin", CopyWithin, 2, INVALID) \ // fixme(hzzhouzebin) Support later. // /* SharedArray.prototype.with ( index, value ) */ \ // V("with", With, 2, INVALID) \ @@ -98,7 +100,6 @@ // /* SharedArray.prototype.reverse ( ) */ \ // V("reverse", Reverse, 0, INVALID) \ // /* SharedArray.prototype.copyWithin ( target, start [ , end ] ) */ \ - // V("copyWithin", CopyWithin, 2, INVALID) \ // /* SharedArray.prototype.findLast ( predicate [ , thisArg ] ) */ \ // V("findLast", FindLast, 1, INVALID) \ // /* SharedArray.prototype.findLastIndex ( predicate [ , thisArg ] ) */ \ @@ -151,6 +152,8 @@ public: static JSTaggedValue Every(EcmaRuntimeCallInfo *argv); static JSTaggedValue Some(EcmaRuntimeCallInfo *argv); static JSTaggedValue LastIndexOf(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Of(EcmaRuntimeCallInfo *argv); + static JSTaggedValue CopyWithin(EcmaRuntimeCallInfo *argv); // Excluding the '@@' internal properties static Span GetSharedArrayFunctions() @@ -177,9 +180,9 @@ public: JSHandle &thisObjVal, int64_t k, int64_t len, JSMutableHandle &accumulator, JSHandle &callbackFnHandle); - static JSTaggedValue FilterUnStableJSArray(JSThread *thread, JSHandle &thisArgHandle, - JSHandle &thisObjVal, int64_t k, int64_t len, uint32_t toIndex, - JSHandle newArrayHandle, JSHandle &callbackFnHandle); + static JSTaggedValue FilterArray(JSThread *thread, JSHandle &thisArgHandle, + JSHandle &thisObjVal, JSHandle newArrayHandle, + JSHandle &callbackFnHandle); static Span> GetPrototypeProperties() { @@ -189,7 +192,18 @@ public: { return Span>(ARRAY_FUNCTION_PROPERTIES); } + + static inline uint64_t ConvertTagValueToInteger(JSThread *thread, JSHandle& number, int64_t len); + static inline uint64_t GetNumberArgVal(JSThread *thread, EcmaRuntimeCallInfo *argv, uint32_t idx, int64_t len, + int64_t defVal); + static inline uint64_t GetNumberArgValThrow(JSThread *thread, EcmaRuntimeCallInfo *argv, uint32_t idx, + int64_t len, const char* err); + + static inline void SetElementValue(JSThread *thread, JSHandle arrHandle, uint32_t key, + const JSHandle &value); + private: + static inline JSTaggedValue GetElementByKey(JSThread *thread, JSHandle& thisObjHandle, uint32_t index); static JSTaggedValue PopInner(EcmaRuntimeCallInfo *argv, JSHandle &thisHandle, JSHandle &thisObjHandle); #define BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY(name, method, length, id) \ @@ -232,11 +246,9 @@ private: BUILTIN_SHARED_ARRAY_FUNCTIONS(ARRAY_PROPERTIES_PAIR) std::pair("[Symbol.species]", true), }; - static JSTaggedValue CheckElementForEvery(JSThread *thread, - JSHandle &thisObjVal, - JSHandle &callbackFnHandle, - JSHandle &thisArgHandle, - uint32_t &k); + static JSTaggedValue CheckElementMeetReq(JSThread *thread, + JSHandle &thisObjVal, + JSHandle &callbackFnHandle, bool isSome); #undef ARRAY_PROPERTIES_PAIR #define ARRAY_CHECK_SHARED_ARRAY(errMsg) \ diff --git a/ecmascript/builtins/builtins_string.cpp b/ecmascript/builtins/builtins_string.cpp index dfcdf4fffe42fc897a05da841d7f7bdaed0c5df0..a26849d93876a31f4cfca05a019d5b89c7fc5ad4 100644 --- a/ecmascript/builtins/builtins_string.cpp +++ b/ecmascript/builtins/builtins_string.cpp @@ -507,7 +507,7 @@ JSTaggedValue BuiltinsString::LastIndexOf(EcmaRuntimeCallInfo *argv) } pos = std::min(std::max(pos, 0), thisLen); int32_t res = EcmaStringAccessor::LastIndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, pos); - if (res >= 0 && res < thisLen) { + if (res >= 0 && res <= thisLen) { return GetTaggedInt(res); } res = -1; @@ -609,7 +609,7 @@ JSTaggedValue BuiltinsString::Match(EcmaRuntimeCallInfo *argv) RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle regexp = BuiltinsString::GetCallArg(argv, 0); if (thisTag->IsString() && regexp->IsECMAObject()) { - if (BuiltinsRegExp::IsFastRegExp(thread, regexp, BuiltinsRegExp::RegExpSymbol::MATCH)) { + if (BuiltinsRegExp::IsFastRegExp(thread, regexp.GetTaggedValue(), BuiltinsRegExp::RegExpSymbol::MATCH)) { return BuiltinsRegExp::RegExpMatch(thread, regexp, thisTag, true); } } @@ -659,7 +659,7 @@ JSTaggedValue BuiltinsString::MatchAll(EcmaRuntimeCallInfo *argv) if (!regexp->IsUndefined() && !regexp->IsNull()) { // a. Let isRegExp be ? IsRegExp(searchValue). if (regexp->IsECMAObject() && - BuiltinsRegExp::IsFastRegExp(thread, regexp, BuiltinsRegExp::RegExpSymbol::MATCH)) { + BuiltinsRegExp::IsFastRegExp(thread, regexp.GetTaggedValue(), BuiltinsRegExp::RegExpSymbol::MATCH)) { bool isGlobal = BuiltinsRegExp::GetOriginalFlag(thread, regexp, RegExpParser::FLAG_GLOBAL); if (!isGlobal) { THROW_TYPE_ERROR_AND_RETURN(thread, @@ -689,7 +689,7 @@ JSTaggedValue BuiltinsString::MatchAll(EcmaRuntimeCallInfo *argv) RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); if (thisTag->IsString() && regexp->IsECMAObject()) { if (PropertyDetector::IsRegExpSpeciesDetectorValid(env) && - BuiltinsRegExp::IsFastRegExp(thread, regexp, BuiltinsRegExp::RegExpSymbol::MATCHALL)) { + BuiltinsRegExp::IsFastRegExp(thread, regexp.GetTaggedValue(), BuiltinsRegExp::RegExpSymbol::MATCHALL)) { JSHandle string = JSHandle::Cast(thisTag); return BuiltinsRegExp::RegExpMatchAll(thread, regexp, string, true); } @@ -1030,7 +1030,7 @@ JSTaggedValue BuiltinsString::Replace(EcmaRuntimeCallInfo *argv) JSHandle re(searchTag); JSHandle pattern(thread, re->GetOriginalSource()); JSHandle flags(thread, re->GetOriginalFlags()); - bool isFastPath = BuiltinsRegExp::IsFastRegExp(thread, searchTag); + bool isFastPath = BuiltinsRegExp::IsFastRegExp(thread, searchTag.GetTaggedValue()); if (isFastPath) { uint32_t lastIndex = static_cast(BuiltinsRegExp::GetLastIndex(thread, searchTag, true)); JSTaggedValue cacheResult = cacheTable->FindCachedResult(thread, thisTag, @@ -1251,7 +1251,9 @@ JSTaggedValue BuiltinsString::ReplaceAll(EcmaRuntimeCallInfo *argv) EcmaStringAccessor::FastSubString(ecmaVm, thisString, endOfLastMatch, pos - endOfLastMatch)); accumulatedResult.Update(JSTaggedValue(EcmaStringAccessor::Concat(ecmaVm, accumulatedResult, prefixString))); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); accumulatedResult.Update(JSTaggedValue(EcmaStringAccessor::Concat(ecmaVm, accumulatedResult, realReplaceStr))); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); endOfLastMatch = pos + searchLength; pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, searchString, pos + advanceBy); thread->CheckSafepointIfSuspended(); @@ -1262,6 +1264,7 @@ JSTaggedValue BuiltinsString::ReplaceAll(EcmaRuntimeCallInfo *argv) JSHandle suffixString(thread, EcmaStringAccessor::FastSubString(ecmaVm, thisString, endOfLastMatch, thisLen - endOfLastMatch)); accumulatedResult.Update(JSTaggedValue(EcmaStringAccessor::Concat(ecmaVm, accumulatedResult, suffixString))); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } return accumulatedResult.GetTaggedValue(); @@ -1502,7 +1505,7 @@ JSTaggedValue BuiltinsString::Search(EcmaRuntimeCallInfo *argv) RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle regexp = BuiltinsString::GetCallArg(argv, 0); if (thisTag->IsString() && regexp->IsECMAObject()) { - if (BuiltinsRegExp::IsFastRegExp(thread, regexp, BuiltinsRegExp::RegExpSymbol::SEARCH)) { + if (BuiltinsRegExp::IsFastRegExp(thread, regexp.GetTaggedValue(), BuiltinsRegExp::RegExpSymbol::SEARCH)) { return BuiltinsRegExp::RegExpSearchFast(thread, regexp, thisTag); } } @@ -1547,7 +1550,7 @@ JSTaggedValue BuiltinsString::Slice(EcmaRuntimeCallInfo *argv) JSHandle startTag = BuiltinsString::GetCallArg(argv, 0); JSTaggedNumber startVal = JSTaggedValue::ToInteger(thread, startTag); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - int32_t start = ConvertDoubleToInt(startVal.GetNumber()); + int32_t start = base::NumberHelper::SaturateTruncDoubleToInt32(startVal.GetNumber()); int32_t end = 0; JSHandle endTag = BuiltinsString::GetCallArg(argv, 1); if (endTag->IsUndefined()) { @@ -1555,7 +1558,7 @@ JSTaggedValue BuiltinsString::Slice(EcmaRuntimeCallInfo *argv) } else { JSTaggedNumber endVal = JSTaggedValue::ToInteger(thread, endTag); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - end = ConvertDoubleToInt(endVal.GetNumber()); + end = base::NumberHelper::SaturateTruncDoubleToInt32(endVal.GetNumber()); } int32_t from = 0; int32_t to = 0; @@ -1591,7 +1594,7 @@ JSTaggedValue BuiltinsString::Split(EcmaRuntimeCallInfo *argv) if (thisTag->IsString() && seperatorTag->IsECMAObject()) { // this condition need change, all regexp should use RegExpSplit - if (BuiltinsRegExp::IsFastRegExp(thread, seperatorTag)) { + if (BuiltinsRegExp::IsFastRegExp(thread, seperatorTag.GetTaggedValue())) { return BuiltinsRegExp::RegExpSplit(thread, seperatorTag, thisTag, limitTag, true); } } @@ -1858,7 +1861,7 @@ JSTaggedValue BuiltinsString::Substring(EcmaRuntimeCallInfo *argv) JSHandle startTag = BuiltinsString::GetCallArg(argv, 0); JSTaggedNumber startVal = JSTaggedValue::ToInteger(thread, startTag); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - int32_t start = ConvertDoubleToInt(startVal.GetNumber()); + int32_t start = base::NumberHelper::SaturateTruncDoubleToInt32(startVal.GetNumber()); int32_t end = 0; JSHandle endTag = BuiltinsString::GetCallArg(argv, 1); if (endTag->IsUndefined()) { @@ -1866,7 +1869,7 @@ JSTaggedValue BuiltinsString::Substring(EcmaRuntimeCallInfo *argv) } else { JSTaggedNumber endVal = JSTaggedValue::ToInteger(thread, endTag); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - end = ConvertDoubleToInt(endVal.GetNumber()); + end = base::NumberHelper::SaturateTruncDoubleToInt32(endVal.GetNumber()); } start = std::min(std::max(start, 0), thisLen); end = std::min(std::max(end, 0), thisLen); @@ -2305,20 +2308,6 @@ JSTaggedValue BuiltinsString::Pad(EcmaRuntimeCallInfo *argv, bool isStart) resultString.size()).GetTaggedValue(); } -int32_t BuiltinsString::ConvertDoubleToInt(double d) -{ - if (std::isnan(d) || d == -base::POSITIVE_INFINITY) { - return 0; - } - if (d >= static_cast(INT_MAX)) { - return INT_MAX; - } - if (d <= static_cast(INT_MIN)) { - return INT_MIN; - } - return base::NumberHelper::DoubleToInt(d, base::INT32_BITS); -} - JSTaggedValue BuiltinsString::StringToList(JSThread *thread, JSHandle &str) { JSHandle cacheTable(thread->GetCurrentEcmaContext()->GetStringToListResultCache()); diff --git a/ecmascript/builtins/builtins_string.h b/ecmascript/builtins/builtins_string.h index 999faef225a722d9a9fef29ccc27d317c3d92534..19b3f65345612c8ee495475dfbfeeda73a44eca6 100644 --- a/ecmascript/builtins/builtins_string.h +++ b/ecmascript/builtins/builtins_string.h @@ -282,7 +282,6 @@ private: #undef BUILTIN_STRING_FUNCTION_ENTRY static JSTaggedValue Pad(EcmaRuntimeCallInfo *argv, bool isStart); - static int32_t ConvertDoubleToInt(double d); static JSTaggedValue CreateArrayFromString(JSThread *thread, EcmaVM *ecmaVm, const JSHandle &thisString, uint32_t thisLength, uint32_t lim = UINT32_MAX - 1); static JSTaggedValue CreateArrayBySplitString(JSThread *thread, EcmaVM *ecmaVm, diff --git a/ecmascript/builtins/shared_builtins.cpp b/ecmascript/builtins/shared_builtins.cpp index a46a78fd9b2c00ec329a04d7ac4aac4b52fd0e74..0cd2bf44b6b10bc6ea84c990cf6cc6dd3408a7c0 100644 --- a/ecmascript/builtins/shared_builtins.cpp +++ b/ecmascript/builtins/shared_builtins.cpp @@ -25,6 +25,9 @@ #include "ecmascript/builtins/builtins_shared_map.h" #include "ecmascript/builtins/builtins_shared_set.h" #include "ecmascript/builtins/builtins_shared_typedarray.h" +#include "ecmascript/containers/containers_bitvector.h" +#include "ecmascript/containers/containers_private.h" +#include "ecmascript/js_api/js_api_bitvector.h" #include "ecmascript/shared_objects/js_shared_array.h" #include "ecmascript/shared_objects/js_sendable_arraybuffer.h" #include "ecmascript/shared_objects/js_shared_map.h" @@ -46,6 +49,7 @@ using BuiltinsSharedMap = builtins::BuiltinsSharedMap; using BuiltinsSharedArray = builtins::BuiltinsSharedArray; using BuiltinsSharedTypedArray = builtins::BuiltinsSharedTypedArray; using BuiltinsSendableArrayBuffer = builtins::BuiltinsSendableArrayBuffer; +using ContainersBitVector = containers::ContainersBitVector; void Builtins::InitializeSObjectAndSFunction(const JSHandle &env) const { @@ -572,6 +576,35 @@ JSHandle Builtins::CreateSMapFunctionHClass(const JSHandle return sobjPrototypeHClass; } +JSHandle Builtins::CreateBitVectorFunctionHClass(const JSHandle &sFuncPrototype) const +{ + uint32_t index = 0; + auto env = vm_->GetGlobalEnv(); + PropertyAttributes attributes = PropertyAttributes::Default(false, false, false); + attributes.SetIsInlinedProps(true); + attributes.SetRepresentation(Representation::TAGGED); + auto properties = ContainersBitVector::GetFunctionProperties(); + uint32_t length = properties.size(); + JSHandle keyString; + JSHandle layout = factory_->CreateSLayoutInfo(length); + for (const auto &[key, isAccessor] : properties) { + attributes.SetOffset(index); + attributes.SetIsAccessor(isAccessor); + if (key == "[Symbol.species]") { + keyString = env->GetSpeciesSymbol(); + } else { + keyString = JSHandle(factory_->NewFromUtf8ReadOnly(key)); + } + layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes); + } + JSHandle sobjPrototypeHClass = + factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION, + JSHandle(sFuncPrototype), JSHandle(layout)); + sobjPrototypeHClass->SetConstructor(true); + sobjPrototypeHClass->SetCallable(true); + return sobjPrototypeHClass; +} + JSHandle Builtins::CreateSFunctionPrototypeHClass(const JSHandle &sObjPrototypeVal) const { uint32_t index = 0; @@ -691,6 +724,37 @@ JSHandle Builtins::CreateSMapPrototypeHClass(const JSHandle return sMapPrototypeHClass; } +JSHandle Builtins::CreateBitVectorPrototypeHClass(const JSHandle &sObjPrototype) const +{ + uint32_t index = 0; + auto env = vm_->GetGlobalEnv(); + PropertyAttributes attributes = PropertyAttributes::Default(false, false, false); + attributes.SetIsInlinedProps(true); + attributes.SetRepresentation(Representation::TAGGED); + auto properties = ContainersBitVector::GetPrototypeProperties(); + uint32_t length = properties.size(); + ASSERT(length == ContainersBitVector::GetNumPrototypeInlinedProperties()); + JSHandle layout = factory_->CreateSLayoutInfo(length); + JSHandle keyString; + for (const auto &[key, isAccessor] : properties) { + attributes.SetOffset(index); + attributes.SetIsAccessor(isAccessor); + if (key == "[Symbol.iterator]") { + keyString = env->GetIteratorSymbol(); + } else if (key == "[Symbol.toStringTag]") { + keyString = env->GetToStringTagSymbol(); + } else { + keyString = JSHandle(factory_->NewFromUtf8ReadOnly(key)); + } + layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes); + } + JSHandle sBitVectorPrototypeHClass = + factory_->NewSEcmaHClass(JSSharedObject::SIZE, length, JSType::JS_SHARED_OBJECT, + JSHandle(sObjPrototype), + JSHandle(layout)); + return sBitVectorPrototypeHClass; +} + JSHandle Builtins::CreateSArrayPrototypeHClass(const JSHandle &sObjPrototype) const { uint32_t index = 0; @@ -983,6 +1047,56 @@ void Builtins::InitializeSharedArray(const JSHandle &env, const JSHan env->SetSharedArrayPrototype(thread_, arrFuncPrototype); } +void Builtins::InitializeSharedBitVector(const JSHandle &env, const JSHandle &sObjPrototype, + const JSHandle &sFuncPrototype) const +{ + [[maybe_unused]] EcmaHandleScope scope(thread_); + auto globalConst = const_cast(thread_->GlobalConstants()); + // BitVector.prototype + JSHandle prototypeHClass = CreateBitVectorPrototypeHClass(sObjPrototype); + JSHandle bitVectorFuncPrototype = factory_->NewSharedOldSpaceJSObjectWithInit(prototypeHClass); + JSHandle bitVectorFuncPrototypeValue(bitVectorFuncPrototype); + + // BitVector.prototype_or_hclass + auto emptySLayout = globalConst->GetHandledEmptySLayoutInfo(); + JSHandle bitVectorInstanceClass = + factory_->NewSEcmaHClass(JSAPIBitVector::SIZE, 0, + JSType::JS_API_BITVECTOR, bitVectorFuncPrototypeValue, emptySLayout); + + // BitVector.hclass + JSHandle bitVectorFuncHClass = CreateBitVectorFunctionHClass(sFuncPrototype); + bitVectorFuncHClass->SetExtensible(false); + + // BitVector() = new Function() + JSHandle bitVectorFunction = + factory_->NewSFunctionByHClass(reinterpret_cast(ContainersBitVector::BitVectorConstructor), + bitVectorFuncHClass, FunctionKind::BUILTIN_CONSTRUCTOR); + InitializeSCtor(bitVectorInstanceClass, bitVectorFunction, "BitVector", FunctionLength::ONE); + // BitVector.prototype + int32_t protoFieldIndex = 0; + bitVectorFuncPrototype->SetPropertyInlinedProps(thread_, protoFieldIndex++, bitVectorFunction.GetTaggedValue()); + for (const base::BuiltinFunctionEntry &entry: ContainersBitVector::GetBitVectorPrototypeFunctions()) { + SetSFunction(env, bitVectorFuncPrototype, entry.GetName(), entry.GetEntrypoint(), protoFieldIndex++, + entry.GetLength(), entry.GetBuiltinStubId()); + } + // @@StringTag + JSHandle strTag(factory_->NewFromUtf8ReadOnly("BitVector")); + bitVectorFuncPrototype->SetPropertyInlinedProps(thread_, protoFieldIndex++, strTag.GetTaggedValue()); + + JSHandle sizeGetter = CreateSGetterSetter(env, ContainersBitVector::GetSize, "size", + FunctionLength::ZERO); + JSHandle lengthGetter = CreateSGetterSetter(env, ContainersBitVector::GetSize, "length", + FunctionLength::ZERO); + SetSAccessor(bitVectorFuncPrototype, protoFieldIndex++, sizeGetter, globalConst->GetHandledUndefined()); + SetSAccessor(bitVectorFuncPrototype, protoFieldIndex++, lengthGetter, globalConst->GetHandledUndefined()); + + SetSFunction(env, bitVectorFuncPrototype, "[Symbol.iterator]", + ContainersBitVector::GetIteratorObj, protoFieldIndex++, FunctionLength::ONE); + env->SetBitVectorPrototype(thread_, bitVectorFuncPrototype); + env->SetBitVectorFunction(thread_, bitVectorFunction); +} + + // todo: remove sendableName when refactor #define BUILTIN_SHARED_TYPED_ARRAY_DEFINE_INITIALIZE(Type, ctorName, TYPE, bytesPerElement, sendableName) \ void Builtins::InitializeS##Type(const JSHandle &env, const JSHandle &arrFuncClass) const \ diff --git a/ecmascript/builtins/tests/BUILD.gn b/ecmascript/builtins/tests/BUILD.gn index 5f96e926603a0a364eb5bdc8c3efac8b08015034..177a17f82ebb2bfee91e4faa5870aaaa2dd5077e 100755 --- a/ecmascript/builtins/tests/BUILD.gn +++ b/ecmascript/builtins/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("BuiltinsInternational_001_Test") { module_out_path = module_output_path diff --git a/ecmascript/builtins/tests/builtins_shared_array_test.cpp b/ecmascript/builtins/tests/builtins_shared_array_test.cpp index 77dc701a8945ae5f1fd7ca49102dbcbceb18de5b..22ecd3349978833a761a79aaeabc4b94f9b1452e 100644 --- a/ecmascript/builtins/tests/builtins_shared_array_test.cpp +++ b/ecmascript/builtins/tests/builtins_shared_array_test.cpp @@ -1636,4 +1636,267 @@ HWTEST_F_L0(BuiltinsSharedArrayTest, Every) EXPECT_EQ(JSSharedArrayIterator::Next(ecmaRuntimeCallInfo1), JSTaggedValue::Exception()); } +std::vector> DefineSharedArrProperty(JSThread* thread, JSHandle& obj, + std::vector& vals) +{ + std::vector> keys; + for (size_t i = 0; i < vals.size(); i++) { + keys.push_back(JSHandle(thread, JSTaggedValue(static_cast(i)))); + ARRAY_DEFINE_OWN_PROPERTY(obj, static_cast(i), vals[i]); + } + return keys; +} + +void CheckSharedArrKeyValue(JSThread* thread, JSHandle& valueHandle, PropertyDescriptor& descRes, + std::vector>& keys, std::vector& vals) +{ + for (size_t i = 0; i < vals.size(); i++) { + JSObject::GetOwnProperty(thread, valueHandle, keys[i], descRes); + ASSERT_EQ(descRes.GetValue().GetTaggedValue(), JSTaggedValue(vals[i])); + } +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, Of_One) +{ + auto ecmaVM = thread->GetEcmaVM(); + JSHandle env = ecmaVM->GetGlobalEnv(); + JSHandle array(env->GetSharedArrayFunction()); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo1->SetFunction(array.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetThis(array.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(1))); + ecmaRuntimeCallInfo1->SetCallArg(1, JSTaggedValue(static_cast(3))); + ecmaRuntimeCallInfo1->SetCallArg(2, JSTaggedValue(static_cast(5))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::Of(ecmaRuntimeCallInfo1); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue value(static_cast(result.GetRawData())); + ASSERT_TRUE(value.IsECMAObject()); + PropertyDescriptor descRes(thread); + JSHandle valueHandle(thread, value); + JSHandle key0(thread, JSTaggedValue(0)); + JSHandle key1(thread, JSTaggedValue(1)); + JSHandle key2(thread, JSTaggedValue(2)); + std::vector> keys{key0, key1, key2}; + std::vector vals{1, 3, 5}; + CheckSharedArrKeyValue(thread, valueHandle, descRes, keys, vals); +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, Of_Two) +{ + auto ecmaVM = thread->GetEcmaVM(); + JSHandle env = ecmaVM->GetGlobalEnv(); + JSHandle array(env->GetSharedArrayFunction()); + JSHandle globalObject(thread, env->GetGlobalObject()); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo1->SetFunction(array.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(2))); + ecmaRuntimeCallInfo1->SetCallArg(1, JSTaggedValue(static_cast(4))); + ecmaRuntimeCallInfo1->SetCallArg(2, JSTaggedValue(static_cast(6))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::Of(ecmaRuntimeCallInfo1); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue value(static_cast(result.GetRawData())); + ASSERT_TRUE(value.IsECMAObject()); + PropertyDescriptor descRes(thread); + JSHandle valueHandle(thread, value); + JSHandle key0(thread, JSTaggedValue(0)); + JSHandle key1(thread, JSTaggedValue(1)); + JSHandle key2(thread, JSTaggedValue(2)); + std::vector> keys{key0, key1, key2}; + std::vector vals{2, 4, 6}; + CheckSharedArrKeyValue(thread, valueHandle, descRes, keys, vals); +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, Of_Three) +{ + auto ecmaVM = thread->GetEcmaVM(); + JSHandle env = ecmaVM->GetGlobalEnv(); + JSHandle array(env->GetSharedArrayFunction()); + JSHandle globalObject(thread, env->GetGlobalObject()); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo1->SetFunction(array.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(2))); + ecmaRuntimeCallInfo1->SetCallArg(1, env->GetArrayFunction().GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(2, JSTaggedValue(static_cast(6))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::Of(ecmaRuntimeCallInfo1); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue value(static_cast(result.GetRawData())); + ASSERT_TRUE(value.IsException()); +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, Of_Four) +{ + auto ecmaVM = thread->GetEcmaVM(); + JSHandle env = ecmaVM->GetGlobalEnv(); + JSHandle array(env->GetArrayFunction()); + JSHandle globalObject(thread, env->GetGlobalObject()); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, array.GetTaggedValue(), 10); + ecmaRuntimeCallInfo1->SetFunction(array.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetThis(array.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(2))); + ecmaRuntimeCallInfo1->SetCallArg(1, env->GetArrayFunction().GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(2, JSTaggedValue(static_cast(6))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::Of(ecmaRuntimeCallInfo1); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue value(static_cast(result.GetRawData())); + ASSERT_TRUE(value.IsException()); +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, CopyWithin_One) +{ + std::vector descVals{1, 2, 3, 4, 5}; + JSHandle lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString(); + JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, + JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject()); + EXPECT_TRUE(arr != nullptr); + JSHandle obj(thread, arr); + EXPECT_EQ(JSSharedArray::GetProperty(thread, JSHandle(obj), lengthKeyHandle, + SCheckMode::SKIP).GetValue()->GetInt(), 0); + auto keys = DefineSharedArrProperty(thread, obj, descVals); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetThis(obj.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo1->SetCallArg(1, JSTaggedValue(static_cast(3))); + ecmaRuntimeCallInfo1->SetCallArg(2, JSTaggedValue(static_cast(5))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::CopyWithin(ecmaRuntimeCallInfo1); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue value(static_cast(result.GetRawData())); + ASSERT_TRUE(value.IsECMAObject()); + PropertyDescriptor descRes(thread); + JSHandle valueHandle(thread, value); + std::vector vals{4, 5, 3, 4, 5}; + CheckSharedArrKeyValue(thread, valueHandle, descRes, keys, vals); +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, CopyWithin_Two) +{ + std::vector descVals{1, 2, 3, 4, 5}; + JSHandle lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString(); + JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, + JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject()); + EXPECT_TRUE(arr != nullptr); + JSHandle obj(thread, arr); + EXPECT_EQ(JSSharedArray::GetProperty(thread, JSHandle(obj), lengthKeyHandle, + SCheckMode::SKIP).GetValue()->GetInt(), 0); + auto keys = DefineSharedArrProperty(thread, obj, descVals); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetThis(obj.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue::Undefined()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::CopyWithin(ecmaRuntimeCallInfo1); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue value(static_cast(result.GetRawData())); + ASSERT_TRUE(value.IsException()); +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, CopyWithin_Three) +{ + std::vector descVals{1, 2, 3, 4, 5}; + JSHandle lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString(); + JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, + JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject()); + EXPECT_TRUE(arr != nullptr); + JSHandle obj(thread, arr); + EXPECT_EQ(JSSharedArray::GetProperty(thread, JSHandle(obj), lengthKeyHandle, + SCheckMode::SKIP).GetValue()->GetInt(), 0); + auto keys = DefineSharedArrProperty(thread, obj, descVals); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetThis(obj.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo1->SetCallArg(1, JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetCallArg(2, JSTaggedValue::Undefined()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::CopyWithin(ecmaRuntimeCallInfo1); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue value(static_cast(result.GetRawData())); + ASSERT_TRUE(value.IsECMAObject()); + PropertyDescriptor descRes(thread); + JSHandle valueHandle(thread, value); + std::vector vals{1, 2, 3, 4, 5}; + CheckSharedArrKeyValue(thread, valueHandle, descRes, keys, vals); +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, CopyWithin_Four) +{ + std::vector descVals{1, 2, 3, 4, 5, 6}; + JSHandle lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString(); + JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, + JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject()); + EXPECT_TRUE(arr != nullptr); + JSHandle obj(thread, arr); + EXPECT_EQ(JSSharedArray::GetProperty(thread, JSHandle(obj), lengthKeyHandle, + SCheckMode::SKIP).GetValue()->GetInt(), 0); + auto keys = DefineSharedArrProperty(thread, obj, descVals); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetThis(obj.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(1))); + ecmaRuntimeCallInfo1->SetCallArg(1, JSTaggedValue(static_cast(-3))); + ecmaRuntimeCallInfo1->SetCallArg(2, JSTaggedValue(static_cast(5))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::CopyWithin(ecmaRuntimeCallInfo1); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue value(static_cast(result.GetRawData())); + ASSERT_TRUE(value.IsECMAObject()); + PropertyDescriptor descRes(thread); + JSHandle valueHandle(thread, value); + std::vector vals{1, 4, 5, 4, 5, 6}; + CheckSharedArrKeyValue(thread, valueHandle, descRes, keys, vals); +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, CopyWithin_Five) +{ + std::vector descVals{1, 2, 3, 4, 5, 6, 7, 8}; + JSHandle lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString(); + JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, + JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject()); + EXPECT_TRUE(arr != nullptr); + JSHandle obj(thread, arr); + EXPECT_EQ(JSSharedArray::GetProperty(thread, JSHandle(obj), lengthKeyHandle, + SCheckMode::SKIP).GetValue()->GetInt(), 0); + auto keys = DefineSharedArrProperty(thread, obj, descVals); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetThis(obj.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(4))); + ecmaRuntimeCallInfo1->SetCallArg(1, JSTaggedValue(static_cast(2))); + ecmaRuntimeCallInfo1->SetCallArg(2, JSTaggedValue(JSTaggedValue::Undefined())); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::CopyWithin(ecmaRuntimeCallInfo1); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue value(static_cast(result.GetRawData())); + ASSERT_TRUE(value.IsECMAObject()); + PropertyDescriptor descRes(thread); + JSHandle valueHandle(thread, value); + std::vector vals{1, 2, 3, 4, 3, 4, 5, 6}; + CheckSharedArrKeyValue(thread, valueHandle, descRes, keys, vals); +} + } // namespace panda::test diff --git a/ecmascript/common_enum.h b/ecmascript/common_enum.h index d10d217480f18649734f836366a6f29c2831aa7d..1ef15da1346df9965678d07cfbbc0a96542302f0 100644 --- a/ecmascript/common_enum.h +++ b/ecmascript/common_enum.h @@ -59,6 +59,7 @@ enum class GCReason : uint8_t { TRIGGER_BY_MEM_TOOLS, TRIGGER_BY_TASKPOOL, HINT_GC, + IDLE_NATIVE, OTHER }; diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index 65433644d7a1a2d716945ab9694ca07b716ce06e..e884ee3ae99027d32ccac52635e3552804cfa9f7 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -62,6 +62,7 @@ libark_jsoptimizer_sources = [ "baseline/baseline_stubs.cpp", "bc_call_signature.cpp", "builtins/builtins_array_stub_builder.cpp", + "builtins/builtins_array_stub_builder_next_optimization.cpp", "builtins/builtins_call_signature.cpp", "builtins/builtins_collator_stub_builder.cpp", "builtins/builtins_collection_stub_builder.cpp", diff --git a/ecmascript/compiler/access_object_stub_builder.cpp b/ecmascript/compiler/access_object_stub_builder.cpp index ea9e1cb38a5b1d8069af637ca6032a606c55958f..6afd047186eae9ccc964852d6e7f1c2157800987 100644 --- a/ecmascript/compiler/access_object_stub_builder.cpp +++ b/ecmascript/compiler/access_object_stub_builder.cpp @@ -292,7 +292,7 @@ GateRef AccessObjectStubBuilder::DeprecatedLoadObjByValue(GateRef glue, GateRef return ret; } -GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, +GateRef AccessObjectStubBuilder::StoreOwnByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback) { auto env = GetEnvironment(); @@ -305,11 +305,20 @@ GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver, DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); ICStubBuilder builder(this); - builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key, callback); + builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, IntToTaggedPtr(index), callback); builder.StoreICByValue(&result, &tryFastPath, &tryPreDump, &exit); Bind(&tryFastPath); { - result = SetPropertyByValue(glue, receiver, key, value, false, callback); + Label isHeapObject(env); + BRANCH(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath); + Bind(&isHeapObject); + Label notClassConstructor(env); + BRANCH(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); + Bind(¬ClassConstructor); + Label notClassPrototype(env); + BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype); + Bind(¬ClassPrototype); + result = SetPropertyByIndex(glue, receiver, index, value, true); BRANCH(TaggedIsHole(*result), &slowPath, &exit); } Bind(&tryPreDump); @@ -319,8 +328,9 @@ GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver, } Bind(&slowPath); { - result = CallRuntime( - glue, RTSTUB_ID(StoreICByValue), {profileTypeInfo, receiver, key, value, IntToTaggedInt(slotId)}); + result = CallRuntime(glue, + RTSTUB_ID(StoreOwnICByValue), + {profileTypeInfo, receiver, IntToTaggedInt(index), value, IntToTaggedInt(slotId)}); Jump(&exit); } Bind(&exit); @@ -329,7 +339,7 @@ GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver, return ret; } -GateRef AccessObjectStubBuilder::StoreOwnByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, +GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback) { auto env = GetEnvironment(); @@ -342,20 +352,11 @@ GateRef AccessObjectStubBuilder::StoreOwnByIndex(GateRef glue, GateRef receiver, DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); ICStubBuilder builder(this); - builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, IntToTaggedPtr(index), callback); + builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key, callback); builder.StoreICByValue(&result, &tryFastPath, &tryPreDump, &exit); Bind(&tryFastPath); { - Label isHeapObject(env); - BRANCH(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath); - Bind(&isHeapObject); - Label notClassConstructor(env); - BRANCH(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); - Bind(¬ClassConstructor); - Label notClassPrototype(env); - BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype); - Bind(¬ClassPrototype); - result = SetPropertyByIndex(glue, receiver, index, value, true); + result = SetPropertyByValue(glue, receiver, key, value, false, callback); BRANCH(TaggedIsHole(*result), &slowPath, &exit); } Bind(&tryPreDump); @@ -365,9 +366,8 @@ GateRef AccessObjectStubBuilder::StoreOwnByIndex(GateRef glue, GateRef receiver, } Bind(&slowPath); { - result = CallRuntime(glue, - RTSTUB_ID(StoreOwnICByValue), - {profileTypeInfo, receiver, IntToTaggedInt(index), value, IntToTaggedInt(slotId)}); + result = CallRuntime( + glue, RTSTUB_ID(StoreICByValue), {profileTypeInfo, receiver, key, value, IntToTaggedInt(slotId)}); Jump(&exit); } Bind(&exit); diff --git a/ecmascript/compiler/aot_compiler.cpp b/ecmascript/compiler/aot_compiler.cpp index 1f61682de3f80cf410289717d21572541c8befad..43fb555ccc1b0c48c00f0b983abf33d88a9b162d 100644 --- a/ecmascript/compiler/aot_compiler.cpp +++ b/ecmascript/compiler/aot_compiler.cpp @@ -222,7 +222,11 @@ int Main(const int argc, const char **argv) compilerStats.SetIsLiteCg(isEnableLiteCG); AOTFileGenerator generator(&log, &logList, &aotCompilationEnv, cOptions.triple_, isEnableLiteCG); - + if (runtimeOptions.IsTargetCompilerMode() && runtimeOptions.IsEnableAotCodeComment()) { + if (!generator.CreateAOTCodeCommentFile(cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AN)) { + LOG_COMPILER(ERROR) << "Generate aot code comment file failed."; + } + } passManager.CompileValidFiles(generator, ret, compilerStats); if (compilerStats.GetCompilerMethodCount() == 0) { return runtimeOptions.IsPartialCompilerMode() ? ERR_AN_EMPTY : ERR_OK; diff --git a/ecmascript/compiler/aot_compiler_preprocessor.h b/ecmascript/compiler/aot_compiler_preprocessor.h index 8c8f01a5cece5f5c147d41bd445900dcb4f7508e..c14c36ea7362d89561320e0610ca57d0c894d622 100644 --- a/ecmascript/compiler/aot_compiler_preprocessor.h +++ b/ecmascript/compiler/aot_compiler_preprocessor.h @@ -92,6 +92,7 @@ struct CompilationOptions { bool isEnableInductionVariableAnalysis_ {false}; bool isEnableVerifierPass_ {true}; bool isEnableBaselinePgo_ {false}; + bool enableAotCodeComment_ {false}; std::map> optionSelectMethods_; std::map> optionSkipMethods_; }; diff --git a/ecmascript/compiler/aot_file/aot_file_info.h b/ecmascript/compiler/aot_file/aot_file_info.h index ecc868578273f9eb551c3c65531a114804239b68..888a70cfa54833fb24fd501c856e414a937ef0a3 100644 --- a/ecmascript/compiler/aot_file/aot_file_info.h +++ b/ecmascript/compiler/aot_file/aot_file_info.h @@ -36,6 +36,7 @@ public: virtual ~AOTFileInfo() = default; static constexpr uint32_t TEXT_SEC_ALIGN = 16; + static constexpr uint32_t RODATA_SEC_ALIGN = 16; static constexpr uint32_t DATA_SEC_ALIGN = 8; static constexpr uint32_t PAGE_ALIGN = 4096; diff --git a/ecmascript/compiler/aot_file/aot_file_manager.cpp b/ecmascript/compiler/aot_file/aot_file_manager.cpp index 4a143ee5bc9b7ed3d63b3781f0807f6b139112b2..253080c985fabca7ccce8d207756859caddf9e2e 100644 --- a/ecmascript/compiler/aot_file/aot_file_manager.cpp +++ b/ecmascript/compiler/aot_file/aot_file_manager.cpp @@ -18,6 +18,7 @@ #include "ecmascript/compiler/aot_snapshot/aot_snapshot_constants.h" #include "ecmascript/js_file_path.h" +#include "ecmascript/message_string.h" #include "ecmascript/ohos/framework_helper.h" #include "ecmascript/ohos/ohos_preload_app_info.h" #include "ecmascript/snapshot/mem/snapshot.h" diff --git a/ecmascript/compiler/aot_file/elf_builder.cpp b/ecmascript/compiler/aot_file/elf_builder.cpp index 21522376ad73fb4291df79e58f11b35118a464bb..1eca0fd5fc11f76d483492d7d316bdd8ea9177c1 100644 --- a/ecmascript/compiler/aot_file/elf_builder.cpp +++ b/ecmascript/compiler/aot_file/elf_builder.cpp @@ -379,7 +379,7 @@ void ElfBuilder::MergeTextSections(std::ofstream &file, curInfo.textSize = curSecSize; curSecOffset += curSecSize; if (rodataSizeAfterText != 0) { - curSecOffset = AlignUp(curSecOffset, AOTFileInfo::DATA_SEC_ALIGN); + curSecOffset = AlignUp(curSecOffset, AOTFileInfo::RODATA_SEC_ALIGN); file.seekp(curSecOffset); file.write(reinterpret_cast(rodataAddrAfterText), rodataSizeAfterText); curInfo.rodataSizeAfterText = rodataSizeAfterText; diff --git a/ecmascript/compiler/aot_file/elf_reader.cpp b/ecmascript/compiler/aot_file/elf_reader.cpp index fe5698394604ccea6d78deabe19434459cf6bb0c..f912259be88baefa7a9273115cb2e4f6026a2085 100644 --- a/ecmascript/compiler/aot_file/elf_reader.cpp +++ b/ecmascript/compiler/aot_file/elf_reader.cpp @@ -293,7 +293,7 @@ void ElfReader::SeparateTextSections(std::vector &des, des[i].SetSecAddrAndSize(ElfSecName::TEXT, secAddr + secOffset, textSize); secOffset += textSize; if (rodataSizeAfterText != 0) { - secOffset = AlignUp(secOffset, AOTFileInfo::DATA_SEC_ALIGN); + secOffset = AlignUp(secOffset, AOTFileInfo::RODATA_SEC_ALIGN); secOffset += rodataSizeAfterText; } } @@ -365,7 +365,7 @@ void ElfReader::SeparateTextSections(BinaryBufferParser &parser, des[i].SetSecAddrAndSize(ElfSecName::TEXT, secAddr + secOffset, textSize); secOffset += textSize; if (rodataSizeAfterText != 0) { - secOffset = AlignUp(secOffset, AOTFileInfo::DATA_SEC_ALIGN); + secOffset = AlignUp(secOffset, AOTFileInfo::RODATA_SEC_ALIGN); parser.ParseBuffer(reinterpret_cast(secAddr + secOffset), rodataSizeAfterText, curShOffset + secOffset); secOffset += rodataSizeAfterText; diff --git a/ecmascript/compiler/aot_file/stub_file_info.cpp b/ecmascript/compiler/aot_file/stub_file_info.cpp index fc0a8fa6e358c1358fadfccf3ced411de19330be..3a990cbd46141081cbf824a331c75262f86c2c9d 100644 --- a/ecmascript/compiler/aot_file/stub_file_info.cpp +++ b/ecmascript/compiler/aot_file/stub_file_info.cpp @@ -31,6 +31,10 @@ void StubFileInfo::Save(const std::string &filename, Triple triple) } std::ofstream file(realPath.c_str(), std::ofstream::binary); + if (!file.is_open()) { + LOG_ECMA(FATAL) << "Failed to open file : " << realPath.c_str(); + UNREACHABLE(); + } ASSERT(GetCodeUnitsNum() == ASMSTUB_MODULE_NUM); SetStubNum(entries_.size()); ModuleSectionDes &des = des_[0]; diff --git a/ecmascript/compiler/aot_snapshot/snapshot_global_data.h b/ecmascript/compiler/aot_snapshot/snapshot_global_data.h index de3184cbe5080227b694e0ddeb47e92f226399d5..0ccf621210afcf159455ddcb5648b413ccd784e1 100644 --- a/ecmascript/compiler/aot_snapshot/snapshot_global_data.h +++ b/ecmascript/compiler/aot_snapshot/snapshot_global_data.h @@ -180,11 +180,6 @@ public: return constantIndexInfo_; } - JSTaggedValue GetProtoTransTableInfo() const - { - return protoTransTableInfo_; - } - JSTaggedValue GetObjectLiteralHClassCache() const { if (hclassInfo_.IsTaggedArray()) { @@ -195,6 +190,11 @@ public: return JSTaggedValue::Undefined(); } + JSTaggedValue GetProtoTransTableInfo() const + { + return protoTransTableInfo_; + } + void StoreHClassInfo(JSHandle info) { hclassInfo_ = info.GetTaggedValue(); diff --git a/ecmascript/compiler/async_function_lowering.h b/ecmascript/compiler/async_function_lowering.h index fb05bfaf5496de0c649f04430bc09aae6521802f..adca55226c7621a35c709e74656297123d0ef8a2 100644 --- a/ecmascript/compiler/async_function_lowering.h +++ b/ecmascript/compiler/async_function_lowering.h @@ -18,7 +18,9 @@ #include "ecmascript/compiler/bytecode_circuit_builder.h" #include "ecmascript/compiler/circuit.h" +#include "ecmascript/compiler/circuit_builder-inl.h" #include "ecmascript/compiler/circuit_builder.h" +#include "ecmascript/mem/chunk_containers.h" namespace panda::ecmascript::kungfu { class AsyncFunctionLowering { diff --git a/ecmascript/compiler/base/depend_chain_helper.h b/ecmascript/compiler/base/depend_chain_helper.h index 02a2f1cf6720b165dc20835449a79387bee50e68..ccfc5dba95c51fc5df280de7a10805beaf96fbda 100644 --- a/ecmascript/compiler/base/depend_chain_helper.h +++ b/ecmascript/compiler/base/depend_chain_helper.h @@ -64,7 +64,7 @@ public: head_ = other->head_; size_ = other->size_; } - + GateRef GetHeadGate() { return head_->gate; diff --git a/ecmascript/compiler/baseline/baseline_compiler.cpp b/ecmascript/compiler/baseline/baseline_compiler.cpp index f3a6d90fb1fed935368a0bbb3f39034c223bca6a..bbf105391d4106533c21db8307faa15e9d3083d4 100644 --- a/ecmascript/compiler/baseline/baseline_compiler.cpp +++ b/ecmascript/compiler/baseline/baseline_compiler.cpp @@ -295,7 +295,8 @@ BYTECODE_BASELINE_HANDLER_IMPLEMENT(LDINFINITY) (void)bytecodeArray; LOG_INST() << " ldinfinity " << std::hex << base::POSITIVE_INFINITY; - GetBaselineAssembler().Move(SpecialRegister::ACC_REGISTER, Immediate(JSTaggedValue(base::POSITIVE_INFINITY).GetRawData())); + GetBaselineAssembler().Move(SpecialRegister::ACC_REGISTER, + Immediate(JSTaggedValue(base::POSITIVE_INFINITY).GetRawData())); } BYTECODE_BASELINE_HANDLER_IMPLEMENT(LDNULL) @@ -5633,7 +5634,7 @@ BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_LDSENDABLEEXTERNALMODULEVAR_PREF (void)bytecodeArray; } -BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDELDSENDABLEEXTERNALMODULEVAR_PREF_IMM16) +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4) { (void)bytecodeArray; } @@ -5643,17 +5644,17 @@ BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_NEWSENDABLEENV_PREF_IMM8) (void)bytecodeArray; } -BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDENEWSENDABLEENV_PREF_IMM16) +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_STSENDABLEVAR_PREF_IMM8_IMM8) { (void)bytecodeArray; } -BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_STSENDABLEVAR_PREF_IMM4_IMM4) +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16) { (void)bytecodeArray; } -BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_STSENDABLEVAR_PREF_IMM8_IMM8) +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_STSENDABLEVAR_PREF_IMM4_IMM4) { (void)bytecodeArray; } @@ -5663,17 +5664,17 @@ BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDESTSENDABLEVAR_PREF_IMM16_IMM (void)bytecodeArray; } -BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4) +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8) { (void)bytecodeArray; } -BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8) +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDENEWSENDABLEENV_PREF_IMM16) { (void)bytecodeArray; } -BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16) +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDELDSENDABLEEXTERNALMODULEVAR_PREF_IMM16) { (void)bytecodeArray; } diff --git a/ecmascript/compiler/baseline/baseline_stubs.cpp b/ecmascript/compiler/baseline/baseline_stubs.cpp index dd4d5a2f5b909d1d1ee94c085dd4f6fdb5a5ab7f..951260d0e407f6485e116c4f4a4235cdd4d22464 100644 --- a/ecmascript/compiler/baseline/baseline_stubs.cpp +++ b/ecmascript/compiler/baseline/baseline_stubs.cpp @@ -3970,7 +3970,7 @@ void BaselineNewobjrangeImm16Imm8V8StubBuilder::GenerateCircuit() Bind(&ctorNotBase); { GateRef argv = PtrAdd(sp, PtrMul( - PtrAdd(firstArgRegIdx, firstArgOffset), IntPtr(8))); // 8: skip function + PtrAdd(firstArgRegIdx, firstArgOffset), IntPtr(8))); // 8: skip function GateRef jumpSize = IntPtr(-BytecodeInstruction::Size(BytecodeInstruction::Format::IMM16_IMM8_V8)); METHOD_ENTRY_ENV_DEFINED(ctor); JSCallArgs callArgs(JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV); diff --git a/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp index e664078452ba330779781c25fa5d54d21ab08c8e..b2ca50d5caa35fa0ad12cc3dfdcd57f145969e21 100644 --- a/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#include "ecmascript/base/config.h" #include "ecmascript/compiler/builtins/builtins_array_stub_builder.h" #include "ecmascript/builtins/builtins_string.h" @@ -169,6 +169,9 @@ void BuiltinsArrayStubBuilder::With(GateRef glue, GateRef thisValue, GateRef num void BuiltinsArrayStubBuilder::Unshift(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result, Label *exit, Label *slowPath) { +#if ENABLE_NEXT_OPTIMIZATION + UnshiftOptimised(glue, thisValue, numArgs, result, exit, slowPath); +#else auto env = GetEnvironment(); Label isHeapObject(env); Label isJsArray(env); @@ -176,10 +179,12 @@ void BuiltinsArrayStubBuilder::Unshift(GateRef glue, GateRef thisValue, GateRef Label notOverRange(env); Label numNotEqualZero(env); Label numLessThanOrEqualThree(env); - Label afterCopy(env); + Label loopHead(env); + Label next(env); + Label loopEnd(env); + Label loopExit(env); Label grow(env); Label setValue(env); - Label matchCls(env); Label numEqual2(env); Label numEqual3(env); Label threeArgs(env); @@ -190,9 +195,6 @@ void BuiltinsArrayStubBuilder::Unshift(GateRef glue, GateRef thisValue, GateRef Bind(&isJsArray); BRANCH(IsStableJSArray(glue, thisValue), &isStableJsArray, slowPath); Bind(&isStableJsArray); - GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); BRANCH(Int64GreaterThan(numArgs, IntPtr(0)), &numNotEqualZero, slowPath); Bind(&numNotEqualZero); GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); @@ -203,48 +205,69 @@ void BuiltinsArrayStubBuilder::Unshift(GateRef glue, GateRef thisValue, GateRef // 3 : max param num BRANCH(Int64LessThanOrEqual(numArgs, IntPtr(3)), &numLessThanOrEqualThree, slowPath); Bind(&numLessThanOrEqualThree); - GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(GetElementsArray(thisValue))); - BRANCH(Int64GreaterThan(newLen, capacity), &grow, &setValue); - Bind(&grow); { - GrowElementsCapacity(glue, thisValue, TruncInt64ToInt32(newLen)); - Jump(&setValue); - } - Bind(&setValue); - { - Label elementsKindEnabled(env); - GateRef elements = GetElementsArray(thisValue); - GateRef arrayStart = GetDataPtrInTaggedArray(elements); - GateRef moveTo = PtrAdd(arrayStart, PtrMul(numArgs, IntPtr(JSTaggedValue::TaggedTypeSize()))); - GateRef isElementsKindEnabled = IsEnableElementsKind(glue); - Label isIntOrNumber(env); - Label isTagged(env); - BRANCH_NO_WEIGHT(isElementsKindEnabled, &elementsKindEnabled, &isTagged); - Bind(&elementsKindEnabled); + DEFVARIABLE(elements, VariableType::JS_ANY(), GetElementsArray(thisValue)); + GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(*elements)); + BRANCH(Int64GreaterThan(newLen, capacity), &grow, &setValue); + Bind(&grow); { - GateRef kind = GetElementsKindFromHClass(LoadHClass(thisValue)); - GateRef isInt = LogicAndBuilder(env) - .And(Int32GreaterThanOrEqual(kind, Int32(static_cast(ElementsKind::INT)))) - .And(Int32LessThanOrEqual(kind, Int32(static_cast(ElementsKind::HOLE_INT)))) - .Done(); - GateRef isNumber = LogicAndBuilder(env) - .And(Int32GreaterThanOrEqual(kind, Int32(static_cast(ElementsKind::NUMBER)))) - .And(Int32LessThanOrEqual(kind, Int32(static_cast(ElementsKind::HOLE_NUMBER)))) - .Done(); - GateRef isIntOrNumberKind = LogicOrBuilder(env).Or(isInt).Or(isNumber).Done(); - BRANCH_NO_WEIGHT(isIntOrNumberKind, &isIntOrNumber, &isTagged); - Bind(&isIntOrNumber); - { - ArrayCopy(glue, arrayStart, moveTo, TruncInt64ToInt32(thisLen), - MemoryAttribute::NoBarrier()); - Jump(&afterCopy); - } - Bind(&isTagged); + elements = CallRuntime(glue, RTSTUB_ID(JSObjectGrowElementsCapacity), {thisValue, IntToTaggedInt(newLen)}); + Jump(&setValue); + } + Bind(&setValue); + { + DEFVARIABLE(fromKey, VariableType::INT64(), Int64Sub(thisLen, Int64(1))); + DEFVARIABLE(toKey, VariableType::INT64(), Int64Sub(newLen, Int64(1))); + DEFVARIABLE(ele, VariableType::JS_ANY(), Hole()); + Label eleIsHole(env); + Label hasProperty(env); + Label notHasProperty(env); + Label hasException0(env); + Label notHasException0(env); + Jump(&loopHead); + LoopBegin(&loopHead); { - ArrayCopy(glue, arrayStart, moveTo, TruncInt64ToInt32(thisLen)); - Jump(&afterCopy); + BRANCH(Int64GreaterThanOrEqual(*fromKey, Int64(0)), &next, &loopExit); + Bind(&next); + { + ele = GetTaggedValueWithElementsKind(thisValue, *fromKey); + BRANCH(TaggedIsHole(*ele), &eleIsHole, ¬HasException0); + Bind(&eleIsHole); + { + GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), + { thisValue, IntToTaggedInt(*fromKey) }); + BRANCH(TaggedIsTrue(hasProp), &hasProperty, ¬HasProperty); + Bind(&hasProperty); + { + ele = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*fromKey), + ProfileOperation()); + BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); + Bind(&hasException0); + { + result->WriteVariable(Exception()); + Jump(exit); + } + } + Bind(¬HasProperty); + { + SetValueWithElementsKind(glue, thisValue, Hole(), *toKey, Boolean(false), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd); + } + } + Bind(¬HasException0); + { + SetValueWithElementsKind(glue, thisValue, *ele, *toKey, Boolean(false), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd); + } + } } - Bind(&afterCopy); + Bind(&loopEnd); + fromKey = Int64Sub(*fromKey, Int64(1)); + toKey = Int64Sub(*toKey, Int64(1)); + LoopEnd(&loopHead); + Bind(&loopExit); { GateRef value0 = GetCallArg0(numArgs); // 0 : the first Element position @@ -280,6 +303,7 @@ void BuiltinsArrayStubBuilder::Unshift(GateRef glue, GateRef thisValue, GateRef } } } +#endif } void BuiltinsArrayStubBuilder::Shift(GateRef glue, GateRef thisValue, @@ -537,13 +561,16 @@ void BuiltinsArrayStubBuilder::Filter(GateRef glue, GateRef thisValue, GateRef n auto env = GetEnvironment(); Label isHeapObject(env); Label isJsArray(env); + Label isprototypeJsArray(env); Label defaultConstr(env); BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); Bind(&isHeapObject); - GateRef thisValueAndProtoIsJSArray = LogicAndBuilder(env).And(IsJsArray(thisValue)) - .And(IsJsArray(StubBuilder::GetPrototype(glue, thisValue))).Done(); - BRANCH(thisValueAndProtoIsJSArray, &isJsArray, slowPath); + BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); Bind(&isJsArray); + GateRef prototype = StubBuilder::GetPrototype(glue, thisValue); + GateRef protoIsJSArray = LogicAndBuilder(env).And(TaggedIsHeapObject(prototype)).And(IsJsArray(prototype)).Done(); + BRANCH(protoIsJSArray, &isprototypeJsArray, slowPath); + Bind(&isprototypeJsArray); BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); Bind(&defaultConstr); @@ -568,7 +595,7 @@ void BuiltinsArrayStubBuilder::Filter(GateRef glue, GateRef thisValue, GateRef n Bind(¬EmptyArray); BRANCH(Int64GreaterThan(len, Int64(JSObject::MAX_GAP)), slowPath, ¬OverFlow); Bind(¬OverFlow); - + GateRef argHandle = GetCallArg1(numArgs); GateRef newArray = NewArray(glue, len); GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); @@ -700,13 +727,16 @@ void BuiltinsArrayStubBuilder::Map(GateRef glue, GateRef thisValue, GateRef numA auto env = GetEnvironment(); Label isHeapObject(env); Label isJsArray(env); + Label isprototypeJsArray(env); Label defaultConstr(env); BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); Bind(&isHeapObject); - GateRef thisValueAndProtoIsJSArray = LogicAndBuilder(env).And(IsJsArray(thisValue)) - .And(IsJsArray(StubBuilder::GetPrototype(glue, thisValue))).Done(); - BRANCH(thisValueAndProtoIsJSArray, &isJsArray, slowPath); + BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); Bind(&isJsArray); + GateRef prototype = StubBuilder::GetPrototype(glue, thisValue); + GateRef protoIsJSArray = LogicAndBuilder(env).And(TaggedIsHeapObject(prototype)).And(IsJsArray(prototype)).Done(); + BRANCH(protoIsJSArray, &isprototypeJsArray, slowPath); + Bind(&isprototypeJsArray); BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); Bind(&defaultConstr); @@ -832,7 +862,6 @@ void BuiltinsArrayStubBuilder::ForEach([[maybe_unused]] GateRef glue, GateRef th { auto env = GetEnvironment(); Label thisExists(env); - Label matchCls(env); Label isHeapObject(env); Label isGeneric(env); Label isJsArray(env); @@ -852,9 +881,6 @@ void BuiltinsArrayStubBuilder::ForEach([[maybe_unused]] GateRef glue, GateRef th Bind(&isStability); BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); - GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); Label arg0HeapObject(env); Label callable(env); Label thisIsStable(env); @@ -1440,6 +1466,9 @@ void BuiltinsArrayStubBuilder::ToSorted(GateRef glue, GateRef thisValue, GateRef BuiltinsArrayStubBuilder::DoSort(GateRef glue, GateRef receiver, GateRef receiverState, Variable *result, Label *exit, Label *slowPath, GateRef hir) { +#if ENABLE_NEXT_OPTIMIZATION + return DoSortOptimised(glue, receiver, receiverState, result, exit, slowPath, hir); +#else auto env = GetEnvironment(); Label entry(env); env->SubCfgEntry(&entry); @@ -1519,42 +1548,17 @@ GateRef BuiltinsArrayStubBuilder::DoSort(GateRef glue, GateRef receiver, GateRef Bind(&afterGettingmiddleValue); { Label isInt(env); - Label notInt(env); - Label exchangeIndex(env); GateRef middleVal = *middleValue; GateRef presentVal = *presentValue; - DEFVARIABLE(compareResult, VariableType::INT32(), Int32(0)); - GateRef intBool = LogicAndBuilder(env) - .And(TaggedIsInt(middleVal)) - .And(TaggedIsInt(presentVal)) - .Done(); - BRANCH(intBool, &isInt, ¬Int); + BRANCH(LogicAndBuilder(env).And(TaggedIsInt(middleVal)).And(TaggedIsInt(presentVal)).Done(), + &isInt, slowPath); Bind(&isInt); { - compareResult = + GateRef compareResult = CallNGCRuntime(glue, RTSTUB_ID(FastArraySort), {*middleValue, *presentValue}); - Jump(&exchangeIndex); - } - Bind(¬Int); - { - Label isString(env); - GateRef strBool = LogicAndBuilder(env) - .And(TaggedIsString(middleVal)) - .And(TaggedIsString(presentVal)) - .Done(); - BRANCH(strBool, &isString, slowPath); - Bind(&isString); - { - compareResult = CallNGCRuntime(glue, - RTSTUB_ID(FastArraySortString), {glue, *middleValue, *presentValue}); - Jump(&exchangeIndex); - } - } - Bind(&exchangeIndex); - { Label less0(env); Label greater0(env); - BRANCH(Int32LessThanOrEqual(*compareResult, Int32(0)), &less0, &greater0); + BRANCH(Int32LessThanOrEqual(compareResult, Int32(0)), &less0, &greater0); Bind(&greater0); { endIndex = middleIndex; @@ -1656,6 +1660,7 @@ GateRef BuiltinsArrayStubBuilder::DoSort(GateRef glue, GateRef receiver, GateRef Bind(&loopExit); env->SubCfgExit(); return receiver; +#endif } void BuiltinsArrayStubBuilder::Reduce(GateRef glue, GateRef thisValue, GateRef numArgs, @@ -1888,14 +1893,14 @@ void BuiltinsArrayStubBuilder::FastReverse(GateRef glue, GateRef thisValue, Gate if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) { GateRef lower = GetValueFromMutantTaggedArray(elements, *i); GateRef upper = GetValueFromMutantTaggedArray(elements, *j); - FastSetValueWithElementsKind(glue, elements, upper, *i, kind); - FastSetValueWithElementsKind(glue, elements, lower, *j, kind); + FastSetValueWithElementsKind(glue, thisValue, elements, upper, *i, kind); + FastSetValueWithElementsKind(glue, thisValue, elements, lower, *j, kind); Jump(&loopEnd); } else { GateRef lower = GetValueFromTaggedArray(elements, *i); GateRef upper = GetValueFromTaggedArray(elements, *j); - FastSetValueWithElementsKind(glue, elements, upper, *i, kind); - FastSetValueWithElementsKind(glue, elements, lower, *j, kind); + FastSetValueWithElementsKind(glue, thisValue, elements, upper, *i, kind); + FastSetValueWithElementsKind(glue, thisValue, elements, lower, *j, kind); Jump(&loopEnd); } } @@ -1912,6 +1917,9 @@ void BuiltinsArrayStubBuilder::FastReverse(GateRef glue, GateRef thisValue, Gate void BuiltinsArrayStubBuilder::ToReversed(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs, Variable* result, Label* exit, Label* slowPath) { +#if ENABLE_NEXT_OPTIMIZATION + ToReversedOptimised(glue, thisValue, numArgs, result, exit, slowPath); +#else auto env = GetEnvironment(); Label isHeapObject(env); Label isJsArray(env); @@ -1928,142 +1936,142 @@ void BuiltinsArrayStubBuilder::ToReversed(GateRef glue, GateRef thisValue, [[may Bind(&isStability); BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); - Label ElementsKindEnabled(env); - Label ElementsKindDisabled(env); - Label next(env); - GateRef isElementsKindEnabled = IsEnableElementsKind(glue); - DEFVARIABLE(receiver, VariableType::JS_ANY(), Hole()); - GateRef kind = GetElementsKindFromHClass(LoadHClass(thisValue)); + GateRef thisArrLen = GetArrayLength(thisValue); - BRANCH_UNLIKELY(isElementsKindEnabled, &ElementsKindEnabled, &ElementsKindDisabled); - Bind(&ElementsKindEnabled); - { - Label newArrayIsTagged(env); - Label reuseOldHClass(env); - BRANCH_NO_WEIGHT(ElementsKindHasHole(kind), &newArrayIsTagged, &reuseOldHClass); - Bind(&newArrayIsTagged); - { - // If the kind has hole, we know it must be transited to TAGGED kind; - // There will be no hole in the new array because hole will be converted to undefined. - GateRef newHClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue, - ConstantIndex::ELEMENT_TAGGED_HCLASS_INDEX); - receiver = NewEmptyArrayWithHClass(glue, newHClass); - Jump(&next); - } - Bind(&reuseOldHClass); - { - receiver = NewEmptyArrayWithHClass(glue, LoadHClass(thisValue)); - Jump(&next); - } - } - Bind(&ElementsKindDisabled); - { - receiver = NewArray(glue, Int64(0)); - Jump(&next); - } - Bind(&next); - GrowElementsCapacity(glue, *receiver, thisArrLen); - SetArrayLength(glue, *receiver, thisArrLen); - - Label afterReverse(env); - Label isIntOrNumber(env); - Label notIntOrNumber(env); - Label isTagged(env); - Label isHoleOrIntOrNumber(env); - Label elementsKindEnabled(env); - BRANCH_NO_WEIGHT(isElementsKindEnabled, &elementsKindEnabled, &isTagged); - Bind(&elementsKindEnabled); - { - GateRef intOrNumber = LogicOrBuilder(env) - .Or(Int32Equal(kind, Int32(static_cast(ElementsKind::INT)))) - .Or(Int32Equal(kind, Int32(static_cast(ElementsKind::NUMBER)))) - .Done(); - BRANCH_NO_WEIGHT(intOrNumber, &isIntOrNumber, ¬IntOrNumber); - Bind(¬IntOrNumber); - { - GateRef holeOrIntOrNumber = LogicOrBuilder(env) - .Or(Int32Equal(kind, Int32(static_cast(ElementsKind::HOLE_INT)))) - .Or(Int32Equal(kind, Int32(static_cast(ElementsKind::HOLE_NUMBER)))) - .Done(); - BRANCH_NO_WEIGHT(holeOrIntOrNumber, &isHoleOrIntOrNumber, &isTagged); - } - } - Bind(&isTagged); - { - // The old array and new array are both TaggedArray, so load and store the element directly. - // And barrier is needed. - DoReverse(glue, thisValue, *receiver, true, false, MemoryAttribute::Default()); - Jump(&afterReverse); - } - Bind(&isIntOrNumber); - { - // The old array and new array are both MutantTaggedArray, so load and store the element directly. - // And barrier is not needed. - DoReverse(glue, thisValue, *receiver, false, false, MemoryAttribute::NoBarrier()); - Jump(&afterReverse); - } - Bind(&isHoleOrIntOrNumber); - { - // The old array is mutant, but new array is TaggedArray, so load the value from old array with - // elements kind. And set it to new array directly, And barrier is not needed. - DoReverse(glue, thisValue, *receiver, true, true, MemoryAttribute::NoBarrier()); - Jump(&afterReverse); - } - Bind(&afterReverse); - result->WriteVariable(*receiver); + GateRef receiver = NewArray(glue, Int32(0)); + GrowElementsCapacity(glue, receiver, thisArrLen); + SetArrayLength(glue, receiver, thisArrLen); + result->WriteVariable(DoReverse(glue, thisValue, receiver, Boolean(true), result, exit)); Jump(exit); +#endif } -void BuiltinsArrayStubBuilder::DoReverse(GateRef glue, GateRef fromArray, GateRef toArray, bool holeToUndefined, - bool getWithKind, MemoryAttribute mAttr) +GateRef BuiltinsArrayStubBuilder::DoReverse(GateRef glue, GateRef thisValue, GateRef receiver, + GateRef receiverState, Variable *result, Label *exit) { auto env = GetEnvironment(); Label entry(env); env->SubCfgEntry(&entry); + DEFVARIABLE(i, VariableType::INT64(), Int64(0)); + DEFVARIABLE(j, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(GetArrayLength(thisValue)), Int64(1))); + Label loopHead(env); + Label loopEnd(env); + Label next(env); Label loopExit(env); - Label begin(env); - Label body(env); - Label endLoop(env); - - GateRef fromElements = GetElementsArray(fromArray); - GateRef toElements = GetElementsArray(toArray); - GateRef thisArrLen = GetArrayLength(fromArray); - DEFVARIABLE(index, VariableType::INT32(), Int32(0)); - GateRef endIndex = Int32Sub(thisArrLen, Int32(1)); - Jump(&begin); - LoopBegin(&begin); + + Jump(&loopHead); + LoopBegin(&loopHead); { - BRANCH_LIKELY(Int32UnsignedLessThan(*index, thisArrLen), &body, &loopExit); - Bind(&body); + DEFVARIABLE(lower, VariableType::JS_ANY(), Hole()); + DEFVARIABLE(upper, VariableType::JS_ANY(), Hole()); + Label lowerValueIsHole(env); + Label afterGettingLower(env); + Label lowerHasProperty(env); + Label lowerHasException0(env); + Label upperValueIsHole(env); + Label afterGettingUpper(env); + Label upperHasProperty(env); + Label upperHasException0(env); + Label receiverIsNew(env); + Label receiverIsOrigin(env); + Label lowerIsHole(env); + Label lowerIsNotHole(env); + Label dealWithUpper(env); + Label upperIsHole(env); + Label upperIsNotHole(env); + BRANCH(Int64LessThanOrEqual(*i, *j), &next, &loopExit); + Bind(&next); { - GateRef toIndex = Int32Sub(endIndex, *index); - // The old array and new array are both TaggedArray, so load and store the element directly. - // And barrier is needed. - GateRef value = getWithKind ? GetTaggedValueWithElementsKind(fromArray, *index) - : GetValueFromTaggedArray(fromElements, *index); - if (holeToUndefined) { - Label isHole(env); - Label isNotHole(env); - BRANCH_UNLIKELY(TaggedIsHole(value), &isHole, &isNotHole); - Bind(&isHole); + lower = GetTaggedValueWithElementsKind(thisValue, *i); + BRANCH(TaggedIsHole(*lower), &lowerValueIsHole, &afterGettingLower); + Bind(&lowerValueIsHole); + { + GateRef lowerHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); + BRANCH(TaggedIsTrue(lowerHasProp), &lowerHasProperty, &afterGettingLower); + Bind(&lowerHasProperty); { - // The return value of toReversed() is never sparse. - // Empty slots become undefined in the returned array. - SetValueToTaggedArray(VariableType::JS_ANY(), glue, toElements, toIndex, Undefined(), - MemoryAttribute::NoBarrier()); - Jump(&endLoop); + lower = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); + BRANCH(HasPendingException(glue), &lowerHasException0, &afterGettingLower); + Bind(&lowerHasException0); + { + result->WriteVariable(Exception()); + Jump(exit); + } + } + } + Bind(&afterGettingLower); + { + upper = GetTaggedValueWithElementsKind(thisValue, *j); + BRANCH(TaggedIsHole(*upper), &upperValueIsHole, &afterGettingUpper); + Bind(&upperValueIsHole); + { + GateRef upperHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*j) }); + BRANCH(TaggedIsTrue(upperHasProp), &upperHasProperty, &afterGettingUpper); + Bind(&upperHasProperty); + { + upper = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*j), ProfileOperation()); + BRANCH(HasPendingException(glue), &upperHasException0, &afterGettingUpper); + } + Bind(&upperHasException0); + { + result->WriteVariable(Exception()); + Jump(exit); + } + } + Bind(&afterGettingUpper); + { + BRANCH(receiverState, &receiverIsNew, &receiverIsOrigin); + Bind(&receiverIsNew); + { + BRANCH(TaggedIsHole(*lower), &lowerIsHole, &lowerIsNotHole); + Bind(&lowerIsHole); + { + SetValueWithElementsKind(glue, receiver, Undefined(), *j, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&dealWithUpper); + } + Bind(&lowerIsNotHole); + { + SetValueWithElementsKind(glue, receiver, *lower, *j, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&dealWithUpper); + } + Bind(&dealWithUpper); + { + BRANCH(TaggedIsHole(*upper), &upperIsHole, &upperIsNotHole); + Bind(&upperIsHole); + { + SetValueWithElementsKind(glue, receiver, Undefined(), *i, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd); + } + Bind(&upperIsNotHole); + { + SetValueWithElementsKind(glue, receiver, *upper, *i, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd); + } + } + } + Bind(&receiverIsOrigin); + { + SetValueWithElementsKind(glue, receiver, *upper, *i, Boolean(false), + Int32(static_cast(ElementsKind::NONE))); + SetValueWithElementsKind(glue, receiver, *lower, *j, Boolean(false), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd); + } } - Bind(&isNotHole); } - SetValueToTaggedArray(VariableType::JS_ANY(), glue, toElements, toIndex, value, mAttr); - Jump(&endLoop); } } - Bind(&endLoop); - index = Int32Add(*index, Int32(1)); - LoopEnd(&begin); + Bind(&loopEnd); + i = Int64Add(*i, Int64(1)); + j = Int64Sub(*j, Int64(1)); + LoopEnd(&loopHead); Bind(&loopExit); env->SubCfgExit(); + return receiver; } GateRef BuiltinsArrayStubBuilder::IsJsArrayWithLengthLimit(GateRef glue, GateRef object, @@ -2392,6 +2400,101 @@ void BuiltinsArrayStubBuilder::FindIndex(GateRef glue, GateRef thisValue, GateRe } } +#if ENABLE_NEXT_OPTIMIZATION +void BuiltinsArrayStubBuilder::Push(GateRef glue, GateRef thisValue, + GateRef numArgs, Variable *result, Label *exit, Label *slowPath) +{ + auto env = GetEnvironment(); + Label isStability(env); + Label setLength(env); + Label smallArgs(env); + Label checkSmallArgs(env); + Label isLengthWritable(env); + + BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); + Bind(&isStability); + BRANCH(IsArrayLengthWritable(glue, thisValue), &isLengthWritable, slowPath); + Bind(&isLengthWritable); + GateRef oldLength = GetArrayLength(thisValue); + *result = IntToTaggedPtr(oldLength); + BRANCH(Int32Equal(ChangeIntPtrToInt32(numArgs), Int32(0)), exit, &checkSmallArgs); + Bind(&checkSmallArgs); + // now unsupport more than 2 args + BRANCH(Int32LessThanOrEqual(ChangeIntPtrToInt32(numArgs), Int32(2)), &smallArgs, slowPath); + Bind(&smallArgs); + + GateRef elementsKindEnabled = IsEnableElementsKind(glue); + GateRef newLength = Int32Add(oldLength, ChangeIntPtrToInt32(numArgs)); + + DEFVARIABLE(elements, VariableType::JS_ANY(), GetElementsArray(thisValue)); + GateRef capacity = GetLengthOfTaggedArray(*elements); + Label grow(env); + Label setValue(env); + BRANCH(Int32GreaterThan(newLength, capacity), &grow, &setValue); + Bind(&grow); + { + elements = GrowElementsCapacity(glue, thisValue, newLength); + Jump(&setValue); + } + Bind(&setValue); + { + Label oneArg(env); + Label twoArg(env); + DEFVARIABLE(index, VariableType::INT32(), Int32(0)); + DEFVARIABLE(value, VariableType::JS_ANY(), Undefined()); + BRANCH(Int64Equal(numArgs, IntPtr(1)), &oneArg, &twoArg); // 1 one arg + Bind(&oneArg); + { + value = GetCallArg0(numArgs); + index = Int32Add(oldLength, Int32(0)); // 0 slot index + Label slowSet(env); + Label fastSet(env); + BRANCH(elementsKindEnabled, &slowSet, &fastSet); + Bind(&slowSet); + { + SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&setLength); + } + Bind(&fastSet); + { + FastSetValueWithElementsKind(glue, thisValue, *elements, *value, *index, ElementsKind::NONE, true); + Jump(&setLength); + } + } + Bind(&twoArg); + { + DEFVARIABLE(index2, VariableType::INT32(), Int32(0)); + DEFVARIABLE(value2, VariableType::JS_ANY(), Undefined()); + value = GetCallArg0(numArgs); + index = Int32Add(oldLength, Int32(0)); // 0 slot index + value2 = GetCallArg1(numArgs); + index2 = Int32Add(oldLength, Int32(1)); // 1 slot index + Label slowSet(env); + Label fastSet(env); + BRANCH(elementsKindEnabled, &slowSet, &fastSet); + Bind(&slowSet); + { + SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + SetValueWithElementsKind(glue, thisValue, *value2, *index2, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&setLength); + } + Bind(&fastSet); + { + FastSetValueWithElementsKind(glue, thisValue, *elements, *value, *index, ElementsKind::NONE, true); + FastSetValueWithElementsKind(glue, thisValue, *elements, *value2, *index2, ElementsKind::NONE, true); + Jump(&setLength); + } + } + } + Bind(&setLength); + SetArrayLength(glue, thisValue, newLength); + result->WriteVariable(IntToTaggedPtr(newLength)); + Jump(exit); +} +#else void BuiltinsArrayStubBuilder::Push(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result, Label *exit, Label *slowPath) { @@ -2467,7 +2570,7 @@ void BuiltinsArrayStubBuilder::Push(GateRef glue, GateRef thisValue, result->WriteVariable(IntToTaggedPtr(newLength)); Jump(exit); } - +#endif GateRef BuiltinsArrayStubBuilder::IsConcatSpreadable(GateRef glue, GateRef obj) { auto env = GetEnvironment(); @@ -2546,35 +2649,6 @@ GateRef BuiltinsArrayStubBuilder::NewArray(GateRef glue, GateRef count) return res; } -// new an empty array, the length is zero, but with specific hclass, -GateRef BuiltinsArrayStubBuilder::NewEmptyArrayWithHClass(GateRef glue, GateRef hclass) -{ - #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC - hclass = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ELEMENT_HOLE_TAGGED_HCLASS_INDEX); - #endif - // New an array with zero length. - auto env = GetEnvironment(); - Label entry(env); - env->SubCfgEntry(&entry); - DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined()); - Label exit(env); - Label setProperties(env); - NewObjectStubBuilder newBuilder(this); - newBuilder.SetParameters(glue, Int32(0)); - result = newBuilder.NewEmptyJSArrayWithHClass(hclass); - BRANCH(TaggedIsException(*result), &exit, &setProperties); - Bind(&setProperties); - { - InitializeArray(glue, Int32(0), &result, hclass); - Jump(&exit); - } - Bind(&exit); - auto res = *result; - env->SubCfgExit(); - return res; -} - - void BuiltinsArrayStubBuilder::Includes(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result, Label *exit, Label *slowPath) { @@ -3066,7 +3140,6 @@ void BuiltinsArrayStubBuilder::Splice(GateRef glue, GateRef thisValue, GateRef n Label isJsArray(env); Label isStability(env); Label defaultConstr(env); - Label matchCls(env); Label isGeneric(env); BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); Bind(&isHeapObject); @@ -3080,8 +3153,6 @@ void BuiltinsArrayStubBuilder::Splice(GateRef glue, GateRef thisValue, GateRef n BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); GateRef arrayLen = GetArrayLength(thisValue); Label lessThreeArg(env); @@ -3284,72 +3355,17 @@ void BuiltinsArrayStubBuilder::Splice(GateRef glue, GateRef thisValue, GateRef n } } -void BuiltinsArrayStubBuilder::FastToSpliced(GateRef glue, GateRef thisValue, GateRef newArray, GateRef actualStart, - GateRef actualDeleteCount, GateRef insertCount, GateRef insertValue) -{ - auto env = GetEnvironment(); - Label entry(env); - env->SubCfgEntry(&entry); - Label copyBefore(env); - Label copyAfter(env); - Label insertArg(env); - Label exit(env); - GateRef srcElements = GetElementsArray(thisValue); - GateRef dstElements = GetElementsArray(newArray); - GateRef thisLength = GetLengthOfJSArray(thisValue); - BRANCH(Int32GreaterThan(actualStart, Int32(0)), ©Before, &insertArg); - Bind(©Before); - { - GateRef srcStart = GetDataPtrInTaggedArray(srcElements); - GateRef dstStart = GetDataPtrInTaggedArray(dstElements); - ArrayCopyAndHoleToUndefined(glue, srcStart, dstStart, actualStart); - Jump(&insertArg); - } - Bind(&insertArg); - { - Label insert(env); - BRANCH(Int32GreaterThan(insertCount, Int32(0)), &insert, ©After); - Bind(&insert); - { - SetValueToTaggedArray(VariableType::JS_ANY(), glue, dstElements, actualStart, insertValue); - Jump(©After); - } - } - Bind(©After); - { - Label canCopyAfter(env); - Label setLength(env); - GateRef oldIndex = Int32Add(actualStart, actualDeleteCount); - GateRef newIndex = Int32Add(actualStart, insertCount); - BRANCH(Int32LessThan(oldIndex, thisLength), &canCopyAfter, &setLength); - Bind(&canCopyAfter); - { - GateRef srcStart = GetDataPtrInTaggedArray(srcElements, oldIndex); - GateRef dstStart = GetDataPtrInTaggedArray(dstElements, newIndex); - GateRef afterLength = Int32Sub(thisLength, oldIndex); - ArrayCopyAndHoleToUndefined(glue, srcStart, dstStart, afterLength); - newIndex = Int32Add(newIndex, afterLength); - Jump(&setLength); - } - Bind(&setLength); - { - SetArrayLength(glue, newArray, newIndex); - Jump(&exit); - } - } - Bind(&exit); - env->SubCfgExit(); -} - void BuiltinsArrayStubBuilder::ToSpliced(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result, Label *exit, Label *slowPath) { +#if ENABLE_NEXT_OPTIMIZATION + ToSplicedOptimised(glue, thisValue, numArgs, result, exit, slowPath); +#else auto env = GetEnvironment(); Label isHeapObject(env); Label isJsArray(env); Label isStability(env); Label defaultConstr(env); - Label matchCls(env); Label isGeneric(env); BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); Bind(&isHeapObject); @@ -3362,9 +3378,6 @@ void BuiltinsArrayStubBuilder::ToSpliced(GateRef glue, GateRef thisValue, GateRe Label notCOWArray(env); BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); - GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); GateRef thisLen = GetArrayLength(thisValue); Label lessThreeArg(env); DEFVARIABLE(actualStart, VariableType::INT32(), Int32(0)); @@ -3454,17 +3467,6 @@ void BuiltinsArrayStubBuilder::ToSpliced(GateRef glue, GateRef thisValue, GateRe Label insertArg(env); GateRef newArray = NewArray(glue, Int32(0)); GrowElementsCapacity(glue, newArray, *newLen); - Label elementsKindToSpliced(env); - Label fastToSpliced(env); - BRANCH_UNLIKELY(IsEnableElementsKind(glue), &elementsKindToSpliced, &fastToSpliced); - Bind(&fastToSpliced); - { - FastToSpliced(glue, thisValue, newArray, *actualStart, *actualDeleteCount, *insertCount, - GetCallArg2(numArgs)); - result->WriteVariable(newArray); - Jump(exit); - } - Bind(&elementsKindToSpliced); DEFVARIABLE(oldIndex, VariableType::INT32(), Int32(0)); DEFVARIABLE(newIndex, VariableType::INT32(), Int32(0)); BRANCH(Int32GreaterThan(*actualStart, Int32(0)), ©Before, &insertArg); @@ -3568,6 +3570,7 @@ void BuiltinsArrayStubBuilder::ToSpliced(GateRef glue, GateRef thisValue, GateRe } } } +#endif } void BuiltinsArrayStubBuilder::CopyWithin(GateRef glue, GateRef thisValue, GateRef numArgs, @@ -3581,7 +3584,6 @@ void BuiltinsArrayStubBuilder::CopyWithin(GateRef glue, GateRef thisValue, GateR Label isStability(env); Label isGeneric(env); Label notCOWArray(env); - Label matchCls(env); BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); Bind(&thisExists); BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); @@ -3594,9 +3596,6 @@ void BuiltinsArrayStubBuilder::CopyWithin(GateRef glue, GateRef thisValue, GateR Bind(&isStability); BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); - GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); DEFVARIABLE(startPos, VariableType::INT64(), Int64(0)); DEFVARIABLE(endPos, VariableType::INT64(), Int64(0)); Label targetTagExists(env); @@ -3626,7 +3625,7 @@ void BuiltinsArrayStubBuilder::CopyWithin(GateRef glue, GateRef thisValue, GateR Bind(&afterCallArg1); { endPos = thisLen; - BRANCH(Int64GreaterThanOrEqual(IntPtr(2), numArgs), &afterCallArg2, &endTagExists); + BRANCH(Int64GreaterThanOrEqual(IntPtr(2), numArgs), &afterCallArg2, &endTagExists); //2: 2 parameters Bind(&endTagExists); { GateRef endTag = GetCallArg2(numArgs); @@ -3797,7 +3796,6 @@ void BuiltinsArrayStubBuilder::Some(GateRef glue, GateRef thisValue, GateRef num Label isStability(env); Label notCOWArray(env); Label equalCls(env); - Label matchCls(env); Label isGeneric(env); BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); Bind(&thisExists); @@ -3811,9 +3809,6 @@ void BuiltinsArrayStubBuilder::Some(GateRef glue, GateRef thisValue, GateRef num Bind(&isStability); BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); - GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); Label arg0HeapObject(env); Label callable(env); Label thisIsStable(env); @@ -4000,7 +3995,6 @@ void BuiltinsArrayStubBuilder::Every(GateRef glue, GateRef thisValue, GateRef nu Label equalCls(env); Label arg0HeapObject(env); Label callable(env); - Label matchCls(env); Label isGeneric(env); BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); Bind(&thisExists); @@ -4014,9 +4008,6 @@ void BuiltinsArrayStubBuilder::Every(GateRef glue, GateRef thisValue, GateRef nu Bind(&isStability); BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); - GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); GateRef callbackFnHandle = GetCallArg0(numArgs); BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath); Bind(&arg0HeapObject); @@ -4187,7 +4178,6 @@ void BuiltinsArrayStubBuilder::ReduceRight(GateRef glue, GateRef thisValue, Gate Label isStability(env); Label notCOWArray(env); Label equalCls(env); - Label matchCls(env); Label isGeneric(env); BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); Bind(&thisExists); @@ -4201,9 +4191,6 @@ void BuiltinsArrayStubBuilder::ReduceRight(GateRef glue, GateRef thisValue, Gate Bind(&isStability); BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); - GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0)); DEFVARIABLE(accumulator, VariableType::JS_ANY(), Undefined()); DEFVARIABLE(k, VariableType::INT32(), Int32(0)); @@ -4391,7 +4378,6 @@ void BuiltinsArrayStubBuilder::FindLastIndex(GateRef glue, GateRef thisValue, Ga Label notCOWArray(env); Label equalCls(env); Label isGeneric(env); - Label matchCls(env); BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); Bind(&thisExists); BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); @@ -4404,9 +4390,6 @@ void BuiltinsArrayStubBuilder::FindLastIndex(GateRef glue, GateRef thisValue, Ga Bind(&isStability); BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); - GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); Label arg0HeapObject(env); Label callable(env); Label thisIsStable(env); @@ -4582,7 +4565,6 @@ void BuiltinsArrayStubBuilder::FindLast(GateRef glue, GateRef thisValue, GateRef Label isStability(env); Label notCOWArray(env); Label equalCls(env); - Label matchCls(env); Label isGeneric(env); BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); Bind(&thisExists); @@ -4596,9 +4578,6 @@ void BuiltinsArrayStubBuilder::FindLast(GateRef glue, GateRef thisValue, GateRef Bind(&isStability); BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); - GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); Label arg0HeapObject(env); Label callable(env); Label thisIsStable(env); @@ -4971,7 +4950,6 @@ void BuiltinsArrayStubBuilder::FlatMap(GateRef glue, GateRef thisValue, GateRef Label isStability(env); Label notCOWArray(env); Label equalCls(env); - Label matchCls(env); Label isGeneric(env); BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); Bind(&thisExists); @@ -4985,9 +4963,6 @@ void BuiltinsArrayStubBuilder::FlatMap(GateRef glue, GateRef thisValue, GateRef Bind(&isStability); BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); Bind(¬COWArray); - GateRef arrayCls = LoadHClass(thisValue); - ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); - Bind(&matchCls); Label arg0HeapObject(env); Label callable(env); Label thisIsStable(env); diff --git a/ecmascript/compiler/builtins/builtins_array_stub_builder.h b/ecmascript/compiler/builtins/builtins_array_stub_builder.h index 28876eb6fd98e432e303b2c23124ca6278549c18..9906b4650d50aa3aff7c2171181c7f9a2dcfedd1 100644 --- a/ecmascript/compiler/builtins/builtins_array_stub_builder.h +++ b/ecmascript/compiler/builtins/builtins_array_stub_builder.h @@ -77,8 +77,18 @@ private: GateRef intialHClass, GateRef start); void DoReverse(GateRef glue, GateRef fromArray, GateRef toArray, bool holeToUndefined, bool getWithKind, MemoryAttribute mAttr); + GateRef DoReverse(GateRef glue, GateRef thisValue, GateRef receiver, GateRef receiverState, Variable *result, + Label *exit); void FastToSpliced(GateRef glue, GateRef thisValue, GateRef newArray, GateRef actualStart, GateRef actualDeleteCount, GateRef insertCount, GateRef insertValue); + void ToSplicedOptimised(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result, Label *exit, + Label *slowPath); + void UnshiftOptimised(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result, Label *exit, + Label *slowPath); + GateRef DoSortOptimised(GateRef glue, GateRef receiver, GateRef receiverState, Variable *result, Label *exit, + Label *slowPath, GateRef hir); + void ToReversedOptimised(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result, Label *exit, + Label *slowPath); }; } // namespace panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_BUILTINS_ARRAY_STUB_BUILDER_H diff --git a/ecmascript/compiler/builtins/builtins_array_stub_builder_next_optimization.cpp b/ecmascript/compiler/builtins/builtins_array_stub_builder_next_optimization.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d333cdc7aaae9fb93c9e5377bac0e67a801837b1 --- /dev/null +++ b/ecmascript/compiler/builtins/builtins_array_stub_builder_next_optimization.cpp @@ -0,0 +1,832 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ecmascript/compiler/builtins/builtins_array_stub_builder.h" + +#include "ecmascript/builtins/builtins_string.h" +#include "ecmascript/compiler/builtins/builtins_stubs.h" +#include "ecmascript/compiler/call_stub_builder.h" +#include "ecmascript/compiler/new_object_stub_builder.h" +#include "ecmascript/compiler/profiler_operation.h" +#include "ecmascript/compiler/rt_call_signature.h" +#include "ecmascript/runtime_call_id.h" +#include "ecmascript/js_iterator.h" +#include "ecmascript/base/array_helper.h" + +namespace panda::ecmascript::kungfu { +void BuiltinsArrayStubBuilder::UnshiftOptimised(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result, + Label *exit, Label *slowPath) +{ + auto env = GetEnvironment(); + Label isHeapObject(env); + Label isJsArray(env); + Label isStableJsArray(env); + Label notOverRange(env); + Label numNotEqualZero(env); + Label numLessThanOrEqualThree(env); + Label afterCopy(env); + Label grow(env); + Label setValue(env); + Label numEqual2(env); + Label numEqual3(env); + Label threeArgs(env); + Label final(env); + BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); + Bind(&isHeapObject); + BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); + Bind(&isJsArray); + BRANCH(IsStableJSArray(glue, thisValue), &isStableJsArray, slowPath); + Bind(&isStableJsArray); + BRANCH(Int64GreaterThan(numArgs, IntPtr(0)), &numNotEqualZero, slowPath); + Bind(&numNotEqualZero); + GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); + GateRef argLen = ZExtInt32ToInt64(ChangeIntPtrToInt32(numArgs)); + GateRef newLen = Int64Add(thisLen, argLen); + BRANCH(Int64GreaterThan(newLen, Int64(base::MAX_SAFE_INTEGER)), slowPath, ¬OverRange); + Bind(¬OverRange); + // 3 : max param num + BRANCH(Int64LessThanOrEqual(numArgs, IntPtr(3)), &numLessThanOrEqualThree, slowPath); + Bind(&numLessThanOrEqualThree); + GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(GetElementsArray(thisValue))); + BRANCH(Int64GreaterThan(newLen, capacity), &grow, &setValue); + Bind(&grow); + { + GrowElementsCapacity(glue, thisValue, TruncInt64ToInt32(newLen)); + Jump(&setValue); + } + Bind(&setValue); + { + Label elementsKindEnabled(env); + GateRef elements = GetElementsArray(thisValue); + GateRef arrayStart = GetDataPtrInTaggedArray(elements); + GateRef moveTo = PtrAdd(arrayStart, PtrMul(numArgs, IntPtr(JSTaggedValue::TaggedTypeSize()))); + GateRef isElementsKindEnabled = IsEnableElementsKind(glue); + Label isIntOrNumber(env); + Label isTagged(env); + BRANCH_NO_WEIGHT(isElementsKindEnabled, &elementsKindEnabled, &isTagged); + Bind(&elementsKindEnabled); + { + GateRef kind = GetElementsKindFromHClass(LoadHClass(thisValue)); + GateRef isInt = LogicAndBuilder(env) + .And(Int32GreaterThanOrEqual(kind, Int32(static_cast(ElementsKind::INT)))) + .And(Int32LessThanOrEqual(kind, Int32(static_cast(ElementsKind::HOLE_INT)))) + .Done(); + GateRef isNumber = LogicAndBuilder(env) + .And(Int32GreaterThanOrEqual(kind, Int32(static_cast(ElementsKind::NUMBER)))) + .And(Int32LessThanOrEqual(kind, Int32(static_cast(ElementsKind::HOLE_NUMBER)))) + .Done(); + GateRef isIntOrNumberKind = LogicOrBuilder(env).Or(isInt).Or(isNumber).Done(); + BRANCH_NO_WEIGHT(isIntOrNumberKind, &isIntOrNumber, &isTagged); + Bind(&isIntOrNumber); + { + ArrayCopy(glue, arrayStart, elements, moveTo, TruncInt64ToInt32(thisLen), + MemoryAttribute::NoBarrier()); + Jump(&afterCopy); + } + Bind(&isTagged); + { + ArrayCopy(glue, arrayStart, elements, moveTo, TruncInt64ToInt32(thisLen)); + Jump(&afterCopy); + } + Bind(&afterCopy); + { + GateRef value0 = GetCallArg0(numArgs); + // 0 : the first Element position + SetValueWithElementsKind(glue, thisValue, value0, Int64(0), Boolean(false), + Int32(static_cast(ElementsKind::NONE))); + // 2 : the second param + BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(2)), &numEqual2, &numEqual3); + Bind(&numEqual2); + { + GateRef value1 = GetCallArg1(numArgs); + // 1 : the second Element position + SetValueWithElementsKind(glue, thisValue, value1, Int64(1), Boolean(false), + Int32(static_cast(ElementsKind::NONE))); + Jump(&numEqual3); + } + Bind(&numEqual3); + { + // 3 : the third param + BRANCH(Int64Equal(numArgs, IntPtr(3)), &threeArgs, &final); + Bind(&threeArgs); + GateRef value2 = GetCallArg2(numArgs); + // 2 : the third Element position + SetValueWithElementsKind(glue, thisValue, value2, Int64(2), Boolean(false), + Int32(static_cast(ElementsKind::NONE))); + Jump(&final); + } + Bind(&final); + { + SetArrayLength(glue, thisValue, newLen); + result->WriteVariable(IntToTaggedPtr(newLen)); + Jump(exit); + } + } + } + } +} + +GateRef BuiltinsArrayStubBuilder::DoSortOptimised(GateRef glue, GateRef receiver, GateRef receiverState, + Variable *result, Label *exit, Label *slowPath, GateRef hir) +{ + auto env = GetEnvironment(); + Label entry(env); + env->SubCfgEntry(&entry); + GateRef len = ZExtInt32ToInt64(GetArrayLength(receiver)); + DEFVARIABLE(i, VariableType::INT64(), Int64(1)); + DEFVARIABLE(presentValue, VariableType::JS_ANY(), Undefined()); + DEFVARIABLE(middleValue, VariableType::JS_ANY(), Undefined()); + DEFVARIABLE(previousValue, VariableType::JS_ANY(), Undefined()); + Label loopHead(env); + Label loopEnd(env); + Label next(env); + Label loopExit(env); + Jump(&loopHead); + LoopBegin(&loopHead); + { + BRANCH(Int64LessThan(*i, len), &next, &loopExit); + Bind(&next); + DEFVARIABLE(beginIndex, VariableType::INT64(), Int64(0)); + DEFVARIABLE(endIndex, VariableType::INT64(), *i); + Label presentValueIsHole(env); + Label afterGettingpresentValue(env); + Label presentValueHasProperty(env); + Label presentValueHasException0(env); + presentValue = GetTaggedValueWithElementsKind(receiver, *i); + BRANCH(TaggedIsHole(*presentValue), &presentValueIsHole, &afterGettingpresentValue); + Bind(&presentValueIsHole); + { + GateRef presentValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), {receiver, IntToTaggedInt(*i)}); + BRANCH(TaggedIsTrue(presentValueHasProp), &presentValueHasProperty, &afterGettingpresentValue); + Bind(&presentValueHasProperty); + { + presentValue = FastGetPropertyByIndex(glue, receiver, TruncInt64ToInt32(*i), ProfileOperation(), hir); + BRANCH(HasPendingException(glue), &presentValueHasException0, &afterGettingpresentValue); + Bind(&presentValueHasException0); + { + result->WriteVariable(Exception()); + Jump(exit); + } + } + } + Bind(&afterGettingpresentValue); + { + Label loopHead1(env); + Label loopEnd1(env); + Label next1(env); + Label loopExit1(env); + Jump(&loopHead1); + LoopBegin(&loopHead1); + { + Label middleValueIsHole(env); + Label afterGettingmiddleValue(env); + Label middleValueHasProperty(env); + Label middleValueHasException0(env); + BRANCH(Int64LessThan(*beginIndex, *endIndex), &next1, &loopExit1); + Bind(&next1); + GateRef sum = Int64Add(*beginIndex, *endIndex); + GateRef middleIndex = Int64Div(sum, Int64(2)); // 2 : half + middleValue = GetTaggedValueWithElementsKind(receiver, middleIndex); + BRANCH(TaggedIsHole(*middleValue), &middleValueIsHole, &afterGettingmiddleValue); + Bind(&middleValueIsHole); + { + GateRef middleValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), + {receiver, IntToTaggedInt(middleIndex)}); + BRANCH(TaggedIsTrue(middleValueHasProp), &middleValueHasProperty, &afterGettingmiddleValue); + Bind(&middleValueHasProperty); + { + middleValue = FastGetPropertyByIndex(glue, receiver, + TruncInt64ToInt32(middleIndex), ProfileOperation(), hir); + BRANCH(HasPendingException(glue), &middleValueHasException0, &afterGettingmiddleValue); + Bind(&middleValueHasException0); + { + result->WriteVariable(Exception()); + Jump(exit); + } + } + } + Bind(&afterGettingmiddleValue); + { + Label isInt(env); + Label notInt(env); + Label exchangeIndex(env); + GateRef middleVal = *middleValue; + GateRef presentVal = *presentValue; + DEFVARIABLE(compareResult, VariableType::INT32(), Int32(0)); + GateRef intBool = LogicAndBuilder(env) + .And(TaggedIsInt(middleVal)) + .And(TaggedIsInt(presentVal)) + .Done(); + BRANCH(intBool, &isInt, ¬Int); + Bind(&isInt); + { + compareResult = + CallNGCRuntime(glue, RTSTUB_ID(FastArraySort), {*middleValue, *presentValue}); + Jump(&exchangeIndex); + } + Bind(¬Int); + { + Label isString(env); + GateRef strBool = LogicAndBuilder(env) + .And(TaggedIsString(middleVal)) + .And(TaggedIsString(presentVal)) + .Done(); + BRANCH(strBool, &isString, slowPath); + Bind(&isString); + { + compareResult = CallNGCRuntime(glue, + RTSTUB_ID(FastArraySortString), { + glue, *middleValue, *presentValue + }); + Jump(&exchangeIndex); + } + } + Bind(&exchangeIndex); + { + Label less0(env); + Label greater0(env); + BRANCH(Int32LessThanOrEqual(*compareResult, Int32(0)), &less0, &greater0); + Bind(&greater0); + { + endIndex = middleIndex; + Jump(&loopEnd1); + } + Bind(&less0); + { + beginIndex = middleIndex; + beginIndex = Int64Add(*beginIndex, Int64(1)); + Jump(&loopEnd1); + } + } + } + } + Bind(&loopEnd1); + LoopEnd(&loopHead1); + Bind(&loopExit1); + + Label shouldCopy(env); + GateRef isGreater0 = Int64GreaterThanOrEqual(*endIndex, Int64(0)); + GateRef lessI = Int64LessThan(*endIndex, *i); + BRANCH(BitAnd(isGreater0, lessI), &shouldCopy, &loopEnd); + Bind(&shouldCopy); + { + DEFVARIABLE(j, VariableType::INT64(), *i); + Label loopHead2(env); + Label loopEnd2(env); + Label next2(env); + Label loopExit2(env); + Label receiverIsNew(env); + Label receiverIsOrigin(env); + Label receiverIsNew2(env); + Label receiverIsOrigin2(env); + Jump(&loopHead2); + LoopBegin(&loopHead2); + { + Label previousValueIsHole(env); + Label afterGettingpreviousValue(env); + Label previousValueHasProperty(env); + Label previousValueHasException0(env); + BRANCH(Int64GreaterThan(*j, *endIndex), &next2, &loopExit2); + Bind(&next2); + previousValue = GetTaggedValueWithElementsKind(receiver, Int64Sub(*j, Int64(1))); + BRANCH(TaggedIsHole(*previousValue), &previousValueIsHole, &afterGettingpreviousValue); + Bind(&previousValueIsHole); + { + GateRef previousValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), + {receiver, IntToTaggedInt(Int64Sub(*j, Int64(1)))}); + BRANCH(TaggedIsTrue(previousValueHasProp), + &previousValueHasProperty, &afterGettingpreviousValue); + Bind(&previousValueHasProperty); + { + previousValue = FastGetPropertyByIndex(glue, receiver, + TruncInt64ToInt32(Int64Sub(*j, Int64(1))), + ProfileOperation(), hir); + BRANCH(HasPendingException(glue), &previousValueHasException0, &afterGettingpreviousValue); + Bind(&previousValueHasException0); + { + result->WriteVariable(Exception()); + Jump(exit); + } + } + } + Bind(&afterGettingpreviousValue); + { + BRANCH(receiverState, &receiverIsNew, &receiverIsOrigin); + Bind(&receiverIsNew); + SetValueWithElementsKind(glue, receiver, *previousValue, *j, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd2); + Bind(&receiverIsOrigin); + SetValueWithElementsKind(glue, receiver, *previousValue, *j, Boolean(false), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd2); + } + } + Bind(&loopEnd2); + j = Int64Sub(*j, Int64(1)); + LoopEnd(&loopHead2); + Bind(&loopExit2); + BRANCH(receiverState, &receiverIsNew2, &receiverIsOrigin2); + Bind(&receiverIsNew2); + { + SetValueWithElementsKind(glue, receiver, *presentValue, *endIndex, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd); + } + Bind(&receiverIsOrigin2); + { + SetValueWithElementsKind(glue, receiver, *presentValue, *endIndex, Boolean(false), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd); + } + } + } + } + Bind(&loopEnd); + i = Int64Add(*i, Int64(1)); + LoopEnd(&loopHead); + Bind(&loopExit); + env->SubCfgExit(); + return receiver; +} + +void BuiltinsArrayStubBuilder::ToReversedOptimised(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs, + Variable *result, Label *exit, Label *slowPath) +{ + auto env = GetEnvironment(); + Label isHeapObject(env); + Label isJsArray(env); + Label defaultConstr(env); + Label isStability(env); + Label notCOWArray(env); + BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); + Bind(&isHeapObject); + BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); + Bind(&isJsArray); + BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); + Bind(&defaultConstr); + BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); + Bind(&isStability); + BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); + Bind(¬COWArray); + Label ElementsKindEnabled(env); + Label ElementsKindDisabled(env); + Label next(env); + GateRef isElementsKindEnabled = IsEnableElementsKind(glue); + DEFVARIABLE(receiver, VariableType::JS_ANY(), Hole()); + GateRef kind = GetElementsKindFromHClass(LoadHClass(thisValue)); + GateRef thisArrLen = GetArrayLength(thisValue); + BRANCH_UNLIKELY(isElementsKindEnabled, &ElementsKindEnabled, &ElementsKindDisabled); + Bind(&ElementsKindEnabled); + { + Label newArrayIsTagged(env); + Label reuseOldHClass(env); + BRANCH_NO_WEIGHT(ElementsKindHasHole(kind), &newArrayIsTagged, &reuseOldHClass); + Bind(&newArrayIsTagged); + { + // If the kind has hole, we know it must be transited to TAGGED kind; + // There will be no hole in the new array because hole will be converted to undefined. + GateRef newHClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue, + ConstantIndex::ELEMENT_TAGGED_HCLASS_INDEX); + receiver = NewEmptyArrayWithHClass(glue, newHClass); + Jump(&next); + } + Bind(&reuseOldHClass); + { + receiver = NewEmptyArrayWithHClass(glue, LoadHClass(thisValue)); + Jump(&next); + } + } + Bind(&ElementsKindDisabled); + { + receiver = NewArray(glue, Int64(0)); + Jump(&next); + } + Bind(&next); + GrowElementsCapacity(glue, *receiver, thisArrLen); + SetArrayLength(glue, *receiver, thisArrLen); + + Label afterReverse(env); + Label isIntOrNumber(env); + Label notIntOrNumber(env); + Label isTagged(env); + Label isHoleOrIntOrNumber(env); + Label elementsKindEnabled(env); + BRANCH_NO_WEIGHT(isElementsKindEnabled, &elementsKindEnabled, &isTagged); + Bind(&elementsKindEnabled); + { + GateRef intOrNumber = LogicOrBuilder(env) + .Or(Int32Equal(kind, Int32(static_cast(ElementsKind::INT)))) + .Or(Int32Equal(kind, Int32(static_cast(ElementsKind::NUMBER)))) + .Done(); + BRANCH_NO_WEIGHT(intOrNumber, &isIntOrNumber, ¬IntOrNumber); + Bind(¬IntOrNumber); + { + GateRef holeOrIntOrNumber = LogicOrBuilder(env) + .Or(Int32Equal(kind, Int32(static_cast(ElementsKind::HOLE_INT)))) + .Or(Int32Equal(kind, Int32(static_cast(ElementsKind::HOLE_NUMBER)))) + .Done(); + BRANCH_NO_WEIGHT(holeOrIntOrNumber, &isHoleOrIntOrNumber, &isTagged); + } + } + Bind(&isTagged); + { + // The old array and new array are both TaggedArray, so load and store the element directly. + // And barrier is needed. + DoReverse(glue, thisValue, *receiver, true, false, MemoryAttribute::Default()); + Jump(&afterReverse); + } + Bind(&isIntOrNumber); + { + // The old array and new array are both MutantTaggedArray, so load and store the element directly. + // And barrier is not needed. + DoReverse(glue, thisValue, *receiver, false, false, MemoryAttribute::NoBarrier()); + Jump(&afterReverse); + } + Bind(&isHoleOrIntOrNumber); + { + // The old array is mutant, but new array is TaggedArray, so load the value from old array with + // elements kind. And set it to new array directly, And barrier is not needed. + DoReverse(glue, thisValue, *receiver, true, true, MemoryAttribute::NoBarrier()); + Jump(&afterReverse); + } + Bind(&afterReverse); + result->WriteVariable(*receiver); + Jump(exit); +} + +void BuiltinsArrayStubBuilder::DoReverse(GateRef glue, GateRef fromArray, GateRef toArray, bool holeToUndefined, + bool getWithKind, MemoryAttribute mAttr) +{ + auto env = GetEnvironment(); + Label entry(env); + env->SubCfgEntry(&entry); + Label loopExit(env); + Label begin(env); + Label body(env); + Label endLoop(env); + + GateRef fromElements = GetElementsArray(fromArray); + GateRef toElements = GetElementsArray(toArray); + GateRef thisArrLen = GetArrayLength(fromArray); + DEFVARIABLE(index, VariableType::INT32(), Int32(0)); + GateRef endIndex = Int32Sub(thisArrLen, Int32(1)); + Jump(&begin); + LoopBegin(&begin); + { + BRANCH_LIKELY(Int32UnsignedLessThan(*index, thisArrLen), &body, &loopExit); + Bind(&body); + { + GateRef toIndex = Int32Sub(endIndex, *index); + // The old array and new array are both TaggedArray, so load and store the element directly. + // And barrier is needed. + GateRef value = getWithKind + ? GetTaggedValueWithElementsKind(fromArray, *index) + : GetValueFromTaggedArray(fromElements, *index); + if (holeToUndefined) { + Label isHole(env); + Label isNotHole(env); + BRANCH_UNLIKELY(TaggedIsHole(value), &isHole, &isNotHole); + Bind(&isHole); + { + // The return value of toReversed() is never sparse. + // Empty slots become undefined in the returned array. + SetValueToTaggedArray(VariableType::JS_ANY(), glue, toElements, toIndex, Undefined(), + MemoryAttribute::NoBarrier()); + Jump(&endLoop); + } + Bind(&isNotHole); + } + SetValueToTaggedArray(VariableType::JS_ANY(), glue, toElements, toIndex, value, mAttr); + Jump(&endLoop); + } + } + Bind(&endLoop); + index = Int32Add(*index, Int32(1)); + LoopEnd(&begin); + Bind(&loopExit); + env->SubCfgExit(); +} + + +// new an empty array, the length is zero, but with specific hclass, +GateRef BuiltinsArrayStubBuilder::NewEmptyArrayWithHClass(GateRef glue, GateRef hclass) +{ +#if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC + hclass = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ELEMENT_HOLE_TAGGED_HCLASS_INDEX); +#endif + // New an array with zero length. + auto env = GetEnvironment(); + Label entry(env); + env->SubCfgEntry(&entry); + DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined()); + Label exit(env); + Label setProperties(env); + NewObjectStubBuilder newBuilder(this); + newBuilder.SetParameters(glue, Int32(0)); + result = newBuilder.NewEmptyJSArrayWithHClass(hclass); + BRANCH(TaggedIsException(*result), &exit, &setProperties); + Bind(&setProperties); + { + InitializeArray(glue, Int32(0), &result, hclass); + Jump(&exit); + } + Bind(&exit); + auto res = *result; + env->SubCfgExit(); + return res; +} + +void BuiltinsArrayStubBuilder::FastToSpliced(GateRef glue, GateRef thisValue, GateRef newArray, GateRef actualStart, + GateRef actualDeleteCount, GateRef insertCount, GateRef insertValue) +{ + auto env = GetEnvironment(); + Label entry(env); + env->SubCfgEntry(&entry); + Label copyBefore(env); + Label copyAfter(env); + Label insertArg(env); + Label exit(env); + GateRef srcElements = GetElementsArray(thisValue); + GateRef dstElements = GetElementsArray(newArray); + GateRef thisLength = GetLengthOfJSArray(thisValue); + BRANCH(Int32GreaterThan(actualStart, Int32(0)), ©Before, &insertArg); + Bind(©Before); + { + GateRef srcStart = GetDataPtrInTaggedArray(srcElements); + GateRef dstStart = GetDataPtrInTaggedArray(dstElements); + ArrayCopyAndHoleToUndefined(glue, srcStart, dstElements, dstStart, actualStart); + Jump(&insertArg); + } + Bind(&insertArg); + { + Label insert(env); + BRANCH(Int32GreaterThan(insertCount, Int32(0)), &insert, ©After); + Bind(&insert); + { + SetValueToTaggedArray(VariableType::JS_ANY(), glue, dstElements, actualStart, insertValue); + Jump(©After); + } + } + Bind(©After); + { + Label canCopyAfter(env); + Label setLength(env); + GateRef oldIndex = Int32Add(actualStart, actualDeleteCount); + GateRef newIndex = Int32Add(actualStart, insertCount); + BRANCH(Int32LessThan(oldIndex, thisLength), &canCopyAfter, &setLength); + Bind(&canCopyAfter); + { + GateRef srcStart = GetDataPtrInTaggedArray(srcElements, oldIndex); + GateRef dstStart = GetDataPtrInTaggedArray(dstElements, newIndex); + GateRef afterLength = Int32Sub(thisLength, oldIndex); + ArrayCopyAndHoleToUndefined(glue, srcStart, dstElements, dstStart, afterLength); + newIndex = Int32Add(newIndex, afterLength); + Jump(&setLength); + } + Bind(&setLength); + { + SetArrayLength(glue, newArray, newIndex); + Jump(&exit); + } + } + Bind(&exit); + env->SubCfgExit(); +} + +void BuiltinsArrayStubBuilder::ToSplicedOptimised(GateRef glue, GateRef thisValue, GateRef numArgs, + Variable *result, Label *exit, Label *slowPath) +{ + auto env = GetEnvironment(); + Label isHeapObject(env); + Label isJsArray(env); + Label isStability(env); + Label defaultConstr(env); + Label isGeneric(env); + BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); + Bind(&isHeapObject); + BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); + Bind(&isJsArray); + BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); + Bind(&defaultConstr); + BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); + Bind(&isStability); + Label notCOWArray(env); + BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); + Bind(¬COWArray); + GateRef thisLen = GetArrayLength(thisValue); + Label lessThreeArg(env); + DEFVARIABLE(actualStart, VariableType::INT32(), Int32(0)); + DEFVARIABLE(actualDeleteCount, VariableType::INT32(), Int32(0)); + DEFVARIABLE(newLen, VariableType::INT32(), Int32(0)); + DEFVARIABLE(insertCount, VariableType::INT32(), Int32(0)); + GateRef argc = ChangeIntPtrToInt32(numArgs); + // 3: max arg count + BRANCH(Int32LessThanOrEqual(argc, Int32(3)), &lessThreeArg, slowPath); + Bind(&lessThreeArg); + { + Label checkOverFlow(env); + Label greaterZero(env); + Label greaterOne(env); + Label checkGreaterOne(env); + Label notOverFlow(env); + Label copyAfter(env); + // 0: judge the first arg exists + BRANCH(Int32GreaterThan(argc, Int32(0)), &greaterZero, &checkGreaterOne); + Bind(&greaterZero); + { + GateRef taggedStart = GetCallArg0(numArgs); + Label taggedStartInt(env); + BRANCH(TaggedIsInt(taggedStart), &taggedStartInt, slowPath); + Bind(&taggedStartInt); + { + GateRef intStart = GetInt32OfTInt(taggedStart); + actualStart = CalArrayRelativePos(intStart, thisLen); + actualDeleteCount = Int32Sub(thisLen, *actualStart); + Jump(&checkGreaterOne); + } + } + Bind(&checkGreaterOne); + { + // 1: judge the second arg exists + BRANCH(Int32GreaterThan(argc, Int32(1)), &greaterOne, &checkOverFlow); + Bind(&greaterOne); + { + // 2: arg count which is not an item + insertCount = Int32Sub(argc, Int32(2)); + GateRef argDeleteCount = GetCallArg1(numArgs); + Label argDeleteCountInt(env); + BRANCH(TaggedIsInt(argDeleteCount), &argDeleteCountInt, slowPath); + Bind(&argDeleteCountInt); + { + DEFVARIABLE(deleteCount, VariableType::INT32(), TaggedGetInt(argDeleteCount)); + Label deleteCountLessZero(env); + Label calActualDeleteCount(env); + BRANCH(Int32LessThan(*deleteCount, Int32(0)), &deleteCountLessZero, &calActualDeleteCount); + Bind(&deleteCountLessZero); + { + deleteCount = Int32(0); + Jump(&calActualDeleteCount); + } + Bind(&calActualDeleteCount); + { + actualDeleteCount = *deleteCount; + Label lessArrayLen(env); + BRANCH(Int32LessThan(Int32Sub(thisLen, *actualStart), *deleteCount), + &lessArrayLen, &checkOverFlow); + Bind(&lessArrayLen); + { + actualDeleteCount = Int32Sub(thisLen, *actualStart); + Jump(&checkOverFlow); + } + } + } + } + Bind(&checkOverFlow); + { + newLen = Int32Add(Int32Sub(thisLen, *actualDeleteCount), *insertCount); + BRANCH(Int64GreaterThan(ZExtInt32ToInt64(*newLen), Int64(base::MAX_SAFE_INTEGER)), + slowPath, ¬OverFlow); + Bind(¬OverFlow); + Label newLenEmpty(env); + Label newLenNotEmpty(env); + BRANCH(Int32Equal(*newLen, Int32(0)), &newLenEmpty, &newLenNotEmpty); + Bind(&newLenEmpty); + { + NewObjectStubBuilder newBuilder(this); + result->WriteVariable(newBuilder.CreateEmptyArray(glue)); + Jump(exit); + } + Bind(&newLenNotEmpty); + { + Label copyBefore(env); + Label insertArg(env); + GateRef newArray = NewArray(glue, Int32(0)); + GrowElementsCapacity(glue, newArray, *newLen); + Label elementsKindToSpliced(env); + Label fastToSpliced(env); + BRANCH_UNLIKELY(IsEnableElementsKind(glue), &elementsKindToSpliced, &fastToSpliced); + Bind(&fastToSpliced); + { + FastToSpliced(glue, thisValue, newArray, *actualStart, *actualDeleteCount, *insertCount, + GetCallArg2(numArgs)); + result->WriteVariable(newArray); + Jump(exit); + } + Bind(&elementsKindToSpliced); + DEFVARIABLE(oldIndex, VariableType::INT32(), Int32(0)); + DEFVARIABLE(newIndex, VariableType::INT32(), Int32(0)); + BRANCH(Int32GreaterThan(*actualStart, Int32(0)), ©Before, &insertArg); + Bind(©Before); + { + Label loopHead(env); + Label loopEnd(env); + Label loopNext(env); + Label loopExit(env); + Label eleIsHole(env); + Label eleNotHole(env); + Jump(&loopHead); + LoopBegin(&loopHead); + { + BRANCH(Int32LessThan(*oldIndex, *actualStart), &loopNext, &loopExit); + Bind(&loopNext); + GateRef ele = GetTaggedValueWithElementsKind(thisValue, *oldIndex); + BRANCH(TaggedIsHole(ele), &eleIsHole, &eleNotHole); + Bind(&eleIsHole); + { + SetValueWithElementsKind(glue, newArray, Undefined(), *newIndex, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd); + } + Bind(&eleNotHole); + { + SetValueWithElementsKind(glue, newArray, ele, *newIndex, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd); + } + } + Bind(&loopEnd); + oldIndex = Int32Add(*oldIndex, Int32(1)); + newIndex = Int32Add(*newIndex, Int32(1)); + LoopEnd(&loopHead); + Bind(&loopExit); + Jump(&insertArg); + } + Bind(&insertArg); + { + Label insert(env); + BRANCH(Int32GreaterThan(*insertCount, Int32(0)), &insert, ©After); + Bind(&insert); + { + GateRef insertNum = GetCallArg2(numArgs); + SetValueWithElementsKind(glue, newArray, insertNum, *newIndex, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + newIndex = Int32Add(*newIndex, Int32(1)); + Jump(©After); + } + } + Bind(©After); + { + Label canCopyAfter(env); + Label setLength(env); + oldIndex = Int32Add(*actualStart, *actualDeleteCount); + BRANCH(Int32LessThan(*oldIndex, thisLen), &canCopyAfter, &setLength); + Bind(&canCopyAfter); + { + Label loopHead1(env); + Label loopNext1(env); + Label loopEnd1(env); + Label loopExit1(env); + Label ele1IsHole(env); + Label ele1NotHole(env); + Jump(&loopHead1); + LoopBegin(&loopHead1); + { + BRANCH(Int32LessThan(*oldIndex, thisLen), &loopNext1, &loopExit1); + Bind(&loopNext1); + GateRef ele1 = GetTaggedValueWithElementsKind(thisValue, *oldIndex); + BRANCH(TaggedIsHole(ele1), &ele1IsHole, &ele1NotHole); + Bind(&ele1IsHole); + { + SetValueWithElementsKind(glue, newArray, Undefined(), *newIndex, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd1); + } + Bind(&ele1NotHole); + { + SetValueWithElementsKind(glue, newArray, ele1, *newIndex, Boolean(true), + Int32(static_cast(ElementsKind::NONE))); + Jump(&loopEnd1); + } + } + Bind(&loopEnd1); + oldIndex = Int32Add(*oldIndex, Int32(1)); + newIndex = Int32Add(*newIndex, Int32(1)); + LoopEnd(&loopHead1); + Bind(&loopExit1); + Jump(&setLength); + } + Bind(&setLength); + { + SetArrayLength(glue, newArray, *newLen); + result->WriteVariable(newArray); + Jump(exit); + } + } + } + } + } + } +} +} // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/builtins/builtins_call_signature.h b/ecmascript/compiler/builtins/builtins_call_signature.h index 7792b037178ca4ee55fae68d394c0bdf8c102fb5..a3c3c7793409b838bcc2f2e864794b849a74cc97 100644 --- a/ecmascript/compiler/builtins/builtins_call_signature.h +++ b/ecmascript/compiler/builtins/builtins_call_signature.h @@ -18,6 +18,7 @@ #include "ecmascript/base/config.h" #include "ecmascript/compiler/call_signature.h" +#include "ecmascript/global_env_constants.h" namespace panda::ecmascript::kungfu { @@ -239,12 +240,12 @@ namespace panda::ecmascript::kungfu { V(BigInt64ArrayConstructor) \ V(BigUint64ArrayConstructor) -#define AOT_AND_BUILTINS_STUB_LIST(V) \ - V(StringLocaleCompare) \ - V(StringIteratorProtoNext) \ +#define AOT_AND_BUILTINS_STUB_LIST(V) \ + V(StringLocaleCompare) \ + V(StringIteratorProtoNext) \ V(ArraySort) -#define AOT_BUILTINS_STUB_LIST(V) \ +#define AOT_BUILTINS_STUB_LIST(V) \ V(JsonStringify) \ V(MapProtoIterator) \ V(MapIteratorProtoNext) \ @@ -338,6 +339,7 @@ public: AOT_BUILTINS_INLINE_LIST(DEF_STUB_ID) #undef DEF_STUB_ID_DYN #undef DEF_STUB_ID + NUM_OF_BUILTINS_ID, BUILTINS_CONSTRUCTOR_STUB_FIRST = BooleanConstructor, TYPED_BUILTINS_FIRST = JsonStringify, TYPED_BUILTINS_LAST = IteratorProtoReturn, @@ -452,6 +454,7 @@ public: case BuiltinsStubCSigns::ID::ArrayEvery: case BuiltinsStubCSigns::ID::ArrayPop: case BuiltinsStubCSigns::ID::ArraySlice: + case BuiltinsStubCSigns::ID::ArrayPush: return true; default: return false; @@ -748,6 +751,8 @@ public: return ConstantIndex::ARRAY_EVERY_INDEX; case BuiltinsStubCSigns::ID::ArrayPop: return ConstantIndex::ARRAY_POP_INDEX; + case BuiltinsStubCSigns::ID::ArrayPush: + return ConstantIndex::ARRAY_PUSH_INDEX; case BuiltinsStubCSigns::ID::ArraySlice: return ConstantIndex::ARRAY_SLICE_INDEX; case BuiltinsStubCSigns::ID::GlobalDecodeURIComponent: @@ -861,6 +866,7 @@ public: {ArrayMap, "Array.prototype.map"}, {ArrayEvery, "Array.prototype.every"}, {ArrayPop, "Array.prototype.pop"}, + {ArrayPush, "Array.prototype.push"}, {ArraySlice, "Array.prototype.slice"}, {DataViewGetInt8, "DataView.prototype.GetInt8"}, {DataViewGetUint8, "DataView.prototype.GetUint8"}, @@ -965,6 +971,7 @@ public: {"map", ArrayMap}, {"every", ArrayEvery}, {"pop", ArrayPop}, + {"push", ArrayPush}, {"slice", ArraySlice}, {"getUint8", DataViewGetUint8}, {"getInt8", DataViewGetInt8}, diff --git a/ecmascript/compiler/builtins/builtins_dataview_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_dataview_stub_builder.cpp index aedb6d26681535371d1e9ed90b697b923b8100e6..dce9388e8b7e33c87aec33ac4d067fe40370561b 100644 --- a/ecmascript/compiler/builtins/builtins_dataview_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_dataview_stub_builder.cpp @@ -69,13 +69,14 @@ void BuiltinsDataViewStubBuilder::SetTypedValue(GateRef glue, GateRef thisValue, BRANCH(IsDetachedBuffer(buffer), slowPath, &checkOffset); Bind(&checkOffset); { - GateRef offset = GetByteOffset(thisValue); - GateRef size = GetByteLength(thisValue); - GateRef elementSize = GetElementSize(type); - BRANCH(Int32GreaterThan(Int32Add(index, elementSize), size), slowPath, &setValue); + GateRef size = ZExtInt32ToInt64(GetByteLength(thisValue)); + GateRef elementSize = ZExtInt32ToInt64(GetElementSize(type)); + GateRef indexInt64 = ZExtInt32ToInt64(index); + BRANCH(Int64UnsignedGreaterThan(Int64Add(indexInt64, elementSize), size), slowPath, &setValue); Bind(&setValue); { - GateRef bufferIndex = Int32Add(index, offset); + GateRef offset = ZExtInt32ToInt64(GetByteOffset(thisValue)); + GateRef bufferIndex = TruncInt64ToInt32(Int64Add(indexInt64, offset)); BuiltinsTypedArrayStubBuilder builder(this); GateRef pointer = builder.GetDataPointFromBuffer(buffer); GateRef doubleValue = TaggedGetNumber(value); diff --git a/ecmascript/compiler/builtins/builtins_object_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_object_stub_builder.cpp index cc077808631039ad933ab9fb62324f61bfacdf11..2f52d1ff2ae19e3480256d35b2223022e1e61006 100644 --- a/ecmascript/compiler/builtins/builtins_object_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_object_stub_builder.cpp @@ -760,7 +760,7 @@ void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, La } } -GateRef BuiltinsObjectStubBuilder::GetNumKeysFromLayoutInfo(GateRef object, GateRef end, GateRef layoutInfo) +GateRef BuiltinsObjectStubBuilder::GetNumKeysFromLayoutInfo(GateRef end, GateRef layoutInfo) { auto env = GetEnvironment(); Label entry(env); @@ -773,7 +773,6 @@ GateRef BuiltinsObjectStubBuilder::GetNumKeysFromLayoutInfo(GateRef object, Gate Label loopEnd(env); Label iLessEnd(env); Label isString(env); - Label initializedProp(env); Label isEnumerable(env); Jump(&loopHead); LoopBegin(&loopHead); @@ -784,8 +783,6 @@ GateRef BuiltinsObjectStubBuilder::GetNumKeysFromLayoutInfo(GateRef object, Gate GateRef key = GetKey(layoutInfo, *i); BRANCH(TaggedIsString(key), &isString, &loopEnd); Bind(&isString); - BRANCH(IsUninitializedProperty(object, *i, layoutInfo), &loopEnd, &initializedProp); - Bind(&initializedProp); BRANCH(IsEnumerable(GetAttr(layoutInfo, *i)), &isEnumerable, &loopEnd); Bind(&isEnumerable); result = Int32Add(*result, Int32(1)); @@ -801,52 +798,6 @@ GateRef BuiltinsObjectStubBuilder::GetNumKeysFromLayoutInfo(GateRef object, Gate return ret; } -GateRef BuiltinsObjectStubBuilder::IsUninitializedProperty(GateRef object, GateRef index, GateRef layoutInfo) -{ - auto env = GetEnvironment(); - Label entry(env); - env->SubCfgEntry(&entry); - Label exit(env); - DEFVARIABLE(value, VariableType::JS_ANY(), Undefined()); - DEFVARIABLE(result, VariableType::BOOL(), False()); - - Label inlinedProp(env); - GateRef attr = GetAttr(layoutInfo, index); - GateRef rep = GetRepInPropAttr(attr); - GateRef hclass = LoadHClass(object); - BRANCH(IsInlinedProperty(attr), &inlinedProp, &exit); - Bind(&inlinedProp); - { - value = GetPropertyInlinedProps(object, hclass, index); - result = TaggedIsHole(*value); - Label nonDoubleToTagged(env); - Label doubleToTagged(env); - BRANCH(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged); - Bind(&doubleToTagged); - { - value = TaggedPtrToTaggedDoublePtr(*value); - result = TaggedIsHole(*value); - Jump(&exit); - } - Bind(&nonDoubleToTagged); - { - Label intToTagged(env); - BRANCH(IsIntRepInPropAttr(rep), &intToTagged, &exit); - Bind(&intToTagged); - { - value = TaggedPtrToTaggedIntPtr(*value); - result = TaggedIsHole(*value); - Jump(&exit); - } - } - } - - Bind(&exit); - auto ret = *result; - env->SubCfgExit(); - return ret; -} - GateRef BuiltinsObjectStubBuilder::GetNumKeysFromDictionary(GateRef array) { auto env = GetEnvironment(); @@ -864,7 +815,6 @@ GateRef BuiltinsObjectStubBuilder::GetNumKeysFromDictionary(GateRef array) Label afterLoop(env); Label iLessSize(env); Label isString(env); - Label initializedProp(env); Label isEnumerable(env); Jump(&loopHead); @@ -895,8 +845,7 @@ GateRef BuiltinsObjectStubBuilder::GetNumKeysFromDictionary(GateRef array) return ret; } -void BuiltinsObjectStubBuilder::LayoutInfoGetAllEnumKeys(GateRef end, GateRef offset, - GateRef array, GateRef object, GateRef layoutInfo) +void BuiltinsObjectStubBuilder::LayoutInfoGetAllEnumKeys(GateRef end, GateRef offset, GateRef array, GateRef layoutInfo) { auto env = GetEnvironment(); Label entry(env); @@ -909,7 +858,6 @@ void BuiltinsObjectStubBuilder::LayoutInfoGetAllEnumKeys(GateRef end, GateRef of Label afterLoop(env); Label iLessEnd(env); Label isEnumerable(env); - Label initializedProp(env); Jump(&loopHead); LoopBegin(&loopHead); { @@ -921,8 +869,6 @@ void BuiltinsObjectStubBuilder::LayoutInfoGetAllEnumKeys(GateRef end, GateRef of BRANCH(LogicAndBuilder(env).And(TaggedIsString(key)).And(IsEnumerable(GetAttr(layoutInfo, iVal))).Done(), &isEnumerable, &loopEnd); Bind(&isEnumerable); - BRANCH(IsUninitializedProperty(object, *i, layoutInfo), &loopEnd, &initializedProp); - Bind(&initializedProp); SetValueToTaggedArray(VariableType::JS_ANY(), glue_, array, Int32Add(*enumKeys, offset), key); enumKeys = Int32Add(*enumKeys, Int32(1)); Jump(&loopEnd); @@ -966,7 +912,7 @@ GateRef BuiltinsObjectStubBuilder::CopyFromEnumCache(GateRef glue, GateRef eleme Bind(&afterLenCon); GateRef array = newBuilder.NewTaggedArray(glue, *newLen); Store(VariableType::INT32(), glue, array, IntPtr(TaggedArray::LENGTH_OFFSET), *newLen); - GateRef oldExtractLen = GetExtractLengthOfTaggedArray(elements); + GateRef oldExtractLen = GetExtraLengthOfTaggedArray(elements); Store(VariableType::INT32(), glue, array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen); Label loopHead(env); Label loopEnd(env); @@ -1036,7 +982,7 @@ GateRef BuiltinsObjectStubBuilder::GetAllEnumKeys(GateRef glue, GateRef obj) Label isOnlyOwnKeys(env); Label notOnlyOwnKeys(env); GateRef layout = GetLayoutFromHClass(hclass); - GateRef numOfKeys = GetNumKeysFromLayoutInfo(obj, num, layout); + GateRef numOfKeys = GetNumKeysFromLayoutInfo(num, layout); // JSObject::GetAllEnumKeys GateRef enumCache = GetEnumCacheFromHClass(hclass); GateRef kind = GetEnumCacheKind(glue, enumCache); @@ -1057,7 +1003,7 @@ GateRef BuiltinsObjectStubBuilder::GetAllEnumKeys(GateRef glue, GateRef obj) NewObjectStubBuilder newBuilder(this); GateRef keyArray = newBuilder.NewTaggedArray(glue, Int32Add(numOfKeys, Int32(static_cast(EnumCache::ENUM_CACHE_HEADER_SIZE)))); - LayoutInfoGetAllEnumKeys(num, Int32(EnumCache::ENUM_CACHE_HEADER_SIZE), keyArray, obj, layout); + LayoutInfoGetAllEnumKeys(num, Int32(EnumCache::ENUM_CACHE_HEADER_SIZE), keyArray, layout); SetValueToTaggedArray(VariableType::JS_ANY(), glue, keyArray, Int32(EnumCache::ENUM_CACHE_KIND_OFFSET), IntToTaggedInt(Int32(static_cast(EnumCacheKind::ONLY_OWN_KEYS)))); @@ -1814,15 +1760,10 @@ GateRef BuiltinsObjectStubBuilder::GetAllPropertyKeys(GateRef glue, GateRef obj, BRANCH(Int32UnsignedLessThan(*i, number), &next, &loopExit); Bind(&next); { - Label checkString(env); Label checkSymbol(env); Label setValue(env); GateRef key = GetKey(layout, *i); - BRANCH(TaggedIsString(key), &checkString, &checkSymbol); - Bind(&checkString); - { - BRANCH(IsUninitializedProperty(obj, *i, layout), &checkSymbol, &setValue); - } + BRANCH(TaggedIsString(key), &setValue, &checkSymbol); Bind(&checkSymbol); { BRANCH(TaggedIsSymbol(key), &setValue, &loopEnd); diff --git a/ecmascript/compiler/builtins/builtins_object_stub_builder.h b/ecmascript/compiler/builtins/builtins_object_stub_builder.h index 3f3173b3a0d6d7b8fd6ee0d9fc65bcb73ef66de0..2eaf88e6e49c06ea952c817c0c91105ff395cce7 100644 --- a/ecmascript/compiler/builtins/builtins_object_stub_builder.h +++ b/ecmascript/compiler/builtins/builtins_object_stub_builder.h @@ -42,8 +42,7 @@ BUILTINS_WITH_OBJECT_STUB_BUILDER(DECLARE_BUILTINS_OBJECT_STUB_BUILDER) GateRef hir = Circuit::NullGate()); private: - GateRef GetNumKeysFromLayoutInfo(GateRef object, GateRef end, GateRef layoutInfo); - GateRef IsUninitializedProperty(GateRef object, GateRef index, GateRef layoutInfo); + GateRef GetNumKeysFromLayoutInfo(GateRef end, GateRef layoutInfo); GateRef GetNumKeysFromDictionary(GateRef array); GateRef CopyFromEnumCache(GateRef glue, GateRef elements); GateRef GetAllEnumKeys(GateRef glue, GateRef obj); @@ -55,7 +54,7 @@ private: GateRef TestIntegrityLevel(GateRef glue, GateRef obj, GateRef level, Label *slowPath); GateRef ObjectSetPrototype(GateRef glue, GateRef obj, GateRef proto); GateRef IsNotSlowObjectKey(GateRef obj); - void LayoutInfoGetAllEnumKeys(GateRef end, GateRef offset, GateRef array, GateRef object, GateRef layoutInfo); + void LayoutInfoGetAllEnumKeys(GateRef end, GateRef offset, GateRef array, GateRef layoutInfo); void AssignEnumElementProperty(Variable *res, Label *funcExit, GateRef toAssign, GateRef source); void LayoutInfoAssignAllEnumProperty(Variable *res, Label *funcExit, GateRef toAssign, GateRef source); void NameDictionaryAssignAllEnumProperty(Variable *res, Label *funcExit, GateRef toAssign, GateRef source, diff --git a/ecmascript/compiler/builtins/builtins_typedarray_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_typedarray_stub_builder.cpp index 0e7ad3e9be0e2f811c4b36237836672cd9ae1f22..c5da44df04e578dee185d3028f05883c21528acd 100644 --- a/ecmascript/compiler/builtins/builtins_typedarray_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_typedarray_stub_builder.cpp @@ -450,51 +450,7 @@ void BuiltinsTypedArrayStubBuilder::Reverse(GateRef glue, GateRef thisValue, [[m GateRef buffer = GetViewedArrayBuffer(thisValue); BRANCH(IsDetachedBuffer(buffer), slowPath, ¬Detached); Bind(¬Detached); - - DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); - GateRef middle = Int64Div(*thisArrLen, Int64(2)); - DEFVARIABLE(lower, VariableType::INT64(), Int64(0)); - Label loopHead(env); - Label loopEnd(env); - Label loopNext(env); - Label loopExit(env); - Jump(&loopHead); - LoopBegin(&loopHead); - { - BRANCH(Int64NotEqual(*lower, middle), &loopNext, &loopExit); - Bind(&loopNext); - { - DEFVARIABLE(upper, VariableType::INT64(), Int64Sub(Int64Sub(*thisArrLen, *lower), Int64(1))); - Label hasException0(env); - Label hasException1(env); - Label notHasException0(env); - GateRef lowerValue = FastGetPropertyByIndex(glue, thisValue, - TruncInt64ToInt32(*lower), arrayType); - GateRef upperValue = FastGetPropertyByIndex(glue, thisValue, - TruncInt64ToInt32(*upper), arrayType); - BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); - Bind(&hasException0); - { - result->WriteVariable(Exception()); - Jump(exit); - } - Bind(¬HasException0); - { - StoreTypedArrayElement(glue, thisValue, *lower, upperValue, arrayType); - StoreTypedArrayElement(glue, thisValue, *upper, lowerValue, arrayType); - BRANCH(HasPendingException(glue), &hasException1, &loopEnd); - Bind(&hasException1); - { - result->WriteVariable(Exception()); - Jump(exit); - } - } - } - } - Bind(&loopEnd); - lower = Int64Add(*lower, Int64(1)); - LoopEnd(&loopHead); - Bind(&loopExit); + CallNGCRuntime(glue, RTSTUB_ID(ReverseTypedArray), {thisValue}); result->WriteVariable(thisValue); Jump(exit); } @@ -2137,7 +2093,11 @@ void BuiltinsTypedArrayStubBuilder::Sort( GateRef callbackFnHandle = GetCallArg0(numArgs); BRANCH(TaggedIsUndefined(callbackFnHandle), &argUndefined, slowPath); Bind(&argUndefined); - DoSort(glue, thisValue, result, exit, slowPath); + Label notDetached(env); + GateRef buffer = GetViewedArrayBuffer(thisValue); + BRANCH(IsDetachedBuffer(buffer), slowPath, ¬Detached); + Bind(¬Detached); + CallNGCRuntime(glue, RTSTUB_ID(SortTypedArray), {thisValue}); result->WriteVariable(thisValue); Jump(exit); } diff --git a/ecmascript/compiler/bytecodes.cpp b/ecmascript/compiler/bytecodes.cpp index 6b26dfd49806d0dedc270fc6e93f266dfb5aced9..cda3990b02d909a8ed14ab551f7bdf495d3635a7 100644 --- a/ecmascript/compiler/bytecodes.cpp +++ b/ecmascript/compiler/bytecodes.cpp @@ -29,196 +29,263 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc) flags |= BytecodeFlags::WRITE_ACC; } - switch (inst.GetOpcode()) { - case EcmaOpcode::GETPROPITERATOR: - case EcmaOpcode::TYPEOF_IMM8: - case EcmaOpcode::TYPEOF_IMM16: - case EcmaOpcode::LDSYMBOL: - case EcmaOpcode::LDGLOBAL: - case EcmaOpcode::LDBIGINT_ID16: - case EcmaOpcode::LDEXTERNALMODULEVAR_IMM8: - case EcmaOpcode::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16: - case EcmaOpcode::GETMODULENAMESPACE_IMM8: - case EcmaOpcode::WIDE_GETMODULENAMESPACE_PREF_IMM16: - case EcmaOpcode::ISTRUE: - case EcmaOpcode::ISFALSE: - case EcmaOpcode::CALLRUNTIME_ISTRUE_PREF_IMM8: - case EcmaOpcode::CALLRUNTIME_ISFALSE_PREF_IMM8: - case EcmaOpcode::LDGLOBALVAR_IMM16_ID16: - case EcmaOpcode::LDOBJBYINDEX_IMM8_IMM16: - case EcmaOpcode::LDOBJBYINDEX_IMM16_IMM16: - case EcmaOpcode::WIDE_LDOBJBYINDEX_PREF_IMM32: - case EcmaOpcode::LDLEXVAR_IMM4_IMM4: - case EcmaOpcode::LDLEXVAR_IMM8_IMM8: - case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16: - case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4: - case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16: - case EcmaOpcode::WIDE_LDPATCHVAR_PREF_IMM16: - case EcmaOpcode::LDLOCALMODULEVAR_IMM8: - case EcmaOpcode::WIDE_LDLOCALMODULEVAR_PREF_IMM16: - case EcmaOpcode::LDA_STR_ID16: - case EcmaOpcode::CALLRUNTIME_LDSENDABLECLASS_PREF_IMM16: - flags |= BytecodeFlags::NO_SIDE_EFFECTS; + EcmaOpcode opcode = inst.GetOpcode(); + InitBytecodeFlags(opcode, flags); + InitBytecodeKind(opcode, kind); + + if (kind == BytecodeKind::GENERAL || + kind == BytecodeKind::THROW_BC || + kind == BytecodeKind::RESUME || + kind == BytecodeKind::SUSPEND || + kind == BytecodeKind::GENERATOR_RESOLVE || + kind == BytecodeKind::CALL_BC || + kind == BytecodeKind::ACCESSOR_BC) { + flags |= BytecodeFlags::GENERAL_BC; + } + auto size = inst.GetSize(); + auto vregCount = GetVRegCount(inst); + uint64_t value = SizeField::Encode(size) | KindField::Encode(kind) | + FlagsField::Encode(static_cast(flags)) | + OpcodeField::Encode(inst.GetOpcode()) | VRegCountField::Encode(vregCount); + return BytecodeMetaData(value); +} + +void BytecodeMetaData::InitBytecodeFlags(EcmaOpcode &opcode, uint32_t &flags) +{ + InitNoSideEffectFlag(opcode, flags); + InitNoGCFlag(opcode, flags); + InitNoThrowFlag(opcode, flags); + InitReadThisObjectFlag(opcode, flags); + InitSupportDeoptFlag(opcode, flags); + InitReadACCFlag(opcode, flags); + InitDebuggerFlag(opcode, flags); + InitReadFuncFlag(opcode, flags); + InitWriteEnvFlag(opcode, flags); + InitReadEnvFlag(opcode, flags); + InitReadNewTargetFlag(opcode, flags); + InitReadArgcFlag(opcode, flags); +} + +void BytecodeMetaData::InitReadArgcFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { + case EcmaOpcode::GETUNMAPPEDARGS: + case EcmaOpcode::COPYRESTARGS_IMM8: + case EcmaOpcode::WIDE_COPYRESTARGS_PREF_IMM16: + flags |= BytecodeFlags::READ_ARGC; break; default: break; } +} - switch (inst.GetOpcode()) { - case EcmaOpcode::MOV_V4_V4: - case EcmaOpcode::MOV_V8_V8: - case EcmaOpcode::MOV_V16_V16: - case EcmaOpcode::STA_V8: - case EcmaOpcode::LDA_V8: - case EcmaOpcode::LDHOLE: - case EcmaOpcode::LDAI_IMM32: - case EcmaOpcode::FLDAI_IMM64: - case EcmaOpcode::LDFUNCTION: - case EcmaOpcode::TYPEOF_IMM8: - case EcmaOpcode::TYPEOF_IMM16: - case EcmaOpcode::LDNAN: - case EcmaOpcode::LDINFINITY: - case EcmaOpcode::LDUNDEFINED: - case EcmaOpcode::LDNULL: - case EcmaOpcode::LDTRUE: - case EcmaOpcode::LDFALSE: - case EcmaOpcode::LDSYMBOL: - case EcmaOpcode::LDGLOBAL: - case EcmaOpcode::LDBIGINT_ID16: - case EcmaOpcode::LDLEXVAR_IMM4_IMM4: - case EcmaOpcode::LDLEXVAR_IMM8_IMM8: - case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16: - case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4: - case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16: - case EcmaOpcode::WIDE_LDPATCHVAR_PREF_IMM16: - case EcmaOpcode::LDA_STR_ID16: - case EcmaOpcode::CALLRUNTIME_LDSENDABLECLASS_PREF_IMM16: - case EcmaOpcode::RETURN: - case EcmaOpcode::RETURNUNDEFINED: - flags |= BytecodeFlags::NO_GC; +void BytecodeMetaData::InitReadNewTargetFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { + case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8: + case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8: + case EcmaOpcode::SUPERCALLARROWRANGE_IMM8_IMM8_V8: + case EcmaOpcode::WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8: + case EcmaOpcode::SUPERCALLSPREAD_IMM8_V8: + case EcmaOpcode::CALLRUNTIME_SUPERCALLFORWARDALLARGS_PREF_V8: + flags |= BytecodeFlags::READ_NEWTARGET; break; default: break; } +} - switch (inst.GetOpcode()) { - case EcmaOpcode::MOV_V4_V4: - case EcmaOpcode::MOV_V8_V8: - case EcmaOpcode::MOV_V16_V16: - case EcmaOpcode::STA_V8: - case EcmaOpcode::LDA_V8: - case EcmaOpcode::LDNAN: - case EcmaOpcode::LDINFINITY: - case EcmaOpcode::LDUNDEFINED: - case EcmaOpcode::LDNULL: - case EcmaOpcode::LDTRUE: - case EcmaOpcode::LDFALSE: - case EcmaOpcode::LDHOLE: - case EcmaOpcode::LDAI_IMM32: - case EcmaOpcode::FLDAI_IMM64: - case EcmaOpcode::LDFUNCTION: - case EcmaOpcode::LDA_STR_ID16: - case EcmaOpcode::TYPEOF_IMM8: - case EcmaOpcode::TYPEOF_IMM16: - case EcmaOpcode::ISTRUE: - case EcmaOpcode::ISFALSE: - case EcmaOpcode::CALLRUNTIME_ISTRUE_PREF_IMM8: - case EcmaOpcode::CALLRUNTIME_ISFALSE_PREF_IMM8: - case EcmaOpcode::JEQZ_IMM8: - case EcmaOpcode::JEQZ_IMM16: - case EcmaOpcode::JEQZ_IMM32: - case EcmaOpcode::JNEZ_IMM8: - case EcmaOpcode::JNEZ_IMM16: - case EcmaOpcode::JNEZ_IMM32: - case EcmaOpcode::JMP_IMM8: - case EcmaOpcode::JMP_IMM16: - case EcmaOpcode::JMP_IMM32: - case EcmaOpcode::STMODULEVAR_IMM8: - case EcmaOpcode::WIDE_STMODULEVAR_PREF_IMM16: - case EcmaOpcode::LDEXTERNALMODULEVAR_IMM8: - case EcmaOpcode::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16: +void BytecodeMetaData::InitReadEnvFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { case EcmaOpcode::NEWLEXENV_IMM8: case EcmaOpcode::WIDE_NEWLEXENV_PREF_IMM16: - case EcmaOpcode::CALLRUNTIME_NEWSENDABLEENV_PREF_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDENEWSENDABLEENV_PREF_IMM16: - case EcmaOpcode::POPLEXENV: case EcmaOpcode::NEWLEXENVWITHNAME_IMM8_ID16: case EcmaOpcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16: - case EcmaOpcode::ASYNCFUNCTIONENTER: - case EcmaOpcode::SETGENERATORSTATE_IMM8: - case EcmaOpcode::GETRESUMEMODE: - case EcmaOpcode::RESUMEGENERATOR: - case EcmaOpcode::RETURN: - case EcmaOpcode::RETURNUNDEFINED: + case EcmaOpcode::POPLEXENV: case EcmaOpcode::LDLEXVAR_IMM4_IMM4: case EcmaOpcode::LDLEXVAR_IMM8_IMM8: case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16: - case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4: - case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16: - case EcmaOpcode::STLEXVAR_IMM4_IMM4: - case EcmaOpcode::STLEXVAR_IMM8_IMM8: - case EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16: - case EcmaOpcode::CALLRUNTIME_STSENDABLEVAR_PREF_IMM4_IMM4: - case EcmaOpcode::CALLRUNTIME_STSENDABLEVAR_PREF_IMM8_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDESTSENDABLEVAR_PREF_IMM16_IMM16: - case EcmaOpcode::STRICTNOTEQ_IMM8_V8: - case EcmaOpcode::STRICTEQ_IMM8_V8: - case EcmaOpcode::CREATEEMPTYARRAY_IMM8: - case EcmaOpcode::CREATEEMPTYARRAY_IMM16: - case EcmaOpcode::CREATEEMPTYOBJECT: - case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: - case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: - case EcmaOpcode::CREATEITERRESULTOBJ_V8_V8: + case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: + case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: + case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: + case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: case EcmaOpcode::DEFINEMETHOD_IMM8_ID16_IMM8: case EcmaOpcode::DEFINEMETHOD_IMM16_ID16_IMM8: + case EcmaOpcode::LDPRIVATEPROPERTY_IMM8_IMM16_IMM16: + case EcmaOpcode::STPRIVATEPROPERTY_IMM8_IMM16_IMM16_V8: + case EcmaOpcode::TESTIN_IMM8_IMM16_IMM16: + case EcmaOpcode::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16: + case EcmaOpcode::CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM8_IMM16_IMM16_V8: case EcmaOpcode::CALLRUNTIME_LDSENDABLECLASS_PREF_IMM16: - case EcmaOpcode::DEBUGGER: - case EcmaOpcode::NOP: - flags |= BytecodeFlags::NO_THROW; + flags |= BytecodeFlags::READ_ENV; break; default: break; } +} - switch (inst.GetOpcode()) { - case EcmaOpcode::MOV_V4_V4: - case EcmaOpcode::MOV_V8_V8: - case EcmaOpcode::MOV_V16_V16: - case EcmaOpcode::STA_V8: - case EcmaOpcode::LDA_V8: - kind = BytecodeKind::MOV; - flags |= BytecodeFlags::NO_SIDE_EFFECTS; +void BytecodeMetaData::InitWriteEnvFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { + case EcmaOpcode::NEWLEXENV_IMM8: + case EcmaOpcode::WIDE_NEWLEXENV_PREF_IMM16: + case EcmaOpcode::NEWLEXENVWITHNAME_IMM8_ID16: + case EcmaOpcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16: + case EcmaOpcode::POPLEXENV: + flags |= BytecodeFlags::WRITE_ENV; break; - case EcmaOpcode::LDNAN: - case EcmaOpcode::LDINFINITY: - case EcmaOpcode::LDUNDEFINED: - case EcmaOpcode::LDNULL: - case EcmaOpcode::LDTRUE: - case EcmaOpcode::LDFALSE: - case EcmaOpcode::LDHOLE: - case EcmaOpcode::LDAI_IMM32: - case EcmaOpcode::FLDAI_IMM64: - case EcmaOpcode::LDFUNCTION: - kind = BytecodeKind::SET_CONSTANT; - flags |= BytecodeFlags::NO_SIDE_EFFECTS; + default: break; + } +} + +void BytecodeMetaData::InitReadFuncFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { + case EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE: + case EcmaOpcode::SUSPENDGENERATOR_V8: + case EcmaOpcode::RESUMEGENERATOR: + case EcmaOpcode::TRYLDGLOBALBYNAME_IMM8_ID16: + case EcmaOpcode::TRYLDGLOBALBYNAME_IMM16_ID16: + case EcmaOpcode::STGLOBALVAR_IMM16_ID16: + case EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16: + case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: + case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: + case EcmaOpcode::DEFINEMETHOD_IMM8_ID16_IMM8: + case EcmaOpcode::DEFINEMETHOD_IMM16_ID16_IMM8: + case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: + case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: + case EcmaOpcode::INSTANCEOF_IMM8_V8: + case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: + case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: + case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: + case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: + case EcmaOpcode::STMODULEVAR_IMM8: + case EcmaOpcode::WIDE_STMODULEVAR_PREF_IMM16: + case EcmaOpcode::SETGENERATORSTATE_IMM8: + case EcmaOpcode::DYNAMICIMPORT: + case EcmaOpcode::LDEXTERNALMODULEVAR_IMM8: + case EcmaOpcode::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16: + case EcmaOpcode::GETMODULENAMESPACE_IMM8: + case EcmaOpcode::WIDE_GETMODULENAMESPACE_PREF_IMM16: + case EcmaOpcode::NEWLEXENVWITHNAME_IMM8_ID16: + case EcmaOpcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16: + case EcmaOpcode::LDSUPERBYVALUE_IMM8_V8: + case EcmaOpcode::LDSUPERBYVALUE_IMM16_V8: + case EcmaOpcode::STSUPERBYVALUE_IMM16_V8_V8: + case EcmaOpcode::STSUPERBYVALUE_IMM8_V8_V8: + case EcmaOpcode::TRYSTGLOBALBYNAME_IMM8_ID16: + case EcmaOpcode::TRYSTGLOBALBYNAME_IMM16_ID16: + case EcmaOpcode::LDGLOBALVAR_IMM16_ID16: + case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: + case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: + case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: + case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: + case EcmaOpcode::LDOBJBYVALUE_IMM8_V8: + case EcmaOpcode::LDOBJBYVALUE_IMM16_V8: case EcmaOpcode::LDTHISBYVALUE_IMM8: case EcmaOpcode::LDTHISBYVALUE_IMM16: + case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8: + case EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8: case EcmaOpcode::STTHISBYVALUE_IMM8_V8: case EcmaOpcode::STTHISBYVALUE_IMM16_V8: - flags |= BytecodeFlags::READ_THIS_OBJECT; - break; + case EcmaOpcode::LDSUPERBYNAME_IMM8_ID16: + case EcmaOpcode::LDSUPERBYNAME_IMM16_ID16: + case EcmaOpcode::STSUPERBYNAME_IMM8_ID16_V8: + case EcmaOpcode::STSUPERBYNAME_IMM16_ID16_V8: + case EcmaOpcode::LDLOCALMODULEVAR_IMM8: + case EcmaOpcode::WIDE_LDLOCALMODULEVAR_PREF_IMM16: + case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: + case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: + case EcmaOpcode::STTHISBYNAME_IMM8_ID16: + case EcmaOpcode::STTHISBYNAME_IMM16_ID16: + case EcmaOpcode::ASYNCGENERATORRESOLVE_V8_V8_V8: + case EcmaOpcode::CALLARG0_IMM8: + case EcmaOpcode::CALLARG1_IMM8_V8: + case EcmaOpcode::CALLARGS2_IMM8_V8_V8: + case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8: + case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: + case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8: + case EcmaOpcode::CALLTHIS0_IMM8_V8: + case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: + case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: + case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: + case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: + case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: + case EcmaOpcode::LDA_STR_ID16: + case EcmaOpcode::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8: + case EcmaOpcode::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8: + case EcmaOpcode::STTOGLOBALRECORD_IMM16_ID16: + case EcmaOpcode::STCONSTTOGLOBALRECORD_IMM16_ID16: + case EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8: + case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8: + case EcmaOpcode::CREATEREGEXPWITHLITERAL_IMM8_ID16_IMM8: + case EcmaOpcode::CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8: + case EcmaOpcode::LDBIGINT_ID16: + case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8: + case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8: + case EcmaOpcode::CALLRUNTIME_DEFINEFIELDBYVALUE_PREF_IMM8_V8_V8: + case EcmaOpcode::CALLRUNTIME_DEFINEFIELDBYINDEX_PREF_IMM8_IMM32_V8: + case EcmaOpcode::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16: + case EcmaOpcode::CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM8_IMM16_IMM16_V8: + case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: + case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8: + case EcmaOpcode::CALLRUNTIME_LDSENDABLEEXTERNALMODULEVAR_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEEXTERNALMODULEVAR_PREF_IMM16: + case EcmaOpcode::CALLRUNTIME_STSENDABLEVAR_PREF_IMM4_IMM4: + case EcmaOpcode::CALLRUNTIME_STSENDABLEVAR_PREF_IMM8_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDESTSENDABLEVAR_PREF_IMM16_IMM16: + case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4: + case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16: + case EcmaOpcode::CALLRUNTIME_NEWSENDABLEENV_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDENEWSENDABLEENV_PREF_IMM16: + case EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16: + case EcmaOpcode::CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16: + case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8: + case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8: + flags |= BytecodeFlags::READ_FUNC; + break; + default: + break; + } +} + +void BytecodeMetaData::InitDebuggerFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { + case EcmaOpcode::DEBUGGER: + flags |= BytecodeFlags::DEBUGGER_STMT; + break; + default: + break; + } +} + +void BytecodeMetaData::InitReadACCFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { + case EcmaOpcode::RETURN: + case EcmaOpcode::ASYNCGENERATORRESOLVE_V8_V8_V8: + flags |= BytecodeFlags::READ_ACC; + break; + default: + break; + } +} + +void BytecodeMetaData::InitSupportDeoptFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: case EcmaOpcode::STTHISBYNAME_IMM8_ID16: case EcmaOpcode::STTHISBYNAME_IMM16_ID16: - flags |= BytecodeFlags::READ_THIS_OBJECT; - [[fallthrough]]; case EcmaOpcode::ADD2_IMM8_V8: case EcmaOpcode::SUB2_IMM8_V8: case EcmaOpcode::MUL2_IMM8_V8: @@ -273,8 +340,6 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc) case EcmaOpcode::CALLRUNTIME_TOPROPERTYKEY_PREF_NONE: case EcmaOpcode::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16: case EcmaOpcode::CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM8_IMM16_IMM16_V8: - flags |= BytecodeFlags::SUPPORT_DEOPT; - break; case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: case EcmaOpcode::CALLARG0_IMM8: case EcmaOpcode::CALLARG1_IMM8_V8: @@ -290,252 +355,453 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc) case EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8: case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8: flags |= BytecodeFlags::SUPPORT_DEOPT; - kind = BytecodeKind::CALL_BC; break; - case EcmaOpcode::RETURN: - flags |= BytecodeFlags::READ_ACC; - [[fallthrough]]; - case EcmaOpcode::RETURNUNDEFINED: - flags |= BytecodeFlags::NO_SIDE_EFFECTS; - kind = BytecodeKind::RETURN_BC; + default: break; + } +} + +void BytecodeMetaData::InitReadThisObjectFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { + case EcmaOpcode::LDTHISBYVALUE_IMM8: + case EcmaOpcode::LDTHISBYVALUE_IMM16: + case EcmaOpcode::STTHISBYVALUE_IMM8_V8: + case EcmaOpcode::STTHISBYVALUE_IMM16_V8: + case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: + case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: + case EcmaOpcode::STTHISBYNAME_IMM8_ID16: + case EcmaOpcode::STTHISBYNAME_IMM16_ID16: case EcmaOpcode::SUSPENDGENERATOR_V8: - flags |= BytecodeFlags::READ_THIS_OBJECT; - U_FALLTHROUGH; case EcmaOpcode::DEPRECATED_SUSPENDGENERATOR_PREF_V8_V8: - kind = BytecodeKind::SUSPEND; - break; - case EcmaOpcode::RESUMEGENERATOR: - kind = BytecodeKind::RESUME; + case EcmaOpcode::ASYNCGENERATORRESOLVE_V8_V8_V8: + flags |= BytecodeFlags::READ_THIS_OBJECT; break; - case EcmaOpcode::DEBUGGER: - flags |= BytecodeFlags::DEBUGGER_STMT; + default: break; + } +} + +void BytecodeMetaData::InitNoSideEffectFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { + case EcmaOpcode::GETPROPITERATOR: + case EcmaOpcode::TYPEOF_IMM8: + case EcmaOpcode::TYPEOF_IMM16: + case EcmaOpcode::LDSYMBOL: + case EcmaOpcode::LDGLOBAL: + case EcmaOpcode::LDBIGINT_ID16: + case EcmaOpcode::LDEXTERNALMODULEVAR_IMM8: + case EcmaOpcode::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16: + case EcmaOpcode::GETMODULENAMESPACE_IMM8: + case EcmaOpcode::WIDE_GETMODULENAMESPACE_PREF_IMM16: + case EcmaOpcode::ISTRUE: + case EcmaOpcode::ISFALSE: + case EcmaOpcode::CALLRUNTIME_ISTRUE_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_ISFALSE_PREF_IMM8: + case EcmaOpcode::LDGLOBALVAR_IMM16_ID16: + case EcmaOpcode::LDOBJBYINDEX_IMM8_IMM16: + case EcmaOpcode::LDOBJBYINDEX_IMM16_IMM16: + case EcmaOpcode::WIDE_LDOBJBYINDEX_PREF_IMM32: + case EcmaOpcode::LDLEXVAR_IMM4_IMM4: + case EcmaOpcode::LDLEXVAR_IMM8_IMM8: + case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16: + case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4: + case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16: + case EcmaOpcode::WIDE_LDPATCHVAR_PREF_IMM16: + case EcmaOpcode::LDLOCALMODULEVAR_IMM8: + case EcmaOpcode::WIDE_LDLOCALMODULEVAR_PREF_IMM16: + case EcmaOpcode::LDA_STR_ID16: + case EcmaOpcode::CALLRUNTIME_LDSENDABLECLASS_PREF_IMM16: + case EcmaOpcode::MOV_V4_V4: + case EcmaOpcode::MOV_V8_V8: + case EcmaOpcode::MOV_V16_V16: + case EcmaOpcode::STA_V8: + case EcmaOpcode::LDA_V8: + case EcmaOpcode::LDNAN: + case EcmaOpcode::LDINFINITY: + case EcmaOpcode::LDUNDEFINED: + case EcmaOpcode::LDNULL: + case EcmaOpcode::LDTRUE: + case EcmaOpcode::LDFALSE: + case EcmaOpcode::LDHOLE: + case EcmaOpcode::LDAI_IMM32: + case EcmaOpcode::FLDAI_IMM64: + case EcmaOpcode::LDFUNCTION: + case EcmaOpcode::RETURN: + case EcmaOpcode::RETURNUNDEFINED: case EcmaOpcode::NOP: - kind = BytecodeKind::DISCARDED; - flags |= BytecodeFlags::NO_SIDE_EFFECTS; - break; - case EcmaOpcode::THROW_PREF_NONE: - case EcmaOpcode::THROW_NOTEXISTS_PREF_NONE: - case EcmaOpcode::THROW_PATTERNNONCOERCIBLE_PREF_NONE: - case EcmaOpcode::THROW_DELETESUPERPROPERTY_PREF_NONE: - case EcmaOpcode::THROW_CONSTASSIGNMENT_PREF_V8: - kind = BytecodeKind::THROW_BC; - break; case EcmaOpcode::JEQZ_IMM8: case EcmaOpcode::JEQZ_IMM16: case EcmaOpcode::JEQZ_IMM32: case EcmaOpcode::JNEZ_IMM8: case EcmaOpcode::JNEZ_IMM16: case EcmaOpcode::JNEZ_IMM32: - kind = BytecodeKind::CONDITIONAL_JUMP; - flags |= BytecodeFlags::NO_SIDE_EFFECTS; - break; case EcmaOpcode::JMP_IMM8: case EcmaOpcode::JMP_IMM16: case EcmaOpcode::JMP_IMM32: - kind = BytecodeKind::JUMP_IMM; flags |= BytecodeFlags::NO_SIDE_EFFECTS; break; - case EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE: - flags |= BytecodeFlags::READ_FUNC; - break; - case EcmaOpcode::ASYNCGENERATORRESOLVE_V8_V8_V8: - flags |= BytecodeFlags::READ_THIS_OBJECT; - flags |= BytecodeFlags::READ_ACC; - kind = BytecodeKind::GENERATOR_RESOLVE; - break; default: break; } +} - switch (inst.GetOpcode()) { - case EcmaOpcode::NEWLEXENV_IMM8: - case EcmaOpcode::WIDE_NEWLEXENV_PREF_IMM16: - case EcmaOpcode::NEWLEXENVWITHNAME_IMM8_ID16: - case EcmaOpcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16: - case EcmaOpcode::POPLEXENV: - flags |= BytecodeFlags::WRITE_ENV; - [[fallthrough]]; +void BytecodeMetaData::InitNoGCFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { + case EcmaOpcode::MOV_V4_V4: + case EcmaOpcode::MOV_V8_V8: + case EcmaOpcode::MOV_V16_V16: + case EcmaOpcode::STA_V8: + case EcmaOpcode::LDA_V8: + case EcmaOpcode::LDHOLE: + case EcmaOpcode::LDAI_IMM32: + case EcmaOpcode::FLDAI_IMM64: + case EcmaOpcode::LDFUNCTION: + case EcmaOpcode::TYPEOF_IMM8: + case EcmaOpcode::TYPEOF_IMM16: + case EcmaOpcode::LDNAN: + case EcmaOpcode::LDINFINITY: + case EcmaOpcode::LDUNDEFINED: + case EcmaOpcode::LDNULL: + case EcmaOpcode::LDTRUE: + case EcmaOpcode::LDFALSE: + case EcmaOpcode::LDSYMBOL: + case EcmaOpcode::LDGLOBAL: + case EcmaOpcode::LDBIGINT_ID16: case EcmaOpcode::LDLEXVAR_IMM4_IMM4: case EcmaOpcode::LDLEXVAR_IMM8_IMM8: case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16: - case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: - case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: - case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: - case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: - case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: - case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: - case EcmaOpcode::DEFINEMETHOD_IMM8_ID16_IMM8: - case EcmaOpcode::DEFINEMETHOD_IMM16_ID16_IMM8: - case EcmaOpcode::LDPRIVATEPROPERTY_IMM8_IMM16_IMM16: - case EcmaOpcode::STPRIVATEPROPERTY_IMM8_IMM16_IMM16_V8: - case EcmaOpcode::TESTIN_IMM8_IMM16_IMM16: - case EcmaOpcode::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16: - case EcmaOpcode::CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM8_IMM16_IMM16_V8: + case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4: + case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16: + case EcmaOpcode::WIDE_LDPATCHVAR_PREF_IMM16: + case EcmaOpcode::LDA_STR_ID16: case EcmaOpcode::CALLRUNTIME_LDSENDABLECLASS_PREF_IMM16: - flags |= BytecodeFlags::READ_ENV; + case EcmaOpcode::RETURN: + case EcmaOpcode::RETURNUNDEFINED: + flags |= BytecodeFlags::NO_GC; break; default: break; } +} - switch (inst.GetOpcode()) { - case EcmaOpcode::SUSPENDGENERATOR_V8: - case EcmaOpcode::RESUMEGENERATOR: - case EcmaOpcode::TRYLDGLOBALBYNAME_IMM8_ID16: - case EcmaOpcode::TRYLDGLOBALBYNAME_IMM16_ID16: - case EcmaOpcode::STGLOBALVAR_IMM16_ID16: - case EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16: - case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: - case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: - case EcmaOpcode::DEFINEMETHOD_IMM8_ID16_IMM8: - case EcmaOpcode::DEFINEMETHOD_IMM16_ID16_IMM8: - case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: - case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: - case EcmaOpcode::INSTANCEOF_IMM8_V8: - case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: - case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: - case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: - case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: +void BytecodeMetaData::InitNoThrowFlag(EcmaOpcode &opcode, uint32_t &flags) +{ + switch (opcode) { + case EcmaOpcode::MOV_V4_V4: + case EcmaOpcode::MOV_V8_V8: + case EcmaOpcode::MOV_V16_V16: + case EcmaOpcode::STA_V8: + case EcmaOpcode::LDA_V8: + case EcmaOpcode::LDNAN: + case EcmaOpcode::LDINFINITY: + case EcmaOpcode::LDUNDEFINED: + case EcmaOpcode::LDNULL: + case EcmaOpcode::LDTRUE: + case EcmaOpcode::LDFALSE: + case EcmaOpcode::LDHOLE: + case EcmaOpcode::LDAI_IMM32: + case EcmaOpcode::FLDAI_IMM64: + case EcmaOpcode::LDFUNCTION: + case EcmaOpcode::LDA_STR_ID16: + case EcmaOpcode::TYPEOF_IMM8: + case EcmaOpcode::TYPEOF_IMM16: + case EcmaOpcode::ISTRUE: + case EcmaOpcode::ISFALSE: + case EcmaOpcode::CALLRUNTIME_ISTRUE_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_ISFALSE_PREF_IMM8: + case EcmaOpcode::JEQZ_IMM8: + case EcmaOpcode::JEQZ_IMM16: + case EcmaOpcode::JEQZ_IMM32: + case EcmaOpcode::JNEZ_IMM8: + case EcmaOpcode::JNEZ_IMM16: + case EcmaOpcode::JNEZ_IMM32: + case EcmaOpcode::JMP_IMM8: + case EcmaOpcode::JMP_IMM16: + case EcmaOpcode::JMP_IMM32: case EcmaOpcode::STMODULEVAR_IMM8: case EcmaOpcode::WIDE_STMODULEVAR_PREF_IMM16: - case EcmaOpcode::SETGENERATORSTATE_IMM8: - case EcmaOpcode::DYNAMICIMPORT: case EcmaOpcode::LDEXTERNALMODULEVAR_IMM8: case EcmaOpcode::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16: - case EcmaOpcode::GETMODULENAMESPACE_IMM8: - case EcmaOpcode::WIDE_GETMODULENAMESPACE_PREF_IMM16: + case EcmaOpcode::NEWLEXENV_IMM8: + case EcmaOpcode::WIDE_NEWLEXENV_PREF_IMM16: + case EcmaOpcode::CALLRUNTIME_NEWSENDABLEENV_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDENEWSENDABLEENV_PREF_IMM16: + case EcmaOpcode::POPLEXENV: case EcmaOpcode::NEWLEXENVWITHNAME_IMM8_ID16: case EcmaOpcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16: - case EcmaOpcode::LDSUPERBYVALUE_IMM8_V8: - case EcmaOpcode::LDSUPERBYVALUE_IMM16_V8: - case EcmaOpcode::STSUPERBYVALUE_IMM16_V8_V8: - case EcmaOpcode::STSUPERBYVALUE_IMM8_V8_V8: - case EcmaOpcode::TRYSTGLOBALBYNAME_IMM8_ID16: - case EcmaOpcode::TRYSTGLOBALBYNAME_IMM16_ID16: - case EcmaOpcode::LDGLOBALVAR_IMM16_ID16: + case EcmaOpcode::ASYNCFUNCTIONENTER: + case EcmaOpcode::SETGENERATORSTATE_IMM8: + case EcmaOpcode::GETRESUMEMODE: + case EcmaOpcode::RESUMEGENERATOR: + case EcmaOpcode::RETURN: + case EcmaOpcode::RETURNUNDEFINED: + case EcmaOpcode::LDLEXVAR_IMM4_IMM4: + case EcmaOpcode::LDLEXVAR_IMM8_IMM8: + case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16: + case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4: + case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16: + case EcmaOpcode::STLEXVAR_IMM4_IMM4: + case EcmaOpcode::STLEXVAR_IMM8_IMM8: + case EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16: + case EcmaOpcode::CALLRUNTIME_STSENDABLEVAR_PREF_IMM4_IMM4: + case EcmaOpcode::CALLRUNTIME_STSENDABLEVAR_PREF_IMM8_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDESTSENDABLEVAR_PREF_IMM16_IMM16: + case EcmaOpcode::STRICTNOTEQ_IMM8_V8: + case EcmaOpcode::STRICTEQ_IMM8_V8: + case EcmaOpcode::CREATEEMPTYARRAY_IMM8: + case EcmaOpcode::CREATEEMPTYARRAY_IMM16: + case EcmaOpcode::CREATEEMPTYOBJECT: + case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: + case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: + case EcmaOpcode::CREATEITERRESULTOBJ_V8_V8: + case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: + case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: + case EcmaOpcode::DEFINEMETHOD_IMM8_ID16_IMM8: + case EcmaOpcode::DEFINEMETHOD_IMM16_ID16_IMM8: + case EcmaOpcode::CALLRUNTIME_LDSENDABLECLASS_PREF_IMM16: + case EcmaOpcode::DEBUGGER: + case EcmaOpcode::NOP: + flags |= BytecodeFlags::NO_THROW; + break; + default: + break; + } +} + +void BytecodeMetaData::InitBytecodeKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + if (InitMovKind(opcode, kind)) { + return; + } + if (InitSetConstantKind(opcode, kind)) { + return; + } + if (InitCallBCKind(opcode, kind)) { + return; + } + if (InitRetrunKind(opcode, kind)) { + return; + } + if (InitSuspendKind(opcode, kind)) { + return; + } + if (InitResumeKind(opcode, kind)) { + return; + } + if (InitDiscardedKind(opcode, kind)) { + return; + } + if (InitThrowKind(opcode, kind)) { + return; + } + if (InitConditionJumpKind(opcode, kind)) { + return; + } + if (InitJumpIMMKind(opcode, kind)) { + return; + } + if (InitGeneratorResolveKind(opcode, kind)) { + return; + } + InitAccessorKind(opcode, kind); +} + +bool BytecodeMetaData::InitAccessorKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: - case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: - case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: - case EcmaOpcode::LDOBJBYVALUE_IMM8_V8: - case EcmaOpcode::LDOBJBYVALUE_IMM16_V8: - case EcmaOpcode::LDTHISBYVALUE_IMM8: - case EcmaOpcode::LDTHISBYVALUE_IMM16: - case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8: - case EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8: - case EcmaOpcode::STTHISBYVALUE_IMM8_V8: - case EcmaOpcode::STTHISBYVALUE_IMM16_V8: - case EcmaOpcode::LDSUPERBYNAME_IMM8_ID16: - case EcmaOpcode::LDSUPERBYNAME_IMM16_ID16: - case EcmaOpcode::STSUPERBYNAME_IMM8_ID16_V8: - case EcmaOpcode::STSUPERBYNAME_IMM16_ID16_V8: - case EcmaOpcode::LDLOCALMODULEVAR_IMM8: - case EcmaOpcode::WIDE_LDLOCALMODULEVAR_PREF_IMM16: case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: + case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: + case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: case EcmaOpcode::STTHISBYNAME_IMM8_ID16: case EcmaOpcode::STTHISBYNAME_IMM16_ID16: + case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8: + case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8: + kind = BytecodeKind::ACCESSOR_BC; + return true; + default: + return false; + } + return false; +} + +bool BytecodeMetaData::InitGeneratorResolveKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { case EcmaOpcode::ASYNCGENERATORRESOLVE_V8_V8_V8: + kind = BytecodeKind::GENERATOR_RESOLVE; + return true; + default: + return false; + } + return false; +} + +bool BytecodeMetaData::InitJumpIMMKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { + case EcmaOpcode::JMP_IMM8: + case EcmaOpcode::JMP_IMM16: + case EcmaOpcode::JMP_IMM32: + kind = BytecodeKind::JUMP_IMM; + return true; + default: + return false; + } + return false; +} + +bool BytecodeMetaData::InitConditionJumpKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { + case EcmaOpcode::JEQZ_IMM8: + case EcmaOpcode::JEQZ_IMM16: + case EcmaOpcode::JEQZ_IMM32: + case EcmaOpcode::JNEZ_IMM8: + case EcmaOpcode::JNEZ_IMM16: + case EcmaOpcode::JNEZ_IMM32: + kind = BytecodeKind::CONDITIONAL_JUMP; + return true; + default: + return false; + } + return false; +} + +bool BytecodeMetaData::InitThrowKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { + case EcmaOpcode::THROW_PREF_NONE: + case EcmaOpcode::THROW_NOTEXISTS_PREF_NONE: + case EcmaOpcode::THROW_PATTERNNONCOERCIBLE_PREF_NONE: + case EcmaOpcode::THROW_DELETESUPERPROPERTY_PREF_NONE: + case EcmaOpcode::THROW_CONSTASSIGNMENT_PREF_V8: + kind = BytecodeKind::THROW_BC; + return true; + default: + return false; + } + return false; +} + +bool BytecodeMetaData::InitDiscardedKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { + case EcmaOpcode::NOP: + kind = BytecodeKind::DISCARDED; + return true; + default: + return false; + } + return false; +} + +bool BytecodeMetaData::InitMovKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { + case EcmaOpcode::MOV_V4_V4: + case EcmaOpcode::MOV_V8_V8: + case EcmaOpcode::MOV_V16_V16: + case EcmaOpcode::STA_V8: + case EcmaOpcode::LDA_V8: + kind = BytecodeKind::MOV; + return true; + default: + return false; + } + return false; +} + +bool BytecodeMetaData::InitSetConstantKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { + case EcmaOpcode::LDNAN: + case EcmaOpcode::LDINFINITY: + case EcmaOpcode::LDUNDEFINED: + case EcmaOpcode::LDNULL: + case EcmaOpcode::LDTRUE: + case EcmaOpcode::LDFALSE: + case EcmaOpcode::LDHOLE: + case EcmaOpcode::LDAI_IMM32: + case EcmaOpcode::FLDAI_IMM64: + case EcmaOpcode::LDFUNCTION: + kind = BytecodeKind::SET_CONSTANT; + return true; + default: + return false; + } + return false; +} + +bool BytecodeMetaData::InitCallBCKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { + case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: case EcmaOpcode::CALLARG0_IMM8: case EcmaOpcode::CALLARG1_IMM8_V8: case EcmaOpcode::CALLARGS2_IMM8_V8_V8: case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8: case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: - case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8: case EcmaOpcode::CALLTHIS0_IMM8_V8: - case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: - case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: - case EcmaOpcode::LDA_STR_ID16: - case EcmaOpcode::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8: - case EcmaOpcode::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8: - case EcmaOpcode::STTOGLOBALRECORD_IMM16_ID16: - case EcmaOpcode::STCONSTTOGLOBALRECORD_IMM16_ID16: - case EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8: - case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8: - case EcmaOpcode::CREATEREGEXPWITHLITERAL_IMM8_ID16_IMM8: - case EcmaOpcode::CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8: - case EcmaOpcode::LDBIGINT_ID16: - case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8: - case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8: - case EcmaOpcode::CALLRUNTIME_DEFINEFIELDBYVALUE_PREF_IMM8_V8_V8: - case EcmaOpcode::CALLRUNTIME_DEFINEFIELDBYINDEX_PREF_IMM8_IMM32_V8: - case EcmaOpcode::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16: - case EcmaOpcode::CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM8_IMM16_IMM16_V8: case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: - case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8: - case EcmaOpcode::CALLRUNTIME_LDSENDABLEEXTERNALMODULEVAR_PREF_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEEXTERNALMODULEVAR_PREF_IMM16: - case EcmaOpcode::CALLRUNTIME_STSENDABLEVAR_PREF_IMM4_IMM4: - case EcmaOpcode::CALLRUNTIME_STSENDABLEVAR_PREF_IMM8_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDESTSENDABLEVAR_PREF_IMM16_IMM16: - case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4: - case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16: - case EcmaOpcode::CALLRUNTIME_NEWSENDABLEENV_PREF_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDENEWSENDABLEENV_PREF_IMM16: - case EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16: - case EcmaOpcode::CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8: - case EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16: - flags |= BytecodeFlags::READ_FUNC; - break; - case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8: - case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8: - flags |= BytecodeFlags::READ_FUNC; - flags |= BytecodeFlags::READ_NEWTARGET; - break; - case EcmaOpcode::SUPERCALLARROWRANGE_IMM8_IMM8_V8: - case EcmaOpcode::WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8: - case EcmaOpcode::SUPERCALLSPREAD_IMM8_V8: - case EcmaOpcode::CALLRUNTIME_SUPERCALLFORWARDALLARGS_PREF_V8: - flags |= BytecodeFlags::READ_NEWTARGET; - break; - case EcmaOpcode::GETUNMAPPEDARGS: - case EcmaOpcode::COPYRESTARGS_IMM8: - case EcmaOpcode::WIDE_COPYRESTARGS_PREF_IMM16: - flags |= BytecodeFlags::READ_ARGC; - [[fallthrough]]; + case EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8: + case EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8: + case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8: + kind = BytecodeKind::CALL_BC; + return true; default: - break; + return false; } + return false; +} - switch (inst.GetOpcode()) { - case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: - case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: - case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: - case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: - case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: - case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: - case EcmaOpcode::STTHISBYNAME_IMM8_ID16: - case EcmaOpcode::STTHISBYNAME_IMM16_ID16: - case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8: - case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8: - kind = BytecodeKind::ACCESSOR_BC; - break; +bool BytecodeMetaData::InitRetrunKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { + case EcmaOpcode::RETURN: + case EcmaOpcode::RETURNUNDEFINED: + kind = BytecodeKind::RETURN_BC; + return true; default: - break; + return false; } + return false; +} - if (kind == BytecodeKind::GENERAL || - kind == BytecodeKind::THROW_BC || - kind == BytecodeKind::RESUME || - kind == BytecodeKind::SUSPEND || - kind == BytecodeKind::GENERATOR_RESOLVE || - kind == BytecodeKind::CALL_BC || - kind == BytecodeKind::ACCESSOR_BC) { - flags |= BytecodeFlags::GENERAL_BC; +bool BytecodeMetaData::InitSuspendKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { + case EcmaOpcode::SUSPENDGENERATOR_V8: + case EcmaOpcode::DEPRECATED_SUSPENDGENERATOR_PREF_V8_V8: + kind = BytecodeKind::SUSPEND; + return true; + default: + return false; } - auto size = inst.GetSize(); - auto vregCount = GetVRegCount(inst); - uint64_t value = SizeField::Encode(size) | KindField::Encode(kind) | - FlagsField::Encode(static_cast(flags)) | - OpcodeField::Encode(inst.GetOpcode()) | VRegCountField::Encode(vregCount); - return BytecodeMetaData(value); + return false; +} + +bool BytecodeMetaData::InitResumeKind(EcmaOpcode &opcode, BytecodeKind &kind) +{ + switch (opcode) { + case EcmaOpcode::RESUMEGENERATOR: + kind = BytecodeKind::RESUME; + return true; + default: + return false; + } + return false; } // static diff --git a/ecmascript/compiler/bytecodes.h b/ecmascript/compiler/bytecodes.h index a0a1d251382cc51361c38e42728acb3f0440d99a..6d3ee6dd95bc4594deee5ade2ac01770aa2159d0 100644 --- a/ecmascript/compiler/bytecodes.h +++ b/ecmascript/compiler/bytecodes.h @@ -247,6 +247,34 @@ private: explicit BytecodeMetaData(uint64_t value) : value_(value) {} static BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc); + static void InitBytecodeFlags(EcmaOpcode &opcode, uint32_t &flags); + static void InitBytecodeKind(EcmaOpcode &opcode, BytecodeKind &kind); + + static void InitNoSideEffectFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitNoGCFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitNoThrowFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitReadThisObjectFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitSupportDeoptFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitReadACCFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitDebuggerFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitReadFuncFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitWriteEnvFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitReadEnvFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitReadNewTargetFlag(EcmaOpcode &opcode, uint32_t &flags); + static void InitReadArgcFlag(EcmaOpcode &opcode, uint32_t &flags); + + static bool InitMovKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitSetConstantKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitCallBCKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitRetrunKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitSuspendKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitResumeKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitDiscardedKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitThrowKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitConditionJumpKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitJumpIMMKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitGeneratorResolveKind(EcmaOpcode &opcode, BytecodeKind &kind); + static bool InitAccessorKind(EcmaOpcode &opcode, BytecodeKind &kind); static size_t GetVRegCount(const BytecodeInstruction &inst); diff --git a/ecmascript/compiler/call_signature.cpp b/ecmascript/compiler/call_signature.cpp index 72fd76ff9e3ad20a892c47c5e9c3547f04821905..63b94f61e276bf1c0073b3ad897aec772d0f3230 100644 --- a/ecmascript/compiler/call_signature.cpp +++ b/ecmascript/compiler/call_signature.cpp @@ -916,6 +916,22 @@ DEF_CALL_SIGNATURE(CreateArrayWithBuffer) callSign->SetCallConv(CallSignature::CallConv::CCallConv); } +DEF_CALL_SIGNATURE(CreateObjectHavingMethod) +{ + // 3 : 3 input parameters + CallSignature signature("CreateObjectHavingMethod", 0, 3, + ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); + *callSign = signature; + // 3 : 3 input parameters + std::array params = { + VariableType::NATIVE_POINTER(), // glue + VariableType::JS_ANY(), // obj + VariableType::JS_ANY(), // levEnv + }; + callSign->SetParameters(params.data()); + callSign->SetCallConv(CallSignature::CallConv::CCallConv); +} + DEF_CALL_SIGNATURE(CopyRestArgs) { // 5 : 5 input parameters @@ -1626,21 +1642,6 @@ DEF_CALL_SIGNATURE(ResumeRspAndRollback) callSign->SetCallConv(CallSignature::CallConv::GHCCallConv); } -DEF_CALL_SIGNATURE(StringsAreEquals) -{ - // 2 : 2 input parameters - CallSignature stringsAreEquals("StringsAreEquals", 0, 2, - ArgumentsOrder::DEFAULT_ORDER, VariableType::BOOL()); - *callSign = stringsAreEquals; - std::array params = { // 2 : 2 input parameters - VariableType::JS_POINTER(), - VariableType::JS_POINTER(), - }; - callSign->SetParameters(params.data()); - callSign->SetGCLeafFunction(true); - callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); -} - DEF_CALL_SIGNATURE(JSHClassFindProtoTransitions) { // 3 : 3 input parameters @@ -1835,6 +1836,32 @@ DEF_CALL_SIGNATURE(StringGetEnd) callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); } +DEF_CALL_SIGNATURE(ReverseTypedArray) +{ + CallSignature reverseTypedArray("ReverseTypedArray", 0, 1, + ArgumentsOrder::DEFAULT_ORDER, VariableType::VOID()); + *callSign = reverseTypedArray; + std::array params = { + VariableType::NATIVE_POINTER(), + }; + callSign->SetParameters(params.data()); + callSign->SetGCLeafFunction(true); + callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); +} + +DEF_CALL_SIGNATURE(SortTypedArray) +{ + CallSignature sortTypedArray("SortTypedArray", 0, 1, + ArgumentsOrder::DEFAULT_ORDER, VariableType::VOID()); + *callSign = sortTypedArray; + std::array params = { + VariableType::NATIVE_POINTER(), + }; + callSign->SetParameters(params.data()); + callSign->SetGCLeafFunction(true); + callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); +} + DEF_CALL_SIGNATURE(IsFastRegExp) { // 3 : 3 input parameters @@ -2204,6 +2231,23 @@ DEF_CALL_SIGNATURE(DebugPrintInstruction) callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); } +DEF_CALL_SIGNATURE(CollectingOpcodes) +{ + // 2 : 2 input parameters + CallSignature collectingOpcodes("CollectingOpcodes", 0, 2, + ArgumentsOrder::DEFAULT_ORDER, VariableType::VOID()); + *callSign = collectingOpcodes; + // 2 : 2 input parameters + std::array params = { + VariableType::NATIVE_POINTER(), + VariableType::NATIVE_POINTER(), + }; + callSign->SetVariadicArgs(true); + callSign->SetParameters(params.data()); + callSign->SetGCLeafFunction(true); + callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); +} + DEF_CALL_SIGNATURE(DebugOsrEntry) { // 2 : 2 input parameters @@ -2416,23 +2460,6 @@ DEF_CALL_SIGNATURE(CallDateNow) callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); } -DEF_CALL_SIGNATURE(FindElementWithCache) -{ - // 4 : 4 input parameters - CallSignature index("FindElementWithCache", 0, 4, ArgumentsOrder::DEFAULT_ORDER, VariableType::INT32()); - *callSign = index; - // 4 : 4 input parameters - std::array params = { - VariableType::NATIVE_POINTER(), - VariableType::JS_ANY(), - VariableType::JS_ANY(), - VariableType::INT32(), - }; - callSign->SetParameters(params.data()); - callSign->SetGCLeafFunction(true); - callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); -} - DEF_CALL_SIGNATURE(UpdateFieldType) { // 2 : 2 input parameters @@ -2448,20 +2475,6 @@ DEF_CALL_SIGNATURE(UpdateFieldType) callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); } -DEF_CALL_SIGNATURE(NumberIsFinite) -{ - // 1 : 1 input parameters - CallSignature index("NumberIsFinite", 0, 1, ArgumentsOrder::DEFAULT_ORDER, VariableType::BOOL()); - *callSign = index; - // 1 : 1 input parameters - std::array params = { - VariableType::FLOAT64(), - }; - callSign->SetParameters(params.data()); - callSign->SetGCLeafFunction(true); - callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); -} - DEF_CALL_SIGNATURE(DoubleToInt) { // 2 : 2 input parameters @@ -2477,10 +2490,10 @@ DEF_CALL_SIGNATURE(DoubleToInt) callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); } -DEF_CALL_SIGNATURE(DoubleToLength) +DEF_CALL_SIGNATURE(SaturateTruncDoubleToInt32) { // 1 : 1 input parameters - CallSignature index("DoubleToLength", 0, 1, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); + CallSignature index("SaturateTruncDoubleToInt32", 0, 1, ArgumentsOrder::DEFAULT_ORDER, VariableType::INT32()); *callSign = index; // 1 : 1 input parameters std::array params = { @@ -2540,23 +2553,6 @@ DEF_CALL_SIGNATURE(SharedGCMarkingBarrier) callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); } -DEF_CALL_SIGNATURE(StoreBarrier) -{ - // 4 : 4 input parameters - CallSignature index("StoreBarrier", 0, 4, ArgumentsOrder::DEFAULT_ORDER, VariableType::VOID()); - *callSign = index; - // 4 : 4 input parameters - std::array params = { - VariableType::NATIVE_POINTER(), - VariableType::JS_POINTER(), - VariableType::NATIVE_POINTER(), - VariableType::JS_POINTER() - }; - callSign->SetParameters(params.data()); - callSign->SetGCLeafFunction(true); - callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); -} - DEF_CALL_SIGNATURE(CallArg0) { // 2 : 2 input parameters @@ -2700,23 +2696,6 @@ DEF_CALL_SIGNATURE(JsBoundCallInternal) callSign->SetCallConv(CallSignature::CallConv::CCallConv); } -DEF_CALL_SIGNATURE(CreateArrayFromList) -{ - // 3 : 3 input parameters - CallSignature createArrayFromList("CreateArrayFromList", 0, 3, ArgumentsOrder::DEFAULT_ORDER, - VariableType::JS_POINTER()); - *callSign = createArrayFromList; - // 3 : 3 input parameters - std::array params = { - VariableType::NATIVE_POINTER(), - VariableType::INT32(), - VariableType::NATIVE_POINTER(), - }; - - callSign->SetParameters(params.data()); - callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_VARARGS); -} - DEF_CALL_SIGNATURE(DeoptHandlerAsm) { // 1 : 1 input parameters @@ -3083,4 +3062,20 @@ DEF_CALL_SIGNATURE(CreateJSTypedArrayValues) callSign->SetParameters(params.data()); callSign->SetCallConv(CallSignature::CallConv::CCallConv); } + +DEF_CALL_SIGNATURE(GrowElementsCapacity) +{ + // 6 : 6 input parameters + CallSignature growElementsCapacity("GrowElementsCapacity", 0, 3, ArgumentsOrder::DEFAULT_ORDER, + VariableType::JS_ANY()); + *callSign = growElementsCapacity; + // 6 : 6 input parameters + std::array params = { // 3 : 3 input parameters + VariableType::NATIVE_POINTER(), // glue + VariableType::JS_ANY(), // thisValue + VariableType::INT32(), // newlength + }; + callSign->SetParameters(params.data()); + callSign->SetCallConv(CallSignature::CallConv::CCallConv); +} } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/call_signature.h b/ecmascript/compiler/call_signature.h index bdaeb0a1f2b4648ac3a7a540c8fd382d3a0dbe4b..7a51e4bfe9519e7ede2fd4947d480bce8b0b9f71 100644 --- a/ecmascript/compiler/call_signature.h +++ b/ecmascript/compiler/call_signature.h @@ -422,6 +422,7 @@ private: V(SetSValueWithBarrier) \ V(NewLexicalEnv) \ V(CopyRestArgs) \ + V(CreateObjectHavingMethod) \ V(GetUnmappedArgs) \ V(GetCallSpreadArgs) \ V(NewThisObjectChecked) \ @@ -485,7 +486,6 @@ private: V(ResumeCaughtFrameAndDispatch) \ V(ResumeUncaughtFrameAndReturn) \ V(ResumeRspAndRollback) \ - V(StringsAreEquals) \ V(BigIntEquals) \ V(BigIntSameValueZero) \ V(CallBigIntAsIntN) \ @@ -497,6 +497,7 @@ private: V(DebugPrint) \ V(DebugPrintCustom) \ V(DebugPrintInstruction) \ + V(CollectingOpcodes) \ V(DebugOsrEntry) \ V(Comment) \ V(FatalPrint) \ @@ -507,7 +508,7 @@ private: V(InsertLocalToShareRSet) \ V(SetBitAtomic) \ V(DoubleToInt) \ - V(DoubleToLength) \ + V(SaturateTruncDoubleToInt32) \ V(FloatMod) \ V(FloatAcos) \ V(FloatAcosh) \ @@ -535,13 +536,10 @@ private: V(FloatPow) \ V(FloatCeil) \ V(CallDateNow) \ - V(NumberIsFinite) \ - V(FindElementWithCache) \ V(UpdateFieldType) \ V(MarkingBarrier) \ V(MarkingBarrierWithEden) \ V(SharedGCMarkingBarrier) \ - V(StoreBarrier) \ V(CallArg0) \ V(CallArg1) \ V(CallArgs2) \ @@ -554,7 +552,6 @@ private: V(JSFunctionEntry) \ V(OptimizedFastCallEntry) \ V(JSProxyCallInternalWithArgV) \ - V(CreateArrayFromList) \ V(JSObjectGetMethod) \ V(JsProxyCallInternal) \ V(JsBoundCallInternal) \ @@ -582,11 +579,12 @@ private: V(JSMapValues) \ V(JSSetHas) \ V(JSSetAdd) \ - V(JSMapDelete) \ - V(JSSetDelete) \ + V(GrowElementsCapacity) \ V(CreateJSTypedArrayEntries) \ V(CreateJSTypedArrayKeys) \ V(CreateJSTypedArrayValues) \ + V(JSMapDelete) \ + V(JSSetDelete) \ V(JSSetEntries) \ V(JSHClassFindProtoTransitions) \ V(NumberHelperStringToDouble) \ @@ -597,8 +595,8 @@ private: V(StringGetStart) \ V(StringGetEnd) \ V(ArrayTrim) \ - V(OptimizedFastJmp) \ V(CopyTypedArrayBuffer) \ + V(OptimizedFastJmp) \ V(CallArg0AndDispatchFromBaseline) \ V(CallArg1AndDispatchFromBaseline) \ V(CallArgs2AndDispatchFromBaseline) \ @@ -633,6 +631,8 @@ private: V(ASMFastWriteBarrier) \ V(ASMWriteBarrierWithEden) \ V(VerifyBarrier) \ + V(SortTypedArray) \ + V(ReverseTypedArray) \ V(IsFastRegExp) #define DECL_CALL_SIGNATURE(name) \ diff --git a/ecmascript/compiler/circuit.cpp b/ecmascript/compiler/circuit.cpp index f7d7605287f3ce2f61a23d44a261ef87388e6a7c..10cc703d5359e3d6f141e7503b3b02ca4d718935 100644 --- a/ecmascript/compiler/circuit.cpp +++ b/ecmascript/compiler/circuit.cpp @@ -37,7 +37,7 @@ Circuit::Circuit(NativeAreaAllocator* allocator, DebugInfo* debugInfo, const cha , allGates_(chunk()) #endif { - if (funcName != nullptr && debugInfo_->IsEnable()) { + if (funcName != nullptr && debugInfo_ != nullptr && debugInfo_->IsEnable()) { debugInfo_->AddFuncDebugInfo(funcName); } space_ = panda::ecmascript::PageMap(CIRCUIT_SPACE, PAGE_PROT_READWRITE).GetMem(); diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index c7b67a0e69d0491ca541bd7b30c92b7330d2288b..3ff3cc4a957e7675bc684f8375a7fa9e0cd93b58 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -472,6 +472,7 @@ public: inline GateRef IsStableArguments(GateRef hClass); inline GateRef IsStableArray(GateRef hClass); inline GateRef IsDictionaryElement(GateRef hClass); + inline GateRef IsJSArrayPrototypeModified(GateRef hClass); inline GateRef IsClassConstructor(GateRef object); inline GateRef IsClassConstructorWithBitField(GateRef bitfield); inline GateRef IsConstructor(GateRef object); @@ -481,7 +482,7 @@ public: inline GateRef IsJSObject(GateRef obj); inline GateRef IsCallable(GateRef obj); inline GateRef IsCallableFromBitField(GateRef bitfield); - inline GateRef IsProtoTypeHClass(GateRef hclass); + inline GateRef IsPrototypeHClass(GateRef hclass); inline GateRef IsJsProxy(GateRef obj); GateRef IsJSHClass(GateRef obj); inline void StoreHClass(GateRef glue, GateRef object, GateRef hClass); @@ -514,6 +515,7 @@ public: // **************************** Middle IR **************************** GateRef EcmaObjectCheck(GateRef gate); GateRef HeapObjectCheck(GateRef gate, GateRef frameState); + GateRef MathHClassConsistencyCheck(GateRef receiver); GateRef HeapObjectIsEcmaObjectCheck(GateRef gate, GateRef frameState); GateRef ProtoChangeMarkerCheck(GateRef gate, GateRef frameState = Gate::InvalidGateRef); GateRef StableArrayCheck(GateRef gate, ElementsKind kind, ArrayMetaDataAccessor::Mode mode); @@ -670,7 +672,7 @@ public: GateRef MonoStorePropertyLookUpProto(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex, GateRef value); GateRef MonoStoreProperty(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex, - GateRef value, GateRef keyIndex, GateRef frameState); + GateRef value, GateRef keyIndex, GateRef isProto, GateRef frameState); GateRef TypedCreateObjWithBuffer(std::vector &valueIn); template GateRef ConvertJSArrayHoleAsUndefined(GateRef receiver); @@ -704,7 +706,7 @@ public: inline GateRef TaggedIsWeak(GateRef x); inline GateRef TaggedIsPrototypeHandler(GateRef x); inline GateRef TaggedIsTransitionHandler(GateRef x); - inline GateRef TaggedIsStoreTSHandler(GateRef x); + inline GateRef TaggedIsStoreAOTHandler(GateRef x); inline GateRef TaggedIsTransWithProtoHandler(GateRef x); inline GateRef TaggedIsUndefinedOrNull(GateRef x); inline GateRef TaggedIsUndefinedOrNullOrHole(GateRef x); @@ -804,6 +806,7 @@ public: GateRef thisValue, GateRef callBackFn, GateRef usingThis, GateRef callIDRef, uint32_t pcOffset); GateRef ArrayEvery(GateRef thisValue, GateRef callBackFn, GateRef usingThis, uint32_t pcOffset); GateRef ArrayPop(GateRef thisValue, GateRef frameState); + GateRef ArrayPush(GateRef thisValue, GateRef value); GateRef ArraySlice(GateRef thisValue, GateRef startIndex, GateRef endIndex, GateRef frameState); GateRef ToNumber(GateRef gate, GateRef value, GateRef glue); GateRef StringToNumber(GateRef gate, GateRef value, GateRef radix, GateRef glue); @@ -869,8 +872,9 @@ public: inline GateRef GetDoubleOfTDouble(GateRef x); inline GateRef GetBooleanOfTBoolean(GateRef x); GateRef GetDoubleOfTNumber(GateRef x); - GateRef DoubleToInt(GateRef x, Label *exit); - GateRef DoubleToInt(GateRef glue, GateRef x, size_t typeBits); + GateRef TruncDoubleToInt(GateRef glue, GateRef x, size_t typeBits); + GateRef DoubleToIntOverflowCheck(GateRef x, size_t typeBits); + GateRef SaturateTruncDoubleToInt32(GateRef glue, GateRef x); GateRef DoubleCheckINFInRangeInt32(GateRef x); GateRef DoubleInRangeInt32(GateRef x); inline GateRef Int32ToTaggedPtr(GateRef x); diff --git a/ecmascript/compiler/code_generator.h b/ecmascript/compiler/code_generator.h index 252a718bff76b4d35152dbc562817818693e6b77..cfc89215660f5f022ccf45c0c635e74ed2bc044c 100644 --- a/ecmascript/compiler/code_generator.h +++ b/ecmascript/compiler/code_generator.h @@ -166,8 +166,21 @@ public: { return codeInfo_; } + + void SetAotCodeCommentFile(const std::string &aotCodeCommentFile) + { + litecgCodeCommentFile_ = aotCodeCommentFile; + } + + const std::string &GetAotCodeCommentFile() const + { + return litecgCodeCommentFile_; + } + protected: CodeInfo codeInfo_; +private: + std::string litecgCodeCommentFile_ = ""; }; class CodeGeneratorImpl { diff --git a/ecmascript/compiler/codegen/llvm/aarch64/aarch64_builder.cpp b/ecmascript/compiler/codegen/llvm/aarch64/aarch64_builder.cpp index 0c0c2e7b02a957507e8a6a3d54faafabc77663a0..f56e11a9dd24ecf8b3e171137601747728b24ceb 100644 --- a/ecmascript/compiler/codegen/llvm/aarch64/aarch64_builder.cpp +++ b/ecmascript/compiler/codegen/llvm/aarch64/aarch64_builder.cpp @@ -56,8 +56,7 @@ public: } }; -class Aarch64TargetBuilderRegistry -{ +class Aarch64TargetBuilderRegistry { public: Aarch64TargetBuilderRegistry() { diff --git a/ecmascript/compiler/codegen/llvm/llvm_codegen.cpp b/ecmascript/compiler/codegen/llvm/llvm_codegen.cpp index d799a7a822959f5db288631a10a5a5e2f28ba574..263eee1ba165633542f957ba366e8ba4de862440 100644 --- a/ecmascript/compiler/codegen/llvm/llvm_codegen.cpp +++ b/ecmascript/compiler/codegen/llvm/llvm_codegen.cpp @@ -221,8 +221,10 @@ uint8_t *CodeInfo::AllocaDataSectionImp(uintptr_t size, const char *sectionName, : (this->*allocaInNotReqSecBuffer)(size, AOTFileInfo::PAGE_ALIGN); alreadyPageAlign_ = true; } else { - addr = curSec.isSequentialAOTSec() ? (this->*allocaInReqSecBuffer)(size, AOTFileInfo::DATA_SEC_ALIGN) - : (this->*allocaInNotReqSecBuffer)(size, AOTFileInfo::DATA_SEC_ALIGN); + uint32_t alignedSize = curSec.InRodataSection() ? AOTFileInfo::RODATA_SEC_ALIGN + : AOTFileInfo::DATA_SEC_ALIGN; + addr = curSec.isSequentialAOTSec() ? (this->*allocaInReqSecBuffer)(size, alignedSize) + : (this->*allocaInNotReqSecBuffer)(size, alignedSize); } } else { addr = curSec.isSequentialAOTSec() ? (this->*allocaInReqSecBuffer)(size, 0) diff --git a/ecmascript/compiler/codegen/llvm/x64/x64_builder.cpp b/ecmascript/compiler/codegen/llvm/x64/x64_builder.cpp index 7ab4c7269ae202a5584b08f642703b582976b7b1..a30c8d1b321b02c24cc789d0d27c883593994afb 100644 --- a/ecmascript/compiler/codegen/llvm/x64/x64_builder.cpp +++ b/ecmascript/compiler/codegen/llvm/x64/x64_builder.cpp @@ -53,8 +53,7 @@ public: } }; -class X64TargetBuilderRegistry -{ +class X64TargetBuilderRegistry { public: X64TargetBuilderRegistry() { diff --git a/ecmascript/compiler/codegen/maple/litecg_codegen.cpp b/ecmascript/compiler/codegen/maple/litecg_codegen.cpp index bf5466b53be193f09ecf993388696cfae67a33d3..dcca1fe7b0be49da94821c27e2d45048c4a9987f 100644 --- a/ecmascript/compiler/codegen/maple/litecg_codegen.cpp +++ b/ecmascript/compiler/codegen/maple/litecg_codegen.cpp @@ -113,6 +113,7 @@ void LiteCGAssembler::Run(const CompilerLog &log, [[maybe_unused]] bool fastComp liteCG.SetupLiteCGEmitMemoryManager(&codeInfo_, isJit ? AllocateCodeSectionOnDemand : AllocateCodeSection, SaveFunc2Addr, SaveFunc2FPtoPrevSPDelta, SaveFunc2CalleeOffsetInfo, SavePC2DeoptInfo, SavePC2CallSiteInfo); + liteCG.SetAotCodeCommentFile(GetAotCodeCommentFile()); #ifdef JIT_ENABLE_CODE_SIGN isJit &= JitFort::IsResourceAvailable(); if (isJit) { diff --git a/ecmascript/compiler/codegen/maple/litecg_ir_builder.cpp b/ecmascript/compiler/codegen/maple/litecg_ir_builder.cpp index 1e27fa29056231e6de7e5359ed32d73780afaaf6..abe731d944fa2dad331d7f43ff92e458b46d7b0f 100644 --- a/ecmascript/compiler/codegen/maple/litecg_ir_builder.cpp +++ b/ecmascript/compiler/codegen/maple/litecg_ir_builder.cpp @@ -543,6 +543,10 @@ void LiteCGIRBuilder::HandleBB(const std::vector &bb, std::unordered_se HandleInitVreg(gate); InsertUsedOpcodeSet(usedOpcodeSet, OpCode::INITVREG); break; + case OpCode::ASM_CALL_BARRIER: + HandleCall(gate); + InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ASM_CALL_BARRIER); + break; default: if (illegalOpHandlers_.find(acc_.GetOpCode(gate)) == illegalOpHandlers_.end()) { LOG_COMPILER(FATAL) << "can't process opcode: " << acc_.GetOpCode(gate) << std::endl; @@ -886,8 +890,7 @@ void LiteCGIRBuilder::InitializeHandlers() OpCode::LOOP_EXIT, OpCode::START_ALLOCATE, OpCode::FINISH_ALLOCATE, - OpCode::FRAME_VALUES, - OpCode::ASM_CALL_BARRIER}; + OpCode::FRAME_VALUES}; } void LiteCGIRBuilder::HandleReturnVoid([[maybe_unused]] GateRef gate) @@ -1478,7 +1481,8 @@ void LiteCGIRBuilder::HandleCall(GateRef gate) OpCode callOp = acc_.GetOpCode(gate); if (callOp == OpCode::CALL || callOp == OpCode::NOGC_RUNTIME_CALL || callOp == OpCode::BUILTINS_CALL || callOp == OpCode::BUILTINS_CALL_WITH_ARGV || callOp == OpCode::CALL_OPTIMIZED || - callOp == OpCode::FAST_CALL_OPTIMIZED || callOp == OpCode::BASELINE_CALL) { + callOp == OpCode::FAST_CALL_OPTIMIZED || callOp == OpCode::BASELINE_CALL || + callOp == OpCode::ASM_CALL_BARRIER) { VisitCall(gate, ins, callOp); } else { LOG_ECMA(FATAL) << "this branch is unreachable"; @@ -1533,6 +1537,12 @@ void LiteCGIRBuilder::VisitCall(GateRef gate, const std::vector &inList Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset); callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset); kind = GetCallExceptionKind(index, op); + } else if (op == OpCode::ASM_CALL_BARRIER) { + const size_t index = acc_.GetConstantValue(inList[targetIndex]); + calleeDescriptor = RuntimeStubCSigns::Get(index); + Expr rtoffset = GetRTStubOffset(glue, index); + Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset); + callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset); } else { ASSERT(op == OpCode::BUILTINS_CALL || op == OpCode::BUILTINS_CALL_WITH_ARGV); Expr opcodeOffset = GetExprFromGate(inList[targetIndex]); @@ -1580,6 +1590,12 @@ void LiteCGIRBuilder::VisitCall(GateRef gate, const std::vector &inList LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(calleeFuncType); bool returnVoid = (returnType == lmirBuilder_->voidType); PregIdx returnPregIdx = returnVoid ? -1 : lmirBuilder_->CreatePreg(returnType); + if (op == OpCode::ASM_CALL_BARRIER) { + if (!returnVoid) LOG_JIT(INFO) << "barrier has return use\n"; + Stmt &pureCall = lmirBuilder_->PureCall(callee, params); + lmirBuilder_->AppendStmt(bb, pureCall); + return; + } Stmt &callNode = returnVoid ? lmirBuilder_->ICall(callee, params) : lmirBuilder_->ICall(callee, params, returnPregIdx); if (kind == CallExceptionKind::HAS_PC_OFFSET) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/be/common_utils.h b/ecmascript/compiler/codegen/maple/maple_be/include/be/common_utils.h index 5e00fe1b14df0424fea532a6fcd21d12ce3061a2..d67019a2cf9d4bb555850ceae6baa0cf6415a76f 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/be/common_utils.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/be/common_utils.h @@ -138,6 +138,10 @@ constexpr uint32 kFirstReg = 0; constexpr uint32 kSecondReg = 1; constexpr uint32 kThirdReg = 2; constexpr uint32 kFourthReg = 3; +constexpr uint32 kFifthReg = 4; +constexpr uint32 kSixthReg = 5; +constexpr uint32 kSeventhReg = 6; + /* inline asm operand designations */ constexpr uint32 kAsmStringOpnd = 0; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h index 06dd838230773099175a439a58c6080ffe9a0818..26f025c448905931809aea4b11ab02ce68aad365 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h @@ -618,6 +618,8 @@ private: bool GenerateCompareWithZeroInstruction(Opcode jmpOp, Opcode cmpOp, bool is64Bits, PrimType primType, LabelOperand &targetOpnd, Operand &opnd0); void SelectOverFlowCall(const IntrinsiccallNode &intrnNode); + RegOperand &LoadOpndIntoPhysicalRegister(const IntrinsiccallNode &intrnNode, uint32 index); + void SelectPureCall(const IntrinsiccallNode &intrnNode); /* Helper functions for translating complex Maple IR instructions/inrinsics */ void SelectDassign(StIdx stIdx, FieldID fieldId, PrimType rhsPType, Operand &opnd0); diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_emitter.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_emitter.h index 6c3dbedca5a13c09c06453bd880662e4551ba588..ff6b99f5c16e18f6ed5d7a70ca61ade038fdf1fe 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_emitter.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_emitter.h @@ -68,6 +68,7 @@ private: void EmitCTlsDescRel(Emitter &emitter, const Insn &insn) const; void EmitCTlsDescCall(Emitter &emitter, const Insn &insn) const; void EmitSyncLockTestSet(Emitter &emitter, const Insn &insn) const; + void EmitPureCall(Emitter &emitter, const Insn &insn) const; bool CheckInsnRefField(const Insn &insn, size_t opndIndex) const; }; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_md.def b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_md.def index 14e77068ccce96f295326a929395e26c05d18d22..c5407ff354b0894e6eb0d9068c731d325f1f6a51 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_md.def +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_md.def @@ -892,6 +892,11 @@ DEFINE_MOP(MOP_arrayclass_cache_ldr, {&OpndDesc::Reg64ID,&OpndDesc::LiteralSrc}, */ DEFINE_MOP(MOP_clinit_tail, {&OpndDesc::Reg64IS},ISATOMIC|CANTHROW|ISINTRINSIC,kLtClinitTail,"intrinsic_clinit_tail","0",2) +/* + * blr xt + */ +DEFINE_MOP(MOP_pure_call, {&OpndDesc::Reg64IS, &OpndDesc::ListSrc},0,kLtBranch,"pure_call","0",1,kBranchReg,0xd63f0000) + /* * intrinsic Unsafe.getAndAddInt * intrinsic_get_add_int w0, xt, wt, ws, x1, x2, w3, label diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_option.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_option.h index 1ef9bab77fcf66757b6c6613ef0a8e99553b5687..ae93c8ba4de37976464b52755147cbec0eebb577 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_option.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_option.h @@ -332,6 +332,16 @@ public: ehExclusiveFile = ehExclusive; } + void SetEmitAotCodeCommentFile(const std::string &aotCodeCommentFile) + { + aotCodeCommentFilePath = aotCodeCommentFile; + } + + const std::string &GetEmitAotCodeCommentFile() const + { + return aotCodeCommentFilePath; + } + static std::unordered_set &GetDumpPhases() { return dumpPhases; @@ -887,6 +897,7 @@ private: std::string ehExclusiveFile; /* we don't do exception handling in this list */ std::vector ehExclusiveFunctionName; + std::string aotCodeCommentFilePath = ""; static std::string targetArch; static std::unordered_set dumpPhases; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/emit.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/emit.h index 41610e33d6805fb3f198452b7cffcb6726bf7c83..550cce77bb7e01f20faa0f8cb9091e345f1071bc 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/emit.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/emit.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "isa.h" #include "asm_info.h" #include "cg.h" diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/operand.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/operand.h index 8cfa74bdff097472e282cea555b47cfa87f30ed9..21077eda074fc641dc50eb0a20ac5ea5493f9368 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/operand.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/operand.h @@ -907,7 +907,7 @@ class MemOperand : public OperandVisitable { public: enum AArch64AddressingMode : uint8 { kAddrModeUndef, - /* AddrMode_BO, base, offset. EA = [base] + offset; */ + /* AddrMode_BO, base, offset. EA = [base] + offset */ kAddrModeBOi, /* INTACT: EA = [base]+immediate */ /* * PRE: base += immediate, EA = [base] @@ -1367,7 +1367,7 @@ public: uint32 ShiftAmount() const { uint32 scale = extend & 0xF; - /* 8 is 1 << 3, 4 is 1 << 2, 2 is 1 << 1, 1 is 1 << 0; */ + /* 8 is 1 << 3, 4 is 1 << 2, 2 is 1 << 1, 1 is 1 << 0 */ return (scale == 8) ? 3 : ((scale == 4) ? 2 : ((scale == 2) ? 1 : 0)); } diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_MPISel.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_MPISel.h index 58e1c37b919e8198023e94ee2466d555418e4b3e..a049437f923cb0d715fc508da60e5b2bdde04271 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_MPISel.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_MPISel.h @@ -55,7 +55,8 @@ private: void SelectOverFlowCall(const IntrinsiccallNode &intrnNode); void SelectParmList(StmtNode &naryNode, ListOperand &srcOpnds, uint32 &fpNum); void SelectMpy(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType); - + void SelectPureCall(const IntrinsiccallNode &intrnNode); + RegOperand &LoadOpndIntoPhysicalRegister(const IntrinsiccallNode &intrnNode, uint32 index); /* lt/le in float is replaced by gt/ge on swaped operands */ void SelectCmp(Operand &opnd0, Operand &opnd1, PrimType primType, bool isSwap = false); void SelectCmpFloatEq(RegOperand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primResType, diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_md.def b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_md.def index e972860c2ddad09fab82fd637b22ce1d63414e25..e77e833efb49bca21c0e23d937a6e0f16f904057 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_md.def +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_md.def @@ -471,6 +471,7 @@ DEFINE_MOP(MOP_cmovoq_r_r, {&OpndDesc::Reg64IS,&OpndDesc::Reg64IDS},0,kLtAlu,"cm DEFINE_MOP(MOP_callq_l, {&OpndDesc::Lbl64,&OpndDesc::ListSrc,&OpndDesc::ListDest},ISCALL,kLtAlu,"callq","0",1) DEFINE_MOP(MOP_callq_m, {&OpndDesc::Mem64S,&OpndDesc::ListSrc,&OpndDesc::ListDest},ISCALL,kLtAlu,"callq","0",1) DEFINE_MOP(MOP_callq_r, {&OpndDesc::Reg64IS,&OpndDesc::ListSrc,&OpndDesc::ListDest},ISCALL,kLtAlu,"callq","0",1) +DEFINE_MOP(MOP_pure_call, {&OpndDesc::Reg64IS,&OpndDesc::ListSrc,&OpndDesc::ListDest},ISCALL,kLtAlu,"pure_call","0",1) DEFINE_MOP(MOP_retq, {},CANTHROW,kLtBranch,"ret","",1) diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/litecg/litecg.h b/ecmascript/compiler/codegen/maple/maple_be/include/litecg/litecg.h index 8eec0163bbbb72ed7a474ed9c1ff02207b4be4f4..c4160f68e5963c4be5b5d071eb629df02b41558b 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/litecg/litecg.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/litecg/litecg.h @@ -63,6 +63,7 @@ public: #endif void DumpCGIR(); void DoCG(bool isJit = false); + void SetAotCodeCommentFile(const std::string &aotCodeCommentFile); private: Module &module; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/litecg/lmir_builder.h b/ecmascript/compiler/codegen/maple/maple_be/include/litecg/lmir_builder.h index ca4b92b0e790871da86420c1740d50e1fb03def6..df575e23b8b155debc69d7a0b5dcafaeb14b0f56 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/litecg/lmir_builder.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/litecg/lmir_builder.h @@ -364,6 +364,8 @@ public: // when result is nullptr, don't need the result (or no result) Stmt &Call(Function &func, Args &args, PregIdx pregIdx); + Stmt &PureCall(Expr funcAddr, Args &args, Var *result = nullptr); + Stmt &ICall(Expr funcAddr, Args &args, Var *result = nullptr); Stmt &ICall(Expr funcAddr, Args &args, PregIdx pregIdx); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/be/lower.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/be/lower.cpp index 62dd71a214b7075b8b699c560ccc7ab6274657a7..33996d4056ec52a7ba1936507199b50bb5f607e2 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/be/lower.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/be/lower.cpp @@ -146,7 +146,11 @@ void CGLowerer::LowerCallStmt(StmtNode &stmt, StmtNode *&nextStmt, BlockNode &ne StmtNode *newStmt = nullptr; if (stmt.GetOpCode() == OP_intrinsiccall) { auto &intrnNode = static_cast(stmt); - newStmt = LowerIntrinsiccall(intrnNode, newBlk); + if (intrnNode.GetIntrinsic() == maple::INTRN_JS_PURE_CALL) { + newStmt = &stmt; + } else { + newStmt = LowerIntrinsiccall(intrnNode, newBlk); + } } else { /* We note the function has a user-defined (i.e., not an intrinsic) call. */ DEBUG_ASSERT(GetCurrentFunc() != nullptr, "GetCurrentFunc should not be nullptr"); @@ -909,6 +913,7 @@ bool CGLowerer::IsIntrinsicCallHandledAtLowerLevel(MIRIntrinsicID intrinsic) con case INTRN_ADD_WITH_OVERFLOW: case INTRN_SUB_WITH_OVERFLOW: case INTRN_MUL_WITH_OVERFLOW: + case INTRN_JS_PURE_CALL: return true; default: { return false; diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index 0368a347a6d6e4b81a1af8f3e8ae7842252307b0..9199e929a88f1406320cf80523ba2d662d3bc961 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -4438,6 +4438,59 @@ void AArch64CGFunc::SelectOverFlowCall(const IntrinsiccallNode &intrnNode) } } +RegOperand &AArch64CGFunc::LoadOpndIntoPhysicalRegister(const IntrinsiccallNode &intrnNode, uint32 index) +{ + auto &opnd = *intrnNode.Opnd(index); + auto ptyp = opnd.GetPrimType(); + RegOperand &opndReg = LoadIntoRegister(*HandleExpr(intrnNode, opnd), ptyp); + AArch64reg regId; + switch (index - 1) { + case kFirstReg: + regId = static_cast(R0); + break; + case kSecondReg: + regId = static_cast(R1); + break; + case kThirdReg: + regId = static_cast(R2); + break; + case kFourthReg: + regId = static_cast(R3); + break; + case kFifthReg: + regId = static_cast(R4); + break; + case kSixthReg: + regId = static_cast(R5); + break; + default: + CHECK_FATAL_FALSE("Unreachable!"); + } + RegOperand &realReg = GetOrCreatePhysicalRegisterOperand(regId, opndReg.GetSize(), GetRegTyFromPrimTy(ptyp)); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(PickMovBetweenRegs(ptyp, ptyp), realReg, opndReg)); + return realReg; +} + + +void AArch64CGFunc::SelectPureCall(const IntrinsiccallNode &intrnNode) +{ + DEBUG_ASSERT(intrnNode.NumOpnds() == 7, "must be 7 operands"); // must be 7 operands + // deal with parms + ListOperand *srcOpnds = CreateListOpnd(*GetFuncScopeAllocator()); + auto &callee = *intrnNode.Opnd(0); + auto ptyp = callee.GetPrimType(); + RegOperand &calleeReg = LoadIntoRegister(*HandleExpr(intrnNode, callee), ptyp); + uint32 i = 1; + for (; i < kSeventhReg; i++) { + srcOpnds->PushOpnd(LoadOpndIntoPhysicalRegister(intrnNode, i)); + } + // R15 is used in asm call + srcOpnds->PushOpnd(GetOrCreatePhysicalRegisterOperand(static_cast(R15), + GetPointerSize() * kBitsPerByte, kRegTyInt)); + Insn &callInsn = GetInsnBuilder()->BuildInsn(MOP_pure_call, calleeReg, *srcOpnds); + GetCurBB()->AppendInsn(callInsn); +} + void AArch64CGFunc::SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) { MIRIntrinsicID intrinsic = intrinsiccallNode.GetIntrinsic(); @@ -4451,6 +4504,10 @@ void AArch64CGFunc::SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) SelectOverFlowCall(intrinsiccallNode); return; } + if (intrinsic == maple::INTRN_JS_PURE_CALL) { + SelectPureCall(intrinsiccallNode); + return; + } } Operand *AArch64CGFunc::SelectCclz(IntrinsicopNode &intrnNode) diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_emitter.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_emitter.cpp index 685df00dcac75a5d3d5e69ea5a799805ae37b277..f37617912de6b820a829e92ee7d45d25e1ec74d9 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_emitter.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_emitter.cpp @@ -402,6 +402,10 @@ void AArch64AsmEmitter::EmitAArch64Insn(maplebe::Emitter &emitter, Insn &insn) c EmitSyncLockTestSet(emitter, insn); return; } + case MOP_pure_call: { + EmitPureCall(emitter, insn); + return; + } default: break; } @@ -1529,6 +1533,18 @@ void AArch64AsmEmitter::EmitSyncLockTestSet(Emitter &emitter, const Insn &insn) #endif } +void AArch64AsmEmitter::EmitPureCall(Emitter &emitter, const Insn &insn) const +{ +#ifdef ARK_LITECG_DEBUG + const InsnDesc *md = &AArch64CG::kMd[insn.GetMachineOpcode()]; + auto *callee = &insn.GetOperand(kInsnFirstOpnd); + A64OpndEmitVisitor calleeVisitor(emitter, md->opndMD[kInsnFirstOpnd]); + (void)emitter.Emit("\t").Emit("blr").Emit("\t"); + callee->Accept(calleeVisitor); + (void)emitter.Emit("\n"); +#endif +} + void AArch64AsmEmitter::EmitCheckThrowPendingException(Emitter &emitter, Insn &insn) const { #ifdef ARK_LITECG_DEBUG @@ -1599,6 +1615,7 @@ void AArch64AsmEmitter::EmitAArch64CfiInsn(Emitter &emitter, const Insn &insn) c { #ifdef ARK_LITECG_DEBUG MOperator mOp = insn.GetMachineOpcode(); + CHECK_FATAL(mOp <= cfi::kOpCfiLast, "check overflow"); CfiDescr &cfiDescr = cfiDescrTable[mOp]; (void)emitter.Emit("\t").Emit(cfiDescr.name); for (uint32 i = 0; i < cfiDescr.opndCount; ++i) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_memlayout.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_memlayout.cpp index ec1b56746d2d30a42a25a890719da80156282d79..8c6191ae12f7fe9916b8131099bb000462240a2c 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_memlayout.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_memlayout.cpp @@ -29,6 +29,7 @@ using namespace maple; uint32 AArch64MemLayout::ComputeStackSpaceRequirementForCall(StmtNode &stmt, int32 &aggCopySize, bool isIcall) { /* instantiate a parm locator */ + CHECK_FATAL(cgFunc != nullptr, "nullptr check"); CCImpl &parmLocator = *static_cast(cgFunc)->GetOrCreateLocator(CCImpl::GetCallConvKind(stmt)); uint32 sizeOfArgsToStkPass = 0; uint32 i = 0; @@ -78,6 +79,7 @@ void AArch64MemLayout::LayoutFormalParams() AArch64SymbolAlloc *symLoc = memAllocator->GetMemPool()->New(); SetSymAllocInfo(stIndex, *symLoc); MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(mirFunction->GetFormalDefVec()[i].formalTyIdx); + CHECK_FATAL(ty != nullptr, "nullptr check"); uint32 ptyIdx = ty->GetTypeIndex(); parmLocator.LocateNextParm(*ty, ploc, i == 0, mirFunction->GetMIRFuncType()); if (ploc.reg0 != kRinvalid) { /* register */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_peep.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_peep.cpp index bde2f4648c5f6b826d537f9f201eae9e3d11a036..030de490eadb0ba12726ae1944b9a8cfa612f6fb 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_peep.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_peep.cpp @@ -369,7 +369,7 @@ ImmOperand *EnhanceStrLdrAArch64::GetInsnAddOrSubNewOffset(Insn &insn, ImmOperan } else { auto &immOpnd = static_cast(insn.GetOperand(kInsnThirdOpnd)); auto &shiftOpnd = static_cast(insn.GetOperand(kInsnFourthOpnd)); - CHECK_FATAL(shiftOpnd.GetShiftAmount() == 12, "invalid shiftAmount"); + CHECK_FATAL(shiftOpnd.GetShiftAmount() == 12, "invalid shiftAmount"); // 12: invalid shiftAmount val = (immOpnd.GetValue() << shiftOpnd.GetShiftAmount()); } @@ -673,6 +673,7 @@ void CombineContiLoadAndStorePattern::Run(BB &bb, Insn &insn) } auto *curMemOpnd = static_cast(insn.GetMemOpnd()); + CHECK_FATAL(curMemOpnd != nullptr, "nullptr check"); DEBUG_ASSERT(curMemOpnd->GetAddrMode() == MemOperand::kAddrModeBOi, "invalid continues mem insn"); OfstOperand *curOfstOpnd = curMemOpnd->GetOffsetImmediate(); int64 curOfstVal = curOfstOpnd ? curOfstOpnd->GetOffsetValue() : 0; diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_proepilog.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_proepilog.cpp index 61b8408df7fa05ed007c7f79acbdd8d911f06d57..6df161114b70ad665e1b21488376caad061cfd26 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_proepilog.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_proepilog.cpp @@ -116,8 +116,11 @@ void AArch64GenProEpilog::AppendInstructionPushSingle(CGFunc &cgFunc, AArch64reg MemOperand *aarchMemO1 = static_cast(o1); uint32 dataSize = GetPointerBitSize(); - if (aarchMemO1->GetMemVaryType() == kNotVary && aarchCGFunc.IsImmediateOffsetOutOfRange(*aarchMemO1, dataSize)) { - o1 = &aarchCGFunc.SplitOffsetWithAddInstruction(*aarchMemO1, dataSize, R16); + if (aarchMemO1 != nullptr) { + if (aarchMemO1->GetMemVaryType() == kNotVary && + aarchCGFunc.IsImmediateOffsetOutOfRange(*aarchMemO1, dataSize)) { + o1 = &aarchCGFunc.SplitOffsetWithAddInstruction(*aarchMemO1, dataSize, R16); + } } Insn &pushInsn = cgFunc.GetInsnBuilder()->BuildInsn(mOp, o0, *o1); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfgo.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfgo.cpp index 33e485e50a2c13d8a3e6f01ebb42908bb00656a9..a341e7a40b9485d42153a89942c77bbff72a030e 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfgo.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfgo.cpp @@ -564,7 +564,7 @@ bool UnreachBBPattern::Optimize(BB &curBB) isRemoved = false; } - /* flush after remove; */ + /* flush after remove */ for (BB *bb : curBB.GetSuccs()) { bb->RemovePreds(curBB); cgFunc->GetTheCFG()->FlushUnReachableStatusAndRemoveRelations(*bb, *cgFunc); @@ -587,7 +587,7 @@ bool CgCfgo::PhaseRun(maplebe::CGFunc &f) { auto *loopInfo = GET_ANALYSIS(CgLoopAnalysis, f); CFGOptimizer *cfgOptimizer = f.GetCG()->CreateCFGOptimizer(*GetPhaseMemPool(), f, *loopInfo); - DEBUG_ASSERT(cfgOptimizer != nullptr, "nullptr check"); + CHECK_FATAL(cfgOptimizer != nullptr, "nullptr check"); if (f.IsAfterRegAlloc()) { cfgOptimizer->SetPhase(kCfgoPostRegAlloc); } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi.cpp index f20d432ddaedff153f97456d8f3a678d481a434d..4bbf69b83e899eec9f3820faf8e92f7d91b46785 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi.cpp @@ -40,6 +40,7 @@ void CfiInsn::Dump() const { #ifdef ARK_LITECG_DEBUG MOperator mOp = GetMachineOpcode(); + CHECK_FATAL(mOp <= kOpCfiLast, "check overflow"); CfiDescr &cfiDescr = cfiDescrTable[mOp]; LogInfo::MapleLogger() << "CFI " << cfiDescr.name; for (uint32 i = 0; i < static_cast(cfiDescr.opndCount); ++i) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/emit.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/emit.cpp index 9b936d5e612064715923b2c35c6dd170493feabb..94e0f915ac4424aac672ea1027d7fd66c028d4a6 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/emit.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/emit.cpp @@ -2796,9 +2796,12 @@ void Emitter::EmitHexUnsigned(uint64 num) void Emitter::WriteDebugCommentToFile() { #ifdef ARK_LITECG_DEBUG - std::ofstream file(DEFAULT_PATH.c_str(), std::ios::app); + struct stat buffer; + std::string filePath = cg->GetCGOptions().GetEmitAotCodeCommentFile(); + std::string outputFile = stat(filePath.c_str(), &buffer) == 0 ? filePath : DEFAULT_PATH; + std::ofstream file(outputFile.c_str(), std::ios::app); if (!file.is_open()) { - std::cerr << DEFAULT_PATH << " Unable to open file for writing." << std::endl; + std::cerr << outputFile << " Unable to open file for writing." << std::endl; return; } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp index 8c293a1af8622dd04bdb4c4bc628da07f3e5cb25..0fe0b2a3b36d0bbc343d75f25ba3868848321044 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp @@ -466,6 +466,7 @@ static void InitHandleStmtFactory() RegisterFactoryFunction(OP_goto, HandleGoto); RegisterFactoryFunction(OP_intrinsiccall, HandleIntrinCall); RegisterFactoryFunction(OP_intrinsiccallassigned, HandleIntrinCall); + RegisterFactoryFunction(OP_intrinsiccallwithtype, HandleIntrinCall); RegisterFactoryFunction(OP_rangegoto, HandleRangeGoto); RegisterFactoryFunction(OP_brfalse, HandleCondbr); RegisterFactoryFunction(OP_brtrue, HandleCondbr); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/live.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/live.cpp index 3ee7befe92fcda9ec6adb62acbfffdadedf6917d..8f185d9498fedea197c088f3ba6fc9d7fc5faa98 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/live.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/live.cpp @@ -320,6 +320,7 @@ void LiveAnalysis::ProcessCondOpnd(BB &bb) const /* dump the current info of def/use/livein/liveout */ void LiveAnalysis::Dump() const { + CHECK_FATAL(cgFunc != nullptr, "nullptr check"); MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(cgFunc->GetFunction().GetStIdx().Idx()); DEBUG_ASSERT(funcSt != nullptr, "null ptr check"); LogInfo::MapleLogger() << "\n--------- liveness for " << funcSt->GetName() << " iteration "; diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/memlayout.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/memlayout.cpp index aa6fa1f675da5303ab44d4a4fb8db8c4109b54df..55ba28298f218e4530ac01a5d8245d456d570b35 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/memlayout.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/memlayout.cpp @@ -31,6 +31,7 @@ using namespace maple; */ uint32 MemLayout::FindLargestActualArea(int32 &aggCopySize) { + CHECK_FATAL(mirFunction != nullptr, "nullptr check"); StmtNode *stmt = mirFunction->GetBody()->GetFirst(); if (stmt == nullptr) { return 0; diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/operand.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/operand.cpp index 8b34eb5792e2d66a4920bc7c7e795d51e7904719..4074696712c05c300aadd3381f5b6b915370b657 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/operand.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/operand.cpp @@ -165,6 +165,7 @@ bool MemOperand::Less(const Operand &right) const RegOperand *baseReg = GetBaseRegister(); RegOperand *rbaseReg = rightOpnd->GetBaseRegister(); + CHECK_FATAL(baseReg != nullptr, "nullptr check"); int32 nRet = baseReg->RegCompare(*rbaseReg); if (nRet == 0) { Operand *ofstOpnd = GetOffsetOperand(); @@ -182,6 +183,7 @@ bool MemOperand::Less(const Operand &right) const } RegOperand *indexReg = GetIndexRegister(); const RegOperand *rindexReg = rightOpnd->GetIndexRegister(); + CHECK_FATAL(indexReg != nullptr, "nullptr check"); return indexReg->Less(*rindexReg); } case kAddrModeLiteral: { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp index 9182f7540bdc4cfed1960b9548e06e39e99af038..8d3dfa33f839f3233c84be789bbf92f4236db7a2 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp @@ -1619,7 +1619,6 @@ RegOperand *LSRALinearScanRegAllocator::GetReplaceOpnd(Insn &insn, Operand &opnd if (regInfo->IsCalleeSavedReg(regNO)) { cgFunc->AddtoCalleeSaved(regNO); } - if (li->IsShouldSave() || li->GetStackSlot() == kSpilled) { spillIdx = isDef ? 0 : spillIdx; if (li->IsShouldSave()) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp index b680b3dd00b0eb801427c5e42e10459534be3a1f..af880bd5ebc645be237f51e69be136b9d10d90c5 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp @@ -378,6 +378,60 @@ void X64MPIsel::SelectOverFlowCall(const IntrinsiccallNode &intrnNode) return; } +void X64MPIsel::SelectPureCall(const IntrinsiccallNode &intrnNode) +{ + DEBUG_ASSERT(intrnNode.NumOpnds() == 7, "must be 7 operands"); // must be 7 operands + ListOperand &srcOpnds = cgFunc->GetOpndBuilder()->CreateList(); + auto &callee = *intrnNode.Opnd(0); + auto ptyp = callee.GetPrimType(); + RegOperand &calleeReg = SelectCopy2Reg(*HandleExpr(intrnNode, callee), ptyp); + uint32 i = 1; + for (; i < kSeventhReg; i++) { + srcOpnds.PushOpnd(LoadOpndIntoPhysicalRegister(intrnNode, i)); + } + // R11 is used in asm call + srcOpnds.PushOpnd(cgFunc->GetOpndBuilder()->CreatePReg(x64::R11, GetPrimTypeBitSize(PTY_i64), kRegTyInt)); + MOperator mOp = x64::MOP_pure_call; + Insn &callInsn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, X64CG::kMd[mOp]); + callInsn.AddOpndChain(calleeReg); + callInsn.AddOpndChain(srcOpnds); + cgFunc->GetCurBB()->AppendInsn(callInsn); + return; +} + +RegOperand &X64MPIsel::LoadOpndIntoPhysicalRegister(const IntrinsiccallNode &intrnNode, uint32 index) +{ + auto &opnd = *intrnNode.Opnd(index); + auto ptyp = opnd.GetPrimType(); + RegOperand &opndReg = SelectCopy2Reg(*HandleExpr(intrnNode, opnd), ptyp); + PRegNo regId; + switch (index - 1) { + case kFirstReg: + regId = x64::RDI; + break; + case kSecondReg: + regId = x64::RSI; + break; + case kThirdReg: + regId = x64::RDX; + break; + case kFourthReg: + regId = x64::RCX; + break; + case kFifthReg: + regId = x64::R8; + break; + case kSixthReg: + regId = x64::R9; + break; + default: + CHECK_FATAL_FALSE("Unreachable!"); + } + RegOperand &realReg = cgFunc->GetOpndBuilder()->CreatePReg(regId, GetPrimTypeBitSize(PTY_i64), kRegTyInt); + SelectCopy(realReg, opndReg, ptyp, ptyp); + return realReg; +} + void X64MPIsel::SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) { MIRIntrinsicID intrinsic = intrinsiccallNode.GetIntrinsic(); @@ -386,6 +440,10 @@ void X64MPIsel::SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) SelectOverFlowCall(intrinsiccallNode); return; } + if (intrinsic == maple::INTRN_JS_PURE_CALL) { + SelectPureCall(intrinsiccallNode); + return; + } CHECK_FATAL(false, "Intrinsic %d: %s not implemented by the X64 CG.", intrinsic, GetIntrinsicName(intrinsic)); } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_args.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_args.cpp index d30c88785c068cd234c638a8af580c01472a4a5a..4fcc73ad98b2ec02597f8e4599eb1466b5bef084 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_args.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_args.cpp @@ -30,6 +30,7 @@ void X64MoveRegArgs::CollectRegisterArgs(std::map &argsList, std std::map &pairReg, std::vector &numFpRegs, std::vector &fpSize) const { + CHECK_FATAL(cgFunc != nullptr, "nullptr check"); X64CGFunc *x64CGFunc = static_cast(cgFunc); uint32 numFormal = static_cast(x64CGFunc->GetFunction().GetFormalCount()); numFpRegs.resize(numFormal); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_emitter.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_emitter.cpp index 19baae15d42c63ef2dc69b8faddb2c76b24f67f4..3ed863a1366e18342518181f59f64b354217e08c 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_emitter.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_emitter.cpp @@ -1329,6 +1329,10 @@ void X64Emitter::EmitInsn(Insn &insn, uint32 funcUniqueId) } break; } + case x64::MOP_pure_call: { + assmbler.Call(kQ, TransferReg(opnd0)); + break; + } case x64::MOP_callq_l: { assmbler.Call(kQ, TransferFuncName(opnd0)); if (insn.GetStackMap() != nullptr) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/litecg/litecg.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/litecg/litecg.cpp index 5d8ea5635c632e6485b3c24fce5f0f1430797b22..b069830d3bde3896410544e856044a9a29ef33f7 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/litecg/litecg.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/litecg/litecg.cpp @@ -83,6 +83,11 @@ LiteCG &LiteCG::SetupLiteCGEmitMemoryManager( return *this; } +void LiteCG::SetAotCodeCommentFile(const std::string &aotCodeCommentFile) +{ + cgOptions->SetEmitAotCodeCommentFile(aotCodeCommentFile); +} + void LiteCG::DoCG(bool isJit) { bool timePhases = cgOptions->IsEnableTimePhases(); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/litecg/lmir_builder.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/litecg/lmir_builder.cpp index ce86445a66256af49b7cc3e8794e8ce81fca8f43..f112973893c39464f0d259faed633fd0573b0e21 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/litecg/lmir_builder.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/litecg/lmir_builder.cpp @@ -455,6 +455,16 @@ Stmt &LMIRBuilder::Call(Function &func, Args &args_, PregIdx pregIdx) return *mirBuilder.CreateStmtCallRegassigned(func.GetPuidx(), args, pregIdx, OP_callassigned); } +Stmt &LMIRBuilder::PureCall(Expr funcAddr, Args &args_, Var *result) +{ + MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); + args.push_back(funcAddr.GetNode()); + for (const auto &arg : args_) { + args.emplace_back(arg.GetNode()); + } + return *mirBuilder.CreateStmtIntrinsicCall(MIRIntrinsicID::INTRN_JS_PURE_CALL, args); +} + Stmt &LMIRBuilder::ICall(Expr funcAddr, Args &args_, Var *result) { MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); @@ -486,8 +496,6 @@ Stmt &LMIRBuilder::IntrinsicCall(IntrinsicId func_, Args &args_, PregIdx retPreg for (const auto &arg : args_) { args.emplace_back(arg.GetNode()); } - - // need to fix the type for IntrinsicId auto func = static_cast(func_); return *mirBuilder.CreateStmtIntrinsicCallAssigned(func, args, retPregIdx1, retPregIdx2); } diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsic_js.def b/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsic_js.def index 83391af40411522f05b80133ccf3c03091500757..154196cacb6a9da0179d1d22835399a0cf18c6b3 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsic_js.def +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsic_js.def @@ -20,3 +20,5 @@ DEF_MIR_INTRINSIC(SUB_WITH_OVERFLOW,\ "__sub_with_overflow", kArgTyI32, kArgTyI32, kArgTyI32) DEF_MIR_INTRINSIC(MUL_WITH_OVERFLOW,\ "__mul_with_overflow", kArgTyI32, kArgTyI32, kArgTyI32) +DEF_MIR_INTRINSIC(JS_PURE_CALL,\ + "__jsop_purecall", kArgTyDynany, kArgTyDynany, kArgTyDynany, kArgTyDynany, kArgTyDynany, kArgTyDynany, kArgTyDynany, kArgTyDynany) diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsics.h b/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsics.h index 6854e24f3ae97656a600171257670d7691bba0ca..15480d277dbd14bc505cbe566e035836aaa79a78 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsics.h +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsics.h @@ -37,7 +37,8 @@ enum IntrinArgType { kArgTyA64, kArgTyF32, kArgTyF64, - kArgTyF128 + kArgTyF128, + kArgTyDynany }; class MIRType; // circular dependency exists, no other choice diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_config.h b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_config.h index 09f42979b97b8d861daffeb453510ca4bf4fd302..61da98e678603f7840fb9c0a42483de7f88ffdd3 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_config.h +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_config.h @@ -35,7 +35,6 @@ // 3: with normal warning information // 4: with normal information // 5: with everything -// #ifndef MIR_DEBUG_LEVEL #define MIR_DEBUG_LEVEL 0 #endif // MIR_DEBUG_LEVEL diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_function.h b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_function.h index 74da05c8dbef6161b5a03f758edbf1d70702c6f5..8af37c996b2627bcc87376a117e7ce2a756ad1b9 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_function.h +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_function.h @@ -1475,7 +1475,7 @@ private: // a dynamic memory block that needs reference // count; the bitvector's size is given by // BlockSize2BitvectorSize(frameSize) - // uint16 numlabels; // removed. label table size + // uint16 numlabels // removed. label table size // StmtNode **lbl2stmt // lbl2stmt table, removed // to hold unmangled class and function names MeFunction *meFunc = nullptr; diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/prim_types.def b/ecmascript/compiler/codegen/maple/maple_ir/include/prim_types.def index 453b1c1ac59f5c7aeb50ae76e328be28be731117..8ea91bd6f97a8a3ece27d6076c2b13c11432e959 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/prim_types.def +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/prim_types.def @@ -31,6 +31,7 @@ PRIMTYPE(a64) PRIMTYPE(f32) PRIMTYPE(f64) + PRIMTYPE(dynany) PRIMTYPE(unknown) #endif // ~LOAD_ALGO_PRIMARY_TYPE @@ -120,6 +121,11 @@ static const PrimitiveTypeProperty PTProperty_f64 = { /*isPointer=*/false, /*isSimple=*/false }; +static const PrimitiveTypeProperty PTProperty_dynany = { + /*type=*/PTY_dynany, /*isInteger=*/false, /*isUnsigned=*/false, /*isAddress=*/false, /*isFloat=*/false, + /*isPointer=*/false, /*isSimple=*/false +}; + static const PrimitiveTypeProperty PTProperty_unknown = { /*type=*/PTY_unknown, /*isInteger=*/false, /*isUnsigned=*/false, /*isAddress=*/false, /*isFloat=*/false, /*isPointer=*/false, /*isSimple=*/false diff --git a/ecmascript/compiler/codegen/maple/maple_ir/src/intrinsics.cpp b/ecmascript/compiler/codegen/maple/maple_ir/src/intrinsics.cpp index 03e7473725235cffbb633963ac624cedf5802029..cef1488050641138efb99f5459f85d6d0ae0bfb9 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/src/intrinsics.cpp +++ b/ecmascript/compiler/codegen/maple/maple_ir/src/intrinsics.cpp @@ -66,6 +66,8 @@ MIRType *IntrinDesc::GetTypeFromArgTy(IntrinArgType argType) const return GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast(PTY_f32)); case kArgTyF64: return GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast(PTY_f64)); + case kArgTyDynany: + return GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast(PTY_dynany)); default: return nullptr; } diff --git a/ecmascript/compiler/codegen/maple/maple_util/include/cl_option.h b/ecmascript/compiler/codegen/maple/maple_util/include/cl_option.h index 08c98bb8b94666b65477c4ad61a13e235658c9f6..050f38dd8e8010e750235d34886fc43eb619e0e8 100644 --- a/ecmascript/compiler/codegen/maple/maple_util/include/cl_option.h +++ b/ecmascript/compiler/codegen/maple/maple_util/include/cl_option.h @@ -102,7 +102,7 @@ using OptionCategoryRefWrp = std::reference_wrapper; class OptionWrp { public: template - /* implicit */ OptionWrp(T v) : val(v) + OptionWrp(T v) : val(v) /* implicit */ { } @@ -227,7 +227,7 @@ public: /* Conversation operator is needed to use the option like this: * strding test = option1; or int dig = option2 - here will be implicit conversation. */ - /*implicit*/ operator T() + operator T() /*implicit*/ { return GetValue(); } diff --git a/ecmascript/compiler/codegen/maple/test/BUILD.gn b/ecmascript/compiler/codegen/maple/test/BUILD.gn index a6031bf3b39e87832d855f2cfcafc77633e4537c..bf812a541c36f5e961373555fd820a5c866dd6b0 100644 --- a/ecmascript/compiler/codegen/maple/test/BUILD.gn +++ b/ecmascript/compiler/codegen/maple/test/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("mapleallUT") { rtti_compile_flag = false diff --git a/ecmascript/compiler/codegen/maple/test/maple_ir/intrinsics_test.cpp b/ecmascript/compiler/codegen/maple/test/maple_ir/intrinsics_test.cpp index b807d1060efb349b2a3dab0f9b2ceabdb9651124..9fb61223b28e2724f79f2d17dfa843918d001a66 100644 --- a/ecmascript/compiler/codegen/maple/test/maple_ir/intrinsics_test.cpp +++ b/ecmascript/compiler/codegen/maple/test/maple_ir/intrinsics_test.cpp @@ -27,14 +27,20 @@ TEST(GetTypeFromArgTy_FUNC, t01) { struct IntrinDesc IntrinDesc_struc; IntrinArgType input_ls[] = {kArgTyVoid, kArgTyI8, kArgTyI16, kArgTyI32, kArgTyI64, kArgTyU8, - kArgTyU16, kArgTyU32, kArgTyU64, kArgTyU1, kArgTyPtr, kArgTyRef, + kArgTyU16, kArgTyU32, kArgTyU64, kArgTyU1, kArgTyA64, kArgTyF32, kArgTyF64}; + PrimType res_ls[] = { + PTY_void, PTY_i8, PTY_i16, PTY_i32, PTY_i64, PTY_u8, + PTY_u16, PTY_u32, PTY_u64, PTY_u1, + PTY_a64, PTY_f32, PTY_f64 + }; MIRType *mirtype_ptr; int n = sizeof(input_ls) / sizeof(input_ls[0]); for (int i = 0; i < n; i++) { mirtype_ptr = IntrinDesc_struc.GetTypeFromArgTy(input_ls[i]); - mirtype_ptr->GetPrimType(); + ASSERT_TRUE(mirtype_ptr != nullptr); + EXPECT_EQ(mirtype_ptr->GetPrimType(), res_ls[i]); } } -} // namespace \ No newline at end of file +} // namespace diff --git a/ecmascript/compiler/common_stub_csigns.h b/ecmascript/compiler/common_stub_csigns.h index 797faa203f1c4ff6cc9f8a01f4ba4bacdf0e2519..5550b0705deae98a378dc67d212d5bb634fdcc77 100644 --- a/ecmascript/compiler/common_stub_csigns.h +++ b/ecmascript/compiler/common_stub_csigns.h @@ -88,6 +88,7 @@ namespace panda::ecmascript::kungfu { V(ConstructorCheck) \ V(CreateEmptyArray) \ V(CreateArrayWithBuffer) \ + V(CreateObjectHavingMethod) \ V(NewJSObject) \ V(JsBoundCallInternal) \ V(CreateStringBySingleCharCode) \ @@ -102,11 +103,11 @@ namespace panda::ecmascript::kungfu { V(JSMapHas) \ V(JSSetHas) \ V(JSSetAdd) \ - V(JSMapDelete) \ - V(JSSetDelete) \ V(CreateJSTypedArrayEntries) \ V(CreateJSTypedArrayKeys) \ V(CreateJSTypedArrayValues) \ + V(JSMapDelete) \ + V(JSSetDelete) \ V(GetSingleCharCodeByIndex) \ V(FastStringEqual) \ V(FastStringAdd) \ @@ -118,7 +119,8 @@ namespace panda::ecmascript::kungfu { V(DeleteObjectProperty) \ V(SameValue) \ V(StringIteratorNext) \ - V(VerifyBarrier) + V(VerifyBarrier) \ + V(GrowElementsCapacity) #define COMMON_STUB_ID_LIST(V) \ COMMON_STUB_LIST(V) diff --git a/ecmascript/compiler/common_stubs.cpp b/ecmascript/compiler/common_stubs.cpp index f001330f059e56e19a44f29fbfcd1d240779c7c6..5fc674620531e4362258b874c088f0a2186ea02d 100644 --- a/ecmascript/compiler/common_stubs.cpp +++ b/ecmascript/compiler/common_stubs.cpp @@ -17,8 +17,10 @@ #include "ecmascript/base/number_helper.h" #include "ecmascript/compiler/access_object_stub_builder.h" +#include "ecmascript/compiler/builtins/builtins_array_stub_builder.h" #include "ecmascript/compiler/builtins/builtins_string_stub_builder.h" #include "ecmascript/compiler/builtins/linked_hashtable_stub_builder.h" +#include "ecmascript/compiler/circuit_builder.h" #include "ecmascript/compiler/codegen/llvm/llvm_ir_builder.h" #include "ecmascript/compiler/interpreter_stub.h" #include "ecmascript/compiler/new_object_stub_builder.h" @@ -351,6 +353,18 @@ void NewLexicalEnvStubBuilder::GenerateCircuit() Return(*result); } +void CreateObjectHavingMethodStubBuilder::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef obj = TaggedArgument(1); + GateRef env = Int32Argument(2); /* 2 : 3rd parameter is index */ + + NewObjectStubBuilder newBuilder(this); + newBuilder.SetParameters(glue, 0); + GateRef result = newBuilder.CreateObjectHavingMethod(glue, obj, env); + Return(result); +} + void CopyRestArgsStubBuilder::GenerateCircuit() { DEFVARIABLE(arrayObj, VariableType::JS_ANY(), Undefined()); @@ -1263,6 +1277,18 @@ void JSSetAddStubBuilder::GenerateCircuit() Return(obj); } +void GrowElementsCapacityStubBuilder::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef thisValue = TaggedArgument(1); + GateRef newLength = Int32Argument(2U); + DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); + BuiltinsArrayStubBuilder builder(this); + result = builder.GrowElementsCapacity(glue, thisValue, newLength); + Return(*result); +} + + void SameValueStubBuilder::GenerateCircuit() { GateRef glue = PtrArgument(0); diff --git a/ecmascript/compiler/deopt_type.h b/ecmascript/compiler/deopt_type.h index 1c46a86523c56d561cd66218ceee3479623e0e63..32d2a2a7ce6abf91c32aa665bd43f58ebba17413 100644 --- a/ecmascript/compiler/deopt_type.h +++ b/ecmascript/compiler/deopt_type.h @@ -40,6 +40,7 @@ namespace panda::ecmascript::kungfu { V(NotHeapObject1, NOTHEAPOBJECT1) \ V(NotStableArray1, NOTSARRAY1) \ V(NotStableArray2, NOTSARRAY2) \ + V(NotStableArray3, NOTSARRAY3) \ V(ElementsKindMismatchedAtLoad, ELEMENSKINDMISMATCHEDATLOAD) \ V(ElementsKindMismatchedAtStore, ELEMENSKINDMISMATCHEDATSTORE) \ V(InconsistentElementsKind, INCONSISTENTELEMENTSKIND) \ @@ -92,8 +93,8 @@ namespace panda::ecmascript::kungfu { V(BuiltinInstanceHClassMismatch2, BUILTININSTANCEHCLASSMISMATCH2) \ V(BuiltinPrototypeHClassMismatch1, BUILTINPROTOHCLASSMISMATCH1) \ V(BuiltinPrototypeHClassMismatch2, BUILTINPROTOHCLASSMISMATCH2) \ - V(ProtoTypeChanged1, PROTOTYPECHANGED1) \ - V(ProtoTypeChanged2, PROTOTYPECHANGED2) \ + V(PrototypeChanged1, PROTOTYPECHANGED1) \ + V(PrototypeChanged2, PROTOTYPECHANGED2) \ V(BuiltinIsHole1, BUILTINISHOLE1) \ V(NewBuiltinCtorFail1, NEWBUILTINCTORFAIL1) \ V(NewBuiltinCtorObject, NEWBUILTINCTOROBJECT) \ diff --git a/ecmascript/compiler/early_elimination.cpp b/ecmascript/compiler/early_elimination.cpp index a378def8c020f139367d24be33a81ca3c0db54f2..0610714bb64a7d4342920b046c7a6ef4a5b73753 100644 --- a/ecmascript/compiler/early_elimination.cpp +++ b/ecmascript/compiler/early_elimination.cpp @@ -97,6 +97,7 @@ GateRef EarlyElimination::VisitGate(GateRef gate) case OpCode::LOAD_BUILTIN_OBJECT: case OpCode::LOOK_UP_HOLDER: case OpCode::IS_CALLABLE_CHECK: + case OpCode::MATH_HCLASS_CONSISTENCY_CHECK: return TryEliminateGate(gate); case OpCode::STATE_SPLIT: if (enableFrameStateElimination_) { @@ -362,8 +363,23 @@ bool EarlyElimination::CheckReplacement(GateRef lhs, GateRef rhs) case OpCode::TYPED_ARRAY_CHECK: { TypedArrayMetaDataAccessor lhsAccessor = acc_.GetTypedArrayMetaDataAccessor(lhs); TypedArrayMetaDataAccessor rhsAccessor = acc_.GetTypedArrayMetaDataAccessor(rhs); - if ((lhsAccessor.GetParamType() != rhsAccessor.GetParamType()) || - (lhsAccessor.GetOnHeapMode() != rhsAccessor.GetOnHeapMode())) { + if ((lhsAccessor.GetParamType() != rhsAccessor.GetParamType())) { + return false; + } + + OnHeapMode lMode = lhsAccessor.GetOnHeapMode(); + OnHeapMode rMode = rhsAccessor.GetOnHeapMode(); + // When the onheapmode types of the two checks are inconsistent and one type is none, the none type will be + // updated to another type. Because there is no side effect between the two checks, the onheapmode types are + // also consistent. + if (lMode != rMode) { + if (OnHeap::IsNone(lMode)) { + acc_.UpdateOnHeapMode(lhs, rMode); + return true; + } else if (OnHeap::IsNone(rMode)) { + acc_.UpdateOnHeapMode(rhs, lMode); + return true; + } return false; } break; diff --git a/ecmascript/compiler/file_generators.cpp b/ecmascript/compiler/file_generators.cpp index 52a8c4a849ef2b8dbe2e7f4d6b48458dc1d125f2..fcfe354b14f56d7339ce0962f1056f596a297a3b 100644 --- a/ecmascript/compiler/file_generators.cpp +++ b/ecmascript/compiler/file_generators.cpp @@ -203,7 +203,7 @@ void Module::CollectFuncEntryInfo(std::map &addr2name, A } aotInfo.UpdateCurTextSecOffset(textSize); if (rodataSizeAfterText != 0) { - aotInfo.AlignTextSec(AOTFileInfo::DATA_SEC_ALIGN); + aotInfo.AlignTextSec(AOTFileInfo::RODATA_SEC_ALIGN); aotInfo.UpdateCurTextSecOffset(rodataSizeAfterText); } } @@ -267,7 +267,7 @@ void Module::CollectFuncEntryInfoByLiteCG(std::map &addr } aotInfo.UpdateCurTextSecOffset(textSize); if (rodataSizeAfterText != 0) { - aotInfo.AlignTextSec(AOTFileInfo::DATA_SEC_ALIGN); + aotInfo.AlignTextSec(AOTFileInfo::RODATA_SEC_ALIGN); aotInfo.UpdateCurTextSecOffset(rodataSizeAfterText); } } @@ -320,8 +320,13 @@ uintptr_t Module::GetSectionAddr(ElfSecName sec) const return assembler_->GetSectionAddr(sec); } -void Module::RunAssembler(const CompilerLog &log, bool fastCompileMode, bool isJit) +void Module::RunAssembler(const CompilerLog &log, bool fastCompileMode, bool isJit, const std::string &filename) { + if (!IsLLVM()) { + assembler_->SetAotCodeCommentFile(filename); + } else { + assembler_->SetAotCodeCommentFile(""); + } assembler_->Run(log, fastCompileMode, isJit); } @@ -434,7 +439,7 @@ uint64_t AOTFileGenerator::RollbackTextSize(Module *module) textStart = aotInfo_.GetCurTextSecOffset() - textSize; } else { textStart = aotInfo_.GetCurTextSecOffset() - textSize - rodataSizeAfterText; - textStart = AlignDown(textStart, AOTFileInfo::DATA_SEC_ALIGN); + textStart = AlignDown(textStart, AOTFileInfo::RODATA_SEC_ALIGN); } return textStart; } @@ -592,7 +597,7 @@ void AOTFileGenerator::CompileLatestModuleThenDestroy(bool isJit) { TimeScope timescope("LLVMIROpt", const_cast(log_)); bool fastCompileMode = compilationEnv_->GetJSOptions().GetFastAOTCompileMode(); - latestModule->RunAssembler(*(log_), fastCompileMode, isJit); + latestModule->RunAssembler(*(log_), fastCompileMode, isJit, GetAotCodeCommentFile()); } { TimeScope timescope("LLVMCodeGen", const_cast(log_)); @@ -804,4 +809,50 @@ bool AOTFileGenerator::SaveSnapshotFile() SetSecurityLabel(aiPath.c_str()); return true; } + +bool AOTFileGenerator::CreateAOTCodeCommentFile(const std::string &filename) +{ + if (!CreateDirIfNotExist(filename)) { + LOG_COMPILER(ERROR) << "Fail to access dir: " << filename; + return false; + } + + std::string realPath; + if (!panda::ecmascript::RealPath(filename, realPath, false)) { + LOG_COMPILER(ERROR) << "Fail to get realPath: " << filename; + return false; + } + + auto index = realPath.find_last_of('/'); + if (index == std::string::npos) { + LOG_COMPILER(ERROR) << "Path: " << realPath << " is illegal"; + return false; + } + + std::string aotCodeCommentFile = realPath.substr(0, index) + "/aot_code_comment.txt"; + SetAotCodeCommentFile(aotCodeCommentFile); + if (FileExist(aotCodeCommentFile.c_str())) { + if (Unlink(aotCodeCommentFile.c_str()) == -1) { + SetAotCodeCommentFile(""); + LOG_COMPILER(ERROR) << "remove " << aotCodeCommentFile << " failed and errno is " << errno; + return false; + } + } + + std::ofstream file(aotCodeCommentFile.c_str(), std::ofstream::app); + if (!file.is_open()) { + SetAotCodeCommentFile(""); + LOG_COMPILER(ERROR) << "Failed to create " << aotCodeCommentFile; + return false; + } + file.close(); + + if (!panda::ecmascript::SetFileModeAsDefault(aotCodeCommentFile)) { + SetAotCodeCommentFile(""); + Unlink(aotCodeCommentFile.c_str()); + LOG_COMPILER(ERROR) << "Fail to set file mode: " << aotCodeCommentFile; + return false; + } + return true; +} } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/file_generators.h b/ecmascript/compiler/file_generators.h index 9b2058db81f02166412361c9286cc99f32242f5c..f5c53de7ec38e57d66696cf5372fdd767ecbeb3b 100644 --- a/ecmascript/compiler/file_generators.h +++ b/ecmascript/compiler/file_generators.h @@ -83,7 +83,8 @@ public: return std::make_tuple(addrBeforeText, sizeBeforeText, addrAfterText, sizeAfterText); } - void RunAssembler(const CompilerLog &log, bool fastCompileMode, bool isJit = false); + void RunAssembler(const CompilerLog &log, bool fastCompileMode, bool isJit = false, + const std::string &filename = ""); void DisassemblerFunc(std::map &addr2name, uint64_t textOffset, const CompilerLog &log, const MethodLogList &logList, std::ostringstream &codeStream); @@ -221,6 +222,19 @@ public: bool GetMemoryCodeInfos(MachineCodeDesc &machineCodeDesc); void JitCreateLitecgModule(); bool isAArch64() const; + + bool CreateAOTCodeCommentFile(const std::string &filename); + + const std::string &GetAotCodeCommentFile() const + { + return aotCodeCommentFile_; + } + + void SetAotCodeCommentFile(const std::string &filename) + { + aotCodeCommentFile_ = filename; + } + private: // collect aot component info void CollectCodeInfo(Module *module, uint32_t moduleIdx); @@ -236,6 +250,7 @@ private: std::map methodToEntryIndexMap_ {}; const bool useLiteCG_; CodeInfo::CodeSpaceOnDemand jitCodeSpace_ {}; + std::string aotCodeCommentFile_ = ""; }; enum class StubFileKind { diff --git a/ecmascript/compiler/gate_accessor.cpp b/ecmascript/compiler/gate_accessor.cpp index 14ebcf347ced78dab22ecb39c2a67d0ea59e5799..6184e1a77a914417c4489b2e9d3ccdac68dd5887 100644 --- a/ecmascript/compiler/gate_accessor.cpp +++ b/ecmascript/compiler/gate_accessor.cpp @@ -325,6 +325,15 @@ TypedArrayMetaDataAccessor GateAccessor::GetTypedArrayMetaDataAccessor(GateRef g return TypedArrayMetaDataAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); } +void GateAccessor::UpdateOnHeapMode(GateRef gate, OnHeapMode onHeapMode) +{ + ASSERT(GetOpCode(gate) == OpCode::TYPED_ARRAY_CHECK); + Gate *gatePtr = circuit_->LoadGatePtr(gate); + TypedArrayMetaDataAccessor accessor = GetTypedArrayMetaDataAccessor(gate); + uint64_t value = accessor.UpdateOnHeapMode(onHeapMode); + const_cast(gatePtr->GetOneParameterMetaData())->SetValue(value); +} + LoadElementAccessor GateAccessor::GetLoadElementAccessor(GateRef gate) const { ASSERT(GetOpCode(gate) == OpCode::LOAD_ELEMENT); diff --git a/ecmascript/compiler/gate_accessor.h b/ecmascript/compiler/gate_accessor.h index a26a293aa8ec21d9b62016fae1192c19fe2e8afb..95a2769846f76e23ab8b55512d02e4517f7cf573 100644 --- a/ecmascript/compiler/gate_accessor.h +++ b/ecmascript/compiler/gate_accessor.h @@ -624,6 +624,7 @@ public: TypedBinOp GetRevCompareOpForTypedBinOp(TypedBinOp op); TypedBinOp GetSwapCompareOpForTypedBinOp(TypedBinOp op); + void UpdateOnHeapMode(GateRef gate, OnHeapMode onHeapMode); private: const GateMetaData *GetMetaData(GateRef gate) const; diff --git a/ecmascript/compiler/hcr_circuit_builder.cpp b/ecmascript/compiler/hcr_circuit_builder.cpp index b1f92a6f4fb291f6c1349c5b0114282d86ac737f..d64f8d7998880e6e97880a918d641f337540d544 100644 --- a/ecmascript/compiler/hcr_circuit_builder.cpp +++ b/ecmascript/compiler/hcr_circuit_builder.cpp @@ -589,7 +589,7 @@ GateRef CircuitBuilder::IsStabelArray(GateRef glue, GateRef obj) Bind(&targetIsStableArray); { GateRef guardiansOffset = - IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(false)); + IntPtr(JSThread::GlueData::GetArrayElementsGuardiansOffset(false)); result = Load(VariableType::BOOL(), glue, guardiansOffset); Jump(&exit); } diff --git a/ecmascript/compiler/hcr_circuit_builder.h b/ecmascript/compiler/hcr_circuit_builder.h index 516ef1769d5f3d4ab02a076cdcb8e9c384c48400..159a7ad19c1bfd6e09a7f5bf77c3501d9a3171b3 100644 --- a/ecmascript/compiler/hcr_circuit_builder.h +++ b/ecmascript/compiler/hcr_circuit_builder.h @@ -90,7 +90,7 @@ GateRef CircuitBuilder::IsCallable(GateRef obj) return IsCallableFromBitField(bitfield); } -GateRef CircuitBuilder::IsProtoTypeHClass(GateRef hClass) +GateRef CircuitBuilder::IsPrototypeHClass(GateRef hClass) { GateRef bitfield = LoadConstOffset(VariableType::INT32(), hClass, JSHClass::BIT_FIELD_OFFSET); return TruncInt32ToInt1(Int32And(Int32LSR(bitfield, @@ -300,6 +300,16 @@ GateRef CircuitBuilder::IsStableElements(GateRef hClass) Int32(0)); } +GateRef CircuitBuilder::IsJSArrayPrototypeModified(GateRef hClass) +{ + GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET); + GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset); + return NotEqual(Int32And(Int32LSR(bitfield, + Int32(JSHClass::IsJSArrayPrototypeModifiedBit::START_BIT)), + Int32((1LU << JSHClass::IsJSArrayPrototypeModifiedBit::SIZE) - 1)), + Int32(0)); +} + GateRef CircuitBuilder::HasConstructor(GateRef object) { GateRef hClass = LoadHClass(object); diff --git a/ecmascript/compiler/induction_variable_analysis.cpp b/ecmascript/compiler/induction_variable_analysis.cpp index b05f62e87bd7fa6d114c5126415fddf7c975ab62..2cc053ae49b7c6400d983253206b8560571b4cad 100644 --- a/ecmascript/compiler/induction_variable_analysis.cpp +++ b/ecmascript/compiler/induction_variable_analysis.cpp @@ -117,7 +117,7 @@ bool InductionVariableAnalysis::IsLessOrGreaterCmp(GateRef gate) const bool InductionVariableAnalysis::TryGetLoopTimes(const GraphLinearizer::LoopInfo& loop, int32_t& loopTimes) const { - if (loop.loopExits->size() > 1) { + if (loop.loopExits == nullptr || loop.loopExits->size() > 1) { return false; } ASSERT(loop.loopExits->size() == 1); diff --git a/ecmascript/compiler/instruction_combine.cpp b/ecmascript/compiler/instruction_combine.cpp index b0d7da47eae779f354b9d8565c3fb6c2248932f0..db1f87bc60e7d99467982d913b993b6080bca8f4 100644 --- a/ecmascript/compiler/instruction_combine.cpp +++ b/ecmascript/compiler/instruction_combine.cpp @@ -124,22 +124,6 @@ GateRef InstructionCombine::VisitConvert(GateRef gate) } break; } - case OpCode::INT64_TO_TAGGED: - { - GateMatcher in(acc_.GetValueIn(gate, 0), circuit_); - if (in.IsTaggedToInt64()) { - return in.ValueIn(0); - } - break; - } - case OpCode::SIGNED_INT_TO_FLOAT: - { - GateMatcher in(acc_.GetValueIn(gate, 0), circuit_); - if (in.IsFloatToSignedInt()) { - return in.ValueIn(0); - } - break; - } case OpCode::FLOAT_TO_SIGNED_INT: { GateMatcher in(acc_.GetValueIn(gate, 0), circuit_); @@ -148,8 +132,9 @@ GateRef InstructionCombine::VisitConvert(GateRef gate) } break; } + case OpCode::INT64_TO_TAGGED: + case OpCode::SIGNED_INT_TO_FLOAT: case OpCode::UNSIGNED_FLOAT_TO_INT: - break; case OpCode::BITCAST: case OpCode::ZEXT: case OpCode::SEXT: diff --git a/ecmascript/compiler/interpreter_stub.cpp b/ecmascript/compiler/interpreter_stub.cpp index 0e21dc3e1d369ce4b057d6f233ec45d82d64957f..a1c1aa5f0dfb9a40ab41ecec6050ff5f04a6fce9 100644 --- a/ecmascript/compiler/interpreter_stub.cpp +++ b/ecmascript/compiler/interpreter_stub.cpp @@ -437,6 +437,11 @@ void InterpreterStubBuilder::DebugPrintInstruction() GateRef pc = PtrArgument(static_cast(InterpreterHandlerInputs::PC)); CallNGCRuntime(glue, RTSTUB_ID(DebugPrintInstruction), { glue, pc }); #endif +#if ECMASCRIPT_ENABLE_COLLECTING_OPCODES + GateRef opcodeGlue = PtrArgument(static_cast(InterpreterHandlerInputs::GLUE)); + GateRef opcodePc = PtrArgument(static_cast(InterpreterHandlerInputs::PC)); + CallNGCRuntime(opcodeGlue, RTSTUB_ID(CollectingOpcodes), { opcodeGlue, opcodePc }); +#endif } DECLARE_ASM_HANDLER(HandleLdnan) @@ -4927,6 +4932,10 @@ DECLARE_ASM_HANDLER(HandleDefinemethodImm8Id16Imm8) GetMethodFromConstPool(glue, constpool, ZExtInt16ToInt32(methodId))); result = CallRuntime(glue, RTSTUB_ID(DefineMethod), { *result, acc, Int8ToTaggedInt(length), lexEnv, GetModule(sp) }); +#if ECMASCRIPT_ENABLE_IC + GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc)); + UpdateProfileTypeInfoCellToFunction(glue, *result, profileTypeInfo, slotId); +#endif Label notException(env); CHECK_EXCEPTION_WITH_JUMP(*result, ¬Exception); Bind(¬Exception); @@ -4947,6 +4956,10 @@ DECLARE_ASM_HANDLER(HandleDefinemethodImm16Id16Imm8) GetMethodFromConstPool(glue, constpool, ZExtInt16ToInt32(methodId))); result = CallRuntime(glue, RTSTUB_ID(DefineMethod), { *result, acc, Int8ToTaggedInt(length), lexEnv, GetModule(sp) }); +#if ECMASCRIPT_ENABLE_IC + GateRef slotId = ZExtInt16ToInt32(ReadInst16_0(pc)); + UpdateProfileTypeInfoCellToFunction(glue, *result, profileTypeInfo, slotId); +#endif Label notException(env); CHECK_EXCEPTION_WITH_JUMP(*result, ¬Exception); Bind(¬Exception); diff --git a/ecmascript/compiler/jit_compilation_env.cpp b/ecmascript/compiler/jit_compilation_env.cpp index 12f9715a64e31bfd945c7b32001026ff3a16ae04..506999b39d4f4893442a52303b93317622513b57 100644 --- a/ecmascript/compiler/jit_compilation_env.cpp +++ b/ecmascript/compiler/jit_compilation_env.cpp @@ -24,7 +24,10 @@ namespace panda::ecmascript { JitCompilationEnv::JitCompilationEnv(EcmaVM *jitVm, EcmaVM *jsVm, JSHandle &jsFunction) : CompilationEnv(jitVm), hostThread_(jsVm->GetJSThreadNoCheck()), jsFunction_(jsFunction) { - ptManager_ = hostThread_->GetCurrentEcmaContext()->GetPTManager(); + if (hostThread_ != nullptr && hostThread_->GetCurrentEcmaContext() != nullptr && + hostThread_->GetCurrentEcmaContext()->GetPTManager() != nullptr) { + ptManager_ = hostThread_->GetCurrentEcmaContext()->GetPTManager(); + } Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject()); jsPandaFile_ = const_cast(method->GetJSPandaFile()); methodLiteral_ = method->GetMethodLiteral(); diff --git a/ecmascript/compiler/jit_compiler.cpp b/ecmascript/compiler/jit_compiler.cpp index 22575510c0ec499c6e16fbc9a7bf01be60beb236..4f8639ebeb18fcd5b3bd04dd58bb1dc523e9cbe5 100644 --- a/ecmascript/compiler/jit_compiler.cpp +++ b/ecmascript/compiler/jit_compiler.cpp @@ -116,7 +116,7 @@ JitCompilerTask *JitCompilerTask::CreateJitCompilerTask(JitTask *jitTask) bool JitCompilerTask::Compile() { - if (compilerTier_ == CompilerTier::BASELINE) { + if (compilerTier_.IsBaseLine()) { auto baselineCompiler = new (std::nothrow) BaselineCompiler(jitCompilationEnv_->GetHostThread()->GetEcmaVM(), jitCompilationEnv_.get()); if (baselineCompiler == nullptr) { @@ -164,7 +164,7 @@ bool JitCompilerTask::Finalize(JitTask *jitTask) if (jitTask == nullptr) { return false; } - if (compilerTier_ == CompilerTier::BASELINE) { + if (compilerTier_.IsBaseLine()) { return baselineCompiler_->CollectMemoryCodeInfos(jitTask->GetMachineCodeDesc()); } jitCodeGenerator_->JitCreateLitecgModule(); @@ -276,11 +276,11 @@ bool JitFinalize(void *compilerTask, JitTask *jitTask) return jitCompilerTask->Finalize(jitTask); } -void DeleteJitCompile(void *handle) +void DeleteJitCompilerTask(void *compilerTask) { - if (handle == nullptr) { + if (compilerTask == nullptr) { return; } - delete reinterpret_cast(handle); + delete reinterpret_cast(compilerTask); } } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/jit_compiler.h b/ecmascript/compiler/jit_compiler.h index 172902db337da8f64ea26dd99d441b01169de1f2..03448a4d0a110bcb9e765bc3e7829d6d0a877ec9 100644 --- a/ecmascript/compiler/jit_compiler.h +++ b/ecmascript/compiler/jit_compiler.h @@ -30,7 +30,7 @@ PUBLIC_API void InitJitCompiler(JSRuntimeOptions options); PUBLIC_API void *CreateJitCompilerTask(JitTask *jitTask); PUBLIC_API bool JitCompile(void *compiler, JitTask *jitTask); PUBLIC_API bool JitFinalize(void *compiler, JitTask *jitTask); -PUBLIC_API void DeleteJitCompile(void *handle); +PUBLIC_API void DeleteJitCompilerTask(void *handle); }; struct JitCompilationOptions { diff --git a/ecmascript/compiler/lcr_circuit_builder.cpp b/ecmascript/compiler/lcr_circuit_builder.cpp index 711d92ea14c4e3bb84c6b7fcd48e7c2ad65b227a..4c5930a5998ad1382f03c785d394bb5dc9e2e757 100644 --- a/ecmascript/compiler/lcr_circuit_builder.cpp +++ b/ecmascript/compiler/lcr_circuit_builder.cpp @@ -200,34 +200,42 @@ GateRef CircuitBuilder::GetDoubleOfTNumber(GateRef x) return ret; } -GateRef CircuitBuilder::DoubleToInt(GateRef x, Label *exit) +GateRef CircuitBuilder::DoubleToIntOverflowCheck(GateRef x, size_t typeBits) { - Label overflow(env_); - - GateRef xInt = ChangeFloat64ToInt32(x); - DEFVALUE(result, env_, VariableType::INT32(), xInt); - GateRef xInt64 = CastDoubleToInt64(x); // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK)); exp = TruncInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE))); exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS)); - GateRef bits = Int32(base::INT32_BITS - 1); + GateRef bits = Int32(typeBits - 1); // exp < 32 - 1 - BRANCH_CIR2(Int32LessThan(exp, bits), exit, &overflow); + return Int32LessThan(exp, bits); +} + +GateRef CircuitBuilder::TruncDoubleToInt(GateRef glue, GateRef x, size_t typeBits) +{ + Label entry(env_); + env_->SubCfgEntry(&entry); + Label exit(env_); + Label overflow(env_); + + GateRef xInt = ChangeFloat64ToInt32(x); + DEFVALUE(result, env_, VariableType::INT32(), xInt); + BRANCH_CIR2(DoubleToIntOverflowCheck(x, typeBits), &exit, &overflow); Bind(&overflow); { - result = CallNGCRuntime(acc_.GetGlueFromArgList(), RTSTUB_ID(DoubleToInt), - Circuit::NullGate(), { x, IntPtr(base::INT32_BITS) }, Circuit::NullGate()); - Jump(exit); + result = CallNGCRuntime(glue, RTSTUB_ID(DoubleToInt), Circuit::NullGate(), { x, IntPtr(typeBits) }, + Circuit::NullGate()); + Jump(&exit); } - Bind(exit); + Bind(&exit); auto ret = *result; + env_->SubCfgExit(); return ret; } -GateRef CircuitBuilder::DoubleToInt(GateRef glue, GateRef x, size_t typeBits) +GateRef CircuitBuilder::SaturateTruncDoubleToInt32(GateRef glue, GateRef x) { Label entry(env_); env_->SubCfgEntry(&entry); @@ -236,23 +244,11 @@ GateRef CircuitBuilder::DoubleToInt(GateRef glue, GateRef x, size_t typeBits) GateRef xInt = ChangeFloat64ToInt32(x); DEFVALUE(result, env_, VariableType::INT32(), xInt); + BRANCH_CIR2(DoubleToIntOverflowCheck(x, base::INT32_BITS), &exit, &overflow); - if (env_->IsAmd64()) { - // 0x80000000: amd64 overflow return value - BRANCH_CIR2(Int32Equal(xInt, Int32(0x80000000)), &overflow, &exit); - } else { - GateRef xInt64 = CastDoubleToInt64(x); - // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS - GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK)); - exp = TruncInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE))); - exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS)); - GateRef bits = Int32(typeBits - 1); - // exp < 32 - 1 - BRANCH_CIR2(Int32LessThan(exp, bits), &exit, &overflow); - } Bind(&overflow); { - result = CallNGCRuntime(glue, RTSTUB_ID(DoubleToInt), Circuit::NullGate(), { x, IntPtr(typeBits) }, + result = CallNGCRuntime(glue, RTSTUB_ID(SaturateTruncDoubleToInt32), Circuit::NullGate(), { x }, Circuit::NullGate()); Jump(&exit); } diff --git a/ecmascript/compiler/mcr_circuit_builder.cpp b/ecmascript/compiler/mcr_circuit_builder.cpp index 179d48f3ef58e6adac9cda0415d6dcb8dcbdacd2..3ed6b8307a475743805f29835295ff219b1e4ef7 100644 --- a/ecmascript/compiler/mcr_circuit_builder.cpp +++ b/ecmascript/compiler/mcr_circuit_builder.cpp @@ -118,6 +118,22 @@ GateRef CircuitBuilder::StableArrayCheck(GateRef gate, ElementsKind kind, ArrayM return ret; } +GateRef CircuitBuilder::MathHClassConsistencyCheck(GateRef receiver) +{ + auto currentLabel = env_->GetCurrentLabel(); + auto currentControl = currentLabel->GetControl(); + auto currentDepend = currentLabel->GetDepend(); + GateRef frameState = acc_.FindNearestFrameState(receiver); + + GateRef ret = GetCircuit()->NewGate(circuit_->MathHClassConsistencyCheck(), + MachineType::I1, {currentControl, currentDepend, receiver, frameState}, + GateType::NJSValue()); + + currentLabel->SetControl(ret); + currentLabel->SetDepend(ret); + return ret; +} + GateRef CircuitBuilder::ElementsKindCheck(GateRef receiver, ElementsKind kind, ArrayMetaDataAccessor::Mode mode) { // If elements kind is hole, no ElementsKindCheck is required. @@ -1675,14 +1691,15 @@ GateRef CircuitBuilder::MonoStorePropertyLookUpProto(GateRef receiver, GateRef p } GateRef CircuitBuilder::MonoStoreProperty(GateRef receiver, GateRef plrGate, GateRef unsharedConstPool, - size_t hclassIndex, GateRef value, GateRef keyIndex, GateRef frameState) + size_t hclassIndex, GateRef value, GateRef keyIndex, GateRef isProto, + GateRef frameState) { auto currentLabel = env_->GetCurrentLabel(); auto currentControl = currentLabel->GetControl(); auto currentDepend = currentLabel->GetDepend(); auto ret = GetCircuit()->NewGate(circuit_->MonoStoreProperty(false), MachineType::I64, {currentControl, currentDepend, receiver, plrGate, Int32(hclassIndex), - unsharedConstPool, value, keyIndex, frameState}, + unsharedConstPool, value, keyIndex, isProto, frameState}, GateType::AnyType()); currentLabel->SetControl(ret); currentLabel->SetDepend(ret); @@ -1988,6 +2005,20 @@ GateRef CircuitBuilder::ArrayPop(GateRef thisValue, GateRef frameState) return ret; } +GateRef CircuitBuilder::ArrayPush(GateRef thisValue, GateRef value) +{ + auto currentLabel = env_->GetCurrentLabel(); + auto currentControl = currentLabel->GetControl(); + auto currentDepend = currentLabel->GetDepend(); + GateRef ret = GetCircuit()->NewGate(circuit_->ArrayPush(), + MachineType::I64, + {currentControl, currentDepend, thisValue, value}, + GateType::AnyType()); + currentLabel->SetControl(ret); + currentLabel->SetDepend(ret); + return ret; +} + GateRef CircuitBuilder::ArraySlice(GateRef thisValue, GateRef startIndex, GateRef endIndex, GateRef frameState) { auto currentLabel = env_->GetCurrentLabel(); diff --git a/ecmascript/compiler/mcr_circuit_builder.h b/ecmascript/compiler/mcr_circuit_builder.h index 4e995deb2d1d007045beb18247d4583a95d8a60e..9d0e9b434d5ad3160d27917466f7bb35beae8b41 100644 --- a/ecmascript/compiler/mcr_circuit_builder.h +++ b/ecmascript/compiler/mcr_circuit_builder.h @@ -437,7 +437,7 @@ GateRef CircuitBuilder::TaggedIsTransitionHandler(GateRef x) return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::TRANSITION_HANDLER)).Done(); } -GateRef CircuitBuilder::TaggedIsStoreTSHandler(GateRef x) +GateRef CircuitBuilder::TaggedIsStoreAOTHandler(GateRef x) { return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::STORE_TS_HANDLER)).Done(); } diff --git a/ecmascript/compiler/mcr_lowering.cpp b/ecmascript/compiler/mcr_lowering.cpp index c95e94365b426b017b5266bf6bb551fcac982bc0..3877d58c91ab215a3d1aa0e5e491b8d66156d937 100644 --- a/ecmascript/compiler/mcr_lowering.cpp +++ b/ecmascript/compiler/mcr_lowering.cpp @@ -24,7 +24,7 @@ #include "ecmascript/js_thread.h" #include "ecmascript/jspandafile/program_object.h" #include "ecmascript/message_string.h" - +#include "ecmascript/compiler/builtins/builtins_string_stub_builder.h" namespace panda::ecmascript::kungfu { GateRef MCRLowering::VisitGate(GateRef gate) @@ -133,6 +133,9 @@ GateRef MCRLowering::VisitGate(GateRef gate) case OpCode::IS_CALLABLE_CHECK: LowerIsCallableCheck(gate); break; + case OpCode::MATH_HCLASS_CONSISTENCY_CHECK: + LowerMathHClassConsistencyCheck(gate); + break; case OpCode::STRING_ADD: LowerStringAdd(gate); default: @@ -280,7 +283,7 @@ void MCRLowering::LowerArrayGuardianCheck(GateRef gate) Environment env(gate, circuit_, &builder_); GateRef frameState = acc_.GetFrameState(gate); - GateRef guardiansOffset = builder_.IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(false)); + GateRef guardiansOffset = builder_.IntPtr(JSThread::GlueData::GetArrayElementsGuardiansOffset(false)); GateRef check = builder_.Load(VariableType::BOOL(), glue_, guardiansOffset); builder_.DeoptCheck(check, frameState, DeoptType::NOTSARRAY1); @@ -299,6 +302,20 @@ void MCRLowering::LowerHClassStableArrayCheck(GateRef gate) acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); } +void MCRLowering::LowerMathHClassConsistencyCheck(GateRef gate) +{ + Environment env(gate, circuit_, &builder_); + GateRef receiver = acc_.GetValueIn(gate, 0); + GateRef receiverHClass = builder_.LoadHClassByConstOffset(receiver); + + GateRef cond = builder_.Equal(receiverHClass, + builder_.GetGlobalEnvObj(builder_.GetGlobalEnv(), GlobalEnv::MATH_FUNCTION_CLASS_INDEX)); + + builder_.DeoptCheck(cond, acc_.GetFrameState(gate), DeoptType::INCONSISTENTHCLASS14); + + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); +} + StateDepend MCRLowering::LowerConvert(StateDepend stateDepend, GateRef gate) { Environment env(stateDepend.State(), stateDepend.Depend(), {}, circuit_, &builder_); @@ -335,7 +352,7 @@ StateDepend MCRLowering::LowerConvert(StateDepend stateDepend, GateRef gate) if (dstType == ValueType::TAGGED_DOUBLE) { result = ConvertFloat64ToTaggedDouble(value); } else if (dstType == ValueType::INT32) { - result = ConvertFloat64ToInt32(value, &exit); + result = ConvertFloat64ToInt32(acc_.GetGlueFromArgList(), value); } else { ASSERT(dstType == ValueType::BOOL); result = ConvertFloat64ToBool(value); @@ -356,7 +373,8 @@ StateDepend MCRLowering::LowerConvert(StateDepend stateDepend, GateRef gate) case ValueType::CHAR: { GateRef glue = acc_.GetGlueFromArgList(); if (dstType == ValueType::ECMA_STRING) { - result = builder_.CallStub(glue, gate, CommonStubCSigns::CreateStringBySingleCharCode, { glue, value }); + BuiltinsStringStubBuilder builder(&env); + result = builder.CreateStringBySingleCharCode(glue, value); } else if (dstType == ValueType::INT32) { result = builder_.CallStub(glue, gate, CommonStubCSigns::ConvertCharToInt32, { glue, value }); } else { @@ -457,13 +475,12 @@ GateRef MCRLowering::ConvertTaggedNumberToInt32(GateRef gate, Label *exit) DEFVALUE(result, (&builder_), VariableType::INT32(), builder_.Int32(0)); Label isInt(&builder_); Label isDouble(&builder_); - Label toInt32(&builder_); BRANCH_CIR(builder_.TaggedIsInt(gate), &isInt, &isDouble); builder_.Bind(&isInt); result = ConvertTaggedIntToInt32(gate); builder_.Jump(exit); builder_.Bind(&isDouble); - result = ConvertFloat64ToInt32(ConvertTaggedDoubleToFloat64(gate), &toInt32); + result = ConvertFloat64ToInt32(acc_.GetGlueFromArgList(), ConvertTaggedDoubleToFloat64(gate)); builder_.Jump(exit); builder_.Bind(exit); return *result; @@ -499,7 +516,7 @@ void MCRLowering::LowerCheckAndConvert(GateRef gate) LowerCheckTaggedIntAndConvert(gate, frameState); break; case ValueType::TAGGED_DOUBLE: - LowerCheckTaggedDoubleAndConvert(gate, frameState, &exit); + LowerCheckTaggedDoubleAndConvert(gate, frameState); break; case ValueType::TAGGED_BOOLEAN: LowerCheckTaggedBoolAndConvert(gate, frameState); @@ -523,21 +540,21 @@ void MCRLowering::LowerCheckAndConvert(GateRef gate) LowerCheckSpecialHoleAndConvert(gate, frameState); break; case ValueType::FLOAT64: - LowerCheckFloat64AndConvert(gate, frameState, &exit); + LowerCheckFloat64AndConvert(gate, frameState); break; default: UNREACHABLE(); } } -void MCRLowering::LowerCheckFloat64AndConvert(GateRef gate, GateRef frameState, Label *exit) +void MCRLowering::LowerCheckFloat64AndConvert(GateRef gate, GateRef frameState) { GateRef value = acc_.GetValueIn(gate, 0); ValueType dst = acc_.GetDstType(gate); GateRef result = Circuit::NullGate(); if (dst == ValueType::INT32) { - result = ConvertFloat64ToInt32(value, exit); + result = builder_.ChangeFloat64ToInt32(value); GateRef check = builder_.DoubleEqual(builder_.ChangeInt32ToFloat64(result), value); builder_.DeoptCheck(check, frameState, DeoptType::NOTINT7); } else { @@ -595,7 +612,7 @@ void MCRLowering::LowerCheckTaggedIntAndConvert(GateRef gate, GateRef frameState acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); } -void MCRLowering::LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameState, Label *exit) +void MCRLowering::LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameState) { GateRef value = acc_.GetValueIn(gate, 0); GateRef typeCheck = builder_.TaggedIsDouble(value); @@ -604,7 +621,7 @@ void MCRLowering::LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameSt ValueType dst = acc_.GetDstType(gate); ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64); if (dst == ValueType::INT32) { - result = ConvertTaggedDoubleToInt32(value, exit); + result = ConvertTaggedDoubleToInt32(acc_.GetGlueFromArgList(), value); } else { result = ConvertTaggedDoubleToFloat64(value); } @@ -747,9 +764,9 @@ GateRef MCRLowering::ConvertUInt32ToTaggedNumber(GateRef gate, Label *exit) return *taggedVal; } -GateRef MCRLowering::ConvertFloat64ToInt32(GateRef gate, Label *exit) +GateRef MCRLowering::ConvertFloat64ToInt32(GateRef glue, GateRef gate) { - return builder_.DoubleToInt(gate, exit); + return builder_.TruncDoubleToInt(glue, gate, base::INT32_BITS); } GateRef MCRLowering::ConvertFloat64ToBool(GateRef gate) @@ -775,9 +792,9 @@ GateRef MCRLowering::ConvertTaggedIntToFloat64(GateRef gate) return builder_.ChangeInt32ToFloat64(builder_.GetInt32OfTInt(gate)); } -GateRef MCRLowering::ConvertTaggedDoubleToInt32(GateRef gate, Label *exit) +GateRef MCRLowering::ConvertTaggedDoubleToInt32(GateRef glue, GateRef gate) { - return builder_.DoubleToInt(builder_.GetDoubleOfTDouble(gate), exit); + return builder_.TruncDoubleToInt(glue, builder_.GetDoubleOfTDouble(gate), base::INT32_BITS); } GateRef MCRLowering::ConvertTaggedDoubleToFloat64(GateRef gate) diff --git a/ecmascript/compiler/mcr_lowering.h b/ecmascript/compiler/mcr_lowering.h index 6f5b1318bc514a23994e2eb516c6ac9543e02e1b..622cb71742ed000aefa7e82067f478edc9aaf175 100644 --- a/ecmascript/compiler/mcr_lowering.h +++ b/ecmascript/compiler/mcr_lowering.h @@ -43,6 +43,7 @@ private: void LowerIsMarkerCellValid(GateRef gate); void LowerIsSpecificObjectType(GateRef gate); void LowerHClassStableArrayCheck(GateRef gate); + void LowerMathHClassConsistencyCheck(GateRef gate); void LowerGetConstPool(GateRef gate); void LowerGetUnsharedConstpool(GateRef gate); void LowerLoadConstOffset(GateRef gate); @@ -52,7 +53,7 @@ private: void LowerCheckAndConvert(GateRef gate); void LowerCheckUInt32AndConvert(GateRef gate, GateRef frameState); void LowerCheckTaggedIntAndConvert(GateRef gate, GateRef frameState); - void LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameState, Label *exit); + void LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameState); void LowerCheckTaggedNumberAndConvert(GateRef gate, GateRef frameState, Label *exit); void LowerCheckTaggedBoolAndConvert(GateRef gate, GateRef frameState); void LowerCheckSpecialHoleAndConvert(GateRef gate, GateRef frameState); @@ -82,7 +83,7 @@ private: void LowerMigrateFromHoleNumberToHoleInt(GateRef gate); void LowerHeapObjectIsEcmaObject(GateRef gate); void LowerIsCallableCheck(GateRef gate); - void LowerCheckFloat64AndConvert(GateRef gate, GateRef frameState, Label *exit); + void LowerCheckFloat64AndConvert(GateRef gate, GateRef frameState); void LowerStringAdd(GateRef gate); GateRef ConvertSpecialHoleIntToTagged(GateRef gate, Label* exit); @@ -93,11 +94,11 @@ private: GateRef ConvertInt32ToTaggedInt(GateRef gate); GateRef ConvertUInt32ToTaggedNumber(GateRef gate, Label *exit); GateRef ConvertFloat64ToBool(GateRef gate); - GateRef ConvertFloat64ToInt32(GateRef gate, Label *exit); + GateRef ConvertFloat64ToInt32(GateRef glue, GateRef gate); GateRef ConvertFloat64ToTaggedDouble(GateRef gate); GateRef ConvertTaggedIntToInt32(GateRef gate); GateRef ConvertTaggedIntToFloat64(GateRef gate); - GateRef ConvertTaggedDoubleToInt32(GateRef gate, Label *exit); + GateRef ConvertTaggedDoubleToInt32(GateRef glue, GateRef gate); GateRef ConvertTaggedDoubleToFloat64(GateRef gate); GateRef ConvertTaggedNumberToBool(GateRef gate, Label *exit); GateRef ConvertTaggedNumberToInt32(GateRef gate, Label *exit); diff --git a/ecmascript/compiler/mcr_opcodes.h b/ecmascript/compiler/mcr_opcodes.h index 5260e897e00c2e182caf5ccd6d563a6b7644f58d..c9a663772f2e4f1a2dea15ab0024744e1470ab86 100644 --- a/ecmascript/compiler/mcr_opcodes.h +++ b/ecmascript/compiler/mcr_opcodes.h @@ -46,6 +46,7 @@ namespace panda::ecmascript::kungfu { V(FlattenTreeStringCheck, FLATTEN_TREE_STRING_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ V(HeapObjectCheck, HEAP_OBJECT_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ V(EcmaObjectCheck, ECMA_OBJECT_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ + V(MathHClassConsistencyCheck, MATH_HCLASS_CONSISTENCY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ V(ProtoChangeMarkerCheck, PROTO_CHANGE_MARKER_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ V(LookUpHolder, LOOK_UP_HOLDER, GateFlags::CHECKABLE, 1, 1, 3) \ V(LoadGetter, LOAD_GETTER, GateFlags::NO_WRITE, 0, 1, 2) \ @@ -165,6 +166,7 @@ namespace panda::ecmascript::kungfu { V(ArrayIncludesIndexOf, ARRAY_INCLUDES_INDEXOF, GateFlags::NO_WRITE, 1, 1, 5) \ V(ArrayIteratorBuiltin, ARRAY_ITERATOR_BUILTIN, GateFlags::NONE_FLAG, 1, 1, 2) \ V(ArrayPop, ARRAY_POP, GateFlags::NONE_FLAG, 1, 1, 2) \ + V(ArrayPush, ARRAY_PUSH, GateFlags::NONE_FLAG, 1, 1, 2) \ V(ArraySlice, ARRAY_SLICE, GateFlags::NONE_FLAG, 1, 1, 4) \ V(ArraySort, ARRAY_SORT, GateFlags::NONE_FLAG, 1, 1, 2) \ MCR_BINARY_GATE_META_DATA_CACHE_LIST(V) @@ -211,7 +213,7 @@ namespace panda::ecmascript::kungfu { #define MCR_GATE_META_DATA_LIST_WITH_BOOL(V) \ V(LoadProperty, LOAD_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2) \ V(MonoStorePropertyLookUpProto, MONO_STORE_PROPERTY_LOOK_UP_PROTO, GateFlags::HAS_FRAME_STATE, 1, 1, 5) \ - V(MonoStoreProperty, MONO_STORE_PROPERTY, GateFlags::HAS_FRAME_STATE, 1, 1, 6) + V(MonoStoreProperty, MONO_STORE_PROPERTY, GateFlags::HAS_FRAME_STATE, 1, 1, 7) #define MCR_GATE_META_DATA_LIST_WITH_GATE_TYPE(V) \ V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ diff --git a/ecmascript/compiler/native_inline_lowering.cpp b/ecmascript/compiler/native_inline_lowering.cpp index 906d81160d9659560812e726c35465913ce5260b..4ed66d59e1e8750b555876f1d72250d097ca887c 100644 --- a/ecmascript/compiler/native_inline_lowering.cpp +++ b/ecmascript/compiler/native_inline_lowering.cpp @@ -16,6 +16,7 @@ #include "ecmascript/builtins/builtins_number.h" #include "ecmascript/builtins/builtins_string.h" #include "ecmascript/base/number_helper.h" +#include "ecmascript/compiler/builtins/builtins_call_signature.h" #include "ecmascript/compiler/circuit.h" #include "ecmascript/compiler/circuit_builder-inl.h" #include "ecmascript/compiler/circuit_builder_helper.h" @@ -383,6 +384,9 @@ void NativeInlineLowering::RunNativeInlineLowering() case BuiltinsStubCSigns::ID::ArrayPop: TryInlineArrayPop(gate, argc, id, skipThis); break; + case BuiltinsStubCSigns::ID::ArrayPush: + TryInlineArrayPush(gate, argc, id, skipThis); + break; case BuiltinsStubCSigns::ID::ArraySlice: TryInlineArraySlice(gate, argc, id, skipThis); break; @@ -684,8 +688,9 @@ void NativeInlineLowering::TryInlineNumberParseInt(GateRef gate, size_t argc, bo if (EnableTrace()) { AddTraceLogs(gate, id); } + // this may return exception GateRef ret = builder_.NumberParseInt(arg, radix); - acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); + acc_.ReplaceGate(gate, builder_.GetStateDepend(), ret); } void NativeInlineLowering::TryInlineNumberIsSafeInteger(GateRef gate, size_t argc, bool skipThis) @@ -1536,11 +1541,11 @@ void NativeInlineLowering::TryInlineArrayIterator(GateRef gate, BuiltinsStubCSig if (!Uncheck()) { builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast(id)), {tacc.GetThisObj()}); } + GateRef thisObj = acc_.GetValueIn(gate, 0); + builder_.EcmaObjectCheck(thisObj); if (EnableTrace()) { AddTraceLogs(gate, id); } - GateRef thisObj = acc_.GetValueIn(gate, 0); - builder_.EcmaObjectCheck(thisObj); GateRef CallIDRef = builder_.Int32(static_cast(id)); GateRef ret = builder_.ArrayIteratorBuiltin(thisObj, CallIDRef); acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); @@ -1655,7 +1660,7 @@ void NativeInlineLowering::TryInlineArrayFilter(GateRef gate, size_t argc, Built ret = builder_.ArrayFilter(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset); } else { ret = builder_.ArrayFilter( - thisValue, callBackFn, acc_.GetValueIn(gate, 2), frameState, pcOffset); //2: provide usingThis + thisValue, callBackFn, acc_.GetValueIn(gate, 2), frameState, pcOffset); // 2: provide usingThis } acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret); } @@ -1788,6 +1793,30 @@ void NativeInlineLowering::TryInlineArrayPop(GateRef gate, size_t argc, Builtins ReplaceGateWithPendingException(gate, ret); } +void NativeInlineLowering::TryInlineArrayPush(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) +{ + // To ensure that the Inline code is as small as possible, + // FastPath only processes the case when the number of elements to push equals 1 + // and elementsKinds is not enabled. + if (!skipThis || argc != 1 || enableElementsKind_) { + return; + } + Environment env(gate, circuit_, &builder_); + if (!Uncheck()) { + builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast(id))); + } + GateRef thisValue = acc_.GetValueIn(gate, 0); + ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue); + if (EnableTrace()) { + AddTraceLogs(gate, id); + } + builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); + builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false); + GateRef ret = builder_.ArrayPush(thisValue, acc_.GetValueIn(gate, 1)); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret); +} + + void NativeInlineLowering::TryInlineArraySlice(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) { if (!skipThis) { diff --git a/ecmascript/compiler/native_inline_lowering.h b/ecmascript/compiler/native_inline_lowering.h index cb4c8c9230197be3519da8553b4b8be604f51fdc..1839b27029a292dfcf31b5ca3e542ff702215035 100644 --- a/ecmascript/compiler/native_inline_lowering.h +++ b/ecmascript/compiler/native_inline_lowering.h @@ -38,6 +38,7 @@ public: methodName_(name), nocheck_(ctx->GetCompilationEnv()->GetJSOptions().IsCompilerNoCheck()), traceInline_(ctx->GetCompilationEnv()->GetJSOptions().GetTraceInline()), + enableElementsKind_(ctx->GetCompilationEnv()->GetJSOptions().IsEnableElementsKind()), compilationEnv_(ctx->GetCompilationEnv()), chunk_(chunk) {} ~NativeInlineLowering() = default; @@ -110,6 +111,7 @@ private: void TryInlineArraySome(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis); void TryInlineArrayEvery(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis); void TryInlineArrayPop(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis); + void TryInlineArrayPush(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis); void TryInlineArraySlice(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis); void TryInlineArraySort(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis); @@ -142,6 +144,7 @@ private: std::string methodName_; bool nocheck_; bool traceInline_; + bool enableElementsKind_; const CompilationEnv *compilationEnv_ {nullptr}; Chunk* chunk_ {nullptr}; }; diff --git a/ecmascript/compiler/new_object_stub_builder.cpp b/ecmascript/compiler/new_object_stub_builder.cpp index 8e1c5cbc7f8910eb3186996a56239e859982c473..2ca3cc8564177a712b8f4f37e46b3b8d04b0e073 100644 --- a/ecmascript/compiler/new_object_stub_builder.cpp +++ b/ecmascript/compiler/new_object_stub_builder.cpp @@ -431,10 +431,10 @@ void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hc { StoreHClass(glue_, result->ReadVariable(), hclass); DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined()); - Label isTS(env); + Label isAOT(env); Label initialize(env); - BRANCH(IsTSHClass(hclass), &isTS, &initialize); - Bind(&isTS); + BRANCH(IsAOTHClass(hclass), &isAOT, &initialize); + Bind(&isAOT); { // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist, // to follow ECMA spec. @@ -449,7 +449,8 @@ void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hc Bind(&afterInitialize); auto emptyArray = GetGlobalConstantValue( VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); - SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData())); + GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); + Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData())); SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier()); SetElementsArray(VariableType::INT64(), @@ -473,10 +474,10 @@ void NewObjectStubBuilder::NewSObject(Variable *result, Label *exit, GateRef hcl { StoreHClass(glue_, result->ReadVariable(), hclass); DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined()); - Label isTS(env); + Label isAOT(env); Label initialize(env); - BRANCH(IsTSHClass(hclass), &isTS, &initialize); - Bind(&isTS); + BRANCH(IsAOTHClass(hclass), &isAOT, &initialize); + Bind(&isAOT); { // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist, // to follow ECMA spec. @@ -491,7 +492,8 @@ void NewObjectStubBuilder::NewSObject(Variable *result, Label *exit, GateRef hcl Bind(&afterInitialize); auto emptyArray = GetGlobalConstantValue( VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); - SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData())); + GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); + Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData())); SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier()); SetElementsArray(VariableType::INT64(), @@ -585,7 +587,8 @@ void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hc Bind(&afterInitialize); auto emptyArray = GetGlobalConstantValue( VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); - SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData())); + GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); + Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData())); SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier()); SetElementsArray(VariableType::INT64(), @@ -784,7 +787,7 @@ void NewObjectStubBuilder::ExtendArray(Variable *res, GateRef glue, GateRef elem } Bind(&afterAllocate); Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen); - GateRef oldExtractLen = GetExtractLengthOfTaggedArray(elements); + GateRef oldExtractLen = GetExtraLengthOfTaggedArray(elements); Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen); GateRef oldL = GetLengthOfTaggedArray(elements); Label loopHead(env); @@ -885,7 +888,7 @@ GateRef NewObjectStubBuilder::CopyArray(GateRef glue, GateRef elements, GateRef } Bind(&afterInitializeElements); Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen); - GateRef oldExtractLen = GetExtractLengthOfTaggedArray(elements); + GateRef oldExtractLen = GetExtraLengthOfTaggedArray(elements); Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen); Label afterCopy(env); @@ -894,14 +897,14 @@ GateRef NewObjectStubBuilder::CopyArray(GateRef glue, GateRef elements, GateRef BRANCH(checkIsMutantTaggedArray, ©ToMutantTaggedArray, ©ToTaggedArray); Bind(©ToTaggedArray); { - ArrayCopy(glue, GetDataPtrInTaggedArray(elements), GetDataPtrInTaggedArray(*array), + ArrayCopy(glue, GetDataPtrInTaggedArray(elements), *array, GetDataPtrInTaggedArray(*array), newLen); Jump(&afterCopy); } Bind(©ToMutantTaggedArray); { - ArrayCopy(glue, GetDataPtrInTaggedArray(elements), GetDataPtrInTaggedArray(*array), newLen, - MemoryAttribute::NoBarrier()); + ArrayCopy(glue, GetDataPtrInTaggedArray(elements), *array, GetDataPtrInTaggedArray(*array), + newLen, MemoryAttribute::NoBarrier()); Jump(&afterCopy); } Bind(&afterCopy); @@ -1211,6 +1214,7 @@ GateRef NewObjectStubBuilder::EnumerateObjectProperties(GateRef glue, GateRef ob Label empty(env); Label tryGetEnumCache(env); Label cacheHit(env); + Label checkNativePointer(env); BRANCH(TaggedIsString(obj), &isString, &isNotString); Bind(&isString); { @@ -1223,7 +1227,9 @@ GateRef NewObjectStubBuilder::EnumerateObjectProperties(GateRef glue, GateRef ob Jump(&afterObjectTransform); } Bind(&afterObjectTransform); - BRANCH(TaggedIsUndefinedOrNull(*object), &empty, &tryGetEnumCache); + BRANCH(TaggedIsUndefinedOrNull(*object), &empty, &checkNativePointer); + Bind(&checkNativePointer); + BRANCH(IsNativePointer(*object), &empty, &tryGetEnumCache); Bind(&tryGetEnumCache); GateRef enumCache = TryGetEnumCache(glue, *object); BRANCH(TaggedIsUndefined(enumCache), &slowpath, &cacheHit); @@ -2088,7 +2094,8 @@ void NewObjectStubBuilder::CreateJSCollectionIterator( Bind(&noException); { StoreBuiltinHClass(glue_, result->ReadVariable(), iteratorHClass); - SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData())); + GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); + Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData())); auto emptyArray = GetGlobalConstantValue( VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray); @@ -2143,7 +2150,8 @@ void NewObjectStubBuilder::CreateJSTypedArrayIterator(Variable *result, Label *e Bind(&noException); { StoreBuiltinHClass(glue_, result->ReadVariable(), iteratorHClass); - SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData())); + GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); + Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData())); auto emptyArray = GetGlobalConstantValue( VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray); diff --git a/ecmascript/compiler/ntype_hcr_lowering.cpp b/ecmascript/compiler/ntype_hcr_lowering.cpp index 8d105221e0aa3ac333b28c9a33f49c7f464684ca..a69f079b10036c05930dee7f13e5997ec9775376 100644 --- a/ecmascript/compiler/ntype_hcr_lowering.cpp +++ b/ecmascript/compiler/ntype_hcr_lowering.cpp @@ -313,7 +313,7 @@ void NTypeHCRLowering::LowerStoreModuleVar(GateRef gate, GateRef glue) builder_.Bind(&exit); GateRef dataOffset = builder_.Int32(TaggedArray::DATA_OFFSET); GateRef indexOffset = builder_.Int32Mul(index, builder_.Int32(JSTaggedValue::TaggedTypeSize())); - GateRef offset = builder_.Int32Add(indexOffset, dataOffset); + GateRef offset = builder_.ZExtInt32ToPtr(builder_.Int32Add(indexOffset, dataOffset)); builder_.Store(VariableType::JS_ANY(), glue_, *array, offset, value); ReplaceGateWithPendingException(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); } diff --git a/ecmascript/compiler/number_speculative_retype.cpp b/ecmascript/compiler/number_speculative_retype.cpp index fb492fd01b13e939b86fc01e7e90c160c123a9ee..db6275ba80f4b5226e4f159db08c3dcb46e2b695 100644 --- a/ecmascript/compiler/number_speculative_retype.cpp +++ b/ecmascript/compiler/number_speculative_retype.cpp @@ -342,6 +342,7 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate) case OpCode::BUILTIN_PROTOTYPE_HCLASS_CHECK: case OpCode::FLATTEN_TREE_STRING_CHECK: case OpCode::ARRAY_POP: + case OpCode::ARRAY_PUSH: case OpCode::ARRAY_SOME: case OpCode::ARRAY_EVERY: case OpCode::ARRAY_FOR_EACH: @@ -357,6 +358,7 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate) case OpCode::IS_NOT_UNDEFINED_OR_HOLE_CHECK: case OpCode::ECMA_OBJECT_CHECK: case OpCode::GET_EXCEPTION: + case OpCode::MATH_HCLASS_CONSISTENCY_CHECK: return VisitOthers(gate); case OpCode::CALL: case OpCode::BYTECODE_CALL: @@ -2012,7 +2014,7 @@ TypeInfo NumberSpeculativeRetype::GetNumberInputTypeInfo(GateRef gate, bool skip } } -void NumberSpeculativeRetype::SetNewInputForMathImul(GateRef gate, int idx, Label *exit) +void NumberSpeculativeRetype::SetNewInputForMathImul(GateRef gate, int idx) { GateRef input = acc_.GetValueIn(gate, idx); auto type = GetNumberInputTypeInfo(input); @@ -2021,7 +2023,7 @@ void NumberSpeculativeRetype::SetNewInputForMathImul(GateRef gate, int idx, Labe } else { ASSERT(type == TypeInfo::FLOAT64); input = CheckAndConvertToFloat64(input, GateType::NumberType(), ConvertToNumber::BOOL_ONLY); - input = builder_.DoubleToInt(input, exit); + input = builder_.TruncDoubleToInt(acc_.GetGlueFromArgList(), input, base::INT32_BITS); } ResizeAndSetTypeInfo(input, TypeInfo::INT32); acc_.ReplaceValueIn(gate, input, idx); @@ -2036,11 +2038,8 @@ GateRef NumberSpeculativeRetype::VisitMathImul(GateRef gate) Environment env(gate, circuit_, &builder_); ASSERT(acc_.GetNumValueIn(gate) == 2U); - Label exit1(&builder_); - Label exit2(&builder_); - - SetNewInputForMathImul(gate, 0, &exit1); - SetNewInputForMathImul(gate, 1, &exit2); + SetNewInputForMathImul(gate, 0); + SetNewInputForMathImul(gate, 1); acc_.SetGateType(gate, GateType::NJSValue()); acc_.SetMachineType(gate, MachineType::I32); diff --git a/ecmascript/compiler/number_speculative_retype.h b/ecmascript/compiler/number_speculative_retype.h index a075c583366ff6b6a8ab7f1511bb58b59a033100..1480792cf432541fe306b5b2efaf9e838af9ea25 100644 --- a/ecmascript/compiler/number_speculative_retype.h +++ b/ecmascript/compiler/number_speculative_retype.h @@ -146,7 +146,7 @@ private: template TypeInfo GetNumberInputTypeInfo(GateRef gate, bool skipTagged = false); - void SetNewInputForMathImul(GateRef gate, int idx, Label *exit); + void SetNewInputForMathImul(GateRef gate, int idx); double GetDoubleValueFromConst(GateRef gate); GateRef CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support = ConvertSupport::ENABLE, diff --git a/ecmascript/compiler/pass.h b/ecmascript/compiler/pass.h index 7dc504eabf90c5c7c964fbb4e548b6eb1ec8701e..942a2711a090a174d72a53599893d6fb9925fe4a 100644 --- a/ecmascript/compiler/pass.h +++ b/ecmascript/compiler/pass.h @@ -785,7 +785,7 @@ public: bool liteCG = data->GetPassContext()->GetCompilationEnv()->GetJSOptions().IsCompilerEnableLiteCG(); GraphLinearizer(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, false, licm, liteCG) .Run(data->GetCfg()); - PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk).Run(data->GetCfg()); + PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, true).Run(data->GetCfg()); return true; } }; diff --git a/ecmascript/compiler/pgo_type/pgo_type_parser.cpp b/ecmascript/compiler/pgo_type/pgo_type_parser.cpp index d504d2f911c032521977c77c4fce68e95a6b6962..16299299f55ad593f1589e0df34bd556ddd74bad 100644 --- a/ecmascript/compiler/pgo_type/pgo_type_parser.cpp +++ b/ecmascript/compiler/pgo_type/pgo_type_parser.cpp @@ -49,7 +49,7 @@ bool ClassParser::RecordTypeInfo(const PGODefineOpType &defType, const PGOTypeLo } PGOSampleType ctorSampleType(ctorPt); - auto protoPt = defType.GetProtoTypePt(); + auto protoPt = defType.GetPrototypePt(); if (protoPt.IsNone()) { return false; } @@ -136,7 +136,7 @@ bool FunctionParser::RecordTypeInfo(const PGODefineOpType &defType, const PGOTyp } PGOSampleType ctorSampleType(ctorPt); - auto protoPt = defType.GetProtoTypePt(); + auto protoPt = defType.GetPrototypePt(); if (protoPt.IsNone()) { return false; } @@ -260,8 +260,10 @@ void PGOTypeParser::GenerateHClassForPrototype(ProfileType rootType, const PGOHC auto phc = ptManager_->QueryHClass(rootType, rootType); auto thread = ptManager_->GetJSThread(); JSHandle phclass(thread, phc); - JSHandle prototype = thread->GetEcmaVM()->GetFactory()->NewJSObjectWithInit(phclass); - ptManager_->RecordHClass(classType, classType, prototype.GetTaggedType()); + if (!phc.IsUndefined()) { + JSHandle prototype = thread->GetEcmaVM()->GetFactory()->NewJSObjectWithInit(phclass); + ptManager_->RecordHClass(classType, classType, prototype.GetTaggedType()); + } } } } // namespace panda::ecmascript diff --git a/ecmascript/compiler/pgo_type/pgo_type_recorder.h b/ecmascript/compiler/pgo_type/pgo_type_recorder.h index e59daf5f497270bb0e56cabe3c3d478f551658ae..9123e7b6d3a16a3e6f8bb790d0b979d546c0c7e1 100644 --- a/ecmascript/compiler/pgo_type/pgo_type_recorder.h +++ b/ecmascript/compiler/pgo_type/pgo_type_recorder.h @@ -35,8 +35,8 @@ public: const JSPandaFile *jsPandaFile, uint32_t methodOffset); ~PGOTypeRecorder() = default; - std::vector PUBLIC_API GetElementsKindsForUser(int32_t offset) const; std::vector PUBLIC_API GetTransitionElementsKindsForUser(int32_t offset) const; + std::vector PUBLIC_API GetElementsKindsForUser(int32_t offset) const; ElementsKind PUBLIC_API GetElementsKindForCreater(int32_t offset) const; uint32_t PUBLIC_API GetElementsLength(int32_t offset) const; RegionSpaceFlag PUBLIC_API GetRegionSpaceFlag(int32_t offset) const; diff --git a/ecmascript/compiler/profiler_stub_builder.cpp b/ecmascript/compiler/profiler_stub_builder.cpp index 685e2f2254df7194acd48309da1ccaff4a7eb029..15942680afd4bf1f2e6abe38654f3fa74e3b7028 100644 --- a/ecmascript/compiler/profiler_stub_builder.cpp +++ b/ecmascript/compiler/profiler_stub_builder.cpp @@ -17,12 +17,9 @@ #include "ecmascript/base/number_helper.h" #include "ecmascript/compiler/circuit_builder_helper.h" -#include "ecmascript/compiler/rt_call_signature.h" #include "ecmascript/compiler/share_gate_meta_data.h" #include "ecmascript/compiler/interpreter_stub-inl.h" -#include "ecmascript/compiler/stub_builder.h" #include "ecmascript/compiler/stub_builder-inl.h" -#include "ecmascript/compiler/variable_type.h" #include "ecmascript/ic/profile_type_info.h" namespace panda::ecmascript::kungfu { @@ -244,17 +241,12 @@ void ProfilerStubBuilder::ProfileCall( Label targetIsNotHot(env); Label targetIsHot(env); Label currentIsHot(env); - Label updateTargetIC(env); - BRANCH(IsEnableForceIC(glue), &updateTargetIC, &targetIsHot); - Bind(&updateTargetIC); + BRANCH(IsProfileTypeInfoHotAndValid(targetProfileInfo), &targetIsHot, &targetIsNotHot); + Bind(&targetIsNotHot); { - BRANCH(IsProfileTypeInfoHotAndValid(targetProfileInfo), &targetIsHot, &targetIsNotHot); - Bind(&targetIsNotHot); - { - CallRuntime(glue, RTSTUB_ID(UpdateHotnessCounterWithProf), { target }); - Jump(&targetIsHot); - } + CallRuntime(glue, RTSTUB_ID(UpdateHotnessCounterWithProf), { target }); + Jump(&targetIsHot); } Bind(&targetIsHot); { @@ -343,7 +335,7 @@ GateRef ProfilerStubBuilder::TryGetBuiltinFunctionId(GateRef target) Label exit(env); DEFVARIABLE(functionId, VariableType::INT32(), Int32(PGO_BUILTINS_STUB_ID(NONE))); - + BRANCH(IsJSFunction(target), &targetIsFunction, &exit); Bind(&targetIsFunction); { @@ -800,7 +792,7 @@ GateRef ProfilerStubBuilder::GetSlotID(const SlotIDInfo &slotInfo) auto result = Int16Add(hight, ZExtInt8ToInt16(low)); return ZExtInt16ToInt32(result); } else if (format == SlotIDFormat::PREF_IMM8) { - return ZExtInt8ToInt32(Load(VariableType::INT8(), pc, IntPtr(2))); + return ZExtInt8ToInt32(Load(VariableType::INT8(), pc, IntPtr(2))); // 2 : skip 1 byte of bytecode } return ZExtInt8ToInt32(Load(VariableType::INT8(), pc, IntPtr(1))); } @@ -855,13 +847,6 @@ GateRef ProfilerStubBuilder::IsProfileTypeInfoHotAndValid(GateRef profileTypeInf return ret; } -GateRef ProfilerStubBuilder::IsEnableForceIC(GateRef glue) -{ - auto env = GetEnvironment(); - GateRef offset = IntPtr(JSThread::GlueData::GetIsEnableForceICOffSet(env->Is32Bit())); - return Load(VariableType::BOOL(), glue, offset); -} - void ProfilerStubBuilder::SetDumpPeriodIndex(GateRef glue, GateRef profileTypeInfo) { GateRef periodCounterOffset = GetBitFieldOffsetFromProfileTypeInfo(profileTypeInfo); diff --git a/ecmascript/compiler/profiler_stub_builder.h b/ecmascript/compiler/profiler_stub_builder.h index c4deb4682b4fa74a883193cfd598f490ab853af0..fe90e52f90965671000d5a6ac4f2fac77c82ca48 100644 --- a/ecmascript/compiler/profiler_stub_builder.h +++ b/ecmascript/compiler/profiler_stub_builder.h @@ -139,7 +139,6 @@ private: GateRef IsProfileTypeInfoPreDumped(GateRef profileTypeInfo); GateRef IsProfileTypeInfoWithBigMethod(GateRef profileTypeInfo); GateRef IsProfileTypeInfoHotAndValid(GateRef profileTypeInfo); - GateRef IsEnableForceIC(GateRef glue); void SetDumpPeriodIndex(GateRef glue, GateRef profileTypeInfo); void SetPreDumpPeriodIndex(GateRef glue, GateRef profileTypeInfo); GateRef TaggedToTrackType(GateRef value); diff --git a/ecmascript/compiler/share_gate_meta_data.h b/ecmascript/compiler/share_gate_meta_data.h index b9a96387e2fb3ad3c9e0698906f03b4a40f38037..acba13274a3485fea764aa9e2be575bb58a0c4e6 100644 --- a/ecmascript/compiler/share_gate_meta_data.h +++ b/ecmascript/compiler/share_gate_meta_data.h @@ -690,6 +690,11 @@ public: return OnHeapModeBits::Get(bitField_); } + uint64_t UpdateOnHeapMode(OnHeapMode mode) + { + return OnHeapModeBits::Update(bitField_, mode); + } + bool IsAccessElement() const { return ModeBits::Get(bitField_) == Mode::ACCESS_ELEMENT; diff --git a/ecmascript/compiler/slowpath_lowering.cpp b/ecmascript/compiler/slowpath_lowering.cpp index c311022b4d3fc3ee0216f74881d59a0c227e2de2..cdfd5fcb47aea37eea125f1b551d36c4e94cb06e 100644 --- a/ecmascript/compiler/slowpath_lowering.cpp +++ b/ecmascript/compiler/slowpath_lowering.cpp @@ -1619,7 +1619,7 @@ void SlowPathLowering::LowerCreateObjectWithBuffer(GateRef gate) GateRef obj = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, unsharedConstPool, module, builder_.TruncInt64ToInt32(index), ConstPoolType::OBJECT_LITERAL); GateRef lexEnv = acc_.GetValueIn(gate, 1); - GateRef result = LowerCallRuntime(gate, RTSTUB_ID(CreateObjectHavingMethod), { obj, lexEnv }, true); + GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::CreateObjectHavingMethod, {glue_, obj, lexEnv}); ReplaceHirWithValue(gate, result); } @@ -1827,7 +1827,8 @@ void SlowPathLowering::LowerSuperCallSpread(GateRef gate) } builder_.Bind(&slowPath); { - result = LowerCallRuntime(gate, RTSTUB_ID(OptSuperCallSpread), { func, *newTarget, array }); + GateRef argsTaggedArray = builder_.CallStub(glue_, gate, CommonStubCSigns::GetCallSpreadArgs, {glue_, array}); + result = LowerCallRuntime(gate, RTSTUB_ID(OptSuperCallSpread), {func, *newTarget, argsTaggedArray}); builder_.Jump(&replaceGate); } builder_.Bind(&replaceGate); @@ -2744,9 +2745,9 @@ void SlowPathLowering::LowerDefineClassWithBuffer(GateRef gate) ASSERT(acc_.GetNumValueIn(gate) == 6); // 6: number of value inputs GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC); GateRef methodId = acc_.GetValueIn(gate, 0); - GateRef proto = acc_.GetValueIn(gate, 3); GateRef literalId = acc_.GetValueIn(gate, 1); GateRef length = acc_.GetValueIn(gate, 2); // 2: second arg + GateRef proto = acc_.GetValueIn(gate, 3); GateRef lexicalEnv = acc_.GetValueIn(gate, 4); // 4: Get current env GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL); GateRef module = builder_.GetModuleFromFunction(jsFunc); @@ -3357,7 +3358,7 @@ void SlowPathLowering::LowerCallInternal(GateRef gate) for (size_t i = 0; i < num; ++i) { args[i] = acc_.GetValueIn(gate, i); } - ASSERT(num >= 3); // 3: skip argc argv newtarget + ASSERT(num >= 3); // 3:skip argc argv newtarget std::vector argsFastCall(num - 3); // 3:skip argc argv newtarget size_t j = 0; for (size_t i = 0; i < num; ++i) { @@ -3383,7 +3384,7 @@ void SlowPathLowering::LowerCallNew(GateRef gate) for (size_t i = 0; i < num; ++i) { args[i] = acc_.GetValueIn(gate, i); } - ASSERT(num >= 3); // 3:skip argc argv newtarget + ASSERT(num >= 3); // 3: skip argc argv newtarget std::vector argsFastCall(num - 3); // 3:skip argc argv newtarget size_t j = 0; for (size_t i = 0; i < num; ++i) { @@ -3795,11 +3796,12 @@ void SlowPathLowering::LowerDefineSendableClass(GateRef gate) ASSERT(acc_.GetNumValueIn(gate) == 4); GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC); GateRef methodId = acc_.GetValueIn(gate, 0); + GateRef proto = acc_.GetValueIn(gate, 3); GateRef literalId = acc_.GetValueIn(gate, 1); GateRef length = acc_.GetValueIn(gate, 2); // 2: second arg - GateRef proto = acc_.GetValueIn(gate, 3); GateRef constpool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL); GateRef module = builder_.GetModuleFromFunction(jsFunc); + auto args = { proto, constpool, builder_.ToTaggedInt(methodId), builder_.ToTaggedInt(literalId), builder_.ToTaggedInt(length), module }; GateRef newGate = LowerCallRuntime(gate, RTSTUB_ID(CreateSharedClass), args); diff --git a/ecmascript/compiler/stub_builder-inl.h b/ecmascript/compiler/stub_builder-inl.h index fff398e7ac4832aa8d56473f8c417bc0447e9de0..973399a2f2b307078e96bad2269fe186a8974b3d 100644 --- a/ecmascript/compiler/stub_builder-inl.h +++ b/ecmascript/compiler/stub_builder-inl.h @@ -785,9 +785,9 @@ inline GateRef StubBuilder::TaggedIsPrototypeHandler(GateRef x) return env_->GetBuilder()->TaggedIsPrototypeHandler(x); } -inline GateRef StubBuilder::TaggedIsStoreTSHandler(GateRef x) +inline GateRef StubBuilder::TaggedIsStoreAOTHandler(GateRef x) { - return env_->GetBuilder()->TaggedIsStoreTSHandler(x); + return env_->GetBuilder()->TaggedIsStoreAOTHandler(x); } inline GateRef StubBuilder::TaggedIsTransWithProtoHandler(GateRef x) @@ -1235,18 +1235,6 @@ inline void StubBuilder::SetPropertiesArray(VariableType type, GateRef glue, Gat Store(type, glue, object, propertiesOffset, propsArray, mAttr); } -inline GateRef StubBuilder::GetHash(GateRef object) -{ - GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); - return Load(VariableType::JS_ANY(), object, hashOffset); -} - -inline void StubBuilder::SetHash(GateRef glue, GateRef object, GateRef hash) -{ - GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); - Store(VariableType::INT64(), glue, object, hashOffset, hash, MemoryAttribute::NoBarrier()); -} - inline GateRef StubBuilder::GetLengthOfTaggedArray(GateRef array) { return Load(VariableType::INT32(), array, IntPtr(TaggedArray::LENGTH_OFFSET)); @@ -1257,11 +1245,17 @@ inline GateRef StubBuilder::GetLengthOfJSTypedArray(GateRef array) return Load(VariableType::INT32(), array, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET)); } -inline GateRef StubBuilder::GetExtractLengthOfTaggedArray(GateRef array) +inline GateRef StubBuilder::GetExtraLengthOfTaggedArray(GateRef array) { return Load(VariableType::INT32(), array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET)); } +inline void StubBuilder::SetExtraLengthOfTaggedArray(GateRef glue, GateRef array, GateRef len) +{ + return Store(VariableType::INT32(), glue, array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), + len, MemoryAttribute::NoBarrier()); +} + inline GateRef StubBuilder::IsJSHClass(GateRef obj) { ASM_ASSERT(GET_MESSAGE_STRING_ID(IsJSHClass), TaggedIsHeapObject(obj)); @@ -1319,6 +1313,11 @@ inline GateRef StubBuilder::IsDictionaryElement(GateRef hClass) return env_->GetBuilder()->IsDictionaryElement(hClass); } +inline GateRef StubBuilder::IsJSArrayPrototypeModified(GateRef hClass) +{ + return env_->GetBuilder()->IsJSArrayPrototypeModified(hClass); +} + inline GateRef StubBuilder::IsClassConstructorFromBitField(GateRef bitfield) { // decode @@ -1495,6 +1494,12 @@ inline GateRef StubBuilder::IsNativeModuleFailureInfo(GateRef obj) return Int32Equal(objectType, Int32(static_cast(JSType::NATIVE_MODULE_FAILURE_INFO))); } +inline GateRef StubBuilder::IsNativePointer(GateRef obj) +{ + GateRef objectType = GetObjectType(LoadHClass(obj)); + return Int32Equal(objectType, Int32(static_cast(JSType::JS_NATIVE_POINTER))); +} + inline GateRef StubBuilder::IsModuleNamespace(GateRef obj) { GateRef objectType = GetObjectType(LoadHClass(obj)); @@ -1735,15 +1740,15 @@ inline GateRef StubBuilder::GetPrototypeHandlerHandlerInfo(GateRef object) return Load(VariableType::JS_ANY(), object, handlerInfoOffset); } -inline GateRef StubBuilder::GetStoreTSHandlerHolder(GateRef object) +inline GateRef StubBuilder::GetStoreAOTHandlerHolder(GateRef object) { - GateRef holderOffset = IntPtr(StoreTSHandler::HOLDER_OFFSET); + GateRef holderOffset = IntPtr(StoreAOTHandler::HOLDER_OFFSET); return Load(VariableType::JS_ANY(), object, holderOffset); } -inline GateRef StubBuilder::GetStoreTSHandlerHandlerInfo(GateRef object) +inline GateRef StubBuilder::GetStoreAOTHandlerHandlerInfo(GateRef object) { - GateRef handlerInfoOffset = IntPtr(StoreTSHandler::HANDLER_INFO_OFFSET); + GateRef handlerInfoOffset = IntPtr(StoreAOTHandler::HANDLER_INFO_OFFSET); return Load(VariableType::JS_ANY(), object, handlerInfoOffset); } @@ -2161,7 +2166,7 @@ inline void StubBuilder::SetParentToHClass(VariableType type, GateRef glue, Gate Store(type, glue, hClass, offset, parent); } -inline void StubBuilder::SetIsProtoTypeToHClass(GateRef glue, GateRef hClass, GateRef value) +inline void StubBuilder::SetIsPrototypeToHClass(GateRef glue, GateRef hClass, GateRef value) { GateRef oldValue = ZExtInt1ToInt32(value); GateRef bitfield = GetBitFieldFromHClass(hClass); @@ -2173,19 +2178,19 @@ inline void StubBuilder::SetIsProtoTypeToHClass(GateRef glue, GateRef hClass, Ga SetBitFieldToHClass(glue, hClass, newVal); } -inline void StubBuilder::SetIsTS(GateRef glue, GateRef hClass, GateRef value) +inline void StubBuilder::SetIsAOT(GateRef glue, GateRef hClass, GateRef value) { GateRef oldValue = ZExtInt1ToInt32(value); GateRef bitfield = GetBitFieldFromHClass(hClass); GateRef mask = Int32LSL( - Int32((1LU << JSHClass::IsTSBit::SIZE) - 1), - Int32(JSHClass::IsTSBit::START_BIT)); + Int32((1LU << JSHClass::IsAOTBit::SIZE) - 1), + Int32(JSHClass::IsAOTBit::START_BIT)); GateRef newVal = Int32Or(Int32And(bitfield, Int32Not(mask)), - Int32LSL(oldValue, Int32(JSHClass::IsTSBit::START_BIT))); + Int32LSL(oldValue, Int32(JSHClass::IsAOTBit::START_BIT))); SetBitFieldToHClass(glue, hClass, newVal); } -inline GateRef StubBuilder::IsProtoTypeHClass(GateRef hClass) +inline GateRef StubBuilder::IsPrototypeHClass(GateRef hClass) { GateRef bitfield = GetBitFieldFromHClass(hClass); return TruncInt32ToInt1(Int32And(Int32LSR(bitfield, @@ -2246,12 +2251,12 @@ inline GateRef StubBuilder::HasDeleteProperty(GateRef hClass) return env_->GetBuilder()->HasDeleteProperty(hClass); } -inline GateRef StubBuilder::IsTSHClass(GateRef hClass) +inline GateRef StubBuilder::IsAOTHClass(GateRef hClass) { GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD_OFFSET)); return Int32NotEqual(Int32And(Int32LSR(bitfield, - Int32(JSHClass::IsTSBit::START_BIT)), - Int32((1LU << JSHClass::IsTSBit::SIZE) - 1)), + Int32(JSHClass::IsAOTBit::START_BIT)), + Int32((1LU << JSHClass::IsAOTBit::SIZE) - 1)), Int32(0)); } @@ -3874,13 +3879,6 @@ inline void StubBuilder::SetArrayBufferByteLength(GateRef glue, GateRef buffer, Store(VariableType::INT32(), glue, buffer, offset, length); } -inline GateRef StubBuilder::GetLastLeaveFrame(GateRef glue) -{ - bool isArch32 = GetEnvironment()->Is32Bit(); - GateRef spOffset = IntPtr(JSThread::GlueData::GetLeaveFrameOffset(isArch32)); - return Load(VariableType::NATIVE_POINTER(), glue, spOffset); -} - inline GateRef StubBuilder::GetPropertiesCache(GateRef glue) { GateRef currentContextOffset = IntPtr(JSThread::GlueData::GetCurrentContextOffset(env_->Is32Bit())); @@ -3922,6 +3920,12 @@ inline GateRef StubBuilder::HashFromHclassAndKey(GateRef glue, GateRef cls, Gate GateRef keyHash = GetKeyHashCode(glue, key, hir); return Int32And(Int32Xor(clsHash, keyHash), Int32(PropertiesCache::CACHE_LENGTH_MASK)); } +inline GateRef StubBuilder::GetLastLeaveFrame(GateRef glue) +{ + bool isArch32 = GetEnvironment()->Is32Bit(); + GateRef spOffset = IntPtr(JSThread::GlueData::GetLeaveFrameOffset(isArch32)); + return Load(VariableType::NATIVE_POINTER(), glue, spOffset); +} inline GateRef StubBuilder::OrdinaryNewJSObjectCreate(GateRef glue, GateRef proto) { diff --git a/ecmascript/compiler/stub_builder.cpp b/ecmascript/compiler/stub_builder.cpp index 094467a916ca8228a5628be3fd38a5499f294a8a..44f6243ff3952644bfed62044f914021160fb8f6 100644 --- a/ecmascript/compiler/stub_builder.cpp +++ b/ecmascript/compiler/stub_builder.cpp @@ -27,6 +27,7 @@ #include "ecmascript/compiler/new_object_stub_builder.h" #include "ecmascript/compiler/profiler_stub_builder.h" #include "ecmascript/compiler/rt_call_signature.h" +#include "ecmascript/elements.h" #include "ecmascript/global_env_constants.h" #include "ecmascript/ic/properties_cache.h" #include "ecmascript/js_api/js_api_arraylist.h" @@ -407,7 +408,7 @@ GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key, env->SubCfgEntry(&subentry); DEFVARIABLE(low, VariableType::INT32(), Int32(0)); Label exit(env); - GateRef elements = GetExtractLengthOfTaggedArray(layoutInfo); + GateRef elements = GetExtraLengthOfTaggedArray(layoutInfo); DEFVARIABLE(high, VariableType::INT32(), Int32Sub(elements, Int32(1))); DEFVARIABLE(result, VariableType::INT32(), Int32(-1)); DEFVARIABLE(mid, VariableType::INT32(), Int32(-1)); @@ -1111,7 +1112,26 @@ GateRef StubBuilder::ComputeNonInlinedFastPropsCapacity(GateRef glue, GateRef ol env->SubCfgExit(); return ret; } - +#if ENABLE_NEXT_OPTIMIZATION +GateRef StubBuilder::ComputeElementCapacity(GateRef oldLength) +{ + auto env = GetEnvironment(); + Label subEntry(env); + env->SubCfgEntry(&subEntry); + Label exit(env); + DEFVARIABLE(result, VariableType::INT32(), Int32(0)); + GateRef newL = Int32Add(oldLength, Int32LSR(oldLength, Int32(1))); + // Handle small array edge cases: for small arrays, 1.5 times expansion may not provide sufficient growth, + // so adding a fixed value (like 16) avoids frequent capacity expansion in the short term. + newL = Int32Add(newL, Int32(16)); + result = newL; + Jump(&exit); + Bind(&exit); + auto ret = *result; + env->SubCfgExit(); + return ret; +} +#else GateRef StubBuilder::ComputeElementCapacity(GateRef oldLength) { auto env = GetEnvironment(); @@ -1136,7 +1156,7 @@ GateRef StubBuilder::ComputeElementCapacity(GateRef oldLength) env->SubCfgExit(); return ret; } - +#endif GateRef StubBuilder::CallGetterHelper( GateRef glue, GateRef receiver, GateRef holder, GateRef accessor, ProfileOperation callback, GateRef hir) { @@ -1331,10 +1351,10 @@ void StubBuilder::JSHClassAddProperty(GateRef glue, GateRef receiver, GateRef ke BRANCH(Equal(newClass, Undefined()), ¬FindHClass, &findHClass); Bind(&findHClass); { - GateRef isTSHClass = IsTSHClass(newClass); + GateRef isAOTHClass = IsAOTHClass(newClass); Label setPrototype(env); Label endSetPrototypeCheck(env); - Branch(isTSHClass, &setPrototype, &endSetPrototypeCheck); + Branch(isAOTHClass, &setPrototype, &endSetPrototypeCheck); Bind(&setPrototype); { GateRef prototype = GetPrototypeFromHClass(hclass); @@ -1349,7 +1369,7 @@ void StubBuilder::JSHClassAddProperty(GateRef glue, GateRef receiver, GateRef ke Label needUpdateAOTHClass(env); Label normalNotify(env); Label endUpdate(env); - GateRef updateCondition = LogicAndBuilder(env).And(isTSHClass).And(IsProtoTypeHClass(newClass)).Done(); + GateRef updateCondition = LogicAndBuilder(env).And(isAOTHClass).And(IsPrototypeHClass(newClass)).Done(); Branch(updateCondition, &needUpdateAOTHClass, &normalNotify); Bind(&needUpdateAOTHClass); { @@ -2878,8 +2898,8 @@ GateRef StubBuilder::StoreICWithHandler(GateRef glue, GateRef receiver, GateRef Label handlerNotPrototypeHandler(env); Label handlerIsPropertyBox(env); Label handlerNotPropertyBox(env); - Label handlerIsStoreTSHandler(env); - Label handlerNotStoreTSHandler(env); + Label handlerIsStoreAOTHandler(env); + Label handlerNotStoreAOTHandler(env); Label aotHandlerInfoIsField(env); Label aotHandlerInfoNotField(env); Label cellHasChanged(env); @@ -2983,15 +3003,15 @@ GateRef StubBuilder::StoreICWithHandler(GateRef glue, GateRef receiver, GateRef } Bind(&handlerNotPropertyBox); { - BRANCH(TaggedIsStoreTSHandler(*handler), &handlerIsStoreTSHandler, &handlerNotStoreTSHandler); - Bind(&handlerIsStoreTSHandler); + BRANCH(TaggedIsStoreAOTHandler(*handler), &handlerIsStoreAOTHandler, &handlerNotStoreAOTHandler); + Bind(&handlerIsStoreAOTHandler); { GateRef cellValue = GetProtoCell(*handler); BRANCH(GetHasChanged(cellValue), &cellHasChanged, &aotCellNotChanged); Bind(&aotCellNotChanged); { - holder = GetStoreTSHandlerHolder(*handler); - handler = GetStoreTSHandlerHandlerInfo(*handler); + holder = GetStoreAOTHandlerHolder(*handler); + handler = GetStoreAOTHandlerHandlerInfo(*handler); GateRef handlerInfo = GetInt64OfTInt(*handler); BRANCH(IsField(handlerInfo), &aotHandlerInfoIsField, &aotHandlerInfoNotField); Bind(&aotHandlerInfoIsField); @@ -3007,7 +3027,7 @@ GateRef StubBuilder::StoreICWithHandler(GateRef glue, GateRef receiver, GateRef } } } - Bind(&handlerNotStoreTSHandler); + Bind(&handlerNotStoreAOTHandler); Jump(&exit); } Bind(&cellHasChanged); @@ -3701,8 +3721,8 @@ void StubBuilder::CopyAllHClass(GateRef glue, GateRef dstHClass, GateRef srcHCla { auto env = GetEnvironment(); Label entry(env); - Label isTS(env); - Label isNotTS(env); + Label isAOT(env); + Label isNotAOT(env); env->SubCfgEntry(&entry); auto proto = GetPrototypeFromHClass(srcHClass); SetPrototypeToHClass(VariableType::JS_POINTER(), glue, dstHClass, proto); @@ -3718,13 +3738,13 @@ void StubBuilder::CopyAllHClass(GateRef glue, GateRef dstHClass, GateRef srcHCla dstHClass, GetLayoutFromHClass(srcHClass), MemoryAttribute::NeedBarrierAndAtomic()); - BRANCH(IsTSHClass(srcHClass), &isTS, &isNotTS); - Bind(&isTS); + BRANCH(IsAOTHClass(srcHClass), &isAOT, &isNotAOT); + Bind(&isAOT); { - SetIsTS(glue, dstHClass, False()); - Jump(&isNotTS); + SetIsAOT(glue, dstHClass, False()); + Jump(&isNotAOT); } - Bind(&isNotTS); + Bind(&isNotAOT); env->SubCfgExit(); return; } @@ -3849,7 +3869,7 @@ GateRef StubBuilder::AddElementInternal(GateRef glue, GateRef receiver, GateRef } Bind(¬Array); { - NotifyStableArrayElementsGuardians(glue, receiver); + NotifyArrayPrototypeChangedGuardians(glue, receiver); GateRef hclass = LoadHClass(receiver); GateRef elements = GetElementsArray(receiver); Label isDicMode(env); @@ -3946,7 +3966,7 @@ GateRef StubBuilder::ShouldTransToDict(GateRef capacity, GateRef index) Label isLessThanMax(env); Label notLessThanMax(env); BRANCH(Int32LessThanOrEqual(Int32Sub(index, capacity), - Int32(JSObject::MAX_GAP)), &isLessThanMax, ¬LessThanMax); + Int32(JSObject::MAX_GAP)), &isLessThanMax, ¬LessThanMax); Bind(&isLessThanMax); { Label isLessThanInt32Max(env); @@ -3991,35 +4011,35 @@ GateRef StubBuilder::ShouldTransToDict(GateRef capacity, GateRef index) return ret; } -void StubBuilder::NotifyStableArrayElementsGuardians(GateRef glue, GateRef receiver) +void StubBuilder::NotifyArrayPrototypeChangedGuardians(GateRef glue, GateRef receiver) { auto env = GetEnvironment(); Label subEntry(env); env->SubCfgEntry(&subEntry); Label exit(env); GateRef guardiansOffset = - IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit())); + IntPtr(JSThread::GlueData::GetArrayElementsGuardiansOffset(env->Is32Bit())); GateRef guardians = Load(VariableType::BOOL(), glue, guardiansOffset); Label isGuardians(env); BRANCH(Equal(guardians, True()), &isGuardians, &exit); Bind(&isGuardians); { GateRef hclass = LoadHClass(receiver); - Label isProtoType(env); - BRANCH(BitOr(IsProtoTypeHClass(hclass), IsJsArray(receiver)), &isProtoType, &exit); - Bind(&isProtoType); + Label isPrototype(env); + BRANCH(BitOr(IsPrototypeHClass(hclass), IsJsArray(receiver)), &isPrototype, &exit); + Bind(&isPrototype); { - Label isEnvProtoType(env); + Label isEnvPrototype(env); GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); - GateRef isEnvProtoTypeCheck = LogicOrBuilder(env) + GateRef isEnvPrototypeCheck = LogicOrBuilder(env) .Or(Equal(GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::OBJECT_FUNCTION_PROTOTYPE_INDEX), receiver)) .Or(Equal(GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_PROTOTYPE_INDEX), receiver)) .Done(); - BRANCH(isEnvProtoTypeCheck, &isEnvProtoType, &exit); - Bind(&isEnvProtoType); + BRANCH(isEnvPrototypeCheck, &isEnvPrototype, &exit); + Bind(&isEnvPrototype); Store(VariableType::BOOL(), glue, glue, guardiansOffset, False()); Jump(&exit); } @@ -4064,9 +4084,7 @@ GateRef StubBuilder::IsArrayLengthWritable(GateRef glue, GateRef receiver) } Bind(¬DicMode); { - GateRef layoutInfo = GetLayoutFromHClass(hclass); - GateRef attr = GetPropAttrFromLayoutInfo(layoutInfo, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX)); - result = IsWritable(attr); + result = IsArrayLengthWritableForNonDictMode(receiver); Jump(&exit); } Bind(&exit); @@ -4075,16 +4093,32 @@ GateRef StubBuilder::IsArrayLengthWritable(GateRef glue, GateRef receiver) return ret; } +GateRef StubBuilder::IsArrayLengthWritableForNonDictMode(GateRef receiver) +{ + auto env = GetEnvironment(); + Label subEntry(env); + env->SubCfgEntry(&subEntry); + Label exit(env); + DEFVARIABLE(result, VariableType::BOOL(), False()); + GateRef hclass = LoadHClass(receiver); + GateRef layoutInfo = GetLayoutFromHClass(hclass); + GateRef attr = GetPropAttrFromLayoutInfo(layoutInfo, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX)); + result = IsWritable(attr); + auto ret = *result; + env->SubCfgExit(); + return ret; +} + GateRef StubBuilder::CheckHClassForRep(GateRef hclass, GateRef value) { auto env = GetEnvironment(); Label subEntry(env); env->SubCfgEntry(&subEntry); Label exit(env); - Label isTSHClass(env); + Label isAOTHClass(env); DEFVARIABLE(result, VariableType::BOOL(), Boolean(true)); - Branch(IsTSHClass(hclass), &isTSHClass, &exit); - Bind(&isTSHClass); + Branch(IsAOTHClass(hclass), &isAOTHClass, &exit); + Bind(&isAOTHClass); { GateRef propNums = GetNumberOfPropsFromHClass(hclass); GateRef last = Int32Sub(propNums, Int32(1)); @@ -4710,14 +4744,14 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k } Bind(&writable); { - Label isTS(env); - Label notTS(env); - BRANCH(IsTSHClass(hclass), &isTS, ¬TS); - Bind(&isTS); + Label isAOT(env); + Label notAOT(env); + BRANCH(IsAOTHClass(hclass), &isAOT, ¬AOT); + Bind(&isAOT); { GateRef attrVal = JSObjectGetProperty(*holder, hclass, attr); Label attrValIsHole(env); - BRANCH(TaggedIsHole(attrVal), &attrValIsHole, ¬TS); + BRANCH(TaggedIsHole(attrVal), &attrValIsHole, ¬AOT); Bind(&attrValIsHole); { Label storeReceiverHoleEntry(env); @@ -4739,7 +4773,7 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k } } } - Bind(¬TS); + Bind(¬AOT); Label holdEqualsRecv(env); if (useOwn || defineSemantics) { BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd); @@ -4990,14 +5024,14 @@ GateRef StubBuilder::DefinePropertyByName(GateRef glue, GateRef receiver, GateRe Jump(&exit); Bind(&writable); { - Label isTS(env); - Label notTS(env); - BRANCH(IsTSHClass(hclass), &isTS, ¬TS); - Bind(&isTS); + Label isAOT(env); + Label notAOT(env); + BRANCH(IsAOTHClass(hclass), &isAOT, ¬AOT); + Bind(&isAOT); { GateRef attrVal = JSObjectGetProperty(*holder, hclass, attr); Label attrValIsHole(env); - BRANCH(TaggedIsHole(attrVal), &attrValIsHole, ¬TS); + BRANCH(TaggedIsHole(attrVal), &attrValIsHole, ¬AOT); Bind(&attrValIsHole); { Label storeReceiverHoleEntry(env); @@ -5013,7 +5047,7 @@ GateRef StubBuilder::DefinePropertyByName(GateRef glue, GateRef receiver, GateRe } } } - Bind(¬TS); + Bind(¬AOT); Label holdEqualsRecv(env); BRANCH(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd); Bind(&holdEqualsRecv); @@ -5347,15 +5381,15 @@ void StubBuilder::NotifyHClassChanged(GateRef glue, GateRef oldHClass, GateRef n Label entry(env); env->SubCfgEntry(&entry); Label exit(env); - Label isProtoType(env); - BRANCH(IsProtoTypeHClass(oldHClass), &isProtoType, &exit); - Bind(&isProtoType); + Label isPrototype(env); + BRANCH(IsPrototypeHClass(oldHClass), &isPrototype, &exit); + Bind(&isPrototype); { Label notEqualHClass(env); BRANCH(Equal(oldHClass, newHClass), &exit, ¬EqualHClass); Bind(¬EqualHClass); { - SetIsProtoTypeToHClass(glue, newHClass, True()); + SetIsPrototypeToHClass(glue, newHClass, True()); CallRuntime(glue, RTSTUB_ID(NoticeThroughChainAndRefreshUser), { oldHClass, newHClass }); Jump(&exit); } @@ -5826,7 +5860,7 @@ void StubBuilder::FastSetPropertyByName(GateRef glue, GateRef obj, GateRef key, } Bind(&slowPath); { - result = CallRuntime(glue, RTSTUB_ID(StoreICByValue), { obj, *keyVar, value, IntToTaggedInt(Int32(0)) }); + result = CallRuntime(glue, RTSTUB_ID(StObjByValue), { obj, *keyVar, value }); Jump(&exit); } Bind(&exit); @@ -6693,6 +6727,41 @@ GateRef StubBuilder::FastEqual(GateRef glue, GateRef left, GateRef right, Profil } Bind(&rightIsNotUndefinedOrNull); { + Label bothString(env); + Label eitherNotString(env); + Label isHeapObject(env); + Label notHeapObject(env); + BRANCH(BitAnd(TaggedIsHeapObject(left), TaggedIsHeapObject(right)), &isHeapObject, ¬HeapObject); + Bind(&isHeapObject); + { + Label typeEqual(env); + GateRef leftType = GetObjectType(LoadHClass(left)); + GateRef rightType = GetObjectType(LoadHClass(right)); + BRANCH(Equal(leftType, rightType), &typeEqual, ¬HeapObject); + Bind(&typeEqual); + { + Label eitherNotString1(env); + Label bothBigInt(env); + Label eitherNotBigInt(env); + BRANCH(BothAreString(left, right), &bothString, &eitherNotString1); + Bind(&eitherNotString1); + BRANCH(BitAnd(TaggedIsBigInt(left),TaggedIsBigInt(right)), &bothBigInt, &eitherNotBigInt); + Bind(&bothBigInt); + { + callback.ProfileOpType(TaggedInt(PGOSampleType::BigIntType())); + result =BooleanToTaggedBooleanPtr(CallNGCRuntime(glue, + RTSTUB_ID(BigIntEquals), {left, right})); + Jump(&exit); + } + Bind(&eitherNotBigInt); + { + callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); + result = TaggedFalse(); + Jump(&exit); + } + } + } + Bind(¬HeapObject); Label leftIsUndefinedOrNull(env); Label leftIsNotUndefinedOrNull(env); BRANCH(TaggedIsUndefinedOrNull(right), &leftIsUndefinedOrNull, &leftIsNotUndefinedOrNull); @@ -6724,26 +6793,24 @@ GateRef StubBuilder::FastEqual(GateRef glue, GateRef left, GateRef right, Profil } Bind(&leftNotBoolOrRightNotSpecial); { - Label bothString(env); - Label eitherNotString(env); BRANCH(BothAreString(left, right), &bothString, &eitherNotString); - Bind(&bothString); - { - callback.ProfileOpType(TaggedInt(PGOSampleType::StringType())); - Label stringEqual(env); - Label stringNotEqual(env); - BRANCH(FastStringEqual(glue, left, right), &stringEqual, &stringNotEqual); - Bind(&stringEqual); - result = TaggedTrue(); - Jump(&exit); - Bind(&stringNotEqual); - result = TaggedFalse(); - Jump(&exit); - } - Bind(&eitherNotString); - callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); + } + Bind(&bothString); + { + callback.ProfileOpType(TaggedInt(PGOSampleType::StringType())); + Label stringEqual(env); + Label stringNotEqual(env); + BRANCH(FastStringEqual(glue, left, right), &stringEqual, &stringNotEqual); + Bind(&stringEqual); + result = TaggedTrue(); + Jump(&exit); + Bind(&stringNotEqual); + result = TaggedFalse(); Jump(&exit); } + Bind(&eitherNotString); + callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); + Jump(&exit); } } } @@ -8429,12 +8496,100 @@ void StubBuilder::CalcHashcodeForDouble(GateRef x, Variable *res, Label *exit) Jump(exit); } +GateRef StubBuilder::GetHash(GateRef object) +{ + auto env = GetEnvironment(); + Label subentry(env); + Label isHeapObject(env); + Label exit(env); + env->SubCfgEntry(&subentry); + GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); + GateRef value = Load(VariableType::JS_ANY(), object, hashOffset); + DEFVARIABLE(res, VariableType::INT32(), GetInt32OfTInt(value)); + BRANCH(TaggedIsHeapObject(value), &isHeapObject, &exit); + + Bind(&isHeapObject); + { + Label isTaggedArray(env); + Label notTaggedArray(env); + BRANCH(IsTaggedArray(value), &isTaggedArray, ¬TaggedArray); + Bind(&isTaggedArray); + GateRef extlen = GetExtraLengthOfTaggedArray(value); + GateRef index = Int32Add(Int32(ECMAObject::HASH_INDEX), extlen); + res = GetInt32OfTInt(GetValueFromTaggedArray(value, index)); + Jump(&exit); + Bind(¬TaggedArray); + res = Int32(0); + Jump(&exit); + } + Bind(&exit); + auto ret = *res; + env->SubCfgExit(); + return ret; +} + +void StubBuilder::SetHash(GateRef glue, GateRef object, GateRef hash) +{ + auto env = GetEnvironment(); + Label subentry(env); + Label isHeapObject(env); + Label notHeapObject(env); + Label exit(env); + env->SubCfgEntry(&subentry); + GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); + GateRef value = Load(VariableType::JS_ANY(), object, hashOffset); + DEFVARIABLE(res, VariableType::JS_ANY(), object); + BRANCH(TaggedIsHeapObject(value), &isHeapObject, ¬HeapObject); + + Bind(&isHeapObject); + { + Label isTaggedArray(env); + Label notTaggedArray(env); + BRANCH(IsTaggedArray(value), &isTaggedArray, ¬TaggedArray); + Bind(&isTaggedArray); + { + GateRef extlen = GetExtraLengthOfTaggedArray(value); + GateRef index = Int32Add(Int32(ECMAObject::HASH_INDEX), extlen); + SetValueToTaggedArray(VariableType::JS_ANY(), glue, value, index, IntToTaggedInt(hash)); + Jump(&exit); + } + Bind(¬TaggedArray); + { + Label isNativePointer(env); + Label notNativePointer(env); + BRANCH(IsNativePointer(value), &isNativePointer, ¬NativePointer); + Bind(&isNativePointer); + { + NewObjectStubBuilder newBuilder(this); + GateRef array = newBuilder.NewTaggedArray(glue, Int32(ECMAObject::RESOLVED_MAX_SIZE)); + SetExtraLengthOfTaggedArray(glue, array, Int32(0)); + SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, + Int32(ECMAObject::HASH_INDEX), IntToTaggedInt(hash)); + SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, + Int32(ECMAObject::FUNCTION_EXTRA_INDEX), value); + Store(VariableType::JS_ANY(), glue, object, hashOffset, array); + Jump(&exit); + } + Bind(¬NativePointer); + FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) }); + Jump(&exit); + } + } + Bind(¬HeapObject); + { + Store(VariableType::JS_ANY(), glue, object, hashOffset, IntToTaggedInt(hash), MemoryAttribute::NoBarrier()); + Jump(&exit); + } + Bind(&exit); + env->SubCfgExit(); +} + void StubBuilder::CalcHashcodeForObject(GateRef glue, GateRef value, Variable *res, Label *exit) { auto env = GetEnvironment(); GateRef hash = GetHash(value); - *res = TruncInt64ToInt32(TaggedCastToIntPtr(hash)); + *res = hash; Label calcHash(env); BRANCH(Int32Equal(**res, Int32(0)), &calcHash, exit); Bind(&calcHash); @@ -8448,7 +8603,7 @@ void StubBuilder::CalcHashcodeForObject(GateRef glue, GateRef value, Variable *r GateRef k4 = Int64Mul(k3, Int64(base::GET_MULTIPLY)); GateRef k5 = Int64LSR(k4, Int64(base::INT64_BITS - base::INT32_BITS)); GateRef k6 = Int32And(TruncInt64ToInt32(k5), Int32(INT32_MAX)); - SetHash(glue, value, IntToTaggedPtr(k6)); + SetHash(glue, value, k6); *res = k6; Jump(exit); } @@ -9087,7 +9242,7 @@ GateRef StubBuilder::HasStableElements(GateRef glue, GateRef obj) Bind(&targetIsStableElements); { GateRef guardiansOffset = - IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit())); + IntPtr(JSThread::GlueData::GetArrayElementsGuardiansOffset(env->Is32Bit())); result = Load(VariableType::BOOL(), glue, guardiansOffset); Jump(&exit); } @@ -9116,7 +9271,7 @@ GateRef StubBuilder::IsStableJSArguments(GateRef glue, GateRef obj) Bind(&targetIsStableArguments); { GateRef guardiansOffset = - IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit())); + IntPtr(JSThread::GlueData::GetArrayElementsGuardiansOffset(env->Is32Bit())); result = Load(VariableType::BOOL(), glue, guardiansOffset); Jump(&exit); } @@ -9136,19 +9291,23 @@ GateRef StubBuilder::IsStableJSArray(GateRef glue, GateRef obj) Label exit(env); Label targetIsHeapObject(env); Label targetIsStableArray(env); - BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit); Bind(&targetIsHeapObject); { - GateRef jsHclass = LoadHClass(obj); - BRANCH(IsStableArray(jsHclass), &targetIsStableArray, &exit); + GateRef jsHClass = LoadHClass(obj); + BRANCH(IsStableArray(jsHClass), &targetIsStableArray, &exit); Bind(&targetIsStableArray); { - GateRef guardiansOffset = - IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit())); - GateRef guardians = Load(VariableType::BOOL(), glue, guardiansOffset); - result.WriteVariable(guardians); - Jump(&exit); + Label isPrototypeNotModified(env); + BRANCH(IsJSArrayPrototypeModified(jsHClass), &exit, &isPrototypeNotModified); + Bind(&isPrototypeNotModified); + { + GateRef guardiansOffset = + IntPtr(JSThread::GlueData::GetArrayElementsGuardiansOffset(env->Is32Bit())); + GateRef guardians = Load(VariableType::BOOL(), glue, guardiansOffset); + result.WriteVariable(guardians); + Jump(&exit); + } } } Bind(&exit); @@ -9684,13 +9843,16 @@ GateRef StubBuilder::SetValueWithElementsKind(GateRef glue, GateRef receiver, Ga return ret; } -void StubBuilder::FastSetValueWithElementsKind(GateRef glue, GateRef elements, GateRef rawValue, - GateRef index, ElementsKind kind) +void StubBuilder::FastSetValueWithElementsKind(GateRef glue, GateRef receiver, GateRef elements, GateRef rawValue, + GateRef index, ElementsKind kind, bool needTransition) { auto env = GetEnvironment(); Label entryPass(env); env->SubCfgEntry(&entryPass); Label exit(env); + if (needTransition) { + TransitToElementsKind(glue, receiver, rawValue, Int32(static_cast(ElementsKind::NONE))); + } if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) { SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, rawValue); Jump(&exit); @@ -10418,8 +10580,8 @@ GateRef StubBuilder::GetArgumentsElements(GateRef glue, GateRef argvTaggedArray, using CopyKind = StubBuilder::OverlapKind; template <> -void StubBuilder::ArrayCopy(GateRef glue, GateRef src, GateRef dst, GateRef length, - MemoryAttribute mAttr) +void StubBuilder::ArrayCopy(GateRef glue, GateRef srcAddr, GateRef dstObj, GateRef dstAddr, + GateRef length, MemoryAttribute mAttr) { auto env = GetEnvironment(); Label entry(env); @@ -10432,7 +10594,7 @@ void StubBuilder::ArrayCopy(GateRef glue, GateRef src, Gat Label storeHead(env); Label enterLoop(env); DEFVARIABLE(offset, VariableType::INT32(), Int32(0)); - + GateRef dstOff = PtrSub(TaggedCastToIntPtr(dstAddr), TaggedCastToIntPtr(dstObj)); const auto tSize = static_cast(JSTaggedValue::TaggedTypeSize()); static_assert((tSize & (tSize - 1)) == 0 && "TaggedTypeSize must be power of 2"); static_assert(LOOP_UNROLL_FACTOR == 2 && "changing LOOP_UNROLL_FACTOR also need fix the logic here"); @@ -10443,8 +10605,8 @@ void StubBuilder::ArrayCopy(GateRef glue, GateRef src, Gat { // Now use 2 as loop unroll factor, so only store once if reminder is not 0. // But if using other loop unroll factor, the store head should also be refactored. - GateRef value = Load(VariableType::JS_ANY(), src); - Store(VariableType::JS_ANY(), glue, dst, IntPtr(0), value, mAttr); + GateRef value = Load(VariableType::JS_ANY(), srcAddr); + Store(VariableType::JS_ANY(), glue, dstObj, dstOff, value, mAttr); offset = Int32(tSize); Jump(&enterLoop); } @@ -10459,10 +10621,10 @@ void StubBuilder::ArrayCopy(GateRef glue, GateRef src, Gat { GateRef off1 = ZExtInt32ToPtr(*offset); GateRef off2 = PtrAdd(off1, IntPtr(tSize)); - GateRef value1 = Load(VariableType::JS_ANY(), src, off1); - GateRef value2 = Load(VariableType::JS_ANY(), src, off2); - Store(VariableType::JS_ANY(), glue, dst, off1, value1, mAttr); - Store(VariableType::JS_ANY(), glue, dst, off2, value2, mAttr); + GateRef value1 = Load(VariableType::JS_ANY(), srcAddr, off1); + GateRef value2 = Load(VariableType::JS_ANY(), srcAddr, off2); + Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff, off1), value1, mAttr); + Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff, off2), value2, mAttr); offset = Int32Add(*offset, Int32(LOOP_UNROLL_FACTOR * tSize)); Jump(&endLoop); } @@ -10474,8 +10636,8 @@ void StubBuilder::ArrayCopy(GateRef glue, GateRef src, Gat } template <> -void StubBuilder::ArrayCopy(GateRef glue, GateRef src, GateRef dst, GateRef length, - MemoryAttribute mAttr) +void StubBuilder::ArrayCopy(GateRef glue, GateRef srcAddr, GateRef dstObj, GateRef dstAddr, + GateRef length, MemoryAttribute mAttr) { auto env = GetEnvironment(); Label entry(env); @@ -10490,7 +10652,7 @@ void StubBuilder::ArrayCopy(GateRef glue, GateRef src, Ga const auto tSize = static_cast(JSTaggedValue::TaggedTypeSize()); static_assert((tSize & (tSize - 1)) == 0 && "TaggedTypeSize must be power of 2"); static_assert(LOOP_UNROLL_FACTOR == 2 && "changing LOOP_UNROLL_FACTOR also need fix the logic here"); - + GateRef dstOff = PtrSub(TaggedCastToIntPtr(dstAddr), TaggedCastToIntPtr(dstObj)); DEFVARIABLE(offset, VariableType::INT32(), Int32Mul(length, Int32(tSize))); GateRef remainder = Int32And(length, Int32(LOOP_UNROLL_FACTOR - 1)); BRANCH_NO_WEIGHT(Int32NotEqual(remainder, Int32(0)), &storeEnd, &enterLoop); @@ -10499,8 +10661,8 @@ void StubBuilder::ArrayCopy(GateRef glue, GateRef src, Ga // Now use 2 as loop unroll factor, so only store once if reminder is not 0. // But if using other loop unroll factor, the store head should also be refactored. offset = Int32Sub(*offset, Int32(tSize)); - GateRef value = Load(VariableType::JS_ANY(), src, ZExtInt32ToPtr(*offset)); - Store(VariableType::JS_ANY(), glue, dst, ZExtInt32ToPtr(*offset), value, mAttr); + GateRef value = Load(VariableType::JS_ANY(), srcAddr, ZExtInt32ToPtr(*offset)); + Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff, *offset), value, mAttr); Jump(&enterLoop); } Bind(&enterLoop); @@ -10515,10 +10677,10 @@ void StubBuilder::ArrayCopy(GateRef glue, GateRef src, Ga offset = Int32Sub(*offset, Int32(LOOP_UNROLL_FACTOR * tSize)); GateRef off1 = ZExtInt32ToPtr(*offset); GateRef off2 = PtrAdd(off1, IntPtr(tSize)); - GateRef value1 = Load(VariableType::JS_ANY(), src, off1); - GateRef value2 = Load(VariableType::JS_ANY(), src, off2); - Store(VariableType::JS_ANY(), glue, dst, off1, value1, mAttr); - Store(VariableType::JS_ANY(), glue, dst, off2, value2, mAttr); + GateRef value1 = Load(VariableType::JS_ANY(), srcAddr, off1); + GateRef value2 = Load(VariableType::JS_ANY(), srcAddr, off2); + Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff,off1), value1, mAttr); + Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff,off2), value2, mAttr); Jump(&endLoop); } Bind(&endLoop); @@ -10529,35 +10691,36 @@ void StubBuilder::ArrayCopy(GateRef glue, GateRef src, Ga } template <> -void StubBuilder::ArrayCopy(GateRef glue, GateRef src, GateRef dst, GateRef length, - MemoryAttribute mAttr) +void StubBuilder::ArrayCopy(GateRef glue, GateRef srcAddr, GateRef dstObj, GateRef dstAddr, + GateRef length, MemoryAttribute mAttr) { auto env = GetEnvironment(); Label entry(env); env->SubCfgEntry(&entry); Label exit(env); GateRef needRightToLeft = LogicAndBuilder(env) - .And(IntPtrGreaterThan(dst, src)) - .And(IntPtrGreaterThan(PtrAdd(src, ZExtInt32ToPtr(length)), dst)) + .And(IntPtrGreaterThan(dstAddr, srcAddr)) + .And(IntPtrGreaterThan(PtrAdd(srcAddr, ZExtInt32ToPtr(length)), dstAddr)) .Done(); Label leftToRight(env); Label rightToLeft(env); BRANCH_NO_WEIGHT(needRightToLeft, &rightToLeft, &leftToRight); Bind(&rightToLeft); { - ArrayCopy(glue, src, dst, length, mAttr); + ArrayCopy(glue, srcAddr, dstObj, dstAddr, length, mAttr); Jump(&exit); } Bind(&leftToRight); { - ArrayCopy(glue, src, dst, length, mAttr); + ArrayCopy(glue, srcAddr, dstObj, dstAddr, length, mAttr); Jump(&exit); } Bind(&exit); env->SubCfgExit(); } -void StubBuilder::ArrayCopyAndHoleToUndefined(GateRef glue, GateRef src, GateRef dst, GateRef length, MemoryAttribute mAttr) +void StubBuilder::ArrayCopyAndHoleToUndefined(GateRef glue, GateRef srcAddr, GateRef dstObj, GateRef dstAddr, + GateRef length, MemoryAttribute mAttr) { auto env = GetEnvironment(); Label entry(env); @@ -10566,7 +10729,7 @@ void StubBuilder::ArrayCopyAndHoleToUndefined(GateRef glue, GateRef src, GateRef Label begin(env); Label body(env); Label endLoop(env); - + GateRef dstOff = PtrSub(TaggedCastToIntPtr(dstAddr), TaggedCastToIntPtr(dstObj)); DEFVARIABLE(index, VariableType::INT32(), Int32(0)); Jump(&begin); LoopBegin(&begin); @@ -10575,18 +10738,19 @@ void StubBuilder::ArrayCopyAndHoleToUndefined(GateRef glue, GateRef src, GateRef Bind(&body); { GateRef offset = PtrMul(ZExtInt32ToPtr(*index), IntPtr(JSTaggedValue::TaggedTypeSize())); - GateRef value = Load(VariableType::JS_ANY(), src, offset); + GateRef value = Load(VariableType::JS_ANY(), srcAddr, offset); Label isHole(env); Label isNotHole(env); BRANCH_UNLIKELY(TaggedIsHole(value), &isHole, &isNotHole); Bind(&isHole); { - Store(VariableType::JS_ANY(), glue, dst, offset, Undefined(), MemoryAttribute::NoBarrier()); + Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff, offset), Undefined(), + MemoryAttribute::NoBarrier()); Jump(&endLoop); } Bind(&isNotHole); - Store(VariableType::JS_ANY(), glue, dst, offset, value, mAttr); + Store(VariableType::JS_ANY(), glue, dstObj, PtrAdd(dstOff, offset), value, mAttr); Jump(&endLoop); } } diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index 91c1e7a6aeacfa4ec7936a408638538cb9539b56..aa94441cfdc28a61319600e429b0fced84098fdf 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -286,7 +286,7 @@ public: GateRef TaggedIsJSGlobalObject(GateRef x); GateRef TaggedIsWeak(GateRef x); GateRef TaggedIsPrototypeHandler(GateRef x); - GateRef TaggedIsStoreTSHandler(GateRef x); + GateRef TaggedIsStoreAOTHandler(GateRef x); GateRef TaggedIsTransWithProtoHandler(GateRef x); GateRef TaggedIsTransitionHandler(GateRef x); GateRef TaggedIsString(GateRef obj); @@ -380,7 +380,8 @@ public: void SetHash(GateRef glue, GateRef object, GateRef hash); GateRef GetLengthOfTaggedArray(GateRef array); GateRef GetLengthOfJSTypedArray(GateRef array); - GateRef GetExtractLengthOfTaggedArray(GateRef array); + GateRef GetExtraLengthOfTaggedArray(GateRef array); + void SetExtraLengthOfTaggedArray(GateRef glue, GateRef array, GateRef len); // object operation GateRef IsJSHClass(GateRef obj); GateRef LoadHClass(GateRef object); @@ -398,6 +399,7 @@ public: GateRef IsDictionaryMode(GateRef object); GateRef IsDictionaryModeByHClass(GateRef hClass); GateRef IsDictionaryElement(GateRef hClass); + GateRef IsJSArrayPrototypeModified(GateRef hClass); GateRef IsStableElements(GateRef hClass); GateRef HasConstructorByHClass(GateRef hClass); GateRef HasConstructor(GateRef object); @@ -425,6 +427,7 @@ public: GateRef IsJSGlobalObject(GateRef obj); GateRef IsNativeModuleFailureInfo(GateRef obj); GateRef IsModuleNamespace(GateRef obj); + GateRef IsNativePointer(GateRef obj); GateRef IsSourceTextModule(GateRef obj); GateRef ObjIsSpecialContainer(GateRef obj); GateRef IsJSPrimitiveRef(GateRef obj); @@ -444,6 +447,7 @@ public: GateRef IsConfigable(GateRef attr); GateRef IsDefaultAttribute(GateRef attr); GateRef IsArrayLengthWritable(GateRef glue, GateRef receiver); + GateRef IsArrayLengthWritableForNonDictMode(GateRef receiver); GateRef IsAccessor(GateRef attr); GateRef IsInlinedProperty(GateRef attr); GateRef IsField(GateRef attr); @@ -489,8 +493,8 @@ public: GateRef GetProtoCell(GateRef object); GateRef GetPrototypeHandlerHolder(GateRef object); GateRef GetPrototypeHandlerHandlerInfo(GateRef object); - GateRef GetStoreTSHandlerHolder(GateRef object); - GateRef GetStoreTSHandlerHandlerInfo(GateRef object); + GateRef GetStoreAOTHandlerHolder(GateRef object); + GateRef GetStoreAOTHandlerHandlerInfo(GateRef object); inline GateRef GetLengthOfJSArray(GateRef array); inline GateRef GetPrototype(GateRef glue, GateRef object); GateRef GetHasChanged(GateRef object); @@ -547,9 +551,9 @@ public: void SetEnumCacheToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef key); void SetTransitionsToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef transition); void SetParentToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef parent); - void SetIsProtoTypeToHClass(GateRef glue, GateRef hClass, GateRef value); - inline void SetIsTS(GateRef glue, GateRef hClass, GateRef value); - GateRef IsProtoTypeHClass(GateRef hClass); + void SetIsPrototypeToHClass(GateRef glue, GateRef hClass, GateRef value); + inline void SetIsAOT(GateRef glue, GateRef hClass, GateRef value); + GateRef IsPrototypeHClass(GateRef hClass); void SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef hClass, GateRef value, GateRef attrOffset, VariableType type = VariableType::JS_ANY(), MemoryAttribute mAttr = MemoryAttribute::Default()); @@ -560,7 +564,7 @@ public: void IncNumberOfProps(GateRef glue, GateRef hClass); GateRef GetNumberOfPropsFromHClass(GateRef hClass); GateRef HasDeleteProperty(GateRef hClass); - GateRef IsTSHClass(GateRef hClass); + GateRef IsAOTHClass(GateRef hClass); void SetNumberOfPropsToHClass(GateRef glue, GateRef hClass, GateRef value); void SetElementsKindToTrackInfo(GateRef glue, GateRef trackInfo, GateRef elementsKind); void SetSpaceFlagToTrackInfo(GateRef glue, GateRef trackInfo, GateRef spaceFlag); @@ -587,8 +591,8 @@ public: GateRef UpdateSOutOfBoundsForHandler(GateRef handlerInfo); void RestoreElementsKindToGeneric(GateRef glue, GateRef jsHClass); GateRef GetTaggedValueWithElementsKind(GateRef receiver, GateRef index); - void FastSetValueWithElementsKind(GateRef glue, GateRef elements, GateRef rawValue, - GateRef index, ElementsKind kind); + void FastSetValueWithElementsKind(GateRef glue, GateRef receiver, GateRef elements, GateRef rawValue, + GateRef index, ElementsKind kind, bool needTransition = false); GateRef SetValueWithElementsKind(GateRef glue, GateRef receiver, GateRef rawValue, GateRef index, GateRef needTransition, GateRef extraKind); GateRef CopyJSArrayToTaggedArrayArgs(GateRef glue, GateRef srcObj); @@ -843,7 +847,7 @@ public: GateRef GetGlobalOwnProperty(GateRef glue, GateRef receiver, GateRef key, ProfileOperation callback); GateRef AddElementInternal(GateRef glue, GateRef receiver, GateRef index, GateRef value, GateRef attr); GateRef ShouldTransToDict(GateRef capcity, GateRef index); - void NotifyStableArrayElementsGuardians(GateRef glue, GateRef receiver); + void NotifyArrayPrototypeChangedGuardians(GateRef glue, GateRef receiver); GateRef GrowElementsCapacity(GateRef glue, GateRef receiver, GateRef capacity); inline GateRef GetObjectFromConstPool(GateRef constpool, GateRef index); @@ -915,8 +919,11 @@ public: GateRef ElementsKindIsNumOrHoleNum(GateRef kind); GateRef ElementsKindIsHeapKind(GateRef kind); GateRef ElementsKindHasHole(GateRef kind); - void ArrayCopyAndHoleToUndefined(GateRef glue, GateRef src, GateRef dst, GateRef length, - MemoryAttribute mAttr = MemoryAttribute::Default()); + // dstAddr/srcAddr is the address will be copied to/from. + // It can be a derived pointer point to the middle of an object. + // Note: dstObj is the object address for dstAddr, it must point to the head of an object. + void ArrayCopyAndHoleToUndefined(GateRef glue, GateRef srcAddr, GateRef dstObj, GateRef dstAddr, + GateRef length, MemoryAttribute mAttr = MemoryAttribute::Default()); void MigrateArrayWithKind(GateRef glue, GateRef object, GateRef oldKind, GateRef newKind); GateRef MigrateFromRawValueToHeapValues(GateRef glue, GateRef object, GateRef needCOW, GateRef isIntKind); GateRef MigrateFromHeapValueToRawValue(GateRef glue, GateRef object, GateRef needCOW, GateRef isIntKind); @@ -1011,7 +1018,6 @@ public: inline GateRef GetAccessorHasChanged(GateRef obj); inline GateRef ComputeTaggedTypedArraySize(GateRef elementSize, GateRef length); GateRef ChangeTaggedPointerToInt64(GateRef x); - GateRef GetLastLeaveFrame(GateRef glue); inline GateRef GetPropertiesCache(GateRef glue); GateRef GetIndexFromPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key, GateRef hir = Circuit::NullGate()); @@ -1027,6 +1033,7 @@ public: FunctionKind targetKind = FunctionKind::LAST_FUNCTION_KIND); GateRef BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key, GateRef propsNum, GateRef hir = Circuit::NullGate()); + GateRef GetLastLeaveFrame(GateRef glue); void UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function, GateRef profileTypeInfo, GateRef slotId); GateRef Loadlocalmodulevar(GateRef glue, GateRef index, GateRef module); @@ -1046,8 +1053,12 @@ public: // Unknown means all the kinds above are possible, it will select the suitable one in runtime. Unknown, }; + // dstAddr/srcAddr is the address will be copied to/from. + // It can be a derived pointer point to the middle of an object. + // + // Note: dstObj is the object address for dstAddr, it must point to the head of an object. template - void ArrayCopy(GateRef glue, GateRef src, GateRef dst, GateRef length, + void ArrayCopy(GateRef glue, GateRef srcAddr, GateRef dstObj, GateRef dstAddr, GateRef length, MemoryAttribute mAttr = MemoryAttribute::Default()); protected: static constexpr int LOOP_UNROLL_FACTOR = 2; diff --git a/ecmascript/compiler/tests/BUILD.gn b/ecmascript/compiler/tests/BUILD.gn index aec941e0149815313aca93a941c4419b58c5ef84..6f7354b56ea9287f72723d61e7c5e9ffdd186cb6 100644 --- a/ecmascript/compiler/tests/BUILD.gn +++ b/ecmascript/compiler/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("AssemblerTest") { module_out_path = module_output_path diff --git a/ecmascript/compiler/tests/instruction_combine_test.cpp b/ecmascript/compiler/tests/instruction_combine_test.cpp index 06811a6bf502b06b427127110aa0a514b7ca9f69..05025e2961c30181e00b4548c9cb43853ecfb07b 100644 --- a/ecmascript/compiler/tests/instruction_combine_test.cpp +++ b/ecmascript/compiler/tests/instruction_combine_test.cpp @@ -1283,10 +1283,13 @@ HWTEST_F_L0(InstructionCombineTests, ConvertTest) auto x = b.Arguments(1); EXPECT_EQ(instcombie.VisitGate(b.ChangeFloat64ToInt32(b.ChangeInt32ToFloat64(x))), x); } - { auto x = b.Arguments(2); - EXPECT_EQ(instcombie.VisitGate(b.ChangeInt32ToFloat64(b.ChangeFloat64ToInt32(x))), x); + EXPECT_NE(instcombie.VisitGate(b.ChangeInt32ToFloat64(b.ChangeFloat64ToInt32(x))), x); + } + { + auto x = b.Arguments(3); + EXPECT_NE(instcombie.VisitGate(b.Int64ToTaggedPtr(b.ChangeTaggedPointerToInt64(x))), x); } } } // namespace panda::test \ No newline at end of file diff --git a/ecmascript/compiler/trampoline/aarch64/asm_interpreter_call.cpp b/ecmascript/compiler/trampoline/aarch64/asm_interpreter_call.cpp index d199f6a7dfce26d1defc41ca4e43635da7e9460b..5a968a1e9e1b7428b5d8d532e6bf48c3dc46cf3a 100644 --- a/ecmascript/compiler/trampoline/aarch64/asm_interpreter_call.cpp +++ b/ecmascript/compiler/trampoline/aarch64/asm_interpreter_call.cpp @@ -1631,7 +1631,12 @@ void AsmInterpreterCall::PushVregs(ExtendedAssembler *assembler, __ Cmp(tempRegister, Immediate(JSTaggedValue::VALUE_HOLE)); __ B(Condition::EQ, &baselineCodeUndefined); - __ Ldr(tempRegister, MemoryOperand(tempRegister, MachineCode::FUNCADDR_OFFSET)); + if (MachineCode::FUNCADDR_OFFSET % 8 == 0) { // 8: imm in 64-bit ldr insn must be a multiple of 8 + __ Ldr(tempRegister, MemoryOperand(tempRegister, MachineCode::FUNCADDR_OFFSET)); + } else { + ASSERT(MachineCode::FUNCADDR_OFFSET < 256); // 256: imm in ldur insn must be in the range -256 to 255 + __ Ldur(tempRegister, MemoryOperand(tempRegister, MachineCode::FUNCADDR_OFFSET)); + } if (glue != X19) { __ Mov(X19, glue); } diff --git a/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp b/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp index 9f20434cc28ae234cc1388b9e172c79b89ac15b1..05e79df6ddee90299ab675f2946f9914d0635179 100644 --- a/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp +++ b/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp @@ -1854,6 +1854,12 @@ void AsmInterpreterCall::ThrowStackOverflowExceptionAndReturn(ExtendedAssembler __ Pushq(static_cast(FrameType::ASM_BRIDGE_FRAME)); // set frame type __ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp); // skip frame type + Label callRuntime; + // 16 bytes align check + __ Testq(0x8, rsp); + __ Jnz(&callRuntime); + __ PushAlignBytes(); + __ Bind(&callRuntime); __ Pushq(r10); // caller save __ Pushq(0); // argc __ Pushq(kungfu::RuntimeStubCSigns::ID_ThrowStackOverflowException); // runtime id @@ -1863,13 +1869,13 @@ void AsmInterpreterCall::ThrowStackOverflowExceptionAndReturn(ExtendedAssembler __ Callq(r10); // call CallRuntime __ Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip argc and runtime_id __ Popq(r10); - __ Addq(FRAME_SLOT_SIZE, rsp); // skip frame type + __ Movq(rbp, rsp); __ Popq(rbp); __ Ret(); } -void AsmInterpreterCall::ThrowStackOverflowExceptionAndReturnToAotFrame(ExtendedAssembler *assembler, Register glue, - Register fp, Register op) +void AsmInterpreterCall::ThrowStackOverflowExceptionAndReturnToAsmInterpBridgeFrame(ExtendedAssembler *assembler, + Register glue, Register fp, Register op) { if (fp != rsp) { __ Movq(fp, rsp); @@ -1884,6 +1890,12 @@ void AsmInterpreterCall::ThrowStackOverflowExceptionAndReturnToAotFrame(Extended __ Pushq(static_cast(FrameType::ASM_BRIDGE_FRAME)); // set frame type __ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp); // skip frame type + Label callRuntime; + // 16 bytes align check + __ Testq(0x8, rsp); + __ Jnz(&callRuntime); + __ PushAlignBytes(); + __ Bind(&callRuntime); __ Pushq(r10); // caller save __ Pushq(0); // argc __ Pushq(kungfu::RuntimeStubCSigns::ID_ThrowStackOverflowException); // runtime id @@ -1893,10 +1905,13 @@ void AsmInterpreterCall::ThrowStackOverflowExceptionAndReturnToAotFrame(Extended __ Callq(r10); // call CallRuntime __ Addq(2 * FRAME_SLOT_SIZE, rsp); // 2: skip argc and runtime_id __ Popq(r10); - __ Addq(FRAME_SLOT_SIZE, rsp); // skip frame type - __ Popq(rbp); __ Movq(rbp, rsp); - __ Movq(Operand(rbp, -2 * FRAME_SLOT_SIZE), rbp); // 2: skip returnAddr and frameType in AsmBridgeFrame + __ Popq(rbp); + + // Base on PushAsmInterpBridgeFrame, need to skip AsmInterpBridgeFrame size, callee Save Registers(5) + // and PushAlignBytes(1) + int32_t skipNum = AsmInterpretedBridgeFrame::GetSize(false) / FRAME_SLOT_SIZE + 5 + 1; + __ Leaq(Operand(rbp, -skipNum * FRAME_SLOT_SIZE), rsp); __ Ret(); } diff --git a/ecmascript/compiler/trampoline/x64/common_call.h b/ecmascript/compiler/trampoline/x64/common_call.h index 8ca9f2dea4f1e35ff5f2cb405532342548e86cc8..11cd85811e95d3deb07d1c6ced0fb667a2122b23 100644 --- a/ecmascript/compiler/trampoline/x64/common_call.h +++ b/ecmascript/compiler/trampoline/x64/common_call.h @@ -202,7 +202,7 @@ private: Register op1, Register op2, Label *stackOverflow); static void ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, Register fp, Register op); - static void ThrowStackOverflowExceptionAndReturnToAotFrame(ExtendedAssembler *assembler, Register glue, + static void ThrowStackOverflowExceptionAndReturnToAsmInterpBridgeFrame(ExtendedAssembler *assembler, Register glue, Register fp, Register op); static void HasPendingException(ExtendedAssembler *assembler, Register threadRegister); static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode, diff --git a/ecmascript/compiler/trampoline/x64/optimized_call.cpp b/ecmascript/compiler/trampoline/x64/optimized_call.cpp index 1927535f223e646c7f84d7dd17909a8ca97a3b52..056895dfdcb5c1c02efae856dd0427502951e4ab 100644 --- a/ecmascript/compiler/trampoline/x64/optimized_call.cpp +++ b/ecmascript/compiler/trampoline/x64/optimized_call.cpp @@ -1406,7 +1406,7 @@ void OptimizedCall::DeoptEnterAsmInterp(ExtendedAssembler *assembler) { [[maybe_unused]] TempRegisterScope scope(assembler); Register temp = __ TempRegister(); - AsmInterpreterCall::ThrowStackOverflowExceptionAndReturnToAotFrame(assembler, + AsmInterpreterCall::ThrowStackOverflowExceptionAndReturnToAsmInterpBridgeFrame(assembler, glueRegister, rsp, temp); } } diff --git a/ecmascript/compiler/type_info_accessors.cpp b/ecmascript/compiler/type_info_accessors.cpp index b2df6ea64cbd3cedac5d5c2479d51665eaf14381..f38fd66a7bbfc81eab37b794054982d9e23b56d8 100644 --- a/ecmascript/compiler/type_info_accessors.cpp +++ b/ecmascript/compiler/type_info_accessors.cpp @@ -680,6 +680,9 @@ bool StorePrivatePropertyTypeInfoAccessor::AotAccessorStrategy::GenerateObjectAc return true; } + if (parent_.types_.size() == 0) { + return false; + } ProfileTyper receiverType = std::get<0>(parent_.types_.at(0)); ProfileTyper holderType = std::get<1>(parent_.types_.at(0)); if (receiverType == holderType) { @@ -704,6 +707,9 @@ bool StorePrivatePropertyTypeInfoAccessor::JitAccessorStrategy::GenerateObjectAc return true; } + if (parent_.jitTypes_.size() == 0) { + return false; + } JSHClass *receiverType = parent_.jitTypes_[0].GetReceiverHclass(); JSHClass *holderType = parent_.jitTypes_[0].GetHolderHclass(); if (receiverType->IsJsPrimitiveRef() || holderType->IsJsPrimitiveRef()) { @@ -780,6 +786,9 @@ bool LoadPrivatePropertyTypeInfoAccessor::AotAccessorStrategy::GenerateObjectAcc return true; } + if (parent_.types_.size() == 0) { + return false; + } ProfileTyper receiverType = parent_.types_.at(0).first; ProfileTyper holderType = parent_.types_.at(0).second; if (receiverType == holderType) { @@ -804,6 +813,9 @@ bool LoadPrivatePropertyTypeInfoAccessor::JitAccessorStrategy::GenerateObjectAcc return true; } + if (parent_.jitTypes_.size() == 0) { + return false; + } JSHClass *receiver = parent_.jitTypes_[0].GetReceiverHclass(); JSHClass *holder = parent_.jitTypes_[0].GetHolderHclass(); // case: r.toFixed() => HeapObjectCheck Deopt @@ -876,6 +888,9 @@ bool LoadObjByNameTypeInfoAccessor::AotAccessorStrategy::GenerateObjectAccessInf if (key.IsUndefined()) { return false; } + if (parent_.types_.size() == 0) { + return false; + } for (size_t i = 0; i < parent_.types_.size(); ++i) { ProfileTyper receiverType = parent_.types_[i].first; ProfileTyper holderType = parent_.types_[i].second; @@ -909,6 +924,9 @@ bool LoadObjByNameTypeInfoAccessor::JitAccessorStrategy::GenerateObjectAccessInf if (key.IsUndefined()) { return false; } + if (parent_.jitTypes_.size() == 0) { + return false; + } for (size_t i = 0; i < parent_.jitTypes_.size(); ++i) { JSHClass *receiver = parent_.jitTypes_[i].GetReceiverHclass(); JSHClass *holder = parent_.jitTypes_[i].GetHolderHclass(); @@ -1015,6 +1033,9 @@ void StoreObjByNameTypeInfoAccessor::JitAccessorStrategy::FetchPGORWTypesDual() bool StoreObjByNameTypeInfoAccessor::AotAccessorStrategy::GenerateObjectAccessInfo() { JSTaggedValue key = parent_.GetKeyTaggedValue(); + if (parent_.types_.size() == 0) { + return false; + } for (size_t i = 0; i < parent_.types_.size(); ++i) { ProfileTyper receiverType = std::get<0>(parent_.types_[i]); ProfileTyper holderType = std::get<1>(parent_.types_[i]); @@ -1054,6 +1075,9 @@ bool StoreObjByNameTypeInfoAccessor::JitAccessorStrategy::GenerateObjectAccessIn if (key.IsUndefined()) { return false; } + if (parent_.jitTypes_.size() == 0) { + return false; + } for (size_t i = 0; i < parent_.jitTypes_.size(); ++i) { JSHClass* receiverType = parent_.jitTypes_[i].GetReceiverHclass(); JSHClass* holderType = parent_.jitTypes_[i].GetHolderHclass(); @@ -1169,6 +1193,9 @@ bool InstanceOfTypeInfoAccessor::AotAccessorStrategy::GenerateObjectAccessInfo() if (!IsMono()) { return false; } + if (parent_.types_.size() == 0) { + return false; + } JSTaggedValue key = parent_.GetKeyTaggedValue(); for (size_t i = 0; i < parent_.types_.size(); ++i) { ProfileTyper targetPgoType = parent_.types_[i].first; @@ -1198,6 +1225,9 @@ bool InstanceOfTypeInfoAccessor::JitAccessorStrategy::GenerateObjectAccessInfo() if (key.IsUndefined()) { return false; } + if (parent_.jitTypes_.size() == 0) { + return false; + } for (size_t i = 0; i < parent_.jitTypes_.size(); ++i) { JSHClass *receiver = parent_.jitTypes_[i].GetReceiverHclass(); if (receiver->IsJsPrimitiveRef()) { diff --git a/ecmascript/compiler/type_info_accessors.h b/ecmascript/compiler/type_info_accessors.h index b29cb50ccd43b20cd37bb13753224e7f3069d98a..3ca8ff75c92dcc399c7eb67b28a701f4cbec932c 100644 --- a/ecmascript/compiler/type_info_accessors.h +++ b/ecmascript/compiler/type_info_accessors.h @@ -1369,6 +1369,7 @@ public: virtual bool IsHolderEqNewHolder(size_t index) const = 0; virtual void FetchPGORWTypesDual() = 0; virtual bool GenerateObjectAccessInfo() = 0; + virtual bool IsPrototypeHclass(size_t index) const = 0; }; class AotAccessorStrategy : public AccessorStrategy { @@ -1409,6 +1410,17 @@ public: return std::get(parent_.types_[index]) == std::get(parent_.types_[index]); } + + bool IsPrototypeHclass(size_t index) const override + { + ProfileTyper recv = std::get(parent_.types_[index]); + JSTaggedValue hclass = parent_.ptManager_->QueryHClass(recv.first, recv.second); + if (!hclass.IsJSHClass()) { + return false; + } + return JSHClass::Cast(hclass.GetTaggedObject())->IsPrototype(); + } + void FetchPGORWTypesDual() override; bool GenerateObjectAccessInfo() override; @@ -1451,6 +1463,12 @@ public: { return parent_.jitTypes_[index].GetHolderHclass() == parent_.jitTypes_[index].GetHolderTraHclass(); } + + bool IsPrototypeHclass(size_t index) const override + { + return parent_.jitTypes_[index].GetReceiverHclass()->IsPrototype(); + } + void FetchPGORWTypesDual() override; bool GenerateObjectAccessInfo() override; @@ -1492,6 +1510,11 @@ public: return strategy_->IsHolderEqNewHolder(index); } + bool IsPrototypeHclass(size_t index) const + { + return strategy_->IsPrototypeHclass(index); + } + GateRef GetValue() const { return value_; diff --git a/ecmascript/compiler/typed_bytecode_lowering.cpp b/ecmascript/compiler/typed_bytecode_lowering.cpp index b82a6b3bdb1eef389d846b7a3589f917908cb5ea..10780a85b6f180615c1504bd773770bec3cbf2bb 100644 --- a/ecmascript/compiler/typed_bytecode_lowering.cpp +++ b/ecmascript/compiler/typed_bytecode_lowering.cpp @@ -578,7 +578,6 @@ void TypedBytecodeLowering::DeleteConstDataIfNoUser(GateRef gate) void TypedBytecodeLowering::LowerTypedLdObjByName(GateRef gate) { - DISALLOW_GARBAGE_COLLECTION; LoadObjByNameTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); if (TryLowerTypedLdobjBynameFromGloablBuiltin(gate)) { @@ -680,7 +679,6 @@ void TypedBytecodeLowering::LowerTypedLdObjByName(GateRef gate) void TypedBytecodeLowering::LowerTypedLdPrivateProperty(GateRef gate) { - DISALLOW_GARBAGE_COLLECTION; LoadPrivatePropertyTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); if (tacc.HasIllegalType()) { @@ -718,7 +716,6 @@ void TypedBytecodeLowering::LowerTypedLdPrivateProperty(GateRef gate) void TypedBytecodeLowering::LowerTypedStPrivateProperty(GateRef gate) { - DISALLOW_GARBAGE_COLLECTION; StorePrivatePropertyTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); if (tacc.HasIllegalType()) { @@ -757,7 +754,6 @@ void TypedBytecodeLowering::LowerTypedStPrivateProperty(GateRef gate) void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate) { - DISALLOW_GARBAGE_COLLECTION; StoreObjByNameTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, chunk_); if (tacc.TypesIsEmpty() || tacc.HasIllegalType()) { return; @@ -805,7 +801,8 @@ void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate) value); } else { builder_.MonoStoreProperty(tacc.GetReceiver(), plrGate, unsharedConstPool, holderHClassIndex, value, - builder_.TruncInt64ToInt32(tacc.GetKey()), frameState); + builder_.TruncInt64ToInt32(tacc.GetKey()), + builder_.Boolean(tacc.IsPrototypeHclass(0)), frameState); } } else if (tacc.IsReceiverEqHolder(0)) { BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(), @@ -829,9 +826,10 @@ void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate) } if (tacc.IsReceiverNoEqNewHolder(i)) { builder_.ProtoChangeMarkerCheck(tacc.GetReceiver(), frameState); - auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET); if (tacc.IsHolderEqNewHolder(i)) { // lookup from receiver for holder + auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, + JSHClass::PROTOTYPE_OFFSET); auto holderHC = builder_.GetHClassGateFromIndex(gate, tacc.GetAccessInfo(i).HClassIndex()); DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype); Label loopHead(&builder_); @@ -854,52 +852,7 @@ void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate) tacc.GetAccessInfo(i).Plr()); builder_.Jump(&exit); } else { - // transition happened - Label notProto(&builder_); - Label isProto(&builder_); - auto newHolderHC = builder_.GetHClassGateFromIndex(gate, tacc.GetAccessInfo(i).HClassIndex()); - builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype); - builder_.Branch(builder_.IsProtoTypeHClass(receiverHC), &isProto, ¬Proto, - BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "isProtoTypeHClass"); - builder_.Bind(&isProto); - GateRef propKey = builder_.GetObjectByIndexFromConstPool( - glue_, gate, frameState, builder_.TruncInt64ToInt32(tacc.GetKey()), ConstPoolType::STRING); - builder_.CallRuntime(glue_, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef, - { receiverHC, newHolderHC, propKey }, gate); - builder_.Jump(¬Proto); - builder_.Bind(¬Proto); - MemoryAttribute mAttr = MemoryAttribute::NeedBarrierAndAtomic(); - builder_.StoreConstOffset(VariableType::JS_ANY(), tacc.GetReceiver(), - TaggedObject::HCLASS_OFFSET, newHolderHC, mAttr); - if (!tacc.GetAccessInfo(i).Plr().IsInlinedProps()) { - auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), tacc.GetReceiver(), - JSObject::PROPERTIES_OFFSET); - auto capacity = - builder_.LoadConstOffset(VariableType::INT32(), properties, TaggedArray::LENGTH_OFFSET); - auto index = builder_.Int32(tacc.GetAccessInfo(i).Plr().GetOffset()); - Label needExtend(&builder_); - Label notExtend(&builder_); - BRANCH_CIR(builder_.Int32UnsignedLessThan(index, capacity), ¬Extend, &needExtend); - builder_.Bind(¬Extend); - { - BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(), - tacc.GetValue(), tacc.GetAccessInfo(i).Plr()); - builder_.Jump(&exit); - } - builder_.Bind(&needExtend); - { - builder_.CallRuntime(glue_, - RTSTUB_ID(PropertiesSetValue), - Gate::InvalidGateRef, - { tacc.GetReceiver(), tacc.GetValue(), properties, builder_.Int32ToTaggedInt(capacity), - builder_.Int32ToTaggedInt(index) }, gate); - builder_.Jump(&exit); - } - } else { - BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(), - tacc.GetValue(), tacc.GetAccessInfo(i).Plr()); - builder_.Jump(&exit); - } + TypedStObjByNameTransition(gate, receiverHC, frameState, exit, tacc, i); } } else if (tacc.IsReceiverEqHolder(i)) { // Local @@ -921,6 +874,58 @@ void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate) DeleteConstDataIfNoUser(tacc.GetKey()); } +void TypedBytecodeLowering::TypedStObjByNameTransition(GateRef gate, GateRef receiverHC, GateRef frameState, + Label &exit, StoreObjByNameTypeInfoAccessor &tacc, size_t i) +{ + Label notProto(&builder_); + Label isProto(&builder_); + auto newHolderHC = builder_.GetHClassGateFromIndex(gate, tacc.GetAccessInfo(i).HClassIndex()); + if (compilationEnv_->IsAotCompiler()) { + auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET); + builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype); + } + if (!tacc.IsPrototypeHclass(i)) { + builder_.DeoptCheck(builder_.BoolNot(builder_.IsPrototypeHClass(receiverHC)), frameState, + DeoptType::PROTOTYPECHANGED2); + } else { + builder_.Branch(builder_.IsPrototypeHClass(receiverHC), &isProto, ¬Proto, + BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "isPrototypeHClass"); + builder_.Bind(&isProto); + GateRef propKey = + builder_.GetObjectByIndexFromConstPool(glue_, gate, frameState, + builder_.TruncInt64ToInt32(tacc.GetKey()), ConstPoolType::STRING); + builder_.CallRuntime(glue_, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef, + { receiverHC, newHolderHC, propKey }, gate); + builder_.Jump(¬Proto); + builder_.Bind(¬Proto); + } + MemoryAttribute mAttr = MemoryAttribute::NeedBarrierAndAtomic(); + builder_.StoreConstOffset(VariableType::JS_ANY(), tacc.GetReceiver(), TaggedObject::HCLASS_OFFSET, + newHolderHC, mAttr); + if (!tacc.GetAccessInfo(i).Plr().IsInlinedProps()) { + auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), tacc.GetReceiver(), + JSObject::PROPERTIES_OFFSET); + auto capacity = builder_.LoadConstOffset(VariableType::INT32(), properties, TaggedArray::LENGTH_OFFSET); + auto index = builder_.Int32(tacc.GetAccessInfo(i).Plr().GetOffset()); + Label needExtend(&builder_); + Label notExtend(&builder_); + BRANCH_CIR(builder_.Int32UnsignedLessThan(index, capacity), ¬Extend, &needExtend); + builder_.Bind(¬Extend); + BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(), tacc.GetValue(), + tacc.GetAccessInfo(i).Plr()); + builder_.Jump(&exit); + builder_.Bind(&needExtend); + builder_.CallRuntime(glue_, RTSTUB_ID(PropertiesSetValue), Gate::InvalidGateRef, + { tacc.GetReceiver(), tacc.GetValue(), properties, builder_.Int32ToTaggedInt(capacity), + builder_.Int32ToTaggedInt(index) }, gate); + builder_.Jump(&exit); + } else { + BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(), tacc.GetValue(), + tacc.GetAccessInfo(i).Plr()); + builder_.Jump(&exit); + } +} + void TypedBytecodeLowering::LowerTypedStOwnByName(GateRef gate) { LowerTypedStObjByName(gate); @@ -1095,10 +1100,7 @@ bool TypedBytecodeLowering::TryLowerTypedLdobjBynameFromGloablBuiltin(GateRef ga return false; } AddProfiling(gate); - GateRef receiverHClass = builder_.LoadHClassByConstOffset(receiver); - GateRef cond = builder_.Equal( - receiverHClass, builder_.GetGlobalEnvObj(builder_.GetGlobalEnv(), GlobalEnv::MATH_FUNCTION_CLASS_INDEX)); - builder_.DeoptCheck(cond, acc_.GetFrameState(gate), DeoptType::INCONSISTENTHCLASS14); + builder_.MathHClassConsistencyCheck(receiver); GateRef plrGate = builder_.Int32(plr.GetData()); GateRef result = builder_.LoadProperty(receiver, plrGate, plr.IsFunction()); acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result); @@ -2288,7 +2290,6 @@ void TypedBytecodeLowering::LowerTypedTryLdGlobalByName(GateRef gate) if (!enableLoweringBuiltin_) { return; } - DISALLOW_GARBAGE_COLLECTION; LoadGlobalObjByNameTypeInfoAccessor tacc(compilationEnv_, circuit_, gate); JSTaggedValue key = tacc.GetKeyTaggedValue(); if (key.IsUndefined()) { @@ -2376,7 +2377,6 @@ void TypedBytecodeLowering::LowerTypedStOwnByValue(GateRef gate) void TypedBytecodeLowering::LowerCreateObjectWithBuffer(GateRef gate) { - DISALLOW_GARBAGE_COLLECTION; CreateObjWithBufferTypeInfoAccessor tacc(compilationEnv_, circuit_, gate, recordName_, chunk_); if (!tacc.CanOptimize()) { return; diff --git a/ecmascript/compiler/typed_bytecode_lowering.h b/ecmascript/compiler/typed_bytecode_lowering.h index 9ed95c4dab6001158ee1bdb42c2749a230ac6b0a..3533439a86cf37a689dd63b2029c02a5f86ad86c 100644 --- a/ecmascript/compiler/typed_bytecode_lowering.h +++ b/ecmascript/compiler/typed_bytecode_lowering.h @@ -124,6 +124,8 @@ private: void LowerTypedLdPrivateProperty(GateRef gate); void LowerTypedLdObjByName(GateRef gate); void LowerTypedStObjByName(GateRef gate); + void TypedStObjByNameTransition(GateRef gate, GateRef receiverHC, GateRef frameState, + Label &exit, StoreObjByNameTypeInfoAccessor &tacc, size_t i); void LowerTypedStOwnByName(GateRef gate); GateRef BuildNamedPropertyAccess(GateRef hir, GateRef receiver, GateRef holder, PropertyLookupResult plr); GateRef BuildNamedPropertyAccess(GateRef hir, GateRef receiver, GateRef holder, diff --git a/ecmascript/compiler/typed_hcr_lowering.cpp b/ecmascript/compiler/typed_hcr_lowering.cpp index cf77ebbc70a51a022f88f6661738bedbc2f93ea8..ad64debf1b387f104ffaeafdc9936678b8d80ed9 100644 --- a/ecmascript/compiler/typed_hcr_lowering.cpp +++ b/ecmascript/compiler/typed_hcr_lowering.cpp @@ -418,21 +418,24 @@ void TypedHCRLowering::LowerTypedArrayCheck(GateRef gate) GateRef glueGlobalEnv = builder_.GetGlobalEnv(); GateRef receiver = acc_.GetValueIn(gate, 0); builder_.HeapObjectCheck(receiver, frameState); - GateRef receiverHClass = builder_.LoadHClass(receiver); - GateRef rootHclass = builder_.GetGlobalEnvObj(glueGlobalEnv, typedArrayRootHclassIndex); - GateRef rootOnHeapHclass = builder_.GetGlobalEnvObj(glueGlobalEnv, typedArrayRootHclassOnHeapIndex); - GateRef check1 = builder_.Equal(receiverHClass, rootHclass); - GateRef check2 = builder_.Equal(receiverHClass, rootOnHeapHclass); - builder_.DeoptCheck(builder_.BitOr(check1, check2), frameState, deoptType); + GateRef receiverHClass = builder_.LoadHClassByConstOffset(receiver); OnHeapMode onHeapMode = accessor.GetOnHeapMode(); - if (accessor.IsAccessElement() && !OnHeap::IsNone(onHeapMode)) { - GateRef profilingOnHeap = builder_.Boolean(OnHeap::ToBoolean(onHeapMode)); - GateRef runtimeOnHeap = builder_.IsOnHeap(receiverHClass); - GateRef onHeapCheck = builder_.Equal(profilingOnHeap, runtimeOnHeap); - builder_.DeoptCheck(onHeapCheck, frameState, DeoptType::INCONSISTENTONHEAP1); + if (OnHeap::IsOnHeap(onHeapMode)) { + GateRef rootOnHeapHclass = builder_.GetGlobalEnvObj(glueGlobalEnv, typedArrayRootHclassOnHeapIndex); + GateRef check = builder_.Equal(receiverHClass, rootOnHeapHclass); + builder_.DeoptCheck(check, frameState, deoptType); + } else if (OnHeap::IsNotOnHeap(onHeapMode)) { + GateRef rootHclass = builder_.GetGlobalEnvObj(glueGlobalEnv, typedArrayRootHclassIndex); + GateRef check = builder_.Equal(receiverHClass, rootHclass); + builder_.DeoptCheck(check, frameState, deoptType); + } else { + GateRef rootHclass = builder_.GetGlobalEnvObj(glueGlobalEnv, typedArrayRootHclassIndex); + GateRef rootOnHeapHclass = builder_.GetGlobalEnvObj(glueGlobalEnv, typedArrayRootHclassOnHeapIndex); + GateRef check1 = builder_.Equal(receiverHClass, rootHclass); + GateRef check2 = builder_.Equal(receiverHClass, rootOnHeapHclass); + builder_.DeoptCheck(builder_.BitOr(check1, check2), frameState, deoptType); } - acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); } @@ -468,7 +471,7 @@ void TypedHCRLowering::LowerEcmaMapCheck(GateRef gate) GateRef receiver = acc_.GetValueIn(gate, 0); builder_.HeapObjectCheck(receiver, frameState); - GateRef hclass = builder_.LoadHClass(receiver); + GateRef hclass = builder_.LoadHClassByConstOffset(receiver); size_t mapHclassIndex = GlobalEnv::MAP_CLASS_INDEX; GateRef glueGlobalEnv = builder_.GetGlobalEnv(); @@ -623,10 +626,17 @@ void TypedHCRLowering::BuiltinInstanceHClassCheck(Environment *env, GateRef gate auto iter = arrayHClassIndexMap.find(kind); ASSERT(iter != arrayHClassIndexMap.end()); GateRef receiverHClass = builder_.LoadHClassByConstOffset(receiver); + // If the Elements kind is Generic, hclass comparison is required. Other kinds can ensure that hclass has + // not been modified. ihcMatches = LogicOrBuilder(env) .Or(builder_.Equal(receiverHClass, builder_.GetGlobalConstantValue(iter->second.first))) .Or(builder_.Equal(receiverHClass, builder_.GetGlobalConstantValue(iter->second.second))) .Done(); + GateRef elementsKind = builder_.GetElementsKindByHClass(receiverHClass); + ihcMatches = LogicOrBuilder(env) + .Or(ihcMatches) + .Or(builder_.NotEqual(elementsKind, builder_.Int32(static_cast(ElementsKind::GENERIC)))) + .Done(); } else { GateRef receiverHClass = builder_.LoadHClassByConstOffset(receiver); GateRef elementsKind = builder_.GetElementsKindByHClass(receiverHClass); @@ -1212,7 +1222,7 @@ GateRef TypedHCRLowering::BuildTypedArrayLoadElement(GateRef receiver, GateRef o DEFVALUE(data, (&builder_), VariableType::JS_ANY(), builder_.Undefined()); DEFVALUE(result, (&builder_), type, builder_.Double(0)); - GateRef isOnHeap = builder_.IsOnHeap(builder_.LoadHClass(receiver)); + GateRef isOnHeap = builder_.IsOnHeap(builder_.LoadHClassByConstOffset(receiver)); BRANCH_CIR(isOnHeap, isByteArray, isArrayBuffer); builder_.Bind(isByteArray); { @@ -1238,12 +1248,12 @@ GateRef TypedHCRLowering::BuildTypedArrayLoadElement(GateRef receiver, GateRef o void TypedHCRLowering::LowerStringLoadElement(GateRef gate) { Environment env(gate, circuit_, &builder_); - GateRef glue = acc_.GetGlueFromArgList(); GateRef receiver = acc_.GetValueIn(gate, 0); GateRef index = acc_.GetValueIn(gate, 1); - GateRef result = builder_.CallStub(glue, gate, CommonStubCSigns::GetSingleCharCodeByIndex, - { glue, receiver, index }); + BuiltinsStringStubBuilder builder(&env); + GateRef result = builder.GetSingleCharCodeByIndex(receiver, index); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); } @@ -1394,7 +1404,7 @@ void TypedHCRLowering::BuildTypedArrayStoreElement(GateRef receiver, GateRef off { GateRef byteArrayOrArrayBuffer = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET); - GateRef isOnHeap = builder_.IsOnHeap(builder_.LoadHClass(receiver)); + GateRef isOnHeap = builder_.IsOnHeap(builder_.LoadHClassByConstOffset(receiver)); DEFVALUE(data, (&builder_), VariableType::JS_ANY(), builder_.Undefined()); BRANCH_CIR(isOnHeap, isByteArray, isArrayBuffer); builder_.Bind(isByteArray); @@ -1596,10 +1606,9 @@ void TypedHCRLowering::LowerJSInlineTargetTypeCheck(GateRef gate) GateRef frameState = GetFrameState(gate); auto func = acc_.GetValueIn(gate, 0); builder_.HeapObjectCheck(func, frameState); - GateRef check = LogicAndBuilder(&env) - .And(builder_.IsJSFunction(func)) - .And(builder_.Equal(builder_.GetMethodId(func), acc_.GetValueIn(gate, 1))) - .Done(); + GateRef isFunction = builder_.IsJSFunction(func); + builder_.DeoptCheck(isFunction, frameState, DeoptType::NOTJSFUNCTION); + GateRef check = builder_.Equal(builder_.GetMethodId(func), acc_.GetValueIn(gate, 1)); builder_.DeoptCheck(check, frameState, DeoptType::INLINEFAIL1); acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); } @@ -1648,7 +1657,7 @@ void TypedHCRLowering::LowerGetSuperConstructor(GateRef gate) { Environment env(gate, circuit_, &builder_); GateRef ctor = acc_.GetValueIn(gate, 0); - GateRef hclass = builder_.LoadHClass(ctor); + GateRef hclass = builder_.LoadHClassByConstOffset(ctor); GateRef superCtor = builder_.LoadConstOffset(VariableType::JS_ANY(), hclass, JSHClass::PROTOTYPE_OFFSET); acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), superCtor); } @@ -1724,7 +1733,7 @@ void TypedHCRLowering::LowerLookupHolder(GateRef gate) builder_.LoopBegin(&loopHead); builder_.DeoptCheck(builder_.TaggedIsNotNull(*holder), frameState, DeoptType::INCONSISTENTHCLASS13); - auto curHC = builder_.LoadHClass(*holder); + auto curHC = builder_.LoadHClassByConstOffset(*holder); BRANCH_CIR(builder_.Equal(curHC, holderHC), &exit, &lookUpProto); builder_.Bind(&lookUpProto); @@ -1787,7 +1796,7 @@ void TypedHCRLowering::LowerPrototypeCheck(GateRef gate) auto expectedReceiverHC = builder_.LoadHClassFromConstpool(unsharedConstPool, hclassIndex); auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), expectedReceiverHC, JSHClass::PROTOTYPE_OFFSET); - auto protoHClass = builder_.LoadHClass(prototype); + auto protoHClass = builder_.LoadHClassByConstOffset(prototype); auto marker = builder_.LoadConstOffset(VariableType::JS_ANY(), protoHClass, JSHClass::PROTO_CHANGE_MARKER_OFFSET); builder_.DeoptCheck(builder_.TaggedIsNotNull(marker), frameState, DeoptType::PROTOTYPECHANGED1); auto check = LogicAndBuilder(&env) @@ -1964,9 +1973,8 @@ void TypedHCRLowering::LowerArrayConstructor(GateRef gate, GateRef glue) builder_.Bind(&argIsDouble); { Label validDoubleLength(&builder_); - Label GetDoubleToIntValue(&builder_); GateRef doubleLength = builder_.GetDoubleOfTDouble(arg0); - GateRef doubleToInt = builder_.DoubleToInt(doubleLength, &GetDoubleToIntValue); + GateRef doubleToInt = builder_.TruncDoubleToInt(glue, doubleLength, base::INT32_BITS); GateRef intToDouble = builder_.CastInt64ToFloat64(builder_.SExtInt32ToInt64(doubleToInt)); GateRef doubleEqual = builder_.DoubleEqual(doubleLength, intToDouble); GateRef doubleLEMaxLen = @@ -2061,9 +2069,8 @@ void TypedHCRLowering::ConvertFloat32ArrayConstructorLength(GateRef len, Variabl builder_.Bind(&argIsDouble); { Label validDoubleLength(&builder_); - Label GetDoubleToIntValue(&builder_); GateRef doubleLength = builder_.GetDoubleOfTDouble(len); - GateRef doubleToInt = builder_.DoubleToInt(doubleLength, &GetDoubleToIntValue); + GateRef doubleToInt = builder_.TruncDoubleToInt(acc_.GetGlueFromArgList(), doubleLength, base::INT32_BITS); GateRef intToDouble = builder_.CastInt64ToFloat64(builder_.SExtInt32ToInt64(doubleToInt)); GateRef doubleEqual = builder_.DoubleEqual(doubleLength, intToDouble); GateRef doubleLEMaxLen = @@ -2568,7 +2575,7 @@ void TypedHCRLowering::LowerOrdinaryHasInstance(GateRef gate, GateRef glue) } builder_.Bind(&objectNotIsJsProxy); { - GateRef objHClass = builder_.LoadHClass(*object); + GateRef objHClass = builder_.LoadHClassByConstOffset(*object); object = builder_.LoadPrototype(objHClass); builder_.Jump(&shouldContinue); } @@ -2813,25 +2820,34 @@ void TypedHCRLowering::LowerMonoStoreProperty(GateRef gate, GateRef glue) GateRef unsharedConstPool = acc_.GetValueIn(gate, 3); // 3: constPool GateRef value = acc_.GetValueIn(gate, 4); // 4: value GateRef keyIndex = acc_.GetValueIn(gate, 5); // 5: keyIndex + bool isPrototype = acc_.TryGetValue(acc_.GetValueIn(gate, 6)); // 6: proto flag Index PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult)); bool noBarrier = acc_.IsNoBarrier(gate); auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET); - auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET); // transition happened Label exit(&builder_); Label notProto(&builder_); Label isProto(&builder_); auto newHolderHC = builder_.LoadHClassFromConstpool(unsharedConstPool, acc_.GetConstantValue(hclassIndex)); - builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype); - builder_.Branch(builder_.IsProtoTypeHClass(receiverHC), &isProto, ¬Proto, - BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "isProtoTypeHClass"); - builder_.Bind(&isProto); - - GateRef propKey = builder_.GetObjectByIndexFromConstPool(glue, gate, frameState, keyIndex, ConstPoolType::STRING); - builder_.CallRuntime(glue, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef, - { receiverHC, newHolderHC, propKey }, gate); - builder_.Jump(¬Proto); - builder_.Bind(¬Proto); + if (compilationEnv_->IsAotCompiler()) { + auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET); + builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype); + } + if (!isPrototype) { + builder_.DeoptCheck(builder_.BoolNot(builder_.IsPrototypeHClass(receiverHC)), frameState, + DeoptType::PROTOTYPECHANGED2); + } else { + builder_.Branch(builder_.IsPrototypeHClass(receiverHC), &isProto, ¬Proto, + BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "isPrototypeHClass"); + builder_.Bind(&isProto); + + GateRef propKey = + builder_.GetObjectByIndexFromConstPool(glue, gate, frameState, keyIndex, ConstPoolType::STRING); + builder_.CallRuntime(glue, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef, + { receiverHC, newHolderHC, propKey }, gate); + builder_.Jump(¬Proto); + builder_.Bind(¬Proto); + } MemoryAttribute mAttr = MemoryAttribute::NeedBarrierAndAtomic(); builder_.StoreConstOffset(VariableType::JS_ANY(), receiver, TaggedObject::HCLASS_OFFSET, newHolderHC, mAttr); if (!plr.IsInlinedProps()) { @@ -3018,7 +3034,7 @@ void TypedHCRLowering::LowerStringFromSingleCharCode(GateRef gate, GateRef glue) builder_.Bind(¬Int); { value = builder_.TruncInt32ToInt16( - builder_.DoubleToInt(glue, builder_.GetDoubleOfTDouble(codePointValue), base::INT16_BITS)); + builder_.TruncDoubleToInt(glue, builder_.GetDoubleOfTDouble(codePointValue), base::INT16_BITS)); builder_.Jump(&newObj); } builder_.Bind(&newObj); diff --git a/ecmascript/compiler/typed_native_inline_lowering.cpp b/ecmascript/compiler/typed_native_inline_lowering.cpp index 544e79e1eb7e30a5d331a1fab5bd3f36ef0779fd..7c92e754aeaf0272b8e1734a02c55eb1e3072469 100644 --- a/ecmascript/compiler/typed_native_inline_lowering.cpp +++ b/ecmascript/compiler/typed_native_inline_lowering.cpp @@ -34,6 +34,7 @@ #include "ecmascript/compiler/type_info_accessors.h" #include "ecmascript/compiler/variable_type.h" #include "ecmascript/global_env.h" +#include "ecmascript/interpreter/interpreter-inl.h" #include "ecmascript/jit/jit.h" #include "ecmascript/js_array_iterator.h" #include "ecmascript/js_arraybuffer.h" @@ -360,6 +361,9 @@ GateRef TypedNativeInlineLowering::VisitGate(GateRef gate) case OpCode::ARRAY_POP: LowerArrayPop(gate); break; + case OpCode::ARRAY_PUSH: + LowerArrayPush(gate); + break; case OpCode::ARRAY_SLICE: LowerArraySlice(gate); break; @@ -1992,12 +1996,14 @@ void TypedNativeInlineLowering::LowerNumberParseInt(GateRef gate) builder_.Bind(&slowPath); { GateRef glue = acc_.GetGlueFromArgList(); - result = builder_.CallRuntime(glue, RTSTUB_ID(ParseInt), Gate::InvalidGateRef, { msg, arg2 }, gate); + // this may return exception + result = builder_.CallRuntime(glue, RTSTUB_ID(ParseInt), Gate::InvalidGateRef, {msg, arg2}, gate); builder_.Jump(&exit); } builder_.Bind(&exit); - acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result); + ReplaceGateWithPendingException( + gate, acc_.GetGlueFromArgList(), builder_.GetState(), builder_.GetDepend(), *result); } void TypedNativeInlineLowering::LowerNumberParseFloat(GateRef gate) @@ -2205,19 +2211,8 @@ void TypedNativeInlineLowering::LowerStringSubstring(GateRef gate) builder_.Jump(&next); builder_.Bind(&startTagNotInt); { - Label slowPath(&builder_); - Label fastPath(&builder_); - BRANCH_CIR(BuildTaggedPointerOverflowInt32(startTag), &slowPath, &fastPath); - builder_.Bind(&slowPath); - { - start = length; - builder_.Jump(&next); - } - builder_.Bind(&fastPath); - { - start = builder_.DoubleToInt(glue, builder_.GetDoubleOfTDouble(startTag), base::INT32_BITS); - builder_.Jump(&next); - } + start = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(startTag)); + builder_.Jump(&next); } } else { start = NumberToInt32(startTag); @@ -2232,19 +2227,8 @@ void TypedNativeInlineLowering::LowerStringSubstring(GateRef gate) builder_.Jump(&countStart); builder_.Bind(&endTagNotInt); { - Label slowPath(&builder_); - Label fastPath(&builder_); - BRANCH_CIR(BuildTaggedPointerOverflowInt32(endTag), &slowPath, &fastPath); - builder_.Bind(&slowPath); - { - end = length; - builder_.Jump(&countStart); - } - builder_.Bind(&fastPath); - { - end = builder_.DoubleToInt(glue, builder_.GetDoubleOfTDouble(endTag), base::INT32_BITS); - builder_.Jump(&countStart); - } + end = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(endTag)); + builder_.Jump(&countStart); } } else { end = NumberToInt32(endTag); @@ -2295,19 +2279,8 @@ void TypedNativeInlineLowering::LowerStringSubStr(GateRef gate) builder_.Jump(&next); builder_.Bind(&intStartNotInt); { - Label slowPath(&builder_); - Label fastPath(&builder_); - BRANCH_CIR(BuildTaggedPointerOverflowInt32(intStart), &slowPath, &fastPath); - builder_.Bind(&slowPath); - { - start = length; - builder_.Jump(&next); - } - builder_.Bind(&fastPath); - { - start = builder_.DoubleToInt(glue, builder_.GetDoubleOfTDouble(intStart), base::INT32_BITS); - builder_.Jump(&next); - } + start = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(intStart)); + builder_.Jump(&next); } } else { start = NumberToInt32(intStart); @@ -2322,19 +2295,8 @@ void TypedNativeInlineLowering::LowerStringSubStr(GateRef gate) builder_.Jump(&countStart); builder_.Bind(&lengthTagNotInt); { - Label slowPath(&builder_); - Label fastPath(&builder_); - BRANCH_CIR(BuildTaggedPointerOverflowInt32(lengthTag), &slowPath, &fastPath); - builder_.Bind(&slowPath); - { - end = length; - builder_.Jump(&countStart); - } - builder_.Bind(&fastPath); - { - end = builder_.DoubleToInt(glue, builder_.GetDoubleOfTDouble(lengthTag), base::INT32_BITS); - builder_.Jump(&countStart); - } + end = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(lengthTag)); + builder_.Jump(&countStart); } } else { end = NumberToInt32(lengthTag); @@ -2411,19 +2373,8 @@ void TypedNativeInlineLowering::LowerStringSlice(GateRef gate) builder_.Jump(&next); builder_.Bind(&startTagNotInt); { - Label slowPath(&builder_); - Label fastPath(&builder_); - BRANCH_CIR(BuildTaggedPointerOverflowInt32(startTag), &slowPath, &fastPath); - builder_.Bind(&slowPath); - { - start = length; - builder_.Jump(&next); - } - builder_.Bind(&fastPath); - { - start = builder_.DoubleToInt(glue, builder_.GetDoubleOfTDouble(startTag), base::INT32_BITS); - builder_.Jump(&next); - } + start = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(startTag)); + builder_.Jump(&next); } } else { start = NumberToInt32(startTag); @@ -2437,7 +2388,7 @@ void TypedNativeInlineLowering::LowerStringSlice(GateRef gate) end = builder_.GetInt32OfTInt(endTag); builder_.Jump(&countStart); builder_.Bind(&endTagNotInt); - end = builder_.DoubleToInt(glue, builder_.GetDoubleOfTDouble(endTag), base::INT32_BITS); + end = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(endTag)); builder_.Jump(&countStart); } else { end = NumberToInt32(endTag); @@ -2503,7 +2454,12 @@ GateRef TypedNativeInlineLowering::NumberToInt32(GateRef gate) case MachineType::I32: return gate; case MachineType::F64: - return builder_.ChangeFloat64ToInt32(gate); + if (isLiteCG_) { + return builder_.ChangeFloat64ToInt32(gate); + } else { + GateRef glue = acc_.GetGlueFromArgList(); + return builder_.SaturateTruncDoubleToInt32(glue, gate); + } case MachineType::I1: return builder_.ZExtInt1ToInt32(gate); default: @@ -3730,6 +3686,44 @@ void TypedNativeInlineLowering::LowerArrayPop(GateRef gate) acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *ret); } +void TypedNativeInlineLowering::LowerArrayPush(GateRef gate) +{ + Environment env(gate, circuit_, &builder_); + Label grow(&builder_); + Label setValue(&builder_); + Label setLength(&builder_); + Label exit(&builder_); + BuiltinsArrayStubBuilder arrayBuilder(&env); + GateRef thisValue = acc_.GetValueIn(gate, 0); + GateRef value = acc_.GetValueIn(gate, 1); + GateRef oldLength = builder_.GetLengthOfJSArray(thisValue); + GateRef glue = acc_.GetGlueFromArgList(); + DEFVALUE(ret, (&builder_), VariableType::JS_ANY(), builder_.Int32ToTaggedPtr(thisValue)); + DEFVALUE(elements, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant()); + GateRef newLength = builder_.Int32Add(oldLength, builder_.Int32(1)); + elements = builder_.GetElementsArray(thisValue); + GateRef capacity = builder_.GetLengthOfTaggedArray(*elements); + BRANCH_CIR(builder_.Int32GreaterThan(newLength, capacity), &grow, &setValue); + builder_.Bind(&grow); + { + elements = builder_.CallStub(glue, gate, CommonStubCSigns::GrowElementsCapacity, {glue, thisValue, newLength}); + builder_.Jump(&setValue); + } + builder_.Bind(&setValue); + { + arrayBuilder.FastSetValueWithElementsKind(glue, thisValue, *elements, value, oldLength, ElementsKind::NONE); + builder_.Jump(&setLength); + } + builder_.Bind(&setLength); + { + arrayBuilder.SetArrayLength(glue, thisValue, newLength); + ret = arrayBuilder.IntToTaggedPtr(newLength); + builder_.Jump(&exit); + } + builder_.Bind(&exit); + ReplaceGateWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *ret); +} + void TypedNativeInlineLowering::LowerArraySlice(GateRef gate) { Environment env(gate, circuit_, &builder_); diff --git a/ecmascript/compiler/typed_native_inline_lowering.h b/ecmascript/compiler/typed_native_inline_lowering.h index c141ae2d2d7719306a7119b6cb986728944ffde3..ddeaf4b3a56007619b7bc24709fb031296799163 100644 --- a/ecmascript/compiler/typed_native_inline_lowering.h +++ b/ecmascript/compiler/typed_native_inline_lowering.h @@ -193,6 +193,7 @@ private: void LowerArraySome(GateRef gate); void LowerArrayEvery(GateRef gate); void LowerArrayPop(GateRef gate); + void LowerArrayPush(GateRef gate); void LowerArraySlice(GateRef gate); void CheckAndCalcuSliceIndex(GateRef length, GateRef startHandler, diff --git a/ecmascript/containers/containers_bitvector.cpp b/ecmascript/containers/containers_bitvector.cpp index ae66e01eb6d2a4d09d6047d4f4fe0d4be034acb2..a29d48c455c6270d03ddba87a4faee4924612f65 100644 --- a/ecmascript/containers/containers_bitvector.cpp +++ b/ecmascript/containers/containers_bitvector.cpp @@ -34,8 +34,10 @@ JSTaggedValue ContainersBitVector::BitVectorConstructor(EcmaRuntimeCallInfo* arg THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } JSHandle constructor = GetConstructor(argv); + ASSERT(constructor->IsJSSharedFunction() && constructor.GetTaggedValue().IsInSharedHeap()); JSHandle obj = JSHandle(factory->NewJSObjectByConstructor(JSHandle(constructor), newTarget)); + ASSERT(obj.GetTaggedValue().IsInSharedHeap()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle length = GetCallArg(argv, 0); @@ -49,15 +51,16 @@ JSTaggedValue ContainersBitVector::BitVectorConstructor(EcmaRuntimeCallInfo* arg auto* newBitSetVector = new std::vector>(); if (!length->IsZero()) { - int32_t capacity = (length->GetInt() / JSAPIBitVector::BIT_SET_LENGTH) + 1; + int32_t capacity = std::max(0, (length->GetInt() / JSAPIBitVector::BIT_SET_LENGTH) + 1); std::bitset initBitSet; newBitSetVector->resize(capacity, initBitSet); } - JSHandle pointer = factory->NewJSNativePointer(newBitSetVector, - ContainersBitVector::FreeBitsetVectorPointer); + JSHandle pointer = factory->NewSJSNativePointer(newBitSetVector, + ContainersBitVector::FreeBitsetVectorPointer, + newBitSetVector); obj->SetNativePointer(thread, pointer); - obj->SetLength(length->GetInt()); + obj->SetLength(std::max(0, length->GetInt())); return obj.GetTaggedValue(); } diff --git a/ecmascript/containers/containers_bitvector.h b/ecmascript/containers/containers_bitvector.h index 9a83f88cd2e9eb2924d2901c09701345d8d31b13..4113dbf077b5fc86d625e2e45327b41f970bf310 100644 --- a/ecmascript/containers/containers_bitvector.h +++ b/ecmascript/containers/containers_bitvector.h @@ -19,6 +19,21 @@ #include "ecmascript/base/builtins_base.h" #include "ecmascript/ecma_runtime_call_info.h" +#define BUILTIN_BITVECTOR_PROTOTYPE_FUNCTIONS(V) \ + V("push", Push, 1, INVALID) \ + V("pop", Pop, 0, INVALID) \ + V("has", Has, 3, INVALID) \ + V("setBitsByRange", SetBitsByRange, 3, INVALID) \ + V("getBitsByRange", GetBitsByRange, 2, INVALID) \ + V("setAllBits", SetAllBits, 1, INVALID) \ + V("resize", Resize, 1, INVALID) \ + V("getBitCountByRange", GetBitCountByRange, 3, INVALID) \ + V("getIndexOf", GetIndexOf, 3, INVALID) \ + V("getLastIndexOf", GetLastIndexOf, 3, INVALID) \ + V("flipBitByIndex", FlipBitByIndex, 1, INVALID) \ + V("flipBitsByRange", FlipBitsByRange, 2, INVALID) \ + V("values", GetIteratorObj, 0, INVALID) + namespace panda::ecmascript::containers { class ContainersBitVector : public base::BuiltinsBase { public: @@ -37,8 +52,63 @@ public: static JSTaggedValue GetIteratorObj(EcmaRuntimeCallInfo* argv); static JSTaggedValue GetSize(EcmaRuntimeCallInfo* argv); static JSTaggedValue SetAllBits(EcmaRuntimeCallInfo* argv); + + // Excluding the constructor and '@@' internal properties. + static Span GetBitVectorPrototypeFunctions() + { + return Span(BITVECTOR_PROTOTYPE_FUNCTIONS); + } + + static size_t GetNumPrototypeInlinedProperties() + { + // 4 : 4 more inline properties in BitVector.prototype + // (1) BitVector.prototype.constructor + // (2) BitVector.prototype [ @@toStringTag ] + // (3) BitVector.prototype [ @@iterator ] + // (4) get BitVector.prototype.size + // (5) get BitVector.prototype.length + return GetBitVectorPrototypeFunctions().Size() + 5; + } + + static Span> GetPrototypeProperties() + { + return Span>(BITVECTOR_PROTOTYPE_PROPERTIES); + } + + static Span> GetFunctionProperties() + { + return Span>(BITVECTOR_FUNCTION_PROPERTIES); + } private: static void FreeBitsetVectorPointer([[maybe_unused]] void *env, void *pointer, void *data); + +#define BUILTIN_BITVECTOR_FUNCTION_ENTRY(name, func, length, id) \ + base::BuiltinFunctionEntry::Create(name, ContainersBitVector::func, length, kungfu::BuiltinsStubCSigns::id), + + static constexpr std::array BITVECTOR_PROTOTYPE_FUNCTIONS = { + BUILTIN_BITVECTOR_PROTOTYPE_FUNCTIONS(BUILTIN_BITVECTOR_FUNCTION_ENTRY) + }; +#undef BUILTIN_BITVECTOR_FUNCTION_ENTRY + +#define BITVECTOR_PROPERTIES_PAIR(name, func, length, id) \ + std::pair(name, false), + + static constexpr std::array BITVECTOR_PROTOTYPE_PROPERTIES = { + std::pair("constructor", false), + BUILTIN_BITVECTOR_PROTOTYPE_FUNCTIONS(BITVECTOR_PROPERTIES_PAIR) + std::pair("[Symbol.toStringTag]", false), + std::pair("length", true), + std::pair("size", true), + std::pair("[Symbol.iterator]", false) + }; + + static constexpr std::array BITVECTOR_FUNCTION_PROPERTIES = { + std::pair("length", false), + std::pair("name", false), + std::pair("prototype", false), + std::pair("[Symbol.species]", true), + }; +#undef BITVECTOR_PROPERTIES_PAIR }; } // namespace panda::ecmascript::containers #endif // ECMASCRIPT_CONTAINERS_CONTAINERS_BIT_VECTOR_H diff --git a/ecmascript/containers/containers_private.cpp b/ecmascript/containers/containers_private.cpp index 97b385d3325303e9e58811b67b1db39bae675016..545dd1740dacb52ba4bed85a2e965ceac9bc68fd 100644 --- a/ecmascript/containers/containers_private.cpp +++ b/ecmascript/containers/containers_private.cpp @@ -30,6 +30,7 @@ #include "containers_treemap.h" #include "containers_treeset.h" #include "containers_vector.h" +#include "ecmascript/global_env_fields.h" #include "ecmascript/js_api/js_api_arraylist_iterator.h" #include "ecmascript/js_api/js_api_bitvector_iterator.h" #include "ecmascript/js_api/js_api_deque_iterator.h" @@ -50,6 +51,7 @@ #include "ecmascript/js_api/js_api_tree_set_iterator.h" #include "ecmascript/js_api/js_api_tree_set.h" #include "ecmascript/js_api/js_api_vector_iterator.h" +#include "ecmascript/builtins/builtins.h" #include "ecmascript/object_fast_operator-inl.h" namespace panda::ecmascript::containers { @@ -195,7 +197,9 @@ void ContainersPrivate::SetFrozenFunction(JSThread *thread, const JSHandle &obj, const char *keyChar, JSHandle &value) { - JSObject::PreventExtensions(thread, JSHandle::Cast(value)); + if (value->IsECMAObject()) { + JSObject::PreventExtensions(thread, JSHandle::Cast(value)); + } ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle key(factory->NewFromASCII(keyChar)); PropertyDescriptor descriptor(thread, value, false, false, false); @@ -849,53 +853,15 @@ void ContainersPrivate::InitializeVectorIterator(JSThread *thread, const JSHandl JSHandle ContainersPrivate::InitializeBitVector(JSThread* thread) { auto globalConst = const_cast(thread->GlobalConstants()); - ObjectFactory* factory = thread->GetEcmaVM()->GetFactory(); - // BitVector.prototype - JSHandle prototype = factory->NewEmptyJSObject(); - JSHandle bitVectorFuncPrototypeValue(prototype); - // BitVector.prototype_or_hclass - JSHandle bitVectorInstanceClass = - factory->NewEcmaHClass(JSAPIBitVector::SIZE, JSType::JS_API_BITVECTOR, bitVectorFuncPrototypeValue); - // BitVector() = new Function() - JSHandle bitVectorFunction(NewContainerConstructor( - thread, prototype, ContainersBitVector::BitVectorConstructor, "BitVector", FuncLength::ONE)); - JSFunction::SetFunctionPrototypeOrInstanceHClass( - thread, JSHandle::Cast(bitVectorFunction), bitVectorInstanceClass.GetTaggedValue()); - - // "constructor" property on the prototype - JSHandle constructorKey = globalConst->GetHandledConstructorString(); - JSObject::SetProperty(thread, JSHandle(prototype), constructorKey, bitVectorFunction); - RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); - - // BitVector.prototype - SetFrozenFunction(thread, prototype, "push", ContainersBitVector::Push, FuncLength::ONE); - SetFrozenFunction(thread, prototype, "pop", ContainersBitVector::Pop, FuncLength::ZERO); - SetFrozenFunction(thread, prototype, "has", ContainersBitVector::Has, FuncLength::THREE); - SetFrozenFunction(thread, prototype, "setBitsByRange", ContainersBitVector::SetBitsByRange, FuncLength::THREE); - SetFrozenFunction(thread, prototype, "getBitsByRange", ContainersBitVector::GetBitsByRange, FuncLength::TWO); - SetFrozenFunction(thread, prototype, "setAllBits", ContainersBitVector::SetAllBits, FuncLength::ONE); - SetFrozenFunction(thread, prototype, "resize", ContainersBitVector::Resize, FuncLength::ONE); - SetFrozenFunction( - thread, prototype, "getBitCountByRange", ContainersBitVector::GetBitCountByRange, FuncLength::THREE); - SetFrozenFunction(thread, prototype, "getIndexOf", ContainersBitVector::GetIndexOf, FuncLength::THREE); - SetFrozenFunction(thread, prototype, "getLastIndexOf", ContainersBitVector::GetLastIndexOf, FuncLength::THREE); - SetFrozenFunction(thread, prototype, "flipBitByIndex", ContainersBitVector::FlipBitByIndex, FuncLength::ONE); - SetFrozenFunction(thread, prototype, "flipBitsByRange", ContainersBitVector::FlipBitsByRange, FuncLength::TWO); - SetFrozenFunction(thread, prototype, "values", ContainersBitVector::GetIteratorObj, FuncLength::ZERO); - - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - SetStringTagSymbol(thread, env, prototype, "BitVector"); - - JSHandle lengthGetter = - CreateGetter(thread, ContainersBitVector::GetSize, "length", FuncLength::ZERO); - JSHandle lengthKey(thread, globalConst->GetLengthString()); - SetGetter(thread, prototype, lengthKey, lengthGetter); - - SetFunctionAtSymbol(thread, env, prototype, env->GetIteratorSymbol(), "[Symbol.iterator]", - ContainersBitVector::GetIteratorObj, FuncLength::ONE); - ContainersPrivate::InitializeBitVectorIterator(thread, env, globalConst); - - globalConst->SetConstant(ConstantIndex::BITVECTOR_FUNCTION_INDEX, bitVectorFunction.GetTaggedValue()); + auto vm = thread->GetEcmaVM(); + ObjectFactory* factory = vm->GetFactory(); + JSHandle env = vm->GetGlobalEnv(); + Builtins builtin(thread, factory, vm); + JSHandle sObjPrototype = JSHandle::Cast(env->GetSObjectFunctionPrototype()); + JSHandle sFuncPrototype = JSHandle::Cast(env->GetSFunctionPrototype()); + builtin.InitializeSharedBitVector(env, sObjPrototype, sFuncPrototype); + InitializeBitVectorIterator(thread, env, globalConst); + JSHandle bitVectorFunction = env->GetBitVectorFunction(); return bitVectorFunction; } @@ -903,15 +869,13 @@ void ContainersPrivate::InitializeBitVectorIterator( JSThread* thread, const JSHandle& env, GlobalEnvConstants* globalConst) { ObjectFactory* factory = thread->GetEcmaVM()->GetFactory(); - JSHandle iteratorFuncHClass = - JSHandle(thread, globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject()); - // BitVectorIterator.prototype - JSHandle bitVectorIteratorPrototype(factory->NewJSObject(iteratorFuncHClass)); + JSHandle iteratorFuncClass = JSHandle(thread, + globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject()); + JSHandle bitVectorIteratorPrototype(factory->NewJSObjectWithInit(iteratorFuncClass)); // Iterator.prototype.next() SetFrozenFunction(thread, bitVectorIteratorPrototype, "next", JSAPIBitVectorIterator::Next, FuncLength::ONE); SetStringTagSymbol(thread, env, bitVectorIteratorPrototype, "BitVector Iterator"); - globalConst->SetConstant( - ConstantIndex::BITVECTOR_ITERATOR_PROTOTYPE_INDEX, bitVectorIteratorPrototype.GetTaggedValue()); + env->SetBitVectorIteratorPrototype(thread, bitVectorIteratorPrototype); } JSHandle ContainersPrivate::InitializeQueue(JSThread *thread) diff --git a/ecmascript/containers/tests/BUILD.gn b/ecmascript/containers/tests/BUILD.gn index 71d736a0d3ac67de9f67f9004ecc021883bbef09..6429bfbe907946b27b59acebb4d4776f49704df9 100644 --- a/ecmascript/containers/tests/BUILD.gn +++ b/ecmascript/containers/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("Containers_001_Test") { module_out_path = module_output_path diff --git a/ecmascript/debugger/tests/BUILD.gn b/ecmascript/debugger/tests/BUILD.gn index 5abb9b2f1d6c905333af4356f419c8169957b704..29cf6d757331134935f3f67d1f11d7a883067460 100644 --- a/ecmascript/debugger/tests/BUILD.gn +++ b/ecmascript/debugger/tests/BUILD.gn @@ -22,7 +22,7 @@ test_js_files = [ "patch/index", ] -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" foreach(file, test_js_files) { es2abc_gen_abc("gen_${file}_abc") { diff --git a/ecmascript/dfx/cpu_profiler/tests/BUILD.gn b/ecmascript/dfx/cpu_profiler/tests/BUILD.gn index c454d56d2545b93c7c0bc4c8d0bbc5438aed3d06..668df6b797b8ca0d260e969355549748f0842ae3 100755 --- a/ecmascript/dfx/cpu_profiler/tests/BUILD.gn +++ b/ecmascript/dfx/cpu_profiler/tests/BUILD.gn @@ -35,7 +35,7 @@ foreach(file, test_js_files) { } } -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("CpuProfilerTest") { module_out_path = module_output_path diff --git a/ecmascript/dfx/hprof/heap_profiler.cpp b/ecmascript/dfx/hprof/heap_profiler.cpp index 1839e566449fa13c16297d72dac0b295a8b377bb..54635eb35c5a1aa2cae899e71d84aa3d939c4325 100644 --- a/ecmascript/dfx/hprof/heap_profiler.cpp +++ b/ecmascript/dfx/hprof/heap_profiler.cpp @@ -94,6 +94,7 @@ bool EntryIdMap::Move(JSTaggedType oldAddr, JSTaggedType forwardAddr) void EntryIdMap::UpdateEntryIdMap(HeapSnapshot *snapshot) { + LOG_ECMA(INFO) << "EntryIdMap::UpdateEntryIdMap"; if (snapshot == nullptr) { LOG_ECMA(FATAL) << "EntryIdMap::UpdateEntryIdMap:snapshot is nullptr"; UNREACHABLE(); @@ -152,7 +153,8 @@ void HeapProfiler::UpdateHeapObjects(HeapSnapshot *snapshot) snapshot->UpdateNodes(); } -void HeapProfiler::DumpHeapSnapshot([[maybe_unused]] const DumpSnapShotOption &dumpOption) +void HeapProfiler::DumpHeapSnapshotForOOM([[maybe_unused]] const DumpSnapShotOption &dumpOption, + [[maybe_unused]] bool fromSharedGC) { #if defined(ENABLE_DUMP_IN_FAULTLOG) // Write in faultlog for heap leak. @@ -167,10 +169,27 @@ void HeapProfiler::DumpHeapSnapshot([[maybe_unused]] const DumpSnapShotOption &d return; } FileDescriptorStream stream(fd); - DumpHeapSnapshot(&stream, dumpOption); + if (!fromSharedGC) { + DumpHeapSnapshot(&stream, dumpOption); + } else { + DumpHeapSnapshotFromSharedGC(&stream, dumpOption); + } #endif } +void HeapProfiler::DumpHeapSnapshotFromSharedGC(Stream *stream, const DumpSnapShotOption &dumpOption) +{ + base::BlockHookScope blockScope; + const_cast(vm_->GetHeap())->Prepare(); + SharedHeap::GetInstance()->Prepare(true); + Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) { + ASSERT(!thread->IsInRunningState()); + const_cast(thread->GetEcmaVM()->GetHeap())->FillBumpPointerForTlab(); + }); + BinaryDump(stream, dumpOption); + stream->EndOfStream(); +} + bool HeapProfiler::DoDump(Stream *stream, Progress *progress, const DumpSnapShotOption &dumpOption) { DISALLOW_GARBAGE_COLLECTION; @@ -204,69 +223,6 @@ bool HeapProfiler::DoDump(Stream *stream, Progress *progress, const DumpSnapShot return serializerResult; } -ChunkDecoder::ChunkDecoder(char *mAddr, uint64_t fSize) : mapAddr(mAddr), fileSize(fSize) -{ - auto u64Ptr = reinterpret_cast(mapAddr); - size_t currInd = 0; - heapObjCnt = u64Ptr[currInd++]; - rootObjCnt = u64Ptr[currInd++]; - shareObjCnt = u64Ptr[currInd++]; - strTableOffset = u64Ptr[currInd++]; - LOG_ECMA(INFO) << "ChunkDecoder init: heapObjCnt=" << heapObjCnt << ", rootObjCnt=" << rootObjCnt - << ", ShareObjCnt=" << shareObjCnt << std::hex << ", strTableOffset=0x" << strTableOffset; - auto cPtr = mapAddr; - CUnorderedSet rootAddrSet; - for (uint64_t i = 0; i < rootObjCnt; i++) { - rootAddrSet.insert(u64Ptr[currInd++]); - } - auto &objInfoVec = rawHeapArgs.rawObjInfoVec; - auto table = reinterpret_cast(&u64Ptr[currInd]); - for (uint64_t i = 0; i < heapObjCnt; ++i) { - auto objInfo = new RawHeapObjInfo(); - objInfo->tInfo = &table[i]; - if (rootAddrSet.find(objInfo->tInfo->addr) != rootAddrSet.end()) { - objInfo->isRoot = true; - } else { - objInfo->isRoot = false; - } - objInfoVec.push_back(objInfo); - auto objMem = cPtr + objInfo->tInfo->offset; - objInfo->newAddr = objMem; - rawHeapArgs.oldAddrMapObjInfo.emplace(objInfo->tInfo->addr, objInfo); - } - DecodeStrTable(cPtr); -} - -void ChunkDecoder::DecodeStrTable(const char *charPtr) -{ - auto currInd = strTableOffset; - if (currInd >= fileSize) { - LOG_ECMA(ERROR) << "DecodeStrTable no str table: str=" << charPtr; - return; - } - auto &strTableIdMap = rawHeapArgs.strTableIdMapNewStr; - - auto u64Ptr = reinterpret_cast(charPtr + currInd); - auto strCnt = *u64Ptr; - LOG_ECMA(INFO) << "DecodeStrTable: strCnt=" << std::dec << strCnt; - while (currInd < fileSize && strTableIdMap.size() < strCnt) { - auto id = *reinterpret_cast(charPtr + currInd); - currInd += sizeof(uint64_t); - if (currInd >= fileSize) { - break; - } - auto *currPtr = &charPtr[currInd]; - auto currSize = strlen(currPtr) + 1; - if (currSize == 1) { - currInd += currSize; - continue; - } - strTableIdMap[id] = currPtr; - currInd += currSize; - } - LOG_ECMA(INFO) << "DecodeStrTable finished: strTableVec.size=" << strTableIdMap.size(); -} - static uint64_t CheckAndRemoveWeak(JSTaggedValue &value, uint64_t originalAddr) { if (!value.IsWeak()) { @@ -287,52 +243,75 @@ static uint64_t CheckAndAddWeak(JSTaggedValue &value, uint64_t originalAddr) return weakValue.GetRawData(); } -void DecodeObj(RawHeapInfoArgs &rawHeapArgs, HeapSnapshot *snapshot) +static uint64_t VisitMember(ObjectSlot &slot, uint64_t objAddr, CUnorderedSet ¬FoundObj, + JSHClass *jsHclass, CUnorderedMap &objMap) +{ + auto taggedPointerAddr = reinterpret_cast(slot.SlotAddress()); + JSTaggedValue value(reinterpret_cast(*taggedPointerAddr)); + auto originalAddr = reinterpret_cast(*taggedPointerAddr); + originalAddr = CheckAndRemoveWeak(value, originalAddr); + if (!value.IsHeapObject() || originalAddr == 0) { + return 0LL; + } + auto toItemInfo = objMap.find(originalAddr); + if (toItemInfo == objMap.end()) { + LOG_ECMA(ERROR) << "ark raw heap decode visit " << std::hex << objAddr << ", type=" + << JSHClass::DumpJSType(jsHclass->GetObjectType()) + << ", not found member old addr=" << originalAddr; + notFoundObj.insert(reinterpret_cast(*taggedPointerAddr)); + return 0LL; + } + auto newAddr = reinterpret_cast(toItemInfo->second->Data()); + newAddr = CheckAndAddWeak(value, newAddr); + slot.Update(reinterpret_cast(newAddr)); + return newAddr; +} + +CUnorderedMap> VisitObj(CUnorderedMap &objMap) { - std::set notFoundObj; - CUnorderedSet *refVec = nullptr; - auto visitor = [¬FoundObj, &rawHeapArgs, &refVec] ([[maybe_unused]] TaggedObject *root, - ObjectSlot start, ObjectSlot end, VisitObjectArea area) { + CUnorderedSet notFoundObj; + CUnorderedMap> refSetMap; // old addr map to ref set + auto visitor = [¬FoundObj, &objMap, &refSetMap] (TaggedObject *root, ObjectSlot start, + ObjectSlot end, VisitObjectArea area) { if (area == VisitObjectArea::RAW_DATA || area == VisitObjectArea::NATIVE_POINTER) { return; } + auto jsHclass = root->GetClass(); + auto objAddr = reinterpret_cast(root); + CUnorderedSet *refSet = nullptr; + if (refSetMap.find(objAddr) != refSetMap.end()) { + refSet = &refSetMap[objAddr]; + } for (ObjectSlot slot = start; slot < end; slot++) { - auto taggedPointerAddr = reinterpret_cast(slot.SlotAddress()); - JSTaggedValue value(reinterpret_cast(*taggedPointerAddr)); - auto originalAddr = reinterpret_cast(*taggedPointerAddr); - originalAddr = CheckAndRemoveWeak(value, originalAddr); - if (!value.IsHeapObject() || originalAddr == 0) { - continue; + auto newAddr = VisitMember(slot, objAddr, notFoundObj, jsHclass, objMap); + if (jsHclass->IsJsGlobalEnv() && refSet != nullptr && newAddr != 0LL) { + refSet->insert(newAddr); } - auto toItemInfo = rawHeapArgs.oldAddrMapObjInfo.find(originalAddr); - if (toItemInfo == rawHeapArgs.oldAddrMapObjInfo.end()) { - notFoundObj.insert(reinterpret_cast(*taggedPointerAddr)); - continue; - } - auto newAddr = reinterpret_cast(toItemInfo->second->newAddr); - newAddr = CheckAndAddWeak(value, newAddr); - refVec->insert(newAddr); - slot.Update(reinterpret_cast(newAddr)); } }; - for (auto v : rawHeapArgs.rawObjInfoVec) { - refVec = &v->refSet; - auto jsHclassAddr = *reinterpret_cast(v->newAddr); - auto jsHclassItem = rawHeapArgs.oldAddrMapObjInfo.find(jsHclassAddr); - if (jsHclassItem == rawHeapArgs.oldAddrMapObjInfo.end()) { - LOG_ECMA(ERROR) << "ark DecodeObj hclass not find jsHclassAddr=" << std::hex << jsHclassAddr; + for (auto objInfo : objMap) { + auto newAddr = objInfo.second->Data(); + auto jsHclassAddr = *reinterpret_cast(newAddr); + auto jsHclassItem = objMap.find(jsHclassAddr); + if (jsHclassItem == objMap.end()) { + LOG_ECMA(ERROR) << "ark raw heap decode hclass not find jsHclassAddr=" << std::hex << jsHclassAddr; + continue; + } + TaggedObject *obj = reinterpret_cast(newAddr); + *reinterpret_cast(newAddr) = reinterpret_cast(jsHclassItem->second->Data()); + auto jsHclass = reinterpret_cast(jsHclassItem->second->Data()); + if (jsHclass->IsString()) { continue; } - TaggedObject *obj = reinterpret_cast(v->newAddr); - *reinterpret_cast(v->newAddr) = reinterpret_cast(jsHclassItem->second->newAddr); - auto hclassObj = reinterpret_cast(jsHclassItem->second->newAddr); - ObjectXRay::VisitObjectBody(obj, hclassObj, visitor); + if (jsHclass->IsJsGlobalEnv()) { + refSetMap.emplace(reinterpret_cast(newAddr), CUnorderedSet()); + } + ObjectXRay::VisitObjectBody(obj, jsHclass, visitor); } - LOG_ECMA(INFO) << "ark visitor: not found obj num= " << notFoundObj.size() << ", generate nodes"; - for (auto v : rawHeapArgs.rawObjInfoVec) { - TaggedObject *obj = reinterpret_cast(v->newAddr); - snapshot->GenerateNodeForBinMod(obj, v, rawHeapArgs.strTableIdMapNewStr); + if (notFoundObj.size() > 0) { + LOG_ECMA(ERROR) << "ark raw heap decode visit obj: not found obj num=" << notFoundObj.size(); } + return refSetMap; } static uint64_t GetFileSize(std::string &inputFilePath) @@ -347,53 +326,225 @@ static uint64_t GetFileSize(std::string &inputFilePath) return 0; } -bool HeapProfiler::GenerateHeapSnapshot(std::string &inputFilePath, std::string &outputPath) +bool ReadFileAtOffset(std::ifstream &file, uint32_t offset, char *buf, uint32_t size) +{ + if (buf == nullptr) { + LOG_ECMA(ERROR) << "ark raw heap decode file buf is nullptr"; + return false; + } + if (!file.is_open()) { + LOG_ECMA(ERROR) << "ark raw heap decode file not open"; + return false; + } + file.clear(); + if (!file.seekg(offset)) { + LOG_ECMA(ERROR) << "ark raw heap decode file set offset failed, offset=" << offset; + return false; + } + if (file.read(buf, size).fail()) { + LOG_ECMA(ERROR) << "ark raw heap decode file read failed, offset=" << offset; + return false; + } + return true; +} + +CUnorderedMap DecodeMemObj(std::ifstream &file, CVector §ions) +{ + CUnorderedMap objMap; // old addr map to new obj + uint32_t heapTotalSize = 0; + uint32_t objTotalNum = 0; + for (uint32_t sec = 4; sec + 1 < sections.size(); sec += 2) { // 2 :step is 2 + uint32_t offset = sections[sec]; + uint32_t secHead[2]; + if (!ReadFileAtOffset(file, offset, reinterpret_cast(secHead), sizeof(secHead))) { + LOG_ECMA(ERROR) << "ark raw heap decode read obj section failed, sec=" << sec << ", offset=" + << offset << ", size=" << sections[sec + 1]; + return objMap; + } + LOG_ECMA(INFO) << "ark raw heap decode read obj section failed, sec=" << sec << ", offset=" << offset + << ", size=" << sections[sec + 1] << ", obj num=" << secHead[0]; + auto tbSize = secHead[0] * sizeof(AddrTableItem); + if (secHead[1] != sizeof(AddrTableItem) || tbSize == 0 || tbSize > MAX_OBJ_SIZE) { + LOG_ECMA(ERROR) << "ark raw heap decode check obj table section=" << sections[sec] << ", head size=" + << sizeof(AddrTableItem) << ", but=" << secHead[1] << "or error table size=" << tbSize; + continue; + } + CVector objTabBuf(tbSize); + file.read(objTabBuf.data(), tbSize); + auto objTab = reinterpret_cast(objTabBuf.data()); + offset += sizeof(secHead); + objTotalNum += secHead[0]; + for (uint32_t i = 0; i < secHead[0]; i++) { + heapTotalSize += objTab[i].objSize; + auto actSize = i + 1 < secHead[0] ? objTab[i + 1].offset - objTab[i].offset : + sections[sec + 1] - objTab[i].offset - sizeof(secHead); + if (actSize != objTab[i].objSize && actSize != sizeof(uint64_t)) { + auto tabOffset = offset + i * sizeof(AddrTableItem); + LOG_ECMA(ERROR) << "ark raw heap decode check obj size i=" << i << std::hex << ", offset=" << tabOffset + << ", addr=" << objTab[i].addr << ", size=" << objTab[i].objSize << " but=" << actSize; + continue; + } + objMap.emplace(objTab[i].addr, new NewAddr(actSize, objTab[i].objSize)); + auto result = ReadFileAtOffset(file, offset + objTab[i].offset, objMap[objTab[i].addr]->Data(), actSize); + if (!result) { + LOG_ECMA(ERROR) << "ark raw heap decode read failed, i=" << i << ", base offset=" << offset + << ", obj addr=" << objTab[i].addr << ", read size=" << actSize; + return objMap; + } + } + } + LOG_ECMA(INFO) << "ark raw heap decode read obj, num=" << objTotalNum << ", size=" << heapTotalSize; + return objMap; +} + +CUnorderedMap DecodeStrTable(StringHashMap *strTable, std::ifstream &file, + uint32_t offset, uint32_t secSize) +{ + uint32_t secHead[2]; + if (!ReadFileAtOffset(file, offset, reinterpret_cast(secHead), sizeof(secHead))) { + LOG_ECMA(ERROR) << "ark raw heap decode read str table failed, offset=" << offset << ", size=" << secSize; + return CUnorderedMap(0); + } + uint32_t byteNum = secSize - sizeof(secHead); + char *charPtr = new char[byteNum]; + file.read(charPtr, byteNum); + CUnorderedMap strTabMap; // old addr map to str id + uint32_t cnt = 0; + uint32_t baseOff = 0; + while (cnt++ < secHead[0]) { + uint32_t *u32Ptr = reinterpret_cast(charPtr + baseOff); + auto strOffset = (u32Ptr[1] + 1) * sizeof(uint64_t) + baseOff; + auto getSize = strlen(charPtr + strOffset); + if (u32Ptr[0] != getSize) { + LOG_ECMA(ERROR) << cnt << " ark raw heap decode check str size=" << u32Ptr[0] << ", but=" << getSize<<"\n"; + } + auto strAddr = strTable->GetString(charPtr + strOffset); + uint32_t num = 0; + uint64_t *u64Ptr = reinterpret_cast(&u32Ptr[2]); + while (num < u32Ptr[1]) { + strTabMap[u64Ptr[num]] = strAddr; + num++; + } + baseOff = strOffset + u32Ptr[0] + 1; + } + delete[] charPtr; + LOG_ECMA(INFO) << "ark raw heap decode string table size=" << strTable->GetCapcity(); + return strTabMap; +} + +CUnorderedSet DecodeRootTable(std::ifstream &file, uint32_t offset, uint32_t secSize) +{ + uint32_t secHead[2]; + if (!ReadFileAtOffset(file, offset, reinterpret_cast(secHead), sizeof(secHead))) { + LOG_ECMA(ERROR) << "ark raw heap decode read root table failed, offset=" << offset << ", size=" << secSize; + return CUnorderedSet(0); + } + if (secHead[1] != sizeof(uint64_t)) { + LOG_ECMA(ERROR) << "ark raw heap decode error root size, need=" << sizeof(uint32_t) << ", but=" << secHead[0]; + return CUnorderedSet(0); + } + auto checkSize = sizeof(uint64_t) * secHead[0] + sizeof(secHead); + if (secSize != checkSize) { + LOG_ECMA(ERROR) << "ark raw heap decode check root section size=" << secSize << ", but=" << checkSize; + return CUnorderedSet(0); + } + CVector rootVec(secHead[0]); + file.read(reinterpret_cast(rootVec.data()), sizeof(uint64_t) * secHead[0]); + CUnorderedSet rootSet; + for (auto addr : rootVec) { + rootSet.insert(addr); + } + LOG_ECMA(INFO) << "ark raw heap decode root obj num=" << rootSet.size(); + return rootSet; +} + +CVector GetSectionInfo(std::ifstream &file, uint64_t fileSize) +{ + uint32_t secHead[2]; + uint32_t fileOffset = fileSize - sizeof(uint32_t) * 2; // 2 : last 2 uint32 + file.seekg(fileOffset); + file.read(reinterpret_cast(secHead), sizeof(secHead)); + if (secHead[1] != sizeof(uint32_t)) { + LOG_ECMA(ERROR) << "ark raw heap decode unexpect head, need=" << sizeof(uint32_t) << ", but=" << secHead[0]; + return CVector(0); + } + CVector secInfo(secHead[0]); // last 4 byte is section num + auto secInfoSize = secHead[0] * secHead[1]; + fileOffset -= secInfoSize; + file.seekg(fileOffset); + file.read(reinterpret_cast(secInfo.data()), secInfoSize); + return secInfo; +} + +void ClearObjMem(CUnorderedMap &objMap) +{ + for (auto objItem : objMap) { + delete objItem.second; + } + objMap.clear(); +} + +static bool GetValidFileSize(std::string &inputFilePath, uint64_t &fileSize) { - LOG_ECMA(INFO) << "ark raw heap GenerateHeapSnapshot start"; - uint64_t fileSize = GetFileSize(inputFilePath); + fileSize = GetFileSize(inputFilePath); if (fileSize == 0) { - LOG_ECMA(ERROR) << "ark raw heap get file size=0"; + LOG_ECMA(ERROR) << "ark raw heap decode get file size=0"; + return false; + } + if (fileSize > MAX_FILE_SIZE) { + LOG_ECMA(ERROR) << "ark raw heap decode get file size > 4GB, unsupported"; + return false; + } + return true; +} + +bool HeapProfiler::GenerateHeapSnapshot(std::string &inputFilePath, std::string &outputPath) +{ + LOG_ECMA(INFO) << "ark raw heap decode start target=" << outputPath; + std::string realPath; + if (!RealPath(inputFilePath, realPath)) { + LOG_ECMA(ERROR) << "get real path failed:" << inputFilePath; return false; } - std::ifstream file(inputFilePath, std::ios::binary); + uint64_t fileSize; + if (!GetValidFileSize(realPath, fileSize)) { + return false; + } + std::ifstream file(realPath, std::ios::binary); if (!file.is_open()) { - LOG_ECMA(ERROR) << "ark raw heap open file failed:" << inputFilePath.c_str(); + LOG_ECMA(ERROR) << "ark raw heap decode file failed:" << realPath; return false; } - static uint64_t maxSupportFileSize8GB = 8 * 1024 * 1024 * 1024ULL; - if (fileSize > maxSupportFileSize8GB) { - LOG_ECMA(ERROR) << "ark raw heap get file size > 10GB, unsupported"; + CVector sections = GetSectionInfo(file, fileSize); + if (sections.size() == 0) { + LOG_ECMA(ERROR) << "ark raw heap decode not found section data"; return false; } - auto buf = new char[fileSize]; - file.read(buf, fileSize); + auto objMap = DecodeMemObj(file, sections); + auto refSetMap = VisitObj(objMap); + auto rootSet = DecodeRootTable(file, sections[0], sections[1]); + auto strTabMap = DecodeStrTable(GetEcmaStringTable(), file, sections[2], sections[3]); file.close(); - ChunkDecoder *chunk = new ChunkDecoder(buf, fileSize); - auto &rawHeapArgs = chunk->GetRawHeapInfoArgs(); - auto &strTableIdMap = rawHeapArgs.strTableIdMapNewStr; - auto &objInfoVec = rawHeapArgs.rawObjInfoVec; - bool traceAllocation = false; - DumpSnapShotOption dumpOption; - LOG_ECMA(INFO) << "ark GenerateHeapSnapshot rebuild ref and generate nodes count=" << objInfoVec.size(); - for (auto item : strTableIdMap) { - GetEcmaStringTable()->GetString(item.second); - } - auto *snapshot = new HeapSnapshot(vm_, GetEcmaStringTable(), dumpOption, traceAllocation, entryIdMap_, GetChunk()); - DecodeObj(rawHeapArgs, snapshot); - LOG_ECMA(INFO) << "ark GenerateHeapSnapshot generate edges"; - snapshot->BuildSnapshotForBinMod(objInfoVec); - delete[] buf; - delete chunk; + DumpSnapShotOption dp; + auto *snapshot = new HeapSnapshot(vm_, GetEcmaStringTable(), dp, false, entryIdMap_, GetChunk()); + LOG_ECMA(INFO) << "ark raw heap decode generate nodes=" << objMap.size(); + snapshot->GenerateNodeForBinMod(objMap, rootSet, strTabMap); + rootSet.clear(); + strTabMap.clear(); + LOG_ECMA(INFO) << "ark raw heap decode fill edges=" << objMap.size(); + snapshot->BuildSnapshotForBinMod(objMap, refSetMap); + refSetMap.clear(); + ClearObjMem(objMap); if (outputPath.empty()) { - outputPath = GenDumpFileName(dumpOption.dumpFormat); + outputPath = GenDumpFileName(dp.dumpFormat); } else if (outputPath.back() == '/') { - outputPath += GenDumpFileName(dumpOption.dumpFormat); + outputPath += GenDumpFileName(dp.dumpFormat); } - LOG_GC(INFO) << "ark GenerateHeapSnapshot output file=" << outputPath.c_str(); + LOG_ECMA(INFO) << "ark raw heap decode serialize file=" << outputPath.c_str(); FileStream newStream(outputPath); auto serializerResult = HeapSnapshotJSONSerializer::Serialize(snapshot, &newStream); delete snapshot; - LOG_ECMA(INFO) << "ark raw heap GenerateHeapSnapshot finish"; + LOG_ECMA(INFO) << "ark raw heap decode finish"; return serializerResult; } @@ -422,6 +573,7 @@ void IterateSharedHeap(Callback &cb) { auto heap = SharedHeap::GetInstance(); heap->GetOldSpace()->IterateOverObjects(cb); + heap->GetCompressSpace()->IterateOverObjects(cb); heap->GetNonMovableSpace()->IterateOverObjects(cb); heap->GetHugeObjectSpace()->IterateOverObjects(cb); heap->GetAppSpawnSpace()->IterateOverObjects(cb); @@ -500,8 +652,10 @@ size_t GetNotFoundObj(const EcmaVM *vm) heapTotalSize += objSize; }; vm->GetHeap()->IterateOverObjects(handleObj, false); + vm->GetHeap()->GetCompressSpace()->IterateOverObjects(handleObj); IterateSharedHeap(handleObj); - LOG_ECMA(INFO) << "ark GetNotFound heap count:" << allHeapObjSet.size() << ", heap size=" << heapTotalSize; + LOG_ECMA(INFO) << "ark raw heap dump GetNotFound heap count:" << allHeapObjSet.size() + << ", heap size=" << heapTotalSize; CUnorderedSet notFoundObjSet {}; auto visitor = [¬FoundObjSet, &allHeapObjSet] ([[maybe_unused]]TaggedObject *root, ObjectSlot start, ObjectSlot end, VisitObjectArea area) { @@ -531,105 +685,234 @@ size_t GetNotFoundObj(const EcmaVM *vm) for (auto obj : allHeapObjSet) { ObjectXRay::VisitObjectBody(obj, obj->GetClass(), visitor); } - LOG_ECMA(INFO) << "ark GetNotFound not found count:" << notFoundObjSet.size(); + LOG_ECMA(INFO) << "ark raw heap dump GetNotFound not found count:" << notFoundObjSet.size(); return notFoundObjSet.size(); } -bool FillAddrTable(const EcmaVM *vm, EntryIdMap &idMap, AddrTableItem *table, HeapSnapshot *snapshot) +uint32_t HeapProfiler::CopyObjectMem2Buf(char *objTable, uint32_t objNum, + CVector> &memBufMap) { - uint64_t index = 0; - auto handleObj = [&index, &table, &idMap, &snapshot](TaggedObject *obj) { - auto taggedType = JSTaggedValue(obj).GetRawData(); - auto [exist, id] = idMap.FindId(taggedType); + char *currMemBuf = nullptr; + uint32_t currSize = 0; + uint32_t totalSize = 0; + uint32_t curOffset = objNum * sizeof(AddrTableItem); + auto objHeaders = reinterpret_cast(objTable); + for (uint32_t j = 0; j < objNum; ++j) { + auto obj = reinterpret_cast(objHeaders[j].addr); + JSTaggedValue value(obj); + uint64_t objSize = obj->GetClass()->SizeFromJSHClass(obj); + totalSize += objSize; + if (currSize + objSize > PER_GROUP_MEM_SIZE || currMemBuf == nullptr) { + if (currMemBuf != nullptr) { + memBufMap.push_back({currMemBuf, currSize}); + } + currSize = 0; + currMemBuf = chunk_.NewArray(objSize > PER_GROUP_MEM_SIZE? objSize : PER_GROUP_MEM_SIZE); + } + objHeaders[j].objSize = objSize; + objHeaders[j].offset = curOffset; + int32_t ret; + if (value.IsString()) { + CVector strTmp(objSize / sizeof(uint64_t), 0); + strTmp[0] = *reinterpret_cast(objHeaders[j].addr); + ret = memcpy_s(currMemBuf + currSize, objSize, reinterpret_cast(strTmp.data()), objSize); + } else { + ret = memcpy_s(currMemBuf + currSize, objSize, reinterpret_cast(objHeaders[j].addr), objSize); + } + if (ret != 0) { + LOG_ECMA(ERROR) << "ark raw heap dump CopyObjectMem memcpy_s failed, currSize=" + << currSize << ",objSize=" << objSize << ",addr=" << objHeaders[j].addr; + return totalSize; + } + curOffset += objSize; + currSize += objSize; + } + if (currSize > 0) { + memBufMap.push_back({currMemBuf, currSize}); + } else if (currMemBuf != nullptr) { + chunk_.Delete(currMemBuf); + } + return totalSize; +} + +uint32_t HeapProfiler::GenObjTable(CUnorderedMap &headerMap, HeapSnapshot *snapshot, + CUnorderedMap> &strIdMap) +{ + char *currBuf = chunk_.NewArray(PER_GROUP_MEM_SIZE); + uint32_t index = 0; + uint32_t objNum = 0; + auto table = reinterpret_cast(currBuf); + auto handleObj = [&index, &table, &objNum, &headerMap, &currBuf, &snapshot, &strIdMap, this](TaggedObject *obj) { + JSTaggedValue value(obj); + auto taggedType = value.GetRawData(); + auto [exist, id] = entryIdMap_->FindId(taggedType); if (!exist) { - idMap.InsertId(taggedType, id); + entryIdMap_->InsertId(taggedType, id); } table[index].addr = reinterpret_cast(obj); table[index].id = id; - table[index].stringId = snapshot->GenerateStringId(obj); + auto strId = snapshot->GenerateStringId(obj); + if (strId != 1) { // 1 : invalid str id + if (strIdMap.find(strId) == strIdMap.end()) { + strIdMap.emplace(strId, CVector()); + } + strIdMap[strId].push_back(table[index].addr); + } index++; + if (index == HEAD_NUM_PER_GROUP) { + headerMap.emplace(currBuf, index); + objNum += HEAD_NUM_PER_GROUP; + index = 0; + currBuf = chunk_.NewArray(PER_GROUP_MEM_SIZE); + table = reinterpret_cast(currBuf); + } }; - vm->GetHeap()->IterateOverObjects(handleObj, false); + vm_->GetHeap()->IterateOverObjects(handleObj, false); + vm_->GetHeap()->GetCompressSpace()->IterateOverObjects(handleObj); IterateSharedHeap(handleObj); - LOG_ECMA(INFO) << "ark FillAddrTable obj count: " << index; -#ifdef OHOS_UNIT_TEST - size_t ret = GetNotFoundObj(vm); - return ret == 0; -#else - return true; -#endif + objNum += index; + if (index != 0) { + headerMap.emplace(currBuf, index); + } else { + chunk_.Delete(currBuf); + } + return objNum; } -void CopyObjectMem(char *chunk, AddrTableItem *table, uint64_t len, std::atomic &index, - std::atomic &offset, uint64_t offBase) +// 4 byte: root_num +// 4 byte: unit size = sizeof(addr), 8 byte here +// {8 byte: root obj addr} * root_num +uint32_t HeapProfiler::GenRootTable(Stream *stream) { - auto curIdx = index.fetch_add(1); - while (curIdx < len) { - auto& item = table[curIdx]; - auto obj = reinterpret_cast(item.addr); - uint64_t objSize = obj->GetClass()->SizeFromJSHClass(obj); - auto curOffset = offset.fetch_add(objSize); - item.objSize = objSize; - item.offset = curOffset + offBase; - auto ret = memcpy_s(chunk + curOffset, objSize, reinterpret_cast(item.addr), objSize); - if (ret != 0) { - LOG_ECMA(ERROR) << "ark BinaryDump CopyObjectMem memcpy_s failed"; - return; - } - curIdx = index.fetch_add(1); + auto roots = GetRootObjects(vm_); + uint32_t rootSecHeadSize = 8; // 8 : root num 、 unit size + auto rootSecSize = roots.size() * (sizeof(TaggedObject *)) + rootSecHeadSize; + auto memBuf = chunk_.NewArray(rootSecSize); + uint32_t *rootHeader = reinterpret_cast(memBuf); + uint64_t *rootBuf = reinterpret_cast(memBuf + rootSecHeadSize); // 8 : root addr start offset + rootHeader[0] = roots.size(); // 0: root num + rootHeader[1] = sizeof(TaggedObject *); // 1: unit size + auto currInd = 0; + for (auto root : roots) { + rootBuf[currInd++] = reinterpret_cast(root); } + LOG_ECMA(INFO) << "ark raw heap dump GenRootTable root cnt="<WriteBinBlock(memBuf, rootSecSize); + chunk_.Delete(memBuf); + return rootSecSize; } -bool HeapProfiler::BinaryDump(Stream *stream, [[maybe_unused]] const DumpSnapShotOption &dumpOption) + +// 4 byte: obj_num +// 4 byte: unit size = sizeof(AddrTableItem) +// {AddrTableItem} * obj_num +// {obj contents} * obj_num +uint32_t HeapProfiler::WriteToBinFile(Stream *stream, char *objTab, uint32_t objNum, + CVector> &memBuf) { - LOG_ECMA(INFO) << "ark BinaryDump dump raw heap start"; - auto [localCnt, heapSize] = GetHeapCntAndSize(vm_); - auto [sharedCnt, sharedSize] = GetSharedCntAndSize(); - auto roots = GetRootObjects(vm_); - uint64_t heapTotalCnt = localCnt + sharedCnt; - uint64_t totalSize = sizeof(uint64_t) * (4 + roots.size()) + sizeof(AddrTableItem) * heapTotalCnt; // 4 : file head - uint64_t heapTotalSize = heapSize + sharedSize; - LOG_ECMA(INFO) << "ark rootNum=" << roots.size() << ", ObjSize=" << heapTotalSize << ", ObjNum=" << heapTotalCnt; - char *chunk = new char[totalSize]; - uint64_t *header = reinterpret_cast(chunk); - header[0] = heapTotalCnt; // 0: obj total count offset in file - header[1] = roots.size(); // 1: root obj num offset in file - header[2] = sharedCnt; // 2: share obj num offset in file - auto currInd = 4; // 4 : file head num is 4, then is obj table - for (auto root : roots) { - header[currInd++] = reinterpret_cast(root); + uint32_t secHeader[] = {objNum, sizeof(AddrTableItem)}; + uint32_t secTotalSize = sizeof(secHeader); + stream->WriteBinBlock(reinterpret_cast(secHeader), secTotalSize); + uint32_t headerSize = objNum * sizeof(AddrTableItem); + secTotalSize += headerSize; + stream->WriteBinBlock(objTab, headerSize); // write obj header + chunk_.Delete(objTab); + for (auto memItem : memBuf) { + stream->WriteBinBlock(memItem.first, memItem.second); + secTotalSize += memItem.second; + chunk_.Delete(memItem.first); } - auto table = reinterpret_cast(&header[currInd]); + return secTotalSize; +} + +bool HeapProfiler::DumpRawHeap(Stream *stream, uint32_t &fileOffset, CVector &secIndexVec) +{ + CUnorderedMap objTabMap; // buf map table num + CUnorderedMap> strIdMapObjVec; // string id map to objs vector DumpSnapShotOption op; - auto *snapshotPtr = GetChunk()->New(vm_, GetEcmaStringTable(), op, false, entryIdMap_, GetChunk()); - auto ret = FillAddrTable(vm_, *entryIdMap_, table, snapshotPtr); - char *heapObjData = new char[heapTotalSize]; - uint64_t objMemStart = reinterpret_cast(&table[heapTotalCnt]); - uint64_t offBase = objMemStart - reinterpret_cast(chunk); - std::atomic offset(0); - std::atomic index(0); - auto threadMain = [&offset, &index, heapObjData, table, heapTotalCnt, offBase]() { - CopyObjectMem(heapObjData, table, heapTotalCnt, index, offset, offBase); - }; - std::vector threads; - const uint32_t THREAD_NUM = 8; // 8 : thread num is 8 - for (uint32_t i = 0; i < THREAD_NUM; i++) { - threads.emplace_back(threadMain); - } - for (uint32_t i = 0; i < THREAD_NUM; i++) { - threads[i].join(); - } - header[3] = offBase + heapTotalSize; // 3: string table offset - LOG_ECMA(INFO) << "ark BinaryDump write to file"; - stream->WriteBinBlock(chunk, offBase); - stream->WriteBinBlock(heapObjData, heapTotalSize); - delete[] heapObjData; - delete[] chunk; - LOG_ECMA(INFO) << "ark BinaryDump dump DumpStringTable"; - HeapSnapshotJSONSerializer::DumpStringTable(snapshotPtr, stream); - GetChunk()->Delete(snapshotPtr); - LOG_ECMA(INFO) << "ark BinaryDump dump raw heap finished"; - return ret; + auto snapshot = GetChunk()->New(vm_, GetEcmaStringTable(), op, false, entryIdMap_, GetChunk()); + uint32_t objTotalNum = GenObjTable(objTabMap, snapshot, strIdMapObjVec); + LOG_ECMA(INFO) << "ark raw heap dump DumpRawHeap totalObjNumber=" << objTotalNum; + CVector>> allMemBuf(objTabMap.size(), CVector>()); + CVector threadsVec; + CVector objTabVec(objTabMap.size()); + uint32_t index = 0; + LOG_ECMA(INFO) << "ark raw heap dump DumpRawHeap start to copy, thread num=" << objTabMap.size(); + for (auto tableItem : objTabMap) { + auto tdCb = [this, &tableItem, &allMemBuf, &index] () { + CopyObjectMem2Buf(tableItem.first, tableItem.second, allMemBuf[index]); + }; + threadsVec.emplace_back(tdCb); + objTabVec[index] = tableItem.first; + threadsVec[index].join(); + ++index; + } + LOG_ECMA(INFO) << "ark raw heap dump DumpRawHeap write string, num=" << strIdMapObjVec.size(); + secIndexVec.push_back(fileOffset); // string table section offset + auto size = HeapSnapshotJSONSerializer::DumpStringTable(GetEcmaStringTable(), stream, strIdMapObjVec); + secIndexVec.push_back(size); // string table section size + GetChunk()->Delete(snapshot); + fileOffset += size; + strIdMapObjVec.clear(); + uint32_t finCnt = 0; + LOG_ECMA(INFO) << "ark raw heap dump DumpRawHeap write obj, offset=" << fileOffset; + while (finCnt < threadsVec.size()) { + for (index = 0; index < threadsVec.size(); ++index) { + if (threadsVec[index].joinable()) { // thread not finished + continue; + } + ++finCnt; + secIndexVec.push_back(fileOffset); // current section offset + auto objNum = objTabMap[objTabVec[index]]; + auto currSecSize = WriteToBinFile(stream, objTabVec[index], objNum, allMemBuf[index]); + LOG_ECMA(INFO) << "ark raw heap dump DumpRawHeap write offset=" << fileOffset << ", size=" << currSecSize; + secIndexVec.push_back(currSecSize); // current section size + fileOffset += currSecSize; + } + } + return true; +} + +// * 8 byte: version id +// * root table section +// * string table section +// * {heap section / share heap section} * thread_num +// * 4 byte: root table section offset +// * 4 byte: root table section size +// * 4 byte: string table section offset +// * 4 byte: string table section size +// * { +// * 4 byte: obj section offset +// * 4 byte: obj section size +// * } * thread_num +// * 4 byte: section_offset_num size, 4 byte here +// * 4 byte: section_num +bool HeapProfiler::BinaryDump(Stream *stream, [[maybe_unused]] const DumpSnapShotOption &dumpOption) +{ + char versionID[VERSION_ID_SIZE] = { 0 }; + LOG_ECMA(INFO) << "ark raw heap dump start, version is: " << versionID; + stream->WriteBinBlock(versionID, VERSION_ID_SIZE); + CQueue> needStrObjQue; + // a vector to index all sections, [offset, section_size, offset, section_size, ...] + CVector secIndexVec(2); // 2 : section head size + uint32_t fileOffset = VERSION_ID_SIZE; + secIndexVec[0] = fileOffset; + LOG_ECMA(INFO) << "ark raw heap dump GenRootTable"; + auto rootSectionSize = GenRootTable(stream); + secIndexVec[1] = rootSectionSize; // root section offset + fileOffset += rootSectionSize; // root section size + DumpRawHeap(stream, fileOffset, secIndexVec); + secIndexVec.push_back(secIndexVec.size()); // 4 byte is section num + secIndexVec.push_back(sizeof(uint32_t)); // the penultimate is section index data bytes number + stream->WriteBinBlock(reinterpret_cast(secIndexVec.data()), secIndexVec.size() *sizeof(uint32_t)); +#ifdef OHOS_UNIT_TEST + LOG_ECMA(INFO) << "ark raw heap dump UT check obj self-contained"; + size_t ret = GetNotFoundObj(vm_); + return ret == 0; +#else + LOG_ECMA(INFO) << "ark raw heap dump finished num=" << secIndexVec.size(); + return true; +#endif } void HeapProfiler::FillIdMap() diff --git a/ecmascript/dfx/hprof/heap_profiler.h b/ecmascript/dfx/hprof/heap_profiler.h index 29449508d6aa37dd86c7e85b9116c5cfeba8f9c7..42694c2b7c6261aa3313698f1573d9eddb91196a 100644 --- a/ecmascript/dfx/hprof/heap_profiler.h +++ b/ecmascript/dfx/hprof/heap_profiler.h @@ -78,51 +78,37 @@ private: struct AddrTableItem { uint64_t addr; uint64_t id; - uint64_t objSize; - uint64_t offset; // offset to the file - uint64_t stringId; + uint32_t objSize; + uint32_t offset; // offset to the file }; -struct RawHeapObjInfo { - AddrTableItem *tInfo; - char *newAddr; - bool isRoot; - CUnorderedSet refSet; -}; +#define PER_GROUP_MEM_SIZE (128 * 1024 * 1024) // 128 MB +#define HEAD_NUM_PER_GROUP (PER_GROUP_MEM_SIZE / sizeof(AddrTableItem)) +#define VERSION_ID_SIZE 8 +#define MAX_FILE_SIZE (4 * 1024 * 1024 * 1024ULL) // 4 * 1024 * 1024 * 1024 : file size bigger than 4GB +#define MAX_OBJ_SIZE (MAX_FILE_SIZE >> 1) -struct RawHeapInfoArgs { - CVector rawObjInfoVec; - CUnorderedMap oldAddrMapObjInfo; - CUnorderedMap strTableIdMapNewStr; -}; +struct NewAddr { + char *data; + uint32_t objSize; -class ChunkDecoder { -public: - explicit ChunkDecoder(char *mAddr, uint64_t fSize); - - ~ChunkDecoder() + NewAddr(uint32_t actSize, uint32_t objSize) : objSize(objSize) { - auto &objInfoVec = rawHeapArgs.rawObjInfoVec; - for (auto obj : objInfoVec) { - delete obj; + if (actSize == 0 || actSize > MAX_OBJ_SIZE) { + LOG_ECMA(ERROR) << "ark raw heap decode abnormal obj size=" << actSize; + data = nullptr; + return; } + data = new char[actSize]; } - - RawHeapInfoArgs &GetRawHeapInfoArgs() + ~NewAddr() { - return rawHeapArgs; + delete[] data; + } + char *Data() + { + return data; } - -private: - void DecodeStrTable(const char *charPtr); - - uint64_t heapObjCnt; - uint64_t rootObjCnt; - uint64_t shareObjCnt; - uint64_t strTableOffset; - RawHeapInfoArgs rawHeapArgs; - char *mapAddr; - uint64_t fileSize; }; class HeapProfiler : public HeapProfilerInterface { @@ -140,7 +126,7 @@ public: * dump the specific snapshot in target format */ bool DumpHeapSnapshot(Stream *stream, const DumpSnapShotOption &dumpOption, Progress *progress = nullptr) override; - void DumpHeapSnapshot(const DumpSnapShotOption &dumpOption) override; + void DumpHeapSnapshotForOOM(const DumpSnapShotOption &dumpOption, bool fromSharedGC = false) override; void AddSnapshot(HeapSnapshot *snapshot); bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr, @@ -174,6 +160,7 @@ private: */ bool ForceFullGC(const EcmaVM *vm); void ForceSharedGC(); + void DumpHeapSnapshotFromSharedGC(Stream *stream, const DumpSnapShotOption &dumpOption); /** * make a new heap snapshot and put it into a container eg, vector @@ -187,6 +174,13 @@ private: void ClearSnapshot(); void FillIdMap(); bool BinaryDump(Stream *stream, const DumpSnapShotOption &dumpOption); + uint32_t WriteToBinFile(Stream *stream, char *objTab, uint32_t objNum, + CVector> &memBuf); + uint32_t CopyObjectMem2Buf(char *objTable, uint32_t objNum, CVector> &memBufVec); + uint32_t GenObjTable(CUnorderedMap &headerMap, HeapSnapshot *snapshot, + CUnorderedMap> &strIdMapObjVec); + uint32_t GenRootTable(Stream *stream); + bool DumpRawHeap(Stream *stream, uint32_t &fileOffset, CVector &secIndexVec); const size_t MAX_NUM_HPROF = 5; // ~10MB const EcmaVM *vm_; diff --git a/ecmascript/dfx/hprof/heap_profiler_interface.cpp b/ecmascript/dfx/hprof/heap_profiler_interface.cpp index db0275c465ff99b4f2b95868e359efd150166e18..384b54f8cf95b8b324617edb4d552491b7f1557c 100644 --- a/ecmascript/dfx/hprof/heap_profiler_interface.cpp +++ b/ecmascript/dfx/hprof/heap_profiler_interface.cpp @@ -14,6 +14,7 @@ */ #include "ecmascript/dfx/hprof/heap_profiler_interface.h" +#include "ecmascript/dfx/hprof/heap_profiler.h" #include "ecmascript/ecma_vm.h" @@ -27,4 +28,14 @@ void HeapProfilerInterface::Destroy(EcmaVM *vm) { vm->DeleteHeapProfile(); } + +HeapProfilerInterface *HeapProfilerInterface::CreateNewInstance(const EcmaVM *vm) +{ + return new HeapProfiler(vm); +} + +void HeapProfilerInterface::DestroyInstance(HeapProfilerInterface *heapProfiler) +{ + delete heapProfiler; +} } // namespace panda::ecmascript diff --git a/ecmascript/dfx/hprof/heap_profiler_interface.h b/ecmascript/dfx/hprof/heap_profiler_interface.h index c201197559f1383131e8c9dd0b5a7ea870939457..f6e6bee1513272ccdfb27eb04c9e28771b8ca49e 100644 --- a/ecmascript/dfx/hprof/heap_profiler_interface.h +++ b/ecmascript/dfx/hprof/heap_profiler_interface.h @@ -43,6 +43,10 @@ class HeapProfilerInterface { public: static HeapProfilerInterface *GetInstance(EcmaVM *vm); static void Destroy(EcmaVM *vm); + // This is only used in OOM in SharedGC, since daemon thread does not have EcmaVM, so create a new instance + // to dump main JSThread. + static HeapProfilerInterface *CreateNewInstance(const EcmaVM *vm); + static void DestroyInstance(HeapProfilerInterface *heapProfiler); HeapProfilerInterface() = default; virtual ~HeapProfilerInterface() = default; @@ -53,7 +57,9 @@ public: virtual bool DumpHeapSnapshot(Stream *stream, const DumpSnapShotOption &dumpOption, Progress *progress = nullptr) = 0; // Provide an internal interface for oom dump. - virtual void DumpHeapSnapshot(const DumpSnapShotOption &dumpOption) = 0; + // If `fromSharedGC` is set, means that OOM happened during SharedGC, and should do Dump then Fatal at once + // SharedGC complete, caller Must call this during `SuspendAll`. + virtual void DumpHeapSnapshotForOOM(const DumpSnapShotOption &dumpOption, bool fromSharedGC = false) = 0; virtual bool GenerateHeapSnapshot(std::string &inputFilePath, std::string &outputPath) = 0; virtual bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr, diff --git a/ecmascript/dfx/hprof/heap_snapshot.cpp b/ecmascript/dfx/hprof/heap_snapshot.cpp index e8590e8bdabedeb3734d531b6aee952daf605624..f91386c48839a5b855bbad4efc9c11309782ce0e 100644 --- a/ecmascript/dfx/hprof/heap_snapshot.cpp +++ b/ecmascript/dfx/hprof/heap_snapshot.cpp @@ -565,13 +565,13 @@ CString *HeapSnapshot::GenerateNodeName(TaggedObject *entry) case JSType::GLOBAL_ENV: return GetString("GlobalEnv"); case JSType::PROTOTYPE_HANDLER: - return GetString("ProtoTypeHandler"); + return GetString("PrototypeHandler"); case JSType::TRANSITION_HANDLER: return GetString("TransitionHandler"); case JSType::TRANS_WITH_PROTO_HANDLER: return GetString("TransWithProtoHandler"); case JSType::STORE_TS_HANDLER: - return GetString("StoreTSHandler"); + return GetString("StoreAOTHandler"); case JSType::PROTO_CHANGE_MARKER: return GetString("ProtoChangeMarker"); case JSType::MARKER_CELL: @@ -634,6 +634,8 @@ NodeType HeapSnapshot::GenerateNodeType(TaggedObject *entry) void HeapSnapshot::FillNodes(bool isInFinish, bool isSimplify) { + LOG_ECMA(INFO) << "HeapSnapshot::FillNodes"; + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "HeapSnapshot::FillNodes"); // Iterate Heap Object auto heap = vm_->GetHeap(); if (heap != nullptr) { @@ -1039,6 +1041,8 @@ Node *HeapSnapshot::GenerateObjectNode(JSTaggedValue entry, size_t size, bool is void HeapSnapshot::FillEdges(bool isSimplify) { + LOG_ECMA(INFO) << "HeapSnapshot::FillEdges begin, nodeCount: " << nodeCount_; + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "HeapSnapshot::FillEdges"); auto iter = nodes_.begin(); size_t count = 0; while (count++ < nodes_.size()) { @@ -1079,21 +1083,24 @@ void HeapSnapshot::FillEdges(bool isSimplify) } iter++; } + LOG_ECMA(INFO) << "HeapSnapshot::FillEdges exit, nodeCount: " << nodeCount_ << ", edgeCount: " << edgeCount_; } -void HeapSnapshot::FillEdgesForBinMod(RawHeapObjInfo *objInfo) +void HeapSnapshot::FillEdgesForBinMod(char *newAddr, CUnorderedSet *refSet) { - auto entryFrom = entryMap_.FindEntry(reinterpret_cast(objInfo->newAddr)); + auto entryFrom = entryMap_.FindEntry(reinterpret_cast(newAddr)); JSTaggedValue value(entryFrom->GetAddress()); auto object = value.GetTaggedObject(); std::vector referenceResources; auto jsHclass = object->GetClass(); if (jsHclass->IsJsGlobalEnv() || jsHclass->IsString()) { referenceResources.emplace_back("hclass", JSTaggedValue(jsHclass)); - for (auto refAddr : objInfo->refSet) { - JSTaggedValue val(refAddr); - auto valTy = val.GetTaggedObject()->GetClass()->GetObjectType(); - referenceResources.emplace_back(JSHClass::DumpJSType(valTy), val); + if (refSet != nullptr) { + for (auto refAddr : *refSet) { + JSTaggedValue val(refAddr); + auto valTy = val.GetTaggedObject()->GetClass()->GetObjectType(); + referenceResources.emplace_back(JSHClass::DumpJSType(valTy), val); + } } } else { value.DumpForSnapshot(referenceResources, false); @@ -1130,44 +1137,41 @@ void HeapSnapshot::FillEdgesForBinMod(RawHeapObjInfo *objInfo) } } -void HeapSnapshot::AddSyntheticRootForBinMod(RawHeapObjInfo *objInfo, int &edgeOffset, Node *syntheticRoot) -{ - if (!objInfo->isRoot) { - return; - } - TaggedObject *root = reinterpret_cast(objInfo->newAddr); - Node *rootNode = entryMap_.FindEntry(Node::NewAddress(root)); - if (rootNode != nullptr) { - Edge *edge = Edge::NewEdge(chunk_, - EdgeType::SHORTCUT, syntheticRoot, rootNode, GetString("-subroot-")); - InsertEdgeAt(edgeOffset, edge); - edgeOffset++; - syntheticRoot->IncEdgeCount(); - } -} - -Node *HeapSnapshot::GenerateNodeForBinMod(TaggedObject *obj, RawHeapObjInfo *objInfo, - CUnorderedMap &strTableIdMap) +void HeapSnapshot::GenerateNodeForBinMod(CUnorderedMap &objMap, CUnorderedSet &rootSet, + CUnorderedMap &strTableIdMap) { - auto currNode = GenerateNode(JSTaggedValue(obj), objInfo->tInfo->objSize, false, false, true); - if (strTableIdMap.find(objInfo->tInfo->stringId) != strTableIdMap.end() - && strTableIdMap[objInfo->tInfo->stringId] != nullptr) { - if (currNode != nullptr) { - currNode->SetName(GetString(strTableIdMap[objInfo->tInfo->stringId])); + Node *syntheticRoot = Node::NewNode(chunk_, 1, nodeCount_, GetString("SyntheticRoot"), + NodeType::SYNTHETIC, 0, 0, 0); + InsertNodeAt(0, syntheticRoot); + int edgeOffset = 0; + for (auto objItem : objMap) { + TaggedObject *obj = reinterpret_cast(objItem.second->Data()); + auto currNode = GenerateNode(JSTaggedValue(obj), objItem.second->objSize, false, false, false); + if (currNode == nullptr) { + continue; + } + if (strTableIdMap.find(objItem.first) != strTableIdMap.end()) { + currNode->SetName(strTableIdMap[objItem.first]); + } + if (rootSet.find(objItem.first) != rootSet.end()) { + Edge *edge = Edge::NewEdge(chunk_, EdgeType::SHORTCUT, syntheticRoot, currNode, GetString("-subroot-")); + InsertEdgeAt(edgeOffset, edge); + edgeOffset++; + syntheticRoot->IncEdgeCount(); } } - return currNode; } -bool HeapSnapshot::BuildSnapshotForBinMod(CVector &objInfoVec) +bool HeapSnapshot::BuildSnapshotForBinMod(CUnorderedMap &objMap, + CUnorderedMap> &refSetMap) { - Node *syntheticRoot = Node::NewNode(chunk_, 1, nodeCount_, GetString("SyntheticRoot"), - NodeType::SYNTHETIC, 0, 0, 0); - InsertNodeAt(0, syntheticRoot); - int edgeOffset = 0; - for (auto objInfo : objInfoVec) { - FillEdgesForBinMod(objInfo); - AddSyntheticRootForBinMod(objInfo, edgeOffset, syntheticRoot); + for (auto objItem : objMap) { + CUnorderedSet *refSet = nullptr; + auto newAddr = reinterpret_cast(objItem.second->Data()); + if (refSetMap.find(newAddr) != refSetMap.end()) { + refSet = &refSetMap[newAddr]; + } + FillEdgesForBinMod(objItem.second->Data(), refSet); } int reindex = 0; for (Node *node : nodes_) { @@ -1258,6 +1262,8 @@ Edge *HeapSnapshot::InsertEdgeUnique(Edge *edge) void HeapSnapshot::AddSyntheticRoot() { + LOG_ECMA(INFO) << "HeapSnapshot::AddSyntheticRoot"; + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "HeapSnapshot::AddSyntheticRoot"); Node *syntheticRoot = Node::NewNode(chunk_, 1, nodeCount_, GetString("SyntheticRoot"), NodeType::SYNTHETIC, 0, 0, 0); InsertNodeAt(0, syntheticRoot); diff --git a/ecmascript/dfx/hprof/heap_snapshot.h b/ecmascript/dfx/hprof/heap_snapshot.h index 72c33105f5cd33085898fe93ad94184b9b5874e3..82554fa6c0bddaee611f4b5cd7d75d9567b2f11f 100644 --- a/ecmascript/dfx/hprof/heap_snapshot.h +++ b/ecmascript/dfx/hprof/heap_snapshot.h @@ -502,9 +502,10 @@ public: return stringTable_; } - bool BuildSnapshotForBinMod(CVector &objInfoVec); - Node *GenerateNodeForBinMod(TaggedObject *obj, RawHeapObjInfo *objInfo, - CUnorderedMap &strTableIdMap); + bool BuildSnapshotForBinMod(CUnorderedMap &objMap, + CUnorderedMap> &refSetMap); + void GenerateNodeForBinMod(CUnorderedMap &objMap, CUnorderedSet &rootSetMap, + CUnorderedMap &strTableIdMap); StringId GenerateStringId(TaggedObject *obj) { @@ -541,8 +542,7 @@ private: void EraseNodeUnique(Node *node); Edge *InsertEdgeUnique(Edge *edge); void AddSyntheticRoot(); - void FillEdgesForBinMod(RawHeapObjInfo *objInfo); - void AddSyntheticRootForBinMod(RawHeapObjInfo *objInfoVec, int &edgeOffset, Node *syntheticRoot); + void FillEdgesForBinMod(char *newAddr, CUnorderedSet *refSet); Node *InsertNodeAt(size_t pos, Node *node); Edge *InsertEdgeAt(size_t pos, Edge *edge); diff --git a/ecmascript/dfx/hprof/heap_snapshot_json_serializer.cpp b/ecmascript/dfx/hprof/heap_snapshot_json_serializer.cpp index e13e20c28094c3544d76340e48ef4c0cecbc4d4b..65d002bcccc482e11bc3059fce7d350433d99773 100644 --- a/ecmascript/dfx/hprof/heap_snapshot_json_serializer.cpp +++ b/ecmascript/dfx/hprof/heap_snapshot_json_serializer.cpp @@ -24,6 +24,7 @@ bool HeapSnapshotJSONSerializer::Serialize(HeapSnapshot *snapshot, Stream *strea { // Serialize Node/Edge/String-Table LOG_ECMA(INFO) << "HeapSnapshotJSONSerializer::Serialize begin"; + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "HeapSnapshotJSONSerializer::Serialize"); ASSERT(snapshot->GetNodes() != nullptr && snapshot->GetEdges() != nullptr && snapshot->GetEcmaStringTable() != nullptr); auto writer = new StreamWriter(stream); @@ -45,49 +46,61 @@ bool HeapSnapshotJSONSerializer::Serialize(HeapSnapshot *snapshot, Stream *strea return true; } -void HeapSnapshotJSONSerializer::DumpStringTable(HeapSnapshot *snapshot, Stream *stream) +/* +4 byte: str_num +4 byte: unuse +{ +4 byte: string size +4 byte: obj_num +[8 byte: obj adrr] * obj_num +string contents +} * str_num +*/ +uint32_t HeapSnapshotJSONSerializer::DumpStringTable(StringHashMap *stringTable, Stream *stream, + CUnorderedMap> &strIdMapObjVec) { - const StringHashMap *stringTable = snapshot->GetEcmaStringTable(); ASSERT(stringTable != nullptr); - size_t size5MB = 5 * 1024 * 1024; - char *buf = new char[size5MB]; // 5MB buf use for string dump - auto strNum = stringTable->GetCapcity(); - auto ret = memcpy_s(buf, size5MB, &strNum, sizeof(size_t)); - if (ret != EOK) { - delete[] buf; - LOG_ECMA(ERROR) << "DumpStringTable: memcpy_s failed, strNum=" << strNum; - return; - } - size_t offset = sizeof(size_t); + size_t bufSize = 8 * 1024 * 1024; // 8MB buf use for string dump + char *buf = new char[bufSize]; + uint32_t secHead[] = {stringTable->GetCapcity(), 0}; + *reinterpret_cast(buf) = *reinterpret_cast(secHead); + uint32_t secTotalSize = sizeof(secHead); + size_t offset = sizeof(secHead); for (auto key : stringTable->GetOrderedKeyStorage()) { auto [strId, str] = stringTable->GetStringAndIdPair(key); - const char *s = str->data(); - auto currLen = str->size() + 1; - if (currLen + sizeof(uint64_t) > size5MB) { + auto objVec = strIdMapObjVec[strId]; + uint32_t objVecSize = objVec.size() * sizeof(uint64_t); + uint32_t strHead[] = {str->size(), objVec.size()}; + auto currLen = sizeof(strHead) + objVecSize + str->size() + 1; + if (offset + currLen > bufSize) { stream->WriteBinBlock(buf, offset); offset = 0; - delete[] buf; - size5MB = currLen + sizeof(uint64_t); - buf = new char[size5MB]; + if (currLen > bufSize) { + delete[] buf; + bufSize = currLen; + buf = new char[bufSize]; + } } - if (offset + currLen + sizeof(uint64_t) > size5MB) { - stream->WriteBinBlock(buf, offset); - offset = 0; + *reinterpret_cast(buf + offset) = *reinterpret_cast(strHead); + offset += sizeof(strHead); + if (memcpy_s(buf + offset, bufSize - offset, reinterpret_cast(objVec.data()), objVecSize) != EOK) { + LOG_ECMA(ERROR) << "DumpStringTable: memcpy_s failed"; + break; } - auto strIdPtr = reinterpret_cast(buf + offset); - *strIdPtr = strId; - ret = memcpy_s(buf + offset + sizeof(uint64_t), size5MB - offset, s, currLen); - if (ret != EOK) { - delete[] buf; + offset += objVecSize; + if (memcpy_s(buf + offset, bufSize - offset, str->data(), str->size() + 1) != EOK) { LOG_ECMA(ERROR) << "DumpStringTable: memcpy_s failed"; - return; + break; } - offset += currLen + sizeof(uint64_t); + offset += str->size() + 1; + secTotalSize += currLen; } - if (offset > 0) { - stream->WriteBinBlock(buf, offset); + auto padding = (8 - secTotalSize % 8) % 8; + if (offset + padding > 0) { + stream->WriteBinBlock(buf, offset + padding); } delete[] buf; + return secTotalSize + padding; } void HeapSnapshotJSONSerializer::SerializeSnapshotHeader(HeapSnapshot *snapshot, StreamWriter *writer) @@ -130,6 +143,8 @@ void HeapSnapshotJSONSerializer::SerializeSnapshotHeader(HeapSnapshot *snapshot, void HeapSnapshotJSONSerializer::SerializeNodes(HeapSnapshot *snapshot, StreamWriter *writer) { + LOG_ECMA(INFO) << "HeapSnapshotJSONSerializer::SerializeNodes"; + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "HeapSnapshotJSONSerializer::SerializeNodes"); const CList *nodes = snapshot->GetNodes(); const StringHashMap *stringTable = snapshot->GetEcmaStringTable(); ASSERT(nodes != nullptr); @@ -165,6 +180,8 @@ void HeapSnapshotJSONSerializer::SerializeNodes(HeapSnapshot *snapshot, StreamWr void HeapSnapshotJSONSerializer::SerializeEdges(HeapSnapshot *snapshot, StreamWriter *writer) { + LOG_ECMA(INFO) << "HeapSnapshotJSONSerializer::SerializeEdges"; + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "HeapSnapshotJSONSerializer::SerializeEdges"); const CList *edges = snapshot->GetEdges(); const StringHashMap *stringTable = snapshot->GetEcmaStringTable(); ASSERT(edges != nullptr); @@ -287,6 +304,8 @@ void HeapSnapshotJSONSerializer::SerializeLocations(StreamWriter *writer) void HeapSnapshotJSONSerializer::SerializeStringTable(HeapSnapshot *snapshot, StreamWriter *writer) { + LOG_ECMA(INFO) << "HeapSnapshotJSONSerializer::SerializeStringTable"; + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "HeapSnapshotJSONSerializer::SerializeStringTable"); const StringHashMap *stringTable = snapshot->GetEcmaStringTable(); ASSERT(stringTable != nullptr); writer->WriteString("\"strings\":[\"\",\n"); diff --git a/ecmascript/dfx/hprof/heap_snapshot_json_serializer.h b/ecmascript/dfx/hprof/heap_snapshot_json_serializer.h index 81acae2b7c37487240ac8c22bc2a4372e2bf831b..38ec5a0f21ba29457ed5adc0f9a37939df39cbfe 100644 --- a/ecmascript/dfx/hprof/heap_snapshot_json_serializer.h +++ b/ecmascript/dfx/hprof/heap_snapshot_json_serializer.h @@ -23,6 +23,7 @@ #include "ecmascript/dfx/hprof/file_stream.h" #include "ecmascript/mem/c_containers.h" #include "ecmascript/mem/c_string.h" +#include "ecmascript/dfx/hprof/string_hashmap.h" #include "securec.h" @@ -111,7 +112,8 @@ public: NO_MOVE_SEMANTIC(HeapSnapshotJSONSerializer); NO_COPY_SEMANTIC(HeapSnapshotJSONSerializer); static bool Serialize(HeapSnapshot *snapshot, Stream *stream); - static void DumpStringTable(HeapSnapshot *snapshot, Stream *stream); + static uint32_t DumpStringTable(StringHashMap *stringTable, Stream *stream, + CUnorderedMap> &strIdMapObjVec); private: static constexpr char ASCII_US = 31; diff --git a/ecmascript/dfx/hprof/rawheap_translate/BUILD.gn b/ecmascript/dfx/hprof/rawheap_translate/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..aa1f90bc8ebcffdb09096ceafe065a1957f296ce --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/BUILD.gn @@ -0,0 +1,42 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/js_runtime_config.gni") + +config("rawheap_translate_config") { + include_dirs = [ "$js_root" ] +} + +ohos_executable("rawheap_translator") { + sources = [ + "main.cpp", + "metadata_parse.cpp", + "rawheap_translate.cpp", + "serializer.cpp", + "string_hashmap.cpp", + "utils.cpp", + ] + + cflags_cc = [ "-std=c++17" ] + + configs = [ ":rawheap_translate_config" ] + + external_deps = [ + "bounds_checking_function:libsec_static", + "cJSON:cjson_static", + ] + + install_enable = true + part_name = "ets_runtime" + subsystem_name = "arkcompiler" +} diff --git a/ecmascript/dfx/hprof/rawheap_translate/main.cpp b/ecmascript/dfx/hprof/rawheap_translate/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf641abdc28f7c26b8550a40ed4b17c63f7f694d --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/main.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h" +#include "ecmascript/dfx/hprof/rawheap_translate/serializer.h" + +namespace rawheap_translate { +std::string RAWHEAP_TRANSLATE_HELPER = + "Usage: rawheap_translator \n" + "at least 1 argv provide, you can also extend to include , " + "if output file not available, an automatic one will be generated after all."; + +int Main(const int argc, const char **argv) +{ + // 2: at least 1 argv provide, including + // 3: also extend to include output file + if (argc < 2 || argc > 3) { + LOG_ERROR("Main: input error!\n" + RAWHEAP_TRANSLATE_HELPER); + return -1; + } + + int newArgc = 1; + std::string rawheapPathOrVersionCheck = argv[newArgc]; + if (rawheapPathOrVersionCheck == "-V" || rawheapPathOrVersionCheck == "-v") { + std::cout << VERSION[MAJOR_VERSION_INDEX] + << '.' << VERSION[MINOR_VERSION_INDEX] + << '.' << VERSION[BUILD_VERSION_INDEX] << std::endl; + return 0; + } + + if (!EndsWith(rawheapPathOrVersionCheck, ".rawheap")) { + LOG_ERROR("The second argument must be rawheap file!\n" + RAWHEAP_TRANSLATE_HELPER); + return -1; + } + + newArgc++; + std::string outputPath {}; + if (newArgc < argc) { + outputPath = argv[newArgc]; + if (!EndsWith(outputPath, ".heapsnapshot")) { + LOG_ERROR("The last argument must be heapsnapshot file!\n" + RAWHEAP_TRANSLATE_HELPER); + return -1; + } + } else { + if (!GenerateDumpFileName(outputPath)) { + LOG_ERROR("Generate dump file name failed!\n"); + return -1; + } + } + + LOG_INFO("Main: start to translate rawheap!"); + RawHeapTranslate translate; + if (!translate.Translate(rawheapPathOrVersionCheck)) { + return -1; + } + + LOG_INFO("Main: start to serialize!"); + StreamWriter writer; + if (!writer.Initialize(outputPath)) { + return -1; + } + + HeapSnapshotJSONSerializer::Serialize(&translate, &writer); + LOG_INFO("Main: translate success! file save to " + outputPath); + return 0; +} + +} // namespace rawheap_translate +int main(int argc, const char **argv) +{ + return rawheap_translate::Main(argc, argv); +} \ No newline at end of file diff --git a/ecmascript/dfx/hprof/rawheap_translate/metadata_parse.cpp b/ecmascript/dfx/hprof/rawheap_translate/metadata_parse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a20c0dd48860b45bf501f79833e41b3fdac60081 --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/metadata_parse.cpp @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/dfx/hprof/rawheap_translate/metadata_parse.h" + +namespace rawheap_translate { +bool Meta::Parse(const cJSON *object) +{ + return ParseVersion(object) && + ParseTypeEnums(object) && + ParseTypeList(object) && + ParseTypeLayout(object) && + SetObjTypeBitFieldOffset() && + SetNativatePointerBindingSizeOffset(); +} + +uint32_t Meta::GetNativateSize(char *obj, char *hclass) +{ + JSType typeId = GetObjTypeFromHClass(hclass); + if (typeId != GetObjTypeFromTypeName("JS_NATIVE_POINTER")) { + return 0; + } + return ByteToU32(obj + nativatePointerBindingSizeOffset_); +} + +std::string Meta::GetTypeNameFromHClass(char *hclass) +{ + JSType typeId = GetObjTypeFromHClass(hclass); + if (typeId < enumsVec_.size()) { + return enumsVec_[typeId]; + } + LOG_ERROR("Meta::GetTypeNameFromTypeId: typeId out of range, typeId=" + std::to_string(typeId)); + return "UNKNOWN_TYPE"; +} + +std::shared_ptr Meta::GetObjectLayout(const std::string &name) +{ + auto layout = layout_.find(name); + if (layout != layout_.end()) { + return layout->second; + } + return nullptr; +} + +bool Meta::IsString(char *hclass) +{ + JSType typeId = GetObjTypeFromHClass(hclass); + JSType stringFirst = GetObjTypeFromTypeName(GetTypeDesc("string_first")); + JSType stringLast = GetObjTypeFromTypeName(GetTypeDesc("string_last")); + if (stringFirst <= typeId && typeId <= stringLast) { + return true; + } + return false; +} + +bool Meta::IsDictionaryMode(char *hclass) +{ + return GetObjTypeFromHClass(hclass) == GetObjTypeFromTypeName("TAGGED_DICTIONARY"); +} + +bool Meta::IsJSObject(char *hclass) +{ + JSType typeId = GetObjTypeFromHClass(hclass); + JSType stringFirst = GetObjTypeFromTypeName(GetTypeDesc("js_object_first")); + JSType stringLast = GetObjTypeFromTypeName(GetTypeDesc("js_object_last")); + if (stringFirst <= typeId && typeId <= stringLast) { + return true; + } + return false; +} + +bool Meta::IsGlobalEnv(char *hclass) +{ + return GetObjTypeFromHClass(hclass) == GetObjTypeFromTypeName("GLOBAL_ENV"); +} + +NodeType Meta::GetNodeTypeFromHClass(char *hclass) +{ + std::string name = GetTypeNameFromHClass(hclass); + auto type = enumsMapNodeType_.find(name); + if (type != enumsMapNodeType_.end()) { + return type->second; + } + return DEFAULT_NODETYPE; // 8: means DEFAULT node type +} + +void Meta::VisitObjectBody(const std::string &name, const ObjRangeVisitor &visitor, uint32_t &baseOffset) +{ + auto metadata = GetMetaData(name); + if (!metadata) { + return; + } + + for (const auto &parent : metadata->parents) { + VisitObjectBody(parent, visitor, baseOffset); + } + + visitor(metadata, baseOffset); + baseOffset += metadata->endOffset; +} + +bool Meta::SetObjTypeBitFieldOffset() +{ + auto visitor = [this] (std::shared_ptr &metadata, int offset) { + for (const auto &field : metadata->fields) { + if (field->name == "BitField") { + objTypeBitFieldOffset_ = offset + field->offset; + objTypeBitFieldSize_ = field->size; + } + } + }; + uint32_t baseOffset = 0; + VisitObjectBody("HCLASS", visitor, baseOffset); + LOG_INFO("Meta::SetObjTypeBitFieldOffset: offset=" + std::to_string(objTypeBitFieldOffset_)); + return true; +} + +bool Meta::SetNativatePointerBindingSizeOffset() +{ + auto visitor = [this] (std::shared_ptr &metadata, int offset) { + for (const auto &field : metadata->fields) { + if (field->name == "BindingSize") { + nativatePointerBindingSizeOffset_ = offset + field->offset; + nativatePointerBindingSize_ = field->size; + } + } + }; + uint32_t baseOffset = 0; + VisitObjectBody("JS_NATIVE_POINTER", visitor, baseOffset); + LOG_INFO("Meta::SetNativatePointerBindingSizeOffset: offset=" + std::to_string(nativatePointerBindingSizeOffset_)); + return true; +} + +JSType Meta::GetObjTypeFromHClass(char *hclass) +{ + return ByteToU32(hclass + objTypeBitFieldOffset_) & 0xFF; // lower 8-bits of 32-bit value means JSType +} + +JSType Meta::GetObjTypeFromTypeName(const std::string &name) +{ + auto typeEnum = enumsMapJSType_.find(name); + if (typeEnum == enumsMapJSType_.end()) { + return 0; + } + return typeEnum->second; +} + +std::string Meta::GetTypeDesc(const std::string &name) +{ + auto result = typeDesc_.find(name); + if (result != typeDesc_.end()) { + return result->second; + } + return "UNKNOWN_TYPE"; +} + +bool Meta::ParseTypeEnums(const cJSON *json) +{ + cJSON *typeEnums = cJSON_GetObjectItem(json, "type_enum"); + auto visit = [&typeEnums, this] (const cJSON *item, int index) { + std::string name = item->string; + uint32_t edgeType = 0; + if (GetUInt32(typeEnums, name.c_str(), edgeType)) { + enumsVec_.push_back(name); + enumsMapJSType_.emplace(name, static_cast(index)); + enumsMapNodeType_.emplace(name, static_cast(edgeType)); + } + }; + IterateJSONArray(typeEnums, visit); + LOG_INFO("Meta::ParseTypeEnums: parse type enums, size=" + std::to_string(enumsVec_.size())); + return true; +} + +bool Meta::ParseTypeList(const cJSON *json) +{ + cJSON *metadatas {nullptr}; + std::vector *curParents {nullptr}; + std::vector> *curField {nullptr}; + if (!GetArray(json, "type_list", &metadatas)) { + LOG_ERROR("Meta::ParseTypeList: type list parse failed!"); + return false; + } + + auto parentVisitor = [&curParents] (const cJSON *item, [[maybe_unused]] int index) { + std::string value {}; + if (GetString(item, value)) { + curParents->push_back(value); + } + }; + + auto offsetVisitor = [&curField] (const cJSON *item, [[maybe_unused]] int index) { + auto field = std::make_shared(); + if (GetUInt32(item, "offset", field->offset) && + GetString(item, "name", field->name) && + GetUInt32(item, "size", field->size)) { + curField->push_back(field); + } + }; + + auto metaVisitor = + [&curParents, &curField, &parentVisitor, &offsetVisitor, this] (const cJSON *item, [[maybe_unused]] int index) { + cJSON *fields {nullptr}; + cJSON *parents {nullptr}; + if (!GetArray(item, "offsets", &fields) || !GetArray(item, "parents", &parents)) { + return; + } + + auto metadata = std::make_shared(); + curParents = &metadata->parents; + curField = &metadata->fields; + IterateJSONArray(fields, offsetVisitor); + IterateJSONArray(parents, parentVisitor); + + if (GetString(item, "name", metadata->name) && GetUInt32(item, "end_offset", metadata->endOffset)) { + metadata_.emplace(metadata->name, metadata); + } + + GetString(item, "visit_type", metadata->visitType); + }; + + IterateJSONArray(metadatas, metaVisitor); + LOG_INFO("Meta::ParseTypeList: parse type list, obj size = " + std::to_string(metadata_.size())); + return true; +} + +bool Meta::ParseTypeLayout(const cJSON *json) +{ + cJSON *object = cJSON_GetObjectItem(json, "type_layout"); + + cJSON *dictLayout = cJSON_GetObjectItem(object, "Dictionary_layout"); + auto layout = std::make_shared(); + GetString(dictLayout, "name", layout->name); + GetUInt32(dictLayout, "key_index", layout->keyIndex); + GetUInt32(dictLayout, "value_index", layout->valueIndex); + GetUInt32(dictLayout, "detail_index", layout->detailIndex); + GetUInt32(dictLayout, "entry_size", layout->entrySize); + GetUInt32(dictLayout, "header_size", layout->headerSize); + layout_.emplace(layout->name, layout); + LOG_INFO("Meta::ParseTypeLayout: parse type layout, size=" + std::to_string(layout_.size())); + + cJSON *typeRange = cJSON_GetObjectItem(object, "Type_range"); + auto visit = [&typeRange, this] (const cJSON *item, [[maybe_unused]] int index) { + std::string key = item->string; + std::string value {}; + if (GetString(typeRange, key.c_str(), value)) { + typeDesc_.emplace(key, value); + } + }; + IterateJSONArray(typeRange, visit); + LOG_INFO("Meta::ParseTypeLayout: parse type desc, size=" + std::to_string(typeDesc_.size())); + return true; +} + +bool Meta::ParseVersion(const cJSON *json) +{ + std::string version {}; + if (!GetString(json, "version", version)) { + LOG_ERROR("Meta::ParseVersion: version not found!"); + return false; + } + + if (!CheckVersion(version)) { + return false; + } + + LOG_INFO("Meta::ParseVersion: current metadata version is " + version); + return true; +} +std::shared_ptr Meta::GetMetaData(const std::string &name) +{ + auto metadata = metadata_.find(name); + if (metadata != metadata_.end()) { + return metadata->second; + } + return nullptr; +} + +void Meta::IterateJSONArray(const cJSON *array, const std::function &visitor) +{ + int size = cJSON_GetArraySize(array); + for (int i = 0; i < size; i++) { + cJSON *item = cJSON_GetArrayItem(array, i); + visitor(item, i); + } +} + +bool Meta::GetArray(const cJSON *json, const char *key, cJSON **value) +{ + cJSON *array = cJSON_GetObjectItem(json, key); + if (array == nullptr || cJSON_IsArray(array) == 0) { + return false; + } + *value = array; + return true; +} + +bool Meta::GetString(const cJSON *json, const char *key, std::string &value) +{ + cJSON *item = cJSON_GetObjectItem(json, key); + if (item == nullptr) { + return false; + } + return GetString(item, value); +} + +bool Meta::GetString(const cJSON *json, std::string &value) +{ + if (cJSON_IsString(json) == 0) { + return false; + } + value = json->valuestring; + return true; +} + +bool Meta::GetUInt32(const cJSON *json, const char *key, uint32_t &value) +{ + cJSON *item = cJSON_GetObjectItem(json, key); + if (item == nullptr) { + return false; + } + return GetUInt32(item, value); +} + +bool Meta::GetUInt32(const cJSON *json, uint32_t &value) +{ + if (cJSON_IsNumber(json) == 0) { + return false; + } + if (json->valuedouble < 0 || json->valuedouble > static_cast(UINT32_MAX)) { + return false; + } + value = static_cast(json->valuedouble); + return true; +} +} // namespace rawheap_translate \ No newline at end of file diff --git a/ecmascript/dfx/hprof/rawheap_translate/metadata_parse.h b/ecmascript/dfx/hprof/rawheap_translate/metadata_parse.h new file mode 100644 index 0000000000000000000000000000000000000000..06f322db6cb73dfad7c1978fdc7eedd2c22bddaa --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/metadata_parse.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef METADATA_JSON_PARSE_H +#define METADATA_JSON_PARSE_H + +#include "cJSON.h" +#include "ecmascript/dfx/hprof/rawheap_translate/utils.h" + +namespace rawheap_translate { +struct MetaData; +using JSType = uint8_t; +using NodeType = uint8_t; +using ObjRangeVisitor = std::function &, uint32_t)>; + +struct Field { + std::string name; + uint32_t offset; + uint32_t size; + + Field() : offset(0), size(0) {} +}; + +struct MetaData { + std::string name; + std::vector> fields; + uint32_t endOffset; + std::vector parents; + std::string visitType; + + MetaData() : endOffset(0) {} + + bool IsArray() + { + return visitType == "Array"; + } +}; + +struct Layout { + std::string name; + uint32_t keyIndex; + uint32_t valueIndex; + uint32_t detailIndex; + uint32_t entrySize; + uint32_t headerSize; + + Layout() : keyIndex(0), valueIndex(0), detailIndex(0), entrySize(0), headerSize(0) {} +}; + +class Meta { +public: + Meta() = default; + ~Meta() + { + metadata_.clear(); + enumsMapJSType_.clear(); + enumsMapNodeType_.clear(); + layout_.clear(); + typeDesc_.clear(); + enumsVec_.clear(); + } + + bool Parse(const cJSON *object); + void VisitObjectBody(const std::string &name, const ObjRangeVisitor &visitor, uint32_t &baseOffset); + uint32_t GetNativateSize(char *obj, char *hclass); + NodeType GetNodeTypeFromHClass(char *hclass); + std::string GetTypeNameFromHClass(char *hclass); + std::shared_ptr GetObjectLayout(const std::string &name); + bool IsString(char *hclass); + bool IsDictionaryMode(char *hclass); + bool IsJSObject(char *hclass); + bool IsGlobalEnv(char *hclass); + +private: + bool ParseTypeEnums(const cJSON *json); + bool ParseTypeList(const cJSON *json); + bool ParseTypeLayout(const cJSON *json); + bool ParseVersion(const cJSON *json); + bool SetObjTypeBitFieldOffset(); + bool SetNativatePointerBindingSizeOffset(); + std::shared_ptr GetMetaData(const std::string &name); + JSType GetObjTypeFromHClass(char *hclass); + JSType GetObjTypeFromTypeName(const std::string &name); + std::string GetTypeDesc(const std::string &name); + + static void IterateJSONArray(const cJSON *array, const std::function &visitor); + static bool GetArray(const cJSON *json, const char *key, cJSON **value); + static bool GetString(const cJSON *json, const char *key, std::string &value); + static bool GetString(const cJSON *json, std::string &value); + static bool GetUInt32(const cJSON *json, const char *key, uint32_t &value); + static bool GetUInt32(const cJSON *json, uint32_t &value); + + static constexpr NodeType DEFAULT_NODETYPE = 8; + + std::unordered_map> metadata_ {}; + std::unordered_map enumsMapJSType_ {}; + std::unordered_map enumsMapNodeType_ {}; + std::unordered_map> layout_ {}; + std::unordered_map typeDesc_ {}; + std::vector enumsVec_ {}; + int objTypeBitFieldOffset_ {0}; + int objTypeBitFieldSize_ {0}; + int nativatePointerBindingSizeOffset_ {0}; + int nativatePointerBindingSize_ {0}; +}; +} // namespace rawheap_translate +#endif // METADATA_JSON_PARSE_H diff --git a/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.cpp b/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e47c1ec9d7016824a00b8b2b20a84575ef41b56 --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.cpp @@ -0,0 +1,558 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h" +#include "ecmascript/dfx/hprof/rawheap_translate/utils.h" + +namespace rawheap_translate { +bool RawHeapTranslate::Translate(const std::string &rawheapPath) +{ + uint32_t fileSize = 0; + std::ifstream rawheapFile; + if (!FileCheckAndOpenBinary(rawheapPath, rawheapFile, fileSize)) { + return false; + } + + std::vector sections; + if (!ParseMetaData(rawheapFile, fileSize) || + !ReadSectionInfo(rawheapFile, fileSize, sections) || + !ReadVersion(rawheapFile, 0, sections[0]) || + !ReadObjTableBySection(rawheapFile, sections) || + !ReadStringTable(rawheapFile, sections[2], sections[3]) || // 2: str offset, 3: str size + !ReadRootTable(rawheapFile, sections[0], sections[1])) { + return false; + } + + FillNodesAndBuildEdges(); + return true; +} + +bool RawHeapTranslate::ParseMetaData(std::ifstream &file, uint32_t &offset) +{ + cJSON *object = nullptr; + if (!ReadMetaDataJson(file, offset, &object)) { + return false; + } + + bool result = meta_->Parse(object); + DelMetaDataJson(object); + return result; +} + +bool RawHeapTranslate::ReadMetaDataJson(std::ifstream &file, uint32_t &offset, cJSON **json) +{ + auto result = CheckAndGetHead(file, offset - sizeof(uint64_t), 0); + if (!result.has_value()) { + LOG_ERROR("RawHeapTranslate::ReadMetaDataJson: metadata header error!"); + return false; + } + + auto [metaOffset, metaSize] = result.value(); + std::vector metaJson(metaSize); + if (!ReadFileAtOffset(file, metaOffset, metaSize, metaJson.data())) { + return false; + } + + cJSON *object = cJSON_ParseWithOpts(metaJson.data(), nullptr, true); + if (!object) { + LOG_ERROR("RawHeapTranslate::ReadMetaDataJson: json format error!"); + return false; + } + + *json = object; + offset = metaOffset; + return true; +} + +void RawHeapTranslate::DelMetaDataJson(cJSON *json) +{ + cJSON_Delete(json); +} + +bool RawHeapTranslate::ReadSectionInfo(std::ifstream &file, uint32_t endOffset, std::vector §ions) +{ + auto result = CheckAndGetHead(file, endOffset - sizeof(uint64_t), sizeof(uint32_t)); + if (!result.has_value()) { + LOG_ERROR("RawHeapTranslate::ReadSectionInfo: sections header error!"); + return false; + } + + auto [secSize, unitSize] = result.value(); + uint32_t sectionSize = secSize * unitSize; + std::vector sectionBytes(sectionSize); + if (!ReadFileAtOffset(file, endOffset - sectionSize - sizeof(uint64_t), sectionSize, sectionBytes.data())) { + return false; + } + + sections.resize(secSize); + ByteToU32Array(sectionBytes.data(), sections.data(), secSize); + LOG_INFO("RawHeapTranslate::ReadSectionInfo: sectionSize=" + std::to_string(secSize)); + return true; +} + +bool RawHeapTranslate::ReadVersion(std::ifstream &file, uint32_t offset, uint32_t size) +{ + std::vector version(size); + if (!ReadFileAtOffset(file, offset, size, version.data())) { + return false; + } + LOG_INFO("Rawheap version is " + std::string(version.data())); + return true; +} + +bool RawHeapTranslate::ReadObjTableBySection(std::ifstream &file, const std::vector §ions) +{ + LOG_INFO("RawHeapTranslate::Translate: start to read objects"); + // 4: index of obj table section start from 4 + // 2: step is 2 + for (size_t secIndex = 4; secIndex < sections.size(); secIndex += 2) { + uint32_t offset = sections[secIndex]; + uint32_t size = sections[secIndex + 1]; + if (!ReadObjTable(file, offset, size)) { + return false; + } + } + LOG_INFO("RawHeapTranslate::Translate: read objects finish!"); + return true; +} + +bool RawHeapTranslate::ReadObjTable(std::ifstream &file, uint32_t offset, uint32_t size) +{ + auto result = CheckAndGetHead(file, offset, sizeof(AddrTableItem)); + if (!result.has_value()) { + LOG_ERROR("RawHeapTranslate::ReadObjTable: obj table header error!"); + return false; + } + + auto [objNum, unitSize] = result.value(); + uint32_t baseOffset = sizeof(uint64_t) + offset; + std::vector objTable; + if (!ByteToAddrTableItem(file, baseOffset, objNum, objTable)) { + return false; + } + + uint32_t tableSize = objNum * unitSize; + uint32_t curOffset = baseOffset + tableSize; + uint32_t objMemSize = size - tableSize - sizeof(uint64_t); + char *objMem = new char[objMemSize]; + if (!ReadFileAtOffset(file, curOffset, objMemSize, objMem)) { + delete[] objMem; + return false; + } + memBuf_.emplace_back(objMem); + + for (uint32_t i = 0; i < objNum; i++) { + uint32_t nextOffset = i + 1 < objNum ? objTable[i + 1].offset : size - sizeof(uint64_t); + auto actSize = nextOffset - objTable[i].offset; + if (actSize != objTable[i].objSize && actSize != sizeof(uint64_t)) { + LOG_ERROR("RawHeapTranslate::ReadObjTable: expected objSize=" + std::to_string(objTable[i].objSize)); + continue; + } + uint32_t objMemOffset = objTable[i].offset - tableSize; + if (objMemOffset > objMemSize) { + LOG_ERROR("RawHeapTranslate::ReadObjTable: obj out of memory buf!"); + return false; + } + CreateNode(objTable[i], objMem + objMemOffset); + } + + LOG_INFO("RawHeapTranslate::ReadObjTable: read object, cnt=" + std::to_string(objNum)); + return true; +} + +bool RawHeapTranslate::ReadStringTable(std::ifstream &file, uint32_t offset, uint32_t size) +{ + if (size == 0) { + LOG_ERROR("RawHeapTranslate::ReadStringTable: string section size is 0"); + return false; + } + char *strSection = new char[size]; + if (!ReadFileAtOffset(file, offset, size, strSection)) { + delete[] strSection; + return false; + } + + uint32_t strNum = ByteToU32(strSection); + char *curStrSection = strSection + sizeof(uint32_t) * 2; + uint32_t strIndex = 0; + while (strIndex++ < strNum) { + uint32_t strSize = ByteToU32(curStrSection); + uint32_t objCnt = ByteToU32(curStrSection + sizeof(uint32_t)); + char *objAddr = curStrSection + sizeof(uint32_t) * 2; + uint32_t strOffset = sizeof(uint32_t) * 2 + sizeof(uint64_t) * objCnt; + char *str = curStrSection + strOffset; + StringId strId = strTable_->InsertStrAndGetStringId(std::string(str)); + SetNodeStringId(objAddr, objCnt, strId); + curStrSection += strOffset + strSize + 1; + } + + delete[] strSection; + LOG_INFO("RawHeapTranslate::ReadStringTable: read string table, cnt=" + std::to_string(strNum)); + return true; +} + +bool RawHeapTranslate::ReadRootTable(std::ifstream &file, uint32_t offset, uint32_t size) +{ + auto result = CheckAndGetHead(file, offset, sizeof(uint64_t)); + if (!result.has_value()) { + LOG_ERROR("RawHeapTranslate::ReadObjTable: obj table header error!"); + return false; + } + + auto [rootNum, unitSize] = result.value(); + std::vector roots(rootNum * unitSize); + if (!ReadFileAtOffset(file, offset + sizeof(uint64_t), rootNum * unitSize, roots.data())) { + return false; + } + + auto syntheticRoot = std::make_shared(Node(0)); + syntheticRoot->nodeId = 1; // 1: means root node + syntheticRoot->type = 9; // 9: means SYNTHETIC node type + syntheticRoot->strId = strTable_->InsertStrAndGetStringId("SyntheticRoot"); + nodes_.insert(nodes_.begin(), syntheticRoot); + StringId edgeStrId = strTable_->InsertStrAndGetStringId("-subroot-"); + EdgeType type = EdgeType::SHORTCUT; + + char *addr = roots.data(); + std::vector> rootEdges; + for (uint32_t i = 0; i < rootNum; i++) { + uint64_t rootAddr = ByteToU64(addr); + addr += sizeof(uint64_t); + auto rootNode = nodesMap_.find(rootAddr); + if (rootNode == nodesMap_.end()) { + continue; + } + auto edge = std::make_shared(Edge(type, syntheticRoot, rootNode->second, edgeStrId)); + rootEdges.emplace_back(edge); + syntheticRoot->edgeCount++; + } + + edges_.insert(edges_.begin(), rootEdges.begin(), rootEdges.end()); + LOG_INFO("RawHeapTranslate::ReadRootTable: find root obj " + std::to_string(rootNum)); + return true; +} + +bool RawHeapTranslate::ReadFileAtOffset(std::ifstream &file, uint32_t offset, uint32_t size, char *buf) +{ + if (buf == nullptr) { + LOG_ERROR("RawHeapTranslate::ReadFileAtOffset: file buf is nullptr!"); + return false; + } + if (!file.is_open()) { + LOG_ERROR("RawHeapTranslate::ReadFileAtOffset: file not open!"); + return false; + } + file.clear(); + if (!file.seekg(offset)) { + LOG_ERROR("RawHeapTranslate::ReadFileAtOffset: file set offset failed, offset=" + std::to_string(offset)); + return false; + } + if (file.read(buf, size).fail()) { + LOG_ERROR("RawHeapTranslate::ReadFileAtOffset: file read failed, offset=" + std::to_string(offset)); + return false; + } + return true; +} + +void RawHeapTranslate::CreateNode(AddrTableItem &item, char *data) +{ + static uint32_t nodeIndex = 1; + auto node = std::make_shared(Node(nodeIndex++)); + node->nodeId = item.id; + node->size = item.objSize; + node->data = data; + nodes_.emplace_back(node); + nodesMap_.emplace(item.addr, node); +} + +void RawHeapTranslate::FillNodesAndBuildEdges() +{ + LOG_INFO("RawHeapTranslate::FillNodesAndBuildEdges: start to build edges!"); + int missNodes = 0; + StringId hclassStrId = strTable_->InsertStrAndGetStringId("hclass"); + for (size_t i = 1; i < nodes_.size(); i++) { + auto node = nodes_[i]; + auto result = FindNodeFromAddr(ByteToU64(node->data), nullptr); + if (!result.has_value()) { + missNodes++; + continue; + } + auto hclass = result.value(); + FillNodes(node, hclass->data); + if (hclass->nodeId == node->nodeId) { + continue; + } + CreateEdge(node, hclass, EdgeType::DEFAULT, hclassStrId); + if (meta_->IsString(hclass->data)) { + continue; + } + BuildEdges(node, hclass->data); + } + LOG_INFO("RawHeapTranslate::FillNodesAndBuildEdges: build edges finish!"); + if (missNodes > 0) { + LOG_ERROR("RawHeapTranslate::FillNodesAndBuildEdges: " + std::to_string(missNodes) + " nodes missed hclass!"); + } +} + +void RawHeapTranslate::FillNodes(const std::shared_ptr &node, char *hclass) +{ + node->nativeSize = meta_->GetNativateSize(node->data, hclass); + node->type = meta_->GetNodeTypeFromHClass(hclass); + if (node->strId < 3 && !meta_->IsString(hclass)) { // 3: custom strId start from 3 + std::string name = meta_->GetTypeNameFromHClass(hclass); + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + node->strId = strTable_->InsertStrAndGetStringId(name); + } +} + +void RawHeapTranslate::BuildEdges(const std::shared_ptr &from, char *hclass) +{ + if (meta_->IsGlobalEnv(hclass)) { + BuildGlobalEnvEdges(from); + return; + } + + std::string typeName = meta_->GetTypeNameFromHClass(hclass); + auto visitor = [&from, this] (std::shared_ptr &metadata, uint32_t offset) { + if (!metadata->IsArray()) { + BuildFieldsEdges(from, metadata, offset); + return; + } + BuildArrayEdges(from, metadata, offset); + }; + uint32_t baseOffset = 0; + meta_->VisitObjectBody(typeName, visitor, baseOffset); + BuildJSObjectInlEdges(from, hclass, baseOffset); +} + +void RawHeapTranslate::BuildFieldsEdges( + const std::shared_ptr &from, const std::shared_ptr &metadata, uint32_t offset) +{ + for (const auto &field : metadata->fields) { + if (field->size != sizeof(uint64_t) || offset + sizeof(uint64_t) > from->size) { + continue; + } + uint64_t addr = ByteToU64(from->data + offset + field->offset); + EdgeType type = EdgeType::DEFAULT; + auto result = FindNodeFromAddr(addr, &type); + if (!result.has_value()) { + continue; + } + StringId strId = strTable_->InsertStrAndGetStringId(field->name); + CreateEdge(from, result.value(), type, strId); + } +} + +void RawHeapTranslate::BuildGlobalEnvEdges(const std::shared_ptr &from) +{ + uint32_t index = sizeof(uint64_t); + while ((index + sizeof(uint64_t)) < from->size) { + uint64_t addr = ByteToU64(from->data + index); + index += sizeof(uint64_t); + auto result = FindNodeFromAddr(addr, nullptr); + if (!result.has_value()) { + continue; + } + CreateEdge(from, result.value(), EdgeType::DEFAULT, result.value()->strId); + } +} + +void RawHeapTranslate::BuildArrayEdges( + const std::shared_ptr &from, const std::shared_ptr &metadata, uint32_t offset) +{ + auto lengthField = FindFieldInMetaData(metadata, "Length"); + auto dataField = FindFieldInMetaData(metadata, "Data"); + if (!lengthField || !dataField) { + LOG_ERROR("RawHeapTranslate::BuildArrayEdges: field length or data of array not found!"); + return; + } + + uint32_t len = ByteToU32(from->data + offset + lengthField->offset); + uint32_t step = dataField->size; + if (step != sizeof(uint64_t) || len <= 0 || len * step + offset > from->size) { + return; + } + + uint32_t index = offset + dataField->offset; + uint32_t itemIndex = 0; + uint32_t itemCnt = 0; + while (itemCnt++ < len && index < from->size) { + uint64_t addr = ByteToU64(from->data + index); + index += step; + auto result = FindNodeFromAddr(addr, nullptr); + if (!result.has_value()) { + continue; + } + CreateEdge(from, result.value(), EdgeType::ELEMENT, itemIndex++); + } +} + +void RawHeapTranslate::BuildDictionaryEdges( + const std::shared_ptr &from, const std::shared_ptr &metadata, uint32_t offset) +{ + auto lengthField = FindFieldInMetaData(metadata, "Length"); + auto dataField = FindFieldInMetaData(metadata, "Data"); + auto layout = meta_->GetObjectLayout("Dictionary"); + if (!lengthField || !dataField || !layout) { + LOG_ERROR("RawHeapTranslate::BuildDictionaryEdges: field length or data or layout of dictionary not found!"); + return; + } + + uint32_t len = ByteToU32(from->data + offset + lengthField->offset); + uint32_t step = dataField->size; + if (step != sizeof(uint64_t) || len <= 0 || len * step + offset > from->size) { + return; + } + + uint32_t eleIndex = 0; + uint32_t index = offset + dataField->offset + layout->headerSize * step; + while (index < from->size) { + std::vector item(layout->entrySize); + ByteToU64Array(from->data + index, item.data(), layout->entrySize); + index += layout->entrySize * step; + + auto value = FindNodeFromAddr(item[layout->valueIndex], nullptr); + if (!value.has_value()) { + continue; + } + CreateEdge(from, value.value(), EdgeType::ELEMENT, eleIndex++); + } +} + +void RawHeapTranslate::BuildJSObjectInlEdges(const std::shared_ptr &from, char *hclass, uint32_t offset) +{ + if (!meta_->IsJSObject(hclass)) { + return; + } + + StringId strId = strTable_->InsertStrAndGetStringId("InlineProperty"); + uint32_t propOffset = offset; + while (propOffset + sizeof(uint64_t) <= from->size) { + uint64_t addr = ByteToU64(from->data + propOffset); + propOffset += sizeof(uint64_t); + auto result = FindNodeFromAddr(addr, nullptr); + if (!result.has_value()) { + continue; + } + CreateEdge(from, result.value(), EdgeType::DEFAULT, strId); + } +} + +void RawHeapTranslate::CreateEdge( + const std::shared_ptr &from, const std::shared_ptr &to, EdgeType type, uint32_t index) +{ + auto edge = std::make_shared(Edge(type, from, to, index)); + edges_.emplace_back(edge); + from->edgeCount++; +} + +void RawHeapTranslate::SetNodeStringId(char *addr, uint32_t size, StringId strId) +{ + char *objAddr = addr; + for (uint32_t i = 0; i < size; i++) { + auto node = nodesMap_.find(ByteToU64(objAddr)); + if (node != nodesMap_.end()) { + node->second->strId = strId; + } + objAddr += sizeof(uint64_t); + } +} + +bool RawHeapTranslate::ByteToAddrTableItem( + std::ifstream &file, uint32_t offset, uint32_t objNum, std::vector &table) +{ + uint32_t unitSize = sizeof(AddrTableItem); + uint32_t tableSize = objNum * unitSize; + std::vector tableByte(tableSize); + if (!ReadFileAtOffset(file, offset, tableSize, tableByte.data())) { + return false; + } + table.resize(objNum); + char *item = tableByte.data(); + for (uint32_t i = 0; i < objNum; i++) { + table[i].addr = ByteToU64(item); + item += sizeof(uint64_t); + + table[i].id = ByteToU64(item); + item += sizeof(uint64_t); + + table[i].objSize = ByteToU32(item); + item += sizeof(uint32_t); + + table[i].offset = ByteToU32(item); + item += sizeof(uint32_t); + } + return true; +} + +std::optional> RawHeapTranslate::FindNodeFromAddr(uint64_t addr, EdgeType *type) +{ + if (!IsHeapObject(addr)) { + return std::nullopt; + } + CheckAndRemoveWeak(addr, type); + auto node = nodesMap_.find(addr); + if (node == nodesMap_.end()) { + return std::nullopt; + } + return node->second; +} + +std::optional> RawHeapTranslate::CheckAndGetHead( + std::ifstream &file, uint32_t offset, uint32_t assertNum) +{ + uint32_t headSize = sizeof(uint64_t); + std::vector head(headSize); + if (!ReadFileAtOffset(file, offset, headSize, head.data())) { + return std::nullopt; + } + + uint32_t firstNum = ByteToU32(head.data()); + uint32_t secondNum = ByteToU32(head.data() + sizeof(uint32_t)); + if (assertNum != 0 && secondNum != assertNum) { + return std::nullopt; + } + + return std::pair(firstNum, secondNum); +} + +std::shared_ptr RawHeapTranslate::FindFieldInMetaData( + const std::shared_ptr &metadata, const std::string &name) +{ + for (const auto &field : metadata->fields) { + if (field->name == name) { + return field; + } + } + return nullptr; +} + +void RawHeapTranslate::CheckAndRemoveWeak(uint64_t &addr, EdgeType *type) +{ + if ((addr & TAG_WEAK_MASK) == TAG_WEAK) { + addr &= (~TAG_WEAK); + if (type != nullptr) { + *type = EdgeType::WEAK; + } + } +} + +bool RawHeapTranslate::IsHeapObject(uint64_t addr) +{ + return ((addr & TAG_HEAPOBJECT_MASK) == 0U); +} +} // namespace rawheap_translate \ No newline at end of file diff --git a/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h b/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h new file mode 100644 index 0000000000000000000000000000000000000000..e5beed3b2ef0676b54d2dc0a002a0d765d023903 --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RAWHEAP_TRANSLATE_H +#define RAWHEAP_TRANSLATE_H + +#include +#include +#include "ecmascript/dfx/hprof/rawheap_translate/metadata_parse.h" +#include "ecmascript/dfx/hprof/rawheap_translate/string_hashmap.h" + +namespace rawheap_translate { +struct AddrTableItem { + uint64_t addr; + uint64_t id; + uint32_t objSize; + uint32_t offset; // offset to the file +}; + +struct Node { + uint64_t nodeId; // Range from 1 + uint32_t index; + StringId strId; + uint8_t type; + uint32_t size; + uint32_t nativeSize; + size_t edgeCount; + char *data; + + Node(uint32_t nodeIndex) + : nodeId(0), + index(nodeIndex), + strId(1), // 1: for empty string + type(8), // 8: default node type + size(0), + nativeSize(0), + edgeCount(0), + data(nullptr) + { + } +}; + +enum class EdgeType { CONTEXT, ELEMENT, PROPERTY, INTERNAL, HIDDEN, SHORTCUT, WEAK, DEFAULT = PROPERTY }; + +struct Edge { + EdgeType type; + std::shared_ptr from; + std::shared_ptr to; + uint32_t nameOrIndex; + + Edge(EdgeType edgeType, std::shared_ptr nodeFrom, std::shared_ptr nodeTo, uint32_t index) + : type(edgeType), + from(nodeFrom), + to(nodeTo), + nameOrIndex(index) + { + } +}; + +class RawHeapTranslate { +public: + RawHeapTranslate() + : meta_(std::make_unique(Meta())), + strTable_(std::make_shared(StringHashMap())) {} + + ~RawHeapTranslate() + { + for (auto mem : memBuf_) { + delete mem; + } + memBuf_.clear(); + nodes_.clear(); + edges_.clear(); + nodesMap_.clear(); + } + + bool Translate(const std::string &rawheapPath); + + std::vector> GetNodes() + { + return nodes_; + } + + std::vector> GetEdges() + { + return edges_; + } + + std::shared_ptr GetEcmaStringTable() + { + return strTable_; + } + + size_t GetNodeCount() + { + return nodes_.size(); + } + + size_t GetEdgeCount() + { + return edges_.size(); + } + +private: + bool ParseMetaData(std::ifstream &file, uint32_t &offset); + bool ReadMetaDataJson(std::ifstream &file, uint32_t &offset, cJSON **json); + void DelMetaDataJson(cJSON *json); + + bool ReadSectionInfo(std::ifstream &file, uint32_t endOffset, std::vector §ions); + bool ReadVersion(std::ifstream &file, uint32_t offset, uint32_t size); + bool ReadObjTableBySection(std::ifstream &file, const std::vector §ions); + bool ReadObjTable(std::ifstream &file, uint32_t offset, uint32_t size); + bool ReadStringTable(std::ifstream &file, uint32_t offset, uint32_t size); + bool ReadRootTable(std::ifstream &file, uint32_t offset, uint32_t size); + bool ReadFileAtOffset(std::ifstream &file, uint32_t offset, uint32_t size, char *buf); + + void CreateNode(AddrTableItem &item, char *data); + void FillNodesAndBuildEdges(); + void FillNodes(const std::shared_ptr &node, char *hclass); + void BuildEdges(const std::shared_ptr &from, char *hclass); + void BuildFieldsEdges( + const std::shared_ptr &from, const std::shared_ptr &metadata, uint32_t offset); + void BuildGlobalEnvEdges(const std::shared_ptr &from); + void BuildArrayEdges(const std::shared_ptr &from, const std::shared_ptr &metadata, uint32_t offset); + void BuildDictionaryEdges( + const std::shared_ptr &from, const std::shared_ptr &metadata, uint32_t offset); + void BuildJSObjectInlEdges(const std::shared_ptr &from, char *hclass, uint32_t offset); + void CreateEdge(const std::shared_ptr &from, const std::shared_ptr &to, EdgeType type, uint32_t index); + void SetNodeStringId(char *addr, uint32_t size, StringId strId); + bool ByteToAddrTableItem(std::ifstream &file, uint32_t offset, uint32_t objNum, std::vector &table); + std::optional> FindNodeFromAddr(uint64_t addr, EdgeType *type); + std::optional> CheckAndGetHead( + std::ifstream &file, uint32_t offset, uint32_t assertNum); + + static std::shared_ptr FindFieldInMetaData( + const std::shared_ptr &metadata, const std::string &name); + static void CheckAndRemoveWeak(uint64_t &addr, EdgeType *type); + static bool IsHeapObject(uint64_t addr); + static constexpr uint64_t TAG_WEAK = 0x01ULL; + static constexpr uint64_t TAG_WEAK_MASK = 0x01ULL; + static constexpr uint64_t TAG_HEAPOBJECT_MASK = (0xFFFFULL << 48) | 0x02ULL | 0x04ULL; // 48 means 6 byte shift + + std::vector memBuf_ {}; + std::unique_ptr meta_ {nullptr}; + std::shared_ptr strTable_ {nullptr}; + std::vector> nodes_ {}; + std::vector> edges_ {}; + std::unordered_map> nodesMap_ {}; +}; + +} // namespace rawheap_translate +#endif \ No newline at end of file diff --git a/ecmascript/dfx/hprof/rawheap_translate/serializer.cpp b/ecmascript/dfx/hprof/rawheap_translate/serializer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4990ae641f141fec51b586e4cd95f5241b91dd13 --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/serializer.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/dfx/hprof/rawheap_translate/serializer.h" +#include "ecmascript/dfx/hprof/rawheap_translate/string_hashmap.h" + +namespace rawheap_translate { +bool StreamWriter::Initialize(const std::string &filePath) +{ + if (filePath.empty() || filePath.size() > PATH_MAX) { + LOG_ERROR("filename is illegal!"); + return false; + } + + fileStream_.open(filePath, std::ios::out); + if (fileStream_.fail()) { + LOG_ERROR("FileStream: open file failed"); + return false; + } + + return true; +} + +void StreamWriter::WriteString(const std::string &str) +{ + MaybeWriteChunk(); + auto len = str.size(); + if (len == 0) { + return; + } + const char *cur = str.c_str(); + const char *end = cur + len; + while (cur < end) { + int dstSize = chunkSize_ - current_; + int writeSize = std::min(static_cast(end - cur), dstSize); + if (writeSize <= 0) { + break; + } + if (memcpy_s(chunk_.data() + current_, dstSize, cur, writeSize) != EOK) { + LOG_ERROR("StreamWriter::WriteString: memcpy_s failed!"); + break; + } + cur += writeSize; + current_ += writeSize; + MaybeWriteChunk(); + } +} + +void StreamWriter::EndOfStream() +{ + if (current_ > 0) { + std::string str(chunk_.data(), current_); + fileStream_ << str; + current_ = 0; + } + if (fileStream_.is_open()) { + fileStream_.close(); + } +} + +bool HeapSnapshotJSONSerializer::Serialize(RawHeapTranslate *snapshot, StreamWriter *writer) +{ + // Serialize Node/Edge/String-Table + LOG_INFO("HeapSnapshotJSONSerializer::Serialize begin"); + + SerializeSnapshotHeader(snapshot, writer); // 1. + SerializeNodes(snapshot, writer); // 2. + SerializeEdges(snapshot, writer); // 3. + + writer->WriteString("\"trace_function_infos\":[],"); // 4. + writer->WriteString("\"trace_tree\":[],"); + writer->WriteString("\"samples\":[],"); + writer->WriteString("\"locations\":[],\n"); + + SerializeStringTable(snapshot, writer); // 8. + SerializerSnapshotClosure(writer); // 9. + + LOG_INFO("HeapSnapshotJSONSerializer::Serialize exit"); + return true; +} + +void HeapSnapshotJSONSerializer::SerializeSnapshotHeader(RawHeapTranslate *snapshot, StreamWriter *writer) +{ + writer->WriteString("{\"snapshot\":\n"); // 1. + writer->WriteString("{\"meta\":\n"); // 2. + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("{\"node_fields\":[\"type\",\"name\",\"id\",\"self_size\",\"edge_count\",\"trace_node_id\","); + writer->WriteString("\"detachedness\",\"native_size\"],\n"); // 3. + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("\"node_types\":[[\"hidden\",\"array\",\"string\",\"object\",\"code\",\"closure\",\"regexp\","); + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("\"number\",\"native\",\"synthetic\",\"concatenated string\",\"slicedstring\",\"symbol\","); + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("\"bigint\"],\"string\",\"number\",\"number\",\"number\",\"number\",\"number\"],\n"); // 4. + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("\"edge_fields\":[\"type\",\"name_or_index\",\"to_node\"],\n"); // 5. + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("\"edge_types\":[[\"context\",\"element\",\"property\",\"internal\",\"hidden\",\"shortcut\","); + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("\"weak\"],\"string_or_number\",\"node\"],\n"); // 6. + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("\"trace_function_info_fields\":[\"function_id\",\"name\",\"script_name\",\"script_id\","); + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("\"line\",\"column\"],\n"); // 7. + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("\"trace_node_fields\":[\"id\",\"function_info_index\",\"count\",\"size\",\"children\"],\n"); + // NOLINTNEXTLINE(modernize-raw-string-literal) + writer->WriteString("\"sample_fields\":[\"timestamp_us\",\"last_assigned_id\"],\n"); // 9. + // NOLINTNEXTLINE(modernize-raw-string-literal) + // 10. + writer->WriteString("\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]},\n\"node_count\":"); + writer->WriteNumber(snapshot->GetNodeCount()); // 11. + writer->WriteString(",\n\"edge_count\":"); + writer->WriteNumber(snapshot->GetEdgeCount()); // 12. + writer->WriteString(",\n\"trace_function_count\":"); + writer->WriteNumber(0); // 13. + writer->WriteString("\n},\n"); // 14. +} + +void HeapSnapshotJSONSerializer::SerializeNodes(RawHeapTranslate *snapshot, StreamWriter *writer) +{ + auto nodes = snapshot->GetNodes(); + writer->WriteString("\"nodes\":["); // Section Header + size_t i = 0; + for (auto node : nodes) { + if (i > 0) { + writer->WriteChar(','); // add comma except first line + } + writer->WriteNumber(node->type); // 1. + writer->WriteChar(','); + writer->WriteNumber(node->strId); // 2. + writer->WriteChar(','); + writer->WriteNumber(node->nodeId); // 3. + writer->WriteChar(','); + writer->WriteNumber(node->size); // 4. + writer->WriteChar(','); + writer->WriteNumber(node->edgeCount); // 5. + writer->WriteChar(','); + writer->WriteNumber(0); // 6. + writer->WriteChar(','); + writer->WriteChar('0'); // 7.detachedness default 0 + writer->WriteChar(','); + writer->WriteNumber(node->nativeSize); + if (i == nodes.size() - 1) { // add comma at last the line + writer->WriteString("],\n"); // 7. detachedness default + } else { + writer->WriteString("\n"); // 7. + } + i++; + } +} + +void HeapSnapshotJSONSerializer::SerializeEdges(RawHeapTranslate *snapshot, StreamWriter *writer) +{ + auto edges = snapshot->GetEdges(); + writer->WriteString("\"edges\":["); + size_t i = 0; + for (auto edge : edges) { + if (i > 0) { // add comma except the first line + writer->WriteChar(','); + } + writer->WriteNumber(static_cast(edge->type)); // 1. + writer->WriteChar(','); + writer->WriteNumber(static_cast(edge->nameOrIndex)); // 2. Use StringId + writer->WriteChar(','); + + if (i == edges.size() - 1) { // add comma at last the line + writer->WriteNumber(edge->to->index * NODE_FIELD_COUNT); // 3. + writer->WriteString("],\n"); + } else { + writer->WriteNumber(edge->to->index * NODE_FIELD_COUNT); // 3. + writer->WriteChar('\n'); + } + i++; + } +} + +void HeapSnapshotJSONSerializer::SerializeStringTable(RawHeapTranslate *snapshot, StreamWriter *writer) +{ + auto stringTable = snapshot->GetEcmaStringTable(); + writer->WriteString("\"strings\":[\"\",\n"); + writer->WriteString("\"\",\n"); + writer->WriteString("\"GC roots\",\n"); + // StringId Range from 3 + size_t capcity = stringTable->GetCapcity(); + if (capcity <= 0) { + return; + } + size_t i = 0; + for (auto key : stringTable->GetOrderedKeyStorage()) { + if (i == capcity - 1) { + writer->WriteChar('\"'); + SerializeString(stringTable->GetStringByKey(key).c_str(), writer); // No Comma for the last line + writer->WriteString("\"\n"); + } else { + writer->WriteChar('\"'); + SerializeString(stringTable->GetStringByKey(key).c_str(), writer); + writer->WriteString("\",\n"); + } + i++; + } + writer->WriteString("]\n"); +} + +void HeapSnapshotJSONSerializer::SerializeString(const char *str, StreamWriter *writer) +{ + if (str == nullptr || writer == nullptr) { + return; + } + const char *s = str; + while (*s != '\0') { + if (*s == '\"' || *s == '\\') { + writer->WriteChar('\\'); + writer->WriteChar(*s); + s++; + } else if (*s == '\n') { + writer->WriteString("\\n"); + s++; + } else if (*s == '\b') { + writer->WriteString("\\b"); + s++; + } else if (*s == '\f') { + writer->WriteString("\\f"); + s++; + } else if (*s == '\r') { + writer->WriteString("\\r"); + s++; + } else if (*s == '\t') { + writer->WriteString("\\t"); + s++; + } else if (*s > ASCII_US && *s < ASCII_DEL) { + writer->WriteChar(*s); + s++; + } else { + writer->WriteChar(*s); + s++; + } + } +} + +void HeapSnapshotJSONSerializer::SerializerSnapshotClosure(StreamWriter *writer) +{ + writer->WriteString("}\n"); +} + +} // namespace rawheap_translate diff --git a/ecmascript/dfx/hprof/rawheap_translate/serializer.h b/ecmascript/dfx/hprof/rawheap_translate/serializer.h new file mode 100644 index 0000000000000000000000000000000000000000..15c1a0046b4bf72d209391396fc2475873c1acfb --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/serializer.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RAWHEAP_TRANSLATE_SERIALIZER_H +#define RAWHEAP_TRANSLATE_SERIALIZER_H + +#define NODE_FIELD_COUNT 8 +#include "ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h" +#include "ecmascript/dfx/hprof/rawheap_translate/utils.h" + + +namespace rawheap_translate { +class StreamWriter { +public: + StreamWriter() + { + chunk_.resize(chunkSize_); + } + + ~StreamWriter() + { + EndOfStream(); + } + + bool Initialize(const std::string &filePath); + void WriteString(const std::string &str); + void EndOfStream(); + + void WriteChar(char c) + { + if (c == '\0') { + return; + } + MaybeWriteChunk(); + chunk_[current_++] = c; + } + + void WriteNumber(uint64_t num) + { + WriteString(std::to_string(num)); + } + +private: + void MaybeWriteChunk() + { + if (current_ == chunkSize_) { + std::string str(chunk_.begin(), chunk_.end()); + fileStream_ << str; + current_ = 0; + } + } + + std::ofstream fileStream_; + std::vector chunk_; + int current_ {0}; + int chunkSize_ {1024 * 1024}; +}; + +class HeapSnapshotJSONSerializer { +public: + explicit HeapSnapshotJSONSerializer() = default; + ~HeapSnapshotJSONSerializer() = default; + + static bool Serialize(RawHeapTranslate *snapshot, StreamWriter *writer); + +private: + static constexpr char ASCII_US = 31; + static constexpr char ASCII_DEL = 127; + static constexpr uint8_t UTF8_MAX_BYTES = 4; + +private: + static void SerializeSnapshotHeader(RawHeapTranslate *snapshot, StreamWriter *writer); + static void SerializeNodes(RawHeapTranslate *snapshot, StreamWriter *writer); + static void SerializeEdges(RawHeapTranslate *snapshot, StreamWriter *writer); + static void SerializeStringTable(RawHeapTranslate *snapshot, StreamWriter *writer); + static void SerializeString(const char *str, StreamWriter *writer); + static void SerializerSnapshotClosure(StreamWriter *writer); +}; +} // namespace rawheap_translate +#endif \ No newline at end of file diff --git a/test/fuzztest/jsnapifork_fuzzer/jsnapifork_fuzzer.cpp b/ecmascript/dfx/hprof/rawheap_translate/string_hashmap.cpp similarity index 38% rename from test/fuzztest/jsnapifork_fuzzer/jsnapifork_fuzzer.cpp rename to ecmascript/dfx/hprof/rawheap_translate/string_hashmap.cpp index e96adebd2a97307c59a9f584986e8d6a19078b85..107f3cd71f8ba4295b1747c9d35e9e81529855e8 100644 --- a/test/fuzztest/jsnapifork_fuzzer/jsnapifork_fuzzer.cpp +++ b/ecmascript/dfx/hprof/rawheap_translate/string_hashmap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,35 +13,35 @@ * limitations under the License. */ -#include "ecmascript/ecma_string-inl.h" -#include "ecmascript/js_runtime_options.h" -#include "ecmascript/napi/include/jsnapi.h" -#include "jsnapifork_fuzzer.h" +#include "ecmascript/dfx/hprof/rawheap_translate/string_hashmap.h" -using namespace panda; -using namespace panda::ecmascript; +namespace rawheap_translate { +std::string StringHashMap::GetStringByKey(StringKey key) const +{ + auto it = hashmap_.find(key); + if (it != hashmap_.end()) { + return it->second; + } + return ""; +} -namespace OHOS { - void JSNApiPreForkFuzzTest(const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (data == nullptr || size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - uint8_t* ptr = nullptr; - ptr = const_cast(data); - JSNApi::PreFork(vm); - JSNApi::DestroyJSVM(vm); +StringId StringHashMap::InsertStrAndGetStringId(const std::string &str) +{ + StringKey key = GenerateStringKey(str); + auto it = indexMap_.find(key); + if (it != indexMap_.end()) { + return it->second; + } else { // NOLINT(readability-else-after-return) + index_++; + hashmap_.emplace(key, str); + orderedKey_.emplace_back(key); + indexMap_.emplace(key, index_); + return index_; } } -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +StringKey StringHashMap::GenerateStringKey(const std::string &str) const { - // Run your code on data. - OHOS::JSNApiPreForkFuzzTest(data, size); - return 0; -} \ No newline at end of file + return std::hash{} (str); +} +} // namespace rawheap_translate diff --git a/ecmascript/dfx/hprof/rawheap_translate/string_hashmap.h b/ecmascript/dfx/hprof/rawheap_translate/string_hashmap.h new file mode 100644 index 0000000000000000000000000000000000000000..52f33e1438e32a57c3c356ba88c1eae75dcb36c3 --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/string_hashmap.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RAWHEAP_TRANSLATE_STRING_HASHMAP_H +#define RAWHEAP_TRANSLATE_STRING_HASHMAP_H + +#include "ecmascript/dfx/hprof/rawheap_translate/utils.h" + +namespace rawheap_translate { +using StringKey = size_t; +using StringId = uint32_t; + +// An Implementation for Native StringTable without Auto Mem-Management +// To make sure when using String, it still stays where it was. +class StringHashMap { +public: + explicit StringHashMap() + { + } + + ~StringHashMap() + { + } + + /* + * Get all keys sorted by insert order + */ + const std::vector &GetOrderedKeyStorage() const + { + return orderedKey_; + } + /* + * Get string by its hash key + */ + std::string GetStringByKey(StringKey key) const; + StringId InsertStrAndGetStringId(const std::string &cstrArg); + size_t GetCapcity() const + { + return orderedKey_.size(); + } + +private: + StringKey GenerateStringKey(const std::string &cstr) const; + std::vector orderedKey_; // Used for Serialize Order + size_t index_ {2}; // 2: Offset the String-Table Header + std::unordered_map indexMap_; + std::unordered_map hashmap_; +}; +} // namespace rawheap_translate +#endif // RAWHEAP_TRANSLATE_STRING_HASHMAP_H diff --git a/ecmascript/dfx/hprof/rawheap_translate/utils.cpp b/ecmascript/dfx/hprof/rawheap_translate/utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..076846f8025a03288f16a7e598cbcdace409ada6 --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/utils.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef _WIN32 +#include +#else +#include +#endif +#include +#include +#include +#include "ecmascript/dfx/hprof/rawheap_translate/utils.h" + +namespace rawheap_translate { +bool CheckVersion(const std::string &version) +{ + std::vector result {}; + std::stringstream ss(version); + std::string token; + while (getline(ss, token, '.')) { + int number; + std::istringstream(token) >> number; + result.push_back(number); + } + + // 3: means the version format is x.x.x + if (result.size() != 3) { + LOG_ERROR("current version " + version + " is illegal!"); + return false; + } + + bool majorVersionCheckFalse = result[MAJOR_VERSION_INDEX] > VERSION[MAJOR_VERSION_INDEX]; + bool minorVersionCheckFalse = result[MAJOR_VERSION_INDEX] == VERSION[MAJOR_VERSION_INDEX] && + result[MINOR_VERSION_INDEX] > VERSION[MINOR_VERSION_INDEX]; + bool buildVersionCheckFalse = result[MAJOR_VERSION_INDEX] == VERSION[MAJOR_VERSION_INDEX] && + result[MINOR_VERSION_INDEX] == VERSION[MINOR_VERSION_INDEX] && + result[BUILD_VERSION_INDEX] > VERSION[BUILD_VERSION_INDEX]; + if (majorVersionCheckFalse || minorVersionCheckFalse || buildVersionCheckFalse) { + std::ostringstream oss; + oss << "The rawheap file's version " << version; + oss << " is not matched the current rawheap translator, please use the newest version of the translator!"; + LOG_ERROR(oss.str()); + return false; + }; + return true; +} + +bool RealPath(const std::string &filename, std::string &realpath) +{ + if (filename.empty() || filename.size() > PATH_MAX) { + LOG_ERROR("filename is illegal!"); + return false; + } + +#ifdef _WIN32 + if (_access(filename.c_str(), 0) < 0) { +#else + if (access(filename.c_str(), 0) < 0) { +#endif + LOG_ERROR("file can not access! filePath=" + filename); + return false; + } + + char resolvedPath[PATH_MAX]; + if (strcpy_s(resolvedPath, PATH_MAX, filename.c_str()) != 0) { + return false; + } + + realpath = resolvedPath; + return true; +} + +uint64_t GetFileSize(std::string &inputFilePath) +{ + if (inputFilePath.empty()) { + return 0; + } + struct stat fileInfo; + if (stat(inputFilePath.c_str(), &fileInfo) == 0) { + return fileInfo.st_size; + } + return 0; +} + +bool FileCheckAndOpenBinary(const std::string &rawheapPath, std::ifstream &file, uint32_t &fileSize) +{ + std::string realpath {}; + if (!RealPath(rawheapPath, realpath)) { + LOG_ERROR("file path is illegal! filePath: " + rawheapPath); + return false; + } + + uint64_t size = GetFileSize(realpath); + if (size == 0 || size >= MAX_FILE_SIZE) { + LOG_ERROR("file size >= 4GB or size = 0, unsupported!"); + return false; + } + + fileSize = static_cast(size); + file.open(realpath, std::ios::binary); + return true; +} + +bool GenerateDumpFileName(std::string &filename) +{ + std::time_t t = std::time(nullptr); + struct tm *now = localtime(&t); + if (now == nullptr) { + LOG_ERROR("Failed to converting time to local time!"); + return false; + } + + filename = "hprof_"; + const int timeStart = 1900; // 1900: means the start of timestamp + filename += std::to_string(now->tm_year + timeStart); + filename += '-' + std::to_string(now->tm_mon + 1); + filename += '-' + std::to_string(now->tm_mday); + filename += '-' + std::to_string(now->tm_hour); + filename += '-' + std::to_string(now->tm_min); + filename += '-' + std::to_string(now->tm_sec); + filename += ".heapsnapshot"; + return true; +} + +bool EndsWith(const std::string &str, const std::string &suffix) +{ + if (str.length() < suffix.length()) { + return false; + } + std::string subStr = str.substr(str.length() - suffix.length(), str.length()); + return subStr == suffix; +} + +bool IsLittleEndian() +{ + int i = 1; + return *reinterpret_cast(&i) == 1; +} + +uint32_t ByteToU32(char *data) +{ + uint32_t value = *reinterpret_cast(data); + if (!IsLittleEndian()) { + value = (value & 0x000000FF) << 24 | + (value & 0x0000FF00) << 8 | + (value & 0x00FF0000) >> 8 | + (value & 0xFF000000) >> 24; + } + return value; +} + +uint64_t ByteToU64(char *data) +{ + uint64_t value = *reinterpret_cast(data); + if (!IsLittleEndian()) { + value = (value & 0x00000000000000FF) << 56 | + (value & 0x000000000000FF00) << 40 | + (value & 0x0000000000FF0000) << 24 | + (value & 0x00000000FF000000) << 8 | + (value & 0x000000FF00000000) >> 8 | + (value & 0x0000FF00000000) >> 24 | + (value & 0x00FF0000000000) >> 40 | + (value & 0xFF000000000000) >> 56; + } + return value; +} + +void ByteToU32Array(char *data, uint32_t *array, uint32_t size) +{ + char *num = data; + for (uint32_t i = 0; i < size; i++) { + array[i] = ByteToU32(num); + num += sizeof(uint32_t); + } +} + +void ByteToU64Array(char *data, uint64_t *array, uint32_t size) +{ + char *num = data; + for (uint32_t i = 0; i < size; i++) { + array[i] = ByteToU64(num); + num += sizeof(uint64_t); + } +} +} // namespace rawheap_translate \ No newline at end of file diff --git a/ecmascript/dfx/hprof/rawheap_translate/utils.h b/ecmascript/dfx/hprof/rawheap_translate/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..724d5543d8324512cbc77fceba33a5005050c65a --- /dev/null +++ b/ecmascript/dfx/hprof/rawheap_translate/utils.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RAWHEAP_TRANSLATE_UTILS_H +#define RAWHEAP_TRANSLATE_UTILS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rawheap_translate { +#define LOG_ERROR(msg) std::cerr << "[ERRO] " << (msg) << std::endl +#define LOG_INFO(msg) std::cout << "[INFO] " << (msg) << std::endl +#ifdef PATH_MAX +#undef PATH_MAX +#endif +#define PATH_MAX 4096 +#define MAX_FILE_SIZE (4 * 1024 * 1024 * 1024ULL) // 4 * 1024 * 1024 * 1024 : file size bigger than 4GB +#define MAX_OBJ_SIZE (MAX_FILE_SIZE >> 1) + +static const int MAJOR_VERSION_INDEX = 0; +static const int MINOR_VERSION_INDEX = 1; +static const int BUILD_VERSION_INDEX = 2; +static const int VERSION[3] = {1, 0, 0}; + +bool CheckVersion(const std::string &version); + +bool RealPath(const std::string &filename, std::string &realpath); + +uint64_t GetFileSize(std::string &inputFilePath); + +bool FileCheckAndOpenBinary(const std::string &rawheapPath, std::ifstream &file, uint32_t &fileSize); + +bool GenerateDumpFileName(std::string &filename); + +bool EndsWith(const std::string &str, const std::string &suffix); + +bool IsLittleEndian(); + +uint32_t ByteToU32(char *data); + +uint64_t ByteToU64(char *data); + +void ByteToU32Array(char *data, uint32_t *array, uint32_t size); + +void ByteToU64Array(char *data, uint64_t *array, uint32_t size); +} // namespace rawheap_translate +#endif \ No newline at end of file diff --git a/ecmascript/dfx/hprof/tests/BUILD.gn b/ecmascript/dfx/hprof/tests/BUILD.gn index 27b8c119c12a74665728fa33b3b09c1eed0d6096..4109adeb10b6e59c0041ee170eb34efb901d0ad3 100644 --- a/ecmascript/dfx/hprof/tests/BUILD.gn +++ b/ecmascript/dfx/hprof/tests/BUILD.gn @@ -14,7 +14,11 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" + +metadata_file_path = "//arkcompiler/ets_runtime/ecmascript/js_type_metadata/" + +target_test_path = "/tests/unittest/arkcompiler/ets_runtime/resource/obj/arkcompiler/ets_runtime/ecmascript/dfx/hprof/tests" test_js_path = "//arkcompiler/ets_runtime/ecmascript/dfx/hprof/tests/js_files/" @@ -228,6 +232,80 @@ host_unittest_action("HeapSamplingTest") { deps += hiviewdfx_deps } +host_unittest_action("RawHeapTranslateTest") { + module_out_path = module_output_path + + sources = [ + # test file + "../rawheap_translate/metadata_parse.cpp", + "../rawheap_translate/utils.cpp", + "rawheap_translate_test.cpp", + ] + + configs = [ "$js_root:ecma_test_config" ] + + deps = [ + "$ark_third_party_root/icu/icu4c:shared_icui18n", + "$ark_third_party_root/icu/icu4c:shared_icuuc", + "$js_root:libark_jsruntime_test", + sdk_libc_secshared_dep, + ] + + cflags_cc = [ "-std=c++17" ] + + external_deps = [ + "bounds_checking_function:libsec_static", + "cJSON:cjson_static", + ] + + # hiviewdfx libraries + external_deps += hiviewdfx_ext_deps + deps += hiviewdfx_deps +} + +action("copy_metadata_for_test") { + script = "$js_root/script/metadata_copy_for_test.py" + + target_path = rebase_path(root_out_dir) + "$target_test_path/metadata" + + args = [ + "--metadata", + rebase_path("$js_root/ecmascript/js_type_metadata"), + "--outputs", + rebase_path("$target_path"), + ] + + outputs = [ "$root_gen_dir/arkcompiler/ets_runtime/metadata_copy_dummy.txt" ] +} + +host_unittest_action("JSMetadataTest") { + module_out_path = module_output_path + + sources = [ "js_metadata_test.cpp" ] + + configs = [ "../../../../:ecma_test_config" ] + + deps = [ + ":copy_metadata_for_test", + "$ark_third_party_root/icu/icu4c:shared_icui18n", + "$ark_third_party_root/icu/icu4c:shared_icuuc", + "../../../../:libark_jsruntime_test", + sdk_libc_secshared_dep, + ] + + if (is_ohos && is_standard_system) { + metadata_file_path = "/data/test/" + } + + metadata_file_path = rebase_path(metadata_file_path) + defines = [ "METADATA_SOURCE_FILE_DIR=\"${metadata_file_path}\"" ] + + # hiviewdfx libraries + external_deps = hiviewdfx_ext_deps + external_deps += [ "cJSON:cjson_static" ] + deps += hiviewdfx_deps +} + group("unittest") { testonly = true deps = [ @@ -238,6 +316,8 @@ group("unittest") { ":HeapTrackerFirstTest", ":HeapTrackerSecondTest", ":HeapTrackerThirdTest", + ":JSMetadataTest", + ":RawHeapTranslateTest", ] } @@ -251,6 +331,8 @@ group("host_unittest") { ":HeapTrackerFirstTestAction", ":HeapTrackerSecondTestAction", ":HeapTrackerThirdTestAction", + ":JSMetadataTestAction", + ":RawHeapTranslateTestAction", ] if (is_mac) { deps -= [ @@ -261,6 +343,8 @@ group("host_unittest") { ":HeapTrackerFirstTestAction", ":HeapTrackerSecondTestAction", ":HeapTrackerThirdTestAction", + ":JSMetadataTestAction", + ":RawHeapTranslateTestAction", ] } } diff --git a/ecmascript/dfx/hprof/tests/heap_dump_test.cpp b/ecmascript/dfx/hprof/tests/heap_dump_test.cpp index 5d2a27f015c6dd080cf4c46cd008ee28044e5b74..212f44f4bc30ace0437185094bad8e8259c27b80 100644 --- a/ecmascript/dfx/hprof/tests/heap_dump_test.cpp +++ b/ecmascript/dfx/hprof/tests/heap_dump_test.cpp @@ -137,7 +137,8 @@ public: return true; } } - GTEST_LOG_(INFO) << "_______________" << targetStr << std::to_string(lineNum) <<"_______________ not found"; + GTEST_LOG_(ERROR) << "file: " << filePath.c_str() << ", target:" << targetStr.c_str() + << ", line:" << std::to_string(lineNum) <<"not found"; return false; // Lost the Line } @@ -544,9 +545,9 @@ public: return profiler_->DumpHeapSnapshot(stream, dumpOption, progress); } - void DumpHeapSnapshot(const DumpSnapShotOption &dumpOption) override + void DumpHeapSnapshotForOOM(const DumpSnapShotOption &dumpOption, bool fromSharedGC = false) override { - profiler_->DumpHeapSnapshot(dumpOption); + profiler_->DumpHeapSnapshotForOOM(dumpOption, fromSharedGC); } bool GenerateHeapSnapshot(std::string &inputFilePath, std::string &outputPath) override @@ -1130,10 +1131,9 @@ HWTEST_F_L0(HeapDumpTest, TestHeapDumpBinaryDump) std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); ASSERT_TRUE(content.size() > 0); auto u64Ptr = reinterpret_cast(content.c_str()); - ASSERT_TRUE(*u64Ptr > 0); + ASSERT_TRUE(u64Ptr[1] > 0); std::string snapshotPath("test_binary_dump.heapsnapshot"); - ret = tester.DecodeRawHeapSnashot(rawHeapPath, snapshotPath); - ASSERT_TRUE(ret); + tester.DecodeRawHeapSnashot(rawHeapPath, snapshotPath); ASSERT_TRUE(tester.MatchHeapDumpString(snapshotPath, "\"SharedArrayBuffer\"")); ASSERT_TRUE(tester.MatchHeapDumpString(snapshotPath, "\"WeakSet\"")); ASSERT_TRUE(tester.MatchHeapDumpString(snapshotPath, "\"WeakMap\"")); diff --git a/ecmascript/dfx/hprof/tests/js_files/heap_snapshot.js b/ecmascript/dfx/hprof/tests/js_files/heap_snapshot.js index f5ad5264ddcf36c749bf5f524de147dc51609406..298427287ff1acfa38dfa6a9c3717e081e728b55 100644 --- a/ecmascript/dfx/hprof/tests/js_files/heap_snapshot.js +++ b/ecmascript/dfx/hprof/tests/js_files/heap_snapshot.js @@ -25,7 +25,13 @@ let treeStr1 = str1 + str2; let treeStr2 = str3 + str4; let treeStr3 = str5 + str6; let treeStr4 = str7 + str8; -let treeStr5 = treeStr1 + treeStr2; -let treeStr6 = treeStr3 + treeStr4; -let treeStr7 = treeStr5 + treeStr6; -globalThis.save = treeStr7; \ No newline at end of file +let treeStr5 = str1 + str2 + str3 + str4; +let treeStr6 = str5 + str6 + str7 + str8; +let treeStr7 = str1 + str2 + str3 + str4 + str5 + str6 + str7 + str8; +globalThis.save1 = treeStr1; +globalThis.save2 = treeStr2; +globalThis.save3 = treeStr3; +globalThis.save4 = treeStr4; +globalThis.save5 = treeStr5; +globalThis.save6 = treeStr6; +globalThis.save7 = treeStr7; \ No newline at end of file diff --git a/ecmascript/dfx/hprof/tests/js_metadata_test.cpp b/ecmascript/dfx/hprof/tests/js_metadata_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7c0851a9a420219ae8701c54264b014988dc53e --- /dev/null +++ b/ecmascript/dfx/hprof/tests/js_metadata_test.cpp @@ -0,0 +1,4483 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ecmascript/byte_array.h" +#include "ecmascript/dfx/native_module_failure_info.h" +#include "ecmascript/ic/ic_handler.h" +#include "ecmascript/ic/profile_type_info.h" +#include "ecmascript/ic/proto_change_details.h" +#include "ecmascript/jobs/micro_job_queue.h" +#include "ecmascript/jobs/pending_job.h" +#include "ecmascript/js_native_pointer.h" +#include "ecmascript/js_object.h" +#include "ecmascript/js_tagged_value.h" +#include "ecmascript/js_arraybuffer.h" +#include "ecmascript/js_array_iterator.h" +#include "ecmascript/js_async_function.h" +#include "ecmascript/js_async_from_sync_iterator.h" +#include "ecmascript/js_async_generator_object.h" +#include "ecmascript/js_iterator.h" +#include "ecmascript/js_finalization_registry.h" +#include "ecmascript/js_api/js_api_arraylist_iterator.h" +#include "ecmascript/js_api/js_api_arraylist.h" +#include "ecmascript/js_api/js_api_bitvector.h" +#include "ecmascript/js_api/js_api_bitvector_iterator.h" +#include "ecmascript/js_api/js_api_deque.h" +#include "ecmascript/js_api/js_api_deque_iterator.h" +#include "ecmascript/js_api/js_api_hashmap.h" +#include "ecmascript/js_api/js_api_hashmap_iterator.h" +#include "ecmascript/js_api/js_api_hashset.h" +#include "ecmascript/js_api/js_api_hashset_iterator.h" +#include "ecmascript/js_api/js_api_lightweightmap.h" +#include "ecmascript/js_api/js_api_lightweightmap_iterator.h" +#include "ecmascript/js_api/js_api_lightweightset.h" +#include "ecmascript/js_api/js_api_lightweightset_iterator.h" +#include "ecmascript/js_api/js_api_linked_list.h" +#include "ecmascript/js_api/js_api_linked_list_iterator.h" +#include "ecmascript/js_api/js_api_list.h" +#include "ecmascript/js_api/js_api_list_iterator.h" +#include "ecmascript/js_api/js_api_plain_array.h" +#include "ecmascript/js_api/js_api_plain_array_iterator.h" +#include "ecmascript/js_api/js_api_queue.h" +#include "ecmascript/js_api/js_api_queue_iterator.h" +#include "ecmascript/js_api/js_api_stack.h" +#include "ecmascript/js_api/js_api_stack_iterator.h" +#include "ecmascript/js_api/js_api_tree_map.h" +#include "ecmascript/js_api/js_api_tree_map_iterator.h" +#include "ecmascript/js_api/js_api_tree_set.h" +#include "ecmascript/js_api/js_api_tree_set_iterator.h" +#include "ecmascript/js_api/js_api_vector.h" +#include "ecmascript/js_api/js_api_vector_iterator.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_async_generator_object.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_finalization_registry.h" +#include "ecmascript/js_function.h" +#include "ecmascript/js_generator_object.h" +#include "ecmascript/js_hclass.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_regexp_iterator.h" +#include "ecmascript/js_relative_time_format.h" +#include "ecmascript/js_segmenter.h" +#include "ecmascript/js_segments.h" +#include "ecmascript/js_segment_iterator.h" +#include "ecmascript/js_set.h" +#include "ecmascript/js_displaynames.h" +#include "ecmascript/js_list_format.h" +#include "ecmascript/js_set_iterator.h" +#include "ecmascript/js_string_iterator.h" +#include "ecmascript/js_typed_array.h" +#include "ecmascript/js_weak_container.h" +#include "ecmascript/js_weak_ref.h" +#include "ecmascript/marker_cell.h" +#include "ecmascript/js_typed_array.h" +#include "ecmascript/jspandafile/class_info_extractor.h" +#include "ecmascript/jspandafile/class_literal.h" +#include "ecmascript/jspandafile/program_object.h" +#include "ecmascript/module/js_module_record.h" +#include "ecmascript/napi/include/jsnapi.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tests/test_helper.h" +#include "ecmascript/dfx/hprof/heap_profiler.h" +#include "ecmascript/global_env.h" +#include "ecmascript/require/js_cjs_module.h" +#include "ecmascript/require/js_cjs_require.h" +#include "ecmascript/require/js_cjs_exports.h" +#include "ecmascript/module/js_module_source_text.h" +#include "ecmascript/module/js_shared_module.h" +#include "ecmascript/shared_objects/js_shared_array.h" +#include "ecmascript/shared_objects/js_sendable_arraybuffer.h" +#include "ecmascript/shared_objects/js_shared_array_iterator.h" +#include "ecmascript/shared_objects/js_shared_map.h" +#include "ecmascript/shared_objects/js_shared_map_iterator.h" +#include "ecmascript/shared_objects/js_shared_set.h" +#include "ecmascript/shared_objects/js_shared_set_iterator.h" +#include "ecmascript/shared_objects/js_shared_typed_array.h" +#include "ecmascript/tagged_hash_table.h" +#include "gtest/gtest.h" +#include +#include +#include +#include +#include +#include "cJSON.h" + + +namespace panda::test { +using namespace panda::ecmascript; +using ArrayVisitor = const std::function; +class JSMetadataTest : public testing::Test { +public: + void SetUp() override + { + GTEST_LOG_(INFO) << "JSMetadataTest Setup"; + } + + void TearDown() override + { + GTEST_LOG_(INFO) << "JSMetadataTest TearDown"; + } +}; + +class JSMetadataTestHelper { +public: + explicit JSMetadataTestHelper() + { + // { typeName: [all fields' name of this type in the same order as declared in .h files + typeName] } + // typeName: Type name in JSType Enum + fieldNameTable_ = { + {JSType::HCLASS, { + "Proto", "Layout", "Transitions", "Parent", "ProtoChangeMarker", + "ProtoChangeDetails", "EnumCache", "ProfilerType", "BitField", "BitField1", "HCLASS"}}, + {JSType::ACCESSOR_DATA, {"Getter", "Setter", "ACCESSOR_DATA"}}, + {JSType::AOT_LITERAL_INFO, {"AOT_LITERAL_INFO"}}, + {JSType::ASYNC_GENERATOR_REQUEST, {"Completion", "Capability", "ASYNC_GENERATOR_REQUEST"}}, + {JSType::ASYNC_ITERATOR_RECORD, {"Iterator", "NextMethod", "ASYNC_ITERATOR_RECORD"}}, + {JSType::BIGINT, {"BIGINT"}}, + {JSType::BYTE_ARRAY, {"BYTE_ARRAY"}}, + {JSType::CELL_RECORD, {"WeakRefTarget", "HeldValue", "CELL_RECORD"}}, + {JSType::CLASS_INFO_EXTRACTOR, { + "NonStaticKeys", "NonStaticProperties", "NonStaticElements", "StaticKeys", + "StaticProperties", "StaticElements", + "ConstructorMethod", "CLASS_INFO_EXTRACTOR"}}, + {JSType::CLASS_LITERAL, {"Array", "CLASS_LITERAL"}}, + {JSType::COMPLETION_RECORD, {"Value", "COMPLETION_RECORD"}}, + {JSType::CONSTANT_POOL, {"CONSTANT_POOL"}}, + {JSType::CONSTANT_STRING, {"RelocatedData", "CONSTANT_STRING"}}, + {JSType::COW_MUTANT_TAGGED_ARRAY, {"COW_MUTANT_TAGGED_ARRAY"}}, + {JSType::COW_TAGGED_ARRAY, {"COW_TAGGED_ARRAY"}}, + {JSType::EXTRA_PROFILE_TYPE_INFO, {"ReceiverObject", "HolderObject", "EXTRA_PROFILE_TYPE_INFO"}}, + {JSType::FUNCTION_TEMPLATE, {"Method", "Module", "RawProfileTypeInfo", "FUNCTION_TEMPLATE"}}, + {JSType::GLOBAL_ENV, {"GLOBAL_ENV"}}, + {JSType::IMPORTENTRY_RECORD, {"ModuleRequest", "ImportName", "LocalName", "IMPORTENTRY_RECORD"}}, + {JSType::INDIRECT_EXPORTENTRY_RECORD, {"ExportName", "ModuleRequest", + "ImportName", "INDIRECT_EXPORTENTRY_RECORD"}}, + {JSType::INTERNAL_ACCESSOR, {"Getter", "Setter", "INTERNAL_ACCESSOR"}}, + {JSType::JS_AGGREGATE_ERROR, {"Properties", "Elements", "JS_AGGREGATE_ERROR"}}, + {JSType::JS_API_ARRAYLIST_ITERATOR, {"IteratedArrayList", "JS_API_ARRAYLIST_ITERATOR"}}, + {JSType::JS_API_ARRAY_LIST, {"Length", "JS_API_ARRAY_LIST"}}, + {JSType::JS_API_BITVECTOR, {"NativePointer", "JS_API_BITVECTOR"}}, + {JSType::JS_API_BITVECTOR_ITERATOR, {"IteratedBitVector", "JS_API_BITVECTOR_ITERATOR"}}, + {JSType::JS_API_DEQUE, {"JS_API_DEQUE"}}, + {JSType::JS_API_DEQUE_ITERATOR, {"IteratedDeque", "JS_API_DEQUE_ITERATOR"}}, + {JSType::JS_API_HASHMAP_ITERATOR, {"IteratedHashMap", "TaggedQueue", + "CurrentNodeResult", "JS_API_HASHMAP_ITERATOR"}}, + {JSType::JS_API_HASHSET_ITERATOR, {"IteratedHashSet", "TaggedQueue", + "CurrentNodeResult", "JS_API_HASHSET_ITERATOR"}}, + {JSType::JS_API_HASH_MAP, {"Table", "JS_API_HASH_MAP"}}, + {JSType::JS_API_HASH_SET, {"Table", "JS_API_HASH_SET"}}, + {JSType::JS_API_LIGHT_WEIGHT_MAP, {"Hashes", "Keys", "Values", "JS_API_LIGHT_WEIGHT_MAP"}}, + {JSType::JS_API_LIGHT_WEIGHT_MAP_ITERATOR, {"IteratedLightWeightMap", "JS_API_LIGHT_WEIGHT_MAP_ITERATOR"}}, + {JSType::JS_API_LIGHT_WEIGHT_SET, {"Hashes", "Values", "JS_API_LIGHT_WEIGHT_SET"}}, + {JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR, {"IteratedLightWeightSet", "JS_API_LIGHT_WEIGHT_SET_ITERATOR"}}, + {JSType::JS_API_LINKED_LIST, {"DoubleList", "JS_API_LINKED_LIST"}}, + {JSType::JS_API_LINKED_LIST_ITERATOR, {"IteratedLinkedList", "JS_API_LINKED_LIST_ITERATOR"}}, + {JSType::JS_API_LIST, {"SingleList", "JS_API_LIST"}}, + {JSType::JS_API_LIST_ITERATOR, {"IteratedList", "JS_API_LIST_ITERATOR"}}, + {JSType::JS_API_PLAIN_ARRAY, {"Keys", "Values", "JS_API_PLAIN_ARRAY"}}, + {JSType::JS_API_PLAIN_ARRAY_ITERATOR, {"IteratedPlainArray", "JS_API_PLAIN_ARRAY_ITERATOR"}}, + {JSType::JS_API_QUEUE, {"Length", "JS_API_QUEUE"}}, + {JSType::JS_API_QUEUE_ITERATOR, {"IteratedQueue", "JS_API_QUEUE_ITERATOR"}}, + {JSType::JS_API_STACK, {"JS_API_STACK"}}, + {JSType::JS_API_STACK_ITERATOR, {"IteratedStack", "JS_API_STACK_ITERATOR"}}, + {JSType::JS_API_TREEMAP_ITERATOR, {"IteratedMap", "Entries", "JS_API_TREEMAP_ITERATOR"}}, + {JSType::JS_API_TREESET_ITERATOR, {"IteratedSet", "Entries", "JS_API_TREESET_ITERATOR"}}, + {JSType::JS_API_TREE_MAP, {"TreeMap", "JS_API_TREE_MAP"}}, + {JSType::JS_API_TREE_SET, {"TreeSet", "JS_API_TREE_SET"}}, + {JSType::JS_API_VECTOR, {"JS_API_VECTOR"}}, + {JSType::JS_API_VECTOR_ITERATOR, {"IteratedVector", "JS_API_VECTOR_ITERATOR"}}, + {JSType::JS_ARGUMENTS, {"JS_ARGUMENTS"}}, + {JSType::JS_ARRAY, {"Length", "TrackInfo", "JS_ARRAY"}}, + {JSType::JS_ARRAY_BUFFER, {"ArrayBufferData", "JS_ARRAY_BUFFER"}}, + {JSType::JS_ARRAY_ITERATOR, {"IteratedArray", "JS_ARRAY_ITERATOR"}}, + {JSType::JS_ASYNCITERATOR, {"Properties", "Elements", "JS_ASYNCITERATOR"}}, + {JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION, {"AsyncContext", "JS_ASYNC_AWAIT_STATUS_FUNCTION"}}, + {JSType::JS_ASYNC_FROM_SYNC_ITERATOR, {"SyncIteratorRecord", "JS_ASYNC_FROM_SYNC_ITERATOR"}}, + {JSType::JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION, {"Done", "JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION"}}, + {JSType::JS_ASYNC_FUNCTION, {"JS_ASYNC_FUNCTION"}}, + {JSType::JS_ASYNC_FUNC_OBJECT, {"Promise", "JS_ASYNC_FUNC_OBJECT"}}, + {JSType::JS_ASYNC_GENERATOR_FUNCTION, {"JS_ASYNC_GENERATOR_FUNCTION"}}, + {JSType::JS_ASYNC_GENERATOR_OBJECT, {"GeneratorContext", "AsyncGeneratorQueue", "GeneratorBrand", + "ResumeResult", "JS_ASYNC_GENERATOR_OBJECT"}}, + {JSType::JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN, { + "AsyncGeneratorObject", "JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN"}}, + {JSType::JS_ASYNC_MODULE_FULFILLED_FUNCTION, {"JS_ASYNC_MODULE_FULFILLED_FUNCTION"}}, + {JSType::JS_ASYNC_MODULE_REJECTED_FUNCTION, {"JS_ASYNC_MODULE_REJECTED_FUNCTION"}}, + {JSType::JS_BIGINT64_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_BIGINT64_ARRAY"}}, + {JSType::JS_BIGUINT64_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_BIGUINT64_ARRAY"}}, + {JSType::JS_BOUND_FUNCTION, {"BoundTarget", "BoundThis", "BoundArguments", "JS_BOUND_FUNCTION"}}, + {JSType::JS_CJS_EXPORTS, {"Exports", "JS_CJS_EXPORTS"}}, + {JSType::JS_CJS_MODULE, {"Id", "Path", "Exports", "Filename", "JS_CJS_MODULE"}}, + {JSType::JS_CJS_REQUIRE, {"Cache", "Parent", "JS_CJS_REQUIRE"}}, + {JSType::JS_COLLATOR, {"IcuFiled", "Locale", "Collation", "BoundCompare", "JS_COLLATOR"}}, + {JSType::JS_DATA_VIEW, {"DataView", "ViewedArrayBuffer", "JS_DATA_VIEW"}}, + {JSType::JS_DATE, {"TimeValue", "LocalOffset", "JS_DATE"}}, + {JSType::JS_DATE_TIME_FORMAT, {"Locale", "Calendar", "NumberingSystem", "TimeZone", "LocaleIcu", + "SimpleDateTimeFormatIcu", "Iso8601", + "BoundFormat", "JS_DATE_TIME_FORMAT"}}, + {JSType::JS_DISPLAYNAMES, {"Locale", "IcuLDN", "JS_DISPLAYNAMES"}}, + {JSType::JS_ERROR, {"Properties", "Elements", "JS_ERROR"}}, + {JSType::JS_EVAL_ERROR, {"Properties", "Elements", "JS_EVAL_ERROR"}}, + {JSType::JS_FINALIZATION_REGISTRY, {"CleanupCallback", "NoUnregister", + "MaybeUnregister", "Next", "Prev", "JS_FINALIZATION_REGISTRY"}}, + {JSType::JS_FLOAT32_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_FLOAT32_ARRAY"}}, + {JSType::JS_FLOAT64_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_FLOAT64_ARRAY"}}, + {JSType::JS_FORIN_ITERATOR, {"Object", "CachedHclass", "Keys", "JS_FORIN_ITERATOR"}}, + {JSType::JS_FUNCTION, {"ProtoOrHClass", "LexicalEnv", "MachineCode", "BaselineCode", "RawProfileTypeInfo", + "HomeObject", "Module", "ProtoTransRootHClass", "JS_FUNCTION"}}, + {JSType::JS_FUNCTION_BASE, {"Method", "JS_FUNCTION_BASE"}}, + {JSType::JS_GENERATOR_CONTEXT, {"RegsArray", "Method", "This", "Acc", + "GeneratorObject", "LexicalEnv", "JS_GENERATOR_CONTEXT"}}, + {JSType::JS_GENERATOR_FUNCTION, {"JS_GENERATOR_FUNCTION"}}, + {JSType::JS_GENERATOR_OBJECT, {"GeneratorContext", "ResumeResult", "JS_GENERATOR_OBJECT"}}, + {JSType::JS_GLOBAL_OBJECT, {"JS_GLOBAL_OBJECT"}}, + {JSType::JS_INT16_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_INT16_ARRAY"}}, + {JSType::JS_INT32_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_INT32_ARRAY"}}, + {JSType::JS_INT8_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_INT8_ARRAY"}}, + {JSType::JS_INTL, {"FallbackSymbol", "JS_INTL"}}, + {JSType::JS_INTL_BOUND_FUNCTION, {"NumberFormat", "DateTimeFormat", + "Collator", "JS_INTL_BOUND_FUNCTION"}}, + {JSType::JS_ITERATOR, {"Properties", "Elements", "JS_ITERATOR"}}, + {JSType::JS_LIST_FORMAT, {"Locale", "IcuLF", "JS_LIST_FORMAT"}}, + {JSType::JS_LOCALE, {"IcuField", "JS_LOCALE"}}, + {JSType::JS_MAP, {"LinkedMap", "JS_MAP"}}, + {JSType::JS_MAP_ITERATOR, {"IteratorMap", "JS_MAP_ITERATOR"}}, + {JSType::JS_MODULE_NAMESPACE, {"Module", "Exports", "DeregisterProcession", "JS_MODULE_NAMESPACE"}}, + {JSType::JS_NATIVE_POINTER, {"BindingSize", "JS_NATIVE_POINTER"}}, + {JSType::JS_NUMBER_FORMAT, {"Locale", "NumberingSystem", "Currency", "Unit", "MinimumIntegerDigits", + "MinimumFractionDigits", "MaximumFractionDigits", + "MinimumSignificantDigits", "MaximumSignificantDigits", + "UseGrouping", "BoundFormat", "IcuField", "JS_NUMBER_FORMAT"}}, + {JSType::JS_OBJECT, {"Properties", "Elements", "JS_OBJECT"}}, + {JSType::JS_OOM_ERROR, {"Properties", "Elements", "JS_OOM_ERROR"}}, + {JSType::JS_PLURAL_RULES, {"Locale", "MinimumIntegerDigits", + "MinimumFractionDigits", "MaximumFractionDigits", + "MinimumSignificantDigits", "MaximumSignificantDigits", + "IcuPR", "IcuNF", "JS_PLURAL_RULES"}}, + {JSType::JS_PRIMITIVE_REF, {"Value", "JS_PRIMITIVE_REF"}}, + {JSType::JS_PROMISE, {"PromiseResult", "PromiseFulfillReactions", "PromiseRejectReactions", "JS_PROMISE"}}, + {JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION, {"Index", "Values", "Capabilities", "RemainingElements", + "AlreadyCalled", + "JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION"}}, + {JSType::JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION, {"AlreadyCalled", "Values", "Capability", + "RemainingElements", + "JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION"}}, + {JSType::JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION, {"Errors", "Capability", "RemainingElements", + "AlreadyCalled", + "JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION"}}, + {JSType::JS_PROMISE_EXECUTOR_FUNCTION, {"Capability", "JS_PROMISE_EXECUTOR_FUNCTION"}}, + {JSType::JS_PROMISE_FINALLY_FUNCTION, {"Constructor", "OnFinally", "JS_PROMISE_FINALLY_FUNCTION"}}, + {JSType::JS_PROMISE_REACTIONS_FUNCTION, {"Promise", "AlreadyResolved", "JS_PROMISE_REACTIONS_FUNCTION"}}, + {JSType::JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION, {"Result", + "JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION"}}, + {JSType::JS_PROXY, {"Target", "Handler", "Method", "PrivateField", "JS_PROXY"}}, + {JSType::JS_PROXY_REVOC_FUNCTION, {"RevocableProxy", "JS_PROXY_REVOC_FUNCTION"}}, + {JSType::JS_RANGE_ERROR, {"Properties", "Elements", "JS_RANGE_ERROR"}}, + {JSType::JS_REALM, {"Value", "GlobalEnv", "JS_REALM"}}, + {JSType::JS_REFERENCE_ERROR, {"Properties", "Elements", "JS_REFERENCE_ERROR"}}, + {JSType::JS_REG_EXP, {"ByteCodeBuffer", "OriginalSource", "OriginalFlags", "GroupName", "JS_REG_EXP"}}, + {JSType::JS_REG_EXP_ITERATOR, {"IteratingRegExp", "IteratedString", "JS_REG_EXP_ITERATOR"}}, + {JSType::JS_RELATIVE_TIME_FORMAT, {"Locale", "NumberingSystem", "IcuField", "JS_RELATIVE_TIME_FORMAT"}}, + {JSType::JS_SEGMENTER, {"Locale", "IcuField", "JS_SEGMENTER"}}, + {JSType::JS_SEGMENTS, {"IcuField", "SegmentsString", "UnicodeString", "JS_SEGMENTS"}}, + {JSType::JS_SEGMENT_ITERATOR, {"IcuField", "IteratedString", "UnicodeString", "JS_SEGMENT_ITERATOR"}}, + {JSType::JS_SENDABLE_ARRAY_BUFFER, {"ArrayBufferData", "JS_SENDABLE_ARRAY_BUFFER"}}, + {JSType::JS_SET, {"LinkedSet", "JS_SET"}}, + {JSType::JS_SET_ITERATOR, {"IteratorSet", "JS_SET_ITERATOR"}}, + {JSType::JS_SHARED_ARRAY, {"TrackInfo", "JS_SHARED_ARRAY"}}, + {JSType::JS_SHARED_ARRAY_BUFFER, {"ArrayBufferData", "JS_SHARED_ARRAY_BUFFER"}}, + {JSType::JS_SHARED_ARRAY_ITERATOR, {"IteratedArray", "JS_SHARED_ARRAY_ITERATOR"}}, + {JSType::JS_SHARED_ASYNC_FUNCTION, {"JS_SHARED_ASYNC_FUNCTION"}}, + {JSType::JS_SHARED_BIGINT64_ARRAY, {"JS_SHARED_BIGINT64_ARRAY"}}, + {JSType::JS_SHARED_BIGUINT64_ARRAY, {"JS_SHARED_BIGUINT64_ARRAY"}}, + {JSType::JS_SHARED_FLOAT32_ARRAY, {"JS_SHARED_FLOAT32_ARRAY"}}, + {JSType::JS_SHARED_FLOAT64_ARRAY, {"JS_SHARED_FLOAT64_ARRAY"}}, + {JSType::JS_SHARED_FUNCTION, {"JS_SHARED_FUNCTION"}}, + {JSType::JS_SHARED_INT16_ARRAY, {"JS_SHARED_INT16_ARRAY"}}, + {JSType::JS_SHARED_INT32_ARRAY, {"JS_SHARED_INT32_ARRAY"}}, + {JSType::JS_SHARED_INT8_ARRAY, {"JS_SHARED_INT8_ARRAY"}}, + {JSType::JS_SHARED_MAP, {"LinkedMap", "JS_SHARED_MAP"}}, + {JSType::JS_SHARED_MAP_ITERATOR, {"IteratorMap", "JS_SHARED_MAP_ITERATOR"}}, + {JSType::JS_SHARED_OBJECT, {"JS_SHARED_OBJECT"}}, + {JSType::JS_SHARED_SET, {"LinkedSet", "JS_SHARED_SET"}}, + {JSType::JS_SHARED_SET_ITERATOR, {"IteratorSet", "JS_SHARED_SET_ITERATOR"}}, + {JSType::JS_SHARED_TYPED_ARRAY, {"JS_SHARED_TYPED_ARRAY"}}, + {JSType::JS_SHARED_UINT16_ARRAY, {"JS_SHARED_UINT16_ARRAY"}}, + {JSType::JS_SHARED_UINT32_ARRAY, {"JS_SHARED_UINT32_ARRAY"}}, + {JSType::JS_SHARED_UINT8_ARRAY, {"JS_SHARED_UINT8_ARRAY"}}, + {JSType::JS_SHARED_UINT8_CLAMPED_ARRAY, {"JS_SHARED_UINT8_CLAMPED_ARRAY"}}, + {JSType::JS_STRING_ITERATOR, {"IteratedString", "JS_STRING_ITERATOR"}}, + {JSType::JS_SYNTAX_ERROR, {"Properties", "Elements", "JS_SYNTAX_ERROR"}}, + {JSType::JS_TERMINATION_ERROR, {"Properties", "Elements", "JS_TERMINATION_ERROR"}}, + {JSType::JS_TYPED_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_TYPED_ARRAY"}}, + {JSType::JS_TYPE_ERROR, {"Properties", "Elements", "JS_TYPE_ERROR"}}, + {JSType::JS_UINT16_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_UINT16_ARRAY"}}, + {JSType::JS_UINT32_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_UINT32_ARRAY"}}, + {JSType::JS_UINT8_ARRAY, {"ViewedArrayBufferOrByteArray", "TypedArrayName", "JS_UINT8_ARRAY"}}, + {JSType::JS_UINT8_CLAMPED_ARRAY, {"ViewedArrayBufferOrByteArray", + "TypedArrayName", "JS_UINT8_CLAMPED_ARRAY"}}, + {JSType::JS_URI_ERROR, {"Properties", "Elements", "JS_URI_ERROR"}}, + {JSType::JS_WEAK_MAP, {"LinkedMap", "JS_WEAK_MAP"}}, + {JSType::JS_WEAK_REF, {"WeakObject", "JS_WEAK_REF"}}, + {JSType::JS_WEAK_SET, {"LinkedSet", "JS_WEAK_SET"}}, + {JSType::LEXICAL_ENV, {"LEXICAL_ENV"}}, + {JSType::LINE_STRING, {"LINE_STRING"}}, + {JSType::LINKED_NODE, {"Next", "LINKED_NODE"}}, + {JSType::LOCAL_EXPORTENTRY_RECORD, {"ExportName", "LocalName", "LOCAL_EXPORTENTRY_RECORD"}}, + {JSType::MACHINE_CODE_OBJECT, {"MACHINE_CODE_OBJECT"}}, + {JSType::MARKER_CELL, {"MARKER_CELL"}}, + {JSType::METHOD, {"ConstantPool", "METHOD"}}, + {JSType::MICRO_JOB_QUEUE, {"PromiseJobQueue", "ScriptJobQueue", "MICRO_JOB_QUEUE"}}, + {JSType::MODULE_RECORD, {"MODULE_RECORD"}}, + {JSType::MUTANT_TAGGED_ARRAY, {"MUTANT_TAGGED_ARRAY"}}, + {JSType::NATIVE_MODULE_FAILURE_INFO, {"ArkNativeModuleFailureInfo", "NATIVE_MODULE_FAILURE_INFO"}}, + {JSType::PENDING_JOB, {"Job", "Arguments", "PENDING_JOB"}}, + {JSType::PROFILE_TYPE_INFO, {"PROFILE_TYPE_INFO"}}, + {JSType::PROFILE_TYPE_INFO_CELL_0, {"Value", "MachineCode", "Handle", "PROFILE_TYPE_INFO_CELL_0"}}, + {JSType::PROFILE_TYPE_INFO_CELL_1, {"Value", "MachineCode", "Handle", "PROFILE_TYPE_INFO_CELL_1"}}, + {JSType::PROFILE_TYPE_INFO_CELL_N, {"Value", "MachineCode", "Handle", "PROFILE_TYPE_INFO_CELL_N"}}, + {JSType::PROGRAM, {"MainFunction", "PROGRAM"}}, + {JSType::PROMISE_CAPABILITY, {"Promise", "Resolve", "Reject", "PROMISE_CAPABILITY"}}, + {JSType::PROMISE_ITERATOR_RECORD, {"Iterator", "PROMISE_ITERATOR_RECORD"}}, + {JSType::PROMISE_REACTIONS, {"PromiseCapability", "Handler", "PROMISE_REACTIONS"}}, + {JSType::PROMISE_RECORD, {"Value", "PROMISE_RECORD"}}, + {JSType::PROPERTY_BOX, {"Value", "PROPERTY_BOX"}}, + {JSType::PROTOTYPE_HANDLER, {"HandlerInfo", "ProtoCell", "Holder", + "AccessorJSFunction", "PROTOTYPE_HANDLER"}}, + {JSType::PROTOTYPE_INFO, {"ChangeListener", "PROTOTYPE_INFO"}}, + {JSType::PROTO_CHANGE_MARKER, {"PROTO_CHANGE_MARKER"}}, + {JSType::RB_TREENODE, {"Left", "Right", "IsRed", "RB_TREENODE"}}, + {JSType::RESOLVEDBINDING_RECORD, {"Module", "BindingName", "RESOLVEDBINDING_RECORD"}}, + {JSType::RESOLVEDINDEXBINDING_RECORD, {"Module", "Index", "RESOLVEDINDEXBINDING_RECORD"}}, + {JSType::RESOLVEDRECORDBINDING_RECORD, {"ModuleRecord", "BindingName", "RESOLVEDRECORDBINDING_RECORD"}}, + {JSType::RESOLVEDRECORDINDEXBINDING_RECORD, {"ModuleRecord", + "AbcFileName", "RESOLVEDRECORDINDEXBINDING_RECORD"}}, + {JSType::RESOLVING_FUNCTIONS_RECORD, {"ResolveFunction", "RejectFunction", "RESOLVING_FUNCTIONS_RECORD"}}, + {JSType::SENDABLE_ENV, {"SENDABLE_ENV"}}, + {JSType::SLICED_STRING, {"Parent", "SLICED_STRING"}}, + {JSType::SOURCE_TEXT_MODULE_RECORD, {"Environment", "Namespace", "RequestedModules", + "ImportEntries", "LocalExportEntries", + "IndirectExportEntries", "StarExportEntries", + "NameDictionary", "CycleRoot", "TopLevelCapability", + "AsyncParentModules", "SendableEnv", "SOURCE_TEXT_MODULE_RECORD"}}, + {JSType::STAR_EXPORTENTRY_RECORD, {"ModuleRequest", "STAR_EXPORTENTRY_RECORD"}}, + {JSType::STORE_TS_HANDLER, {"HandlerInfo", "ProtoCell", "Holder", "STORE_TS_HANDLER"}}, + {JSType::SYMBOL, {"Description", "SYMBOL"}}, + {JSType::TAGGED_ARRAY, {"Length", "Data", "TAGGED_ARRAY"}}, + {JSType::TAGGED_DICTIONARY, {"TAGGED_DICTIONARY"}}, + {JSType::TEMPLATE_MAP, {"TEMPLATE_MAP"}}, + {JSType::TRACK_INFO, {"CachedHClass", "CachedFunc", "TRACK_INFO"}}, + {JSType::TRANSITION_HANDLER, {"HandlerInfo", "TransitionHClass", "TRANSITION_HANDLER"}}, + {JSType::TRANS_WITH_PROTO_HANDLER, {"HandlerInfo", "TransitionHClass", + "ProtoCell", "TRANS_WITH_PROTO_HANDLER"}}, + {JSType::TREE_STRING, {"First", "Second", "TREE_STRING"}}, + {JSType::VTABLE, {"VTABLE"}} + }; + // { typeName: [all fields' start offset of this type in the same order as declared in .h files + endOffset] } + // endOffset: LAST_OFFSET - (start offset of the first field of this type) + fieldOffsetTable_ = { + {JSType::HCLASS, { + JSHClass::PROTOTYPE_OFFSET, JSHClass::LAYOUT_OFFSET, JSHClass::TRANSTIONS_OFFSET, + JSHClass::PARENT_OFFSET, JSHClass::PROTO_CHANGE_MARKER_OFFSET, + JSHClass::PROTO_CHANGE_DETAILS_OFFSET, + JSHClass::ENUM_CACHE_OFFSET, JSHClass::PROFILE_TYPE, + JSHClass::BIT_FIELD_OFFSET, JSHClass::BIT_FIELD1_OFFSET, + JSHClass::LAST_OFFSET - JSHClass::PROTOTYPE_OFFSET}}, + {JSType::ACCESSOR_DATA, {AccessorData::GETTER_OFFSET, AccessorData::SETTER_OFFSET, + AccessorData::SIZE - AccessorData::GETTER_OFFSET}}, + {JSType::AOT_LITERAL_INFO, {TaggedArray::LAST_OFFSET - TaggedArray::LENGTH_OFFSET}}, + {JSType::ASYNC_GENERATOR_REQUEST, { + AsyncGeneratorRequest::COMPLETION_OFFSET, + AsyncGeneratorRequest::CAPABILITY_OFFSET, + AsyncGeneratorRequest::SIZE - AsyncGeneratorRequest::COMPLETION_OFFSET}}, + {JSType::ASYNC_ITERATOR_RECORD, {AsyncIteratorRecord::ITERATOR_OFFSET, + AsyncIteratorRecord::NEXTMETHOD_OFFSET, + AsyncIteratorRecord::SIZE - AsyncIteratorRecord::ITERATOR_OFFSET}}, + {JSType::BIGINT, {BigInt::LAST_OFFSET - BigInt::LENGTH_OFFSET}}, + {JSType::BYTE_ARRAY, {ByteArray::LAST_OFFSET - ByteArray::ARRAY_LENGTH_OFFSET}}, + {JSType::CELL_RECORD, {CellRecord::WEAKREF_TARGET_OFFSET, + CellRecord::HELD_VALUE_OFFSET, + CellRecord::SIZE - CellRecord::WEAKREF_TARGET_OFFSET}}, + {JSType::CLASS_INFO_EXTRACTOR, { + ClassInfoExtractor::PROTOTYPE_HCLASS_OFFSET, + ClassInfoExtractor::NON_STATIC_PROPERTIES_OFFSET, + ClassInfoExtractor::NON_STATIC_ELEMENTS_OFFSET, + ClassInfoExtractor::CONSTRUCTOR_HCLASS_OFFSET, + ClassInfoExtractor::STATIC_PROPERTIES_OFFSET, + ClassInfoExtractor::STATIC_ELEMENTS_OFFSET, + ClassInfoExtractor::CONSTRUCTOR_METHOD_OFFSET, + ClassInfoExtractor::SIZE - ClassInfoExtractor::PROTOTYPE_HCLASS_OFFSET}}, + {JSType::CLASS_LITERAL, {ClassLiteral::ARRAY_OFFSET, + ClassLiteral::SIZE - ClassLiteral::ARRAY_OFFSET}}, + {JSType::COMPLETION_RECORD, {CompletionRecord::VALUE_OFFSET, + CompletionRecord::SIZE - CompletionRecord::VALUE_OFFSET}}, + {JSType::CONSTANT_POOL, {0}}, + {JSType::CONSTANT_STRING, {ConstantString::RELOCTAED_DATA_OFFSET, + ConstantString::LAST_OFFSET - ConstantString::RELOCTAED_DATA_OFFSET}}, + {JSType::COW_MUTANT_TAGGED_ARRAY, {0}}, + {JSType::COW_TAGGED_ARRAY, {0}}, + {JSType::EXTRA_PROFILE_TYPE_INFO, { + ExtraProfileTypeInfo::RECEIVER_OBJECT_OFFSET, + ExtraProfileTypeInfo::HOLDER_OBJECT_OFFSET, + ExtraProfileTypeInfo::LAST_OFFSET - ExtraProfileTypeInfo::RECEIVER_OBJECT_OFFSET}}, + {JSType::FUNCTION_TEMPLATE, {FunctionTemplate::METHOD_OFFSET, + FunctionTemplate::MODULE_OFFSET, + FunctionTemplate::RAW_PROFILE_TYPE_INFO_OFFSET, + FunctionTemplate::SIZE - FunctionTemplate::METHOD_OFFSET}}, + {JSType::GLOBAL_ENV, {GlobalEnv::SIZE - GlobalEnv::HEADER_SIZE}}, + {JSType::IMPORTENTRY_RECORD, {ImportEntry::IMPORT_ENTRY_OFFSET, + ImportEntry::MODULE_REQUEST_OFFSET, + ImportEntry::IMPORT_NAME_OFFSET, + ImportEntry::SIZE - ImportEntry::IMPORT_ENTRY_OFFSET}}, + {JSType::INDIRECT_EXPORTENTRY_RECORD, { + IndirectExportEntry::INDIRECT_EXPORT_ENTRY_OFFSET, + IndirectExportEntry::MODULE_REQUEST_OFFSET, + IndirectExportEntry::IMPORT_NAME_OFFSET, + IndirectExportEntry::SIZE - IndirectExportEntry::INDIRECT_EXPORT_ENTRY_OFFSET}}, + {JSType::INTERNAL_ACCESSOR, {InternalAccessor::GETTER_OFFSET, + InternalAccessor::SETTER_OFFSET, + InternalAccessor::SIZE - InternalAccessor::GETTER_OFFSET}}, + {JSType::JS_AGGREGATE_ERROR, {JSObject::PROPERTIES_OFFSET, + JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_API_ARRAYLIST_ITERATOR, { + JSAPIArrayListIterator::ITERATED_ARRAYLIST_OFFSET, + JSAPIArrayListIterator::SIZE - JSAPIArrayListIterator::ITERATED_ARRAYLIST_OFFSET}}, + {JSType::JS_API_ARRAY_LIST, {JSAPIArrayList::LENGTH_OFFSET, + JSAPIArrayList::SIZE - JSAPIArrayList::LENGTH_OFFSET}}, + {JSType::JS_API_BITVECTOR, {JSAPIBitVector::NATIVE_POINTER_OFFSET, + JSAPIBitVector::LAST_OFFSET - JSAPIBitVector::NATIVE_POINTER_OFFSET}}, + {JSType::JS_API_BITVECTOR_ITERATOR, { + JSAPIBitVectorIterator::ITERATED_BITVECTOR_OFFSET, + JSAPIBitVectorIterator::SIZE - JSAPIBitVectorIterator::ITERATED_BITVECTOR_OFFSET}}, + {JSType::JS_API_DEQUE, {JSAPIDeque::ENDL_OFFSET - JSAPIDeque::FIRST_OFFSET}}, + {JSType::JS_API_DEQUE_ITERATOR, {JSAPIDequeIterator::ITERATED_DEQUE_OFFSET, + JSAPIDequeIterator::SIZE - JSAPIDequeIterator::ITERATED_DEQUE_OFFSET}}, + {JSType::JS_API_HASHMAP_ITERATOR, { + JSAPIHashMapIterator::ITERATED_HASHMAP_OFFSET, + JSAPIHashMapIterator::TAGGED_QUEUE_OFFSET, + JSAPIHashMapIterator::CURRENT_NODE_RESULT, + JSAPIHashMapIterator::LAST_OFFSET - JSAPIHashMapIterator::ITERATED_HASHMAP_OFFSET}}, + {JSType::JS_API_HASHSET_ITERATOR, { + JSAPIHashSetIterator::ITERATED_HASHSET_OFFSET, + JSAPIHashSetIterator::TAGGED_QUEUE_OFFSET, + JSAPIHashSetIterator::CURRENT_NODE_RESULT, + JSAPIHashSetIterator::SIZE - JSAPIHashSetIterator::ITERATED_HASHSET_OFFSET}}, + {JSType::JS_API_HASH_MAP, {JSAPIHashMap::HASHMAP_TABLE_INDEX, + JSAPIHashMap::SIZE - JSAPIHashMap::HASHMAP_TABLE_INDEX}}, + {JSType::JS_API_HASH_SET, {JSAPIHashSet::HASHSET_TABLE_INDEX, + JSAPIHashSet::SIZE - JSAPIHashSet::HASHSET_TABLE_INDEX}}, + {JSType::JS_API_LIGHT_WEIGHT_MAP, { + JSAPILightWeightMap::LWP_HASHES_OFFSET, + JSAPILightWeightMap::LWP_KEYS_OFFSET, + JSAPILightWeightMap::LWP_VALUES_OFFSET, + JSAPILightWeightMap::SIZE - JSAPILightWeightMap::LWP_HASHES_OFFSET}}, + {JSType::JS_API_LIGHT_WEIGHT_MAP_ITERATOR, { + JSAPILightWeightMapIterator::ITERATED_LIGHT_WEIGHT_MAP_OFFSET, + JSAPILightWeightMapIterator::LAST_OFFSET - JSAPILightWeightMapIterator::ITERATED_LIGHT_WEIGHT_MAP_OFFSET}}, + {JSType::JS_API_LIGHT_WEIGHT_SET, { + JSAPILightWeightSet::HASHES_OFFSET, + JSAPILightWeightSet::VALUES_OFFSET, + JSAPILightWeightSet::SIZE - JSAPILightWeightSet::HASHES_OFFSET}}, + {JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR, { + JSAPILightWeightSetIterator::ITERATED_LIGHT_WEIGHT_SET_OFFSET, + JSAPILightWeightSetIterator::LAST_OFFSET - JSAPILightWeightSetIterator::ITERATED_LIGHT_WEIGHT_SET_OFFSET}}, + {JSType::JS_API_LINKED_LIST, {JSAPILinkedList::DOUBLE_LIST_OFFSET, + JSAPILinkedList::SIZE - JSAPILinkedList::DOUBLE_LIST_OFFSET}}, + {JSType::JS_API_LINKED_LIST_ITERATOR, { + JSAPILinkedListIterator::ITERATED_LINKED_LIST_OFFSET, + JSAPILinkedListIterator::LAST_OFFSET - JSAPILinkedListIterator::ITERATED_LINKED_LIST_OFFSET}}, + {JSType::JS_API_LIST, {JSAPIList::SINGLY_LIST_OFFSET, + JSAPIList::SIZE - JSAPIList::SINGLY_LIST_OFFSET}}, + {JSType::JS_API_LIST_ITERATOR, { + JSAPIListIterator::ITERATED_LIST_OFFSET, + JSAPIListIterator::LAST_OFFSET - JSAPIListIterator::ITERATED_LIST_OFFSET}}, + {JSType::JS_API_PLAIN_ARRAY, {JSAPIPlainArray::KEYS_OFFSET, + JSAPIPlainArray::VALUES_OFFSET, + JSAPIPlainArray::SIZE - JSAPIPlainArray::KEYS_OFFSET}}, + {JSType::JS_API_PLAIN_ARRAY_ITERATOR, { + JSAPIPlainArrayIterator::ITERATED_PLAIN_ARRAY_OFFSET, + JSAPIPlainArrayIterator::LAST_OFFSET - JSAPIPlainArrayIterator::ITERATED_PLAIN_ARRAY_OFFSET}}, + {JSType::JS_API_QUEUE, {JSAPIQueue::LENGTH_OFFSET, + JSAPIQueue::LAST_OFFSET - JSAPIQueue::LENGTH_OFFSET}}, + {JSType::JS_API_QUEUE_ITERATOR, { + JSAPIQueueIterator::ITERATED_QUEUE_OFFSET, + JSAPIQueueIterator::SIZE - JSAPIQueueIterator::ITERATED_QUEUE_OFFSET}}, + {JSType::JS_API_STACK, {JSAPIStack::SIZE - JSAPIStack::TOP_OFFSET}}, + {JSType::JS_API_STACK_ITERATOR, { + JSAPIStackIterator::ITERATED_STACK_OFFSET, + JSAPIStackIterator::SIZE - JSAPIStackIterator::ITERATED_STACK_OFFSET}}, + {JSType::JS_API_TREEMAP_ITERATOR, { + JSAPITreeMapIterator::ITERATED_MAP_OFFSET, + JSAPITreeMapIterator::ITERATED_ENTRIES_OFFSET, + JSAPITreeMapIterator::LAST_OFFSET - JSAPITreeMapIterator::ITERATED_MAP_OFFSET}}, + {JSType::JS_API_TREESET_ITERATOR, { + JSAPITreeSetIterator::ITERATED_SET_OFFSET, + JSAPITreeSetIterator::ITERATED_ENTRIES_OFFSET, + JSAPITreeSetIterator::LAST_OFFSET - JSAPITreeSetIterator::ITERATED_SET_OFFSET}}, + {JSType::JS_API_TREE_MAP, {JSAPITreeMap::TREE_MAP_OFFSET, + JSAPITreeMap::SIZE - JSAPITreeMap::TREE_MAP_OFFSET}}, + {JSType::JS_API_TREE_SET, {JSAPITreeSet::TREE_SET_OFFSET, + JSAPITreeSet::SIZE - JSAPITreeSet::TREE_SET_OFFSET}}, + {JSType::JS_API_VECTOR, {JSAPIVector::SIZE - JSAPIVector::ELEMENT_COUNT_OFFSET}}, + {JSType::JS_API_VECTOR_ITERATOR, { + JSAPIVectorIterator::ITERATED_VECTOR_OFFSET, + JSAPIVectorIterator::SIZE - JSAPIVectorIterator::ITERATED_VECTOR_OFFSET}}, + {JSType::JS_ARGUMENTS, {0}}, + {JSType::JS_ARRAY, {JSArray::LENGTH_OFFSET, + JSArray::TRACK_INFO_OFFSET, + JSArray::SIZE - JSArray::LENGTH_OFFSET}}, + {JSType::JS_ARRAY_BUFFER, {JSArrayBuffer::DATA_OFFSET, + JSArrayBuffer::LAST_OFFSET - JSArrayBuffer::DATA_OFFSET}}, + {JSType::JS_ARRAY_ITERATOR, {JSArrayIterator::ITERATED_ARRAY_OFFSET, + JSArrayIterator::LAST_OFFSET - JSArrayIterator::ITERATED_ARRAY_OFFSET}}, + {JSType::JS_ASYNCITERATOR, {JSObject::PROPERTIES_OFFSET, + JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION, { + JSAsyncAwaitStatusFunction::ASYNC_CONTEXT_OFFSET, + JSAsyncAwaitStatusFunction::SIZE - JSAsyncAwaitStatusFunction::ASYNC_CONTEXT_OFFSET}}, + {JSType::JS_ASYNC_FROM_SYNC_ITERATOR, { + JSAsyncFromSyncIterator::SYNC_ITERATOR_RECORD, + JSAsyncFromSyncIterator::SIZE - JSAsyncFromSyncIterator::SYNC_ITERATOR_RECORD}}, + {JSType::JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION, { + JSAsyncFromSyncIterUnwarpFunction::DONE_OFFSET, + JSAsyncFromSyncIterUnwarpFunction::SIZE - JSAsyncFromSyncIterUnwarpFunction::DONE_OFFSET}}, + {JSType::JS_ASYNC_FUNCTION, {JSAsyncFunction::SIZE - JSAsyncFunction::SIZE}}, + {JSType::JS_ASYNC_FUNC_OBJECT, {JSAsyncFuncObject::GENERATOR_PROMISE_OFFSET, + JSAsyncFuncObject::SIZE - JSAsyncFuncObject::GENERATOR_PROMISE_OFFSET}}, + {JSType::JS_ASYNC_GENERATOR_FUNCTION, {JSAsyncGeneratorFunction::SIZE - JSAsyncGeneratorFunction::SIZE}}, + {JSType::JS_ASYNC_GENERATOR_OBJECT, { + JSAsyncGeneratorObject::GENERATOR_CONTEXT_OFFSET, + JSAsyncGeneratorObject::ASYNC_GENERATOR_QUEUE_OFFSET, + JSAsyncGeneratorObject::GENERATOR_OFFSET, + JSAsyncGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET, + JSAsyncGeneratorObject::SIZE - JSAsyncGeneratorObject::GENERATOR_CONTEXT_OFFSET}}, + {JSType::JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN, { + JSAsyncGeneratorResNextRetProRstFtn::ASYNC_GENERATOR_OBJECT_OFFSET, + JSAsyncGeneratorResNextRetProRstFtn::SIZE - JSAsyncGeneratorResNextRetProRstFtn::ASYNC_GENERATOR_OBJECT_OFFSET}}, + {JSType::JS_ASYNC_MODULE_FULFILLED_FUNCTION, { + JSAsyncModuleFulfilledFunction::SIZE - JSAsyncModuleFulfilledFunction::SIZE}}, + {JSType::JS_ASYNC_MODULE_REJECTED_FUNCTION, { + JSAsyncModuleRejectedFunction::SIZE - JSAsyncModuleRejectedFunction::SIZE}}, + {JSType::JS_BIGINT64_ARRAY, {JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_BIGUINT64_ARRAY, {JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_BOUND_FUNCTION, {JSBoundFunction::BOUND_TARGET_OFFSET, + JSBoundFunction::BOUND_THIS_OFFSET, + JSBoundFunction::BOUND_ARGUMENTS_OFFSET, + JSBoundFunction::SIZE - JSBoundFunction::BOUND_TARGET_OFFSET}}, + {JSType::JS_CJS_EXPORTS, {CjsExports::JS_CJS_EXPORTS_OFFSET, + CjsExports::SIZE - CjsExports::JS_CJS_EXPORTS_OFFSET}}, + {JSType::JS_CJS_MODULE, {CjsModule::JS_CJS_MODULE_OFFSET, + CjsModule::ID_OFFSET, + CjsModule::PATH_OFFSET, + CjsModule::EXPORTS_OFFSET, + CjsModule::SIZE - CjsModule::JS_CJS_MODULE_OFFSET}}, + {JSType::JS_CJS_REQUIRE, {CjsRequire::JS_CJS_REQUIRE_OFFSET, + CjsRequire::CACHE_OFFSET, + CjsRequire::SIZE - CjsRequire::JS_CJS_REQUIRE_OFFSET}}, + {JSType::JS_COLLATOR, {JSCollator::ICU_FIELD_OFFSET, + JSCollator::LOCALE_OFFSET, + JSCollator::COLLATION_OFFSET, + JSCollator::BOUND_COMPARE_OFFSET, + JSCollator::SIZE - JSCollator::ICU_FIELD_OFFSET}}, + {JSType::JS_DATA_VIEW, {JSDataView::DATA_VIEW_OFFSET, + JSDataView::VIEW_ARRAY_BUFFER_OFFSET, + JSDataView::LAST_OFFSET - JSDataView::DATA_VIEW_OFFSET}}, + {JSType::JS_DATE, {JSDate::TIME_VALUE_OFFSET, + JSDate::LOCAL_TIME_OFFSET, + JSDate::SIZE - JSDate::TIME_VALUE_OFFSET}}, + {JSType::JS_DATE_TIME_FORMAT, {JSDateTimeFormat::LOCALE_OFFSET, + JSDateTimeFormat::CALENDAR_OFFSET, + JSDateTimeFormat::NUMBER_STRING_SYSTEM_OFFSET, + JSDateTimeFormat::TIME_ZONE_OFFSET, + JSDateTimeFormat::LOCALE_ICU_OFFSET, + JSDateTimeFormat::SIMPLE_DATE_TIME_FORMAT_ICU_OFFSET, + JSDateTimeFormat::ISO8601_OFFSET, + JSDateTimeFormat::BOUND_FORMAT_OFFSET, + JSDateTimeFormat::SIZE - JSDateTimeFormat::LOCALE_OFFSET}}, + {JSType::JS_DISPLAYNAMES, {JSDisplayNames::LOCALE_OFFSET, + JSDisplayNames::ICU_LOCALE_DISPPLAY_NAMES, + JSDisplayNames::SIZE - JSDisplayNames::LOCALE_OFFSET}}, + {JSType::JS_ERROR, {JSObject::PROPERTIES_OFFSET, + JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_EVAL_ERROR, {JSObject::PROPERTIES_OFFSET, + JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_FINALIZATION_REGISTRY, { + JSFinalizationRegistry::CLEANUP_CALLBACK_OFFSET, + JSFinalizationRegistry::NO_UNREGISTER_OFFSET, + JSFinalizationRegistry::MAYBE_UNREGISTER_OFFSET, + JSFinalizationRegistry::NEXT_OFFSET, + JSFinalizationRegistry::PREV_OFFSET, + JSFinalizationRegistry::SIZE - JSFinalizationRegistry::CLEANUP_CALLBACK_OFFSET}}, + {JSType::JS_FLOAT32_ARRAY, {JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_FLOAT64_ARRAY, {JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_FORIN_ITERATOR, {JSForInIterator::OBJECT_OFFSET, + JSForInIterator::CACHED_HCLASS_OFFSET, + JSForInIterator::KEYS_OFFSET, + JSForInIterator::LAST_OFFSET - JSForInIterator::OBJECT_OFFSET}}, + {JSType::JS_FUNCTION, {JSFunction::PROTO_OR_DYNCLASS_OFFSET, + JSFunction::LEXICAL_ENV_OFFSET, + JSFunction::MACHINECODE_OFFSET, + JSFunction::BASELINECODE_OFFSET, + JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET, + JSFunction::HOME_OBJECT_OFFSET, + JSFunction::ECMA_MODULE_OFFSET, + JSFunction::PROTO_TRANS_ROOT_HCLASS_OFFSET, + JSFunction::LAST_OFFSET - JSFunction::PROTO_OR_DYNCLASS_OFFSET}}, + {JSType::JS_FUNCTION_BASE, {JSFunctionBase::METHOD_OFFSET, + JSFunctionBase::LAST_OFFSET - JSFunctionBase::METHOD_OFFSET}}, + {JSType::JS_GENERATOR_CONTEXT, { + GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET, + GeneratorContext::GENERATOR_METHOD_OFFSET, + GeneratorContext::GENERATOR_THIS_OFFSET, + GeneratorContext::GENERATOR_ACC_OFFSET, + GeneratorContext::GENERATOR_GENERATOR_OBJECT_OFFSET, + GeneratorContext::GENERATOR_LEXICALENV_OFFSET, + GeneratorContext::LAST_OFFSET - GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET}}, + {JSType::JS_GENERATOR_FUNCTION, {JSGeneratorFunction::SIZE - JSGeneratorFunction::SIZE}}, + {JSType::JS_GENERATOR_OBJECT, { + JSGeneratorObject::GENERATOR_CONTEXT_OFFSET, + JSGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET, + JSGeneratorObject::SIZE - JSGeneratorObject::GENERATOR_CONTEXT_OFFSET}}, + {JSType::JS_GLOBAL_OBJECT, {JSGlobalObject::SIZE - JSGlobalObject::SIZE}}, + {JSType::JS_INT16_ARRAY, {JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_INT32_ARRAY, {JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_INT8_ARRAY, {JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_INTL, {JSIntl::FALLBACK_SYMBOL, + JSIntl::SIZE - JSIntl::FALLBACK_SYMBOL}}, + {JSType::JS_INTL_BOUND_FUNCTION, {JSIntlBoundFunction::NUMBER_FORMAT_OFFSET, + JSIntlBoundFunction::DATETIME_FORMAT_OFFSET, + JSIntlBoundFunction::COLLATOR_OFFSET, + JSIntlBoundFunction::SIZE - JSIntlBoundFunction::NUMBER_FORMAT_OFFSET}}, + {JSType::JS_ITERATOR, {JSObject::PROPERTIES_OFFSET, + JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_LIST_FORMAT, {JSListFormat::LOCALE_OFFSET, + JSListFormat::ICU_LIST_FORMAT, + JSListFormat::SIZE - JSListFormat::LOCALE_OFFSET}}, + {JSType::JS_LOCALE, {JSLocale::ICU_FIELD_OFFSET, + JSLocale::SIZE - JSLocale::ICU_FIELD_OFFSET}}, + {JSType::JS_MAP, {JSMap::LINKED_MAP_OFFSET, + JSMap::SIZE - JSMap::LINKED_MAP_OFFSET}}, + {JSType::JS_MAP_ITERATOR, {JSMapIterator::ITERATED_MAP_OFFSET, + JSMapIterator::LAST_OFFSET - JSMapIterator::ITERATED_MAP_OFFSET}}, + {JSType::JS_MODULE_NAMESPACE, {ModuleNamespace::MODULE_OFFSET, + ModuleNamespace::EXPORTS_OFFSET, + ModuleNamespace::DEREGISTER_PROCESSION_OFFSET, + ModuleNamespace::SIZE - ModuleNamespace::MODULE_OFFSET}}, + {JSType::JS_NATIVE_POINTER, {JSNativePointer::DATA_SIZE_OFFSET, + JSNativePointer::LAST_OFFSET - JSNativePointer::POINTER_OFFSET}}, + {JSType::JS_NUMBER_FORMAT, {JSNumberFormat::LOCALE_OFFSET, + JSNumberFormat::NUMBER_STRING_SYSTEM_OFFSET, + JSNumberFormat::CURRENCY_OFFSET, + JSNumberFormat::UNIT_OFFSET, + JSNumberFormat::MINIMUM_INTEGER_DIGITS_OFFSET, + JSNumberFormat::MINIMUM_FRACTION_DIGITS_OFFSET, + JSNumberFormat::MAXIMUM_FRACTION_DIGITS_OFFSET, + JSNumberFormat::MINIMUM_SIGNIFICANT_DIGITS_OFFSET, + JSNumberFormat::MAXIMUM_SIGNIFICANT_DIGITS_OFFSET, + JSNumberFormat::USER_GROUPING_OFFSET, + JSNumberFormat::BOUND_FORMAT_OFFSET, + JSNumberFormat::ICU_FIELD_OFFSET, + JSNumberFormat::SIZE - JSNumberFormat::LOCALE_OFFSET}}, + {JSType::JS_OBJECT, {JSObject::PROPERTIES_OFFSET, + JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_OOM_ERROR, {JSObject::PROPERTIES_OFFSET, + JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_PLURAL_RULES, {JSPluralRules::LOCALE_OFFSET, + JSPluralRules::MINIMUM_INTEGER_DIGITS_OFFSET, + JSPluralRules::MINIMUM_FRACTION_DIGITS_OFFSET, + JSPluralRules::MAXIMUM_FRACTION_DIGITS_OFFSET, + JSPluralRules::MININUM_SIGNIFICANT_DIGITS_OFFSET, + JSPluralRules::MAXINUM_SIGNIFICANT_DIGITS_OFFSET, + JSPluralRules::ICU_PLURAL_RULES_OFFSET, + JSPluralRules::ICU_NUMBER_FORMAT_OFFSET, + JSPluralRules::SIZE - JSPluralRules::LOCALE_OFFSET}}, + {JSType::JS_PRIMITIVE_REF, {JSPrimitiveRef::VALUE_OFFSET, + JSPrimitiveRef::SIZE - JSPrimitiveRef::VALUE_OFFSET}}, + {JSType::JS_PROMISE, {JSPromise::PROMISE_RESULT_OFFSET, + JSPromise::PROMISE_FULFILL_REACTIONS_OFFSET, + JSPromise::PROMISE_REJECT_REACTIONS_OFFSET, + JSPromise::SIZE - JSPromise::PROMISE_RESULT_OFFSET}}, + {JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION, { + JSPromiseAllResolveElementFunction::INDEX_OFFSET, + JSPromiseAllResolveElementFunction::VALUES_OFFSET, + JSPromiseAllResolveElementFunction::CAPABILITIES_OFFSET, + JSPromiseAllResolveElementFunction::REMAINING_ELEMENTS_OFFSET, + JSPromiseAllResolveElementFunction::ALREADY_CALLED_OFFSET, + JSPromiseAllResolveElementFunction::SIZE - JSPromiseAllResolveElementFunction::INDEX_OFFSET}}, + {JSType::JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION, { + JSPromiseAllSettledElementFunction::ALREADY_CALLED_OFFSET, + JSPromiseAllSettledElementFunction::VALUES_OFFSET, + JSPromiseAllSettledElementFunction::CAPABILITY_OFFSET, + JSPromiseAllSettledElementFunction::REMAINING_ELEMENTS_OFFSET, + JSPromiseAllSettledElementFunction::SIZE - JSPromiseAllSettledElementFunction::ALREADY_CALLED_OFFSET}}, + {JSType::JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION, { + JSPromiseAnyRejectElementFunction::ERRORS_OFFSET, + JSPromiseAnyRejectElementFunction::CAPABILITY_OFFSET, + JSPromiseAnyRejectElementFunction::REMAINING_ELEMENTS_OFFSET, + JSPromiseAnyRejectElementFunction::ALREADY_CALLED_OFFSET, + JSPromiseAnyRejectElementFunction::SIZE - JSPromiseAnyRejectElementFunction::ERRORS_OFFSET}}, + {JSType::JS_PROMISE_EXECUTOR_FUNCTION, { + JSPromiseExecutorFunction::CAPABILITY_OFFSET, + JSPromiseExecutorFunction::SIZE - JSPromiseExecutorFunction::CAPABILITY_OFFSET}}, + {JSType::JS_PROMISE_FINALLY_FUNCTION, { + JSPromiseFinallyFunction::CONSTRUCTOR_OFFSET, + JSPromiseFinallyFunction::ONFINALLY_OFFSET, + JSPromiseFinallyFunction::SIZE - JSPromiseFinallyFunction::CONSTRUCTOR_OFFSET}}, + {JSType::JS_PROMISE_REACTIONS_FUNCTION, { + JSPromiseReactionsFunction::PROMISE_OFFSET, + JSPromiseReactionsFunction::ALREADY_RESOLVED_OFFSET, + JSPromiseReactionsFunction::SIZE - JSPromiseReactionsFunction::PROMISE_OFFSET}}, + {JSType::JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION, { + JSPromiseValueThunkOrThrowerFunction::RESULT_OFFSET, + JSPromiseValueThunkOrThrowerFunction::SIZE - JSPromiseValueThunkOrThrowerFunction::RESULT_OFFSET}}, + {JSType::JS_PROXY, {JSProxy::TARGET_OFFSET, JSProxy::HANDLER_OFFSET, JSProxy::METHOD_OFFSET, + JSProxy::PRIVATE_FIELD_OFFSET, JSProxy::SIZE - JSProxy::TARGET_OFFSET}}, + {JSType::JS_PROXY_REVOC_FUNCTION, { + JSProxyRevocFunction::REVOCABLE_PROXY_OFFSET, + JSProxyRevocFunction::SIZE - JSProxyRevocFunction::REVOCABLE_PROXY_OFFSET}}, + {JSType::JS_RANGE_ERROR, {JSObject::PROPERTIES_OFFSET, JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_REALM, {JSRealm::VALUE_OFFSET, JSRealm::GLOBAL_ENV_OFFSET, + JSRealm::SIZE - JSRealm::VALUE_OFFSET}}, + {JSType::JS_REFERENCE_ERROR, {JSObject::PROPERTIES_OFFSET, JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_REG_EXP, {JSRegExp::REGEXP_BYTE_CODE_OFFSET, JSRegExp::ORIGINAL_SOURCE_OFFSET, + JSRegExp::ORIGINAL_FLAGS_OFFSET, JSRegExp::GROUP_NAME_OFFSET, + JSRegExp::SIZE - JSRegExp::REGEXP_BYTE_CODE_OFFSET}}, + {JSType::JS_REG_EXP_ITERATOR, { + JSRegExpIterator::ITERATING_REGEXP_OFFSET, + JSRegExpIterator::ITERATED_STRING_OFFSET, + JSRegExpIterator::SIZE - JSRegExpIterator::ITERATING_REGEXP_OFFSET}}, + {JSType::JS_RELATIVE_TIME_FORMAT, { + JSRelativeTimeFormat::LOCALE_OFFSET, + JSRelativeTimeFormat::NUMBERING_SYSTEM_OFFSET, + JSRelativeTimeFormat::ICU_FIELD_OFFSET, + JSRelativeTimeFormat::SIZE - JSRelativeTimeFormat::LOCALE_OFFSET}}, + {JSType::JS_SEGMENTER, {JSSegmenter::LOCALE_OFFSET, + JSSegmenter::ICU_FIELD_OFFSET, + JSSegmenter::SIZE - JSSegmenter::LOCALE_OFFSET}}, + {JSType::JS_SEGMENTS, {JSSegments::ICU_FIELD_OFFSET, JSSegments::SEGMENTS_STRING_OFFSET, + JSSegments::UNICODE_STRING_OFFSET, + JSSegments::SIZE - JSSegments::ICU_FIELD_OFFSET}}, + {JSType::JS_SEGMENT_ITERATOR, {JSSegmentIterator::ICU_FIELD_OFFSET, + JSSegmentIterator::SEGMENTS_STRING_OFFSET, + JSSegmentIterator::UNICODE_STRING_OFFSET, + JSSegmentIterator::SIZE - JSSegmentIterator::ICU_FIELD_OFFSET}}, + {JSType::JS_SENDABLE_ARRAY_BUFFER, { + JSSendableArrayBuffer::DATA_OFFSET, + JSSendableArrayBuffer::LAST_OFFSET - JSSendableArrayBuffer::DATA_OFFSET}}, + {JSType::JS_SET, {JSSet::LINKED_SET_OFFSET, JSSet::SIZE - JSSet::LINKED_SET_OFFSET}}, + {JSType::JS_SET_ITERATOR, {JSSetIterator::ITERATED_SET_OFFSET, + JSSetIterator::LAST_OFFSET - JSSetIterator::ITERATED_SET_OFFSET}}, + {JSType::JS_SHARED_ARRAY, {JSSharedArray::TRACK_INFO_OFFSET, + JSSharedArray::SIZE - JSSharedArray::LENGTH_OFFSET}}, + {JSType::JS_SHARED_ARRAY_BUFFER, {JSArrayBuffer::DATA_OFFSET, + JSArrayBuffer::LAST_OFFSET - JSArrayBuffer::DATA_OFFSET}}, + {JSType::JS_SHARED_ARRAY_ITERATOR, { + JSSharedArrayIterator::ITERATED_ARRAY_OFFSET, + JSSharedArrayIterator::LAST_OFFSET - JSSharedArrayIterator::ITERATED_ARRAY_OFFSET}}, + {JSType::JS_SHARED_ASYNC_FUNCTION, {JSAsyncFunction::SIZE - JSAsyncFunction::SIZE}}, + {JSType::JS_SHARED_BIGINT64_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_BIGUINT64_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_FLOAT32_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_FLOAT64_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_FUNCTION, {JSSharedFunction::SIZE - JSSharedFunction::SIZE}}, + {JSType::JS_SHARED_INT16_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_INT32_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_INT8_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_MAP, {JSSharedMap::LINKED_MAP_OFFSET, + JSSharedMap::SIZE - JSSharedMap::LINKED_MAP_OFFSET}}, + {JSType::JS_SHARED_MAP_ITERATOR, { + JSSharedMapIterator::ITERATED_MAP_OFFSET, + JSSharedMapIterator::LAST_OFFSET - JSSharedMapIterator::ITERATED_MAP_OFFSET}}, + {JSType::JS_SHARED_OBJECT, {JSSharedObject::SIZE - JSSharedObject::SIZE}}, + {JSType::JS_SHARED_SET, {JSSharedSet::LINKED_SET_OFFSET, + JSSharedSet::SIZE - JSSharedSet::LINKED_SET_OFFSET}}, + {JSType::JS_SHARED_SET_ITERATOR, { + JSSharedSetIterator::ITERATED_SET_OFFSET, + JSSharedSetIterator::LAST_OFFSET - JSSharedSetIterator::ITERATED_SET_OFFSET}}, + {JSType::JS_SHARED_TYPED_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_UINT16_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_UINT32_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_UINT8_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_SHARED_UINT8_CLAMPED_ARRAY, { + JSSharedTypedArray::SIZE - JSSharedTypedArray::MOD_RECORD_OFFSET}}, + {JSType::JS_STRING_ITERATOR, { + JSStringIterator::ITERATED_STRING_OFFSET, + JSStringIterator::SIZE - JSStringIterator::ITERATED_STRING_OFFSET}}, + {JSType::JS_SYNTAX_ERROR, {JSObject::PROPERTIES_OFFSET, JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_TERMINATION_ERROR, {JSObject::PROPERTIES_OFFSET, JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_TYPED_ARRAY, {JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_TYPE_ERROR, {JSObject::PROPERTIES_OFFSET, JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_UINT16_ARRAY, { + JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_UINT32_ARRAY, { + JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_UINT8_ARRAY, { + JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_UINT8_CLAMPED_ARRAY, { + JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::TYPED_ARRAY_NAME_OFFSET, + JSTypedArray::SIZE - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_URI_ERROR, {JSObject::PROPERTIES_OFFSET, JSObject::ELEMENTS_OFFSET, + JSObject::SIZE - JSObject::PROPERTIES_OFFSET}}, + {JSType::JS_WEAK_MAP, { + JSWeakMap::LINKED_MAP_OFFSET, JSWeakMap::SIZE - JSWeakMap::LINKED_MAP_OFFSET}}, + {JSType::JS_WEAK_REF, { + JSWeakRef::WEAK_OBJECT_OFFSET, JSWeakRef::SIZE - JSWeakRef::WEAK_OBJECT_OFFSET}}, + {JSType::JS_WEAK_SET, { + JSWeakSet::LINKED_SET_OFFSET, JSWeakSet::SIZE - JSWeakSet::LINKED_SET_OFFSET}}, + {JSType::LEXICAL_ENV, {TaggedArray::SIZE - TaggedArray::SIZE}}, + {JSType::LINE_STRING, {LineEcmaString::SIZE - LineEcmaString::SIZE}}, + {JSType::LINKED_NODE, {LinkedNode::NEXT_OFFSET, LinkedNode::LAST_OFFSET - LinkedNode::NEXT_OFFSET}}, + {JSType::LOCAL_EXPORTENTRY_RECORD, { + LocalExportEntry::LOCAL_EXPORT_ENTRY_OFFSET, + LocalExportEntry::LOCAL_NAME_OFFSET, + LocalExportEntry::SIZE - LocalExportEntry::LOCAL_EXPORT_ENTRY_OFFSET}}, + {JSType::MACHINE_CODE_OBJECT, {MachineCode::LAST_OFFSET - MachineCode::INS_SIZE_OFFSET}}, + {JSType::MARKER_CELL, {MarkerCell::SIZE - MarkerCell::BIT_FIELD_OFFSET}}, + {JSType::METHOD, {Method::CONSTANT_POOL_OFFSET, Method::LAST_OFFSET - Method::CONSTANT_POOL_OFFSET}}, + {JSType::MICRO_JOB_QUEUE, {job::MicroJobQueue::PROMISE_JOB_QUEUE_OFFSET, + job::MicroJobQueue::SCRIPT_JOB_QUEUE_OFFSET, + job::MicroJobQueue::SIZE - job::MicroJobQueue::PROMISE_JOB_QUEUE_OFFSET}}, + {JSType::MODULE_RECORD, {ModuleRecord::SIZE - ModuleRecord::SIZE}}, + {JSType::MUTANT_TAGGED_ARRAY, {MutantTaggedArray::SIZE - MutantTaggedArray::SIZE}}, + {JSType::NATIVE_MODULE_FAILURE_INFO, { + NativeModuleFailureInfo::ARK_NATIVE_MODULE_FAILURE_INFO_OFFSET, + NativeModuleFailureInfo::SIZE - NativeModuleFailureInfo::ARK_NATIVE_MODULE_FAILURE_INFO_OFFSET}}, + {JSType::PENDING_JOB, {job::PendingJob::JOB_OFFSET, + job::PendingJob::ARGUMENT_OFFSET, + job::PendingJob::SIZE - job::PendingJob::ARGUMENT_OFFSET}}, + {JSType::PROFILE_TYPE_INFO, {ProfileTypeInfo::SIZE - ProfileTypeInfo::SIZE}}, + {JSType::PROFILE_TYPE_INFO_CELL_0, { + ProfileTypeInfoCell::VALUE_OFFSET, + ProfileTypeInfoCell::MACHINE_CODE_OFFSET, + ProfileTypeInfoCell::HANDLE_OFFSET, + ProfileTypeInfoCell::LAST_OFFSET - ProfileTypeInfoCell::VALUE_OFFSET}}, + {JSType::PROFILE_TYPE_INFO_CELL_1, { + ProfileTypeInfoCell::VALUE_OFFSET, + ProfileTypeInfoCell::MACHINE_CODE_OFFSET, + ProfileTypeInfoCell::HANDLE_OFFSET, + ProfileTypeInfoCell::LAST_OFFSET - ProfileTypeInfoCell::VALUE_OFFSET}}, + {JSType::PROFILE_TYPE_INFO_CELL_N, { + ProfileTypeInfoCell::VALUE_OFFSET, + ProfileTypeInfoCell::MACHINE_CODE_OFFSET, + ProfileTypeInfoCell::HANDLE_OFFSET, + ProfileTypeInfoCell::LAST_OFFSET - ProfileTypeInfoCell::VALUE_OFFSET}}, + {JSType::PROGRAM, {Program::MAIN_FUNCTION_OFFSET, Program::SIZE - Program::MAIN_FUNCTION_OFFSET}}, + {JSType::PROMISE_CAPABILITY, {PromiseCapability::PROMISE_OFFSET, PromiseCapability::RESOLVE_OFFSET, + PromiseCapability::REJECT_OFFSET, + PromiseCapability::SIZE - PromiseCapability::PROMISE_OFFSET}}, + {JSType::PROMISE_ITERATOR_RECORD, {PromiseIteratorRecord::ITERATOR_OFFSET, + PromiseIteratorRecord::SIZE - PromiseIteratorRecord::ITERATOR_OFFSET}}, + {JSType::PROMISE_REACTIONS, {PromiseReaction::PROMISE_CAPABILITY_OFFSET, + PromiseReaction::HANDLER_OFFSET, + PromiseReaction::SIZE - PromiseReaction::PROMISE_CAPABILITY_OFFSET}}, + {JSType::PROMISE_RECORD, {PromiseRecord::VALUE_OFFSET, + PromiseRecord::SIZE - PromiseRecord::VALUE_OFFSET}}, + {JSType::PROPERTY_BOX, {PropertyBox::VALUE_OFFSET, + PropertyBox::SIZE - PropertyBox::VALUE_OFFSET}}, + {JSType::PROTOTYPE_HANDLER, {PrototypeHandler::HANDLER_INFO_OFFSET, + PrototypeHandler::PROTO_CELL_OFFSET, + PrototypeHandler::HOLDER_OFFSET, + PrototypeHandler::ACCESSOR_JSFUNCTION_OFFSET, + PrototypeHandler::SIZE - PrototypeHandler::HANDLER_INFO_OFFSET}}, + {JSType::PROTOTYPE_INFO, {ProtoChangeDetails::CHANGE_LISTENER_OFFSET, + ProtoChangeDetails::SIZE - ProtoChangeDetails::CHANGE_LISTENER_OFFSET}}, + {JSType::PROTO_CHANGE_MARKER, {ProtoChangeMarker::SIZE - ProtoChangeMarker::BIT_FIELD_OFFSET}}, + {JSType::RB_TREENODE, {RBTreeNode::LEFT_OFFSET, RBTreeNode::RIGHT_OFFSET, RBTreeNode::ISRED_OFFSET, + RBTreeNode::SIZE - RBTreeNode::LEFT_OFFSET}}, + {JSType::RESOLVEDBINDING_RECORD, {ResolvedBinding::MODULE_OFFSET, ResolvedBinding::BINDING_NAME_OFFSET, + ResolvedBinding::SIZE - ResolvedBinding::MODULE_OFFSET}}, + {JSType::RESOLVEDINDEXBINDING_RECORD, { + ResolvedIndexBinding::MODULE_OFFSET, + ResolvedIndexBinding::INDEX_OFFSET, + ResolvedIndexBinding::SIZE - ResolvedIndexBinding::MODULE_OFFSET}}, + {JSType::RESOLVEDRECORDBINDING_RECORD, { + ResolvedRecordBinding::MODULE_RECORD_OFFSET, + ResolvedRecordBinding::BINDING_NAME_OFFSET, + ResolvedRecordBinding::SIZE - ResolvedRecordBinding::MODULE_RECORD_OFFSET}}, + {JSType::RESOLVEDRECORDINDEXBINDING_RECORD, { + ResolvedRecordIndexBinding::MODULE_RECORD_INDEX_OFFSET, + ResolvedRecordIndexBinding::ABC_FILE_NAME, + ResolvedRecordIndexBinding::SIZE - ResolvedRecordIndexBinding::MODULE_RECORD_INDEX_OFFSET}}, + {JSType::RESOLVING_FUNCTIONS_RECORD, { + ResolvingFunctionsRecord::RESOLVE_FUNCTION_OFFSET, + ResolvingFunctionsRecord::REJECT_FUNCTION_OFFSET, + ResolvingFunctionsRecord::SIZE - ResolvingFunctionsRecord::RESOLVE_FUNCTION_OFFSET}}, + {JSType::SENDABLE_ENV, {TaggedArray::SIZE - TaggedArray::SIZE}}, + {JSType::SLICED_STRING, {SlicedString::PARENT_OFFSET, SlicedString::SIZE - SlicedString::PARENT_OFFSET}}, + {JSType::SOURCE_TEXT_MODULE_RECORD, { + SourceTextModule::SOURCE_TEXT_MODULE_OFFSET, + SourceTextModule::NAMESPACE_OFFSET, + SourceTextModule::REQUESTED_MODULES_OFFSET, + SourceTextModule::IMPORT_ENTRIES_OFFSET, + SourceTextModule::LOCAL_EXPORT_ENTTRIES_OFFSET, + SourceTextModule::INDIRECT_EXPORT_ENTTRIES_OFFSET, + SourceTextModule::START_EXPORT_ENTTRIES_OFFSET, + SourceTextModule::NAME_DICTIONARY_OFFSET, + SourceTextModule::CYCLE_ROOT_OFFSET, + SourceTextModule::TOP_LEVEL_CAPABILITY_OFFSET, + SourceTextModule::ASYNC_PARENT_MODULES_OFFSET, + SourceTextModule::SENDABLE_ENV_OFFSET, + SourceTextModule::SIZE - SourceTextModule::SOURCE_TEXT_MODULE_OFFSET}}, + {JSType::STAR_EXPORTENTRY_RECORD, {StarExportEntry::STAR_EXPORT_ENTRY_OFFSET, + StarExportEntry::SIZE - StarExportEntry::STAR_EXPORT_ENTRY_OFFSET}}, + {JSType::STORE_TS_HANDLER, {StoreAOTHandler::HANDLER_INFO_OFFSET, + StoreAOTHandler::PROTO_CELL_OFFSET, + StoreAOTHandler::HOLDER_OFFSET, + StoreAOTHandler::SIZE - StoreAOTHandler::HANDLER_INFO_OFFSET}}, + {JSType::SYMBOL, {JSSymbol::DESCRIPTION_OFFSET, + JSSymbol::SIZE - JSSymbol::DESCRIPTION_OFFSET}}, + {JSType::TAGGED_ARRAY, {TaggedArray::LENGTH_OFFSET, TaggedArray::DATA_OFFSET, + TaggedArray::SIZE - TaggedArray::SIZE}}, + {JSType::TAGGED_DICTIONARY, {TaggedArray::LAST_OFFSET - TaggedArray::LENGTH_OFFSET}}, + {JSType::TEMPLATE_MAP, {TaggedArray::LAST_OFFSET - TaggedArray::LENGTH_OFFSET}}, + {JSType::TRACK_INFO, {TrackInfo::CACHED_HCLASS_OFFSET, TrackInfo::CACHED_FUNC_OFFSET, + TrackInfo::LAST_OFFSET - TrackInfo::CACHED_HCLASS_OFFSET}}, + {JSType::TRANSITION_HANDLER, {TransitionHandler::HANDLER_INFO_OFFSET, + TransitionHandler::TRANSITION_HCLASS_OFFSET, + TransitionHandler::SIZE - TransitionHandler::HANDLER_INFO_OFFSET}}, + {JSType::TRANS_WITH_PROTO_HANDLER, { + TransWithProtoHandler::HANDLER_INFO_OFFSET, + TransWithProtoHandler::TRANSITION_HCLASS_OFFSET, + TransWithProtoHandler::PROTO_CELL_OFFSET, + TransWithProtoHandler::SIZE - TransWithProtoHandler::HANDLER_INFO_OFFSET}}, + {JSType::TREE_STRING, {TreeEcmaString::FIRST_OFFSET, TreeEcmaString::SECOND_OFFSET, + TreeEcmaString::SIZE - TreeEcmaString::FIRST_OFFSET}}, + {JSType::VTABLE, {TaggedArray::LAST_OFFSET - TaggedArray::LENGTH_OFFSET}} + }; + // { typeName: [all parents of this type]} + parentsTable_ = { + {JSType::HCLASS, {"TAGGED_OBJECT"}}, + {JSType::ACCESSOR_DATA, {"RECORD"}}, + {JSType::AOT_LITERAL_INFO, {"TAGGED_OBJECT"}}, + {JSType::ASYNC_GENERATOR_REQUEST, {"RECORD"}}, + {JSType::ASYNC_ITERATOR_RECORD, {"RECORD"}}, + {JSType::BIGINT, {"TAGGED_OBJECT"}}, + {JSType::BYTE_ARRAY, {"TAGGED_OBJECT"}}, + {JSType::CELL_RECORD, {"RECORD"}}, + {JSType::CLASS_INFO_EXTRACTOR, {"TAGGED_OBJECT"}}, + {JSType::CLASS_LITERAL, {"TAGGED_OBJECT"}}, + {JSType::COMPLETION_RECORD, {"RECORD"}}, + {JSType::CONSTANT_POOL, {"TAGGED_ARRAY"}}, + {JSType::CONSTANT_STRING, {"ECMA_STRING"}}, + {JSType::COW_MUTANT_TAGGED_ARRAY, {"MUTANT_TAGGED_ARRAY"}}, + {JSType::COW_TAGGED_ARRAY, {"TAGGED_ARRAY"}}, + {JSType::EXTRA_PROFILE_TYPE_INFO, {"TAGGED_OBJECT"}}, + {JSType::FUNCTION_TEMPLATE, {"TAGGED_OBJECT"}}, + {JSType::GLOBAL_ENV, {"TAGGED_OBJECT"}}, + {JSType::IMPORTENTRY_RECORD, {"RECORD"}}, + {JSType::INDIRECT_EXPORTENTRY_RECORD, {"RECORD"}}, + {JSType::INTERNAL_ACCESSOR, {"RECORD"}}, + {JSType::JS_AGGREGATE_ERROR, {"ECMA_OBJECT"}}, + {JSType::JS_API_ARRAYLIST_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_ARRAY_LIST, {"JS_OBJECT"}}, + {JSType::JS_API_BITVECTOR, {"JS_OBJECT"}}, + {JSType::JS_API_BITVECTOR_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_DEQUE, {"JS_OBJECT"}}, + {JSType::JS_API_DEQUE_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_HASHMAP_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_HASHSET_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_HASH_MAP, {"JS_OBJECT"}}, + {JSType::JS_API_HASH_SET, {"JS_OBJECT"}}, + {JSType::JS_API_LIGHT_WEIGHT_MAP, {"JS_OBJECT"}}, + {JSType::JS_API_LIGHT_WEIGHT_MAP_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_LIGHT_WEIGHT_SET, {"JS_OBJECT"}}, + {JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_LINKED_LIST, {"JS_OBJECT"}}, + {JSType::JS_API_LINKED_LIST_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_LIST, {"JS_OBJECT"}}, + {JSType::JS_API_LIST_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_PLAIN_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_API_PLAIN_ARRAY_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_QUEUE, {"JS_OBJECT"}}, + {JSType::JS_API_QUEUE_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_STACK, {"JS_OBJECT"}}, + {JSType::JS_API_STACK_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_TREEMAP_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_TREESET_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_API_TREE_MAP, {"JS_OBJECT"}}, + {JSType::JS_API_TREE_SET, {"JS_OBJECT"}}, + {JSType::JS_API_VECTOR, {"JS_OBJECT"}}, + {JSType::JS_API_VECTOR_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_ARGUMENTS, {"JS_OBJECT"}}, + {JSType::JS_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_ARRAY_BUFFER, {"JS_OBJECT"}}, + {JSType::JS_ARRAY_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_ASYNCITERATOR, {"ECMA_OBJECT"}}, + {JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_ASYNC_FROM_SYNC_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_ASYNC_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_ASYNC_FUNC_OBJECT, {"JS_GENERATOR_OBJECT"}}, + {JSType::JS_ASYNC_GENERATOR_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_ASYNC_GENERATOR_OBJECT, {"JS_OBJECT"}}, + {JSType::JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN, {"JS_FUNCTION"}}, + {JSType::JS_ASYNC_MODULE_FULFILLED_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_ASYNC_MODULE_REJECTED_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_BIGINT64_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_BIGUINT64_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_BOUND_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_CJS_EXPORTS, {"JS_OBJECT"}}, + {JSType::JS_CJS_MODULE, {"JS_OBJECT"}}, + {JSType::JS_CJS_REQUIRE, {"JS_OBJECT"}}, + {JSType::JS_COLLATOR, {"JS_OBJECT"}}, + {JSType::JS_DATA_VIEW, {"JS_OBJECT"}}, + {JSType::JS_DATE, {"JS_OBJECT"}}, + {JSType::JS_DATE_TIME_FORMAT, {"JS_OBJECT"}}, + {JSType::JS_DISPLAYNAMES, {"JS_OBJECT"}}, + {JSType::JS_ERROR, {"ECMA_OBJECT"}}, + {JSType::JS_EVAL_ERROR, {"ECMA_OBJECT"}}, + {JSType::JS_FINALIZATION_REGISTRY, {"JS_OBJECT"}}, + {JSType::JS_FLOAT32_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_FLOAT64_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_FORIN_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_FUNCTION, {"JS_FUNCTION_BASE"}}, + {JSType::JS_FUNCTION_BASE, {"JS_OBJECT"}}, + {JSType::JS_GENERATOR_CONTEXT, {"TAGGED_OBJECT"}}, + {JSType::JS_GENERATOR_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_GENERATOR_OBJECT, {"JS_OBJECT"}}, + {JSType::JS_GLOBAL_OBJECT, {"JS_OBJECT"}}, + {JSType::JS_INT16_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_INT32_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_INT8_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_INTL, {"JS_OBJECT"}}, + {JSType::JS_INTL_BOUND_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_ITERATOR, {"ECMA_OBJECT"}}, + {JSType::JS_LIST_FORMAT, {"JS_OBJECT"}}, + {JSType::JS_LOCALE, {"JS_OBJECT"}}, + {JSType::JS_MAP, {"JS_OBJECT"}}, + {JSType::JS_MAP_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_MODULE_NAMESPACE, {"JS_OBJECT"}}, + {JSType::JS_NATIVE_POINTER, {"TAGGED_OBJECT"}}, + {JSType::JS_NUMBER_FORMAT, {"JS_OBJECT"}}, + {JSType::JS_OBJECT, {"ECMA_OBJECT"}}, + {JSType::JS_OOM_ERROR, {"ECMA_OBJECT"}}, + {JSType::JS_PLURAL_RULES, {"JS_OBJECT"}}, + {JSType::JS_PRIMITIVE_REF, {"JS_OBJECT"}}, + {JSType::JS_PROMISE, {"JS_OBJECT"}}, + {JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_PROMISE_EXECUTOR_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_PROMISE_FINALLY_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_PROMISE_REACTIONS_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_PROXY, {"ECMA_OBJECT"}}, + {JSType::JS_PROXY_REVOC_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_RANGE_ERROR, {"ECMA_OBJECT"}}, + {JSType::JS_REALM, {"JS_OBJECT"}}, + {JSType::JS_REFERENCE_ERROR, {"ECMA_OBJECT"}}, + {JSType::JS_REG_EXP, {"JS_OBJECT"}}, + {JSType::JS_REG_EXP_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_RELATIVE_TIME_FORMAT, {"JS_OBJECT"}}, + {JSType::JS_SEGMENTER, {"JS_OBJECT"}}, + {JSType::JS_SEGMENTS, {"JS_OBJECT"}}, + {JSType::JS_SEGMENT_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_SENDABLE_ARRAY_BUFFER, {"JS_OBJECT"}}, + {JSType::JS_SET, {"JS_OBJECT"}}, + {JSType::JS_SET_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_SHARED_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_SHARED_ARRAY_BUFFER, {"JS_OBJECT"}}, + {JSType::JS_SHARED_ARRAY_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_SHARED_ASYNC_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_SHARED_BIGINT64_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_BIGUINT64_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_FLOAT32_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_FLOAT64_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_FUNCTION, {"JS_FUNCTION"}}, + {JSType::JS_SHARED_INT16_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_INT32_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_INT8_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_MAP, {"JS_OBJECT"}}, + {JSType::JS_SHARED_MAP_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_SHARED_OBJECT, {"JS_OBJECT"}}, + {JSType::JS_SHARED_SET, {"JS_OBJECT"}}, + {JSType::JS_SHARED_SET_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_SHARED_TYPED_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_UINT16_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_UINT32_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_UINT8_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_SHARED_UINT8_CLAMPED_ARRAY, {"JS_TYPED_ARRAY"}}, + {JSType::JS_STRING_ITERATOR, {"JS_OBJECT"}}, + {JSType::JS_SYNTAX_ERROR, {"ECMA_OBJECT"}}, + {JSType::JS_TERMINATION_ERROR, {"ECMA_OBJECT"}}, + {JSType::JS_TYPED_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_TYPE_ERROR, {"ECMA_OBJECT"}}, + {JSType::JS_UINT16_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_UINT32_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_UINT8_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_UINT8_CLAMPED_ARRAY, {"JS_OBJECT"}}, + {JSType::JS_URI_ERROR, {"ECMA_OBJECT"}}, + {JSType::JS_WEAK_MAP, {"JS_OBJECT"}}, + {JSType::JS_WEAK_REF, {"JS_OBJECT"}}, + {JSType::JS_WEAK_SET, {"JS_OBJECT"}}, + {JSType::LEXICAL_ENV, {"TAGGED_ARRAY"}}, + {JSType::LINE_STRING, {"ECMA_STRING"}}, + {JSType::LINKED_NODE, {"TAGGED_NODE"}}, + {JSType::LOCAL_EXPORTENTRY_RECORD, {"RECORD"}}, + {JSType::MACHINE_CODE_OBJECT, {"TAGGED_OBJECT"}}, + {JSType::MARKER_CELL, {"TAGGED_OBJECT"}}, + {JSType::METHOD, {"TAGGED_OBJECT"}}, + {JSType::MICRO_JOB_QUEUE, {"RECORD"}}, + {JSType::MODULE_RECORD, {"RECORD"}}, + {JSType::MUTANT_TAGGED_ARRAY, {"TAGGED_ARRAY"}}, + {JSType::NATIVE_MODULE_FAILURE_INFO, {"JS_OBJECT"}}, + {JSType::PENDING_JOB, {"RECORD"}}, + {JSType::PROFILE_TYPE_INFO, {"TAGGED_ARRAY"}}, + {JSType::PROFILE_TYPE_INFO_CELL_0, {"TAGGED_OBJECT"}}, + {JSType::PROFILE_TYPE_INFO_CELL_1, {"TAGGED_OBJECT"}}, + {JSType::PROFILE_TYPE_INFO_CELL_N, {"TAGGED_OBJECT"}}, + {JSType::PROGRAM, {"ECMA_OBJECT"}}, + {JSType::PROMISE_CAPABILITY, {"RECORD"}}, + {JSType::PROMISE_ITERATOR_RECORD, {"RECORD"}}, + {JSType::PROMISE_REACTIONS, {"RECORD"}}, + {JSType::PROMISE_RECORD, {"RECORD"}}, + {JSType::PROPERTY_BOX, {"TAGGED_OBJECT"}}, + {JSType::PROTOTYPE_HANDLER, {"TAGGED_OBJECT"}}, + {JSType::PROTOTYPE_INFO, {"TAGGED_OBJECT"}}, + {JSType::PROTO_CHANGE_MARKER, {"TAGGED_OBJECT"}}, + {JSType::RB_TREENODE, {"TAGGED_NODE"}}, + {JSType::RESOLVEDBINDING_RECORD, {"RECORD"}}, + {JSType::RESOLVEDINDEXBINDING_RECORD, {"RECORD"}}, + {JSType::RESOLVEDRECORDBINDING_RECORD, {"RECORD"}}, + {JSType::RESOLVEDRECORDINDEXBINDING_RECORD, {"RECORD"}}, + {JSType::RESOLVING_FUNCTIONS_RECORD, {"RECORD"}}, + {JSType::SENDABLE_ENV, {"TAGGED_ARRAY"}}, + {JSType::SLICED_STRING, {"ECMA_STRING"}}, + {JSType::SOURCE_TEXT_MODULE_RECORD, {"MODULE_RECORD"}}, + {JSType::STAR_EXPORTENTRY_RECORD, {"RECORD"}}, + {JSType::STORE_TS_HANDLER, {"TAGGED_OBJECT"}}, + {JSType::SYMBOL, {"TAGGED_OBJECT"}}, + {JSType::TAGGED_ARRAY, {"TAGGED_OBJECT"}}, + {JSType::TAGGED_DICTIONARY, {"TAGGED_ARRAY"}}, + {JSType::TEMPLATE_MAP, {"TAGGED_OBJECT"}}, + {JSType::TRACK_INFO, {"TAGGED_OBJECT"}}, + {JSType::TRANSITION_HANDLER, {"TAGGED_OBJECT"}}, + {JSType::TRANS_WITH_PROTO_HANDLER, {"TAGGED_OBJECT"}}, + {JSType::TREE_STRING, {"ECMA_STRING"}}, + {JSType::VTABLE, {"TAGGED_OBJECT"}} + }; + // { typeName: [size of all fields' in the same order as declared in .h files]} + fieldSizeTable_ = { + {JSType::HCLASS, {JSHClass::LAYOUT_OFFSET - JSHClass::PROTOTYPE_OFFSET, + JSHClass::TRANSTIONS_OFFSET - JSHClass::LAYOUT_OFFSET, + JSHClass::PARENT_OFFSET - JSHClass::TRANSTIONS_OFFSET, + JSHClass::PROTO_CHANGE_MARKER_OFFSET - JSHClass::PARENT_OFFSET, + JSHClass::PROTO_CHANGE_DETAILS_OFFSET - JSHClass::PROTO_CHANGE_MARKER_OFFSET, + JSHClass::ENUM_CACHE_OFFSET - JSHClass::PROTO_CHANGE_DETAILS_OFFSET, + JSHClass::PROFILE_TYPE - JSHClass::ENUM_CACHE_OFFSET, + JSHClass::BIT_FIELD_OFFSET - JSHClass::PROFILE_TYPE, + JSHClass::BIT_FIELD1_OFFSET - JSHClass::BIT_FIELD_OFFSET, + JSHClass::LAST_OFFSET - JSHClass::BIT_FIELD1_OFFSET}}, + {JSType::ACCESSOR_DATA, {AccessorData::SETTER_OFFSET - AccessorData::GETTER_OFFSET, + AccessorData::SIZE - AccessorData::SETTER_OFFSET}}, + {JSType::AOT_LITERAL_INFO, {}}, + {JSType::ASYNC_GENERATOR_REQUEST, { + AsyncGeneratorRequest::CAPABILITY_OFFSET - AsyncGeneratorRequest::COMPLETION_OFFSET, + AsyncGeneratorRequest::SIZE - AsyncGeneratorRequest::CAPABILITY_OFFSET}}, + {JSType::ASYNC_ITERATOR_RECORD, { + AsyncIteratorRecord::NEXTMETHOD_OFFSET - AsyncIteratorRecord::ITERATOR_OFFSET, + AsyncIteratorRecord::BIT_FIELD_OFFSET - AsyncIteratorRecord::NEXTMETHOD_OFFSET}}, + {JSType::BIGINT, {}}, + {JSType::BYTE_ARRAY, {}}, + {JSType::CELL_RECORD, {CellRecord::HELD_VALUE_OFFSET - CellRecord::WEAKREF_TARGET_OFFSET, + CellRecord::SIZE - CellRecord::HELD_VALUE_OFFSET}}, + {JSType::CLASS_INFO_EXTRACTOR, { + ClassInfoExtractor::NON_STATIC_PROPERTIES_OFFSET - ClassInfoExtractor::PROTOTYPE_HCLASS_OFFSET, + ClassInfoExtractor::NON_STATIC_ELEMENTS_OFFSET - ClassInfoExtractor::NON_STATIC_PROPERTIES_OFFSET, + ClassInfoExtractor::CONSTRUCTOR_HCLASS_OFFSET - ClassInfoExtractor::NON_STATIC_ELEMENTS_OFFSET, + ClassInfoExtractor::STATIC_PROPERTIES_OFFSET - ClassInfoExtractor::CONSTRUCTOR_HCLASS_OFFSET, + ClassInfoExtractor::STATIC_ELEMENTS_OFFSET - ClassInfoExtractor::STATIC_PROPERTIES_OFFSET, + ClassInfoExtractor::CONSTRUCTOR_METHOD_OFFSET - ClassInfoExtractor::STATIC_ELEMENTS_OFFSET, + ClassInfoExtractor::BIT_FIELD_OFFSET - ClassInfoExtractor::CONSTRUCTOR_METHOD_OFFSET}}, + {JSType::CLASS_LITERAL, {ClassLiteral::IS_AOT_USED_OFFSET - ClassLiteral::ARRAY_OFFSET}}, + {JSType::COMPLETION_RECORD, {CompletionRecord::BIT_FIELD_OFFSET - CompletionRecord::VALUE_OFFSET}}, + {JSType::CONSTANT_POOL, {}}, + {JSType::CONSTANT_STRING, {ConstantString::ENTITY_ID_OFFSET - ConstantString::RELOCTAED_DATA_OFFSET}}, + {JSType::COW_MUTANT_TAGGED_ARRAY, {}}, + {JSType::COW_TAGGED_ARRAY, {}}, + {JSType::EXTRA_PROFILE_TYPE_INFO, { + ExtraProfileTypeInfo::HOLDER_OBJECT_OFFSET - ExtraProfileTypeInfo::RECEIVER_OBJECT_OFFSET, + ExtraProfileTypeInfo::LAST_OFFSET - ExtraProfileTypeInfo::HOLDER_OBJECT_OFFSET}}, + {JSType::FUNCTION_TEMPLATE, { + FunctionTemplate::MODULE_OFFSET - FunctionTemplate::METHOD_OFFSET, + FunctionTemplate::RAW_PROFILE_TYPE_INFO_OFFSET - FunctionTemplate::MODULE_OFFSET, + FunctionTemplate::LENGTH_OFFSET - FunctionTemplate::RAW_PROFILE_TYPE_INFO_OFFSET}}, + {JSType::GLOBAL_ENV, {}}, + {JSType::IMPORTENTRY_RECORD, { + ImportEntry::MODULE_REQUEST_OFFSET - ImportEntry::IMPORT_ENTRY_OFFSET, + ImportEntry::IMPORT_NAME_OFFSET - ImportEntry::MODULE_REQUEST_OFFSET, + ImportEntry::SIZE - ImportEntry::IMPORT_NAME_OFFSET}}, + {JSType::INDIRECT_EXPORTENTRY_RECORD, { + IndirectExportEntry::MODULE_REQUEST_OFFSET - IndirectExportEntry::INDIRECT_EXPORT_ENTRY_OFFSET, + IndirectExportEntry::IMPORT_NAME_OFFSET - IndirectExportEntry::MODULE_REQUEST_OFFSET, + IndirectExportEntry::SIZE - IndirectExportEntry::IMPORT_NAME_OFFSET}}, + {JSType::INTERNAL_ACCESSOR, { + InternalAccessor::SETTER_OFFSET - InternalAccessor::GETTER_OFFSET, + InternalAccessor::SIZE - InternalAccessor::SETTER_OFFSET}}, + {JSType::JS_AGGREGATE_ERROR, { + JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, + JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_API_ARRAYLIST_ITERATOR, { + JSAPIArrayListIterator::NEXT_INDEX_OFFSET - JSAPIArrayListIterator::ITERATED_ARRAYLIST_OFFSET}}, + {JSType::JS_API_ARRAY_LIST, {JSAPIArrayList::SIZE - JSAPIArrayList::LENGTH_OFFSET}}, + {JSType::JS_API_BITVECTOR, {JSAPIBitVector::LENGTH_OFFSET - JSAPIBitVector::NATIVE_POINTER_OFFSET}}, + {JSType::JS_API_BITVECTOR_ITERATOR, { + JSAPIBitVectorIterator::NEXT_INDEX_OFFSET - JSAPIBitVectorIterator::ITERATED_BITVECTOR_OFFSET}}, + {JSType::JS_API_DEQUE, {}}, + {JSType::JS_API_DEQUE_ITERATOR, { + JSAPIDequeIterator::NEXT_INDEX_OFFSET - JSAPIDequeIterator::ITERATED_DEQUE_OFFSET}}, + {JSType::JS_API_HASHMAP_ITERATOR, { + JSAPIHashMapIterator::TAGGED_QUEUE_OFFSET - JSAPIHashMapIterator::ITERATED_HASHMAP_OFFSET, + JSAPIHashMapIterator::CURRENT_NODE_RESULT - JSAPIHashMapIterator::TAGGED_QUEUE_OFFSET, + JSAPIHashMapIterator::NEXT_INDEX_OFFSET - JSAPIHashMapIterator::CURRENT_NODE_RESULT + }}, + {JSType::JS_API_HASHSET_ITERATOR, { + JSAPIHashSetIterator::TAGGED_QUEUE_OFFSET - JSAPIHashSetIterator::ITERATED_HASHSET_OFFSET, + JSAPIHashSetIterator::CURRENT_NODE_RESULT - JSAPIHashSetIterator::TAGGED_QUEUE_OFFSET, + JSAPIHashSetIterator::NEXT_INDEX_OFFSET - JSAPIHashSetIterator::CURRENT_NODE_RESULT}}, + {JSType::JS_API_HASH_MAP, {JSAPIHashMap::HASHMAP_SIZE_OFFSET- JSAPIHashMap::HASHMAP_TABLE_INDEX}}, + {JSType::JS_API_HASH_SET, {JSAPIHashSet::HASHSET_SIZE_OFFSET- JSAPIHashSet::HASHSET_TABLE_INDEX}}, + {JSType::JS_API_LIGHT_WEIGHT_MAP, { + JSAPILightWeightMap::LWP_KEYS_OFFSET - JSAPILightWeightMap::LWP_HASHES_OFFSET, + JSAPILightWeightMap::LWP_VALUES_OFFSET - JSAPILightWeightMap::LWP_KEYS_OFFSET, + JSAPILightWeightMap::LWP_LENGTH_OFFSET - JSAPILightWeightMap::LWP_VALUES_OFFSET}}, + {JSType::JS_API_LIGHT_WEIGHT_MAP_ITERATOR, { + JSAPILightWeightMapIterator::NEXT_INDEX_OFFSET - JSAPILightWeightMapIterator::ITERATED_LIGHT_WEIGHT_MAP_OFFSET}}, + {JSType::JS_API_LIGHT_WEIGHT_SET, { + JSAPILightWeightSet::VALUES_OFFSET - JSAPILightWeightSet::HASHES_OFFSET, + JSAPILightWeightSet::LENGTH_OFFSET - JSAPILightWeightSet::VALUES_OFFSET}}, + {JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR, { + JSAPILightWeightSetIterator::NEXT_INDEX_OFFSET - JSAPILightWeightSetIterator::ITERATED_LIGHT_WEIGHT_SET_OFFSET}}, + {JSType::JS_API_LINKED_LIST, {JSAPILinkedList::SIZE - JSAPILinkedList::DOUBLE_LIST_OFFSET}}, + {JSType::JS_API_LINKED_LIST_ITERATOR, { + JSAPILinkedListIterator::DATA_INDEX_OFFSET - JSAPILinkedListIterator::ITERATED_LINKED_LIST_OFFSET}}, + {JSType::JS_API_LIST, {JSAPIList::BIT_FIELD_OFFSET - JSAPIList::SINGLY_LIST_OFFSET}}, + {JSType::JS_API_LIST_ITERATOR, { + JSAPIListIterator::DATA_INDEX_OFFSET - JSAPIListIterator::ITERATED_LIST_OFFSET}}, + {JSType::JS_API_PLAIN_ARRAY, {JSAPIPlainArray::VALUES_OFFSET - JSAPIPlainArray::KEYS_OFFSET, + JSAPIPlainArray::LENGTH_OFFSET - JSAPIPlainArray::VALUES_OFFSET}}, + {JSType::JS_API_PLAIN_ARRAY_ITERATOR, { + JSAPIPlainArrayIterator::NEXT_INDEX_OFFSET - JSAPIPlainArrayIterator::ITERATED_PLAIN_ARRAY_OFFSET}}, + {JSType::JS_API_QUEUE, {JSAPIQueue::FRONT_OFFSET - JSAPIQueue::LENGTH_OFFSET}}, + {JSType::JS_API_QUEUE_ITERATOR, { + JSAPIQueueIterator::NEXT_INDEX_OFFSET - JSAPIQueueIterator::ITERATED_QUEUE_OFFSET}}, + {JSType::JS_API_STACK, {}}, + {JSType::JS_API_STACK_ITERATOR, { + JSAPIStackIterator::NEXT_INDEX_OFFSET - JSAPIStackIterator::ITERATED_STACK_OFFSET}}, + {JSType::JS_API_TREEMAP_ITERATOR, { + JSAPITreeMapIterator::ITERATED_ENTRIES_OFFSET - JSAPITreeMapIterator::ITERATED_MAP_OFFSET, + JSAPITreeMapIterator::NEXT_INDEX_OFFSET - JSAPITreeMapIterator::ITERATED_ENTRIES_OFFSET}}, + {JSType::JS_API_TREESET_ITERATOR, { + JSAPITreeSetIterator::ITERATED_ENTRIES_OFFSET - JSAPITreeSetIterator::ITERATED_SET_OFFSET, + JSAPITreeSetIterator::NEXT_INDEX_OFFSET - JSAPITreeSetIterator::ITERATED_ENTRIES_OFFSET}}, + {JSType::JS_API_TREE_MAP, {JSAPITreeMap::SIZE - JSAPITreeMap::TREE_MAP_OFFSET}}, + {JSType::JS_API_TREE_SET, {JSAPITreeSet::SIZE - JSAPITreeSet::TREE_SET_OFFSET}}, + {JSType::JS_API_VECTOR, {}}, + {JSType::JS_API_VECTOR_ITERATOR, { + JSAPIVectorIterator::NEXT_INDEX_OFFSET - JSAPIVectorIterator::ITERATED_VECTOR_OFFSET}}, + {JSType::JS_ARGUMENTS, {}}, + {JSType::JS_ARRAY, {JSArray::TRACE_INDEX_OFFSET - JSArray::LENGTH_OFFSET, + JSArray::SIZE - JSArray::TRACK_INFO_OFFSET}}, + {JSType::JS_ARRAY_BUFFER, {JSArrayBuffer::BYTE_LENGTH_OFFSET - JSArrayBuffer::DATA_OFFSET}}, + {JSType::JS_ARRAY_ITERATOR, { + JSArrayIterator::NEXT_INDEX_OFFSET - JSArrayIterator::ITERATED_ARRAY_OFFSET}}, + {JSType::JS_ASYNCITERATOR, {JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, + JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION, { + JSAsyncAwaitStatusFunction::SIZE - JSAsyncAwaitStatusFunction::ASYNC_CONTEXT_OFFSET}}, + {JSType::JS_ASYNC_FROM_SYNC_ITERATOR, { + JSAsyncFromSyncIterator::SIZE - JSAsyncFromSyncIterator::SYNC_ITERATOR_RECORD}}, + {JSType::JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION, { + JSAsyncFromSyncIterUnwarpFunction::SIZE - JSAsyncFromSyncIterUnwarpFunction::DONE_OFFSET}}, + {JSType::JS_ASYNC_FUNCTION, {}}, + {JSType::JS_ASYNC_FUNC_OBJECT, { + JSAsyncFuncObject::SIZE - JSAsyncFuncObject::GENERATOR_PROMISE_OFFSET}}, + {JSType::JS_ASYNC_GENERATOR_FUNCTION, {}}, + {JSType::JS_ASYNC_GENERATOR_OBJECT, { + JSAsyncGeneratorObject::ASYNC_GENERATOR_QUEUE_OFFSET - JSAsyncGeneratorObject::GENERATOR_CONTEXT_OFFSET, + JSAsyncGeneratorObject::GENERATOR_OFFSET - JSAsyncGeneratorObject::ASYNC_GENERATOR_QUEUE_OFFSET, + JSAsyncGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET - JSAsyncGeneratorObject::GENERATOR_OFFSET, + JSAsyncGeneratorObject::BIT_FIELD_OFFSET - JSAsyncGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET}}, + {JSType::JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN, { + JSAsyncGeneratorResNextRetProRstFtn::SIZE - JSAsyncGeneratorResNextRetProRstFtn::ASYNC_GENERATOR_OBJECT_OFFSET}}, + {JSType::JS_ASYNC_MODULE_FULFILLED_FUNCTION, {}}, + {JSType::JS_ASYNC_MODULE_REJECTED_FUNCTION, {}}, + {JSType::JS_BIGINT64_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_BIGUINT64_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_BOUND_FUNCTION, { + JSBoundFunction::BOUND_THIS_OFFSET - JSBoundFunction::BOUND_TARGET_OFFSET, + JSBoundFunction::BOUND_ARGUMENTS_OFFSET - JSBoundFunction::BOUND_THIS_OFFSET, + JSBoundFunction::SIZE - JSBoundFunction::BOUND_ARGUMENTS_OFFSET}}, + {JSType::JS_CJS_EXPORTS, {CjsExports::SIZE - CjsExports::JS_CJS_EXPORTS_OFFSET}}, + {JSType::JS_CJS_MODULE, {CjsModule::ID_OFFSET - CjsModule::JS_CJS_MODULE_OFFSET, + CjsModule::PATH_OFFSET - CjsModule::ID_OFFSET, + CjsModule::EXPORTS_OFFSET - CjsModule::PATH_OFFSET, + CjsModule::BIT_FIELD_OFFSET - CjsModule::EXPORTS_OFFSET}}, + {JSType::JS_CJS_REQUIRE, {CjsRequire::CACHE_OFFSET - CjsRequire::JS_CJS_REQUIRE_OFFSET, + CjsRequire::SIZE - CjsRequire::CACHE_OFFSET}}, + {JSType::JS_COLLATOR, {JSCollator::LOCALE_OFFSET - JSCollator::ICU_FIELD_OFFSET, + JSCollator::COLLATION_OFFSET - JSCollator::LOCALE_OFFSET, + JSCollator::BOUND_COMPARE_OFFSET - JSCollator::COLLATION_OFFSET, + JSCollator::BIT_FIELD_OFFSET - JSCollator::BOUND_COMPARE_OFFSET}}, + {JSType::JS_DATA_VIEW, {JSDataView::VIEW_ARRAY_BUFFER_OFFSET - JSDataView::DATA_VIEW_OFFSET, + JSDataView::BYTE_LENGTH_OFFSET - JSDataView::VIEW_ARRAY_BUFFER_OFFSET}}, + {JSType::JS_DATE, {JSDate::LOCAL_TIME_OFFSET - JSDate::TIME_VALUE_OFFSET, + JSDate::SIZE - JSDate::LOCAL_TIME_OFFSET}}, + {JSType::JS_DATE_TIME_FORMAT, { + JSDateTimeFormat::CALENDAR_OFFSET - JSDateTimeFormat::LOCALE_OFFSET, + JSDateTimeFormat::NUMBER_STRING_SYSTEM_OFFSET - JSDateTimeFormat::CALENDAR_OFFSET, + JSDateTimeFormat::TIME_ZONE_OFFSET - JSDateTimeFormat::NUMBER_STRING_SYSTEM_OFFSET, + JSDateTimeFormat::LOCALE_ICU_OFFSET - JSDateTimeFormat::TIME_ZONE_OFFSET, + JSDateTimeFormat::SIMPLE_DATE_TIME_FORMAT_ICU_OFFSET - JSDateTimeFormat::LOCALE_ICU_OFFSET, + JSDateTimeFormat::ISO8601_OFFSET - JSDateTimeFormat::SIMPLE_DATE_TIME_FORMAT_ICU_OFFSET, + JSDateTimeFormat::BOUND_FORMAT_OFFSET - JSDateTimeFormat::ISO8601_OFFSET, + JSDateTimeFormat::BIT_FIELD_OFFSET - JSDateTimeFormat::BOUND_FORMAT_OFFSET}}, + {JSType::JS_DISPLAYNAMES, {JSDisplayNames::ICU_LOCALE_DISPPLAY_NAMES - JSDisplayNames::LOCALE_OFFSET, + JSDisplayNames::BIT_FIELD_OFFSET - JSDisplayNames::ICU_LOCALE_DISPPLAY_NAMES}}, + {JSType::JS_ERROR, {JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, + JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_EVAL_ERROR, {JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, + JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_FINALIZATION_REGISTRY, { + JSFinalizationRegistry::NO_UNREGISTER_OFFSET - JSFinalizationRegistry::CLEANUP_CALLBACK_OFFSET, + JSFinalizationRegistry::MAYBE_UNREGISTER_OFFSET - JSFinalizationRegistry::NO_UNREGISTER_OFFSET, + JSFinalizationRegistry::NEXT_OFFSET - JSFinalizationRegistry::MAYBE_UNREGISTER_OFFSET, + JSFinalizationRegistry::PREV_OFFSET - JSFinalizationRegistry::NEXT_OFFSET, + JSFinalizationRegistry::SIZE - JSFinalizationRegistry::PREV_OFFSET}}, + {JSType::JS_FLOAT32_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_FLOAT64_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_FORIN_ITERATOR, { + JSForInIterator::CACHED_HCLASS_OFFSET - JSForInIterator::OBJECT_OFFSET, + JSForInIterator::KEYS_OFFSET - JSForInIterator::CACHED_HCLASS_OFFSET, + JSForInIterator::INDEX_OFFSET - JSForInIterator::KEYS_OFFSET}}, + {JSType::JS_FUNCTION, { + JSFunction::LEXICAL_ENV_OFFSET - JSFunction::PROTO_OR_DYNCLASS_OFFSET, + JSFunction::MACHINECODE_OFFSET - JSFunction::LEXICAL_ENV_OFFSET, + JSFunction::BASELINECODE_OFFSET - JSFunction::MACHINECODE_OFFSET, + JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET - JSFunction::BASELINECODE_OFFSET, + JSFunction::HOME_OBJECT_OFFSET - JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET, + JSFunction::ECMA_MODULE_OFFSET - JSFunction::HOME_OBJECT_OFFSET, + JSFunction::PROTO_TRANS_ROOT_HCLASS_OFFSET - JSFunction::ECMA_MODULE_OFFSET, + JSFunction::WORK_NODE_POINTER_OFFSET - JSFunction::PROTO_TRANS_ROOT_HCLASS_OFFSET}}, + {JSType::JS_FUNCTION_BASE, {JSFunctionBase::CODE_ENTRY_OFFSET - JSFunctionBase::METHOD_OFFSET}}, + {JSType::JS_GENERATOR_CONTEXT, { + GeneratorContext::GENERATOR_METHOD_OFFSET - GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET, + GeneratorContext::GENERATOR_THIS_OFFSET - GeneratorContext::GENERATOR_METHOD_OFFSET, + GeneratorContext::GENERATOR_ACC_OFFSET - GeneratorContext::GENERATOR_THIS_OFFSET, + GeneratorContext::GENERATOR_GENERATOR_OBJECT_OFFSET - GeneratorContext::GENERATOR_ACC_OFFSET, + GeneratorContext::GENERATOR_LEXICALENV_OFFSET - GeneratorContext::GENERATOR_GENERATOR_OBJECT_OFFSET, + GeneratorContext::GENERATOR_NREGS_OFFSET - GeneratorContext::GENERATOR_LEXICALENV_OFFSET}}, + {JSType::JS_GENERATOR_FUNCTION, {}}, + {JSType::JS_GENERATOR_OBJECT, { + JSGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET - JSGeneratorObject::GENERATOR_CONTEXT_OFFSET, + JSGeneratorObject::TASK_INFO_OFFSET - JSGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET}}, + {JSType::JS_GLOBAL_OBJECT, {}}, + {JSType::JS_INT16_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_INT32_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_INT8_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_INTL, {JSIntl::SIZE - JSIntl::FALLBACK_SYMBOL}}, + {JSType::JS_INTL_BOUND_FUNCTION, { + JSIntlBoundFunction::DATETIME_FORMAT_OFFSET - JSIntlBoundFunction::NUMBER_FORMAT_OFFSET, + JSIntlBoundFunction::COLLATOR_OFFSET - JSIntlBoundFunction::DATETIME_FORMAT_OFFSET, + JSIntlBoundFunction::SIZE - JSIntlBoundFunction::COLLATOR_OFFSET}}, + {JSType::JS_ITERATOR, {JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, + JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_LIST_FORMAT, {JSListFormat::ICU_LIST_FORMAT - JSListFormat::LOCALE_OFFSET, + JSListFormat::BIT_FIELD_OFFSET - JSListFormat::ICU_LIST_FORMAT}}, + {JSType::JS_LOCALE, {JSLocale::SIZE - JSLocale::ICU_FIELD_OFFSET}}, + {JSType::JS_MAP, {JSMap::SIZE - JSMap::LINKED_MAP_OFFSET}}, + {JSType::JS_MAP_ITERATOR, {JSMapIterator::NEXT_INDEX_OFFSET - JSMapIterator::ITERATED_MAP_OFFSET}}, + {JSType::JS_MODULE_NAMESPACE, { + ModuleNamespace::EXPORTS_OFFSET - ModuleNamespace::MODULE_OFFSET, + ModuleNamespace::DEREGISTER_PROCESSION_OFFSET - ModuleNamespace::EXPORTS_OFFSET, + ModuleNamespace::SIZE - ModuleNamespace::DEREGISTER_PROCESSION_OFFSET}}, + {JSType::JS_NATIVE_POINTER, { + JSNativePointer::FLAG_OFFSET- JSNativePointer::DATA_SIZE_OFFSET}}, + {JSType::JS_NUMBER_FORMAT, { + JSNumberFormat::NUMBER_STRING_SYSTEM_OFFSET - JSNumberFormat::LOCALE_OFFSET, + JSNumberFormat::CURRENCY_OFFSET - JSNumberFormat::NUMBER_STRING_SYSTEM_OFFSET, + JSNumberFormat::UNIT_OFFSET - JSNumberFormat::CURRENCY_OFFSET, + JSNumberFormat::MINIMUM_INTEGER_DIGITS_OFFSET - JSNumberFormat::UNIT_OFFSET, + JSNumberFormat::MINIMUM_FRACTION_DIGITS_OFFSET - JSNumberFormat::MINIMUM_INTEGER_DIGITS_OFFSET, + JSNumberFormat::MAXIMUM_FRACTION_DIGITS_OFFSET - JSNumberFormat::MINIMUM_FRACTION_DIGITS_OFFSET, + JSNumberFormat::MINIMUM_SIGNIFICANT_DIGITS_OFFSET - JSNumberFormat::MAXIMUM_FRACTION_DIGITS_OFFSET, + JSNumberFormat::MAXIMUM_SIGNIFICANT_DIGITS_OFFSET - JSNumberFormat::MINIMUM_SIGNIFICANT_DIGITS_OFFSET, + JSNumberFormat::USER_GROUPING_OFFSET - JSNumberFormat::MAXIMUM_SIGNIFICANT_DIGITS_OFFSET, + JSNumberFormat::BOUND_FORMAT_OFFSET - JSNumberFormat::USER_GROUPING_OFFSET, + JSNumberFormat::ICU_FIELD_OFFSET - JSNumberFormat::BOUND_FORMAT_OFFSET, + JSNumberFormat::BIT_FIELD_OFFSET - JSNumberFormat::ICU_FIELD_OFFSET}}, + {JSType::JS_OBJECT, { + JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, + JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_OOM_ERROR, { + JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, + JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_PLURAL_RULES, { + JSPluralRules::MINIMUM_INTEGER_DIGITS_OFFSET - JSPluralRules::LOCALE_OFFSET, + JSPluralRules::MINIMUM_FRACTION_DIGITS_OFFSET - JSPluralRules::MINIMUM_INTEGER_DIGITS_OFFSET, + JSPluralRules::MAXIMUM_FRACTION_DIGITS_OFFSET - JSPluralRules::MINIMUM_FRACTION_DIGITS_OFFSET, + JSPluralRules::MININUM_SIGNIFICANT_DIGITS_OFFSET - JSPluralRules::MAXIMUM_FRACTION_DIGITS_OFFSET, + JSPluralRules::MAXINUM_SIGNIFICANT_DIGITS_OFFSET - JSPluralRules::MININUM_SIGNIFICANT_DIGITS_OFFSET, + JSPluralRules::ICU_PLURAL_RULES_OFFSET - JSPluralRules::MAXINUM_SIGNIFICANT_DIGITS_OFFSET, + JSPluralRules::ICU_NUMBER_FORMAT_OFFSET - JSPluralRules::ICU_PLURAL_RULES_OFFSET, + JSPluralRules::BIT_FIELD_OFFSET - JSPluralRules::ICU_NUMBER_FORMAT_OFFSET}}, + {JSType::JS_PRIMITIVE_REF, {JSPrimitiveRef::SIZE - JSPrimitiveRef::VALUE_OFFSET}}, + {JSType::JS_PROMISE, { + JSPromise::PROMISE_FULFILL_REACTIONS_OFFSET - JSPromise::PROMISE_RESULT_OFFSET, + JSPromise::PROMISE_REJECT_REACTIONS_OFFSET - JSPromise::PROMISE_FULFILL_REACTIONS_OFFSET, + JSPromise::BIT_FIELD_OFFSET - JSPromise::PROMISE_REJECT_REACTIONS_OFFSET}}, + {JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION, { + JSPromiseAllResolveElementFunction::VALUES_OFFSET - JSPromiseAllResolveElementFunction::INDEX_OFFSET, + JSPromiseAllResolveElementFunction::CAPABILITIES_OFFSET - JSPromiseAllResolveElementFunction::VALUES_OFFSET, + JSPromiseAllResolveElementFunction::REMAINING_ELEMENTS_OFFSET - JSPromiseAllResolveElementFunction::CAPABILITIES_OFFSET, + JSPromiseAllResolveElementFunction::ALREADY_CALLED_OFFSET - JSPromiseAllResolveElementFunction::REMAINING_ELEMENTS_OFFSET, + JSPromiseAllResolveElementFunction::SIZE - JSPromiseAllResolveElementFunction::ALREADY_CALLED_OFFSET}}, + {JSType::JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION, { + JSPromiseAllSettledElementFunction::VALUES_OFFSET - JSPromiseAllSettledElementFunction::ALREADY_CALLED_OFFSET, + JSPromiseAllSettledElementFunction::CAPABILITY_OFFSET - JSPromiseAllSettledElementFunction::VALUES_OFFSET, + JSPromiseAllSettledElementFunction::REMAINING_ELEMENTS_OFFSET - JSPromiseAllSettledElementFunction::CAPABILITY_OFFSET, + JSPromiseAllSettledElementFunction::INDEX_OFFSET - JSPromiseAllSettledElementFunction::REMAINING_ELEMENTS_OFFSET}}, + {JSType::JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION, { + JSPromiseAnyRejectElementFunction::CAPABILITY_OFFSET - JSPromiseAnyRejectElementFunction::ERRORS_OFFSET, + JSPromiseAnyRejectElementFunction::REMAINING_ELEMENTS_OFFSET - JSPromiseAnyRejectElementFunction::CAPABILITY_OFFSET, + JSPromiseAnyRejectElementFunction::ALREADY_CALLED_OFFSET - JSPromiseAnyRejectElementFunction::REMAINING_ELEMENTS_OFFSET, + JSPromiseAnyRejectElementFunction::INDEX_OFFSET - JSPromiseAnyRejectElementFunction::ALREADY_CALLED_OFFSET}}, + {JSType::JS_PROMISE_EXECUTOR_FUNCTION, { + JSPromiseExecutorFunction::SIZE - JSPromiseExecutorFunction::CAPABILITY_OFFSET}}, + {JSType::JS_PROMISE_FINALLY_FUNCTION, { + JSPromiseFinallyFunction::ONFINALLY_OFFSET - JSPromiseFinallyFunction::CONSTRUCTOR_OFFSET, + JSPromiseFinallyFunction::SIZE - JSPromiseFinallyFunction::ONFINALLY_OFFSET}}, + {JSType::JS_PROMISE_REACTIONS_FUNCTION, { + JSPromiseReactionsFunction::ALREADY_RESOLVED_OFFSET - JSPromiseReactionsFunction::PROMISE_OFFSET, + JSPromiseReactionsFunction::SIZE - JSPromiseReactionsFunction::ALREADY_RESOLVED_OFFSET}}, + {JSType::JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION, { + JSPromiseValueThunkOrThrowerFunction::SIZE - JSPromiseValueThunkOrThrowerFunction::RESULT_OFFSET}}, + {JSType::JS_PROXY, {JSProxy::HANDLER_OFFSET - JSProxy::TARGET_OFFSET, + JSProxy::METHOD_OFFSET - JSProxy::HANDLER_OFFSET, + JSProxy::PRIVATE_FIELD_OFFSET - JSProxy::METHOD_OFFSET, + JSProxy::BIT_FIELD_OFFSET - JSProxy::PRIVATE_FIELD_OFFSET}}, + {JSType::JS_PROXY_REVOC_FUNCTION, { + JSProxyRevocFunction::SIZE - JSProxyRevocFunction::REVOCABLE_PROXY_OFFSET}}, + {JSType::JS_RANGE_ERROR, {JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, + JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_REALM, {JSRealm::GLOBAL_ENV_OFFSET - JSRealm::VALUE_OFFSET, + JSRealm::SIZE - JSRealm::GLOBAL_ENV_OFFSET}}, + {JSType::JS_REFERENCE_ERROR, {JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, + JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_REG_EXP, {JSRegExp::ORIGINAL_SOURCE_OFFSET - JSRegExp::REGEXP_BYTE_CODE_OFFSET, + JSRegExp::ORIGINAL_FLAGS_OFFSET - JSRegExp::ORIGINAL_SOURCE_OFFSET, + JSRegExp::GROUP_NAME_OFFSET - JSRegExp::ORIGINAL_FLAGS_OFFSET, + JSRegExp::LENGTH_OFFSET - JSRegExp::GROUP_NAME_OFFSET}}, + {JSType::JS_REG_EXP_ITERATOR, { + JSRegExpIterator::ITERATED_STRING_OFFSET - JSRegExpIterator::ITERATING_REGEXP_OFFSET, + JSRegExpIterator::BIT_FIELD_OFFSET - JSRegExpIterator::ITERATED_STRING_OFFSET}}, + {JSType::JS_RELATIVE_TIME_FORMAT, { + JSRelativeTimeFormat::NUMBERING_SYSTEM_OFFSET - JSRelativeTimeFormat::LOCALE_OFFSET, + JSRelativeTimeFormat::ICU_FIELD_OFFSET - JSRelativeTimeFormat::NUMBERING_SYSTEM_OFFSET, + JSRelativeTimeFormat::BIT_FIELD_OFFSET - JSRelativeTimeFormat::ICU_FIELD_OFFSET}}, + {JSType::JS_SEGMENTER, {JSSegmenter::ICU_FIELD_OFFSET - JSSegmenter::LOCALE_OFFSET, + JSSegmenter::BIT_FIELD_OFFSET - JSSegmenter::ICU_FIELD_OFFSET}}, + {JSType::JS_SEGMENTS, {JSSegments::SEGMENTS_STRING_OFFSET - JSSegments::ICU_FIELD_OFFSET, + JSSegments::UNICODE_STRING_OFFSET - JSSegments::SEGMENTS_STRING_OFFSET, + JSSegments::BIT_FIELD_OFFSET - JSSegments::UNICODE_STRING_OFFSET}}, + {JSType::JS_SEGMENT_ITERATOR, { + JSSegmentIterator::SEGMENTS_STRING_OFFSET - JSSegmentIterator::ICU_FIELD_OFFSET, + JSSegmentIterator::UNICODE_STRING_OFFSET - JSSegmentIterator::SEGMENTS_STRING_OFFSET, + JSSegmentIterator::BIT_FIELD_OFFSET - JSSegmentIterator::UNICODE_STRING_OFFSET}}, + {JSType::JS_SENDABLE_ARRAY_BUFFER, { + JSSendableArrayBuffer::BYTE_LENGTH_OFFSET- JSSendableArrayBuffer::DATA_OFFSET}}, + {JSType::JS_SET, {JSSet::SIZE - JSSet::LINKED_SET_OFFSET}}, + {JSType::JS_SET_ITERATOR, { + JSSetIterator::NEXT_INDEX_OFFSET - JSSetIterator::ITERATED_SET_OFFSET}}, + {JSType::JS_SHARED_ARRAY, { + JSSharedArray::MOD_RECORD_OFFSET - JSSharedArray::TRACK_INFO_OFFSET}}, + {JSType::JS_SHARED_ARRAY_BUFFER, { + JSArrayBuffer::BYTE_LENGTH_OFFSET - JSArrayBuffer::DATA_OFFSET}}, + {JSType::JS_SHARED_ARRAY_ITERATOR, { + JSSharedArrayIterator::NEXT_INDEX_OFFSET - JSSharedArrayIterator::ITERATED_ARRAY_OFFSET}}, + {JSType::JS_SHARED_ASYNC_FUNCTION, {}}, + {JSType::JS_SHARED_BIGINT64_ARRAY, {}}, + {JSType::JS_SHARED_BIGUINT64_ARRAY, {}}, + {JSType::JS_SHARED_FLOAT32_ARRAY, {}}, + {JSType::JS_SHARED_FLOAT64_ARRAY, {}}, + {JSType::JS_SHARED_FUNCTION, {}}, + {JSType::JS_SHARED_INT16_ARRAY, {}}, + {JSType::JS_SHARED_INT32_ARRAY, {}}, + {JSType::JS_SHARED_INT8_ARRAY, {}}, + {JSType::JS_SHARED_MAP, { + JSSharedMap::MOD_RECORD_OFFSET - JSSharedMap::LINKED_MAP_OFFSET}}, + {JSType::JS_SHARED_MAP_ITERATOR, { + JSSharedMapIterator::NEXT_INDEX_OFFSET - JSSharedMapIterator::ITERATED_MAP_OFFSET}}, + {JSType::JS_SHARED_OBJECT, {}}, + {JSType::JS_SHARED_SET, { + JSSharedSet::MOD_RECORD_OFFSET - JSSharedSet::LINKED_SET_OFFSET}}, + {JSType::JS_SHARED_SET_ITERATOR, { + JSSharedSetIterator::NEXT_INDEX_OFFSET - JSSharedSetIterator::ITERATED_SET_OFFSET}}, + {JSType::JS_SHARED_TYPED_ARRAY, {}}, + {JSType::JS_SHARED_UINT16_ARRAY, {}}, + {JSType::JS_SHARED_UINT32_ARRAY, {}}, + {JSType::JS_SHARED_UINT8_ARRAY, {}}, + {JSType::JS_SHARED_UINT8_CLAMPED_ARRAY, {}}, + {JSType::JS_STRING_ITERATOR, { + JSStringIterator::STRING_ITERATOR_NEXT_INDEX_OFFSET - JSStringIterator::ITERATED_STRING_OFFSET}}, + {JSType::JS_SYNTAX_ERROR, { + JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_TERMINATION_ERROR, { + JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_TYPED_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_TYPE_ERROR, { + JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_UINT16_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_UINT32_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_UINT8_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_UINT8_CLAMPED_ARRAY, { + JSTypedArray::TYPED_ARRAY_NAME_OFFSET - JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET, + JSTypedArray::BYTE_LENGTH_OFFSET - JSTypedArray::TYPED_ARRAY_NAME_OFFSET}}, + {JSType::JS_URI_ERROR, { + JSObject::ELEMENTS_OFFSET - JSObject::PROPERTIES_OFFSET, + JSObject::SIZE - JSObject::ELEMENTS_OFFSET}}, + {JSType::JS_WEAK_MAP, {JSWeakMap::SIZE - JSWeakMap::LINKED_MAP_OFFSET}}, + {JSType::JS_WEAK_REF, {JSWeakRef::SIZE - JSWeakRef::WEAK_OBJECT_OFFSET}}, + {JSType::JS_WEAK_SET, {JSWeakSet::SIZE - JSWeakSet::LINKED_SET_OFFSET}}, + {JSType::LEXICAL_ENV, {}}, + {JSType::LINE_STRING, {}}, + {JSType::LINKED_NODE, {LinkedNode::SIZE - LinkedNode::NEXT_OFFSET}}, + {JSType::LOCAL_EXPORTENTRY_RECORD, { + LocalExportEntry::LOCAL_NAME_OFFSET - LocalExportEntry::LOCAL_EXPORT_ENTRY_OFFSET, + LocalExportEntry::LOCAL_INDEX_OFFSET - LocalExportEntry::LOCAL_NAME_OFFSET}}, + {JSType::MACHINE_CODE_OBJECT, {}}, + {JSType::MARKER_CELL, {}}, + {JSType::METHOD, {Method::CALL_FIELD_OFFSET - Method::CONSTANT_POOL_OFFSET}}, + {JSType::MICRO_JOB_QUEUE, { + job::MicroJobQueue::SCRIPT_JOB_QUEUE_OFFSET - job::MicroJobQueue::PROMISE_JOB_QUEUE_OFFSET, + job::MicroJobQueue::SIZE - job::MicroJobQueue::SCRIPT_JOB_QUEUE_OFFSET}}, + {JSType::MODULE_RECORD, {}}, + {JSType::MUTANT_TAGGED_ARRAY, {}}, + {JSType::NATIVE_MODULE_FAILURE_INFO, { + NativeModuleFailureInfo::SIZE - NativeModuleFailureInfo::ARK_NATIVE_MODULE_FAILURE_INFO_OFFSET}}, + {JSType::PENDING_JOB, {job::PendingJob::ARGUMENT_OFFSET - job::PendingJob::JOB_OFFSET, + job::PendingJob::SIZE - job::PendingJob::ARGUMENT_OFFSET}}, + {JSType::PROFILE_TYPE_INFO, {}}, + {JSType::PROFILE_TYPE_INFO_CELL_0, { + ProfileTypeInfoCell::MACHINE_CODE_OFFSET - ProfileTypeInfoCell::VALUE_OFFSET, + ProfileTypeInfoCell::HANDLE_OFFSET - ProfileTypeInfoCell::MACHINE_CODE_OFFSET, + ProfileTypeInfoCell::LAST_OFFSET - ProfileTypeInfoCell::HANDLE_OFFSET}}, + {JSType::PROFILE_TYPE_INFO_CELL_1, { + ProfileTypeInfoCell::MACHINE_CODE_OFFSET - ProfileTypeInfoCell::VALUE_OFFSET, + ProfileTypeInfoCell::HANDLE_OFFSET - ProfileTypeInfoCell::MACHINE_CODE_OFFSET, + ProfileTypeInfoCell::LAST_OFFSET - ProfileTypeInfoCell::HANDLE_OFFSET}}, + {JSType::PROFILE_TYPE_INFO_CELL_N, { + ProfileTypeInfoCell::MACHINE_CODE_OFFSET - ProfileTypeInfoCell::VALUE_OFFSET, + ProfileTypeInfoCell::HANDLE_OFFSET - ProfileTypeInfoCell::MACHINE_CODE_OFFSET, + ProfileTypeInfoCell::LAST_OFFSET - ProfileTypeInfoCell::HANDLE_OFFSET}}, + {JSType::PROGRAM, {Program::SIZE - Program::MAIN_FUNCTION_OFFSET}}, + {JSType::PROMISE_CAPABILITY, { + PromiseCapability::RESOLVE_OFFSET - PromiseCapability::PROMISE_OFFSET, + PromiseCapability::REJECT_OFFSET - PromiseCapability::RESOLVE_OFFSET, + PromiseCapability::SIZE - PromiseCapability::REJECT_OFFSET}}, + {JSType::PROMISE_ITERATOR_RECORD, { + PromiseIteratorRecord::BIT_FIELD_OFFSET - PromiseIteratorRecord::ITERATOR_OFFSET}}, + {JSType::PROMISE_REACTIONS, { + PromiseReaction::HANDLER_OFFSET - PromiseReaction::PROMISE_CAPABILITY_OFFSET, + PromiseReaction::BIT_FIELD_OFFSET - PromiseReaction::HANDLER_OFFSET}}, + {JSType::PROMISE_RECORD, {PromiseRecord::SIZE - PromiseRecord::VALUE_OFFSET}}, + {JSType::PROPERTY_BOX, {PropertyBox::SIZE - PropertyBox::VALUE_OFFSET}}, + {JSType::PROTOTYPE_HANDLER, { + PrototypeHandler::PROTO_CELL_OFFSET - PrototypeHandler::HANDLER_INFO_OFFSET, + PrototypeHandler::HOLDER_OFFSET - PrototypeHandler::PROTO_CELL_OFFSET, + PrototypeHandler::ACCESSOR_JSFUNCTION_OFFSET - PrototypeHandler::HOLDER_OFFSET, + PrototypeHandler::ACCESSOR_METHOD_ID_OFFSET - PrototypeHandler::PrototypeHandler::ACCESSOR_JSFUNCTION_OFFSET}}, + {JSType::PROTOTYPE_INFO, { + ProtoChangeDetails::REGISTER_INDEX_OFFSET - ProtoChangeDetails::CHANGE_LISTENER_OFFSET}}, + {JSType::PROTO_CHANGE_MARKER, {}}, + {JSType::RB_TREENODE, { + RBTreeNode::RIGHT_OFFSET - RBTreeNode::LEFT_OFFSET, + RBTreeNode::ISRED_OFFSET - RBTreeNode::RIGHT_OFFSET, + RBTreeNode::COUNT_OFFSET - RBTreeNode::ISRED_OFFSET}}, + {JSType::RESOLVEDBINDING_RECORD, { + ResolvedBinding::BINDING_NAME_OFFSET - ResolvedBinding::MODULE_OFFSET, + ResolvedBinding::SIZE - ResolvedBinding::BINDING_NAME_OFFSET}}, + {JSType::RESOLVEDINDEXBINDING_RECORD, { + ResolvedIndexBinding::INDEX_OFFSET - ResolvedIndexBinding::MODULE_OFFSET, + ResolvedIndexBinding::END_OFFSET - ResolvedIndexBinding::INDEX_OFFSET}}, + {JSType::RESOLVEDRECORDBINDING_RECORD, { + ResolvedRecordBinding::BINDING_NAME_OFFSET - ResolvedRecordBinding::MODULE_RECORD_OFFSET, + ResolvedRecordBinding::SIZE - ResolvedRecordBinding::BINDING_NAME_OFFSET}}, + {JSType::RESOLVEDRECORDINDEXBINDING_RECORD, { + ResolvedRecordIndexBinding::ABC_FILE_NAME - ResolvedRecordIndexBinding::MODULE_RECORD_INDEX_OFFSET, + ResolvedRecordIndexBinding::INDEX_OFFSET - ResolvedRecordIndexBinding::ABC_FILE_NAME}}, + {JSType::RESOLVING_FUNCTIONS_RECORD, { + ResolvingFunctionsRecord::REJECT_FUNCTION_OFFSET - ResolvingFunctionsRecord::RESOLVE_FUNCTION_OFFSET, + ResolvingFunctionsRecord::SIZE - ResolvingFunctionsRecord::REJECT_FUNCTION_OFFSET}}, + {JSType::SENDABLE_ENV, {}}, + {JSType::SLICED_STRING, {SlicedString::STARTINDEX_OFFSET - SlicedString::PARENT_OFFSET}}, + {JSType::SOURCE_TEXT_MODULE_RECORD, { + SourceTextModule::NAMESPACE_OFFSET - SourceTextModule::SOURCE_TEXT_MODULE_OFFSET, + SourceTextModule::REQUESTED_MODULES_OFFSET - SourceTextModule::NAMESPACE_OFFSET, + SourceTextModule::IMPORT_ENTRIES_OFFSET - SourceTextModule::REQUESTED_MODULES_OFFSET, + SourceTextModule::LOCAL_EXPORT_ENTTRIES_OFFSET - SourceTextModule::IMPORT_ENTRIES_OFFSET, + SourceTextModule::INDIRECT_EXPORT_ENTTRIES_OFFSET - SourceTextModule::LOCAL_EXPORT_ENTTRIES_OFFSET, + SourceTextModule::START_EXPORT_ENTTRIES_OFFSET - SourceTextModule::INDIRECT_EXPORT_ENTTRIES_OFFSET, + SourceTextModule::NAME_DICTIONARY_OFFSET - SourceTextModule::START_EXPORT_ENTTRIES_OFFSET, + SourceTextModule::CYCLE_ROOT_OFFSET - SourceTextModule::NAME_DICTIONARY_OFFSET, + SourceTextModule::TOP_LEVEL_CAPABILITY_OFFSET - SourceTextModule::CYCLE_ROOT_OFFSET, + SourceTextModule::ASYNC_PARENT_MODULES_OFFSET - SourceTextModule::TOP_LEVEL_CAPABILITY_OFFSET, + SourceTextModule::SENDABLE_ENV_OFFSET - SourceTextModule::ASYNC_PARENT_MODULES_OFFSET, + SourceTextModule::EVALUATION_ERROR_OFFSET - SourceTextModule::SENDABLE_ENV_OFFSET}}, + {JSType::STAR_EXPORTENTRY_RECORD, {StarExportEntry::SIZE - StarExportEntry::STAR_EXPORT_ENTRY_OFFSET}}, + {JSType::STORE_TS_HANDLER, {StoreAOTHandler::PROTO_CELL_OFFSET - StoreAOTHandler::HANDLER_INFO_OFFSET, + StoreAOTHandler::HOLDER_OFFSET - StoreAOTHandler::PROTO_CELL_OFFSET, + StoreAOTHandler::SIZE - StoreAOTHandler::HOLDER_OFFSET}}, + {JSType::SYMBOL, {JSSymbol::HASHFIELD_OFFSET - JSSymbol::DESCRIPTION_OFFSET}}, + {JSType::TAGGED_ARRAY, { + TaggedArray::EXTRA_LENGTH_OFFSET - TaggedArray::LENGTH_OFFSET, TaggedArray::LENGTH_OFFSET}}, + {JSType::TAGGED_DICTIONARY, {}}, + {JSType::TEMPLATE_MAP, {}}, + {JSType::TRACK_INFO, { + TrackInfo::CACHED_FUNC_OFFSET - TrackInfo::CACHED_HCLASS_OFFSET, + TrackInfo::BIT_FIELD_OFFSET - TrackInfo::CACHED_FUNC_OFFSET}}, + {JSType::TRANSITION_HANDLER, { + TransitionHandler::TRANSITION_HCLASS_OFFSET - TransitionHandler::HANDLER_INFO_OFFSET, + TransitionHandler::SIZE - TransitionHandler::TRANSITION_HCLASS_OFFSET}}, + {JSType::TRANS_WITH_PROTO_HANDLER, { + TransWithProtoHandler::TRANSITION_HCLASS_OFFSET - TransWithProtoHandler::HANDLER_INFO_OFFSET, + TransWithProtoHandler::PROTO_CELL_OFFSET - TransWithProtoHandler::TRANSITION_HCLASS_OFFSET, + TransWithProtoHandler::SIZE - TransWithProtoHandler::PROTO_CELL_OFFSET}}, + {JSType::TREE_STRING, {TreeEcmaString::SECOND_OFFSET - TreeEcmaString::FIRST_OFFSET, + TreeEcmaString::SIZE - TreeEcmaString::SECOND_OFFSET}}, + {JSType::VTABLE, {}} + }; + } + + ~JSMetadataTestHelper() = default; + + enum MetadataStatus { + UNINITIALIZED = 0, + INITIALIZED + }; + + struct Metadata { + std::string name {}; + std::unordered_map> offsets {}; + int endOffset {}; + std::vector parents {}; + int status {MetadataStatus::UNINITIALIZED}; + }; + + void ReadAndParseMetadataJson(std::string &filePath, Metadata &metadata) + { + // Open specific metadata json file and using cJSON to parse + std::ifstream jsonFile(filePath); + if (!jsonFile.is_open()) { + std::cout << "Fail to open metadata file: " << filePath << std::endl; + return; + } + std::stringstream buffer; + buffer << jsonFile.rdbuf(); + auto json = cJSON_ParseWithOpts(buffer.str().c_str(), nullptr, true); + if (!json) { + std::cout << "Fail to read metadata file: " << filePath << std::endl; + jsonFile.close(); + return; + } + jsonFile.close(); + // Get "name" from json and set it to metadata.name + if (!GetStringFromJson(json, "name", metadata.name)) { + std::cout << "Fail to read name: " << filePath << std::endl; + return; + } + // Get "end_offset" from json and set it to metadata.endoffset + if (!GetIntFromJson(json, "end_offset", metadata.endOffset)) { + std::cout << "Fail to read endOffset: " << filePath << std::endl; + return; + } + // Get "offsets" and "parents" arrays from json + cJSON *offsets {}; + cJSON *parents {}; + if (!GetArrayFromJson(json, "offsets", &offsets)) { + std::cout << "Fail to read offsets array: " << filePath << std::endl; + return; + } + if (!GetArrayFromJson(json, "parents", &parents)) { + std::cout << "Fail to read parents array: " << filePath << std::endl; + return; + } + // Iterate over those two arrays and set items to metadata + auto parentVisitor = [&filePath, &metadata](const cJSON *item, int index) -> bool { + if (!cJSON_IsString(item)) { + std::cout << "Fail to visit parent: " << filePath << ", parents index: " << index << std::endl; + return false; + } + metadata.parents.emplace_back(item->valuestring); + return true; + }; + auto offsetVisitor = [&filePath, &metadata, this](const cJSON *item, int index) -> bool { + std::string key {}; + int offset {}; + int size {}; + if (!GetStringFromJson(item, "name", key)) { + std::cout << "Fail to visit name: " << filePath << ", offsets index " << index << std::endl; + return false; + } + if (!GetIntFromJson(item, "offset", offset)) { + std::cout << "Fail to visit offset: " << filePath << ", offsets index " << index << std::endl; + return false; + } + if (!GetIntFromJson(item, "size", size)) { + std::cout << "Fail to visit size: " << filePath << ", offsets index " << index << std::endl; + return false; + } + metadata.offsets[key] = std::make_pair(offset, size); + return true; + }; + if (!VisitArrayItems(offsets, offsetVisitor)) { + std::cout << "Fail to get offsets: " << filePath << std::endl; + return; + } + if (!VisitArrayItems(parents, parentVisitor)) { + std::cout << "Fail to get parents: " << filePath << std::endl; + return; + } + // Set metadata status to INITIALIZED + metadata.status = MetadataStatus::INITIALIZED; + } + + bool Test(JSType type, Metadata &metadata) + { + auto fieldNames = GetFieldNamesByType(type); + auto fieldOffsets = GetFieldOffsetsByType(type); + auto sizeTable = GetFieldSizesByType(type); + // Fields count should be the same as offsets' + if (fieldNames.size() != fieldOffsets.size()) { + std::cout << "Type fields' number inconsistent with offsets' number" << std::endl; + return false; + } + // check each [name, offset] pair + int index = 0; + for (; index < fieldNames.size(); index++) { + if (index == fieldNames.size() - 1) { + // Check typename and endOffset, stored at the last index of each array + if (!CheckTypeNameAndEndOffset(metadata.name, fieldNames[index], + metadata.endOffset, fieldOffsets[index])) { + return false; + } + } else { + // Check individual fields + if (!CheckField(fieldNames[index], fieldOffsets[index], metadata, fieldOffsets[0], sizeTable[index])) { + return false; + } + } + } + // If any field left in metadata that has not been checked, return false + if (!CheckLeftoverFieldInMetadata(metadata)) { + return false; + } + // Check if parent array is the same + if (!CheckParents(type, metadata)) { + return false; + } + + return true; + } + + bool TestForDictionaryLayout(std::string &filePath) + { + std::ifstream jsonFile(filePath); + if (!jsonFile.is_open()) { + std::cout << "Fail to open metadata file: " << filePath << std::endl; + return false; + } + std::stringstream buffer; + buffer << jsonFile.rdbuf(); + auto json = cJSON_ParseWithOpts(buffer.str().c_str(), nullptr, true); + if (!json) { + std::cout << "Fail to read metadata file: " << filePath << std::endl; + jsonFile.close(); + return false; + } + jsonFile.close(); + + int value; + if (!GetIntFromJson(json, "key_index", value)) { + std::cout << "Fail to get key_index: " << filePath << std::endl; + return false; + } + if (value != NameDictionary::ENTRY_KEY_INDEX) { + std::cout << "Dictionary layout key_index inconsistent: " << value << " "; + std::cout << NameDictionary::ENTRY_KEY_INDEX << std::endl; + return false; + } + if (!GetIntFromJson(json, "value_index", value)) { + std::cout << "Fail to get value_index: " << filePath << std::endl; + return false; + } + if (value != NameDictionary::ENTRY_VALUE_INDEX) { + std::cout << "Dictionary layout value_index inconsistent: " << value << " "; + std::cout << NameDictionary::ENTRY_VALUE_INDEX << std::endl; + return false; + } + if (!GetIntFromJson(json, "detail_index", value)) { + std::cout << "Fail to get detail_index: " << filePath << std::endl; + return false; + } + if (value != NameDictionary::ENTRY_DETAILS_INDEX) { + std::cout << "Dictionary layout detail_index inconsistent: " << value << " "; + std::cout << NameDictionary::ENTRY_DETAILS_INDEX << std::endl; + return false; + } + if (!GetIntFromJson(json, "entry_size", value)) { + std::cout << "Fail to get entry_size: " << filePath << std::endl; + return false; + } + if (value != NameDictionary::ENTRY_SIZE) { + std::cout << "Dictionary layout entry_size inconsistent: " << value << " "; + std::cout << NameDictionary::ENTRY_SIZE << std::endl; + return false; + } + if (!GetIntFromJson(json, "header_size", value)) { + std::cout << "Fail to get header_size: " << filePath << std::endl; + return false; + } + if (value != NameDictionary::TABLE_HEADER_SIZE) { + std::cout << "Dictionary layout header_size inconsistent: " << value << " "; + std::cout << NameDictionary::TABLE_HEADER_SIZE << std::endl; + return false; + } + return true; + } + + bool TestForTypeRange(std::string &filePath) + { + std::ifstream jsonFile(filePath); + if (!jsonFile.is_open()) { + std::cout << "Fail to open metadata file: " << filePath << std::endl; + return false; + } + std::stringstream buffer; + buffer << jsonFile.rdbuf(); + auto json = cJSON_ParseWithOpts(buffer.str().c_str(), nullptr, true); + if (!json) { + std::cout << "Fail to read metadata file: " << filePath << std::endl; + jsonFile.close(); + return false; + } + jsonFile.close(); + + std::string value; + if (!GetStringFromJson(json, "string_first", value)) { + std::cout << "Fail to read string_first: " << filePath << std::endl; + return false; + } + if (value != "LINE_STRING") { + std::cout << "string_first inconsistent" << std::endl; + return false; + } + if (!GetStringFromJson(json, "string_last", value)) { + std::cout << "Fail to read string_last: " << filePath << std::endl; + return false; + } + if (value != "TREE_STRING") { + std::cout << "string_last inconsistent" << std::endl; + return false; + } + if (!GetStringFromJson(json, "js_object_first", value)) { + std::cout << "Fail to read js_object_first: " << filePath << std::endl; + return false; + } + if (value != "JS_OBJECT") { + std::cout << "js_object_first inconsistent" << std::endl; + return false; + } + if (!GetStringFromJson(json, "js_object_last", value)) { + std::cout << "Fail to read js_object_last: " << filePath << std::endl; + return false; + } + if (value != "JS_GLOBAL_OBJECT") { + std::cout << "js_object_last inconsistent" << std::endl; + return false; + } + return true; + } + + static std::unordered_map> fieldNameTable_; + static std::unordered_map> fieldOffsetTable_; + static std::unordered_map> parentsTable_; + static std::unordered_map> fieldSizeTable_; +private: + std::vector GetFieldNamesByType(JSType type) + { + return HasTypeInFieldNameTable(type) ? fieldNameTable_.at(type) : std::vector(); + } + + std::vector GetFieldOffsetsByType(JSType type) + { + return HasTypeInFieldOffsetTable(type) ? fieldOffsetTable_.at(type) : std::vector(); + } + + std::vector GetParentsByType(JSType type) + { + return HasTypeInParentsTable(type) ? parentsTable_.at(type) : std::vector(); + } + + std::vector GetFieldSizesByType(JSType type) + { + return HasTypeInFieldSizesTable(type) ? fieldSizeTable_.at(type) : std::vector(); + } + + bool HasTypeInFieldNameTable(JSType type) + { + return !fieldNameTable_.empty() && fieldNameTable_.find(type) != fieldNameTable_.end(); + } + + bool HasTypeInFieldOffsetTable(JSType type) + { + return !fieldOffsetTable_.empty() && fieldOffsetTable_.find(type) != fieldOffsetTable_.end(); + } + + bool HasTypeInFieldSizesTable(JSType type) + { + return !fieldSizeTable_.empty() && fieldSizeTable_.find(type) != fieldSizeTable_.end(); + } + + bool HasTypeInParentsTable(JSType type) + { + return !parentsTable_.empty() && parentsTable_.find(type) != parentsTable_.end(); + } + + bool CheckTypeNameAndEndOffset(std::string &metaName, std::string &typeName, int metaEndOffset, int endOffset) + { + if (metaName != typeName || metaEndOffset != endOffset) { + std::cout << "Type name or endOffset inconsistent" << std::endl; + std::cout << "[" << metaName << " " << metaEndOffset << "] ["; + std::cout << typeName << " " << endOffset << "]" << std::endl; + return false; + } + return true; + } + + bool CheckField(std::string &fieldName, int fieldOffset, Metadata &metadata, int offsetAlign, int size) + { + if (metadata.offsets.find(fieldName) == metadata.offsets.end()) { + // a field is defined in the code but not in metadata, ignored for now + std::cout << "Type " << metadata.name << " Field " << fieldName; + std::cout << " is not defined in metadata" << std::endl; + return true; + } + offsetAlign = metadata.name == "JS_NATIVE_POINTER" ? JSNativePointer::POINTER_OFFSET : + metadata.name == "JS_SHARED_ARRAY" ? JSSharedArray::LENGTH_OFFSET : offsetAlign; + if ((fieldOffset - offsetAlign) != metadata.offsets[fieldName].first) { + std::cout << "Type " << metadata.name << " Field " << fieldName << " offset inconsistent" << std::endl; + std::cout << "Metadata: " << metadata.offsets[fieldName].first; + std::cout << ", Class definition: " << fieldOffset << std::endl; + return false; + } + if (size != metadata.offsets[fieldName].second) { + std::cout << "Type " << metadata.name << " Field " << fieldName << " size inconsistent" << std::endl; + std::cout << "Metadata: " << metadata.offsets[fieldName].second; + std::cout << ", Class definition: " << size << std::endl; + return false; + } + // remove fieldName in metadata that has been checked + metadata.offsets.erase(fieldName); + return true; + } + + bool CheckLeftoverFieldInMetadata(Metadata &metadata) + { + if (!metadata.offsets.empty()) { + std::cout << "Following fields of Type " << metadata.name; + std::cout << ", defined in metadata has not been checked: " << std::endl; + DumpFieldsInMetadata(metadata); + return false; + } + return true; + } + + bool CheckParents(JSType type, Metadata &metadata) + { + auto parents = GetParentsByType(type); + if (parents.size() != metadata.parents.size()) { + std::cout << "Type " << metadata.name << " parents inconsistent" << std::endl; + return false; + } + int index = 0; + for (; index < parents.size(); index++) { + if (parents.at(index) != metadata.parents.at(index)) { + std::cout << "Type " << metadata.name << " parents inconsistent" << std::endl; + return false; + } + } + return true; + } + + void DumpFieldsInMetadata(Metadata &metadata) + { + for (const auto &field : metadata.offsets) { + std::cout << "Field: " << field.first << " Offset: "; + std::cout << field.second.first << " Size: " << field.second.second << std::endl; + } + } + + bool GetStringFromJson(const cJSON *json, const char *key, std::string &value) + { + auto item = cJSON_GetObjectItem(json, key); + if (!item || !cJSON_IsString(item)) { + return false; + } + value = item->valuestring; + return true; + } + + bool GetIntFromJson(const cJSON *json, const char *key, int &value) + { + auto item = cJSON_GetObjectItem(json, key); + if (!item || !cJSON_IsNumber(item)) { + return false; + } + value = static_cast(item->valuedouble); + return true; + } + + bool GetArrayFromJson(const cJSON *json, const char *key, cJSON **value) + { + auto item = cJSON_GetObjectItem(json, key); + if (!item || !cJSON_IsArray(item)) { + return false; + } + *value = item; + return true; + } + + bool VisitArrayItems(const cJSON *json, ArrayVisitor &visitor) + { + int size = cJSON_GetArraySize(json); + if (size < 0) { + return false; + } + for (int index = 0; index < size; index++) { + cJSON *item = cJSON_GetArrayItem(json, index); + if (!visitor(item, index)) { + return false; + } + } + return true; + } +}; + +std::unordered_map> JSMetadataTestHelper::fieldNameTable_ {}; +std::unordered_map> JSMetadataTestHelper::fieldOffsetTable_ {}; +std::unordered_map> JSMetadataTestHelper::parentsTable_ {}; +std::unordered_map> JSMetadataTestHelper::fieldSizeTable_ {}; + +HWTEST_F_L0(JSMetadataTest, TestHClassMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"hclass.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::HCLASS, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestAccessorDataMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"accessor_data.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::ACCESSOR_DATA, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestAotLiteralInfoMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"aot_literal_info.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::AOT_LITERAL_INFO, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestAsyncGeneratorRequestMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"async_generator_request.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::ASYNC_GENERATOR_REQUEST, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestAsyncIteratorRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"async_iterator_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::ASYNC_ITERATOR_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestBigintMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"bigint.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::BIGINT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestByteArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"byte_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::BYTE_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestCellRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"cell_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::CELL_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestClassInfoExtractorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"class_info_extractor.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::CLASS_INFO_EXTRACTOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestClassLiteralMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"class_literal.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::CLASS_LITERAL, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestCompletionRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"completion_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::COMPLETION_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestConstantPoolMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"constant_pool.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::CONSTANT_POOL, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestConstantStringMetadata) +{ +#if defined(PANDA_TARGET_AMD64) || defined(PANDA_TARGET_ARM64) + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"constant_string.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::CONSTANT_STRING, metadata)); +#endif +} + +HWTEST_F_L0(JSMetadataTest, TestCowMutantTaggedArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"cow_mutant_tagged_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::COW_MUTANT_TAGGED_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestCowTaggedArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"cow_tagged_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::COW_TAGGED_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestExtraProfileTypeInfoMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"extra_profile_type_info.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::EXTRA_PROFILE_TYPE_INFO, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestFunctionTemplateMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"function_template.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::FUNCTION_TEMPLATE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestGlobalEnvMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"global_env.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::GLOBAL_ENV, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestImportentryRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"importentry_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::IMPORTENTRY_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestIndirectExportentryRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"indirect_exportentry_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::INDIRECT_EXPORTENTRY_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestInternalAccessorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"internal_accessor.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::INTERNAL_ACCESSOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAggregateErrorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_aggregate_error.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_AGGREGATE_ERROR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiArraylistIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_arraylist_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_ARRAYLIST_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiArrayListMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_array_list.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_ARRAY_LIST, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiBitvectorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_bitvector.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_BITVECTOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiBitvectorIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_bitvector_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_BITVECTOR_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiDequeMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_deque.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_DEQUE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiDequeIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_deque_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_DEQUE_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiHashmapIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_hashmap_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_HASHMAP_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiHashsetIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_hashset_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_HASHSET_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiHashMapMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_hash_map.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_HASH_MAP, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiHashSetMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_hash_set.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_HASH_SET, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiLightWeightMapMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_light_weight_map.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_LIGHT_WEIGHT_MAP, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiLightWeightMapIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_light_weight_map_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_LIGHT_WEIGHT_MAP_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiLightWeightSetMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_light_weight_set.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_LIGHT_WEIGHT_SET, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiLightWeightSetIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_light_weight_set_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiLinkedListMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_linked_list.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_LINKED_LIST, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiLinkedListIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_linked_list_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_LINKED_LIST_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiListMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_list.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_LIST, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiListIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_list_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_LIST_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiPlainArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_plain_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_PLAIN_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiPlainArrayIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_plain_array_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_PLAIN_ARRAY_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiQueueMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_queue.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_QUEUE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiQueueIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_queue_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_QUEUE_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiStackMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_stack.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_STACK, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiStackIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_stack_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_STACK_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiTreemapIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_treemap_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_TREEMAP_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiTreesetIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_treeset_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_TREESET_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiTreeMapMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_tree_map.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_TREE_MAP, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiTreeSetMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_tree_set.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_TREE_SET, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiVectorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_vector.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_VECTOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsApiVectorIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_api_vector_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_API_VECTOR_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsArgumentsMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_arguments.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ARGUMENTS, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsArrayBufferMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_array_buffer.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ARRAY_BUFFER, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsArrayIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_array_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ARRAY_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsynciteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_asynciterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNCITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsyncAwaitStatusFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_async_await_status_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsyncFromSyncIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_async_from_sync_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNC_FROM_SYNC_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsyncFromSyncIterUnwarpFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_async_from_sync_iter_unwarp_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsyncFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_async_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNC_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsyncFuncObjectMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_async_func_object.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNC_FUNC_OBJECT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsyncGeneratorFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_async_generator_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNC_GENERATOR_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsyncGeneratorObjectMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_async_generator_object.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNC_GENERATOR_OBJECT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsyncGeneratorResumeNextReturnProcessorRstFtnMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = + METADATA_SOURCE_FILE_DIR"js_async_generator_resume_next.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsyncModuleFulfilledFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_async_module_fulfilled_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNC_MODULE_FULFILLED_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsAsyncModuleRejectedFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_async_module_rejected_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ASYNC_MODULE_REJECTED_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsBigint64ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_bigint64_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_BIGINT64_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsBiguint64ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_biguint64_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_BIGUINT64_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsBoundFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_bound_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_BOUND_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsCjsExportsMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_cjs_exports.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_CJS_EXPORTS, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsCjsModuleMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_cjs_module.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_CJS_MODULE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsCjsRequireMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_cjs_require.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_CJS_REQUIRE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsCollatorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_collator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_COLLATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsDataViewMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_data_view.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_DATA_VIEW, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsDateMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_date.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_DATE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsDateTimeFormatMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_date_time_format.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_DATE_TIME_FORMAT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsDisplaynamesMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_displaynames.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_DISPLAYNAMES, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsErrorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_error.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ERROR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsEvalErrorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_eval_error.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_EVAL_ERROR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsFinalizationRegistryMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_finalization_registry.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_FINALIZATION_REGISTRY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsFloat32ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_float32_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_FLOAT32_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsFloat64ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_float64_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_FLOAT64_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsForinIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_forin_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_FORIN_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsFunctionMetadata) +{ +#if defined(PANDA_TARGET_AMD64) || defined(PANDA_TARGET_ARM64) + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_FUNCTION, metadata)); +#endif +} + +HWTEST_F_L0(JSMetadataTest, TestJsFunctionBaseMetadata) +{ +#if defined(PANDA_TARGET_AMD64) || defined(PANDA_TARGET_ARM64) + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_function_base.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_FUNCTION_BASE, metadata)); +#endif +} + +HWTEST_F_L0(JSMetadataTest, TestJsGeneratorContextMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_generator_context.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_GENERATOR_CONTEXT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsGeneratorFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_generator_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_GENERATOR_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsGeneratorObjectMetadata) +{ +#if defined(PANDA_TARGET_AMD64) || defined(PANDA_TARGET_ARM64) + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_generator_object.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_GENERATOR_OBJECT, metadata)); +#endif +} + +HWTEST_F_L0(JSMetadataTest, TestJsGlobalObjectMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_global_object.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_GLOBAL_OBJECT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsInt16ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_int16_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_INT16_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsInt32ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_int32_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_INT32_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsInt8ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_int8_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_INT8_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsIntlMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_intl.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_INTL, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsIntlBoundFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_intl_bound_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_INTL_BOUND_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsListFormatMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_list_format.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_LIST_FORMAT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsLocaleMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_locale.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_LOCALE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsMapMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_map.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_MAP, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsMapIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_map_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_MAP_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsModuleNamespaceMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_module_namespace.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_MODULE_NAMESPACE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsNativePointerMetadata) +{ +#if defined(PANDA_TARGET_AMD64) || defined(PANDA_TARGET_ARM64) + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_native_pointer.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_NATIVE_POINTER, metadata)); +#endif +} + +HWTEST_F_L0(JSMetadataTest, TestJsNumberFormatMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_number_format.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_NUMBER_FORMAT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsObjectMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_object.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_OBJECT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsOomErrorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_oom_error.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_OOM_ERROR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsPluralRulesMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_plural_rules.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PLURAL_RULES, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsPrimitiveRefMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_primitive_ref.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PRIMITIVE_REF, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsPromiseMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_promise.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PROMISE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsPromiseAllResolveElementFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_promise_all_resolve_element_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsPromiseAllSettledElementFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_promise_all_settled_element_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsPromiseAnyRejectElementFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_promise_any_reject_element_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsPromiseExecutorFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_promise_executor_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PROMISE_EXECUTOR_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsPromiseFinallyFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_promise_finally_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PROMISE_FINALLY_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsPromiseReactionsFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_promise_reactions_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PROMISE_REACTIONS_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsPromiseValueThunkOrThrowerFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_promise_value_thunk_or_thrower_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsProxyMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_proxy.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PROXY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsProxyRevocFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_proxy_revoc_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_PROXY_REVOC_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsRangeErrorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_range_error.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_RANGE_ERROR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsRealmMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_realm.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_REALM, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsReferenceErrorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_reference_error.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_REFERENCE_ERROR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsRegExpMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_reg_exp.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_REG_EXP, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsRegExpIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_reg_exp_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_REG_EXP_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsRelativeTimeFormatMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_relative_time_format.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_RELATIVE_TIME_FORMAT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSegmenterMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_segmenter.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SEGMENTER, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSegmentsMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_segments.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SEGMENTS, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSegmentIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_segment_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SEGMENT_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSendableArrayBufferMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_sendable_array_buffer.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SENDABLE_ARRAY_BUFFER, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSetMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_set.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SET, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSetIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_set_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SET_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedArrayBufferMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_array_buffer.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_ARRAY_BUFFER, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedArrayIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_array_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_ARRAY_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedAsyncFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_async_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_ASYNC_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedBigint64ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_bigint64_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_BIGINT64_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedBiguint64ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_biguint64_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_BIGUINT64_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedFloat32ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_float32_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_FLOAT32_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedFloat64ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_float64_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_FLOAT64_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedFunctionMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_function.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_FUNCTION, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedInt16ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_int16_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_INT16_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedInt32ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_int32_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_INT32_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedInt8ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_int8_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_INT8_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedMapMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_map.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_MAP, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedMapIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_map_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_MAP_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedObjectMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_object.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_OBJECT, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedSetMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_set.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_SET, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedSetIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_set_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_SET_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedTypedArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_typed_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_TYPED_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedUint16ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_uint16_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_UINT16_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedUint32ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_uint32_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_UINT32_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedUint8ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_uint8_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_UINT8_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSharedUint8ClampedArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_shared_uint8_clamped_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SHARED_UINT8_CLAMPED_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsStringIteratorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_string_iterator.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_STRING_ITERATOR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsSyntaxErrorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_syntax_error.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_SYNTAX_ERROR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsTerminationErrorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_termination_error.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_TERMINATION_ERROR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsTypedArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_typed_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_TYPED_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsTypeErrorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_type_error.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_TYPE_ERROR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsUint16ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_uint16_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_UINT16_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsUint32ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_uint32_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_UINT32_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsUint8ArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_uint8_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_UINT8_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsUint8ClampedArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_uint8_clamped_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_UINT8_CLAMPED_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsUriErrorMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_uri_error.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_URI_ERROR, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsWeakMapMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_weak_map.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_WEAK_MAP, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsWeakRefMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_weak_ref.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_WEAK_REF, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestJsWeakSetMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_weak_set.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::JS_WEAK_SET, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestLexicalEnvMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"lexical_env.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::LEXICAL_ENV, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestLineStringMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"line_string.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::LINE_STRING, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestLinkedNodeMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"linked_node.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::LINKED_NODE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestLocalExportentryRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"local_exportentry_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::LOCAL_EXPORTENTRY_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestMachineCodeObjectMetadata) +{ +#if defined(PANDA_TARGET_AMD64) || defined(PANDA_TARGET_ARM64) + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"machine_code_object.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::MACHINE_CODE_OBJECT, metadata)); +#endif +} + +HWTEST_F_L0(JSMetadataTest, TestMarkerCellMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"marker_cell.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::MARKER_CELL, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestMethodMetadata) +{ +#if defined(PANDA_TARGET_AMD64) || defined(PANDA_TARGET_ARM64) + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"method.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::METHOD, metadata)); +#endif +} + +HWTEST_F_L0(JSMetadataTest, TestMicroJobQueueMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"micro_job_queue.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::MICRO_JOB_QUEUE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestModuleRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"module_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::MODULE_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestMutantTaggedArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"mutant_tagged_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::MUTANT_TAGGED_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestNativeModuleFailureInfoMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"native_module_failure_info.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::NATIVE_MODULE_FAILURE_INFO, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestProfileTypeInfoMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"profile_type_info.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROFILE_TYPE_INFO, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestProfileTypeInfoCell0Metadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"profile_type_info_cell_0.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROFILE_TYPE_INFO_CELL_0, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestProfileTypeInfoCell1Metadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"profile_type_info_cell_1.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROFILE_TYPE_INFO_CELL_1, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestProfileTypeInfoCellNMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"profile_type_info_cell_n.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROFILE_TYPE_INFO_CELL_N, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestProgramMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"program.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROGRAM, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestPromiseCapabilityMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"promise_capability.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROMISE_CAPABILITY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestPromiseIteratorRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"promise_iterator_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROMISE_ITERATOR_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestPromiseReactionsMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"promise_reactions.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROMISE_REACTIONS, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestPromiseRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"promise_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROMISE_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestPropertyBoxMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"property_box.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROPERTY_BOX, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestPrototypeHandlerMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"prototype_handler.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROTOTYPE_HANDLER, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestPrototypeInfoMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"prototype_info.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROTOTYPE_INFO, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestProtoChangeMarkerMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"proto_change_marker.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::PROTO_CHANGE_MARKER, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestRbTreenodeMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"rb_treenode.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::RB_TREENODE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestResolvedbindingRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"resolvedbinding_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::RESOLVEDBINDING_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestResolvedindexbindingRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"resolvedindexbinding_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::RESOLVEDINDEXBINDING_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestResolvedrecordbindingRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"resolvedrecordbinding_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::RESOLVEDRECORDBINDING_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestResolvedrecordindexbindingRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"resolvedrecordindexbinding_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::RESOLVEDRECORDINDEXBINDING_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestResolvingFunctionsRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"resolving_functions_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::RESOLVING_FUNCTIONS_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestSendableEnvMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"sendable_env.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::SENDABLE_ENV, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestSlicedStringMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"sliced_string.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::SLICED_STRING, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestSourceTextModuleRecordMetadata) +{ +#if defined(PANDA_TARGET_AMD64) || defined(PANDA_TARGET_ARM64) + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"source_text_module_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::SOURCE_TEXT_MODULE_RECORD, metadata)); +#endif +} + +HWTEST_F_L0(JSMetadataTest, TestStarExportentryRecordMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"star_exportentry_record.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::STAR_EXPORTENTRY_RECORD, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestStoreAOTHandlerMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"store_ts_handler.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::STORE_TS_HANDLER, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestSymbolMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"symbol.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::SYMBOL, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestTaggedArrayMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"tagged_array.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::TAGGED_ARRAY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestTaggedDictionaryMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"tagged_dictionary.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::TAGGED_DICTIONARY, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestTemplateMapMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"template_map.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::TEMPLATE_MAP, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestTrackInfoMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"track_info.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::TRACK_INFO, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestTransitionHandlerMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"transition_handler.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::TRANSITION_HANDLER, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestTransWithProtoHandlerMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"trans_with_proto_handler.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::TRANS_WITH_PROTO_HANDLER, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestTreeStringMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"tree_string.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::TREE_STRING, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestVtableMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"vtable.json"; + JSMetadataTestHelper::Metadata metadata {}; + + tester.ReadAndParseMetadataJson(metadataFilePath, metadata); + ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); + ASSERT_TRUE(tester.Test(JSType::VTABLE, metadata)); +} + +HWTEST_F_L0(JSMetadataTest, TestDictionaryLayoutMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"dictionary_layout.json"; + ASSERT_TRUE(tester.TestForDictionaryLayout(metadataFilePath)); +} + +HWTEST_F_L0(JSMetadataTest, TestTypeRangeMetadata) +{ + JSMetadataTestHelper tester {}; + std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"type_range.json"; + ASSERT_TRUE(tester.TestForTypeRange(metadataFilePath)); +} +} \ No newline at end of file diff --git a/ecmascript/dfx/hprof/tests/rawheap_translate_test.cpp b/ecmascript/dfx/hprof/tests/rawheap_translate_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5cebd895448f7b2d319efc985da58d3927f7ba8 --- /dev/null +++ b/ecmascript/dfx/hprof/tests/rawheap_translate_test.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/tests/test_helper.h" +#include "ecmascript/dfx/hprof/rawheap_translate/metadata_parse.h" +#include "ecmascript/dfx/hprof/rawheap_translate/utils.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class RawHeapTranslateTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + meta = std::make_unique(); + } + + void TearDown() override + { + } + + std::unique_ptr meta {nullptr}; +}; + +HWTEST_F_L0(RawHeapTranslateTest, MetaDataParse) +{ + /* + metadataJson a json is similar to the following example + { + "type_enum": {"INVALID": 8}, + "type_list": [ + { + "name": "JS_OBJECT", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "ECMA_OBJECT" + ] + }, + { + "name": "ECMA_OBJECT", + "offsets": [], + "end_offset": 8, + "parents": [ + "TAGGED_OBJECT" + ] + }, + { + "name": "TAGGED_OBJECT", + "offsets": [], + "end_offset": 8, + "parents": [] + } + ], + "type_layout": { + "Dictionary_layout": { + "name": "Dictionary", + "key_index": 0, + "value_index": 1, + "detail_index": 2, + "entry_size": 3, + "header_size": 4 + }, + "Type_range": { + "string_first": "LINE_STRING", + "string_last": "TREE_STRING", + "js_object_first": "JS_OBJECT", + "js_object_last": "JS_GLOBAL_OBJECT" + } + }, + "version": "1.0.0" + } + */ + std::string metadataJson = + "{\"type_enum\": {\"INVALID\": 8}, \"type_list\": [{\"name\": \"JS_OBJECT\"," + "\"offsets\": [{\"name\": \"Properties\", \"offset\": 0, \"size\": 8}, " + "{\"name\": \"Elements\", \"offset\": 8, \"size\": 8}], \"end_offset\": 16, " + "\"parents\": [\"ECMA_OBJECT\"]}, {\"name\": \"ECMA_OBJECT\", \"offsets\": [], " + "\"end_offset\": 8, \"parents\": [\"TAGGED_OBJECT\"]}, {\"name\": \"TAGGED_OBJECT\", " + "\"offsets\": [], \"end_offset\": 8, \"parents\": []}], \"type_layout\": {\"Dictionary_layout\": {" + "\"name\": \"Dictionary\", \"key_index\": 0, \"value_index\": 1, \"detail_index\": 2, " + "\"entry_size\": 3, \"header_size\": 4}, \"Type_range\": {\"string_first\": \"LINE_STRING\", " + "\"string_last\": \"TREE_STRING\", \"js_object_first\": \"JS_OBJECT\", \"js_object_last\": " + "\"JS_GLOBAL_OBJECT\"}}, \"version\": \"1.0.0\"}"; + + cJSON *metadataCJson = cJSON_ParseWithOpts(metadataJson.c_str(), nullptr, true); + ASSERT_TRUE(metadataCJson != nullptr); + + bool result = meta->Parse(metadataCJson); + cJSON_Delete(metadataCJson); + ASSERT_TRUE(result); + + auto visit = [] ([[maybe_unused]]std::shared_ptr &metadata, + [[maybe_unused]]int offset) {}; + uint32_t baseOffset = 0; + meta->VisitObjectBody("JS_OBJECT", visit, baseOffset); + ASSERT_TRUE(baseOffset == 32); // 32: 16 + 8 + 8 = 32, all parent endOffset count total +} + +HWTEST_F_L0(RawHeapTranslateTest, BytesToNumber) +{ + char bytes[4] = {0x78, 0x56, 0x34, 0x12}; // write by little endian + + uint32_t u32 = rawheap_translate::ByteToU32(bytes); + if (rawheap_translate::IsLittleEndian()) { + ASSERT_TRUE(u32 == 0x12345678); + } else { + ASSERT_TRUE(u32 == 0x78563412); + } +} +} // namespace panda::test diff --git a/ecmascript/dfx/stackinfo/tests/BUILD.gn b/ecmascript/dfx/stackinfo/tests/BUILD.gn index b1e8d817d36b0afdbb7da36f1f65f9e1eab82997..e32a6f6da04984bbc6cf03a4e6f2b1c327a2a9f4 100644 --- a/ecmascript/dfx/stackinfo/tests/BUILD.gn +++ b/ecmascript/dfx/stackinfo/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("JsStackInfoTest") { module_out_path = module_output_path diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index 14b86289aeb10640fb0c58160b1587a084f03dae..3e86c19706efa02ed13cbbce40a4b7f4d467e6db 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -45,44 +45,6 @@ static constexpr uint32_t DUMP_TYPE_OFFSET = 12; static constexpr uint32_t DUMP_PROPERTY_OFFSET = 20; static constexpr uint32_t DUMP_ELEMENT_OFFSET = 2; -static bool HasEdge(std::vector &vec, JSTaggedValue toValue) -{ - for (auto &ref : vec) { - if (ref.value_ == toValue) { - return true; - } - } - return false; -} - -static void AddAnonymousEdge(TaggedObject *obj, std::vector &vec) -{ - auto hclass = obj->GetClass(); - if (hclass == nullptr) { - return; - } - ObjectXRay::VisitObjectBody(obj, hclass, - [&vec]([[maybe_unused]]TaggedObject *root, ObjectSlot start, ObjectSlot end, VisitObjectArea area) { - if (area != VisitObjectArea::NORMAL) { - return; - } - uint32_t cnt = 0; - for (auto slot = start; slot != end; slot++) { - JSTaggedValue toValue = JSTaggedValue(slot.GetTaggedType()); - if (!toValue.IsHeapObject()) { - continue; - } - if (HasEdge(vec, toValue)) { - continue; - } - std::string name = "anonymous-slot" + std::to_string(cnt); - cnt += 1; - vec.emplace_back(ConvertToString(name), toValue); - } - } - ); -} - CString JSHClass::DumpJSType(JSType type) { switch (type) { @@ -662,8 +624,7 @@ static void DumpHClass(const JSHClass *jshclass, std::ostream &os, bool withDeta os << "| ElementsKind :" << Elements::GetString(jshclass->GetElementsKind()); os << "| NumberOfProps :" << std::dec << jshclass->NumberOfProps(); os << "| InlinedProperties :" << std::dec << jshclass->GetInlinedProperties(); - os << "| IsTS :" << std::boolalpha << jshclass->IsTS(); - os << "| Level :" << std::dec << static_cast(jshclass->GetLevel()); + os << "| IsAOT :" << std::boolalpha << jshclass->IsAOT(); os << "\n"; } @@ -673,7 +634,7 @@ static void DumpClass(TaggedObject *obj, std::ostream &os) DumpHClass(JSHClass::Cast(obj), os, true); } -static void DumpObject(TaggedObject *obj, std::ostream &os) +static void DumpObject(TaggedObject *obj, std::ostream &os, bool isPrivacy) { DISALLOW_GARBAGE_COLLECTION; auto jsHclass = obj->GetClass(); @@ -742,7 +703,7 @@ static void DumpObject(TaggedObject *obj, std::ostream &os) case JSType::JS_TERMINATION_ERROR: case JSType::JS_ARGUMENTS: needDumpHClass = true; - JSObject::Cast(obj)->Dump(os); + JSObject::Cast(obj)->Dump(os, isPrivacy); break; case JSType::JS_FUNCTION_BASE: needDumpHClass = true; @@ -1002,7 +963,7 @@ static void DumpObject(TaggedObject *obj, std::ostream &os) TransWithProtoHandler::Cast(obj)->Dump(os); break; case JSType::STORE_TS_HANDLER: - StoreTSHandler::Cast(obj)->Dump(os); + StoreAOTHandler::Cast(obj)->Dump(os); break; case JSType::PROPERTY_BOX: PropertyBox::Cast(obj)->Dump(os); @@ -1345,14 +1306,14 @@ void JSTaggedValue::DumpTaggedValueType(std::ostream &os) const } } -void JSTaggedValue::Dump(std::ostream &os) const +void JSTaggedValue::Dump(std::ostream &os, bool isPrivacy) const { DumpTaggedValue(os); os << "\n"; if (IsHeapObject()) { TaggedObject *obj = IsWeak() ? GetTaggedWeakRef() : GetTaggedObject(); - DumpObject(obj, os); + DumpObject(obj, os, isPrivacy); } } @@ -1372,17 +1333,19 @@ void JSThread::DumpStack() handler.DumpStack(std::cout); } -void NumberDictionary::Dump(std::ostream &os) const +void NumberDictionary::Dump(std::ostream &os, bool isPrivacy) const { DISALLOW_GARBAGE_COLLECTION; int size = Size(); for (int hashIndex = 0; hashIndex < size; hashIndex++) { JSTaggedValue key(GetKey(hashIndex)); if (!key.IsUndefined() && !key.IsHole()) { - JSTaggedValue val(GetValue(hashIndex)); os << std::right << std::setw(DUMP_PROPERTY_OFFSET) << static_cast(JSTaggedNumber(key).GetNumber()) << ": "; - val.DumpTaggedValue(os); + if (!isPrivacy) { + JSTaggedValue val(GetValue(hashIndex)); + val.DumpTaggedValue(os); + } os << " "; DumpAttr(GetAttributes(hashIndex), false, os); os << "\n"; @@ -1390,18 +1353,20 @@ void NumberDictionary::Dump(std::ostream &os) const } } -void NameDictionary::Dump(std::ostream &os) const +void NameDictionary::Dump(std::ostream &os, bool isPrivacy) const { DISALLOW_GARBAGE_COLLECTION; int size = Size(); for (int hashIndex = 0; hashIndex < size; hashIndex++) { JSTaggedValue key(GetKey(hashIndex)); if (!key.IsUndefined() && !key.IsHole()) { - JSTaggedValue val(GetValue(hashIndex)); os << std::right << std::setw(DUMP_PROPERTY_OFFSET); DumpPropertyKey(key, os); os << ": "; - val.DumpTaggedValue(os); + if (!isPrivacy) { + JSTaggedValue val(GetValue(hashIndex)); + val.DumpTaggedValue(os); + } os << " "; DumpAttr(GetAttributes(hashIndex), false, os); os << "\n"; @@ -1409,18 +1374,20 @@ void NameDictionary::Dump(std::ostream &os) const } } -void GlobalDictionary::Dump(std::ostream &os) const +void GlobalDictionary::Dump(std::ostream &os, bool isPrivacy) const { DISALLOW_GARBAGE_COLLECTION; int size = Size(); for (int hashIndex = 0; hashIndex < size; hashIndex++) { JSTaggedValue key(GetKey(hashIndex)); if (!key.IsUndefined() && !key.IsHole()) { - JSTaggedValue val(GetValue(hashIndex)); os << std::right << std::setw(DUMP_PROPERTY_OFFSET); DumpPropertyKey(key, os); os << " : "; - val.DumpTaggedValue(os); + if (!isPrivacy) { + JSTaggedValue val(GetValue(hashIndex)); + val.DumpTaggedValue(os); + } os << " "; DumpAttr(GetAttributes(hashIndex), false, os); os << "\n"; @@ -1545,7 +1512,7 @@ void TaggedSingleList::Dump(std::ostream &os) const } } -void JSObject::Dump(std::ostream &os) const +void JSObject::Dump(std::ostream &os, bool isPrivacy) const { DISALLOW_GARBAGE_COLLECTION; JSHClass *jshclass = GetJSHClass(); @@ -1568,7 +1535,7 @@ void JSObject::Dump(std::ostream &os) const } else { NumberDictionary *dict = NumberDictionary::Cast(elements); os << " EntriesCount() << "]>\n"; - dict->Dump(os); + dict->Dump(os, isPrivacy); } TaggedArray *properties = TaggedArray::Cast(GetProperties().GetTaggedObject()); @@ -1576,7 +1543,7 @@ void JSObject::Dump(std::ostream &os) const if (IsJSGlobalObject()) { GlobalDictionary *dict = GlobalDictionary::Cast(properties); os << " EntriesCount() << "]>\n"; - dict->Dump(os); + dict->Dump(os, isPrivacy); return; } @@ -1602,7 +1569,9 @@ void JSObject::Dump(std::ostream &os) const } else { val = properties->Get(i - static_cast(jshclass->GetInlinedProperties())); } - val.DumpTaggedValue(os); + if (!isPrivacy) { + val.DumpTaggedValue(os); + } os << ") "; DumpAttr(attr, true, os); os << "\n"; @@ -1610,7 +1579,7 @@ void JSObject::Dump(std::ostream &os) const } else { NameDictionary *dict = NameDictionary::Cast(properties); os << " EntriesCount() << "]>\n"; - dict->Dump(os); + dict->Dump(os, isPrivacy); } } @@ -3227,7 +3196,7 @@ void TransWithProtoHandler::Dump(std::ostream &os) const os << "\n"; } -void StoreTSHandler::Dump(std::ostream &os) const +void StoreAOTHandler::Dump(std::ostream &os) const { os << " - HandlerInfo: "; GetHandlerInfo().Dump(os); @@ -4460,7 +4429,7 @@ static void DumpObject(TaggedObject *obj, std::vector &vec, bool isVm TransWithProtoHandler::Cast(obj)->DumpForSnapshot(vec); break; case JSType::STORE_TS_HANDLER: - StoreTSHandler::Cast(obj)->DumpForSnapshot(vec); + StoreAOTHandler::Cast(obj)->DumpForSnapshot(vec); break; case JSType::PROTOTYPE_HANDLER: PrototypeHandler::Cast(obj)->DumpForSnapshot(vec); @@ -4480,7 +4449,6 @@ static void DumpObject(TaggedObject *obj, std::vector &vec, bool isVm } else { vec.pop_back(); } - AddAnonymousEdge(obj, vec); } static inline void EcmaStringToStd(CString &res, EcmaString *str) @@ -5625,7 +5593,7 @@ void TransWithProtoHandler::DumpForSnapshot(std::vector &vec) const vec.emplace_back(CString("ProtoCell"), GetProtoCell()); } -void StoreTSHandler::DumpForSnapshot(std::vector &vec) const +void StoreAOTHandler::DumpForSnapshot(std::vector &vec) const { vec.emplace_back(CString("HandlerInfo"), GetHandlerInfo()); vec.emplace_back(CString("ProtoCell"), GetProtoCell()); diff --git a/ecmascript/ecma_context.cpp b/ecmascript/ecma_context.cpp index 9aeef0edbfd4a126fa63f52d4b04513c92e28949..fc53e404f4c23ced706cbaa292e7a30b23da3dca 100644 --- a/ecmascript/ecma_context.cpp +++ b/ecmascript/ecma_context.cpp @@ -341,11 +341,11 @@ Expected EcmaContext::CommonInvokeEcmaEntrypoint(const JSPa EcmaRuntimeStatScope runtimeStatScope(vm_); result = InvokeEcmaAotEntrypoint(func, global, jsPandaFile, entryPoint); } else if (vm_->GetJSOptions().IsEnableForceJitCompileMain()) { - Jit::Compile(vm_, func, CompilerTier::FAST); + Jit::Compile(vm_, func, CompilerTier::Tier::FAST); EcmaRuntimeStatScope runtimeStatScope(vm_); result = JSFunction::InvokeOptimizedEntrypoint(thread_, func, global, nullptr); } else if (vm_->GetJSOptions().IsEnableForceBaselineCompileMain()) { - Jit::Compile(vm_, func, CompilerTier::BASELINE); + Jit::Compile(vm_, func, CompilerTier::Tier::BASELINE); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread_, JSHandle(func), global, undefined, 0); EcmaRuntimeStatScope runtimeStatScope(vm_); @@ -364,7 +364,7 @@ Expected EcmaContext::CommonInvokeEcmaEntrypoint(const JSPa } } if (thread_->HasPendingException()) { -#ifdef PANDA_TARGET_OHOS +#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE) return result; #else return Unexpected(false); @@ -397,7 +397,7 @@ Expected EcmaContext::InvokeEcmaEntrypoint(const JSPandaFil JSHandle func(thread_, program->GetMainFunction()); Expected result = CommonInvokeEcmaEntrypoint(jsPandaFile, entryPoint, func, executeFromJob); -#ifdef PANDA_TARGET_OHOS +#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE) if (thread_->HasPendingException()) { HandleUncaughtException(); } @@ -467,10 +467,6 @@ void EcmaContext::CJSExecution(JSHandle &func, JSHandle(func), thisArg, undefined, 5); // 5 : argument numbers RETURN_IF_ABRUPT_COMPLETION(thread_); - if (info == nullptr) { - LOG_ECMA(ERROR) << "CJSExecution Stack overflow!"; - return; - } info->SetCallArg(cjsInfo.exportsHdl.GetTaggedValue(), cjsInfo.requireHdl.GetTaggedValue(), cjsInfo.moduleHdl.GetTaggedValue(), diff --git a/ecmascript/ecma_context.h b/ecmascript/ecma_context.h index 2ad4d05ee592004af929ddb9fe792d5bec5f5cd6..2c7f0144ea477e7ab76eb5a6d0cb43b5f358bfbc 100644 --- a/ecmascript/ecma_context.h +++ b/ecmascript/ecma_context.h @@ -124,6 +124,23 @@ public: bool ExecutePromisePendingJob(); + bool IsInPendingJob() const + { + return pendingJobEnterCount > 0; + } + + void AddPendingJobEnterCount() + { + ASSERT(pendingJobEnterCount < std::numeric_limits::max()); + ++pendingJobEnterCount; + } + + void MinusPendingJobEnterCount() + { + ASSERT(IsInPendingJob()); + --pendingJobEnterCount; + } + static EcmaContext *ConstCast(const EcmaContext *context) { return const_cast(context); @@ -780,6 +797,8 @@ private: bool hasKeptObjects_ {false}; + uint64_t pendingJobEnterCount {0}; + friend class EcmaHandleScope; friend class JSPandaFileExecutor; friend class ObjectFactory; diff --git a/ecmascript/ecma_macros.h b/ecmascript/ecma_macros.h index 4c27b6788d5218f9d04e509bd895231d28b7804b..2f93576f54544ee95c5b57ee8d7bb6b0b8a2b3bb 100644 --- a/ecmascript/ecma_macros.h +++ b/ecmascript/ecma_macros.h @@ -342,19 +342,19 @@ } // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define GET_DATE_VALUE(name, code, isLocal) \ - static JSTaggedValue name(EcmaRuntimeCallInfo *argv) \ - { \ - ASSERT(argv); \ - JSThread *thread = argv->GetThread(); \ - [[maybe_unused]] EcmaHandleScope handleScope(thread); \ - JSHandle msg = GetThis(argv); \ - if (!msg->IsDate()) { \ - THROW_TYPE_ERROR_AND_RETURN(thread, "Not a Date Object", JSTaggedValue::Exception()); \ - } \ - JSHandle jsDate(msg); \ - double result = jsDate->GetDateValue(jsDate->GetTimeValue().GetDouble(), code, isLocal); \ - return GetTaggedDouble(result); \ +#define GET_DATE_VALUE(name, code, isLocal) \ + static JSTaggedValue name(EcmaRuntimeCallInfo *argv) \ + { \ + ASSERT(argv); \ + JSThread *thread = argv->GetThread(); \ + [[maybe_unused]] EcmaHandleScope handleScope(thread); \ + JSHandle msg = GetThis(argv); \ + if (!msg->IsDate()) { \ + THROW_TYPE_ERROR_AND_RETURN(thread, "Not a Date Object", JSTaggedValue::Exception()); \ + } \ + JSHandle jsDate(msg); \ + double result = jsDate->GetDateValue(thread, jsDate->GetTimeValue().GetDouble(), code, isLocal); \ + return GetTaggedDouble(result); \ } // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/ecma_param_configuration.h b/ecmascript/ecma_param_configuration.h index 1a54cd57f6a3c5a2b132189423daaf62a8f0d475..85f632310ee43fd5e5ad0ddde656c9025b6efd2d 100644 --- a/ecmascript/ecma_param_configuration.h +++ b/ecmascript/ecma_param_configuration.h @@ -91,6 +91,7 @@ public: oldSpaceMaxOvershootSize_ = 8_MB; outOfMemoryOvershootSize_ = 2_MB; minAllocLimitGrowingStep_ = 2_MB; + minNativeLimitGrowingStep_ = 16_MB; minGrowingStep_ = 4_MB; maxStackSize_ = 128_KB; maxJSSerializerSize_ = 8_MB; @@ -100,7 +101,7 @@ public: stepNativeSizeInc_ = 256_MB; nativeSizeOvershoot_ = 80_MB; maxNativeSizeInc_ = 768_MB; - fragmentationLimitForSharedFullGC_ = 10_MB; + fragmentationLimitForSharedFullGC_ = 5_MB; } else if (maxHeapSize_ < HIGH_MEMORY) { // 128_MB ~ 256_MB minSemiSpaceSize_ = 2_MB; maxSemiSpaceSize_ = 8_MB; @@ -116,6 +117,7 @@ public: oldSpaceMaxOvershootSize_ = 16_MB; outOfMemoryOvershootSize_ = 2_MB; minAllocLimitGrowingStep_ = 4_MB; + minNativeLimitGrowingStep_ = 32_MB; minGrowingStep_ = 8_MB; maxStackSize_ = 128_KB; maxJSSerializerSize_ = 16_MB; @@ -125,7 +127,7 @@ public: stepNativeSizeInc_ = 256_MB; nativeSizeOvershoot_ = 80_MB; maxNativeSizeInc_ = 768_MB; - fragmentationLimitForSharedFullGC_ = 10_MB; + fragmentationLimitForSharedFullGC_ = 5_MB; } else { // 256_MB ~ 384_MB minSemiSpaceSize_ = 2_MB; maxSemiSpaceSize_ = 16_MB; @@ -141,6 +143,7 @@ public: oldSpaceMaxOvershootSize_ = 16_MB; outOfMemoryOvershootSize_ = 2_MB; minAllocLimitGrowingStep_ = 8_MB; + minNativeLimitGrowingStep_ = 64_MB; minGrowingStep_ = 16_MB; maxStackSize_ = 128_KB; maxJSSerializerSize_ = 16_MB; @@ -151,7 +154,7 @@ public: nativeSizeOvershoot_ = 100_MB; asyncClearNativePointerThreshold_ = 500_MB; maxNativeSizeInc_ = 1_GB; - fragmentationLimitForSharedFullGC_ = 10_MB; + fragmentationLimitForSharedFullGC_ = 5_MB; } } @@ -230,6 +233,11 @@ public: return minAllocLimitGrowingStep_; } + size_t GetMinNativeLimitGrowingStep() const + { + return minNativeLimitGrowingStep_; + } + size_t GetMinGrowingStep() const { return minGrowingStep_; @@ -323,6 +331,7 @@ private: size_t oldSpaceMaxOvershootSize_ {0}; size_t outOfMemoryOvershootSize_ {0}; size_t minAllocLimitGrowingStep_ {0}; + size_t minNativeLimitGrowingStep_ {0}; size_t minGrowingStep_ {0}; size_t sharedHeapLimitGrowingFactor_ {0}; size_t sharedHeapLimitGrowingStep_ {0}; diff --git a/ecmascript/ecma_string-inl.h b/ecmascript/ecma_string-inl.h index f6b46bd489fd7f9a1827bd34569901a13620198d..d3fce67dd672e381303427b6ae4c2137b0ffea77 100644 --- a/ecmascript/ecma_string-inl.h +++ b/ecmascript/ecma_string-inl.h @@ -413,7 +413,11 @@ void EcmaString::WriteToFlat(EcmaString *src, Char *buf, uint32_t maxLength) length -= firstLength; } else { // first string is longer. So recurse over second. - if (secondLength > 0) { + // if src{first:A,second:B} is half flat to {first:A+B,second:empty} by another thread + // but the other thread didn't end, and this thread get {first:A+B,second:B} + // it may cause write buffer overflower in line 424, buf + firstLength is overflower. + // so use 'length > firstLength' instead of 'secondLength > 0' + if (length > firstLength) { if (secondLength == 1) { buf[firstLength] = static_cast(second->At(0)); } else if ((second->IsLineOrConstantString()) && second->IsUtf8()) { @@ -421,10 +425,10 @@ void EcmaString::WriteToFlat(EcmaString *src, Char *buf, uint32_t maxLength) } else { WriteToFlat(second, buf + firstLength, maxLength - firstLength); } + length -= secondLength; } maxLength = firstLength; src = first; - length -= secondLength; } continue; } diff --git a/ecmascript/ecma_string.cpp b/ecmascript/ecma_string.cpp index 9109cab901afe7fe4348f7be172a1a255f2c9d2e..fdad437d5137e5d73ac5802870cb3ea0ee34c648 100755 --- a/ecmascript/ecma_string.cpp +++ b/ecmascript/ecma_string.cpp @@ -185,6 +185,20 @@ EcmaString *EcmaString::GetSubString(const EcmaVM *vm, return FastSubString(vm, src, start, length); } +bool EcmaString::SubStringIsUtf8(const EcmaVM *vm, + const JSHandle &src, uint32_t start, uint32_t length) +{ + ASSERT((start + length) <= src->GetLength()); + if (length == 0) { + return true; + } + if (src->IsUtf8()) { + return true; + } + FlatStringInfo srcFlat = FlattenAllString(vm, src); + return CanBeCompressed(srcFlat.GetDataUtf16() + start, length); +} + void EcmaString::WriteData(EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length) { ASSERT(IsLineString() && !IsConstantString()); diff --git a/ecmascript/ecma_string.h b/ecmascript/ecma_string.h index f860767dcb14f4196f16a895cff249ee297ec474..4aeb042e44e596316375a778d16f70a1a21e0be0 100755 --- a/ecmascript/ecma_string.h +++ b/ecmascript/ecma_string.h @@ -116,7 +116,7 @@ private: bool canBeCompress, MemSpaceType type = MemSpaceType::SHARED_OLD_SPACE, bool isConstantString = false, uint32_t idOffset = 0); static EcmaString *CreateFromUtf8CompressedSubString(const EcmaVM *vm, const JSHandle &string, - uint32_t offset, uint32_t utf8Len, MemSpaceType type = MemSpaceType::SEMI_SPACE); + uint32_t offset, uint32_t utf8Len, MemSpaceType type = MemSpaceType::SHARED_OLD_SPACE); static EcmaString *CreateUtf16StringFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len, MemSpaceType type = MemSpaceType::SHARED_OLD_SPACE); static EcmaString *CreateFromUtf16(const EcmaVM *vm, const uint16_t *utf16Data, uint32_t utf16Len, @@ -143,6 +143,8 @@ private: uint32_t length, bool compressed); static EcmaString *FastSubString(const EcmaVM *vm, const JSHandle &src, uint32_t start, uint32_t length); + static bool SubStringIsUtf8(const EcmaVM *vm, + const JSHandle &src, uint32_t start, uint32_t length); static EcmaString *GetSlicedString(const EcmaVM *vm, const JSHandle &src, uint32_t start, uint32_t length); static EcmaString *GetSubString(const EcmaVM *vm, @@ -1006,6 +1008,8 @@ public: } }; +// FlatStringInfo holds an EcmaString* instead of a JSHandle. If a GC occurs during its usage period, +// it may cause the pointer to become invalid, necessitating the pointer to be reset. class FlatStringInfo { public: FlatStringInfo(EcmaString *string, uint32_t startIndex, uint32_t length) : string_(string), @@ -1137,7 +1141,11 @@ public: { return EcmaString::FastSubString(vm, src, start, length); } - + static bool SubStringIsUtf8(const EcmaVM *vm, + const JSHandle &src, uint32_t start, uint32_t length) + { + return EcmaString::SubStringIsUtf8(vm, src, start, length); + } // get static EcmaString *GetSubString(const EcmaVM *vm, const JSHandle &src, uint32_t start, uint32_t length) diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 087701ab09568cb8d60bfda6044e32b9e5dbadcd..a035e7d6cf7cacabf967994a9753c819e4c6c679 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -16,7 +16,6 @@ #include "ecmascript/ecma_vm.h" #include "ecmascript/builtins/builtins_ark_tools.h" -#include "ecmascript/pgo_profiler/pgo_profiler_manager.h" #ifdef ARK_SUPPORT_INTL #include "ecmascript/builtins/builtins_collator.h" #include "ecmascript/builtins/builtins_date_time_format.h" @@ -122,6 +121,8 @@ void EcmaVM::PreFork() auto sHeap = SharedHeap::GetInstance(); sHeap->CompactHeapBeforeFork(thread_); sHeap->DisableParallelGC(thread_); + + Jit::GetInstance()->PreFork(); } void EcmaVM::PostFork() @@ -164,7 +165,7 @@ void EcmaVM::PostFork() EcmaVM::EcmaVM(JSRuntimeOptions options, EcmaParamConfiguration config) : nativeAreaAllocator_(std::make_unique()), - heapRegionAllocator_(std::make_unique()), + heapRegionAllocator_(std::make_unique(options)), chunk_(nativeAreaAllocator_.get()), ecmaParamConfiguration_(std::move(config)) { @@ -210,7 +211,6 @@ void EcmaVM::ResetPGOProfiler() PGOProfilerManager::GetInstance()->Reset(pgoProfiler_, isEnablePGOProfiler); thread_->SetPGOProfilerEnable(isEnablePGOProfiler); thread_->CheckOrSwitchPGOStubs(); - thread_->SetEnableForceIC(ecmascript::pgo::PGOProfilerManager::GetInstance()->IsEnableForceIC()); } } @@ -561,6 +561,35 @@ JSHandle EcmaVM::GetEcmaUncaughtException() const return exceptionHandle; } +#if ECMASCRIPT_ENABLE_COLLECTING_OPCODES +void EcmaVM::PrintCollectedByteCode() +{ + std::unordered_map bytecodeStatsMap_ = bytecodeStatsStack_.top(); + LOG_ECMA(ERROR) << "panda runtime stat:"; + static constexpr int nameRightAdjustment = 45; + static constexpr int numberRightAdjustment = 12; + LOG_ECMA(ERROR) << std::right << std::setw(nameRightAdjustment) << "Hotness Function ByteCode" + << std::setw(numberRightAdjustment) << "Count"; + LOG_ECMA(ERROR) << "============================================================" + << "========================================================="; + std::vector> bytecodeStatsVector; + for (auto& iter: bytecodeStatsMap_) { + bytecodeStatsVector.push_back( + std::make_pair(kungfu::GetEcmaOpcodeStr(static_cast(iter.first)), iter.second)); + } + std::sort(bytecodeStatsVector.begin(), bytecodeStatsVector.end(), + [](std::pair &a, std::pair &b) { + return a.second > b.second; + }); + for (size_t i = 0; i < bytecodeStatsVector.size(); ++i) { + LOG_ECMA(ERROR) << std::right << std::setw(nameRightAdjustment) << bytecodeStatsVector[i].first + << std::setw(numberRightAdjustment) << bytecodeStatsVector[i].second; + } + LOG_ECMA(ERROR) << "============================================================" + << "========================================================="; +} +#endif + void EcmaVM::PrintAOTSnapShotStats() { static constexpr int nameRightAdjustment = 30; @@ -790,6 +819,15 @@ void EcmaVM::TriggerConcurrentCallback(JSTaggedValue result, JSTaggedValue hint) } void *taskInfo = reinterpret_cast(thread_->GetTaskInfo()); + if (UNLIKELY(taskInfo == nullptr)) { + JSTaggedValue extraInfoValue = functionInfo->GetFunctionExtraInfo(); + if (!extraInfoValue.IsJSNativePointer()) { + LOG_ECMA(INFO) << "FunctionExtraInfo is not JSNativePointer"; + return; + } + JSHandle extraInfo(thread_, extraInfoValue); + taskInfo = extraInfo->GetData(); + } // clear the taskInfo when return, which can prevent the callback to get it thread_->SetTaskInfo(reinterpret_cast(nullptr)); auto localResultRef = JSNApiHelper::ToLocal(JSHandle(thread_, result)); diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index be597006a80b236419f5e8e695fc789a0c68875a..8ddb4329e9081096463bbd3ead9736ead58042d7 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -29,6 +29,7 @@ #include "ecmascript/napi/include/dfx_jsnapi.h" #include "ecmascript/napi/include/jsnapi.h" #include "ecmascript/taskpool/taskpool.h" +#include "libpandafile/bytecode_instruction-inl.h" namespace panda { class JSNApi; @@ -164,9 +165,6 @@ public: bool PUBLIC_API IsEnablePGOProfiler() const; bool PUBLIC_API IsEnableElementsKind() const; - bool PUBLIC_API IsEnableForceIC() const; - - void SetEnableForceIC(bool isEnableForceIC); bool Initialize(); void InitializeForJit(JitThread *thread); @@ -808,6 +806,20 @@ public: void PUBLIC_API PrintAOTSnapShotStats(); +#if ECMASCRIPT_ENABLE_COLLECTING_OPCODES + void SetBytecodeStatsStack(std::unordered_map &bytecodeStatsMap) + { + bytecodeStatsStack_.push(bytecodeStatsMap); + } + + std::stack>& GetBytecodeStatsStack() + { + return bytecodeStatsStack_; + } + + void PrintCollectedByteCode(); +#endif + protected: void PrintJSErrorInfo(const JSHandle &exceptionInfo) const; @@ -863,7 +875,7 @@ private: CString moduleName_; CList deregisterModuleList_; CMap mockModuleList_; - CMap hmsModuleList_; + std::map hmsModuleList_; CMap pkgNameList_; CMap>> pkgContextInfoList_; CMap pkgAliasList_; @@ -945,6 +957,10 @@ private: int updateThreadStateTransCount_ = 0; int stringTableLockCount_ = 0; #endif + +#if ECMASCRIPT_ENABLE_COLLECTING_OPCODES + std::stack> bytecodeStatsStack_; +#endif }; } // namespace ecmascript } // namespace panda diff --git a/ecmascript/element_accessor.h b/ecmascript/element_accessor.h index bc82bf78e9d763d1e0d7e669cd9293aec7affd66..867ab34487861c065661faf6b85a15e2094d6dd3 100644 --- a/ecmascript/element_accessor.h +++ b/ecmascript/element_accessor.h @@ -38,7 +38,6 @@ public: const JSHandle &value, ElementsKind kind); static bool IsDictionaryMode(JSHandle receiver); static bool IsDictionaryMode(JSObject *receiver); - static uint32_t GetElementsLength(JSHandle receiver); static uint32_t GetElementsLength(JSObject *receiver); diff --git a/ecmascript/extractortool/tests/BUILD.gn b/ecmascript/extractortool/tests/BUILD.gn index 0037c0335fcaa664c11fe91a197df5db1be47d34..8e898e3bca7bd3470a2868e94b8ca38251f3c2dc 100644 --- a/ecmascript/extractortool/tests/BUILD.gn +++ b/ecmascript/extractortool/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("ExtractorToolTest") { module_out_path = module_output_path diff --git a/ecmascript/global_dictionary.h b/ecmascript/global_dictionary.h index 8ca894ef4bb6346d5a5477c258a47ca29447f63f..749ebd7dc85f7cdeeeb0e676308dfe70b5337f7e 100644 --- a/ecmascript/global_dictionary.h +++ b/ecmascript/global_dictionary.h @@ -85,7 +85,12 @@ public: static bool inline CompKey(const std::pair &a, const std::pair &b); - DECL_DUMP() + void Dump(std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR; + void Dump() const DUMP_API_ATTR + { + Dump(std::cout); + } + void DumpForSnapshot(std::vector &vec) const; public: static constexpr int ENTRY_KEY_INDEX = 0; diff --git a/ecmascript/global_env_constants.cpp b/ecmascript/global_env_constants.cpp index c70ba948bc467f190e656763af141d0a544f24db..9891a55e2ba39182cbd50c742b29ed44837b170b 100644 --- a/ecmascript/global_env_constants.cpp +++ b/ecmascript/global_env_constants.cpp @@ -199,7 +199,7 @@ void GlobalEnvConstants::InitSharedRootsClasses(ObjectFactory *factory) SetConstant(ConstantIndex::TRANS_WITH_PROTO_HANDLER_CLASS_INDEX, factory->NewSEcmaReadOnlyHClass(hClass, TransWithProtoHandler::SIZE, JSType::TRANS_WITH_PROTO_HANDLER)); SetConstant(ConstantIndex::STORE_TS_HANDLER_CLASS_INDEX, - factory->NewSEcmaReadOnlyHClass(hClass, StoreTSHandler::SIZE, JSType::STORE_TS_HANDLER)); + factory->NewSEcmaReadOnlyHClass(hClass, StoreAOTHandler::SIZE, JSType::STORE_TS_HANDLER)); SetConstant(ConstantIndex::PROPERTY_BOX_CLASS_INDEX, factory->NewSEcmaReadOnlyHClass(hClass, PropertyBox::SIZE, JSType::PROPERTY_BOX)); SetConstant(ConstantIndex::PROGRAM_CLASS_INDEX, diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index d3e4400f743946df09d7538926a9606e3842246d..85267de9bdcd4ae41c98dbc08f1337715f2ad119 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -74,7 +74,7 @@ class ObjectFactory; V(JSTaggedValue, PrototypeHandlerClass, PROTOTYPE_HANDLER_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, TransitionHandlerClass, TRANSITION_HANDLER_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, TransWithProtoHandlerClass, TRANS_WITH_PROTO_HANDLER_CLASS_INDEX, ecma_roots_class) \ - V(JSTaggedValue, StoreTSHandlerClass, STORE_TS_HANDLER_CLASS_INDEX, ecma_roots_class) \ + V(JSTaggedValue, StoreAOTHandlerClass, STORE_TS_HANDLER_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, PropertyBoxClass, PROPERTY_BOX_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, ProgramClass, PROGRAM_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, ImportEntryClass, IMPORT_ENTRY_CLASS_INDEX, ecma_roots_class) \ @@ -289,6 +289,7 @@ class ObjectFactory; V(JSTaggedValue, ArraySome, ARRAY_SOME_INDEX, ecma_roots_builtins) \ V(JSTaggedValue, ArrayEvery, ARRAY_EVERY_INDEX, ecma_roots_builtins) \ V(JSTaggedValue, ArrayPop, ARRAY_POP_INDEX, ecma_roots_builtins) \ + V(JSTaggedValue, ArrayPush, ARRAY_PUSH_INDEX, ecma_roots_builtins) \ V(JSTaggedValue, ArraySlice, ARRAY_SLICE_INDEX, ecma_roots_builtins) \ V(JSTaggedValue, GloablDecodeURIComponent, GLOBAL_DECODE_URI_COMPONENT, ecma_roots_builtins) @@ -649,8 +650,6 @@ class ObjectFactory; V(JSTaggedValue, TreeSetIteratorPrototype, TREESET_ITERATOR_PROTOTYPE_INDEX, TreeSetIterator) \ V(JSTaggedValue, VectorFunction, VECTOR_FUNCTION_INDEX, VectorFunction) \ V(JSTaggedValue, VectorIteratorPrototype, VECTOR_ITERATOR_PROTOTYPE_INDEX, VectorIterator) \ - V(JSTaggedValue, BitVectorFunction, BITVECTOR_FUNCTION_INDEX, BitVectorFunction) \ - V(JSTaggedValue, BitVectorIteratorPrototype, BITVECTOR_ITERATOR_PROTOTYPE_INDEX, BitVectorIterator) \ V(JSTaggedValue, QueueIteratorPrototype, QUEUE_ITERATOR_PROTOTYPE_INDEX, QueueIterator) \ V(JSTaggedValue, PlainArrayIteratorPrototype, PLAIN_ARRAY_ITERATOR_PROTOTYPE_INDEX, PlainArrayIterator) \ V(JSTaggedValue, PlainArrayFunction, PLAIN_ARRAY_FUNCTION_INDEX, PlainArrayFunction) \ diff --git a/ecmascript/global_env_fields.h b/ecmascript/global_env_fields.h index 8fc9df6840fdbf349ef9d4feb5fd32ba5fc175be..c38c7ef704d0715dc23529eb8f2101b23562eaa3 100644 --- a/ecmascript/global_env_fields.h +++ b/ecmascript/global_env_fields.h @@ -135,6 +135,8 @@ V(JSTaggedValue, BuiltinsWeakRefFunction, BUILTINS_WEAK_REF_FUNCTION_INDEX) \ V(JSTaggedValue, BuiltinsFinalizationRegistryFunction, \ BUILTINS_FINALIZATION_REGISTRY_FUNCTION_INDEX) \ + V(JSTaggedValue, BitVectorPrototype, BITVECTOR_PROTOTYPE_INDEX) \ + V(JSTaggedValue, BitVectorFunction, BITVECTOR_FUNCTION_INDEX) \ V(JSTaggedValue, MapPrototype, MAP_PROTOTYPE_INDEX) \ V(JSTaggedValue, MathFunction, MATH_FUNCTION_INDEX) \ V(JSTaggedValue, MathFunctionClass, MATH_FUNCTION_CLASS_INDEX) \ @@ -167,6 +169,7 @@ V(JSTaggedValue, StringIteratorClass, STRING_ITERATOR_CLASS_INDEX) \ V(JSTaggedValue, AsyncFromSyncIterator, ASYNC_FROM_SYNC_ITERATOR_INDEX) \ V(JSTaggedValue, MapIteratorPrototype, MAP_ITERATOR_PROTOTYPE_INDEX) \ + V(JSTaggedValue, BitVectorIteratorPrototype, BITVECTOR_ITERATOR_PROTOTYPE_INDEX) \ V(JSTaggedValue, SharedMapIteratorPrototype, SHARED_MAP_ITERATOR_PROTOTYPE_INDEX) \ V(JSTaggedValue, SetIteratorPrototype, SET_ITERATOR_PROTOTYPE_INDEX) \ V(JSTaggedValue, SharedSetIteratorPrototype, SHARED_SET_ITERATOR_PROTOTYPE_INDEX) \ diff --git a/ecmascript/ic/ic_binary_op.h b/ecmascript/ic/ic_binary_op.h deleted file mode 100644 index c204659a3adec5377a28f44fd7394aa0746cc5eb..0000000000000000000000000000000000000000 --- a/ecmascript/ic/ic_binary_op.h +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ECMASCRIPT_IC_IC_BINARY_OP_H_ -#define ECMASCRIPT_IC_IC_BINARY_OP_H_ - -#include "ecmascript/ic/profile_type_info.h" -#include "ecmascript/interpreter/slow_runtime_stub.h" -#include "ecmascript/js_tagged_value.h" -#include "ecmascript/property_attributes.h" -#include "ecmascript/runtime_call_id.h" - -namespace panda::ecmascript { -enum class BinaryType : uint8_t { - NUMBER, - NUMBER_GEN, - STRING, - STRING_GEN, - GENERIC, -}; - -class ICBinaryOP { -public: - static inline JSTaggedValue AddWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, AddWithTSType); - BinaryType addType = static_cast(argType.GetInt()); - switch (addType) { - // Support cases, such as: int + double, int + int, double + double - case BinaryType::NUMBER: { - double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble(); - double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble(); - double ret = a0Double + a1Double; - return JSTaggedValue(ret); - } - // Support cases, such as: number + null, undefined + null, boolean + number, etc. - case BinaryType::NUMBER_GEN: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - JSHandle primitiveA0(thread, JSTaggedValue::ToPrimitive(thread, leftValue)); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle primitiveA1(thread, JSTaggedValue::ToPrimitive(thread, rightValue)); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - - JSTaggedNumber taggedValueA0 = JSTaggedValue::ToNumber(thread, primitiveA0); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSTaggedNumber taggedValueA1 = JSTaggedValue::ToNumber(thread, primitiveA1); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - double a0Double = taggedValueA0.GetNumber(); - double a1Double = taggedValueA1.GetNumber(); - return JSTaggedValue(a0Double + a1Double); - } - // Support case: string + string. - case BinaryType::STRING: { - JSHandle stringA0 = JSHandle(JSHandle(thread, left)); - JSHandle stringA1 = JSHandle(JSHandle(thread, right)); - EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return JSTaggedValue(ret); - } - // Support cases, such as: string + null, string + object, string + boolean, string + number, etc. - case BinaryType::STRING_GEN: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - if (left.IsString()) { - JSHandle stringA0 = JSHandle(leftValue); - JSHandle stringA1 = JSTaggedValue::ToString(thread, rightValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return JSTaggedValue(ret); - } else { - JSHandle stringA0 = JSTaggedValue::ToString(thread, leftValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle stringA1 = JSHandle(rightValue); - EcmaString *ret = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return JSTaggedValue(ret); - } - } - // Some special cases, such as: object + undefined, object + boolean, etc. - case BinaryType::GENERIC: { - JSTaggedValue res = SlowRuntimeStub::Add2(thread, left, right); - return res; - } - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - } - - static inline JSTaggedValue SubWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, SubWithTSType); - BinaryType subType = static_cast(argType.GetInt()); - switch (subType) { - // Support int or number - case BinaryType::NUMBER: { - double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble(); - double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble(); - double ret = a0Double - a1Double; - return JSTaggedValue(ret); - } - // Support cases, such as: string like '2333', boolean, null - case BinaryType::GENERIC: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - JSTaggedNumber number0 = JSTaggedValue::ToNumber(thread, leftValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSTaggedNumber number1 = JSTaggedValue::ToNumber(thread, rightValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - auto ret = number0 - number1; - return JSTaggedValue(ret); - } - case BinaryType::NUMBER_GEN: - case BinaryType::STRING: - case BinaryType::STRING_GEN: - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - } - static inline JSTaggedValue MulWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, MulWithTSType); - BinaryType mulType = static_cast(argType.GetInt()); - switch (mulType) { - // Support int or number - case BinaryType::NUMBER: { - return JSTaggedValue(left.GetNumber() * right.GetNumber()); - } - // Support cases, such as: string like '2333', boolean, null - case BinaryType::GENERIC: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - // 6. Let lnum be ToNumber(leftValue). - JSTaggedNumber primitiveA = JSTaggedValue::ToNumber(thread, leftValue); - // 7. ReturnIfAbrupt(lnum). - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - // 8. Let rnum be ToNumber(rightValue). - JSTaggedNumber primitiveB = JSTaggedValue::ToNumber(thread, rightValue); - // 9. ReturnIfAbrupt(rnum). - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - // 12.6.3.1 Applying the * Operator - return primitiveA * primitiveB; - } - case BinaryType::NUMBER_GEN: - case BinaryType::STRING: - case BinaryType::STRING_GEN: - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - } - - static inline JSTaggedValue DivWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, DivWithTSType); - BinaryType divType = static_cast(argType.GetInt()); - switch (divType) { - // Support int or number - case BinaryType::NUMBER: { - double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble(); - double dRight = right.IsInt() ? right.GetInt() : right.GetDouble(); - if (UNLIKELY(dRight == 0.0)) { - if (dLeft == 0.0 || std::isnan(dLeft)) { - return JSTaggedValue(base::NAN_VALUE); - } - uint64_t flagBit = ((base::bit_cast(dLeft)) ^ (base::bit_cast(dRight))) & - base::DOUBLE_SIGN_MASK; - return JSTaggedValue(base::bit_cast( - flagBit ^ (base::bit_cast(base::POSITIVE_INFINITY)))); - } - return JSTaggedValue(dLeft / dRight); - } - // Support special cases, such as: string like '2333', boolean, null - case BinaryType::GENERIC: { - auto res = SlowRuntimeStub::Div2(thread, left, right); - return res; - } - case BinaryType::NUMBER_GEN: - case BinaryType::STRING: - case BinaryType::STRING_GEN: - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - } - - static inline JSTaggedValue ModWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, ModWithTSType); - BinaryType modType = static_cast(argType.GetInt()); - switch (modType) { - // Support int or number - case BinaryType::NUMBER: { - double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble(); - double dRight = right.IsInt() ? right.GetInt() : right.GetDouble(); - if (dRight == 0.0 || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) { - return JSTaggedValue(base::NAN_VALUE); - } - if (dLeft == 0.0 || std::isinf(dRight)) { - return JSTaggedValue(dLeft); - } - return JSTaggedValue(std::fmod(dLeft, dRight)); - } - // Support special cases, such as: string like '2333', boolean, null - case BinaryType::GENERIC: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - JSTaggedNumber leftNumber = JSTaggedValue::ToNumber(thread, leftValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - double dLeft = leftNumber.GetNumber(); - JSTaggedNumber rightNumber = JSTaggedValue::ToNumber(thread, rightValue); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - double dRight = rightNumber.GetNumber(); - // 12.6.3.3 Applying the % Operator - if ((dRight == 0.0) || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) { - return JSTaggedValue(base::NAN_VALUE); - } - if ((dLeft == 0.0) || std::isinf(dRight)) { - return JSTaggedValue(dLeft); - } - return JSTaggedValue(std::fmod(dLeft, dRight)); - } - case BinaryType::NUMBER_GEN: - case BinaryType::STRING: - case BinaryType::STRING_GEN: - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - } - - static inline void GetBitOPDate(JSThread *thread, JSTaggedValue left, JSTaggedValue right, - int32_t &opNumber0, int32_t &opNumber1, BinaryType opType) - { - INTERPRETER_TRACE(thread, GetBitOPDate); - switch (opType) { - case BinaryType::NUMBER: { - opNumber0 = - left.IsInt() ? left.GetInt() : - base::NumberHelper::DoubleToInt(left.GetDouble(), base::INT32_BITS); - opNumber1 = - right.IsInt() ? right.GetInt() : - base::NumberHelper::DoubleToInt(right.GetDouble(), base::INT32_BITS); - break; - } - // Support special cases, such as: string like '2333', boolean, null - case BinaryType::GENERIC: { - JSHandle leftValue(thread, left); - JSHandle rightValue(thread, right); - JSTaggedValue taggedNumber0 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, - leftValue.GetTaggedValue()); - JSTaggedValue taggedNumber1 = SlowRuntimeStub::ToJSTaggedValueWithUint32(thread, - rightValue.GetTaggedValue()); - opNumber0 = taggedNumber0.GetInt(); - opNumber1 = taggedNumber1.GetInt(); - break; - } - case BinaryType::NUMBER_GEN: - case BinaryType::STRING: - case BinaryType::STRING_GEN: - default: { - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - } - return; - } - - static inline JSTaggedValue ShlWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, ShlWithTSType); - BinaryType shlType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, shlType); - uint32_t shift = - static_cast(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers) - using unsigned_type = std::make_unsigned_t; - auto ret = - static_cast(static_cast(opNumber0) << shift); // NOLINT(hicpp-signed-bitwise) - return JSTaggedValue(ret); - } - - static inline JSTaggedValue ShrWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, ShrWithTSType); - BinaryType shrType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, shrType); - uint32_t shift = - static_cast(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers) - auto ret = static_cast(opNumber0 >> shift); // NOLINT(hicpp-signed-bitwise) - return JSTaggedValue(ret); - } - - static inline JSTaggedValue AshrWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, AshrWithTSType); - BinaryType ashrType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, ashrType); - uint32_t shift = - static_cast(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers) - using unsigned_type = std::make_unsigned_t; - auto ret = - static_cast(static_cast(opNumber0) >> shift); // NOLINT(hicpp-signed-bitwise) - return JSTaggedValue(ret); - } - - static inline JSTaggedValue AndWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, AndWithTSType); - BinaryType andType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, andType); - // NOLINT(hicpp-signed-bitwise) - auto ret = static_cast(opNumber0) & static_cast(opNumber1); - return JSTaggedValue(ret); - } - - static inline JSTaggedValue OrWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, OrWithTSType); - BinaryType orType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, orType); - // NOLINT(hicpp-signed-bitwise) - auto ret = static_cast(opNumber0) | static_cast(opNumber1); - return JSTaggedValue(ret); - } - - static inline JSTaggedValue XorWithTSType(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, JSTaggedValue argType) - { - INTERPRETER_TRACE(thread, XorWithTSType); - BinaryType xorType = static_cast(argType.GetInt()); - int32_t opNumber0 = 0; - int32_t opNumber1 = 0; - GetBitOPDate(thread, left, right, opNumber0, opNumber1, xorType); - // NOLINT(hicpp-signed-bitwise) - auto ret = static_cast(opNumber0) ^ static_cast(opNumber1); - return JSTaggedValue(ret); - } -}; -} // namespace panda::ecmascript - -#endif // ECMASCRIPT_IC_IC_BINARY_OP_H_ diff --git a/ecmascript/ic/ic_compare_op.cpp b/ecmascript/ic/ic_compare_op.cpp deleted file mode 100644 index a8a3de5a33a5a5d49166f6f0f7a6fd7ecd17b8dd..0000000000000000000000000000000000000000 --- a/ecmascript/ic/ic_compare_op.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ecmascript/ic/ic_compare_op.h" - -#include "ecmascript/runtime_call_id.h" - -namespace panda::ecmascript { -JSTaggedValue CompareOp::EqualWithIC(JSThread* thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, EqualWithIC); - double leftDouble = 0; - double rightDouble = 0; - JSTaggedValue ret = JSTaggedValue::False(); - switch (operationType) { - case CompareOpType::NUMBER_NUMBER: { - leftDouble = left.GetNumber(); - rightDouble = right.GetNumber(); - ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble)); - break; - } - case CompareOpType::STRING_NUMBER: { - JSTaggedValue temp = left; - left = right; - right = temp; - [[fallthrough]]; - } - case CompareOpType::NUMBER_STRING: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - rightDouble = JSTaggedValue::ToNumber(thread, rightHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - leftDouble = leftHandle.GetTaggedValue().GetNumber(); - ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble)); - break; - } - case CompareOpType::BOOLEAN_NUMBER: { - JSTaggedValue temp = left; - left = right; - right = temp; - [[fallthrough]]; - } - case CompareOpType::NUMBER_BOOLEAN: { - leftDouble = left.GetNumber(); - if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble)); - break; - } - case CompareOpType::OBJ_NUMBER: { - JSTaggedValue temp = left; - left = right; - right = temp; - [[fallthrough]]; - } - case CompareOpType::NUMBER_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - if (rightPrimitive->IsNumber()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_NUMBER); - } else if (rightPrimitive->IsString()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING); - } else if (rightPrimitive->IsBoolean()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } - break; - } - case CompareOpType::STRING_STRING: { - bool result = EcmaStringAccessor::StringsAreEqual(static_cast(left.GetTaggedObject()), - static_cast(right.GetTaggedObject())); - ret = result ? JSTaggedValue::True() : JSTaggedValue::False(); - break; - } - case CompareOpType::BOOLEAN_STRING: { - JSTaggedValue temp = left; - left = right; - right = temp; - [[fallthrough]]; - } - case CompareOpType::STRING_BOOLEAN: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - leftDouble = JSTaggedValue::ToNumber(thread, leftHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - if (rightHandle.GetTaggedValue().GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble)); - break; - } - case CompareOpType::OBJ_STRING: { - JSTaggedValue temp = left; - left = right; - right = temp; - [[fallthrough]]; - } - case CompareOpType::STRING_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - if (rightPrimitive->IsNumber()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING); - } else if (rightPrimitive->IsString()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::STRING_STRING); - } else if (rightPrimitive->IsBoolean()) { - ret = EqualWithIC(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } - break; - } - case CompareOpType::BOOLEAN_BOOLEAN: { - if (left.GetRawData() == JSTaggedValue::VALUE_TRUE) { - leftDouble = 1; - } - if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble)); - break; - } - case CompareOpType::OBJ_BOOLEAN: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - if (leftPrimitive->IsNumber()) { - ret = EqualWithIC(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } else if (leftPrimitive->IsString()) { - ret = EqualWithIC(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } else if (leftPrimitive->IsBoolean()) { - ret = EqualWithIC(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN); - } - break; - } - case CompareOpType::BOOLEAN_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); - if (rightPrimitive->IsNumber()) { - ret = EqualWithIC(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } else if (rightPrimitive->IsString()) { - ret = EqualWithIC(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } else if (rightPrimitive->IsBoolean()) { - ret = EqualWithIC(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN); - } - break; - } - case CompareOpType::OBJ_OBJ: { - // if same type, must call Type::StrictEqual() - JSType xType = left.GetTaggedObject()->GetClass()->GetObjectType(); - JSType yType = right.GetTaggedObject()->GetClass()->GetObjectType(); - bool resultObj = false; - if (xType == yType) { - resultObj = JSTaggedValue::StrictEqual(thread, JSHandle(thread, left), - JSHandle(thread, right)); - } - ret = resultObj ? JSTaggedValue::True() : JSTaggedValue::False(); - break; - } - case CompareOpType::SYMBOL_SYMBOL: { - ret = left == right ? JSTaggedValue::True() : JSTaggedValue::False(); - break; - } - case CompareOpType::NULL_NULL: - case CompareOpType::NULL_UNDEFINED: - case CompareOpType::UNDEFINED_UNDEFINED: - case CompareOpType::UNDEFINED_NULL: { - ret = JSTaggedValue::True(); - break; - } - default: - ret = JSTaggedValue::False(); - } - return ret; -} - -JSTaggedValue CompareOp::NotEqualWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, NotEqualWithIC); - JSTaggedValue res = EqualWithIC(thread, left, right, operationType); - return res.IsTrue() ? JSTaggedValue::False() : JSTaggedValue::True(); -} - -ComparisonResult CompareOp::Compare(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, Compare); - double leftDouble = 0; - double rightDouble = 0; - ComparisonResult ret = ComparisonResult::UNDEFINED; - switch (operationType) { - case CompareOpType::NUMBER_NUMBER: { - leftDouble = left.IsInt() ? static_cast(left.GetInt()) : left.GetDouble(); - rightDouble = right.IsInt() ? static_cast(right.GetInt()) : right.GetDouble(); - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - case CompareOpType::NUMBER_STRING: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - - rightDouble = JSTaggedValue::ToNumber(thread, rightHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - leftDouble = leftHandle.GetTaggedValue().GetNumber(); - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - case CompareOpType::NUMBER_BOOLEAN: { - leftDouble = left.GetNumber(); - if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - case CompareOpType::NUMBER_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (rightPrimitive->IsNumber()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_NUMBER); - } else if (rightPrimitive->IsString()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING); - } else if (rightPrimitive->IsBoolean()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } - break; - } - case CompareOpType::STRING_STRING: { - JSHandle xHandle(thread, left); - JSHandle yHandle(thread, right); - int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle); - if (result < 0) { - ret = ComparisonResult::LESS; - } else if (result == 0) { - ret = ComparisonResult::EQUAL; - } else { - ret = ComparisonResult::GREAT; - } - break; - } - case CompareOpType::STRING_NUMBER: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - leftDouble = JSTaggedValue::ToNumber(thread, leftHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - rightDouble = rightHandle.GetTaggedValue().GetNumber(); - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - case CompareOpType::STRING_BOOLEAN: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - leftDouble = JSTaggedValue::ToNumber(thread, leftHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (rightHandle.GetTaggedValue().GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - case CompareOpType::STRING_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (rightPrimitive->IsNumber()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING); - } else if (rightPrimitive->IsString()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::STRING_STRING); - } else if (rightPrimitive->IsBoolean()) { - ret = Compare(thread, leftHandle.GetTaggedValue(), - rightPrimitive.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } - break; - } - case CompareOpType::BOOLEAN_BOOLEAN: { - if (left.GetRawData() == JSTaggedValue::VALUE_TRUE) { - leftDouble = 1; - } - if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) { - rightDouble = 1; - } - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - - case CompareOpType::BOOLEAN_NUMBER: { - if (left.GetRawData() == JSTaggedValue::VALUE_TRUE) { - leftDouble = 1; - } - rightDouble = right.GetNumber(); - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - - case CompareOpType::BOOLEAN_STRING: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - rightDouble = JSTaggedValue::ToNumber(thread, rightHandle).GetNumber(); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (leftHandle.GetTaggedValue().GetRawData() == JSTaggedValue::VALUE_TRUE) { - leftDouble = 1; - } - ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble); - break; - } - - case CompareOpType::BOOLEAN_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (rightPrimitive->IsNumber()) { - ret = Compare(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } else if (rightPrimitive->IsString()) { - ret = Compare(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } else if (rightPrimitive->IsBoolean()) { - ret = Compare(thread, rightPrimitive.GetTaggedValue(), - leftHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN); - } - break; - } - case CompareOpType::OBJ_OBJ: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - ret = JSTaggedValue::Compare(thread, leftHandle, rightHandle); - break; - } - case CompareOpType::OBJ_NUMBER: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (leftPrimitive->IsNumber()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::NUMBER_NUMBER); - } else if (leftPrimitive->IsString()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::STRING_NUMBER); - } else if (leftPrimitive->IsBoolean()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_NUMBER); - } - break; - } - case CompareOpType::OBJ_STRING: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (leftPrimitive->IsNumber()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::NUMBER_STRING); - } else if (leftPrimitive->IsString()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::STRING_STRING); - } else if (leftPrimitive->IsBoolean()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_STRING); - } - break; - } - case CompareOpType::OBJ_BOOLEAN: { - JSHandle leftHandle(thread, left); - JSHandle rightHandle(thread, right); - JSHandle leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - if (leftPrimitive->IsNumber()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN); - } else if (leftPrimitive->IsString()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - } else if (leftPrimitive->IsBoolean()) { - ret = Compare(thread, leftPrimitive.GetTaggedValue(), - rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN); - } - break; - } - default: - ret = ComparisonResult::UNDEFINED; - } - return ret; -} - -JSTaggedValue CompareOp::LessWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, LessWithIC); - bool ret = CompareOp::Compare(thread, left, right, operationType) == ComparisonResult::LESS; - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return (ret ? JSTaggedValue::True() : JSTaggedValue::False()); -} - -JSTaggedValue CompareOp::LessEqWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, LessEqWithIC); - bool ret = CompareOp::Compare(thread, left, right, operationType) <= ComparisonResult::EQUAL; - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return (ret ? JSTaggedValue::True() : JSTaggedValue::False()); -} - -JSTaggedValue CompareOp::GreaterWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, GreaterWithIC); - bool ret = CompareOp::Compare(thread, left, right, operationType) == ComparisonResult::GREAT; - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return (ret ? JSTaggedValue::True() : JSTaggedValue::False()); -} - -JSTaggedValue CompareOp::GreaterEqWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType) -{ - INTERPRETER_TRACE(thread, GreaterEqWithIC); - ComparisonResult comparison = CompareOp::Compare(thread, left, right, operationType); - bool ret = (comparison == ComparisonResult::GREAT) || (comparison == ComparisonResult::EQUAL); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - return (ret ? JSTaggedValue::True() : JSTaggedValue::False()); -} -} // namespace panda::ecmascript diff --git a/ecmascript/ic/ic_compare_op.h b/ecmascript/ic/ic_compare_op.h deleted file mode 100644 index aacff9d7f7df4b01f6f6519878c91ebd793d6f41..0000000000000000000000000000000000000000 --- a/ecmascript/ic/ic_compare_op.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2021-2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ECMASCRIPT_IC_IC_COMPARE_OP_H -#define ECMASCRIPT_IC_IC_COMPARE_OP_H - -#include "ecmascript/js_function.h" -#include "ecmascript/js_thread.h" -#include "ecmascript/object_factory.h" - -namespace panda::ecmascript { -enum class CompareOpType { - NUMBER_NUMBER, - NUMBER_STRING, - NUMBER_BOOLEAN, - NUMBER_OBJ, - STRING_STRING, - STRING_NUMBER, - STRING_BOOLEAN, - STRING_OBJ, - BOOLEAN_BOOLEAN, - BOOLEAN_NUMBER, - BOOLEAN_STRING, - BOOLEAN_OBJ, - OBJ_OBJ, - OBJ_NUMBER, - OBJ_STRING, - OBJ_BOOLEAN, - SYMBOL_SYMBOL, - NULL_NULL, - NULL_UNDEFINED, - UNDEFINED_UNDEFINED, - UNDEFINED_NULL, - UNDEFINED_BLLEAN, - OTHER, -}; - -class CompareOp { -public: - - CompareOp() = default; - ~CompareOp() = default; - - static JSTaggedValue EqualWithIC(JSThread* thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static JSTaggedValue NotEqualWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static ComparisonResult Compare(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static JSTaggedValue LessWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static JSTaggedValue LessEqWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static JSTaggedValue GreaterWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); - - static JSTaggedValue GreaterEqWithIC(JSThread *thread, JSTaggedValue left, - JSTaggedValue right, CompareOpType operationType); -}; -} // namespace panda::ecmascript -#endif // ECMASCRIPT_IC_IC_COMPARE_OP_H \ No newline at end of file diff --git a/ecmascript/ic/ic_handler.cpp b/ecmascript/ic/ic_handler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bbbd1551109a0c361ea636e9c57b8222e7ad5220 --- /dev/null +++ b/ecmascript/ic/ic_handler.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/ic/ic_handler.h" +#include "ecmascript/global_env_constants-inl.h" + +namespace panda::ecmascript { + +JSHandle LoadHandler::LoadProperty(const JSThread *thread, const ObjectOperator &op) +{ + uint64_t handler = 0; + ASSERT(!op.IsElement()); + if (!op.IsFound()) { + KindBit::Set(HandlerKind::NON_EXIST, &handler); + return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); + } + ASSERT(op.IsFastMode()); + + JSTaggedValue val = op.GetValue(); + if (val.IsPropertyBox()) { + return JSHandle(thread, val); + } + bool hasAccessor = op.IsAccessorDescriptor(); + AccessorBit::Set(hasAccessor, &handler); + + if (!hasAccessor) { + JSHandle receiver = op.GetReceiver(); + if (receiver->IsString()) { + JSTaggedValue lenKey = thread->GlobalConstants()->GetLengthString(); + JSHandle key = op.GetKey(); + EcmaString *proKey = key->IsString() ? EcmaString::Cast(key->GetTaggedObject()) : nullptr; + if (EcmaStringAccessor::StringsAreEqual(proKey, EcmaString::Cast(lenKey.GetTaggedObject()))) { + KindBit::Set(HandlerKind::STRING_LENGTH, &handler); + } else { + KindBit::Set(HandlerKind::STRING, &handler); + } + } else if (receiver->IsNumber()) { + KindBit::Set(HandlerKind::NUMBER, &handler); + } else { + KindBit::Set(HandlerKind::FIELD, &handler); + } + } + + if (op.IsInlinedProps()) { + InlinedPropsBit::Set(true, &handler); + JSHandle holder = JSHandle::Cast(op.GetHolder()); + auto index = holder->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex()); + OffsetBit::Set(index, &handler); + AttrIndexBit::Set(op.GetIndex(), &handler); + RepresentationBit::Set(op.GetRepresentation(), &handler); + return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); + } + if (op.IsFastMode()) { + JSHandle holder = JSHandle::Cast(op.GetHolder()); + uint32_t inlinePropNum = holder->GetJSHClass()->GetInlinedProperties(); + AttrIndexBit::Set(op.GetIndex() + inlinePropNum, &handler); + OffsetBit::Set(op.GetIndex(), &handler); + RepresentationBit::Set(Representation::TAGGED, &handler); + return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); + } + LOG_ECMA(FATAL) << "this branch is unreachable"; + UNREACHABLE(); +} + +JSHandle LoadHandler::LoadElement(const JSThread *thread, const ObjectOperator &op) +{ + uint64_t handler = 0; + KindBit::Set(HandlerKind::ELEMENT, &handler); + // To avoid logical errors and Deopt, temporarily skipping PGO Profiling. + // logical errors: + // When accessing an element of an object, AOT does not have a chain-climbing operation, + // so if the element is on a prototype, it will not be able to get the correct element. + // deopt: + // Currently there is no way to save the type of the key in pgo file, even if the type of the key + // is string, it will be treated as a number type by the AOT, leading to deopt at runtime. + if (op.GetReceiver() != op.GetHolder() || op.KeyFromStringType()) { + NeedSkipInPGODumpBit::Set(true, &handler); + } + if (op.GetReceiver()->IsJSArray()) { + IsJSArrayBit::Set(true, &handler); + } + return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); +} + +JSHandle StoreHandler::StoreProperty(const JSThread *thread, const ObjectOperator &op) +{ + uint64_t handler = 0; + JSHandle receiver = JSHandle::Cast(op.GetReceiver()); + SFieldTypeBitSet(op, receiver, &handler); + if (op.IsElement()) { + SOutOfBoundsBit::Set(op.GetElementOutOfBounds(), &handler); + return StoreElement(thread, op.GetReceiver(), handler); + } + JSTaggedValue val = op.GetValue(); + if (val.IsPropertyBox()) { + return JSHandle(thread, val); + } + bool hasSetter = op.IsAccessorDescriptor(); + AccessorBit::Set(hasSetter, &handler); + if (!hasSetter) { + SKindBit::Set(StoreHandlerKind::S_FIELD, &handler); + } + if (op.IsInlinedProps()) { + InlinedPropsBit::Set(true, &handler); + uint32_t index = 0; + if (!hasSetter) { + index = receiver->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex()); + } else { + JSHandle holder = JSHandle::Cast(op.GetHolder()); + index = holder->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex()); + } + AttrIndexBit::Set(op.GetIndex(), &handler); + OffsetBit::Set(index, &handler); + RepresentationBit::Set(op.GetRepresentation(), &handler); + return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); + } + ASSERT(op.IsFastMode()); + uint32_t inlinePropNum = receiver->GetJSHClass()->GetInlinedProperties(); + AttrIndexBit::Set(op.GetIndex() + inlinePropNum, &handler); + OffsetBit::Set(op.GetIndex(), &handler); + RepresentationBit::Set(Representation::TAGGED, &handler); + return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); +} + +JSHandle TransitionHandler::StoreTransition(const JSThread *thread, const ObjectOperator &op) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handler = factory->NewTransitionHandler(); + JSHandle handlerInfo = StoreHandler::StoreProperty(thread, op); + handler->SetHandlerInfo(thread, handlerInfo); + auto hclass = JSObject::Cast(op.GetReceiver()->GetTaggedObject())->GetJSHClass(); + handler->SetTransitionHClass(thread, JSTaggedValue(hclass)); + return JSHandle::Cast(handler); +} + +JSHandle PrototypeHandler::LoadPrototype(const JSThread *thread, const ObjectOperator &op, + const JSHandle &hclass) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handlerInfo = LoadHandler::LoadProperty(thread, op); + JSHandle handler = factory->NewPrototypeHandler(); + handler->SetHandlerInfo(thread, handlerInfo); + if (op.IsFound()) { + handler->SetHolder(thread, op.GetHolder()); + } + if (op.IsAccessorDescriptor()) { + JSTaggedValue result = op.GetValue(); + if (result.IsPropertyBox()) { + result = PropertyBox::Cast(result.GetTaggedObject())->GetValue(); + } + AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject()); + if (!accessor->IsInternal()) { + JSTaggedValue getter = accessor->GetGetter(); + if (!getter.IsUndefined()) { + JSHandle func(thread, getter); + uint32_t methodOffset = Method::Cast(func->GetMethod())->GetMethodId().GetOffset(); + handler->SetAccessorMethodId(methodOffset); + handler->SetAccessorJSFunction(thread, getter); + } + } + } + // ShareToLocal is prohibited + if (!hclass->IsJSShared()) { + auto result = JSHClass::EnableProtoChangeMarker(thread, hclass); + handler->SetProtoCell(thread, result); + } + return JSHandle::Cast(handler); +} + +JSHandle PrototypeHandler::StorePrototype(const JSThread *thread, const ObjectOperator &op, + const JSHandle &hclass) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handler = factory->NewPrototypeHandler(); + JSHandle handlerInfo = StoreHandler::StoreProperty(thread, op); + handler->SetHandlerInfo(thread, handlerInfo); + handler->SetHolder(thread, op.GetHolder()); + if (op.IsAccessorDescriptor()) { + JSTaggedValue result = op.GetValue(); + if (result.IsPropertyBox()) { + result = PropertyBox::Cast(result.GetTaggedObject())->GetValue(); + } + AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject()); + if (!accessor->IsInternal() && accessor->HasSetter()) { + JSTaggedValue setter = accessor->GetSetter(); + JSHandle func(thread, setter); + handler->SetAccessorMethodId( + Method::Cast(func->GetMethod())->GetMethodId().GetOffset()); + handler->SetAccessorJSFunction(thread, setter); + } + } + // ShareToLocal is prohibited + if (!hclass->IsJSShared()) { + auto result = JSHClass::EnableProtoChangeMarker(thread, hclass); + handler->SetProtoCell(thread, result); + } + return JSHandle::Cast(handler); +} + +JSHandle TransWithProtoHandler::StoreTransition(const JSThread *thread, const ObjectOperator &op, + const JSHandle &hclass) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle handler = factory->NewTransWithProtoHandler(); + JSHandle handlerInfo = StoreHandler::StoreProperty(thread, op); + handler->SetHandlerInfo(thread, handlerInfo); + auto result = JSHClass::EnableProtoChangeMarker(thread, hclass); + handler->SetProtoCell(thread, result); + handler->SetTransitionHClass(thread, hclass.GetTaggedValue()); + + return JSHandle::Cast(handler); +} + +void HandlerBase::PrintLoadHandler([[maybe_unused]] uint64_t handler, [[maybe_unused]] std::ostream& os) +{ +#if ECMASCRIPT_ENABLE_TRACE_IC + HandlerKind kind = GetKind(handler); + os << "kind = "; + switch (kind) { + case HandlerKind::NONE: + os << "NONE" + << ", is InlinedPropsBit = " + << InlinedPropsBit::Get(handler) + << ", is AccessorBit = " + << AccessorBit::Get(handler) + << ", OffsetBit = " + << OffsetBit::Get(handler) + << ", AttrIndexBit = " + << AttrIndexBit::Get(handler); + break; + case HandlerKind::FIELD: + os << "FIELD" + << ", is InlinedPropsBit = " + << InlinedPropsBit::Get(handler) + << ", is AccessorBit = " + << AccessorBit::Get(handler) + << ", OffsetBit = " + << OffsetBit::Get(handler) + << ", AttrIndexBit = " + << AttrIndexBit::Get(handler); + break; + case HandlerKind::ELEMENT: + os << "ELEMENT" + << ", is JSArray = " + << IsJSArrayBit::Get(handler); + break; + case HandlerKind::DICTIONARY: + os << "DICTIONARY"; + break; + case HandlerKind::STRING: + os << "STRING"; + break; + case HandlerKind::STRING_LENGTH: + os << "STRING_LENGTH"; + break; + case HandlerKind::TYPED_ARRAY: + os << "TYPED_ARRAY," + << "is OnHeap = " + << IsOnHeapBit::Get(handler); + break; + case HandlerKind::NUMBER: + os << "NUMBER"; + break; + case HandlerKind::NON_EXIST: + os << "NON_EXIST"; + break; + default: + UNREACHABLE(); + } + os << std::endl; +#endif +} + +void HandlerBase::PrintStoreHandler([[maybe_unused]] uint64_t handler, [[maybe_unused]] std::ostream& os) +{ +#if ECMASCRIPT_ENABLE_TRACE_IC + StoreHandlerKind kind = static_cast(GetKind(handler)); + os << "kind = "; + switch (kind) { + case StoreHandlerKind::S_NONE: + os << "NONE" + << ", is InlinedPropsBit = " + << InlinedPropsBit::Get(handler) + << ", is AccessorBit = " + << AccessorBit::Get(handler) + << ", OffsetBit = " + << OffsetBit::Get(handler) + << ", AttrIndexBit = " + << AttrIndexBit::Get(handler) + << ", SFieldTypeBit = " + << static_cast(SFieldTypeBit::Get(handler)); + break; + case StoreHandlerKind::S_FIELD: + os << "S_FIELD" + << ", is InlinedPropsBit = " + << InlinedPropsBit::Get(handler) + << ", is AccessorBit = " + << AccessorBit::Get(handler) + << ", OffsetBit = " + << OffsetBit::Get(handler) + << ", AttrIndexBit = " + << AttrIndexBit::Get(handler) + << ", SFieldTypeBit = " + << static_cast(SFieldTypeBit::Get(handler)); + break; + case StoreHandlerKind::S_ELEMENT: + os << "S_ELEMENT" + << ", is JSArray = " + << IsJSArrayBit::Get(handler) + << ", SOutOfBoundsBit = " + << SOutOfBoundsBit::Get(handler) + << ", SFieldTypeBit = " + << static_cast(SFieldTypeBit::Get(handler)); + break; + default: + UNREACHABLE(); + } + os << std::endl; +#endif +} +} // namespace panda::ecmascript \ No newline at end of file diff --git a/ecmascript/ic/ic_handler.h b/ecmascript/ic/ic_handler.h index 6f4c7a51dba497178810ec27d9192dc7bd3981fb..86909e4fd246c40546a07b37a8dece1501470191 100644 --- a/ecmascript/ic/ic_handler.h +++ b/ecmascript/ic/ic_handler.h @@ -194,89 +194,15 @@ public: { return IsOnHeapBit::Get(handler); } + + static void PrintLoadHandler(uint64_t handler, std::ostream& os); + static void PrintStoreHandler(uint64_t handler, std::ostream& os); }; class LoadHandler final : public HandlerBase { public: - static inline JSHandle LoadProperty(const JSThread *thread, const ObjectOperator &op) - { - uint64_t handler = 0; - ASSERT(!op.IsElement()); - if (!op.IsFound()) { - KindBit::Set(HandlerKind::NON_EXIST, &handler); - return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); - } - ASSERT(op.IsFastMode()); - - JSTaggedValue val = op.GetValue(); - if (val.IsPropertyBox()) { - return JSHandle(thread, val); - } - bool hasAccessor = op.IsAccessorDescriptor(); - AccessorBit::Set(hasAccessor, &handler); - - if (!hasAccessor) { - if (op.GetReceiver()->IsString()) { - JSTaggedValue lenKey = thread->GlobalConstants()->GetLengthString(); - EcmaString *proKey = nullptr; - if (op.GetKey()->IsString()) { - proKey = EcmaString::Cast(op.GetKey()->GetTaggedObject()); - } - if (EcmaStringAccessor::StringsAreEqual(proKey, EcmaString::Cast(lenKey.GetTaggedObject()))) { - KindBit::Set(HandlerKind::STRING_LENGTH, &handler); - } else { - KindBit::Set(HandlerKind::STRING, &handler); - } - } else if (op.GetReceiver()->IsNumber()) { - KindBit::Set(HandlerKind::NUMBER, &handler); - } else { - KindBit::Set(HandlerKind::FIELD, &handler); - } - } - - if (op.IsInlinedProps()) { - InlinedPropsBit::Set(true, &handler); - JSHandle holder = JSHandle::Cast(op.GetHolder()); - auto index = holder->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex()); - OffsetBit::Set(index, &handler); - AttrIndexBit::Set(op.GetIndex(), &handler); - RepresentationBit::Set(op.GetRepresentation(), &handler); - return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); - } - if (op.IsFastMode()) { - JSHandle holder = JSHandle::Cast(op.GetHolder()); - uint32_t inlinePropNum = holder->GetJSHClass()->GetInlinedProperties(); - AttrIndexBit::Set(op.GetIndex() + inlinePropNum, &handler); - OffsetBit::Set(op.GetIndex(), &handler); - RepresentationBit::Set(Representation::TAGGED, &handler); - return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); - } - LOG_ECMA(FATAL) << "this branch is unreachable"; - UNREACHABLE(); - } - - static inline JSHandle LoadElement(const JSThread *thread, const ObjectOperator &op) - { - uint64_t handler = 0; - KindBit::Set(HandlerKind::ELEMENT, &handler); - - // To avoid logical errors and Deopt, temporarily skipping PGO Profiling. - // logical errors: - // When accessing an element of an object, AOT does not have a chain-climbing operation, - // so if the element is on a prototype, it will not be able to get the correct element. - // deopt: - // Currently there is no way to save the type of the key in pgo file, even if the type of the key - // is string, it will be treated as a number type by the AOT, leading to deopt at runtime. - if (op.GetReceiver() != op.GetHolder() || - op.KeyFromStringType()) { - NeedSkipInPGODumpBit::Set(true, &handler); - } - - if (op.GetReceiver()->IsJSArray()) { - IsJSArrayBit::Set(true, &handler); - } - return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); - } + static JSHandle LoadProperty(const JSThread *thread, const ObjectOperator &op); + static JSHandle LoadElement(const JSThread *thread, const ObjectOperator &op); static inline JSHandle LoadStringElement(const JSThread *thread) { @@ -297,51 +223,7 @@ public: class StoreHandler final : public HandlerBase { public: - static inline JSHandle StoreProperty(const JSThread *thread, const ObjectOperator &op) - { - uint64_t handler = 0; - JSHandle receiver = JSHandle::Cast(op.GetReceiver()); - SSharedBit::Set(op.GetReceiver()->IsJSShared(), &handler); - TaggedArray *array = TaggedArray::Cast(receiver->GetProperties().GetTaggedObject()); - if (!array->IsDictionaryMode()) { - SFieldTypeBit::Set(op.GetAttr().GetSharedFieldType(), &handler); - } else { - SFieldTypeBit::Set(op.GetAttr().GetDictSharedFieldType(), &handler); - } - if (op.IsElement()) { - SOutOfBoundsBit::Set(op.GetElementOutOfBounds(), &handler); - return StoreElement(thread, op.GetReceiver(), handler); - } - JSTaggedValue val = op.GetValue(); - if (val.IsPropertyBox()) { - return JSHandle(thread, val); - } - bool hasSetter = op.IsAccessorDescriptor(); - AccessorBit::Set(hasSetter, &handler); - if (!hasSetter) { - SKindBit::Set(StoreHandlerKind::S_FIELD, &handler); - } - if (op.IsInlinedProps()) { - InlinedPropsBit::Set(true, &handler); - uint32_t index = 0; - if (!hasSetter) { - index = receiver->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex()); - } else { - JSHandle holder = JSHandle::Cast(op.GetHolder()); - index = holder->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex()); - } - AttrIndexBit::Set(op.GetIndex(), &handler); - OffsetBit::Set(index, &handler); - RepresentationBit::Set(op.GetRepresentation(), &handler); - return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); - } - ASSERT(op.IsFastMode()); - uint32_t inlinePropNum = receiver->GetJSHClass()->GetInlinedProperties(); - AttrIndexBit::Set(op.GetIndex() + inlinePropNum, &handler); - OffsetBit::Set(op.GetIndex(), &handler); - RepresentationBit::Set(Representation::TAGGED, &handler); - return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); - } + static JSHandle StoreProperty(const JSThread *thread, const ObjectOperator &op); static inline JSHandle StoreElement(const JSThread *thread, JSHandle receiver, uint64_t handler) @@ -353,6 +235,17 @@ public: } return JSHandle(thread, JSTaggedValue::WrapUint64(handler)); } + + static inline void SFieldTypeBitSet(const ObjectOperator &op, JSHandle &receiver, uint64_t *handler) + { + SSharedBit::Set(op.GetReceiver()->IsJSShared(), handler); + TaggedArray *array = TaggedArray::Cast(receiver->GetProperties().GetTaggedObject()); + if (!array->IsDictionaryMode()) { + SFieldTypeBit::Set(op.GetAttr().GetSharedFieldType(), handler); + } else { + SFieldTypeBit::Set(op.GetAttr().GetDictSharedFieldType(), handler); + } + } }; class TransitionHandler : public TaggedObject { @@ -363,21 +256,10 @@ public: return static_cast(object); } - static inline JSHandle StoreTransition(const JSThread *thread, const ObjectOperator &op) - { - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle handler = factory->NewTransitionHandler(); - JSHandle handlerInfo = StoreHandler::StoreProperty(thread, op); - handler->SetHandlerInfo(thread, handlerInfo); - auto hclass = JSObject::Cast(op.GetReceiver()->GetTaggedObject())->GetJSHClass(); - handler->SetTransitionHClass(thread, JSTaggedValue(hclass)); - return JSHandle::Cast(handler); - } + static JSHandle StoreTransition(const JSThread *thread, const ObjectOperator &op); static constexpr size_t HANDLER_INFO_OFFSET = TaggedObjectSize(); - ACCESSORS(HandlerInfo, HANDLER_INFO_OFFSET, TRANSITION_HCLASS_OFFSET) - ACCESSORS(TransitionHClass, TRANSITION_HCLASS_OFFSET, SIZE) DECL_VISIT_OBJECT(HANDLER_INFO_OFFSET, SIZE) @@ -392,78 +274,16 @@ public: return static_cast(object); } - static inline JSHandle LoadPrototype(const JSThread *thread, const ObjectOperator &op, - const JSHandle &hclass) - { - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle handlerInfo = LoadHandler::LoadProperty(thread, op); - JSHandle handler = factory->NewPrototypeHandler(); - handler->SetHandlerInfo(thread, handlerInfo); - if (op.IsFound()) { - handler->SetHolder(thread, op.GetHolder()); - } - if (op.IsAccessorDescriptor()) { - JSTaggedValue result = op.GetValue(); - if (result.IsPropertyBox()) { - result = PropertyBox::Cast(result.GetTaggedObject())->GetValue(); - } - AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject()); - if (!accessor->IsInternal()) { - JSTaggedValue getter = accessor->GetGetter(); - if (!getter.IsUndefined()) { - JSHandle func(thread, getter); - uint32_t methodOffset = Method::Cast(func->GetMethod())->GetMethodId().GetOffset(); - handler->SetAccessorMethodId(methodOffset); - handler->SetAccessorJSFunction(thread, getter); - } - } - } - // ShareToLocal is prohibited - if (!hclass->IsJSShared()) { - auto result = JSHClass::EnableProtoChangeMarker(thread, hclass); - handler->SetProtoCell(thread, result); - } - return JSHandle::Cast(handler); - } - static inline JSHandle StorePrototype(const JSThread *thread, const ObjectOperator &op, - const JSHandle &hclass) - { - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle handler = factory->NewPrototypeHandler(); - JSHandle handlerInfo = StoreHandler::StoreProperty(thread, op); - handler->SetHandlerInfo(thread, handlerInfo); - handler->SetHolder(thread, op.GetHolder()); - if (op.IsAccessorDescriptor()) { - JSTaggedValue result = op.GetValue(); - if (result.IsPropertyBox()) { - result = PropertyBox::Cast(result.GetTaggedObject())->GetValue(); - } - AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject()); - if (!accessor->IsInternal() && accessor->HasSetter()) { - JSTaggedValue setter = accessor->GetSetter(); - JSHandle func(thread, setter); - handler->SetAccessorMethodId( - Method::Cast(func->GetMethod())->GetMethodId().GetOffset()); - handler->SetAccessorJSFunction(thread, setter); - } - } - // ShareToLocal is prohibited - if (!hclass->IsJSShared()) { - auto result = JSHClass::EnableProtoChangeMarker(thread, hclass); - handler->SetProtoCell(thread, result); - } - return JSHandle::Cast(handler); - } + static JSHandle LoadPrototype(const JSThread *thread, const ObjectOperator &op, + const JSHandle &hclass); + static JSHandle StorePrototype(const JSThread *thread, const ObjectOperator &op, + const JSHandle &hclass); static constexpr size_t HANDLER_INFO_OFFSET = TaggedObjectSize(); - ACCESSORS(HandlerInfo, HANDLER_INFO_OFFSET, PROTO_CELL_OFFSET) - ACCESSORS(ProtoCell, PROTO_CELL_OFFSET, HOLDER_OFFSET) - ACCESSORS(Holder, HOLDER_OFFSET, ACCESSOR_JSFUNCTION_OFFSET) ACCESSORS(AccessorJSFunction, ACCESSOR_JSFUNCTION_OFFSET, ACCESSOR_METHOD_ID_OFFSET) - ACCESSORS_PRIMITIVE_FIELD(AccessorMethodId, uint32_t, ACCESSOR_METHOD_ID_OFFSET, LAST_OFFSET) DEFINE_ALIGN_SIZE(LAST_OFFSET); @@ -479,59 +299,29 @@ public: return static_cast(object); } - static inline JSHandle StoreTransition(const JSThread *thread, const ObjectOperator &op, - const JSHandle &hclass) - { - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle handler = factory->NewTransWithProtoHandler(); - JSHandle handlerInfo = StoreHandler::StoreProperty(thread, op); - handler->SetHandlerInfo(thread, handlerInfo); - auto result = JSHClass::EnableProtoChangeMarker(thread, hclass); - handler->SetProtoCell(thread, result); - handler->SetTransitionHClass(thread, hclass.GetTaggedValue()); - - return JSHandle::Cast(handler); - } + static JSHandle StoreTransition(const JSThread *thread, const ObjectOperator &op, + const JSHandle &hclass); static constexpr size_t HANDLER_INFO_OFFSET = TaggedObjectSize(); - ACCESSORS(HandlerInfo, HANDLER_INFO_OFFSET, TRANSITION_HCLASS_OFFSET) - ACCESSORS(TransitionHClass, TRANSITION_HCLASS_OFFSET, PROTO_CELL_OFFSET) - ACCESSORS(ProtoCell, PROTO_CELL_OFFSET, SIZE) DECL_VISIT_OBJECT(HANDLER_INFO_OFFSET, SIZE) DECL_DUMP() }; -class StoreTSHandler : public TaggedObject { +class StoreAOTHandler : public TaggedObject { public: - static StoreTSHandler *Cast(TaggedObject *object) - { - ASSERT(JSTaggedValue(object).IsStoreTSHandler()); - return static_cast(object); - } - - static inline JSHandle StoreAOT(const JSThread *thread, const ObjectOperator &op, - const JSHandle &hclass) + static StoreAOTHandler *Cast(TaggedObject *object) { - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle handler = factory->NewStoreTSHandler(); - JSHandle handlerInfo = StoreHandler::StoreProperty(thread, op); - handler->SetHandlerInfo(thread, handlerInfo); - handler->SetHolder(thread, op.GetHolder()); - auto result = JSHClass::EnableProtoChangeMarker(thread, hclass); - handler->SetProtoCell(thread, result); - return JSHandle::Cast(handler); + ASSERT(JSTaggedValue(object).IsStoreAOTHandler()); + return static_cast(object); } static constexpr size_t HANDLER_INFO_OFFSET = TaggedObjectSize(); - ACCESSORS(HandlerInfo, HANDLER_INFO_OFFSET, PROTO_CELL_OFFSET) - ACCESSORS(ProtoCell, PROTO_CELL_OFFSET, HOLDER_OFFSET) - ACCESSORS(Holder, HOLDER_OFFSET, SIZE) DECL_VISIT_OBJECT(HANDLER_INFO_OFFSET, SIZE) diff --git a/ecmascript/ic/ic_runtime.cpp b/ecmascript/ic/ic_runtime.cpp index 339bcc01bfb86cbc8aed97b26e7b253fead3d67f..6d2a5cf092449d3e3b8ede3ab65d339a12bf13bb 100644 --- a/ecmascript/ic/ic_runtime.cpp +++ b/ecmascript/ic/ic_runtime.cpp @@ -15,13 +15,13 @@ #include "ecmascript/ic/ic_runtime.h" #include "ecmascript/ic/ic_handler.h" +#include "ecmascript/dfx/stackinfo/js_stackinfo.h" #include "ecmascript/interpreter/interpreter.h" #include "ecmascript/interpreter/slow_runtime_stub.h" #include "ecmascript/js_primitive_ref.h" #include "ecmascript/shared_objects/js_shared_array.h" namespace panda::ecmascript { -#define TRACE_IC 0 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) void ICRuntime::UpdateLoadHandler(const ObjectOperator &op, JSHandle key, JSHandle receiver) @@ -45,7 +45,7 @@ void ICRuntime::UpdateLoadHandler(const ObjectOperator &op, JSHandleIsTS() && !op.IsFound()) { + if (hclass->IsAOT() && !op.IsFound()) { return; } if (op.IsElement()) { @@ -152,25 +152,6 @@ void ICRuntime::UpdateStoreHandler(const ObjectOperator &op, JSHandle receiver, - [[maybe_unused]] JSHandle key) const -{ -#if TRACE_IC - auto kind = ICKindToString(GetICKind()); - auto state = ProfileTypeAccessor::ICStateToString(icAccessor_.GetICState()); - if (key->IsString()) { - auto keyStrHandle = JSHandle::Cast(key); - LOG_ECMA(ERROR) << kind << " miss key is: " << EcmaStringAccessor(keyStrHandle).ToCString() - << ", receiver is " << receiver->GetTaggedObject()->GetClass()->IsDictionaryMode() - << ", state is " << state; - } else { - LOG_ECMA(ERROR) << kind << " miss " << ", state is " - << ", receiver is " << receiver->GetTaggedObject()->GetClass()->IsDictionaryMode() - << state; - } -#endif -} - JSTaggedValue LoadICRuntime::LoadValueMiss(JSHandle receiver, JSHandle key) { JSTaggedValue::RequireObjectCoercible(thread_, receiver, "Cannot load property of null or undefined"); @@ -210,7 +191,7 @@ JSTaggedValue LoadICRuntime::LoadValueMiss(JSHandle receiver, JSH icAccessor_.SetAsMega(); return result.GetTaggedValue(); } - TraceIC(receiver, key); + TraceIC(GetThread(), receiver, key); // do not cache element if (!op.IsFastMode()) { icAccessor_.SetAsMega(); @@ -246,14 +227,6 @@ JSTaggedValue LoadICRuntime::LoadMiss(JSHandle receiver, JSHandle return CallPrivateGetter(receiver, key); } - if (key->IsSymbol() && JSSymbol::Cast(key->GetTaggedObject())->IsPrivate()) { - PropertyDescriptor desc(thread_); - if (!JSTaggedValue::IsPropertyKey(key) || - !JSTaggedValue::GetOwnProperty(thread_, receiver, key, desc)) { - THROW_TYPE_ERROR_AND_RETURN(thread_, "invalid or cannot find private key", JSTaggedValue::Exception()); - } - } - ObjectOperator op(GetThread(), receiver, key); auto result = JSHandle(thread_, JSObject::GetProperty(GetThread(), &op)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); @@ -269,7 +242,7 @@ JSTaggedValue LoadICRuntime::LoadMiss(JSHandle receiver, JSHandle icAccessor_.SetAsMega(); return result.GetTaggedValue(); } - TraceIC(receiver, key); + TraceIC(GetThread(), receiver, key); // do not cache element if (!op.IsFastMode()) { icAccessor_.SetAsMega(); @@ -293,7 +266,6 @@ inline JSTaggedValue LoadICRuntime::CallPrivateGetter(JSHandle re JSHandle undefined = thread_->GlobalConstants()->GetHandledUndefined(); EcmaRuntimeCallInfo* info = EcmaInterpreter::NewRuntimeCallInfo(thread_, key, receiver, undefined, 0); // 0: getter has 0 argument - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); JSTaggedValue resGetter = JSFunction::Call(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); return resGetter; @@ -312,7 +284,9 @@ JSTaggedValue LoadICRuntime::LoadTypedArrayValueMiss(JSHandle rec } UpdateTypedArrayHandler(receiver); JSHandle indexHandle(GetThread(), numericIndex); - uint32_t index = static_cast(JSTaggedValue::ToInteger(GetThread(), indexHandle).ToInt32()); + JSTaggedNumber integerValue = JSTaggedValue::ToInteger(GetThread(), indexHandle); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread()); + uint32_t index = static_cast(integerValue.ToInt32()); JSType type = receiver->GetTaggedObject()->GetClass()->GetObjectType(); return JSTypedArray::FastGetPropertyByIndex(GetThread(), receiver.GetTaggedValue(), index, type); } else { @@ -328,7 +302,7 @@ JSTaggedValue LoadICRuntime::LoadTypedArrayValueMiss(JSHandle rec icAccessor_.SetAsMega(); return result.GetTaggedValue(); } - TraceIC(receiver, key); + TraceIC(GetThread(), receiver, key); // do not cache element if (!op.IsFastMode()) { icAccessor_.SetAsMega(); @@ -348,9 +322,9 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle receiver, JSHand } if (!receiver->IsJSObject() || receiver->HasOrdinaryGet()) { icAccessor_.SetAsMega(); - bool success = JSTaggedValue::SetProperty(GetThread(), receiver, key, value, true); + JSTaggedValue::SetProperty(GetThread(), receiver, key, value, true); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); - return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); + return JSTaggedValue::Undefined(); } if (receiver->IsTypedArray() || receiver->IsSharedTypedArray()) { return StoreTypedArrayValueMiss(receiver, key, value); @@ -375,23 +349,12 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle receiver, JSHand if (receiver->IsJSSharedArray()) { bool success = JSSharedArray::SetProperty(thread_, receiver, key, value, true, SCheckMode::CHECK); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); - if (success) { - return JSTaggedValue::Undefined(); - } - return JSTaggedValue::Exception(); + return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); } if (key->IsJSFunction()) { // key is a private setter return CallPrivateSetter(receiver, key, value); } - if (key->IsSymbol() && JSSymbol::Cast(key->GetTaggedObject())->IsPrivate()) { - PropertyDescriptor desc(thread_); - if (!JSTaggedValue::IsPropertyKey(key) || - !JSTaggedValue::GetOwnProperty(thread_, receiver, key, desc)) { - THROW_TYPE_ERROR_AND_RETURN(thread_, "invalid or cannot find private key", JSTaggedValue::Exception()); - } - } - ObjectOperator op(GetThread(), receiver, key, isOwn ? OperatorType::OWN : OperatorType::PROTOTYPE_CHAIN); if (!op.IsFound()) { if (kind == ICKind::NamedGlobalStoreIC) { @@ -401,31 +364,40 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle receiver, JSHand return SlowRuntimeStub::ThrowReferenceError(GetThread(), key.GetTaggedValue(), " is not defined"); } } + bool success = false; + // If op is Accessor, it may change the properties of receiver or receiver's proto, + // causing IC compute errors, so move SetPropertyForAccessor to be executed after UpdateStoreHandler. + bool isAccessor = false; if (isOwn) { bool enumerable = !(receiver->IsClassPrototype() || receiver->IsClassConstructor()); PropertyDescriptor desc(thread_, value, true, enumerable, true); success = JSObject::DefineOwnProperty(thread_, &op, desc); } else { - success = JSObject::SetProperty(&op, value, true); + success = JSObject::SetPropertyForData(&op, value, &isAccessor); } RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); - // ic-switch - if (!GetThread()->GetEcmaVM()->ICEnabled()) { - icAccessor_.SetAsMega(); - return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); - } - TraceIC(receiver, key); - // do not cache element - if (!op.IsFastMode()) { + + // IC Disable + if (!GetThread()->GetEcmaVM()->ICEnabled() || !op.IsFastMode()) { icAccessor_.SetAsMega(); - return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); + if (!success) { + return JSTaggedValue::Exception(); + } + if (isAccessor) { + return HandleAccesor(&op, value); + } + return JSTaggedValue::Undefined(); } + + TraceIC(GetThread(), receiver, key); if (success) { UpdateStoreHandler(op, key, receiver); - return JSTaggedValue::Undefined(); } - return JSTaggedValue::Exception(); + if (isAccessor) { + return HandleAccesor(&op, value); + } + return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); } inline JSTaggedValue StoreICRuntime::CallPrivateSetter(JSHandle receiver, JSHandle key, @@ -458,34 +430,104 @@ JSTaggedValue StoreICRuntime::StoreTypedArrayValueMiss(JSHandle r } UpdateTypedArrayHandler(receiver); JSHandle indexHandle(GetThread(), numericIndex); - uint32_t index = static_cast(JSTaggedValue::ToInteger(GetThread(), indexHandle).ToInt32()); + JSTaggedNumber integerValue = JSTaggedValue::ToInteger(GetThread(), indexHandle); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread()); + uint32_t index = static_cast(integerValue.ToInt32()); JSType type = receiver->GetTaggedObject()->GetClass()->GetObjectType(); return JSTypedArray::FastSetPropertyByIndex(GetThread(), receiver.GetTaggedValue(), index, value.GetTaggedValue(), type); } else { UpdateReceiverHClass(JSHandle(GetThread(), JSHandle::Cast(receiver)->GetClass())); ObjectOperator op(GetThread(), receiver, key); - bool success = JSObject::SetProperty(&op, value, true); - if (op.GetValue().IsAccessor()) { - op = ObjectOperator(GetThread(), receiver, key); - } - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread()); - // ic-switch - if (!GetThread()->GetEcmaVM()->ICEnabled()) { - icAccessor_.SetAsMega(); - return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); - } - TraceIC(receiver, key); - // do not cache element - if (!op.IsFastMode()) { + + // If op is Accessor, it may change the properties of receiver or receiver's proto, + // causing IC compute errors, so move SetPropertyForAccessor to be executed after UpdateStoreHandler. + bool isAccessor = false; + bool success = JSObject::SetPropertyForData(&op, value, &isAccessor); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); + + // IC Disable + if (!GetThread()->GetEcmaVM()->ICEnabled() || !op.IsFastMode()) { icAccessor_.SetAsMega(); - return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); + if (!success) { + return JSTaggedValue::Exception(); + } + if (isAccessor) { + return HandleAccesor(&op, value); + } + return JSTaggedValue::Undefined(); } + + TraceIC(GetThread(), receiver, key); if (success) { UpdateStoreHandler(op, key, receiver); - return JSTaggedValue::Undefined(); } + if (isAccessor) { + return HandleAccesor(&op, value); + } + return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); + } +} + +JSTaggedValue StoreICRuntime::HandleAccesor(ObjectOperator *op, const JSHandle &value) +{ + bool success = JSObject::SetPropertyForAccessor(op, value); + if (thread_->HasPendingException()) { + icAccessor_.SetAsMega(); return JSTaggedValue::Exception(); } + return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); +} + +void ICRuntime::TraceIC([[maybe_unused]] JSThread *thread, + [[maybe_unused]] JSHandle receiver, + [[maybe_unused]] JSHandle key) const +{ +#if ECMASCRIPT_ENABLE_TRACE_IC + // If BackTrace affects IC, can choose not to execute it. + std::string strTraceIC = "Miss Func BackTrace: "; + std::vector jsStackInfo = JsStackInfo::BuildJsStackInfo(thread, true); + if (jsStackInfo.empty()) { + strTraceIC += "empty"; + } else { + JsFrameInfo jsFrameInfo = jsStackInfo.front(); + size_t pos = jsFrameInfo.pos.find(':', 0); + if (pos != CString::npos) { + int lineNumber = std::stoi(jsFrameInfo.pos.substr(0, pos)); + int columnNumber = std::stoi(jsFrameInfo.pos.substr(pos + 1)); + auto sourceMapcb = thread->GetEcmaVM()->GetSourceMapTranslateCallback(); + if (sourceMapcb != nullptr && !jsFrameInfo.fileName.empty()) { + sourceMapcb(jsFrameInfo.fileName, lineNumber, columnNumber); + } + } + strTraceIC += "funcName: " + jsFrameInfo.functionName + ", url: " + + jsFrameInfo.fileName + ":" + jsFrameInfo.pos; + } + LOG_ECMA(ERROR) << strTraceIC; + + auto kind = ICKindToString(GetICKind()); + bool primitiveIc = false; + if (receiver->IsNumber() || receiver->IsString()) { + primitiveIc = true; + } + auto state = ProfileTypeAccessor::ICStateToString(icAccessor_.GetICState()); + if (key->IsString()) { + auto keyStrHandle = JSHandle::Cast(key); + LOG_ECMA(ERROR) << kind << " miss, key is: " << EcmaStringAccessor(keyStrHandle).ToCString() + << ", icstate is: " << state + << ", slotid is: " << GetSlotId(); + } else { + LOG_ECMA(ERROR) << kind << " miss, " + << ", icstate is " << state + << ", slotid is:" << GetSlotId(); + } + if (primitiveIc) { + LOG_ECMA(ERROR) << "primitiveIc "; + } else { + JSHClass *jshclass = receiver->GetTaggedObject()->GetClass(); + LOG_ECMA(ERROR) << "receiver DictionaryMode is: " << jshclass->IsDictionaryMode() + << ", hclass is: "<< std::hex << jshclass; + } +#endif } } // namespace panda::ecmascript diff --git a/ecmascript/ic/ic_runtime.h b/ecmascript/ic/ic_runtime.h index 6940e64a7aa9aa4e15e1baff8ae3699baf0ff981..0aa43d197a02d736f2e3a4ef50016b81b1aaa08c 100644 --- a/ecmascript/ic/ic_runtime.h +++ b/ecmascript/ic/ic_runtime.h @@ -57,7 +57,12 @@ public: return icAccessor_.GetKind(); } - void TraceIC(JSHandle receiver, JSHandle key) const; + uint32_t GetSlotId() const + { + return icAccessor_.GetSlotId(); + } + + void TraceIC(JSThread *thread, JSHandle receiver, JSHandle key) const; protected: JSThread *thread_; @@ -99,6 +104,7 @@ public: private: inline JSTaggedValue CallPrivateSetter(JSHandle receiver, JSHandle key, JSHandle value); + JSTaggedValue HandleAccesor(ObjectOperator *op, const JSHandle &value); }; } // namespace panda::ecmascript diff --git a/ecmascript/ic/ic_runtime_stub-inl.h b/ecmascript/ic/ic_runtime_stub-inl.h index 6996afab1035db19603c86b3a666432f2842530e..79e16ed18ee20fc6eeebfad7c4ecd8f288fdac6e 100644 --- a/ecmascript/ic/ic_runtime_stub-inl.h +++ b/ecmascript/ic/ic_runtime_stub-inl.h @@ -223,6 +223,7 @@ ARK_INLINE JSTaggedValue ICRuntimeStub::StoreICWithHandler(JSThread *thread, JST INTERPRETER_TRACE(thread, StoreICWithHandler); if (handler.IsInt()) { auto handlerInfo = JSTaggedValue::UnwrapToUint64(handler); + HandlerBase::PrintStoreHandler(handlerInfo, std::cout); if (HandlerBase::IsNonSharedStoreField(handlerInfo)) { StoreField(thread, JSObject::Cast(receiver.GetTaggedObject()), value, handlerInfo); return JSTaggedValue::Undefined(); @@ -256,7 +257,7 @@ ARK_INLINE JSTaggedValue ICRuntimeStub::StoreICWithHandler(JSThread *thread, JST if (handler.IsPropertyBox()) { return StoreGlobal(thread, value, handler); } - if (handler.IsStoreTSHandler()) { + if (handler.IsStoreAOTHandler()) { return StoreWithTS(thread, receiver, value, handler); } return JSTaggedValue::Undefined(); @@ -288,16 +289,16 @@ JSTaggedValue ICRuntimeStub::StoreWithTS(JSThread *thread, JSTaggedValue receive JSTaggedValue value, JSTaggedValue handler) { INTERPRETER_TRACE(thread, StoreWithAOT); - ASSERT(handler.IsStoreTSHandler()); - StoreTSHandler *storeTSHandler = StoreTSHandler::Cast(handler.GetTaggedObject()); - auto cellValue = storeTSHandler->GetProtoCell(); + ASSERT(handler.IsStoreAOTHandler()); + StoreAOTHandler *storeAOTHandler = StoreAOTHandler::Cast(handler.GetTaggedObject()); + auto cellValue = storeAOTHandler->GetProtoCell(); ASSERT(cellValue.IsProtoChangeMarker()); ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject()); if (cell->GetHasChanged()) { return JSTaggedValue::Hole(); } - auto holder = storeTSHandler->GetHolder(); - JSTaggedValue handlerInfo = storeTSHandler->GetHandlerInfo(); + auto holder = storeAOTHandler->GetHolder(); + JSTaggedValue handlerInfo = storeAOTHandler->GetHandlerInfo(); auto handlerInfoInt = JSTaggedValue::UnwrapToUint64(handlerInfo); if (HandlerBase::IsField(handlerInfoInt)) { StoreField(thread, JSObject::Cast(receiver.GetTaggedObject()), value, handlerInfoInt); @@ -452,6 +453,7 @@ ARK_INLINE JSTaggedValue ICRuntimeStub::LoadICWithHandler(JSThread *thread, JSTa INTERPRETER_TRACE(thread, LoadICWithHandler); if (LIKELY(handler.IsInt())) { auto handlerInfo = JSTaggedValue::UnwrapToUint64(handler); + HandlerBase::PrintLoadHandler(handlerInfo, std::cout); if (LIKELY(HandlerBase::IsField(handlerInfo))) { return LoadFromField(JSObject::Cast(holder.GetTaggedObject()), handlerInfo); } @@ -481,6 +483,7 @@ ARK_INLINE JSTaggedValue ICRuntimeStub::LoadICWithElementHandler(JSThread *threa { if (LIKELY(handler.IsInt())) { auto handlerInfo = JSTaggedValue::UnwrapToUint64(handler); + HandlerBase::PrintLoadHandler(handlerInfo, std::cout); if (HandlerBase::IsNormalElement(handlerInfo)) { return LoadElement(JSObject::Cast(receiver.GetTaggedObject()), key); } else if (HandlerBase::IsTypedArrayElement(handlerInfo)) { @@ -556,6 +559,7 @@ JSTaggedValue ICRuntimeStub::StoreElement(JSThread *thread, JSObject *receiver, uint32_t elementIndex = static_cast(index); if (handler.IsInt()) { auto handlerInfo = JSTaggedValue::UnwrapToUint64(handler); + HandlerBase::PrintStoreHandler(handlerInfo, std::cout); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle receiverHandle(thread, receiver); JSHandle valueHandle(thread, value); diff --git a/ecmascript/ic/invoke_cache.cpp b/ecmascript/ic/invoke_cache.cpp deleted file mode 100644 index 990d3b2100947fa9d6e2b800529105f68e5db5b4..0000000000000000000000000000000000000000 --- a/ecmascript/ic/invoke_cache.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ecmascript/ic/invoke_cache.h" -#include "ecmascript/interpreter/frame_handler.h" -#include "ecmascript/interpreter/interpreter.h" - - -namespace panda::ecmascript { -// Build the infrastructure and wait for TS to invoke. -bool InvokeCache::SetMonoConstuctCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - JSTaggedValue newTarget, JSTaggedValue initialHClass) -{ - // only cache class constructor - if (UNLIKELY(!newTarget.IsClassConstructor())) { - return false; - } - - profileTypeInfo->Set(thread, slotId, newTarget); - profileTypeInfo->Set(thread, slotId + 1, initialHClass); - - return true; -} - -bool InvokeCache::SetPolyConstuctCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - uint8_t length, JSTaggedValue newTargetArray, - JSTaggedValue initialHClassArray) -{ - ASSERT(length <= POLY_CASE_NUM && newTargetArray.IsTaggedArray() && initialHClassArray.IsTaggedArray()); - - JSHandle profileTypeInfoArr(thread, profileTypeInfo); - JSHandle newTargetArr(thread, newTargetArray); - JSHandle initialHClassArr(thread, initialHClassArray); - - auto factory = thread->GetEcmaVM()->GetFactory(); - constexpr uint8_t step = 2; - JSHandle newArray = factory->NewTaggedArray(length * step); // 2: newTarget and hclass - - for (uint8_t index = 0; index < length; ++index) { - ASSERT(newTargetArr->Get(index).IsClassConstructor()); - - newArray->Set(thread, index * step, newTargetArr->Get(index)); - newArray->Set(thread, index * step + 1, initialHClassArr->Get(index)); - } - - profileTypeInfoArr->Set(thread, slotId, newArray); - profileTypeInfoArr->Set(thread, slotId + 1, JSTaggedValue::Hole()); - - return true; -} - -JSTaggedValue InvokeCache::CheckPolyInvokeCache(JSTaggedValue cachedArray, JSTaggedValue func) -{ - ASSERT(cachedArray.IsTaggedArray()); - TaggedArray *array = TaggedArray::Cast(cachedArray.GetTaggedObject()); - uint32_t length = array->GetLength(); - for (uint32_t index = 0; index < length; index += 2) { // 2: means one ic, two slot - auto result = array->Get(index); - if (JSFunction::Cast(result.GetTaggedObject())->GetMethod() == - JSFunction::Cast(func.GetTaggedObject())->GetMethod()) { - return array->Get(index + 1); - } - } - - return JSTaggedValue::Hole(); -} - -JSTaggedValue InvokeCache::Construct(JSThread *thread, JSTaggedValue firstValue, JSTaggedValue secondValue, - JSTaggedValue ctor, JSTaggedValue newTarget, uint16_t firstArgIdx, uint16_t length) -{ - // ic miss - if (UNLIKELY(!firstValue.IsHeapObject())) { - return JSTaggedValue::Hole(); - } - - // gc protection - JSHandle constructor(thread, ctor); - JSHandle newTgt(thread, newTarget); - - JSHandle instanceHClass; - // monomorphic - if (LIKELY(firstValue.IsJSFunction() && - newTgt->GetMethod() == JSFunction::Cast(firstValue.GetTaggedObject())->GetMethod())) { - instanceHClass = JSHandle(thread, JSHClass::Cast(secondValue.GetTaggedObject())); - } else { - // polymorphic - ASSERT(firstValue.IsTaggedArray()); - JSTaggedValue polyCache = CheckPolyInvokeCache(firstValue, newTarget); - if (UNLIKELY(polyCache.IsHole())) { - return JSTaggedValue::Hole(); - } - instanceHClass = JSHandle(thread, JSHClass::Cast(polyCache.GetTaggedObject())); - } - - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle obj = factory->NewJSObject(instanceHClass); - EcmaRuntimeCallInfo *info = - EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle(constructor), JSHandle(obj), - JSHandle(newTgt), length); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - FrameHandler frameHandler(thread); - for (size_t i = 0; i < length; i++) { - info->SetCallArg(i, frameHandler.GetVRegValue(firstArgIdx + i)); - } - EcmaInterpreter::Execute(info); - return obj.GetTaggedValue(); -} - -// just identify simple callee case which can be inlined, the implement of inline need wait TS AOT -bool InvokeCache::SetMonoInlineCallCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - JSTaggedValue callee) -{ - ASSERT(callee.IsJSFunction()); - Method *calleeMethod = JSFunction::Cast(callee.GetTaggedObject())->GetCallTarget(); - if (DecideCanBeInlined(calleeMethod)) { - profileTypeInfo->Set(thread, slotId, callee); - return true; - } - - profileTypeInfo->Set(thread, slotId, JSTaggedValue::Hole()); - return false; -} - -bool InvokeCache::SetPolyInlineCallCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - uint8_t length, JSTaggedValue calleeArray) -{ - ASSERT(calleeArray.IsTaggedArray() && length >= MONO_CASE_NUM && length <= POLY_CASE_NUM); - JSHandle calleeArr(thread, calleeArray); - ASSERT(calleeArr->GetLength() == length); - JSHandle profileTypeInfoArr(thread, profileTypeInfo); - - auto factory = thread->GetEcmaVM()->GetFactory(); - JSHandle newArray = factory->NewTaggedArray(length); - - for (uint8_t index = 0; index < length; ++index) { - JSTaggedValue calleeElement = calleeArr->Get(index); - Method *calleeMethod = JSFunction::Cast(calleeElement.GetTaggedObject())->GetCallTarget(); - if (DecideCanBeInlined(calleeMethod)) { - newArray->Set(thread, index, calleeElement); - } else { - newArray->Set(thread, index, JSTaggedValue::Hole()); - } - } - - profileTypeInfoArr->Set(thread, slotId, newArray); - return true; -} - -bool InvokeCache::DecideCanBeInlined(Method *method) -{ - constexpr uint32_t MAX_INLINED_BYTECODE_SIZE = 128; - uint32_t bcSize = method->GetCodeSize(); - return (bcSize > 0 && bcSize < MAX_INLINED_BYTECODE_SIZE); // 0 is invalid -} -} // namespace panda::ecmascript diff --git a/ecmascript/ic/invoke_cache.h b/ecmascript/ic/invoke_cache.h deleted file mode 100644 index e533122ca597455c3d2395f0aeae4c8e6f414f10..0000000000000000000000000000000000000000 --- a/ecmascript/ic/invoke_cache.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2021-2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ECMASCRIPT_IC_INVOKE_CACHE_H -#define ECMASCRIPT_IC_INVOKE_CACHE_H - -#include "ecmascript/ic/profile_type_info.h" -#include "ecmascript/js_tagged_value.h" - -namespace panda::ecmascript { -class InvokeCache { -public: - static constexpr size_t MONO_CASE_NUM = 2; - static constexpr size_t POLY_CASE_NUM = 4; - - static bool SetMonoConstuctCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - JSTaggedValue newTarget, JSTaggedValue initialHClass); - - static bool SetPolyConstuctCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - uint8_t length, JSTaggedValue newTargetArray, - JSTaggedValue initialHClassArray); - - static JSTaggedValue CheckPolyInvokeCache(JSTaggedValue cachedArray, JSTaggedValue func); - - static JSTaggedValue Construct(JSThread *thread, JSTaggedValue firstValue, JSTaggedValue secondValue, - JSTaggedValue ctor, JSTaggedValue newTarget, uint16_t firstArgIdx, - uint16_t length); - - static bool SetMonoInlineCallCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - JSTaggedValue callee); - - static bool SetPolyInlineCallCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId, - uint8_t length, JSTaggedValue calleeArray); - - static bool DecideCanBeInlined(Method *method); -}; -} // namespace panda::ecmascript - -#endif // ECMASCRIPT_IC_INVOKE_CACHE_H diff --git a/ecmascript/ic/profile_type_info.h b/ecmascript/ic/profile_type_info.h index 8f169765862afcbe36cbfe26473e3b3126a2c412..f805091c9223ead9cfebcfd95e725fda65aaa5b1 100644 --- a/ecmascript/ic/profile_type_info.h +++ b/ecmascript/ic/profile_type_info.h @@ -476,6 +476,11 @@ public: return kind_; } + uint32_t GetSlotId() const + { + return slotId_; + } + private: JSThread* thread_; JSHandle profileTypeInfo_; diff --git a/ecmascript/ic/tests/BUILD.gn b/ecmascript/ic/tests/BUILD.gn index 8cf901a7829adb801f3cf13a520ca99a3a01b6b4..24173646743fa64c3fd1e90ab75d6430889db1e3 100644 --- a/ecmascript/ic/tests/BUILD.gn +++ b/ecmascript/ic/tests/BUILD.gn @@ -14,17 +14,14 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("IC_001_Test") { module_out_path = module_output_path sources = [ # test file - "ic_binaryop_test.cpp", - "ic_compareop_test.cpp", "ic_handler_test.cpp", - "ic_invoke_test.cpp", "ic_runtime_stub_test.cpp", ] diff --git a/ecmascript/ic/tests/ic_binaryop_test.cpp b/ecmascript/ic/tests/ic_binaryop_test.cpp deleted file mode 100644 index dacbc83e4f9b38b4ae38af9c0b82dbd586021889..0000000000000000000000000000000000000000 --- a/ecmascript/ic/tests/ic_binaryop_test.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "ecmascript/ecma_vm.h" -#include "ecmascript/global_env_constants.h" -#include "ecmascript/global_env_constants-inl.h" -#include "ecmascript/ic/ic_binary_op.h" -#include "ecmascript/interpreter/slow_runtime_stub.h" -#include "ecmascript/object_factory.h" -#include "ecmascript/tests/test_helper.h" - -using namespace panda::ecmascript; -namespace panda::test { -class ICBinaryOPTest : public testing::Test { -public: - static void SetUpTestCase() - { - GTEST_LOG_(INFO) << "SetUpTestCase"; - } - - static void TearDownTestCase() - { - GTEST_LOG_(INFO) << "TearDownCase"; - } - - void SetUp() override - { - TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope); - } - - void TearDown() override - { - TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope); - } - - EcmaHandleScope *scope {nullptr}; - JSThread *thread {nullptr}; - EcmaVM *ecmaVm = nullptr; -}; - -HWTEST_F_L0(ICBinaryOPTest, AddWithTSType) -{ - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("AddTest"); - JSHandle Str2 = factory->NewFromASCII("IC"); - JSHandle arg4 = factory->NewEmptyJSObject(); - JSTaggedValue arg1Value(static_cast(2)); - JSTaggedValue arg2Value(static_cast(3)); - JSTaggedValue arg3Value(static_cast(9.5561)); - JSHandle arg1(thread, arg1Value); - JSHandle arg2(thread, arg2Value); - JSHandle arg3(thread, arg3Value); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Add2(thread, arg1.GetTaggedValue(), - arg2.GetTaggedValue()); - JSHandle slowHandle1(thread, resInSlowPath1); - JSTaggedValue resInICPath1 = ICBinaryOP::AddWithTSType(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle1.GetTaggedValue(), resInICPath1); - - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Add2(thread, arg1.GetTaggedValue(), - arg3.GetTaggedValue()); - JSHandle slowHandle2(thread, resInSlowPath2); - JSTaggedValue resInICPath2 = ICBinaryOP::AddWithTSType(thread, arg1.GetTaggedValue(), arg3.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle2.GetTaggedValue(), resInICPath2); - - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Add2(thread, Str1.GetTaggedValue(), - Str2.GetTaggedValue()); - JSHandle slowHandle3(thread, reinterpret_cast(resInSlowPath3.GetRawData())); - JSTaggedValue resInICPath3 = ICBinaryOP::AddWithTSType(thread, Str1.GetTaggedValue(), Str2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::STRING))); - ASSERT_TRUE(resInICPath3.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle3, JSHandle(thread, resInICPath3)), 0); - - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Add2(thread, JSTaggedValue::Undefined(), - arg2.GetTaggedValue()); - JSHandle slowHandle4(thread, resInSlowPath4); - JSTaggedValue resInICPath4 = ICBinaryOP::AddWithTSType(thread, JSTaggedValue::Undefined(), - arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER_GEN))); - EXPECT_EQ(slowHandle4.GetTaggedValue(), resInICPath4); - - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Add2(thread, arg3.GetTaggedValue(), - Str1.GetTaggedValue()); - JSHandle slowHandle5(thread, reinterpret_cast(resInSlowPath5.GetRawData())); - JSTaggedValue resInICPath5 = ICBinaryOP::AddWithTSType(thread, arg3.GetTaggedValue(), - Str1.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::STRING_GEN))); - ASSERT_TRUE(resInICPath5.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle5, JSHandle(thread, resInICPath5)), 0); - - JSTaggedValue resInSlowPath6 = SlowRuntimeStub::Add2(thread, Str1.GetTaggedValue(), - JSTaggedValue::Null()); - JSHandle slowHandle6(thread, reinterpret_cast(resInSlowPath6.GetRawData())); - JSTaggedValue resInICPath6 = ICBinaryOP::AddWithTSType(thread, Str1.GetTaggedValue(), JSTaggedValue::Null(), - JSTaggedValue(static_cast(BinaryType::STRING_GEN))); - ASSERT_TRUE(resInICPath6.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle6, JSHandle(thread, resInICPath6)), 0); - - JSTaggedValue resInSlowPath7 = SlowRuntimeStub::Add2(thread, arg1.GetTaggedValue(), - JSTaggedValue::True()); - JSHandle slowHandle7(thread, resInSlowPath7); - JSTaggedValue resInICPath7 = ICBinaryOP::AddWithTSType(thread, arg1.GetTaggedValue(), JSTaggedValue::True(), - JSTaggedValue(static_cast(BinaryType::NUMBER_GEN))); - EXPECT_EQ(slowHandle7.GetTaggedValue(), resInICPath7); - - JSTaggedValue resInSlowPath8 = SlowRuntimeStub::Add2(thread, arg4.GetTaggedValue(), - JSTaggedValue::Null()); - JSHandle slowHandle8(thread, reinterpret_cast(resInSlowPath8.GetRawData())); - JSTaggedValue resInICPath8 = ICBinaryOP::AddWithTSType(thread, arg4.GetTaggedValue(), JSTaggedValue::Null(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - ASSERT_TRUE(resInICPath8.IsString()); - EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle8, JSHandle(thread, resInICPath8)), 0); -}; - -HWTEST_F_L0(ICBinaryOPTest, SubWithTSType) -{ - JSTaggedValue arg1Value(static_cast(-2)); - JSTaggedValue arg2Value(static_cast(INT32_MAX-1)); - JSTaggedValue arg3Value(static_cast(9.5561)); - JSHandle arg1(thread, arg1Value); - JSHandle arg2(thread, arg2Value); - JSHandle arg3(thread, arg3Value); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Sub2(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle1(thread, resInSlowPath1); - JSTaggedValue resInICPath1 = ICBinaryOP::SubWithTSType(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle1.GetTaggedValue(), resInICPath1); - - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Sub2(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue()); - JSHandle slowHandle2(thread, resInSlowPath2); - JSTaggedValue resInICPath2 = ICBinaryOP::SubWithTSType(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle2.GetTaggedValue(), resInICPath2); - - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Sub2(thread, arg1.GetTaggedValue(), JSTaggedValue::True()); - JSHandle slowHandle3(thread, resInSlowPath3); - JSTaggedValue resInICPath3 = ICBinaryOP::SubWithTSType(thread, arg1.GetTaggedValue(), JSTaggedValue::True(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle3.GetTaggedValue(), resInICPath3); -}; - -HWTEST_F_L0(ICBinaryOPTest, MulWithTSType) -{ - JSTaggedValue arg1Value(static_cast(28.5)); - JSTaggedValue arg2Value(static_cast(354)); - JSTaggedValue arg3Value(static_cast(9.5561)); - JSHandle arg1(thread, arg1Value); - JSHandle arg2(thread, arg2Value); - JSHandle arg3(thread, arg3Value); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Mul2(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle1(thread, resInSlowPath1); - JSTaggedValue resInICPath1 = ICBinaryOP::MulWithTSType(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle1.GetTaggedValue(), resInICPath1); - - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Mul2(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue()); - JSHandle slowHandle2(thread, resInSlowPath2); - JSTaggedValue resInICPath2 = ICBinaryOP::MulWithTSType(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle2.GetTaggedValue(), resInICPath2); - - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Mul2(thread, arg1.GetTaggedValue(), JSTaggedValue::True()); - JSHandle slowHandle3(thread, resInSlowPath3); - JSTaggedValue resInICPath3 = ICBinaryOP::MulWithTSType(thread, arg1.GetTaggedValue(), JSTaggedValue::True(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle3.GetTaggedValue(), resInICPath3); - -}; - -HWTEST_F_L0(ICBinaryOPTest, DivWithTSType) -{ - JSTaggedValue arg1Value(static_cast(2)); - JSTaggedValue arg2Value(static_cast(39884)); - JSTaggedValue arg3Value(static_cast(0)); - JSTaggedValue arg4Value(static_cast(934.5561)); - JSHandle arg1(thread, arg1Value); - JSHandle arg2(thread, arg2Value); - JSHandle arg3(thread, arg3Value); - JSHandle arg4(thread, arg4Value); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Div2(thread, arg3.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle1(thread, resInSlowPath1); - JSTaggedValue resInICPath1 = ICBinaryOP::DivWithTSType(thread, arg3.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle1.GetTaggedValue(), resInICPath1); - - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Div2(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue()); - JSHandle slowHandle2(thread, resInSlowPath2); - JSTaggedValue resInICPath2 = ICBinaryOP::DivWithTSType(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle2.GetTaggedValue(), resInICPath2); - - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Div2(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle3(thread, resInSlowPath3); - JSTaggedValue resInICPath3 = ICBinaryOP::DivWithTSType(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle3.GetTaggedValue(), resInICPath3); - - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Div2(thread, arg2.GetTaggedValue(), JSTaggedValue::True()); - JSHandle slowHandle4(thread, resInSlowPath4); - JSTaggedValue resInICPath4 = ICBinaryOP::DivWithTSType(thread, arg2.GetTaggedValue(), JSTaggedValue::True(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle4.GetTaggedValue(), resInICPath4); - - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Div2(thread, arg4.GetTaggedValue(), JSTaggedValue::False()); - JSHandle slowHandle5(thread, resInSlowPath5); - JSTaggedValue resInICPath5 = ICBinaryOP::DivWithTSType(thread, arg4.GetTaggedValue(), - JSTaggedValue::False(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle5.GetTaggedValue(), resInICPath5); -}; - -HWTEST_F_L0(ICBinaryOPTest, ModWithTSType) -{ - JSTaggedValue arg1Value(static_cast(2)); - JSTaggedValue arg2Value(static_cast(39884)); - JSTaggedValue arg3Value(static_cast(0)); - JSTaggedValue arg4Value(static_cast(934.5561)); - JSHandle arg1(thread, arg1Value); - JSHandle arg2(thread, arg2Value); - JSHandle arg3(thread, arg3Value); - JSHandle arg4(thread, arg4Value); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Mod2(thread, arg3.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle1(thread, resInSlowPath1); - JSTaggedValue resInICPath1 = ICBinaryOP::ModWithTSType(thread, arg3.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle1.GetTaggedValue(), resInICPath1); - - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Mod2(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue()); - JSHandle slowHandle2(thread, resInSlowPath2); - JSTaggedValue resInICPath2 = ICBinaryOP::ModWithTSType(thread, arg2.GetTaggedValue(), arg3.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle2.GetTaggedValue(), resInICPath2); - - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Mod2(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue()); - JSHandle slowHandle3(thread, resInSlowPath3); - JSTaggedValue resInICPath3 = ICBinaryOP::ModWithTSType(thread, arg1.GetTaggedValue(), arg2.GetTaggedValue(), - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(slowHandle3.GetTaggedValue(), resInICPath3); - - - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Mod2(thread, arg2.GetTaggedValue(), JSTaggedValue::True()); - JSHandle slowHandle4(thread, resInSlowPath4); - JSTaggedValue resInICPath4 = ICBinaryOP::ModWithTSType(thread, arg2.GetTaggedValue(), JSTaggedValue::True(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle4.GetTaggedValue(), resInICPath4); - - - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Mod2(thread, arg4.GetTaggedValue(), JSTaggedValue::False()); - JSHandle slowHandle5(thread, resInSlowPath5); - JSTaggedValue resInICPath5 = ICBinaryOP::ModWithTSType(thread, arg4.GetTaggedValue(), - JSTaggedValue::False(), - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(slowHandle5.GetTaggedValue(), resInICPath5); -}; - -HWTEST_F_L0(ICBinaryOPTest, ShlWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg3(static_cast(5)); - - JSTaggedValue resInICPath1 = ICBinaryOP::ShlWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(9152), resInICPath1); - - JSTaggedValue resInICPath2 = ICBinaryOP::ShlWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(7200), resInICPath2); -}; - -HWTEST_F_L0(ICBinaryOPTest, ShrWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg3(static_cast(5)); - - JSTaggedValue resInICPath1 = ICBinaryOP::ShrWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(8), resInICPath1); - - JSTaggedValue resInICPath2 = ICBinaryOP::ShrWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(7), resInICPath2); -}; - -HWTEST_F_L0(ICBinaryOPTest, AshrWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg2(static_cast(-286)); - JSTaggedValue arg3(static_cast(5)); - - JSTaggedValue resInICPath1 = ICBinaryOP::AshrWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(8), resInICPath1); - - JSTaggedValue resInICPath3 = ICBinaryOP::AshrWithTSType(thread, arg2, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(134217719), resInICPath3); - - JSTaggedValue resInICPath2 = ICBinaryOP::AshrWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(7), resInICPath2); - -}; -HWTEST_F_L0(ICBinaryOPTest, AndWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg3(static_cast(541)); - - JSTaggedValue resInICPath1 = ICBinaryOP::AndWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(28), resInICPath1); - - JSTaggedValue resInICPath2 = ICBinaryOP::AndWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(1), resInICPath2); -}; -HWTEST_F_L0(ICBinaryOPTest, OrWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg3(static_cast(523)); - - JSTaggedValue resInICPath1 = ICBinaryOP::OrWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(799), resInICPath1); - - JSTaggedValue resInICPath2 = ICBinaryOP::OrWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(747), resInICPath2); -}; -HWTEST_F_L0(ICBinaryOPTest, XorWithTSType) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = factory->NewFromASCII("1225"); - JSTaggedValue arg1(static_cast(286)); - JSTaggedValue arg3(static_cast(523)); - - JSTaggedValue resInICPath1 = ICBinaryOP::XorWithTSType(thread, arg1, arg3, - JSTaggedValue(static_cast(BinaryType::NUMBER))); - EXPECT_EQ(JSTaggedValue(789), resInICPath1); - - JSTaggedValue resInICPath2 = ICBinaryOP::XorWithTSType(thread, Str1.GetTaggedValue(), arg3, - JSTaggedValue(static_cast(BinaryType::GENERIC))); - EXPECT_EQ(JSTaggedValue(1730), resInICPath2); -}; -} // namespace panda::test diff --git a/ecmascript/ic/tests/ic_compareop_test.cpp b/ecmascript/ic/tests/ic_compareop_test.cpp deleted file mode 100644 index 29c676800ccdab0a4a2046401e4194183420b324..0000000000000000000000000000000000000000 --- a/ecmascript/ic/tests/ic_compareop_test.cpp +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "ecmascript/builtins/builtins_boolean.h" -#include "ecmascript/ecma_runtime_call_info.h" -#include "ecmascript/ecma_string.h" -#include "ecmascript/ecma_vm.h" -#include "ecmascript/global_env.h" -#include "ecmascript/global_env_constants.h" -#include "ecmascript/global_env_constants-inl.h" -#include "ecmascript/ic/ic_compare_op.cpp" -#include "ecmascript/ic/ic_compare_op.h" -#include "ecmascript/interpreter/slow_runtime_stub.h" -#include "ecmascript/js_primitive_ref.h" -#include "ecmascript/js_tagged_value-inl.h" -#include "ecmascript/object_factory.h" -#include "ecmascript/tests/test_helper.h" - -using namespace panda::ecmascript; -namespace panda::test { -class IcCompareOPTest : public testing::Test { -public: - static void SetUpTestCase() - { - GTEST_LOG_(INFO) << "SetUpTestCase"; - } - - static void TearDownTestCase() - { - GTEST_LOG_(INFO) << "TearDownCase"; - } - - void SetUp() override - { - TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope); - } - - void TearDown() override - { - TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope); - } - - EcmaVM *ecmaVm {nullptr}; - EcmaHandleScope *scope {nullptr}; - JSThread *thread {nullptr}; -}; - -HWTEST_F_L0(IcCompareOPTest, EqualWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("1")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(1.0)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(1))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Eq(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Eq(thread, Str1.GetTaggedValue(), arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Eq(thread, Str1.GetTaggedValue(), arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Eq(thread, Str1.GetTaggedValue(), arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Eq(thread, booleanObjHandle.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::Eq(thread, JSTaggedValue::Undefined(), JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::Eq(thread, JSTaggedValue::Undefined(), JSTaggedValue::True()); - - JSTaggedValue resInICPath1 = CompareOp::EqualWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::EqualWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::EqualWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::EqualWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::EqualWithIC(thread, booleanObjHandle.GetTaggedValue(), - arg4Handle.GetTaggedValue(), CompareOpType::OBJ_BOOLEAN); - JSTaggedValue resInICPath9 = CompareOp::EqualWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::EqualWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; - -HWTEST_F_L0(IcCompareOPTest, NotEqualWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("1")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(2.0)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(123))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::NotEq(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::NotEq(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::NotEq(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::NotEq(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::NotEq(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::NotEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::NotEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True()); - - JSTaggedValue resInICPath1 = CompareOp::NotEqualWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), - CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::NotEqualWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::NotEqualWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::NotEqualWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::NotEqualWithIC(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue(), - CompareOpType::NUMBER_OBJ); - JSTaggedValue resInICPath9 = CompareOp::NotEqualWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::NotEqualWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; - - -HWTEST_F_L0(IcCompareOPTest, LessWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("0")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(0.5)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(123))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Less(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Less(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Less(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Less(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Less(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::Less(thread, - JSTaggedValue::Undefined(), JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::Less(thread, - JSTaggedValue::Undefined(), JSTaggedValue::True()); - - JSTaggedValue resInICPath1 = CompareOp::LessWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::LessWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::LessWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::LessWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::LessWithIC(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue(), - CompareOpType::NUMBER_OBJ); - JSTaggedValue resInICPath9 = CompareOp::LessWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::LessWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; - - -HWTEST_F_L0(IcCompareOPTest, LessEqWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("1")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(0.5)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(123))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::LessEq(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::LessEq(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::LessEq(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::LessEq(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::LessEq(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::LessEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::LessEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True()); - JSTaggedValue resInICPath1 = CompareOp::LessEqWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), - CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::LessEqWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), - CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::LessEqWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::LessEqWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::LessEqWithIC(thread, - arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue(), - CompareOpType::NUMBER_OBJ); - JSTaggedValue resInICPath9 = CompareOp::LessEqWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::LessEqWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; - - -HWTEST_F_L0(IcCompareOPTest, GreaterWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("1")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(1.0)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(1))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::Greater(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::Greater(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::Greater(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Greater(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::Greater(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::Greater(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::Greater(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True()); - - JSTaggedValue resInICPath1 = CompareOp::GreaterWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), - CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::GreaterWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), - CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::GreaterWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::GreaterWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::GreaterWithIC(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue(), - CompareOpType::NUMBER_OBJ); - JSTaggedValue resInICPath9 = CompareOp::GreaterWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::GreaterWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; - - -HWTEST_F_L0(IcCompareOPTest, GreaterEqWithIC) -{ - ObjectFactory *factory = ecmaVm->GetFactory(); - - JSHandle Str1 = JSHandle(factory->NewFromASCII("1")); - JSTaggedValue arg1(static_cast(1)); - JSTaggedValue arg2(static_cast(1.0)); - JSTaggedValue arg3(false); - JSTaggedValue arg4(true); - JSHandle arg1Handle(thread, arg1); - JSHandle arg2Handle(thread, arg2); - JSHandle arg3Handle(thread, arg3); - JSHandle arg4Handle(thread, arg4); - - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); - JSHandle globalObject(thread, env->GetGlobalObject()); - - JSHandle boolean(env->GetBooleanFunction()); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*boolean), 6); - ecmaRuntimeCallInfo->SetFunction(boolean.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(0))); - - JSTaggedValue booleanObj = builtins::BuiltinsBoolean::BooleanConstructor(ecmaRuntimeCallInfo); - JSHandle booleanObjHandle(thread, booleanObj); - JSTaggedValue resInSlowPath1 = SlowRuntimeStub::GreaterEq(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath2 = SlowRuntimeStub::GreaterEq(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath3 = SlowRuntimeStub::GreaterEq(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath4 = SlowRuntimeStub::GreaterEq(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue()); - JSTaggedValue resInSlowPath5 = SlowRuntimeStub::GreaterEq(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue()); - JSTaggedValue resInSlowPath9 = SlowRuntimeStub::GreaterEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null()); - JSTaggedValue resInSlowPath10 = SlowRuntimeStub::GreaterEq(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True()); - - JSTaggedValue resInICPath1 = CompareOp::GreaterEqWithIC(thread, arg1Handle.GetTaggedValue(), - arg2Handle.GetTaggedValue(), - CompareOpType::NUMBER_NUMBER); - JSTaggedValue resInICPath2 = CompareOp::GreaterEqWithIC(thread, Str1.GetTaggedValue(), - arg1Handle.GetTaggedValue(), - CompareOpType::STRING_NUMBER); - JSTaggedValue resInICPath3 = CompareOp::GreaterEqWithIC(thread, Str1.GetTaggedValue(), - arg3Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath4 = CompareOp::GreaterEqWithIC(thread, Str1.GetTaggedValue(), - arg4Handle.GetTaggedValue(), - CompareOpType::STRING_BOOLEAN); - JSTaggedValue resInICPath5 = CompareOp::GreaterEqWithIC(thread, arg1Handle.GetTaggedValue(), - booleanObjHandle.GetTaggedValue(), - CompareOpType::NUMBER_OBJ); - JSTaggedValue resInICPath9 = CompareOp::GreaterEqWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::Null(), CompareOpType::UNDEFINED_NULL); - JSTaggedValue resInICPath10 = CompareOp::GreaterEqWithIC(thread, JSTaggedValue::Undefined(), - JSTaggedValue::True(), CompareOpType::OTHER); - - EXPECT_EQ(resInSlowPath1, resInICPath1); - EXPECT_EQ(resInSlowPath2, resInICPath2); - EXPECT_EQ(resInSlowPath3, resInICPath3); - EXPECT_EQ(resInSlowPath4, resInICPath4); - EXPECT_EQ(resInSlowPath5, resInICPath5); - EXPECT_EQ(resInSlowPath9, resInICPath9); - EXPECT_EQ(resInSlowPath10, resInICPath10); -}; -} // namespace panda::test diff --git a/ecmascript/ic/tests/ic_invoke_test.cpp b/ecmascript/ic/tests/ic_invoke_test.cpp deleted file mode 100644 index 69793a18d2f574bc4934c499994caa4b8172558a..0000000000000000000000000000000000000000 --- a/ecmascript/ic/tests/ic_invoke_test.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ecmascript/ecma_vm.h" -#include "ecmascript/ic/invoke_cache.h" -#include "ecmascript/object_factory.h" -#include "ecmascript/tests/test_helper.h" - -using namespace panda::ecmascript; -namespace panda::test { -class ICInvokeTest : public testing::Test { -public: - static void SetUpTestCase() - { - GTEST_LOG_(INFO) << "SetUpTestCase"; - } - - static void TearDownTestCase() - { - GTEST_LOG_(INFO) << "TearDownCase"; - } - - void SetUp() override - { - TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope); - } - - void TearDown() override - { - TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope); - } - - EcmaVM *ecmaVm = nullptr; - EcmaHandleScope *scope {nullptr}; - JSThread *thread {nullptr}; -}; - -HWTEST_F_L0(ICInvokeTest, SetMonoConstuctCacheSlot) -{ - auto globalEnv = ecmaVm->GetGlobalEnv(); - auto factory = ecmaVm->GetFactory(); - JSHandle func = factory->NewJSFunction(globalEnv); - func.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true); - - JSHandle array = factory->NewTaggedArray(10); - uint32_t slotId = 5; - bool setResult = InvokeCache::SetMonoConstuctCacheSlot( - thread, static_cast(*array), slotId, func.GetTaggedValue(), JSTaggedValue(123)); - ASSERT_TRUE(setResult); - ASSERT_EQ(array->Get(thread, slotId), func.GetTaggedValue()); - ASSERT_EQ(array->Get(thread, slotId + 1), JSTaggedValue(123)); -} - -HWTEST_F_L0(ICInvokeTest, SetPolyConstuctCacheSlot) -{ - auto globalEnv = ecmaVm->GetGlobalEnv(); - auto factory = ecmaVm->GetFactory(); - JSHandle array1 = factory->NewTaggedArray(3); - JSHandle array2 = factory->NewTaggedArray(3); - - JSHandle func0 = factory->NewJSFunction(globalEnv); - func0.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true); - array1->Set(thread, 0, func0.GetTaggedValue()); - array2->Set(thread, 0, JSTaggedValue(123)); - JSHandle func1 = factory->NewJSFunction(globalEnv); - func1.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true); - array1->Set(thread, 1, func1.GetTaggedValue()); - array2->Set(thread, 1, JSTaggedValue(456)); - JSHandle func2 = factory->NewJSFunction(globalEnv); - func2.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassConstructor(true); - array1->Set(thread, 2, func2.GetTaggedValue()); - array2->Set(thread, 2, JSTaggedValue(789)); - - JSHandle array = factory->NewTaggedArray(10); - uint32_t slotId = 5; - bool setResult = InvokeCache::SetPolyConstuctCacheSlot( - thread, static_cast(*array), slotId, 3, array1.GetTaggedValue(), array2.GetTaggedValue()); - ASSERT_TRUE(setResult); - JSTaggedValue slot = array->Get(thread, slotId); - ASSERT_TRUE(slot.IsTaggedArray()); - JSHandle slotArray(thread, slot); - ASSERT_EQ(slotArray->Get(thread, 0), func0.GetTaggedValue()); - ASSERT_EQ(slotArray->Get(thread, 1), JSTaggedValue(123)); - ASSERT_EQ(slotArray->Get(thread, 2), func1.GetTaggedValue()); - ASSERT_EQ(slotArray->Get(thread, 3), JSTaggedValue(456)); - ASSERT_EQ(slotArray->Get(thread, 4), func2.GetTaggedValue()); - ASSERT_EQ(slotArray->Get(thread, 5), JSTaggedValue(789)); - ASSERT_EQ(array->Get(thread, slotId + 1), JSTaggedValue::Hole()); -} - -HWTEST_F_L0(ICInvokeTest, CheckPolyInvokeCache) -{ - auto globalEnv = ecmaVm->GetGlobalEnv(); - auto factory = ecmaVm->GetFactory(); - JSHandle array = factory->NewTaggedArray(6); - - JSHandle func0 = factory->NewJSFunction(globalEnv); - JSHandle func1 = factory->NewJSFunction(globalEnv); - JSHandle func2 = factory->NewJSFunction(globalEnv); - JSHandle func3 = factory->NewJSFunction(globalEnv); - array->Set(thread, 0, func0.GetTaggedValue()); - array->Set(thread, 1, JSTaggedValue(123)); - array->Set(thread, 2, func1.GetTaggedValue()); - array->Set(thread, 3, JSTaggedValue(456)); - array->Set(thread, 4, func2.GetTaggedValue()); - array->Set(thread, 5, JSTaggedValue(789)); - - JSTaggedValue testValue0 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func0.GetTaggedValue()); - ASSERT_EQ(testValue0, JSTaggedValue(123)); - JSTaggedValue testValue1 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func1.GetTaggedValue()); - ASSERT_EQ(testValue1, JSTaggedValue(456)); - JSTaggedValue testValue2 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func2.GetTaggedValue()); - ASSERT_EQ(testValue2, JSTaggedValue(789)); - JSTaggedValue testValue3 = InvokeCache::CheckPolyInvokeCache(array.GetTaggedValue(), func3.GetTaggedValue()); - ASSERT_EQ(testValue3, JSTaggedValue::Hole()); -} -} // namespace panda::test \ No newline at end of file diff --git a/ecmascript/ic/tests/ic_runtime_test.cpp b/ecmascript/ic/tests/ic_runtime_test.cpp index 5060ccaa41f84ea8d611e0dda6e924c590c194fc..963e1f4ac95ac8d65ed72b628a7368a2419635a3 100644 --- a/ecmascript/ic/tests/ic_runtime_test.cpp +++ b/ecmascript/ic/tests/ic_runtime_test.cpp @@ -155,8 +155,8 @@ HWTEST_F_L0(ICRunTimeTest, TraceIC) JSHandle handleProfileTypeInfo = factory->NewProfileTypeInfo(arrayLength); ICRuntime icRuntime(thread, handleProfileTypeInfo, 4, ICKind::NamedGlobalLoadIC); // 4: means the NamedGlobalLoadIC - icRuntime.TraceIC(handleReceiver, handleKeyWithString); - icRuntime.TraceIC(handleReceiver, handleKeyWithElement); + icRuntime.TraceIC(thread, handleReceiver, handleKeyWithString); + icRuntime.TraceIC(thread, handleReceiver, handleKeyWithElement); } HWTEST_F_L0(ICRunTimeTest, StoreMiss) diff --git a/ecmascript/interpreter/interpreter-inl.cpp b/ecmascript/interpreter/interpreter-inl.cpp index cae3789af40d0e2a7efeb239ab480a6a48821d7a..fd2649a01da669e72c88adc7c75da5cb97e68a17 100644 --- a/ecmascript/interpreter/interpreter-inl.cpp +++ b/ecmascript/interpreter/interpreter-inl.cpp @@ -2177,8 +2177,9 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t // fast path double doubleBase = base.IsInt() ? base.GetInt() : base.GetDouble(); double doubleExponent = exponent.IsInt() ? exponent.GetInt() : exponent.GetDouble(); - if (std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) { + if ((std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) || std::isnan(doubleExponent)) { SET_ACC(JSTaggedValue(base::NAN_VALUE)); + DISPATCH(EXP_IMM8_V8); } bool baseZero = doubleBase == 0 && (base::bit_cast(doubleBase) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK; diff --git a/ecmascript/interpreter/interpreter_assembly.cpp b/ecmascript/interpreter/interpreter_assembly.cpp index 99b277383f32fabe5a900ab4ff1e1c21033ba3d6..e825775cc8691dbc30ee9c43fa1a631471b58cc8 100644 --- a/ecmascript/interpreter/interpreter_assembly.cpp +++ b/ecmascript/interpreter/interpreter_assembly.cpp @@ -210,6 +210,9 @@ JSTaggedValue InterpreterAssembly::Execute(EcmaRuntimeCallInfo *info) ASSERT(info); JSThread *thread = info->GetThread(); INTERPRETER_TRACE(thread, AsmExecute); +#if ECMASCRIPT_ENABLE_INTERPRETER_ARKUINAITVE_TRACE + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "ArkCompiler::InterpreterAssembly::Execute"); +#endif // When the function is jit-compiled, the Method object is reinstalled. // In this case, the AotWithCall field may be updated. // This causes a Construct that is not a ClassConstructor to call jit code. @@ -1523,7 +1526,7 @@ void InterpreterAssembly::HandleExpImm8V8( // fast path double doubleBase = base.IsInt() ? base.GetInt() : base.GetDouble(); double doubleExponent = exponent.IsInt() ? exponent.GetInt() : exponent.GetDouble(); - if (std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) { + if ((std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) || std::isnan(doubleExponent)) { SET_ACC(JSTaggedValue(base::NAN_VALUE)); } bool baseZero = doubleBase == 0 && diff --git a/ecmascript/jit/compile_decision.cpp b/ecmascript/jit/compile_decision.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cab6df7e60d660525c79144b5a8dd2435ef1ed71 --- /dev/null +++ b/ecmascript/jit/compile_decision.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/jit/compile_decision.h" +#include "ecmascript/jit/jit.h" +#include "ecmascript/jspandafile/js_pandafile.h" +#include "ecmascript/ic/profile_type_info.h" + +namespace panda::ecmascript { +CompileDecision::CompileDecision(EcmaVM *vm, JSHandle &jsFunction, CompilerTier tier, + int32_t osrOffset, JitCompileMode mode) : vm_(vm), jsFunction_(jsFunction), + tier_(tier), osrOffset_(osrOffset), compileMode_(mode) { } + +CString CompileDecision::GetMethodInfo() const +{ + uint32_t codeSize = GetCodeSize(); + return GetMethodName() + ", bytecode size:" + ToCString(codeSize); +} + +CString CompileDecision::GetMethodName() const +{ + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + auto jSPandaFile = method->GetJSPandaFile(); + ASSERT(jSPandaFile != nullptr); + CString fileDesc = jSPandaFile->GetJSPandaFileDesc(); + return fileDesc + ":" + method->GetRecordNameStr() + "." + CString(method->GetMethodName()); +} + +uint32_t CompileDecision::GetCodeSize() const +{ + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + return method->GetCodeSize(); +} + +bool CompileDecision::Decision() +{ + return IsGoodCompilationRequest(); +} + +bool CompileDecision::IsGoodCompilationRequest() const +{ + if (!CheckJsFunctionStatus()) { + return false; + } + + if (!IsJsFunctionSupportCompile()) { + DisableJitCompile(); + return false; + } + + if (!CheckVmState()) { + return false; + } + return true; +} + +bool CompileDecision::IsJsFunctionSupportCompile() const +{ + if (!IsSupportFunctionKind()) { + return false; + } + + uint32_t maxSize = 9000; + if (vm_->GetJSOptions().IsEnableJitFastCompile()) { + maxSize = 15; // 15 is method codesize threshold during fast compiling + } + if (GetCodeSize() > maxSize && !(vm_->GetJSOptions().IsEnableForceJitCompileMain() && compileMode_.IsSync())) { + LOG_JIT(DEBUG) << tier_ << "skip jit task, as too large:" << GetMethodInfo(); + return false; + } + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + if (vm_->IsEnableOsr() && osrOffset_ != MachineCode::INVALID_OSR_OFFSET && method->HasCatchBlock()) { + LOG_JIT(DEBUG) << "skip jit task, as osr does not support catch blocks: " << GetMethodInfo(); + return false; + } + return true; +} + +bool CompileDecision::IsSupportFunctionKind() const +{ + Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); + if (jsFunction_.GetTaggedValue().IsJSSharedFunction()) { + LOG_JIT(DEBUG) << tier_ << "method does not support compile shared function:" << GetMethodInfo(); + return false; + } + + FunctionKind kind = method->GetFunctionKind(); + switch (kind) { + case FunctionKind::NORMAL_FUNCTION: + case FunctionKind::GETTER_FUNCTION: + case FunctionKind::SETTER_FUNCTION: + case FunctionKind::ARROW_FUNCTION: + case FunctionKind::BASE_CONSTRUCTOR: + case FunctionKind::CLASS_CONSTRUCTOR: + case FunctionKind::DERIVED_CONSTRUCTOR: + case FunctionKind::NONE_FUNCTION: + return true; + default: + break; + } + LOG_JIT(DEBUG) << tier_ << "method does not support jit:" << GetMethodInfo() << ", kind:" << static_cast(kind); + return false; +} + +bool CompileDecision::CheckJsFunctionStatus() const +{ + if (jsFunction_->IsJitCompiling()) { + return false; + } + + if (tier_.IsFast() && jsFunction_->IsCompiledCode()) { + JSTaggedValue machineCode = jsFunction_->GetMachineCode(); + if (machineCode.IsMachineCodeObject() && + MachineCode::Cast(machineCode.GetTaggedObject())->GetOSROffset() == MachineCode::INVALID_OSR_OFFSET) { + return false; + } + return true; + } + + if (tier_.IsBaseLine() && !jsFunction_->GetBaselineCode().IsUndefined()) { + return false; + } + return true; +} + +void CompileDecision::DisableJitCompile() const +{ + jsFunction_->SetJitHotnessCnt(ProfileTypeInfo::JIT_DISABLE_FLAG); +} + +bool CompileDecision::CheckVmState() const +{ + if (vm_->GetJSThread()->IsMachineCodeLowMemory()) { + LOG_JIT(DEBUG) << tier_ << "skip jit task, as low code memory:" << GetMethodInfo(); + return false; + } + return true; +} +} // namespace panda::ecmascript diff --git a/ecmascript/jit/compile_decision.h b/ecmascript/jit/compile_decision.h new file mode 100644 index 0000000000000000000000000000000000000000..00cb7d2e86ca2ede9883b1bf78ec51a00255fe6d --- /dev/null +++ b/ecmascript/jit/compile_decision.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_JIT_COMPILE_DECISION_H +#define ECMASCRIPT_JIT_COMPILE_DECISION_H + +#include "ecmascript/ecma_vm.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/js_function.h" + +namespace panda::ecmascript { +class JitCompileMode { +public: + enum class Mode : uint8_t { + SYNC = 0, + ASYNC + }; + + JitCompileMode(Mode mode) : mode_(mode) {} + + bool IsAsync() const + { + return mode_ == Mode::ASYNC; + } + + bool IsSync() const + { + return mode_ == Mode::SYNC; + } + +private: + Mode mode_; +}; + +class CompilerTier { +public: + enum class Tier : uint8_t { + BASELINE, + FAST, + }; + + CompilerTier(Tier tier) : tier_(tier) {} + bool IsFast() const + { + return tier_ == Tier::FAST; + } + + bool IsBaseLine() const + { + return tier_ == Tier::BASELINE; + } + + friend std::ostream &operator<<(std::ostream &os, const CompilerTier &tier) + { + os << (tier.IsFast() ? "[fastjit] " : " [baselinejit] "); + return os; + } + +private: + Tier tier_; +}; + +class CompileDecision { +public: + CompileDecision(EcmaVM *vm, JSHandle &jsFunction, CompilerTier tier, + int32_t osrOffset, JitCompileMode mode); + bool Decision(); + + CompilerTier GetTier() const + { + return tier_; + } + + JSHandle GetJsFunction() const + { + return jsFunction_; + } + + CString GetMethodInfo() const; + CString GetMethodName() const; + uint32_t GetCodeSize() const; + int32_t GetOsrOffset() const + { + return osrOffset_; + } + + JitCompileMode GetCompileMode() const + { + return compileMode_; + } + +private: + bool IsGoodCompilationRequest() const; + bool IsSupportFunctionKind() const; + bool CheckJsFunctionStatus() const; + bool IsJsFunctionSupportCompile() const; + void DisableJitCompile() const; + bool CheckVmState() const; + + EcmaVM *vm_; + JSHandle jsFunction_; + CompilerTier tier_; + int32_t osrOffset_; + JitCompileMode compileMode_; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_JIT_JIT_COMPILE_DECISION_H diff --git a/ecmascript/jit/jit.cpp b/ecmascript/jit/jit.cpp index bc479107b784aa477224bf830d6ea94589a00271..c7f5956cd72d8a67c81227e2bc88ecd21e04ee23 100644 --- a/ecmascript/jit/jit.cpp +++ b/ecmascript/jit/jit.cpp @@ -20,12 +20,6 @@ #include "ecmascript/checkpoint/thread_state_transition.h" namespace panda::ecmascript { -void (*Jit::initJitCompiler_)(JSRuntimeOptions options) = nullptr; -bool(*Jit::jitCompile_)(void*, JitTask*) = nullptr; -bool(*Jit::jitFinalize_)(void*, JitTask*) = nullptr; -void*(*Jit::createJitCompilerTask_)(JitTask*) = nullptr; -void(*Jit::deleteJitCompile_)(void*) = nullptr; -void *Jit::libHandle_ = nullptr; Jit *Jit::GetInstance() { @@ -33,22 +27,46 @@ Jit *Jit::GetInstance() return &instance_; } +void Jit::CreateJitResources() +{ + if (jitResources_ == nullptr) { + jitResources_ = std::make_unique(); + jitResources_->ResolveLib(); + } +} + +bool Jit::IsLibResourcesResolved() const +{ + if (jitResources_ != nullptr) { + return jitResources_->IsLibResolved(); + } + return false; +} + +void Jit::PreFork() +{ + CreateJitResources(); +} + void Jit::SetJitEnablePostFork(EcmaVM *vm, const std::string &bundleName) { JSRuntimeOptions &options = vm->GetJSOptions(); bool jitEnable = ohos::JitTools::GetJitEscapeDisable() || !AotCrashInfo::IsJitEscape(); jitEnable &= ohos::EnableAotJitListHelper::GetInstance()->IsEnableJit(bundleName); jitEnable &= !vm->GetJSOptions().GetAOTHasException(); + jitEnable &= ohos::JitTools::IsSupportJitCodeSigner(); if (jitEnable) { bool isEnableFastJit = options.IsEnableJIT() && options.GetEnableAsmInterpreter(); bool isEnableBaselineJit = options.IsEnableBaselineJIT() && options.GetEnableAsmInterpreter(); options.SetEnableJitFrame(ohos::JitTools::GetJitFrameEnable()); options.SetEnableAPPJIT(true); + isApp_ = true; // for app threshold uint32_t defaultSize = 3000; uint32_t threshold = ohos::JitTools::GetJitHotnessThreshold(defaultSize); options.SetJitHotnessThreshold(threshold); + hotnessThreshold_ = threshold; bundleName_ = bundleName; isEnableAppPGO_ = pgo::PGOProfilerManager::GetInstance()->IsEnable(); @@ -134,68 +152,36 @@ void Jit::ConfigJitFortOptions(EcmaVM *vm) void Jit::SetEnableOrDisable(const JSRuntimeOptions &options, bool isEnableFastJit, bool isEnableBaselineJit) { LockHolder holder(setEnableLock_); - - bool needInitialize = false; - if (!isEnableFastJit) { - fastJitEnable_ = false; - } else { - needInitialize = true; + bool enableJit = isEnableFastJit || isEnableBaselineJit; + if (enableJit) { + CreateJitResources(); } - if (!isEnableBaselineJit) { - baselineJitEnable_ = false; - } else { - needInitialize = true; - } - if (!needInitialize) { - return; - } - if (!initialized_) { - Initialize(); + + if (IsLibResourcesResolved()) { + jitDfx_ = JitDfx::GetInstance(); + jitDfx_->Init(options, bundleName_); + jitResources_->InitJitEnv(options); + initialized_ = true; } + if (initialized_) { - bool jitEnable = false; - if (isEnableFastJit && !fastJitEnable_) { - fastJitEnable_ = true; - jitEnable = true; - } - if (isEnableBaselineJit && !baselineJitEnable_) { - baselineJitEnable_ = true; - jitEnable = true; - } - if (jitEnable) { - jitDfx_ = JitDfx::GetInstance(); - jitDfx_->Init(options, bundleName_); - - isApp_ = options.IsEnableAPPJIT(); - hotnessThreshold_ = options.GetJitHotnessThreshold(); - initJitCompiler_(options); - bool enableCodeSign = !ohos::JitTools::GetCodeSignDisable(options.GetDisableCodeSign()); - bool shouldCompileMain = - options.IsEnableForceJitCompileMain() || options.IsEnableForceBaselineCompileMain(); - if (enableCodeSign && shouldCompileMain) { - JitFort::InitJitFortResource(); - } - JitTaskpool::GetCurrentTaskpool()->Initialize(enableCodeSign && !shouldCompileMain); - } + fastJitEnable_ = isEnableFastJit; + baselineJitEnable_ = isEnableBaselineJit; } } void Jit::Destroy() { + LockHolder holder(setEnableLock_); if (!initialized_) { return; } - LockHolder holder(setEnableLock_); - - JitTaskpool::GetCurrentTaskpool()->Destroy(); initialized_ = false; fastJitEnable_ = false; baselineJitEnable_ = false; - if (libHandle_ != nullptr) { - CloseLib(libHandle_); - libHandle_ = nullptr; - } + jitResources_->Destroy(); + jitResources_ = nullptr; } bool Jit::IsEnableFastJit() const @@ -238,99 +224,10 @@ void Jit::SetEnableAsyncCopyToFort(bool isEnableAsyncCopyToFort) isEnableAsyncCopyToFort_ = isEnableAsyncCopyToFort; } -void Jit::Initialize() -{ - static const std::string CREATEJITCOMPILETASK = "CreateJitCompilerTask"; - static const std::string JITCOMPILEINIT = "InitJitCompiler"; - static const std::string JITCOMPILE = "JitCompile"; - static const std::string JITFINALIZE = "JitFinalize"; - static const std::string DELETEJITCOMPILE = "DeleteJitCompile"; - static const std::string LIBARK_JSOPTIMIZER = "libark_jsoptimizer.so"; - - libHandle_ = LoadLib(LIBARK_JSOPTIMIZER); - if (libHandle_ == nullptr) { - char *error = LoadLibError(); - LOG_JIT(ERROR) << "jit dlopen libark_jsoptimizer.so failed, as:" << - ((error == nullptr) ? "unknown error" : error); - return; - } - - initJitCompiler_ = reinterpret_cast(FindSymbol(libHandle_, JITCOMPILEINIT.c_str())); - if (initJitCompiler_ == nullptr) { - LOG_JIT(ERROR) << "jit can't find symbol initJitCompiler"; - return; - } - jitCompile_ = reinterpret_cast(FindSymbol(libHandle_, JITCOMPILE.c_str())); - if (jitCompile_ == nullptr) { - LOG_JIT(ERROR) << "jit can't find symbol jitCompile"; - return; - } - - jitFinalize_ = reinterpret_cast(FindSymbol(libHandle_, JITFINALIZE.c_str())); - if (jitFinalize_ == nullptr) { - LOG_JIT(ERROR) << "jit can't find symbol jitFinalize"; - return; - } - - createJitCompilerTask_ = reinterpret_cast(FindSymbol(libHandle_, - CREATEJITCOMPILETASK.c_str())); - if (createJitCompilerTask_ == nullptr) { - LOG_JIT(ERROR) << "jit can't find symbol createJitCompilertask"; - return; - } - - deleteJitCompile_ = reinterpret_cast(FindSymbol(libHandle_, DELETEJITCOMPILE.c_str())); - if (deleteJitCompile_ == nullptr) { - LOG_JIT(ERROR) << "jit can't find symbol deleteJitCompile"; - return; - } - initialized_= true; - return; -} - Jit::~Jit() { } -bool Jit::SupportJIT(JSHandle &jsFunction, [[maybe_unused]] EcmaVM *vm, CompilerTier tier) const -{ - Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject()); - if (jsFunction.GetTaggedValue().IsJSSharedFunction()) { - LOG_JIT(DEBUG) << "method does not support compile shared function:" << - method->GetRecordNameStr() + "." + method->GetMethodName(); - return false; - } - - FunctionKind kind = method->GetFunctionKind(); - switch (kind) { - case FunctionKind::NORMAL_FUNCTION: - case FunctionKind::GETTER_FUNCTION: - case FunctionKind::SETTER_FUNCTION: - case FunctionKind::ARROW_FUNCTION: - case FunctionKind::BASE_CONSTRUCTOR: - case FunctionKind::CLASS_CONSTRUCTOR: - case FunctionKind::DERIVED_CONSTRUCTOR: - case FunctionKind::NONE_FUNCTION: - return true; - default: - break; - } - std::stringstream msgStr; - msgStr << "method does not support jit:" << method->GetRecordNameStr() + "." + method->GetMethodName() << - ", kind:" << static_cast(kind); - if (tier == CompilerTier::BASELINE) { - LOG_BASELINEJIT(DEBUG) << msgStr.str(); - } else { - LOG_JIT(DEBUG) << msgStr.str(); - } - return false; -} - -void Jit::DeleteJitCompile(void *compiler) -{ - deleteJitCompile_(compiler); -} - void Jit::CountInterpExecFuncs(JSHandle &jsFunction) { Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject()); @@ -345,86 +242,53 @@ void Jit::CountInterpExecFuncs(JSHandle &jsFunction) } void Jit::Compile(EcmaVM *vm, JSHandle &jsFunction, CompilerTier tier, - int32_t offset, JitCompileMode mode) + int32_t osrOffset, JitCompileMode mode) { auto jit = Jit::GetInstance(); - if ((!jit->IsEnableBaselineJit() && tier == CompilerTier::BASELINE) || - (!jit->IsEnableFastJit() && tier == CompilerTier::FAST)) { + if ((!jit->IsEnableBaselineJit() && tier.IsBaseLine()) || + (!jit->IsEnableFastJit() && tier.IsFast())) { return; } - if (!vm->IsEnableOsr() && offset != MachineCode::INVALID_OSR_OFFSET) { + if (!vm->IsEnableOsr() && osrOffset != MachineCode::INVALID_OSR_OFFSET) { return; } - Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject()); - auto jSPandaFile = method->GetJSPandaFile(); - ASSERT(jSPandaFile != nullptr); - CString fileDesc = jSPandaFile->GetJSPandaFileDesc(); - CString methodName = fileDesc + ":" + method->GetRecordNameStr() + "." + CString(method->GetMethodName()); - uint32_t codeSize = method->GetCodeSize(); - CString methodInfo = methodName + ", bytecode size:" + ToCString(codeSize); - ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, ConvertToStdString("JIT::Compile:" + methodInfo)); - - uint32_t maxSize = 9000; - if (vm->GetJSOptions().IsEnableJitFastCompile()) { - maxSize = 15; // 15 is method codesize threshold during fast compiling - } - if (codeSize > maxSize && !(vm->GetJSOptions().IsEnableForceJitCompileMain() && mode == SYNC)) { - if (tier == CompilerTier::BASELINE) { - LOG_BASELINEJIT(DEBUG) << "skip jit task, as too large:" << methodInfo; - } else { - LOG_JIT(DEBUG) << "skip jit task, as too large:" << methodInfo; - } - - return; - } - if (vm->IsEnableOsr() && offset != MachineCode::INVALID_OSR_OFFSET && method->HasCatchBlock()) { - LOG_JIT(DEBUG) << "skip jit task, as osr does not support catch blocks: " << methodInfo; + CompileDecision compileDecision(vm, jsFunction, tier, osrOffset, mode); + if (!compileDecision.Decision()) { return; } + jit->Compile(vm, compileDecision); +} + +void Jit::Compile(EcmaVM *vm, const CompileDecision &decision) +{ + auto tier = decision.GetTier(); + auto jsFunction = decision.GetJsFunction(); + auto methodInfo = decision.GetMethodInfo(); + auto methodName = decision.GetMethodName(); + auto osrOffset = decision.GetOsrOffset(); + auto mode = decision.GetCompileMode(); + CString msg = "compile method:" + methodInfo + ", in work thread"; TimeScope scope(vm, msg, tier, true, true); - if (vm->GetJSThread()->IsMachineCodeLowMemory()) { - if (tier == CompilerTier::BASELINE) { - LOG_BASELINEJIT(DEBUG) << "skip jit task, as low code memory:" << methodInfo; - } else { - LOG_JIT(DEBUG) << "skip jit task, as low code memory:" << methodInfo; - } - - return; - } - if (!jit->SupportJIT(jsFunction, vm, tier)) { - return; - } - bool needCompile = jit->CheckJitCompileStatus(jsFunction, methodName, tier); - if (!needCompile) { - return; - } - // using hole value to indecate compiling. todo: reset when failed - if (tier == CompilerTier::FAST) { - jsFunction->SetMachineCode(vm->GetJSThread(), JSTaggedValue::Hole()); - jit->GetJitDfx()->SetTriggerCount(false); - } else { - ASSERT(tier == CompilerTier::BASELINE); - jsFunction->SetBaselineCode(vm->GetJSThread(), JSTaggedValue::Hole()); - jit->GetJitDfx()->SetTriggerCount(true); - } + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, ConvertToStdString("JIT::Compile:" + methodInfo)); + jsFunction->SetJitCompilingFlag(true); + GetJitDfx()->SetTriggerCount(tier); { JitTaskpool::GetCurrentTaskpool()->WaitForJitTaskPoolReady(); EcmaVM *compilerVm = JitTaskpool::GetCurrentTaskpool()->GetCompilerVm(); std::shared_ptr jitTask = std::make_shared(vm->GetJSThread(), // avoid check fail when enable multi-thread check - compilerVm->GetJSThreadNoCheck(), - jit, jsFunction, tier, methodName, offset, vm->GetJSThread()->GetThreadId(), mode); + compilerVm->GetJSThreadNoCheck(), this, jsFunction, tier, methodName, osrOffset, mode); jitTask->PrepareCompile(); JitTaskpool::GetCurrentTaskpool()->PostTask( std::make_unique(jitTask, vm->GetJSThread()->GetThreadId())); - if (mode == SYNC) { + if (mode.IsSync()) { // sync mode, also compile in taskpool as litecg unsupport parallel compile, // wait task compile finish then install code jitTask->WaitFinish(); @@ -432,7 +296,7 @@ void Jit::Compile(EcmaVM *vm, JSHandle &jsFunction, CompilerTier tie } int spendTime = scope.TotalSpentTimeInMicroseconds(); jitTask->SetMainThreadCompilerTime(spendTime); - jit->GetJitDfx()->RecordSpentTimeAndPrintStatsLogInJsThread(spendTime); + GetJitDfx()->RecordSpentTimeAndPrintStatsLogInJsThread(spendTime); } } @@ -450,45 +314,6 @@ void Jit::RequestInstallCode(std::shared_ptr jitTask) jitTask->GetHostThread()->SetCheckSafePointStatus(); } -bool Jit::CheckJitCompileStatus(JSHandle &jsFunction, - const CString &methodName, CompilerTier tier) -{ - if (tier == CompilerTier::FAST && - jsFunction->GetMachineCode() == JSTaggedValue::Hole()) { - LOG_JIT(DEBUG) << "skip method, as it compiling:" << methodName; -#if ECMASCRIPT_ENABLE_JIT_WARMUP_PROFILER - auto &profMap = JitWarmupProfiler::GetInstance()->profMap_; - if (profMap.find(methodName) != profMap.end()) { - profMap.erase(methodName); - } -#endif - return false; - } - - if (tier == CompilerTier::BASELINE && - jsFunction->GetBaselineCode() == JSTaggedValue::Hole()) { - LOG_BASELINEJIT(DEBUG) << "skip method, as it compiling:" << methodName; - return false; - } - - if (tier == CompilerTier::FAST && jsFunction->IsCompiledCode()) { - JSTaggedValue machineCode = jsFunction->GetMachineCode(); - if (machineCode.IsMachineCodeObject() && - MachineCode::Cast(machineCode.GetTaggedObject())->GetOSROffset() == MachineCode::INVALID_OSR_OFFSET) { - LOG_JIT(DEBUG) << "skip method, as it has been jit compiled:" << methodName; - return false; - } - return true; - } - - if (tier == CompilerTier::BASELINE && - jsFunction->GetBaselineCode() != JSTaggedValue::Undefined()) { - LOG_BASELINEJIT(DEBUG) << "skip method, as it has been jit compiled:" << methodName; - return false; - } - return true; -} - uint32_t Jit::GetRunningTaskCnt(EcmaVM *vm) { uint32_t cnt = 0; @@ -522,20 +347,22 @@ void Jit::InstallTasks(JSThread *jsThread) bool Jit::JitCompile(void *compiler, JitTask *jitTask) { - ASSERT(jitCompile_ != nullptr); - return jitCompile_(compiler, jitTask); + return jitResources_->Compile(compiler, jitTask); } bool Jit::JitFinalize(void *compiler, JitTask *jitTask) { - ASSERT(jitFinalize_ != nullptr); - return jitFinalize_(compiler, jitTask); + return jitResources_->Finalize(compiler, jitTask); } void *Jit::CreateJitCompilerTask(JitTask *jitTask) { - ASSERT(createJitCompilerTask_ != nullptr); - return createJitCompilerTask_(jitTask); + return jitResources_->CreateJitCompilerTask(jitTask); +} + +void Jit::DeleteJitCompilerTask(void *compiler) +{ + jitResources_->DeleteJitCompilerTask(compiler); } void Jit::ClearTask(const std::function &checkClear) @@ -621,23 +448,13 @@ Jit::TimeScope::~TimeScope() return; } if (isDebugLevel_) { - if (tier_ == CompilerTier::BASELINE) { - LOG_BASELINEJIT(DEBUG) << message_ << ": " << TotalSpentTime() << "ms"; - return; - } - ASSERT(tier_ == CompilerTier::FAST); - LOG_JIT(DEBUG) << message_ << ": " << TotalSpentTime() << "ms"; + LOG_JIT(DEBUG) << tier_ << message_ << ": " << TotalSpentTime() << "ms"; } else { - if (tier_ == CompilerTier::BASELINE) { - LOG_BASELINEJIT(INFO) << message_ << ": " << TotalSpentTime() << "ms"; - return; - } - ASSERT(tier_ == CompilerTier::FAST); auto bundleName = vm_->GetBundleName(); if (vm_->GetEnableJitLogSkip() && bundleName != "" && message_.find(bundleName) == std::string::npos) { return; } - LOG_JIT(INFO) << message_ << ": " << TotalSpentTime() << "ms"; + LOG_JIT(INFO) << tier_ << message_ << ", compile time: " << TotalSpentTime() << "ms"; } } } // namespace panda::ecmascript diff --git a/ecmascript/jit/jit.h b/ecmascript/jit/jit.h index 792079a38eb0a1624047f00a29ee8bd9e7b50cf3..1ffa9a28234e796820d932802c3aaea1ce33c0c2 100644 --- a/ecmascript/jit/jit.h +++ b/ecmascript/jit/jit.h @@ -25,18 +25,11 @@ #include "ecmascript/compiler/compiler_log.h" #include "ecmascript/jit/jit_thread.h" #include "ecmascript/jit/jit_dfx.h" +#include "ecmascript/jit/compile_decision.h" +#include "ecmascript/jit/jit_resources.h" namespace panda::ecmascript { class JitTask; -enum JitCompileMode { - SYNC = 0, - ASYNC -}; - -enum class CompilerTier : uint8_t { - BASELINE, - FAST, -}; struct ThreadTaskInfo { std::deque> installJitTasks_; @@ -52,6 +45,7 @@ public: ~Jit(); static PUBLIC_API Jit *GetInstance(); void SetJitEnablePostFork(EcmaVM *vm, const std::string &bundleName); + void PreFork(); void ConfigJit(EcmaVM *vm); void SwitchProfileStubs(EcmaVM *vm); void ConfigOptions(EcmaVM *vm) const; @@ -65,10 +59,15 @@ public: void SetDisableCodeSign(bool isEnableCodeSign); bool PUBLIC_API IsEnableAsyncCopyToFort() const; void SetEnableAsyncCopyToFort(bool isEnableiAsyncCopyToFort); - void Initialize(); - static void Compile(EcmaVM *vm, JSHandle &jsFunction, CompilerTier tier = CompilerTier::FAST, - int32_t offset = MachineCode::INVALID_OSR_OFFSET, JitCompileMode mode = SYNC); + static void Compile(EcmaVM *vm, JSHandle &jsFunction, + CompilerTier::Tier tier = CompilerTier::Tier::FAST, + int32_t offset = MachineCode::INVALID_OSR_OFFSET, + JitCompileMode::Mode mode = JitCompileMode::Mode::SYNC) + { + Compile(vm, jsFunction, CompilerTier(tier), offset, JitCompileMode(mode)); + } + bool JitCompile(void *compiler, JitTask *jitTask); bool JitFinalize(void *compiler, JitTask *jitTask); void *CreateJitCompilerTask(JitTask *jitTask); @@ -77,7 +76,7 @@ public: return initialized_; } - void DeleteJitCompile(void *compiler); + void DeleteJitCompilerTask(void *compiler); void RequestInstallCode(std::shared_ptr jitTask); void InstallTasks(JSThread *jsThread); @@ -125,12 +124,15 @@ public: class TimeScope : public ClockScope { public: - explicit TimeScope(EcmaVM *vm, CString message, CompilerTier tier = CompilerTier::FAST, bool outPutLog = true, + explicit TimeScope(EcmaVM *vm, CString message, CompilerTier tier, bool outPutLog = true, bool isDebugLevel = false) : vm_(vm), message_(message), tier_(tier), outPutLog_(outPutLog), isDebugLevel_(isDebugLevel) {} explicit TimeScope(EcmaVM *vm) - : vm_(vm), message_(""), tier_(CompilerTier::FAST), outPutLog_(false), isDebugLevel_(true) {} + : vm_(vm), message_(""), tier_(CompilerTier::Tier::FAST), outPutLog_(false), isDebugLevel_(true) {} PUBLIC_API ~TimeScope(); + + void appendMessage(const CString& value) { message_ += value; } + private: EcmaVM *vm_; CString message_; @@ -155,7 +157,7 @@ public: explicit JitLockHolder(const CompilationEnv *env, CString message) : thread_(nullptr), scope_(env->GetJSThread()->GetEcmaVM(), - "Jit Compile Pass: " + message + ", Time:", CompilerTier::FAST, false) + "Jit Compile Pass: " + message + ", Time:", CompilerTier::Tier::FAST, false) { if (env->IsJitCompiler()) { JSThread *thread = env->GetJSThread(); @@ -227,7 +229,11 @@ public: }; private: - bool SupportJIT(JSHandle &jsFunction, EcmaVM *vm, CompilerTier tier) const; + void Compile(EcmaVM *vm, const CompileDecision &decision); + static void Compile(EcmaVM *vm, JSHandle &jsFunction, CompilerTier tier, + int32_t offset, JitCompileMode mode); + void CreateJitResources(); + bool IsLibResourcesResolved() const; bool initialized_ { false }; bool fastJitEnable_ { false }; bool baselineJitEnable_ { false }; @@ -246,16 +252,8 @@ private: Mutex setEnableLock_; JitDfx *jitDfx_ { nullptr }; + std::unique_ptr jitResources_; static constexpr int MIN_CODE_SPACE_SIZE = 1_KB; - - static void (*initJitCompiler_)(JSRuntimeOptions); - static bool(*jitCompile_)(void*, JitTask*); - static bool(*jitFinalize_)(void*, JitTask*); - static void*(*createJitCompilerTask_)(JitTask*); - static void(*deleteJitCompile_)(void*); - static void *libHandle_; - static bool CheckJitCompileStatus(JSHandle &jsFunction, - const CString &methodName, CompilerTier tier); }; } // namespace panda::ecmascript #endif // ECMASCRIPT_JIT_H diff --git a/ecmascript/jit/jit_dfx.h b/ecmascript/jit/jit_dfx.h index e552bef50f1ef87f98362b257ea41aad1ebd101e..94f30d62c14c20ba1aa84490b6bb0c4f21172a4f 100644 --- a/ecmascript/jit/jit_dfx.h +++ b/ecmascript/jit/jit_dfx.h @@ -22,6 +22,7 @@ #include "ecmascript/log.h" #include "ecmascript/mem/c_string.h" +#include "ecmascript/jit/compile_decision.h" namespace panda::ecmascript { using Clock = std::chrono::high_resolution_clock; @@ -140,9 +141,9 @@ public: return jitEventParams.singleTimeOnJitThread_.load() / CONVERT_TO_MILLISECOND; } - void SetTriggerCount(bool isBaselineJit) + void SetTriggerCount(CompilerTier tier) { - if (isBaselineJit) { + if (tier.IsBaseLine()) { jitEventParams.totalBaselineJitTimes_.fetch_add(1); } else { jitEventParams.totalFastoptJitTimes_.fetch_add(1); diff --git a/ecmascript/jit/jit_profiler.cpp b/ecmascript/jit/jit_profiler.cpp index 7032a7cfc3eebe85df8f4179b776ac1cd020d649..e0a2e5581deadc81f836a7a9df2bbb8eaefd8dd1 100644 --- a/ecmascript/jit/jit_profiler.cpp +++ b/ecmascript/jit/jit_profiler.cpp @@ -544,8 +544,8 @@ void JITProfiler::HandleOtherTypes(ApEntityId &abcId, int32_t &bcOffset, HandleOtherTypesPrototypeHandler(abcId, bcOffset, hclass, secondValue, slotId); } else if (secondValue.IsPropertyBox()) { // StoreGlobal - } else if (secondValue.IsStoreTSHandler()) { - HandleStoreTSHandler(abcId, bcOffset, hclass, secondValue); + } else if (secondValue.IsStoreAOTHandler()) { + HandleStoreAOTHandler(abcId, bcOffset, hclass, secondValue); } } @@ -604,17 +604,17 @@ void JITProfiler::HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &b AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId); } -void JITProfiler::HandleStoreTSHandler(ApEntityId &abcId, int32_t &bcOffset, - JSHClass *hclass, JSTaggedValue &secondValue) +void JITProfiler::HandleStoreAOTHandler(ApEntityId &abcId, int32_t &bcOffset, + JSHClass *hclass, JSTaggedValue &secondValue) { - StoreTSHandler *storeTSHandler = StoreTSHandler::Cast(secondValue.GetTaggedObject()); - auto cellValue = storeTSHandler->GetProtoCell(); + StoreAOTHandler *storeAOTHandler = StoreAOTHandler::Cast(secondValue.GetTaggedObject()); + auto cellValue = storeAOTHandler->GetProtoCell(); ASSERT(cellValue.IsProtoChangeMarker()); ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject()); if (cell->GetHasChanged()) { return; } - auto holder = storeTSHandler->GetHolder(); + auto holder = storeAOTHandler->GetHolder(); auto holderHClass = holder.GetTaggedObject()->GetClass(); AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass); } diff --git a/ecmascript/jit/jit_profiler.h b/ecmascript/jit/jit_profiler.h index da9f6463fbdf07cc5d98e1efb81b99b2e7ea2775..c6846548540cc177033f2434ecd6f5a7313f685c 100644 --- a/ecmascript/jit/jit_profiler.h +++ b/ecmascript/jit/jit_profiler.h @@ -111,7 +111,7 @@ private: JSHClass *hclass, JSTaggedValue &secondValue); void HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &bcOffset, JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId); - void HandleStoreTSHandler(ApEntityId &abcId, int32_t &bcOffset, + void HandleStoreAOTHandler(ApEntityId &abcId, int32_t &bcOffset, JSHClass *hclass, JSTaggedValue &secondValue); void ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type, uint32_t slotId); diff --git a/ecmascript/jit/jit_resources.cpp b/ecmascript/jit/jit_resources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..69d96c3378117ea38d6b0c4c93da04f1cb2d51a5 --- /dev/null +++ b/ecmascript/jit/jit_resources.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/jit/jit_resources.h" +#include "ecmascript/jit/jit_task.h" +#include "ecmascript/platform/file.h" +#include "ecmascript/taskpool/taskpool.h" +#include "ecmascript/ohos/jit_tools.h" + +namespace panda::ecmascript { + +void JitResources::Destroy() +{ + JitTaskpool::GetCurrentTaskpool()->Destroy(); + if (libHandle_ != nullptr) { + CloseLib(libHandle_); + libHandle_ = nullptr; + initJitCompiler_ = nullptr; + jitCompile_ = nullptr; + jitFinalize_ = nullptr; + createJitCompilerTask_ = nullptr; + deleteJitCompilerTask_ = nullptr; + } +} + +bool JitResources::InitJitEnv(const JSRuntimeOptions &options) +{ + jsRuntimeOptions_ = options; + InitCompiler(); + InitJitTaskpool(); + return true; +} + +bool JitResources::ResolveLib() +{ +#if defined(OHOS_UNIT_TEST) +#else + static const std::string CREATEJITCOMPILETASK = "CreateJitCompilerTask"; + static const std::string JITCOMPILEINIT = "InitJitCompiler"; + static const std::string JITCOMPILE = "JitCompile"; + static const std::string JITFINALIZE = "JitFinalize"; + static const std::string DELETEJITCOMPILERTASK = "DeleteJitCompilerTask"; + static const std::string LIBARK_JSOPTIMIZER = "libark_jsoptimizer.so"; + + libHandle_ = LoadLib(LIBARK_JSOPTIMIZER); + if (libHandle_ == nullptr) { + char *error = LoadLibError(); + LOG_JIT(ERROR) << "jit dlopen libark_jsoptimizer.so failed, as:" << + ((error == nullptr) ? "unknown error" : error); + return false; + } + + initJitCompiler_ = reinterpret_cast(FindSymbol(libHandle_, JITCOMPILEINIT.c_str())); + if (initJitCompiler_ == nullptr) { + LOG_JIT(ERROR) << "jit can't find symbol initJitCompiler"; + return false; + } + jitCompile_ = reinterpret_cast(FindSymbol(libHandle_, JITCOMPILE.c_str())); + if (jitCompile_ == nullptr) { + LOG_JIT(ERROR) << "jit can't find symbol jitCompile"; + return false; + } + + jitFinalize_ = reinterpret_cast(FindSymbol(libHandle_, JITFINALIZE.c_str())); + if (jitFinalize_ == nullptr) { + LOG_JIT(ERROR) << "jit can't find symbol jitFinalize"; + return false; + } + + createJitCompilerTask_ = reinterpret_cast(FindSymbol(libHandle_, + CREATEJITCOMPILETASK.c_str())); + if (createJitCompilerTask_ == nullptr) { + LOG_JIT(ERROR) << "jit can't find symbol createJitCompilertask"; + return false; + } + + deleteJitCompilerTask_ = reinterpret_cast(FindSymbol(libHandle_, + DELETEJITCOMPILERTASK.c_str())); + if (deleteJitCompilerTask_ == nullptr) { + LOG_JIT(ERROR) << "jit can't find symbol deleteJitCompile"; + return false; + } +#endif + libResolved_ = true; + return true; +} + +void JitResources::InitCompiler() +{ + if (initJitCompiler_ == nullptr) { + return; + } + initJitCompiler_(jsRuntimeOptions_); +} + +void JitResources::InitJitTaskpool() +{ + bool enableCodeSign = !ohos::JitTools::GetCodeSignDisable(jsRuntimeOptions_.GetDisableCodeSign()); + JitTaskpool::GetCurrentTaskpool()->Initialize(enableCodeSign); +} +} // namespace panda::ecmascript diff --git a/ecmascript/jit/jit_resources.h b/ecmascript/jit/jit_resources.h new file mode 100644 index 0000000000000000000000000000000000000000..7746c4a079e3ca7fa17cc88946ca18a09ff25b19 --- /dev/null +++ b/ecmascript/jit/jit_resources.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_JIT_RESOURCES_H +#define ECMASCRIPT_JIT_RESOURCES_H + +#include "ecmascript/ecma_vm.h" +#include "ecmascript/taskpool/taskpool.h" + +namespace panda::ecmascript { +class JitTask; +using InitJitCompilerFuncType = void (*)(JSRuntimeOptions options); +using JitCompileFuncType = bool(*)(void*, JitTask*); +using JitFinalizeFuncType = bool(*)(void*, JitTask*); +using CreateJitCompilerTaskFuncType = void*(*)(JitTask*); +using DeleteJitCompilerTaskFuncType = void(*)(void*); + +class JitResources { +public: + JitResources() = default; + ~JitResources() = default; + + void Resolve(); + void Destroy(); + + bool IsLibResolved() const + { + return libResolved_; + } + + bool Compile(void *compiler, JitTask *jitTask) + { + if (jitCompile_ == nullptr) { + return false; + } + return jitCompile_(compiler, jitTask); + } + + bool Finalize(void *compiler, JitTask *jitTask) + { + if (jitFinalize_ == nullptr) { + return false; + } + return jitFinalize_(compiler, jitTask); + } + + void *CreateJitCompilerTask(JitTask *jitTask) + { + if (createJitCompilerTask_ == nullptr) { + return nullptr; + } + return createJitCompilerTask_(jitTask); + } + + void DeleteJitCompilerTask(void *compilerTask) + { + if (deleteJitCompilerTask_ == nullptr) { + return; + } + deleteJitCompilerTask_(compilerTask); + } + bool ResolveLib(); + bool InitJitEnv(const JSRuntimeOptions &options); + +private: + void DoResolve(); + void InitCompiler(); + void InitJitTaskpool(); + + JSRuntimeOptions jsRuntimeOptions_; + bool libResolved_ {false}; + + InitJitCompilerFuncType initJitCompiler_ {nullptr}; + JitCompileFuncType jitCompile_ {nullptr}; + JitFinalizeFuncType jitFinalize_ {nullptr}; + CreateJitCompilerTaskFuncType createJitCompilerTask_ {nullptr}; + DeleteJitCompilerTaskFuncType deleteJitCompilerTask_ {nullptr}; + void *libHandle_ {nullptr}; + + NO_COPY_SEMANTIC(JitResources); + NO_MOVE_SEMANTIC(JitResources); +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_JIT_RESOURCES_H diff --git a/ecmascript/jit/jit_task.cpp b/ecmascript/jit/jit_task.cpp index 6f998f306e11d71aa5127e799056636cdd667f2b..2f470caf540daa67c3650c7426a2975788a46769 100644 --- a/ecmascript/jit/jit_task.cpp +++ b/ecmascript/jit/jit_task.cpp @@ -31,8 +31,7 @@ uint32_t JitTaskpool::TheMostSuitableThreadNum([[maybe_unused]]uint32_t threadNu } JitTask::JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, JSHandle &jsFunction, - CompilerTier tier, CString &methodName, int32_t offset, uint32_t taskThreadId, - JitCompileMode mode) + CompilerTier tier, CString &methodName, int32_t offset, JitCompileMode mode) : hostThread_(hostThread), compilerThread_(compilerThread), jit_(jit), @@ -42,7 +41,6 @@ JitTask::JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, JSHan compilerTier_(tier), methodName_(methodName), offset_(offset), - taskThreadId_(taskThreadId), ecmaContext_(nullptr), jitCompileMode_(mode), runState_(RunState::INIT) @@ -306,13 +304,14 @@ void JitTask::InstallCode() heap->GetMachineCodeSpace()->MarkJitFortMemInstalled(machineCodeObj.GetObject()); } } + jsFunction_->SetJitCompilingFlag(false); } void JitTask::InstallCodeByCompilerTier(JSHandle &machineCodeObj, JSHandle &methodHandle) { uintptr_t codeAddr = machineCodeObj->GetFuncAddr(); - if (compilerTier_ == CompilerTier::FAST) { + if (compilerTier_.IsFast()) { jsFunction_->SetCompiledFuncEntry(codeAddr, machineCodeObj->GetIsFastCall()); methodHandle->SetDeoptThreshold(hostThread_->GetEcmaVM()->GetJSOptions().GetDeoptThreshold()); jsFunction_->SetMachineCode(hostThread_, machineCodeObj); @@ -327,7 +326,7 @@ void JitTask::InstallCodeByCompilerTier(JSHandle &machineCodeObj, } #endif } else { - ASSERT(compilerTier_ == CompilerTier::BASELINE); + ASSERT(compilerTier_.IsBaseLine()); methodHandle->SetDeoptThreshold(hostThread_->GetEcmaVM()->GetJSOptions().GetDeoptThreshold()); jsFunction_->SetBaselineCode(hostThread_, machineCodeObj); LOG_BASELINEJIT(DEBUG) <<"Install baseline jit machine code:" << GetMethodName(); @@ -377,7 +376,7 @@ void JitTask::CloneProfileTypeInfo() JitTask::~JitTask() { ReleaseSustainingJSHandle(); - jit_->DeleteJitCompile(compilerTask_); + jit_->DeleteJitCompilerTask(compilerTask_); jit_->DecJitTaskCnt(hostThread_); } @@ -418,9 +417,17 @@ bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex) if (jitTask_->IsAsyncTask()) { jitTask_->jit_->RequestInstallCode(jitTask_); } + + MachineCodeDesc codeDesc = jitTask_->GetMachineCodeDesc(); + size_t instrSize = codeDesc.codeSizeAlign + codeDesc.rodataSizeBeforeTextAlign + + codeDesc.rodataSizeAfterTextAlign; + CString sizeInfo = ": text size: "; + sizeInfo.append(std::to_string(instrSize)).append("bytes"); + scope.appendMessage(sizeInfo); + int compilerTime = scope.TotalSpentTimeInMicroseconds(); JitDfx::GetInstance()->RecordSpentTimeAndPrintStatsLogInJitThread(compilerTime, jitTask_->methodName_, - jitTask_->compilerTier_ == CompilerTier::BASELINE, jitTask_->mainThreadCompileTime_); + jitTask_->compilerTier_.IsBaseLine(), jitTask_->mainThreadCompileTime_); } return true; } diff --git a/ecmascript/jit/jit_task.h b/ecmascript/jit/jit_task.h index c58c2ca9851ea897a6954941575aee58102d51e9..8da60488eb71d19367ecef6864da569b1e60bb70 100644 --- a/ecmascript/jit/jit_task.h +++ b/ecmascript/jit/jit_task.h @@ -100,9 +100,9 @@ class JitTask { public: JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, JSHandle &jsFunction, CompilerTier tier, CString &methodName, int32_t offset, - uint32_t taskThreadId, JitCompileMode mode); + JitCompileMode mode); // for ut - JitTask(EcmaVM *hVm, EcmaVM *cVm, Jit *jit, uint32_t taskThreadId, JitCompileMode mode); + JitTask(EcmaVM *hVm, EcmaVM *cVm, Jit *jit, JitCompileMode mode); ~JitTask(); void Optimize(); void Finalize(); @@ -187,11 +187,6 @@ public: methodName_ = methodName; } - uint32_t GetTaskThreadId() const - { - return taskThreadId_; - } - EcmaContext *GetEcmaContext() const { return ecmaContext_; @@ -220,7 +215,7 @@ public: void WaitFinish(); bool IsAsyncTask() const { - return jitCompileMode_ == JitCompileMode::ASYNC; + return jitCompileMode_.IsAsync(); } void SetMainThreadCompilerTime(int time) @@ -303,7 +298,6 @@ private: CompilerTier compilerTier_; CString methodName_; int32_t offset_; - uint32_t taskThreadId_; std::unique_ptr sustainingJSHandle_; EcmaContext *ecmaContext_; JitCompileMode jitCompileMode_; diff --git a/test/fuzztest/jsnapifork_fuzzer/BUILD.gn b/ecmascript/jit/tests/BUILD.gn similarity index 50% rename from test/fuzztest/jsnapifork_fuzzer/BUILD.gn rename to ecmascript/jit/tests/BUILD.gn index 125f38642766852d36f9c1212d66aa2c4d9d983c..1ce9db3046d7f2e78a8ad6c1896719456891aab0 100644 --- a/test/fuzztest/jsnapifork_fuzzer/BUILD.gn +++ b/ecmascript/jit/tests/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. +# Copyright (c) 2024 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -11,24 +11,30 @@ # See the License for the specific language governing permissions and # limitations under the License. -#####################################hydra-fuzz############################### import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") -####################################fuzztest################################## -ohos_fuzztest("JSNApiForkFuzzTest") { - module_out_path = ets_runtime_output_path +module_output_path = "ets_runtime" - fuzz_config_file = "$js_root/test/fuzztest/jsnapifork_fuzzer" +host_unittest_action("JIT_001_Test") { + module_out_path = module_output_path - sources = [ "jsnapifork_fuzzer.cpp" ] + sources = [ + # test file + "jit_test.cpp", + ] - configs = [ "$js_root:ecma_test_config" ] + configs = [ + "../../../:asm_interp_enable_config", + "../../../:ecma_test_config", + "$ark_root/assembler:arkassembler_public_config", + "$ark_root/libpandafile:arkfile_public_config", + ] deps = [ - "$js_root:libark_jsruntime", + "$ark_third_party_root/icu/icu4c:shared_icui18n", + "$ark_third_party_root/icu/icu4c:shared_icuuc", + "../../../:libark_jsruntime_test", sdk_libc_secshared_dep, ] @@ -37,8 +43,22 @@ ohos_fuzztest("JSNApiForkFuzzTest") { deps += hiviewdfx_deps } -group("fuzztest") { +group("unittest") { + testonly = true + + # deps file + deps = [ ":JIT_001_Test" ] +} + +group("host_unittest") { testonly = true - deps = [] - deps += [ ":JSNApiForkFuzzTest" ] + + # deps file + if (is_linux) { + deps = [ ":JIT_001_TestAction" ] + } + + if (is_mac) { + deps = [ ":JIT_001_TestAction" ] + } } diff --git a/ecmascript/jit/tests/jit_test.cpp b/ecmascript/jit/tests/jit_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..baf02c5b2f8b437d7dd657acd3ddc5affb271ee2 --- /dev/null +++ b/ecmascript/jit/tests/jit_test.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/global_env.h" +#include "ecmascript/object_factory-inl.h" +#include "ecmascript/tests/test_helper.h" +#include "ecmascript/jit/jit_task.h" + +using namespace panda::ecmascript; + +namespace panda::test { +class JitTest : 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_, false, false, true, true); + thread_ = instance_->GetJSThread(); + JitTaskpool::GetCurrentTaskpool()->WaitForJitTaskPoolReady(); + compilerVm_ = JitTaskpool::GetCurrentTaskpool()->GetCompilerVm(); + jit_ = Jit::GetInstance(); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance_, scope_); + } + + EcmaVM *instance_ {nullptr}; + EcmaHandleScope *scope_ {nullptr}; + JSThread *thread_ {nullptr}; + EcmaVM *compilerVm_ {nullptr}; + Jit *jit_ {nullptr}; +}; + +/** + * @tc.name: IsEnableFastJit + * @tc.desc: check jit is enable fast. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JitTest, IsEnableFastJit) +{ + EXPECT_TRUE(jit_->IsEnableFastJit()); +} + +/** + * @tc.name: NewJitTask + * @tc.desc: check new jit task. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JitTest, NewJitTask) +{ + JSHandle emptyHandle; + CString methodName("methodName"); + std::shared_ptr jitTask = std::make_shared(thread_, compilerVm_->GetJSThreadNoCheck(), + jit_, emptyHandle, CompilerTier(CompilerTier::Tier::FAST), methodName, 0, + JitCompileMode(JitCompileMode::Mode::SYNC)); + EXPECT_TRUE(jitTask->GetHostThread() == thread_); +} +} // namespace panda::test diff --git a/ecmascript/jobs/micro_job_queue.cpp b/ecmascript/jobs/micro_job_queue.cpp index cdd3251b06f0c4afc2d87e0c8864115f9b7593f3..fbc142ece51108f97c6aeb4f434412b5d46806df 100644 --- a/ecmascript/jobs/micro_job_queue.cpp +++ b/ecmascript/jobs/micro_job_queue.cpp @@ -20,8 +20,19 @@ #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/object_factory.h" #include "ecmascript/tagged_queue.h" +#include "ecmascript/ecma_context.h" namespace panda::ecmascript::job { +MicroJobScope::MicroJobScope(JSThread* thread) : thread_(thread) +{ + thread_->GetCurrentEcmaContext()->AddPendingJobEnterCount(); +} + +MicroJobScope::~MicroJobScope() +{ + thread_->GetCurrentEcmaContext()->MinusPendingJobEnterCount(); +} + uint32_t MicroJobQueue::GetPromiseQueueSize(JSThread *thread, JSHandle jobQueue) { [[maybe_unused]] EcmaHandleScope handleScope(thread); @@ -58,6 +69,7 @@ void MicroJobQueue::EnqueueJob(JSThread *thread, JSHandle jobQueu void MicroJobQueue::ExecutePendingJob(JSThread *thread, JSHandle jobQueue) { [[maybe_unused]] EcmaHandleScope handleScope(thread); + [[maybe_unused]] MicroJobScope microJobScope(thread); JSMutableHandle promiseQueue(thread, jobQueue->GetPromiseJobQueue()); JSMutableHandle pendingJob(thread, JSTaggedValue::Undefined()); while (!promiseQueue->Empty()) { diff --git a/ecmascript/jobs/micro_job_queue.h b/ecmascript/jobs/micro_job_queue.h index d6a60f5f34c99fc403e38057de466b83af3a5cb6..7795657e45f84e52f1d166979b4f562405a5bbd9 100644 --- a/ecmascript/jobs/micro_job_queue.h +++ b/ecmascript/jobs/micro_job_queue.h @@ -23,7 +23,13 @@ #include "ecmascript/tagged_array.h" namespace panda::ecmascript::job { - +class MicroJobScope { +public: + explicit MicroJobScope(JSThread *thread); + ~MicroJobScope(); +private: + JSThread *thread_; +}; class MicroJobQueue final : public Record { public: static MicroJobQueue *Cast(TaggedObject *object) diff --git a/ecmascript/jobs/tests/BUILD.gn b/ecmascript/jobs/tests/BUILD.gn index 2e18f9d6b2a5ce90b00b7e6d9257dcd6fc4330ba..d6f47dd43a88bee5b4ada64eec5f21657e7141bb 100644 --- a/ecmascript/jobs/tests/BUILD.gn +++ b/ecmascript/jobs/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("JobTest") { module_out_path = module_output_path diff --git a/ecmascript/js_api/js_api_bitvector.cpp b/ecmascript/js_api/js_api_bitvector.cpp index 1d76450c018c15b41abe954a86e6df010365e979..241bf29865de532a3dbb1505c487b89e07bb3f57 100644 --- a/ecmascript/js_api/js_api_bitvector.cpp +++ b/ecmascript/js_api/js_api_bitvector.cpp @@ -359,7 +359,7 @@ JSTaggedValue JSAPIBitVector::FlipBitByIndex(JSThread* thread, const JSHandle scope(thread, JSHandle::Cast(bitVector)); - if (index >= bitVector->GetLength()) { + if (index >= bitVector->GetLength() || index < 0) { std::ostringstream oss; oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (bitVector->GetLength() - 1) << ". Received value is: " << index; diff --git a/ecmascript/js_api/js_api_bitvector.h b/ecmascript/js_api/js_api_bitvector.h index 63ce34ea487d47dc90665811350013c2df75d01e..2aa0052f92276b46145360928e12ca9e33f8d383 100644 --- a/ecmascript/js_api/js_api_bitvector.h +++ b/ecmascript/js_api/js_api_bitvector.h @@ -80,7 +80,9 @@ public: ACCESSORS_PRIMITIVE_FIELD(Length, int32_t, LENGTH_OFFSET, MOD_RECORD_OFFSET); ACCESSORS_SYNCHRONIZED_PRIMITIVE_FIELD(ModRecord, uint32_t, MOD_RECORD_OFFSET, LAST_OFFSET); DEFINE_ALIGN_SIZE(LAST_OFFSET); - + + static constexpr uint32_t MAX_INLINE = PropertyAttributes::MAX_FAST_PROPS_CAPACITY - + SIZE / JSTaggedValue::TaggedTypeSize() + 1; DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, NATIVE_POINTER_OFFSET, LENGTH_OFFSET); DECL_DUMP() diff --git a/ecmascript/js_api/js_api_deque.cpp b/ecmascript/js_api/js_api_deque.cpp index b481509469d70b3459f8f5eaa8878117d9a80300..f6b6c59ad23e50a6b6f58e5f221908a04c084f4f 100644 --- a/ecmascript/js_api/js_api_deque.cpp +++ b/ecmascript/js_api/js_api_deque.cpp @@ -200,7 +200,6 @@ JSHandle JSAPIDeque::OwnKeys(JSThread *thread, const JSHandleGetSize(); JSHandle oldElements(thread, deque->GetElements()); - ASSERT(!oldElements->IsDictionaryMode()); uint32_t oldCapacity = oldElements->GetLength(); uint32_t newCapacity = ComputeCapacity(oldCapacity); uint32_t firstIndex = deque->GetFirst(); diff --git a/ecmascript/js_api/js_api_lightweightmap.cpp b/ecmascript/js_api/js_api_lightweightmap.cpp index 90a59060113f7e4b35d0e6b7ef9dc86165d4a11f..d7a91afc164a69839188e9ecab96bc37d9bce72e 100644 --- a/ecmascript/js_api/js_api_lightweightmap.cpp +++ b/ecmascript/js_api/js_api_lightweightmap.cpp @@ -57,7 +57,7 @@ void JSAPILightWeightMap::ReplaceValue(const JSThread *thread, const JSHandle &value, AccossorsKind kind) { JSHandle array = GetArrayByKind(thread, lightWeightMap, kind); - ASSERT(0 <= index || index < static_cast(lightWeightMap->GetSize())); + ASSERT(0 <= index && index < static_cast(lightWeightMap->GetSize())); array->Set(thread, index, value.GetTaggedValue()); } diff --git a/ecmascript/js_api/js_api_queue.cpp b/ecmascript/js_api/js_api_queue.cpp index c0dc6ff5a511b1c569069568bcb76ea6019517d8..09e4c60d15cab19a159269df7e443bdcae210a01 100644 --- a/ecmascript/js_api/js_api_queue.cpp +++ b/ecmascript/js_api/js_api_queue.cpp @@ -158,7 +158,6 @@ JSHandle JSAPIQueue::OwnKeys(JSThread *thread, const JSHandleGetLength().GetArrayLength(); JSHandle oldElements(thread, obj->GetElements()); - ASSERT(!oldElements->IsDictionaryMode()); uint32_t oldCapacity = oldElements->GetLength(); uint32_t newCapacity = ComputeCapacity(oldCapacity); uint32_t front = obj->GetFront(); diff --git a/ecmascript/js_array.cpp b/ecmascript/js_array.cpp index d41eca7e043cc8d8a4d691e236f8b1456726e3e9..2912ecb213b6b69de18c73924d88dbc402112066 100644 --- a/ecmascript/js_array.cpp +++ b/ecmascript/js_array.cpp @@ -242,7 +242,7 @@ void JSArray::SetCapacity(JSThread *thread, const JSHandle &array, if (newLen <= capacity) { // judge if need to cut down the array size, else fill the unused tail with holes CheckAndCopyArray(thread, JSHandle(array)); - array->FillElementsWithHoles(thread, newLen, oldLen < capacity ? oldLen : capacity); + JSObject::FillElementsWithHoles(thread, array, newLen, oldLen < capacity ? oldLen : capacity); } if (JSObject::ShouldTransToDict(oldLen, newLen)) { JSObject::ElementsToDictionary(thread, array); @@ -260,9 +260,19 @@ void JSArray::SetCapacity(JSThread *thread, const JSHandle &array, } #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC ElementsKind newKind = ElementsKind::GENERIC; - #else +#else + // 1.When elementsKind is NONE, means thisArray is empty, + // so we don't need to traverse the elements to transform elementskind. + // 2.Make sure array is already created. + // 3.Make sure newLen > 0 for avoid making empty array elementsKind to HOLE accidently. + // ASSERT: If an array's elementsKind is NONE, its length must be zero. + if (Elements::IsNone(oldKind) && !isNew && newLen > 0) { + ASSERT(oldLen == 0); + JSHClass::TransitToElementsKindUncheck(thread, array, ElementsKind::HOLE); + return; + } ElementsKind newKind = ElementsKind::NONE; - #endif +#endif for (uint32_t i = 0; i < newLen; ++i) { JSTaggedValue val = ElementAccessor::Get(array, i); newKind = Elements::ToElementsKind(val, newKind); @@ -401,6 +411,19 @@ bool JSArray::IsLengthString(JSThread *thread, const JSHandle &ke return key.GetTaggedValue() == thread->GlobalConstants()->GetLengthString(); } +// static +// Check whether the element of the array is dictionary element, +// proto of the array has not been modified +// the element of the array prototype has not been modified +// the attribute of the array has not been modified +bool JSArray::IsProtoNotModifiedDictionaryJSArray(JSThread *thread, const JSHandle &obj) +{ + return obj->GetJSHClass()->IsDictionaryElement() && + !thread->IsArrayPrototypeChangedGuardiansInvalid() && + !obj->GetClass()->IsJSArrayPrototypeModifiedFromBitField() && + JSObject::AttributesUnchanged(thread, obj); +} + // ecma6 7.3 Operations on Objects JSHandle JSArray::CreateArrayFromList(JSThread *thread, const JSHandle &elements) { @@ -478,6 +501,7 @@ bool JSArray::FastSetPropertyByValue(JSThread *thread, const JSHandle &obj, uint32_t index, const JSHandle &value, SCheckMode sCheckMode) { +#if ENABLE_NEXT_OPTIMIZATION JSHandle objVal(obj); if (!objVal->IsStableJSArray(thread)) { // if JSArray is DictionaryMode goto slowPath @@ -508,31 +532,16 @@ bool JSArray::TryFastCreateDataProperty(JSThread *thread, const JSHandleGetElements())->Set(thread, index, value); return true; +#else + return JSObject::CreateDataPropertyOrThrow(thread, obj, index, value, sCheckMode); +#endif } -// ecma2024 23.1.3.20 Array.prototype.sort(comparefn) -JSTaggedValue JSArray::Sort(JSThread *thread, const JSHandle &obj, const JSHandle &fn) +JSTaggedValue JSArray::CopySortedListToReceiver(JSThread *thread, const JSHandle &obj, + JSHandle sortedList, uint32_t len) { - ASSERT(fn->IsUndefined() || fn->IsCallable()); - // 3. Let len be ?LengthOfArrayLike(obj). - int64_t len = ArrayHelper::GetArrayLength(thread, obj); - // ReturnIfAbrupt(len). - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - // If len is 0 or 1, no need to sort - if (len == 0 || len == 1) { - return obj.GetTaggedValue(); - } - - // 4. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and performs - // the following steps when called: - // a. Return ? CompareArrayElements(x, y, comparefn). - // 5. Let sortedList be ? SortIndexedProperties(O, len, SortCompare, SKIP-HOLES). - JSHandle sortedList = - ArrayHelper::SortIndexedProperties(thread, obj, len, fn, base::HolesType::SKIP_HOLES); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 6. Let itemCount be the number of elements in sortedList. uint32_t itemCount = sortedList->GetLength(); - // 7. Let j be 0. uint32_t j = 0; // 8. Repeat, while j < itemCount, @@ -556,7 +565,31 @@ JSTaggedValue JSArray::Sort(JSThread *thread, const JSHandle &obj RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); ++j; } + return obj.GetTaggedValue(); +} + +// ecma2024 23.1.3.20 Array.prototype.sort(comparefn) +JSTaggedValue JSArray::Sort(JSThread *thread, const JSHandle &obj, const JSHandle &fn) +{ + ASSERT(fn->IsUndefined() || fn->IsCallable()); + // 3. Let len be ?LengthOfArrayLike(obj). + int64_t len = ArrayHelper::GetArrayLength(thread, obj); + // ReturnIfAbrupt(len). + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + // If len is 0 or 1, no need to sort + if (len == 0 || len == 1) { + return obj.GetTaggedValue(); + } + // 4. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and performs + // the following steps when called: + // a. Return ? CompareArrayElements(x, y, comparefn). + // 5. Let sortedList be ? SortIndexedProperties(O, len, SortCompare, SKIP-HOLES). + JSHandle sortedList = + ArrayHelper::SortIndexedProperties(thread, obj, len, fn, base::HolesType::SKIP_HOLES); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSArray::CopySortedListToReceiver(thread, obj, sortedList, len); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return obj.GetTaggedValue(); } @@ -585,6 +618,45 @@ void JSArray::SortElementsByMergeSort(JSThread *thread, const JSHandle obj, + JSHandle &newArrayHandle, JSMutableHandle &fromValHandle, + JSMutableHandle &toKey, int64_t &n) +{ + bool isArrayHandleDictionary = newArrayHandle->GetJSHClass()->IsDictionaryElement(); + if (!isArrayHandleDictionary) { + JSObject::ElementsToDictionary(thread, newArrayHandle); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + } + ASSERT(newArrayHandle->GetJSHClass()->IsDictionaryElement()); + JSHandle objVal(obj); + int64_t len = base::ArrayHelper::GetArrayLength(thread, objVal); + JSHandle elements(thread, obj->GetElements()); + uint32_t size = static_cast(elements->Size()); + JSMutableHandle dict(thread, newArrayHandle->GetElements()); + auto attr = PropertyAttributes(PropertyAttributes::GetDefaultAttributes()); + for (uint32_t hashIndex = 0; hashIndex < size; hashIndex++) { + JSTaggedValue key = elements->GetKey(hashIndex); + if (key.IsUndefined() || key.IsHole()) { + continue; + } + ASSERT(key.IsInt()); + uint32_t uintKey = static_cast(key.GetInt()); + if (uintKey < len) { + JSTaggedValue value = elements->GetValue(hashIndex); + toKey.Update(JSTaggedValue(n + uintKey)); + fromValHandle.Update(value); + JSHandle newDict = \ + NumberDictionary::PutIfAbsent(thread, dict, toKey, fromValHandle, attr); + dict.Update(newDict); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + } + } + newArrayHandle->SetElements(thread, dict); + n += len; + return JSTaggedValue(true); +} + void JSArray::MergeSortedElements(JSThread *thread, const JSHandle &elements, const JSHandle &fn, int64_t startIdx, int64_t middleIdx, int64_t endIdx) @@ -764,4 +836,20 @@ void JSArray::CheckAndCopyArray(const JSThread *thread, JSHandle obj) obj->SetProperties(thread, newProps.GetTaggedValue()); } } + +// static +bool JSArray::IsProtoNotChangeJSArray(JSThread *thread, const JSHandle &obj) +{ + if (obj->IsJSArray()) { + if (obj->GetJSHClass()->GetElementsKind() != ElementsKind::GENERIC) { + return true; + } + JSTaggedValue arrayProtoValue = JSObject::GetPrototype(obj); + JSTaggedValue genericArrayHClass = thread->GlobalConstants()->GetElementHoleTaggedClass(); + JSTaggedValue genericArrayProtoValue = \ + JSHClass::Cast(genericArrayHClass.GetTaggedObject())->GetProto(); + return genericArrayProtoValue == arrayProtoValue; + } + return false; +} } // namespace panda::ecmascript diff --git a/ecmascript/js_array.h b/ecmascript/js_array.h index c9e9a5f1a1c605c56a7df52b29e17a44b60e380d..e41768ff6466ee599ccbadf145331b3280c54342 100644 --- a/ecmascript/js_array.h +++ b/ecmascript/js_array.h @@ -45,10 +45,16 @@ public: const PropertyDescriptor &desc); static bool IsLengthString(JSThread *thread, const JSHandle &key); + static bool IsProtoNotChangeJSArray(JSThread *thread, const JSHandle &obj); + static bool IsProtoNotModifiedDictionaryJSArray(JSThread *thread, const JSHandle &obj); // ecma6 7.3 Operations on Objects static JSHandle CreateArrayFromList(JSThread *thread, const JSHandle &elements); static JSHandle CreateArrayFromList(JSThread *thread, const JSHandle &newtarget, const JSHandle &elements); + static JSTaggedValue FastConcatDictionaryArray(JSThread *thread, JSHandle obj, + JSHandle &newArrayHandle, JSMutableHandle &fromValHandle, + JSMutableHandle &toKey, int64_t &n); + // use first inlined property slot for array length inline uint32_t GetArrayLength() const { @@ -109,6 +115,8 @@ public: SCheckMode sCheckMode = SCheckMode::CHECK); static JSTaggedValue Sort(JSThread *thread, const JSHandle &obj, const JSHandle &fn); + static JSTaggedValue CopySortedListToReceiver(JSThread *thread, const JSHandle &thisObjVal, + JSHandle sortedList, uint32_t len); static bool IncludeInSortedValue(JSThread *thread, const JSHandle &obj, const JSHandle &value); static JSHandle ToTaggedArray(JSThread *thread, const JSHandle &obj); diff --git a/ecmascript/js_async_generator_object.cpp b/ecmascript/js_async_generator_object.cpp index f13972ad912a456f03bdf1a9a51bb66c8ca47faf..912942328fa98713126f337f0069febe780a58e0 100644 --- a/ecmascript/js_async_generator_object.cpp +++ b/ecmascript/js_async_generator_object.cpp @@ -67,9 +67,10 @@ JSTaggedValue JSAsyncGeneratorObject::AsyncGeneratorResolve(JSThread *thread, JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); EcmaRuntimeCallInfo* info = EcmaInterpreter::NewRuntimeCallInfo(thread, resolve, undefined, undefined, 1, StackCheck::NO); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); info->SetCallArg(its.GetTaggedValue()); [[maybe_unused]] JSTaggedValue res = JSFunction::Call(info); - if ((thread)->HasPendingException()) { + if (thread->HasPendingException()) { [[maybe_unused]] JSType errorType = thread->GetException().GetTaggedObject()->GetClass()->GetObjectType(); ASSERT(errorType == JSType::JS_RANGE_ERROR); thread->ClearException(); diff --git a/ecmascript/js_collator.cpp b/ecmascript/js_collator.cpp index 0046adf589a8b5a15d9d290f0a8b5ae713d65cec..3707d40541cce3159d2e7585fe8c410ac954ae27 100644 --- a/ecmascript/js_collator.cpp +++ b/ecmascript/js_collator.cpp @@ -679,8 +679,7 @@ bool CharCanFastCompareOrOutOfBounds(EcmaString* string, int stringLength, int i // 5. If all equal, return equal. // 6. Once some chars cannot be fastcompared, use icu. -std::optional TryFastCompareStrings([[maybe_unused]] const icu::Collator* icuCollator, - EcmaString* string1, EcmaString* string2, +std::optional TryFastCompareStrings(EcmaString* string1, EcmaString* string2, int& processedUntilOut) { processedUntilOut = 0; @@ -719,17 +718,17 @@ std::optional TryFastCompareStrings([[maybe_unused]] const icu } // namespace //StringPiece is similar to std::string_view -icu::StringPiece ToICUStringPiece(const JSHandle& string, int offset = 0) +icu::StringPiece ToICUStringPiece(EcmaString* string, int offset = 0) { EcmaStringAccessor stringAcc(string); ASSERT(stringAcc.IsUtf8()); ASSERT(!stringAcc.IsTreeString()); - return icu::StringPiece(reinterpret_cast(EcmaStringAccessor::GetNonTreeUtf8Data(*string)) + offset, + return icu::StringPiece(reinterpret_cast(EcmaStringAccessor::GetNonTreeUtf8Data(string)) + offset, static_cast(stringAcc.GetLength()) - offset); } // Convert to a UTF16 string and partially convert to ICUUnicodeString -icu::UnicodeString ToICUUnicodeString(const JSHandle &string, int offset = 0) +icu::UnicodeString ToICUUnicodeString(EcmaString* string, int offset = 0) { EcmaStringAccessor stringAcc(string); ASSERT(!stringAcc.IsTreeString()); @@ -741,17 +740,42 @@ icu::UnicodeString ToICUUnicodeString(const JSHandle &string, int of // short string on stack UChar shortStringBuffer[shortStringLength]; // utf8 is within ascii, std::copy_n from utf8 to utf16 is OK - std::copy_n(EcmaStringAccessor::GetNonTreeUtf8Data(*string) + offset, partialLength, shortStringBuffer); + std::copy_n(EcmaStringAccessor::GetNonTreeUtf8Data(string) + offset, partialLength, shortStringBuffer); return icu::UnicodeString(shortStringBuffer, partialLength); } CVector ucharBuffer(partialLength); - std::copy_n(EcmaStringAccessor::GetNonTreeUtf8Data(*string) + offset, partialLength, ucharBuffer.begin()); + std::copy_n(EcmaStringAccessor::GetNonTreeUtf8Data(string) + offset, partialLength, ucharBuffer.begin()); return icu::UnicodeString(ucharBuffer.data(), partialLength); } else { - return icu::UnicodeString(EcmaStringAccessor::GetNonTreeUtf16Data(*string) + offset, partialLength); + return icu::UnicodeString(EcmaStringAccessor::GetNonTreeUtf16Data(string) + offset, partialLength); } } +JSTaggedValue JSCollator::SlowCompareStrings(const icu::Collator *icuCollator, + EcmaString* flatString1, + EcmaString* flatString2, + int processedUntil) +{ + UCollationResult result; + UErrorCode status = U_ZERO_ERROR; + if (EcmaStringAccessor(flatString1).IsUtf8() && EcmaStringAccessor(flatString2).IsUtf8()) { + auto string1Piece = ToICUStringPiece(flatString1, processedUntil); + if (!string1Piece.empty()) { + auto string2Piece = ToICUStringPiece(flatString2, processedUntil); + if (!string2Piece.empty()) { + result = icuCollator->compareUTF8(string1Piece, string2Piece, status); + return JSTaggedValue(result); + } + } + } + + auto uString1 = ToICUUnicodeString(flatString1, processedUntil); + auto uString2 = ToICUUnicodeString(flatString2, processedUntil); + result = icuCollator->compare(uString1, uString2, status); + ASSERT(U_SUCCESS(status)); + return JSTaggedValue(result); +} + JSTaggedValue JSCollator::CompareStrings(JSThread *thread, const icu::Collator *icuCollator, const JSHandle &string1, const JSHandle &string2, [[maybe_unused]]CompareStringsOption csOption) @@ -767,30 +791,40 @@ JSTaggedValue JSCollator::CompareStrings(JSThread *thread, const icu::Collator * int processedUntil = 0; if (csOption == CompareStringsOption::TRY_FAST_PATH) { - auto maybeResult = TryFastCompareStrings(icuCollator, *flatString1, *flatString2, processedUntil); + auto maybeResult = TryFastCompareStrings(*flatString1, *flatString2, processedUntil); if (maybeResult.has_value()) { return JSTaggedValue(maybeResult.value()); } } + return SlowCompareStrings(icuCollator, *flatString1, *flatString2, processedUntil); +} - UCollationResult result; - UErrorCode status = U_ZERO_ERROR; - if (EcmaStringAccessor(flatString1).IsUtf8() && EcmaStringAccessor(flatString2).IsUtf8()) { - auto string1Piece = ToICUStringPiece(flatString1, processedUntil); - if (!string1Piece.empty()) { - auto string2Piece = ToICUStringPiece(flatString2, processedUntil); - if (!string2Piece.empty()) { - result = icuCollator->compareUTF8(string1Piece, string2Piece, status); - return JSTaggedValue(result); - } - } +JSTaggedValue JSCollator::FastCachedCompareStrings(JSThread *thread, JSHandle locales, + const JSHandle &string1, + const JSHandle &string2, + CompareStringsOption csOption) +{ + if (*string1 == *string2) { + return JSTaggedValue(UCollationResult::UCOL_EQUAL); } + + // Since Unicode has ignorable characters, + // we cannot return early for 0-length strings. + auto flatString1 = JSHandle(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), string1)); + auto flatString2 = JSHandle(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), string2)); - auto uString1 = ToICUUnicodeString(flatString1, processedUntil); - auto uString2 = ToICUUnicodeString(flatString2, processedUntil); - result = icuCollator->compare(uString1, uString2, status); - ASSERT(U_SUCCESS(status)); + int processedUntil = 0; + if (csOption == CompareStringsOption::TRY_FAST_PATH) { + auto maybeResult = TryFastCompareStrings(*flatString1, *flatString2, processedUntil); + if (maybeResult.has_value()) { + return JSTaggedValue(maybeResult.value()); + } + } - return JSTaggedValue(result); + auto icuCollator = JSCollator::GetCachedIcuCollator(thread, locales); + if (icuCollator != nullptr) { + return SlowCompareStrings(icuCollator, *flatString1, *flatString2, processedUntil); + } + return JSTaggedValue::Undefined(); } } // namespace panda::ecmascript diff --git a/ecmascript/js_collator.h b/ecmascript/js_collator.h index a6b7c7f9a1954dca431efbb96ffdfde982e00774..013b2836648625e6af74f9c6e2cbc0d9380944cd 100644 --- a/ecmascript/js_collator.h +++ b/ecmascript/js_collator.h @@ -122,6 +122,16 @@ public: const JSHandle &string1, const JSHandle &string2, CompareStringsOption csOption = CompareStringsOption::NONE); + static JSTaggedValue FastCachedCompareStrings(JSThread *thread, JSHandle locales, + const JSHandle &string1, + const JSHandle &string2, + CompareStringsOption csOption = CompareStringsOption::NONE); + + static JSTaggedValue SlowCompareStrings(const icu::Collator *icuCollator, + EcmaString* flatString1, + EcmaString* flatString2, + int processedUntil); + private: static CaseFirstOption StringToCaseFirstOption(const std::string &str); diff --git a/ecmascript/js_date.cpp b/ecmascript/js_date.cpp index de711ca6cbd2b5eb5ff5c70a21fcb10a532aac45..61525a7f42ecbeb473de0ccb31dfe3ee93856569 100644 --- a/ecmascript/js_date.cpp +++ b/ecmascript/js_date.cpp @@ -25,11 +25,6 @@ namespace panda::ecmascript { using NumberHelper = base::NumberHelper; -bool DateUtils::isCached_ = false; -int DateUtils::preSumDays_ = 0; -int DateUtils::preDays_ = 0; -int DateUtils::preMonth_ = 0; -int DateUtils::preYear_ = 0; static const std::array WEEK_DAY_NAME = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static const std::array MONTH_NAME = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", @@ -652,13 +647,13 @@ void JSDate::AppendStrToTargetLength(const CString &str, int length, CString &ta } } -bool JSDate::GetThisDateValues(std::array *date, bool isLocal) const +bool JSDate::GetThisDateValues(JSThread *thread, std::array *date, bool isLocal) const { double timeMs = this->GetTimeValue().GetDouble(); if (std::isnan(timeMs)) { return false; } - GetDateValues(timeMs, date, isLocal); + GetDateValues(thread, timeMs, date, isLocal); return true; } @@ -666,7 +661,7 @@ bool JSDate::GetThisDateValues(std::array *date, bool isLo JSTaggedValue JSDate::ToDateString(JSThread *thread) const { std::array fields = {0}; - if (!GetThisDateValues(&fields, true)) { + if (!GetThisDateValues(thread, &fields, true)) { return JSTaggedValue(base::NAN_VALUE); } CString str; @@ -683,13 +678,13 @@ JSTaggedValue JSDate::ToDateString(JSThread *thread) const } // static -CString JSDate::ToDateString(double timeMs) +CString JSDate::ToDateString(JSThread *thread, double timeMs) { if (std::isnan(timeMs)) { return "Invalid Date"; } std::array fields = {0}; - GetDateValues(timeMs, &fields, true); + GetDateValues(thread, timeMs, &fields, true); CString localTime; int localMin = 0; localMin = GetLocalOffsetFromOS(timeMs, true); @@ -725,7 +720,7 @@ CString JSDate::ToDateString(double timeMs) JSTaggedValue JSDate::ToISOString(JSThread *thread) const { std::array fields = {0}; - if (!GetThisDateValues(&fields, false)) { + if (!GetThisDateValues(thread, &fields, false)) { return JSTaggedValue(base::NAN_VALUE); } CString year = ToCString(fields[YEAR]); @@ -760,7 +755,7 @@ JSTaggedValue JSDate::ToString(JSThread *thread) const { int localMin = 0; std::array fields = {0}; - if (!GetThisDateValues(&fields, true)) { + if (!GetThisDateValues(thread, &fields, true)) { return JSTaggedValue(base::NAN_VALUE); } CString localTime; @@ -799,7 +794,7 @@ JSTaggedValue JSDate::ToTimeString(JSThread *thread) const { int localMin = 0; std::array fields = {0}; - if (!GetThisDateValues(&fields, true)) { + if (!GetThisDateValues(thread, &fields, true)) { return JSTaggedValue(base::NAN_VALUE); } CString localTime; @@ -829,7 +824,7 @@ JSTaggedValue JSDate::ToTimeString(JSThread *thread) const JSTaggedValue JSDate::ToUTCString(JSThread *thread) const { std::array fields = {0}; - if (!GetThisDateValues(&fields, false)) { + if (!GetThisDateValues(thread, &fields, false)) { return JSTaggedValue(base::NAN_VALUE); } CString str; @@ -860,7 +855,7 @@ JSTaggedValue JSDate::ValueOf() const } // static -void JSDate::GetDateValues(double timeMs, std::array *date, bool isLocal) +void JSDate::GetDateValues(JSThread *thread, double timeMs, std::array *date, bool isLocal) { int64_t tz = 0; int64_t timeMsInt = static_cast(timeMs); @@ -869,17 +864,17 @@ void JSDate::GetDateValues(double timeMs, std::array *date timeMsInt += tz * MS_PER_SECOND * SEC_PER_MINUTE; } - DateUtils::TransferTimeToDate(timeMsInt, date); + thread->GetDateUtils()->TransferTimeToDate(timeMsInt, date); (*date)[TIMEZONE] = -tz; } -double JSDate::GetDateValue(double timeMs, uint8_t code, bool isLocal) const +double JSDate::GetDateValue(JSThread *thread, double timeMs, uint8_t code, bool isLocal) const { if (std::isnan(timeMs)) { return base::NAN_VALUE; } std::array date = {0}; - GetDateValues(timeMs, &date, isLocal); + GetDateValues(thread, timeMs, &date, isLocal); return static_cast(date[code]); } @@ -907,13 +902,13 @@ JSTaggedValue JSDate::SetDateValue(EcmaRuntimeCallInfo *argv, uint32_t code, boo timeMs = 0.0; isSelectLocal = false; } + JSThread *thread = argv->GetThread(); if (!std::isnan(timeMs)) { - GetDateValues(timeMs, &date, isSelectLocal); + GetDateValues(thread, timeMs, &date, isSelectLocal); } // When timeMs is NaN, the corresponding parameters still need to be obtained for (uint32_t i = 0; i < count; i++) { JSHandle value = base::BuiltinsBase::GetCallArg(argv, i); - JSThread *thread = argv->GetThread(); JSTaggedNumber res = JSTaggedValue::ToNumber(thread, value); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); double temp = res.GetNumber(); diff --git a/ecmascript/js_date.h b/ecmascript/js_date.h index 419b03cd9802d807b0bfaf6423c5e84415e90e3f..736dc98188784c63f82789c5dd5699c8bc08c844 100644 --- a/ecmascript/js_date.h +++ b/ecmascript/js_date.h @@ -71,21 +71,24 @@ static constexpr char DEL = 127; class DateUtils { public: - static void TransferTimeToDate(int64_t timeMs, std::array *date); + explicit DateUtils() = default; + virtual ~DateUtils() = default; + + void TransferTimeToDate(int64_t timeMs, std::array *date); + // return the year, update days. + void GetYearFromDays(std::array *date); static int64_t Mod(int64_t a, int b); static bool IsLeap(int64_t year); static int64_t GetDaysInYear(int64_t year); static int64_t GetDaysFromYear(int64_t year); - // return the year, update days. - static void GetYearFromDays(std::array *date); static int64_t FloorDiv(int64_t a, int64_t b); private: - static bool isCached_; - static int preSumDays_; - static int preDays_; - static int preMonth_; - static int preYear_; + bool isCached_ {false}; + int preSumDays_ {0}; + int preDays_ {0}; + int preMonth_ {0}; + int preYear_ {0}; }; class JSDate : public JSObject { public: @@ -133,7 +136,7 @@ public: // 20.4.4.35 JSTaggedValue ToDateString(JSThread *thread) const; - static CString ToDateString(double timeMs); + static CString ToDateString(JSThread *thread, double timeMs); // 20.4.4.36 JSTaggedValue ToISOString(JSThread *thread) const; @@ -151,7 +154,7 @@ public: JSTaggedValue ValueOf() const; JSTaggedValue SetDateValue(EcmaRuntimeCallInfo *argv, uint32_t code, bool isLocal) const; - double GetDateValue(double timeMs, uint8_t code, bool isLocal) const; + double GetDateValue(JSThread *thread, double timeMs, uint8_t code, bool isLocal) const; static JSTaggedValue GetTimeFromString(const char *str, int len); static constexpr double MAX_DOUBLE = std::numeric_limits::max(); @@ -165,13 +168,13 @@ public: static constexpr int MAX_DAYS_MONTH = 31; static double SetDateValues(const std::array *date, bool isLocal); static double SetDateValues(int64_t year, int64_t month, int64_t day); - static void GetDateValues(double timeMs, std::array *date, bool isLocal); + static void GetDateValues(JSThread *thread, double timeMs, std::array *date, bool isLocal); static CString StrToTargetLength(const CString &str, int length); static void AppendStrToTargetLength(const CString &str, int length, CString &target); DECL_DUMP() private: - bool GetThisDateValues(std::array *date, bool isLocal) const; + bool GetThisDateValues(JSThread *thread, std::array *date, bool isLocal) const; CString GetLocaleTimeStr(const std::array &fields) const; CString GetLocaleDateStr(const std::array &fields) const; static int64_t MathMod(int64_t a, int b); diff --git a/ecmascript/js_displaynames.cpp b/ecmascript/js_displaynames.cpp index 3e298ce416ebc6d61e4959e6c04811e98aa78903..46454f68d08b2561baac8d18f59f0a258fda4959 100644 --- a/ecmascript/js_displaynames.cpp +++ b/ecmascript/js_displaynames.cpp @@ -350,7 +350,8 @@ JSHandle JSDisplayNames::CanonicalCodeForDisplayNames(JSThread *thre width = UDATPG_NARROW; break; default: - break; + LOG_ECMA(FATAL) << "this branch is unreachable"; + UNREACHABLE(); } std::string datetimeCode = intl::LocaleHelper::ConvertToStdString(code); UDateTimePatternField field = StringToUDateTimePatternField(datetimeCode.c_str()); diff --git a/ecmascript/js_function.cpp b/ecmascript/js_function.cpp index 3db77ab99a36bc3887b97dd4358c37bd6de86543..9ffffd4e8667058c2f7cd6bdb0ee082694f56313 100644 --- a/ecmascript/js_function.cpp +++ b/ecmascript/js_function.cpp @@ -25,6 +25,7 @@ #include "ecmascript/object_factory-inl.h" #include "ecmascript/pgo_profiler/pgo_profiler.h" #include "ecmascript/require/js_require_manager.h" +#include "ecmascript/ic/profile_type_info.h" namespace panda::ecmascript { void JSFunction::InitializeJSFunction(JSThread *thread, const JSHandle &func, FunctionKind kind) @@ -183,7 +184,7 @@ bool JSFunction::PrototypeSetter(JSThread *thread, const JSHandle &sel JSHandle newClass = JSHClass::SetPrototypeWithNotification(thread, hclass, value); func->SetProtoOrHClass(thread, newClass); // Forbide to profile for changing the function prototype after an instance of the function has been created - if (!hclass->IsTS() && thread->GetEcmaVM()->IsEnablePGOProfiler()) { + if (!hclass->IsAOT() && thread->GetEcmaVM()->IsEnablePGOProfiler()) { EntityId ctorMethodId = Method::Cast(func->GetMethod().GetTaggedObject())->GetMethodId(); thread->GetEcmaVM()->GetPGOProfiler()->InsertSkipCtorMethodIdSafe(ctorMethodId); } @@ -905,6 +906,9 @@ JSHandle JSFunction::GetOrCreateDerivedJSHClass(JSThread *thread, JSHa } JSHandle newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass); + if (ctorInitialJSHClass->IsJSArray()) { + newJSHClass->SetIsJSArrayPrototypeModified(true); + } newJSHClass->SetElementsKind(ElementsKind::GENERIC); // guarante derived has function prototype JSHandle prototype(thread, derived->GetProtoOrHClass()); @@ -959,22 +963,23 @@ void JSFunction::SetFunctionLength(const JSThread *thread, JSTaggedValue length) SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, length); } -void JSFunction::SetFunctionExtraInfo(JSThread *thread, void *nativeFunc, const NativePointerCallback &deleter, - void *data, size_t nativeBindingsize, Concurrent isConcurrent) +// static +void JSFunction::SetFunctionExtraInfo(JSThread *thread, const JSHandle &func, void *nativeFunc, + const NativePointerCallback &deleter, void *data, size_t nativeBindingsize, + Concurrent isConcurrent) { - JSTaggedType hashField = Barriers::GetValue(this, HASH_OFFSET); + JSTaggedType hashField = Barriers::GetValue(*func, HASH_OFFSET); EcmaVM *vm = thread->GetEcmaVM(); JSHandle value(thread, JSTaggedValue(hashField)); - JSHandle obj(thread, this); JSHandle pointer = vm->GetFactory()->NewJSNativePointer(nativeFunc, deleter, data, false, nativeBindingsize, isConcurrent); - if (!obj->HasHash()) { - Barriers::SetObject(thread, *obj, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); + if (!func->HasHash()) { + Barriers::SetObject(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); return; } if (value->IsHeapObject()) { if (value->IsJSNativePointer()) { - Barriers::SetObject(thread, *obj, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); + Barriers::SetObject(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); return; } JSHandle array(value); @@ -990,33 +995,33 @@ void JSFunction::SetFunctionExtraInfo(JSThread *thread, void *nativeFunc, const } newArray->Set(thread, nativeFieldCount + HASH_INDEX, array->Get(nativeFieldCount + HASH_INDEX)); newArray->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer); - Barriers::SetObject(thread, *obj, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); + Barriers::SetObject(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); } } else { JSHandle newArray = vm->GetFactory()->NewTaggedArray(RESOLVED_MAX_SIZE); newArray->SetExtraLength(0); newArray->Set(thread, HASH_INDEX, value); newArray->Set(thread, FUNCTION_EXTRA_INDEX, pointer); - Barriers::SetObject(thread, *obj, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); + Barriers::SetObject(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); } } -void JSFunction::SetSFunctionExtraInfo( - JSThread *thread, void *nativeFunc, const NativePointerCallback &deleter, void *data, size_t nativeBindingsize) +// static +void JSFunction::SetSFunctionExtraInfo(JSThread *thread, const JSHandle &func, void *nativeFunc, + const NativePointerCallback &deleter, void *data, size_t nativeBindingsize) { - JSTaggedType hashField = Barriers::GetValue(this, HASH_OFFSET); + JSTaggedType hashField = Barriers::GetValue(*func, HASH_OFFSET); EcmaVM *vm = thread->GetEcmaVM(); JSHandle value(thread, JSTaggedValue(hashField)); - JSHandle obj(thread, this); JSHandle pointer = vm->GetFactory()->NewSJSNativePointer(nativeFunc, deleter, data, false, nativeBindingsize); - if (!obj->HasHash()) { - Barriers::SetObject(thread, *obj, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); + if (!func->HasHash()) { + Barriers::SetObject(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); return; } if (value->IsHeapObject()) { if (value->IsJSNativePointer()) { - Barriers::SetObject(thread, *obj, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); + Barriers::SetObject(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); return; } JSHandle array(value); @@ -1033,14 +1038,14 @@ void JSFunction::SetSFunctionExtraInfo( } newArray->Set(thread, nativeFieldCount + HASH_INDEX, array->Get(nativeFieldCount + HASH_INDEX)); newArray->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer); - Barriers::SetObject(thread, *obj, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); + Barriers::SetObject(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); } } else { JSHandle newArray = vm->GetFactory()->NewSTaggedArrayWithoutInit(RESOLVED_MAX_SIZE); newArray->SetExtraLength(0); newArray->Set(thread, HASH_INDEX, value); newArray->Set(thread, FUNCTION_EXTRA_INDEX, pointer); - Barriers::SetObject(thread, *obj, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); + Barriers::SetObject(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); } } @@ -1207,6 +1212,15 @@ void JSFunction::SetJitCompiledFuncEntry(JSThread *thread, JSHandle SetCompiledFuncEntry(codeEntry, isFastCall); } +void JSFunction::SetJitHotnessCnt(uint16_t cnt) +{ + JSTaggedValue profileTypeInfoVal = GetProfileTypeInfo(); + if (!profileTypeInfoVal.IsUndefined()) { + ProfileTypeInfo *profileTypeInfo = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject()); + profileTypeInfo->SetJitHotnessCnt(cnt); + } +} + void JSFunctionBase::ClearCompiledCodeFlags() { SetCompiledCodeBit(false); diff --git a/ecmascript/js_function.h b/ecmascript/js_function.h index 66c19eff7f3cd5ab1ee514111cab8dfe9a7fdf4e..c486a1d2f39f0a64b79961ac12c3ef779976b9cc 100644 --- a/ecmascript/js_function.h +++ b/ecmascript/js_function.h @@ -126,6 +126,19 @@ public: return TaskConcurrentFuncFlagBit::Decode(bitField); } + void SetJitCompilingFlag(bool value) + { + uint32_t bitField = GetBitField(); + uint32_t newValue = JitCompilingFlagBit::Update(bitField, value); + SetBitField(newValue); + } + + bool IsJitCompiling() const + { + uint32_t bitField = GetBitField(); + return JitCompilingFlagBit::Decode(bitField); + } + JSTaggedValue GetFunctionExtraInfo() const; /* compiled code flag field */ @@ -134,6 +147,7 @@ public: static constexpr uint32_t COMPILED_CODE_FASTCALL_BITS = 0x3; // 0x3U: compiled code and fastcall bit field using TaskConcurrentFuncFlagBit = IsFastCallBit::NextFlag; // offset 2 + using JitCompilingFlagBit = TaskConcurrentFuncFlagBit::NextFlag; // offset 3 static constexpr size_t METHOD_OFFSET = JSObject::SIZE; ACCESSORS(Method, METHOD_OFFSET, CODE_ENTRY_OFFSET) @@ -312,10 +326,11 @@ public: !ProfileTypeInfoCell::Cast(GetRawProfileTypeInfo())->GetValue().IsUndefined(); } - void SetFunctionExtraInfo(JSThread *thread, void *nativeFunc, const NativePointerCallback &deleter, - void *data, size_t nativeBindingsize = 0, Concurrent isConcurrent = Concurrent::NO); - void SetSFunctionExtraInfo(JSThread *thread, void *nativeFunc, const NativePointerCallback &deleter, - void *data, size_t nativeBindingsize = 0); + static void SetFunctionExtraInfo(JSThread *thread, const JSHandle &func, void *nativeFunc, + const NativePointerCallback &deleter, void *data, size_t nativeBindingsize = 0, + Concurrent isConcurrent = Concurrent::NO); + static void SetSFunctionExtraInfo(JSThread *thread, const JSHandle &func, void *nativeFunc, + const NativePointerCallback &deleter, void *data, size_t nativeBindingsize = 0); static void SetProfileTypeInfo(const JSThread *thread, const JSHandle &func, const JSHandle &value, BarrierMode mode = WRITE_BARRIER); static void UpdateProfileTypeInfoCell(JSThread *thread, JSHandle literalFunc, @@ -332,6 +347,7 @@ public: } void SetJitCompiledFuncEntry(JSThread *thread, JSHandle &machineCode, bool isFastCall); + void SetJitHotnessCnt(uint16_t cnt); static void InitializeForConcurrentFunction(JSThread *thread, JSHandle &func); diff --git a/ecmascript/js_hclass-inl.h b/ecmascript/js_hclass-inl.h index d5e9ee57ca4a9658babddee06c4a6d407cd76488..026e12696977936c848e1bc6d7a90ccc13466d7b 100644 --- a/ecmascript/js_hclass-inl.h +++ b/ecmascript/js_hclass-inl.h @@ -180,7 +180,7 @@ inline void JSHClass::RestoreElementsKindToGeneric(JSHClass *newJsHClass) inline JSHClass *JSHClass::CheckHClassForRep(JSHClass *hclass, const Representation &rep) { - if (!hclass->IsTS()) { + if (!hclass->IsAOT()) { return hclass; } if (rep == Representation::NONE) { diff --git a/ecmascript/js_hclass.cpp b/ecmascript/js_hclass.cpp index eb0b8667937b1f43bc60eb39c7bbb5e808272acd..6e93f62579fb0fec0dc281e4160c64ccdece9539 100644 --- a/ecmascript/js_hclass.cpp +++ b/ecmascript/js_hclass.cpp @@ -147,7 +147,6 @@ void JSHClass::InitializeWithDefaultValue(const JSThread *thread, uint32_t size, SetProtoChangeMarker(thread, JSTaggedValue::Null()); SetProtoChangeDetails(thread, JSTaggedValue::Null()); SetEnumCache(thread, JSTaggedValue::Null()); - SetLevel(0); } bool JSHClass::IsJSTypeShared(JSType type) @@ -157,6 +156,7 @@ bool JSHClass::IsJSTypeShared(JSType type) case JSType::JS_SHARED_OBJECT: case JSType::JS_SHARED_FUNCTION: case JSType::JS_SHARED_ASYNC_FUNCTION: + case JSType::JS_API_BITVECTOR: case JSType::JS_SHARED_SET: case JSType::JS_SHARED_MAP: case JSType::JS_SHARED_ARRAY: @@ -229,8 +229,8 @@ JSHandle JSHClass::Clone(const JSThread *thread, const JSHandleSetLayout(thread, jshclass->GetLayout()); - if (jshclass->IsTS()) { - newJsHClass->SetTS(false); + if (jshclass->IsAOT()) { + newJsHClass->SetAOT(false); } return newJsHClass; @@ -285,7 +285,7 @@ void JSHClass::AddProperty(const JSThread *thread, const JSHandle &obj JSHClass *newClass = jshclass->FindTransitions(key.GetTaggedValue(), metadata, rep); if (newClass != nullptr) { // The transition hclass from AOT, which does not have a prototype, needs to be reset here. - if (newClass->IsTS()) { + if (newClass->IsAOT()) { newClass->SetPrototype(thread, jshclass->GetPrototype()); } // Because we currently only supports Fast ElementsKind @@ -294,7 +294,7 @@ void JSHClass::AddProperty(const JSThread *thread, const JSHandle &obj #if ECMASCRIPT_ENABLE_IC // The transition hclass from AOT, which does not have protochangemarker, needs to be reset here JSHandle newHClass = JSHandle(thread, newClass); - if (newClass->IsTS() && newClass->IsPrototype()) { + if (newClass->IsAOT() && newClass->IsPrototype()) { if (JSHClass::IsNeedNotifyHclassChangedForAotTransition(thread, jshclass, key.GetTaggedValue())) { JSHClass::EnableProtoChangeMarker(thread, newHClass); JSHClass::NotifyHclassChanged(thread, jshclass, newHClass, key.GetTaggedValue()); @@ -390,7 +390,7 @@ JSHClass *JSHClass::FindTransitionProtoForAOT(const JSThread *thread, const JSHa return nullptr; } JSHandle baseIhc(thread, proto->GetTaggedObject()->GetClass()); - if (!jshclass->IsTS() || !baseIhc->IsTS()) { + if (!jshclass->IsAOT() || !baseIhc->IsAOT()) { return nullptr; } auto transitionTable = thread->GetCurrentEcmaContext()->GetFunctionProtoTransitionTable(); @@ -491,7 +491,10 @@ void JSHClass::SetPrototypeTransition(JSThread *thread, const JSHandle auto newClass = SetPrototypeWithNotification(thread, hclass, proto, isChangeProto); RestoreElementsKindToGeneric(*newClass); object->SynchronizedSetClass(thread, *newClass); - thread->NotifyStableArrayElementsGuardians(object, StableArrayChangeKind::PROTO); + if (object->IsJSArray()) { + thread->NotifyArrayPrototypeChangedGuardians(object); + newClass->SetIsJSArrayPrototypeModified(true); + } ObjectOperator::UpdateDetectorOnSetPrototype(thread, object.GetTaggedValue()); } @@ -512,7 +515,7 @@ void JSHClass::OptimizePrototypeForIC(const JSThread *thread, const JSHandleIsTS() && !hclass->IsJSShared()) || isChangeProto) { + if ((!hclass->IsAOT() && !hclass->IsJSShared()) || isChangeProto) { // The local IC and on-proto IC are different, because the former don't need to notify the whole // prototype-chain or listen the changes of prototype chain, but the latter do. Therefore, when // an object becomes a prototype object at the first time, we need to copy its hidden class in @@ -929,7 +932,7 @@ void JSHClass::NotifyHclassChanged(const JSThread *thread, JSHandle ol // it will not have IsPrototype bit set as true. // // Good neww is our AOT hclass can not be shared, hence we can set newHclass IsPrototype as true at here. - if (newHclass->IsTS() && !newHclass->IsPrototype()) { + if (newHclass->IsAOT() && !newHclass->IsPrototype()) { newHclass->SetIsPrototype(true); } JSHClass::NoticeThroughChain(thread, oldHclass, addedKey); @@ -1113,7 +1116,7 @@ void JSHClass::RefreshUsers(const JSThread *thread, const JSHandle &ol PropertyLookupResult JSHClass::LookupPropertyInAotHClass(const JSThread *thread, JSHClass *hclass, JSTaggedValue key) { DISALLOW_GARBAGE_COLLECTION; - ASSERT(hclass->IsTS()); + ASSERT(hclass->IsAOT()); PropertyLookupResult result; if (hclass->IsDictionaryMode()) { @@ -1287,7 +1290,7 @@ JSHandle JSHClass::CreateRootHClassFromPGO(const JSThread* thread, }); hclass->SetLayout(thread, layout); hclass->SetNumberOfProps(numOfProps); - hclass->SetTS(true); + hclass->SetAOT(true); return hclass; } @@ -1304,7 +1307,7 @@ JSHandle JSHClass::CreateRootHClassWithCached(const JSThread* thread, JSHandle layout = factory->CreateLayoutInfo(maxNum, MemSpaceType::SEMI_SPACE, GrowMode::KEEP); hclass->SetPrototype(thread, JSTaggedValue::Null()); hclass->SetLayout(thread, layout); - hclass->SetTS(true); + hclass->SetAOT(true); rootDesc->IterateProps([thread, factory, &index, &hclass](const pgo::PropertyDesc& propDesc) { auto& cstring = propDesc.first; auto& handler = propDesc.second; @@ -1320,7 +1323,7 @@ JSHandle JSHClass::CreateRootHClassWithCached(const JSThread* thread, JSHandle child = SetPropertyOfObjHClass(thread, hclass, key, attributes, rep); child->SetParent(thread, hclass); child->SetPrototype(thread, JSTaggedValue::Null()); - child->SetTS(true); + child->SetAOT(true); hclass = child; }); return hclass; @@ -1337,7 +1340,7 @@ JSHandle JSHClass::CreateChildHClassFromPGO(const JSThread* thread, uint32_t numOfProps = parent->NumberOfProps(); JSHandle newJsHClass = JSHClass::Clone(thread, parent); - newJsHClass->SetTS(true); + newJsHClass->SetAOT(true); ASSERT(newJsHClass->GetInlinedProperties() >= (numOfProps + 1)); uint32_t offset = numOfProps; { diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index c802c48b18f988ed36f37d9574cd3076a3f804a5..77d4bea284592a1909882cd5f5a6cec2851c3e82 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -394,11 +394,11 @@ public: using HasConstructorBits = IsStableElementsBit::NextFlag; // 21 using IsClassConstructorOrPrototypeBit = HasConstructorBits::NextFlag; // 22 using IsNativeBindingObjectBit = IsClassConstructorOrPrototypeBit::NextFlag; // 23 - using IsTSBit = IsNativeBindingObjectBit::NextFlag; // 24 - using LevelBit = IsTSBit::NextField; // 25-29 - using IsJSFunctionBit = LevelBit::NextFlag; // 30 - using IsOnHeap = IsJSFunctionBit::NextFlag; // 31 - using IsJSSharedBit = IsOnHeap::NextFlag; // 32 + using IsAOTBit = IsNativeBindingObjectBit::NextFlag; // 24 + using IsJSArrayPrototypeModifiedBit = IsAOTBit::NextFlag; // 25 + using IsJSFunctionBit = IsJSArrayPrototypeModifiedBit::NextFlag; // 26 + using IsOnHeap = IsJSFunctionBit::NextFlag; // 27 + using IsJSSharedBit = IsOnHeap::NextFlag; // 28 using BitFieldLastBit = IsJSSharedBit; static_assert(BitFieldLastBit::START_BIT + BitFieldLastBit::SIZE <= sizeof(uint32_t) * BITS_PER_BYTE, "Invalid"); @@ -587,9 +587,14 @@ public: IsDictionaryBit::Set(flag, GetBitFieldAddr()); } - inline void SetTS(bool flag) const + inline void SetIsJSArrayPrototypeModified(bool flag) const { - IsTSBit::Set(flag, GetBitFieldAddr()); + IsJSArrayPrototypeModifiedBit::Set(flag, GetBitFieldAddr()); + } + + inline void SetAOT(bool flag) const + { + IsAOTBit::Set(flag, GetBitFieldAddr()); } inline void SetIsJSFunction(bool flag) const @@ -1419,7 +1424,7 @@ public: return GetObjectType() == JSType::TRANS_WITH_PROTO_HANDLER; } - inline bool IsStoreTSHandler() const + inline bool IsStoreAOTHandler() const { return GetObjectType() == JSType::STORE_TS_HANDLER; } @@ -1511,11 +1516,17 @@ public: return IsDictionaryBit::Decode(bits); } - // created from TypeScript Types - inline bool IsTS() const + inline bool IsJSArrayPrototypeModifiedFromBitField() const + { + uint32_t bits = GetBitField(); + return IsJSArrayPrototypeModifiedBit::Decode(bits); + } + + // created from AOT + inline bool IsAOT() const { uint32_t bits = GetBitField(); - return IsTSBit::Decode(bits); + return IsAOTBit::Decode(bits); } inline bool IsJSFunctionFromBitField() const @@ -1794,19 +1805,6 @@ public: return ElementsKindBits::Decode(bits); } - inline void SetLevel(uint8_t level) - { - uint32_t bits = GetBitField(); - uint32_t newVal = LevelBit::Update(bits, level); - SetBitField(newVal); - } - - inline uint8_t GetLevel() const - { - uint32_t bits = GetBitField(); - return LevelBit::Decode(bits); - } - inline void SetIsDictionaryElement(bool value) { uint32_t newVal = DictionaryElementBits::Update(GetBitField(), value); diff --git a/ecmascript/js_map_iterator.cpp b/ecmascript/js_map_iterator.cpp index 7b5ed30080de8f68104d9489c14d9c2735ec9bb3..7a689fddfa0aa374e8245dad99208c4ee4012302 100644 --- a/ecmascript/js_map_iterator.cpp +++ b/ecmascript/js_map_iterator.cpp @@ -87,7 +87,7 @@ JSTaggedValue JSMapIterator::NextInternal(JSThread *thread, JSHandleIsExtensible(); } -inline void JSObject::FillElementsWithHoles(const JSThread *thread, uint32_t start, uint32_t end) +// static +inline void JSObject::FillElementsWithHoles(const JSThread *thread, const JSHandle &obj, + uint32_t start, uint32_t end) { if (start >= end) { return; } - JSHandle holeHandle(thread, JSTaggedValue::Hole()); - JSHandle thisObj(thread, this); for (uint32_t i = start; i < end; i++) { - ElementAccessor::Set(thread, thisObj, i, holeHandle, false); + ElementAccessor::Set(thread, obj, i, holeHandle, false); } } diff --git a/ecmascript/js_object.cpp b/ecmascript/js_object.cpp index 6f6ce48513b3899f222a0a941d73eae07d1fb370..f466dd02b534d46c03b0de6f05c892ab3689f241 100644 --- a/ecmascript/js_object.cpp +++ b/ecmascript/js_object.cpp @@ -248,7 +248,8 @@ void JSObject::ElementsToDictionary(const JSThread *thread, JSHandle o TryMigrateToGenericKindForJSObject(thread, obj, oldKind); } -inline bool JSObject::ShouldOptimizeAsFastElements(const JSThread *thread, JSHandle obj) +bool JSObject::AttributesUnchanged(const JSThread *thread, + const JSHandle &obj) { JSHandle elements(thread, obj->GetElements()); uint32_t size = static_cast(elements->Size()); @@ -268,7 +269,7 @@ inline bool JSObject::ShouldOptimizeAsFastElements(const JSThread *thread, JSHan void JSObject::TryOptimizeAsFastElements(const JSThread *thread, JSHandle obj) { ASSERT(obj->GetJSHClass()->IsDictionaryElement() && obj->IsJSArray()); - if (ShouldOptimizeAsFastElements(thread, obj)) { + if (AttributesUnchanged(thread, obj)) { uint32_t length = JSArray::Cast(*obj)->GetLength(); JSHandle elements(thread, obj->GetElements()); uint32_t size = static_cast(elements->Size()); @@ -393,9 +394,7 @@ bool JSObject::AddElementInternal(JSThread *thread, const JSHandle &re } } if (receiver->IsJSSArray()) { - DISALLOW_GARBAGE_COLLECTION; - JSSharedArray *arr = JSSharedArray::Cast(*receiver); - uint32_t oldLength = arr->GetArrayLength(); + uint32_t oldLength = JSSharedArray::Cast(*receiver)->GetArrayLength(); if (index >= oldLength) { JSHandle newLength(thread, JSTaggedValue(static_cast(index + 1))); JSSharedArray::LengthSetter(thread, receiver, newLength); @@ -404,7 +403,7 @@ bool JSObject::AddElementInternal(JSThread *thread, const JSHandle &re } } } - thread->NotifyStableArrayElementsGuardians(receiver, StableArrayChangeKind::NOT_PROTO); + thread->NotifyArrayPrototypeChangedGuardians(receiver); // check whether to convert to dictionary if (receiver->GetJSHClass()->IsDictionaryElement() && receiver->IsJSArray()) { @@ -487,7 +486,7 @@ void JSObject::GetAllKeys(const JSThread *thread, const JSHandle &obj, int end = static_cast(obj->GetJSHClass()->NumberOfProps()); if (end > 0) { LayoutInfo::Cast(obj->GetJSHClass()->GetLayout().GetTaggedObject()) - ->GetAllKeys(thread, end, offset, *keyArray, obj); + ->GetAllKeys(thread, end, offset, *keyArray); } return; } @@ -511,7 +510,7 @@ void JSObject::GetAllKeysByFilter(const JSThread *thread, const JSHandleGetJSHClass()->NumberOfProps(); if (numberOfProps > 0) { LayoutInfo::Cast(obj->GetJSHClass()->GetLayout().GetTaggedObject())-> - GetAllKeysByFilter(thread, numberOfProps, keyArrayEffectivelength, *keyArray, obj, filter); + GetAllKeysByFilter(thread, numberOfProps, keyArrayEffectivelength, *keyArray, filter); } return; } @@ -569,7 +568,7 @@ JSHandle JSObject::GetAllEnumKeys(JSThread *thread, const JSHandle< int end = static_cast(jsHclass->NumberOfProps()); JSHandle keyArray = factory->NewTaggedArray(numOfKeys + EnumCache::ENUM_CACHE_HEADER_SIZE); LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject()) - ->GetAllEnumKeys(thread, end, EnumCache::ENUM_CACHE_HEADER_SIZE, keyArray, keys, obj); + ->GetAllEnumKeys(thread, end, EnumCache::ENUM_CACHE_HEADER_SIZE, keyArray, keys); JSObject::SetEnumCacheKind(thread, *keyArray, EnumCacheKind::ONLY_OWN_KEYS); if (!JSTaggedValue(jsHclass).IsInSharedHeap()) { jsHclass->SetEnumCache(thread, keyArray.GetTaggedValue()); @@ -596,7 +595,7 @@ uint32_t JSObject::GetAllEnumKeys(JSThread *thread, const JSHandle &ob int end = static_cast(jsHclass->NumberOfProps()); if (end > 0) { LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject()) - ->GetAllEnumKeys(thread, end, offset, keyArray, &keys, obj); + ->GetAllEnumKeys(thread, end, offset, keyArray, &keys); } return keys; } @@ -779,7 +778,7 @@ std::pair JSObject::GetNumberOfEnumKeys() const int end = static_cast(GetJSHClass()->NumberOfProps()); if (end > 0) { LayoutInfo *layout = LayoutInfo::Cast(GetJSHClass()->GetLayout().GetTaggedObject()); - return layout->GetNumOfEnumKeys(end, this); + return layout->GetNumOfEnumKeys(end); } return std::make_pair(0, 0); } @@ -1037,6 +1036,51 @@ bool JSObject::SetProperty(ObjectOperator *op, const JSHandle &va return CallSetter(thread, *accessor, receiver, value, mayThrow); } +bool JSObject::SetPropertyForData(ObjectOperator *op, const JSHandle &value, bool *isAccessor) +{ + JSThread *thread = op->GetThread(); + op->UpdateDetector(); + + JSHandle receiver = op->GetReceiver(); + JSHandle holder = op->GetHolder(); + if (holder->IsJSProxy()) { + if (op->IsElement()) { + JSHandle key(thread, JSTaggedValue(op->GetElementIndex())); + return JSProxy::SetProperty(thread, JSHandle::Cast(holder), key, value, receiver, true); + } + return JSProxy::SetProperty(thread, JSHandle::Cast(holder), op->GetKey(), value, receiver, true); + } + + // When op is not found and is not set extra attributes + if (!op->IsFound() && op->IsPrimitiveAttr()) { + op->SetAsDefaultAttr(); + } + + bool isInternalAccessor = false; + if (op->IsAccessorDescriptor()) { + JSTaggedValue ret = ShouldGetValueFromBox(op); + isInternalAccessor = AccessorData::Cast(ret.GetTaggedObject())->IsInternal(); + } + + // 5. If IsDataDescriptor(ownDesc) is true, then + if (!op->IsAccessorDescriptor() || isInternalAccessor) { + return SetPropertyForDataDescriptor(op, value, receiver, true, isInternalAccessor); + } + // 6. Assert: IsAccessorDescriptor(ownDesc) is true. + ASSERT(op->IsAccessorDescriptor()); + *isAccessor = true; + return true; +} + +bool JSObject::SetPropertyForAccessor(ObjectOperator *op, const JSHandle &value) +{ + JSThread *thread = op->GetThread(); + JSHandle receiver = op->GetReceiver(); + JSTaggedValue ret = JSObject::ShouldGetValueFromBox(op); + AccessorData *accessor = AccessorData::Cast(ret.GetTaggedObject()); + return JSObject::CallSetter(thread, *accessor, receiver, value, true); +} + bool JSObject::CallSetter(JSThread *thread, const AccessorData &accessor, const JSHandle &receiver, const JSHandle &value, bool mayThrow) { @@ -1665,7 +1709,7 @@ void JSObject::CollectEnumKeysAlongProtoChain(JSThread *thread, const JSHandle(jsHclass->NumberOfProps()); if (end > 0) { LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject()) - ->GetAllEnumKeys(thread, end, *keys, keyArray, keys, shadowQueue, obj, lastLength); + ->GetAllEnumKeys(thread, end, *keys, keyArray, keys, shadowQueue, lastLength); } return; } @@ -2627,7 +2671,7 @@ JSHandle JSObject::EnumerateObjectProperties(JSThread *thread, JSMutableHandle keys(thread, JSTaggedValue::Undefined()); JSMutableHandle cachedHclass(thread, JSTaggedValue::Undefined()); - if (object->IsNull() || object->IsUndefined()) { + if (object->IsNull() || object->IsUndefined() || object->IsJSNativePointer()) { JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); keys.Update(factory->EmptyArray()); @@ -2721,7 +2765,7 @@ JSHandle JSObject::CreateObjectFromProperties(const JSThread *thread, hclass = factory->GetObjectLiteralHClass(properties, propsLen); isLiteral = true; } - if (hclass->IsTS()) { + if (hclass->IsAOT()) { if (CheckPropertiesForRep(properties, propsLen, hclass)) { return CreateObjectFromPropertiesByIHClass(thread, properties, propsLen, hclass); } else if (!isLiteral) { @@ -2833,7 +2877,7 @@ void JSObject::AddAccessor(JSThread *thread, const JSHandle &obj, bool JSObject::UpdatePropertyInDictionary(const JSThread *thread, JSTaggedValue key, JSTaggedValue value) { - [[maybe_unused]] DisallowGarbageCollection noGc; + DISALLOW_GARBAGE_COLLECTION; NameDictionary *dict = NameDictionary::Cast(GetProperties().GetTaggedObject()); int entry = dict->FindEntry(key); if (entry == -1) { @@ -2865,11 +2909,12 @@ void ECMAObject::SetHash(const JSThread *thread, int32_t hash, const JSHandleSet(thread, array->GetExtraLength() + HASH_INDEX, JSTaggedValue(hash)); } else if (value.IsNativePointer()) { // FunctionExtraInfo + JSHandle nativePointer(thread, value); JSHandle newArray = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(RESOLVED_MAX_SIZE); newArray->SetExtraLength(0); newArray->Set(thread, HASH_INDEX, JSTaggedValue(hash)); - newArray->Set(thread, FUNCTION_EXTRA_INDEX, value); + newArray->Set(thread, FUNCTION_EXTRA_INDEX, nativePointer.GetTaggedValue()); Barriers::SetObject(thread, *obj, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); } else { LOG_ECMA(FATAL) << "this branch is unreachable"; @@ -2925,17 +2970,18 @@ void *ECMAObject::GetNativePointerField(int32_t index) const return nullptr; } -void ECMAObject::SetNativePointerField(const JSThread *thread, int32_t index, void *nativePointer, - const NativePointerCallback &callBack, void *data, size_t nativeBindingsize, Concurrent isConcurrent) +// static +void ECMAObject::SetNativePointerField(const JSThread *thread, const JSHandle &obj, int32_t index, + void *nativePointer, const NativePointerCallback &callBack, void *data, + size_t nativeBindingsize, Concurrent isConcurrent) { - JSTaggedType hashField = Barriers::GetValue(this, HASH_OFFSET); + JSTaggedType hashField = Barriers::GetValue(*obj, HASH_OFFSET); JSTaggedValue value(hashField); if (value.IsTaggedArray()) { JSHandle array(thread, value); if (static_cast(array->GetExtraLength()) > index) { EcmaVM *vm = thread->GetEcmaVM(); JSHandle current = JSHandle(thread, array->Get(thread, index)); - JSHandle obj(thread, this); if (!current->IsHole() && nativePointer == nullptr) { // Try to remove native pointer if exists. vm->RemoveFromNativePointerList(*JSHandle(current)); @@ -2965,14 +3011,14 @@ int32_t ECMAObject::GetNativePointerFieldCount() const return len; } -void ECMAObject::SetNativePointerFieldCount(const JSThread *thread, int32_t count) +// static +void ECMAObject::SetNativePointerFieldCount(const JSThread *thread, const JSHandle &obj, int32_t count) { if (count == 0) { return; } - JSTaggedType hashField = Barriers::GetValue(this, HASH_OFFSET); + JSTaggedType hashField = Barriers::GetValue(*obj, HASH_OFFSET); JSHandle value(thread, JSTaggedValue(hashField)); - JSHandle obj(thread, this); JSHandle object(obj); bool isShared = object->IsJSShared(); if (value->IsHeapObject()) { diff --git a/ecmascript/js_object.h b/ecmascript/js_object.h index e88a31c06ad50d843e4aa43881a0ae80b5e60d11..a85ddf6ea62e6ffcb59c4aad3e90f01bbea8df5c 100644 --- a/ecmascript/js_object.h +++ b/ecmascript/js_object.h @@ -385,11 +385,11 @@ public: } void* GetNativePointerField(int32_t index) const; - void SetNativePointerField(const JSThread *thread, int32_t index, void *nativePointer, - const NativePointerCallback &callBack, void *data, size_t nativeBindingsize = 0, - Concurrent isConcurrent = Concurrent::NO); + static void SetNativePointerField(const JSThread *thread, const JSHandle &obj, int32_t index, + void *nativePointer, const NativePointerCallback &callBack, void *data, + size_t nativeBindingsize = 0, Concurrent isConcurrent = Concurrent::NO); int32_t GetNativePointerFieldCount() const; - void SetNativePointerFieldCount(const JSThread *thread, int32_t count); + static void SetNativePointerFieldCount(const JSThread *thread, const JSHandle &obj, int32_t count); DECL_VISIT_OBJECT(HASH_OFFSET, SIZE); @@ -605,7 +605,8 @@ public: const JSHandle &receiver, const JSHandle &value, bool mayThrow = false); - void FillElementsWithHoles(const JSThread *thread, uint32_t start, uint32_t end); + static void FillElementsWithHoles(const JSThread *thread, const JSHandle &obj, + uint32_t start, uint32_t end); JSHClass *GetJSHClass() const { @@ -715,7 +716,12 @@ public: DECL_VISIT_OBJECT_FOR_JS_OBJECT(ECMAObject, PROPERTIES_OFFSET, SIZE) - DECL_DUMP() + void Dump(std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR; + void Dump() const DUMP_API_ATTR + { + Dump(std::cout); + } + void DumpForSnapshot(std::vector &vec) const; static const CString ExtractConstructorAndRecordName(JSThread *thread, TaggedObject *obj, bool noAllocate = false, bool *isCallGetter = nullptr); @@ -745,7 +751,7 @@ public: bool UpdatePropertyInDictionary(const JSThread *thread, JSTaggedValue key, JSTaggedValue value); static bool ShouldTransToDict(uint32_t capacity, uint32_t index); static bool ShouldTransToFastElements(JSThread *thread, TaggedArray *elements, uint32_t capacity, uint32_t index); - static bool ShouldOptimizeAsFastElements(const JSThread *thread, JSHandle obj); + static bool AttributesUnchanged(const JSThread *thread, const JSHandle &obj); static JSHandle GrowElementsCapacity(const JSThread *thread, const JSHandle &obj, uint32_t capacity, bool highGrowth = false, bool isNew = false); @@ -768,7 +774,6 @@ public: static void PUBLIC_API TryMigrateToGenericKindForJSObject(const JSThread *thread, const JSHandle &obj, const ElementsKind oldKind); -protected: static void ElementsToDictionary(const JSThread *thread, JSHandle obj); private: @@ -789,6 +794,8 @@ private: static JSTaggedValue GetProperty(JSThread *thread, ObjectOperator *op); static bool SetProperty(ObjectOperator *op, const JSHandle &value, bool mayThrow); + static bool SetPropertyForData(ObjectOperator *op, const JSHandle &value, bool *isAccessor); + static bool SetPropertyForAccessor(ObjectOperator *op, const JSHandle &value); static void DeletePropertyInternal(JSThread *thread, const JSHandle &obj, const JSHandle &key, uint32_t index); int FindProperty(const JSHandle &key); diff --git a/ecmascript/js_proxy.cpp b/ecmascript/js_proxy.cpp index 4868b1223bfb83b4196427ae4c0531dc3da17f6d..398d67bb4b272324bfcf676f84caf36d0b46ecf2 100644 --- a/ecmascript/js_proxy.cpp +++ b/ecmascript/js_proxy.cpp @@ -74,12 +74,12 @@ JSTaggedValue JSProxy::GetPrototype(JSThread *thread, const JSHandle &p EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, trap, handler, undefined, 1); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); info->SetCallArg(targetHandle.GetTaggedValue()); - JSTaggedValue handlerProto = JSFunction::Call(info); + JSHandle handlerProto(thread, JSFunction::Call(info)); // 9. ReturnIfAbrupt(handlerProto). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 10. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception. - if (!handlerProto.IsECMAObject() && !handlerProto.IsNull()) { + if (!handlerProto->IsECMAObject() && !handlerProto->IsNull()) { THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetPrototype: Type(handlerProto) is neither Object nor Null", JSTaggedValue::Exception()); } @@ -87,7 +87,7 @@ JSTaggedValue JSProxy::GetPrototype(JSThread *thread, const JSHandle &p // 12. ReturnIfAbrupt(extensibleTarget). // 13. If extensibleTarget is true, return handlerProto. if (targetHandle->IsExtensible(thread)) { - return handlerProto; + return handlerProto.GetTaggedValue(); } RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -96,12 +96,12 @@ JSTaggedValue JSProxy::GetPrototype(JSThread *thread, const JSHandle &p // 15. ReturnIfAbrupt(targetProto). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 16. If SameValue(handlerProto, targetProto) is false, throw a TypeError exception. - if (!JSTaggedValue::SameValue(handlerProto, targetProto)) { + if (!JSTaggedValue::SameValue(handlerProto.GetTaggedValue(), targetProto)) { THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetPrototype: SameValue(handlerProto, targetProto) is false", JSTaggedValue::Exception()); } // 17. Return handlerProto. - return handlerProto; + return handlerProto.GetTaggedValue(); } // ES6 9.5.2 [[SetPrototypeOf]] (V) diff --git a/ecmascript/js_regexp_iterator.cpp b/ecmascript/js_regexp_iterator.cpp index ad1dca016f557a793e67ce8c1ac2fe36e98ee87e..4811b28f90474d5618a9bc97f4142b8e37c603ff 100644 --- a/ecmascript/js_regexp_iterator.cpp +++ b/ecmascript/js_regexp_iterator.cpp @@ -56,7 +56,7 @@ JSTaggedValue JSRegExpIterator::Next(EcmaRuntimeCallInfo *argv) // 9. Let match be ? RegExpExec(R, S). JSMutableHandle match(thread, JSTaggedValue::Undefined()); - bool isFastPath = BuiltinsRegExp::IsFastRegExp(thread, regexp); + bool isFastPath = BuiltinsRegExp::IsFastRegExp(thread, regexp.GetTaggedValue()); if (isFastPath) { match.Update(BuiltinsRegExp::RegExpBuiltinExec(thread, regexp, inputStr, isFastPath, true)); } else { diff --git a/ecmascript/js_runtime_options.cpp b/ecmascript/js_runtime_options.cpp index f74c1a163652389210e9da332d2868d0c0d91e81..5b51de70b909ca64c232cb7e952b4817bf403de0 100644 --- a/ecmascript/js_runtime_options.cpp +++ b/ecmascript/js_runtime_options.cpp @@ -134,7 +134,6 @@ const std::string PUBLIC_API HELP_OPTION_MSG = "--enable-pgo-profiler: Enable pgo profiler to sample jsfunction call and output to file. " "Default: 'false'\n" "--enable-elements-kind: Enable elementsKind sampling and usage. Default: 'false'\n" - "--enable-force-ic: Enable force ic for pgo. Default: 'true'\n" "--compiler-pgo-hotness-threshold: Set hotness threshold for pgo in aot compiler. Default: '2'\n" "--compiler-pgo-profiler-path: The pgo file output dir or the pgo file dir of AOT compiler. Default: ''\n" "--compiler-pgo-save-min-interval: Set the minimum time interval for automatically saving profile, " @@ -197,7 +196,9 @@ const std::string PUBLIC_API HELP_OPTION_MSG = "--async-load-abc-test: Enable asynchronous load abc test. Default: 'false'\n" "--compiler-enable-concurrent: Enable concurrent compile(only support in ark_stub_compiler).\n" " Default: 'true'\n" - "--compiler-opt-frame-state-elimination: Enable frame state elimination. Default: 'true'\n\n"; + "--compiler-opt-frame-state-elimination: Enable frame state elimination. Default: 'true'\n" + "--compiler-enable-aot-code-comment Enable generate aot_code_comment.txt file during compilation.\n" + " Default : 'false'\n\n"; bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) { @@ -276,7 +277,6 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) {"enable-print-execute-time", required_argument, nullptr, OPTION_PRINT_EXECUTE_TIME}, {"enable-pgo-profiler", required_argument, nullptr, OPTION_ENABLE_PGO_PROFILER}, {"enable-elements-kind", required_argument, nullptr, OPTION_ENABLE_ELEMENTSKIND}, - {"enable-force-ic", required_argument, nullptr, OPTION_ENABLE_FORCE_IC}, {"compiler-pgo-profiler-path", required_argument, nullptr, OPTION_COMPILER_PGO_PROFILER_PATH}, {"compiler-pgo-hotness-threshold", required_argument, nullptr, OPTION_COMPILER_PGO_HOTNESS_THRESHOLD}, {"compiler-pgo-save-min-interval", required_argument, nullptr, OPTION_COMPILER_PGO_SAVE_MIN_INTERVAL}, @@ -338,6 +338,7 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) {"compiler-enable-concurrent", required_argument, nullptr, OPTION_COMPILER_ENABLE_CONCURRENT}, {"compiler-opt-frame-state-elimination", required_argument, nullptr, OPTION_COMPILER_OPT_FRAME_STATE_ELIMINATION}, + {"compiler-enable-aot-code-comment", required_argument, nullptr, OPTION_COMPILER_ENABLE_AOT_CODE_COMMENT}, {nullptr, 0, nullptr, 0}, }; @@ -735,14 +736,6 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) return false; } break; - case OPTION_ENABLE_FORCE_IC: - ret = ParseBoolParam(&argBool); - if (ret) { - SetEnableForceIC(argBool); - } else { - return false; - } - break; case OPTION_COMPILER_PGO_PROFILER_PATH: if (*optarg == '\0') { return false; @@ -1311,13 +1304,21 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) } break; case OPTION_COMPILER_ENABLE_PGO_SPACE: - ret = ParseBoolParam(&argBool); + ret = ParseBoolParam(&argBool); if (ret) { SetCompilerEnablePgoSpace(argBool); } else { return false; } break; + case OPTION_COMPILER_ENABLE_AOT_CODE_COMMENT: + ret = ParseBoolParam(&argBool); + if (ret) { + SetEnableAotCodeComment(argBool); + } else { + return false; + } + break; default: LOG_ECMA(ERROR) << "Invalid option\n"; return false; diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index 2f4a47e62b0a8ccb441a528f4c4d2a8c91c0e670..6db993c335436563cb12d02a88a416faf14f78d6 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -62,7 +62,8 @@ enum ArkProperties { DISABLE_SHARED_CONCURRENT_MARK = 1 << 22, ENABLE_ESM_TRACE = 1 << 24, ENABLE_MODULE_LOG = 1 << 25, - ENABLE_SERIALIZATION_TIMEOUT_CHECK = 1 << 26 + ENABLE_SERIALIZATION_TIMEOUT_CHECK = 1 << 26, + ENABLE_PAGETAG_THREAD_ID = 1 << 27, }; // asm interpreter control parsed option @@ -141,8 +142,9 @@ enum CommandValues { OPTION_COMPILER_PGO_HOTNESS_THRESHOLD, OPTION_COMPILER_PGO_SAVE_MIN_INTERVAL, OPTION_ENABLE_PGO_PROFILER, - OPTION_PRINT_EXECUTE_TIME, + OPTION_INVALID, OPTION_SPLIT_ONE, + OPTION_PRINT_EXECUTE_TIME, OPTION_ENABLE_EDEN_GC, OPTION_COMPILER_DEVICE_STATE, OPTION_COMPILER_VERIFY_VTABLE, @@ -205,8 +207,8 @@ enum CommandValues { OPTION_COMPILER_FORCE_BASELINEJIT_COMPILE_MAIN, OPTION_ENABLE_AOT_CRASH_ESCAPE, OPTION_COMPILER_ENABLE_JIT_FAST_COMPILE, - OPTION_COMPILER_BASELINE_PGO, OPTION_SPLIT_TWO, + OPTION_COMPILER_BASELINE_PGO, OPTION_ASYNC_LOAD_ABC, OPTION_ASYNC_LOAD_ABC_TEST, OPTION_PGO_TRACE, @@ -215,9 +217,10 @@ enum CommandValues { OPTION_COMPILER_OPT_STRING, OPTION_OPEN_ARK_TOOLS, OPTION_COMPILER_OPT_FRAME_STATE_ELIMINATION, - OPTION_ENABLE_FORCE_IC, OPTION_COMPILER_ENABLE_PGO_SPACE, + OPTION_COMPILER_ENABLE_AOT_CODE_COMMENT, }; +static_assert(OPTION_INVALID == 63); // Placeholder for invalid options static_assert(OPTION_SPLIT_ONE == 64); // add new option at the bottom, DO NOT modify this value static_assert(OPTION_SPLIT_TWO == 128); // add new option at the bottom, DO NOT modify this value @@ -632,6 +635,11 @@ public: return (static_cast(arkProperties_) & ArkProperties::ENABLE_SERIALIZATION_TIMEOUT_CHECK) != 0; } + bool EnablePageTagThreadId() const + { + return (static_cast(arkProperties_) & ArkProperties::ENABLE_PAGETAG_THREAD_ID) != 0; + } + bool WasSetMaxNonmovableSpaceCapacity() const { return WasOptionSet(OPTION_MAX_UNMOVABLE_SPACE); @@ -1086,16 +1094,6 @@ public: return enableElementsKind_; } - void SetEnableForceIC(bool value) - { - enableForceIC_ = value; - } - - bool IsEnableForceIC() const - { - return enableForceIC_; - } - void SetEnablePGOProfiler(bool value) { enablePGOProfiler_ = value; @@ -1965,7 +1963,7 @@ public: { return aotHasException_; } - + void SetCompilerEnablePgoSpace(bool value) { enablePgoSpace_ = value; @@ -1976,6 +1974,16 @@ public: return enablePgoSpace_; } + void SetEnableAotCodeComment(bool value) + { + enableAotCodeComment_ = value; + } + + bool IsEnableAotCodeComment() const + { + return enableAotCodeComment_; + } + public: static constexpr int32_t MAX_APP_COMPILE_METHOD_SIZE = 4_KB; @@ -2072,7 +2080,6 @@ private: bool enableValueNumbering_ {true}; bool enableOptString_ {true}; bool enableElementsKind_ {false}; - bool enableForceIC_ {true}; bool enableInstrcutionCombine {true}; bool enableNewValueNumbering_ {true}; bool enableOptInlining_ {true}; @@ -2138,6 +2145,7 @@ private: bool enableTypedOpProfiler_ {false}; bool enableBranchProfiling_ {true}; bool enablePgoSpace_ {false}; + bool enableAotCodeComment_ {false}; bool testAssert_ {false}; std::pair compileMethodsRange_ {0, UINT32_MAX}; arg_list_t compileCodegenOption_ {{""}}; diff --git a/ecmascript/js_set_iterator.cpp b/ecmascript/js_set_iterator.cpp index a8506b414a01f988e3df7ec77bb8cc845dcd5f45..6fcc51ed1533705a5791755fc32c1ab561dccfb7 100644 --- a/ecmascript/js_set_iterator.cpp +++ b/ecmascript/js_set_iterator.cpp @@ -79,7 +79,7 @@ JSTaggedValue JSSetIterator::NextInternal(JSThread *thread, JSHandle receiver, EcmaRuntimeCallIn return result->IsHole() ? JSTaggedValue::Undefined() : result.GetTaggedValue(); } +#if ENABLE_NEXT_OPTIMIZATION +bool JSStableArray::WorthUseTreeString(uint32_t sepLength, size_t allocateLength, uint32_t len) +{ + if (allocateLength >= TREE_STRING_THRESHOLD) { + // if sepLength is 0, means all the elements in treeString is len -1; + // otherwise, the num of elements is (len-1)(string in vector) + (len -1)(num of seps) + size_t treeStringElementNum = (sepLength == 0) ? (len - 1) : (2 * (len - 1)); + + if (treeStringElementNum * TreeEcmaString::SIZE <= allocateLength) { + // heuristic: if tree string uses less memory than linestring, it is worth. + // In other words, we hope tree string can work for the large strings join. + return true; + } + } + return false; +} + +template +JSTaggedValue JSStableArray::JoinUseTreeString(const JSThread *thread, const JSHandle receiverValue, + const JSHandle sepStringHandle, uint32_t sepLength, + Container &arrElements, int elemNum) +{ + // Do not concat the elements one by one, it will make the tree string unbalanced. Concat each element with its + // right neighbor first level by level, then the tree string will be balanced as possible. + if (sepLength != 0) { + for (int k = 0; k < elemNum - 1; k++) { + arrElements[k] = JSHandle( + thread, EcmaStringAccessor::Concat(thread->GetEcmaVM(), arrElements[k], sepStringHandle)); + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, receiverValue); + } + } + + while (elemNum > 1) { + size_t newNum = (elemNum + 1) / NUM_2; + for (size_t i = 0; i < elemNum / NUM_2; ++i) { + arrElements[i] = JSHandle( + thread, + EcmaStringAccessor::Concat(thread->GetEcmaVM(), arrElements[NUM_2 * i], arrElements[NUM_2 * i + 1]) + ); + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, receiverValue); + } + if (elemNum % NUM_2 == 1) { + arrElements[newNum - 1] = arrElements[elemNum - 1]; + } + elemNum = newNum; + } + thread->GetCurrentEcmaContext()->JoinStackPopFastPath(receiverValue); + return arrElements[0].GetTaggedValue(); +} + +template +void JSStableArray::ProcessElements(JSThread *thread, JSHandle receiverValue, uint32_t len, + Container &arrElements, bool &isOneByte, uint64_t &allocateLength) +{ + JSMutableHandle elementHandle(thread, JSTaggedValue::Undefined()); + JSHandle obj(thread, receiverValue.GetTaggedValue()); + JSTaggedValue element = JSTaggedValue::Undefined(); + for (uint32_t k = 0; k < len; k++) { + element = ElementAccessor::Get(obj, k); + if (element.IsHole() && JSTaggedValue::HasProperty(thread, receiverValue, k)) { + element = JSArray::FastGetPropertyByValue(thread, receiverValue, k).GetTaggedValue(); + RETURN_IF_ABRUPT_COMPLETION(thread); + } + if (!element.IsUndefinedOrNull() && !element.IsHole()) { + if (!element.IsString()) { + elementHandle.Update(element); + JSHandle strElement = JSTaggedValue::ToString(thread, elementHandle); + RETURN_IF_ABRUPT_COMPLETION(thread); + element = strElement.GetTaggedValue(); + } + auto nextStr = EcmaString::Cast(element.GetTaggedObject()); + arrElements[k] = JSHandle(thread, nextStr); + isOneByte = isOneByte & EcmaStringAccessor(nextStr).IsUtf8(); + allocateLength += EcmaStringAccessor(nextStr).GetLength(); + } else { + arrElements[k] = JSHandle(thread->GlobalConstants()->GetHandledEmptyString()); + } + } +} + +template +JSTaggedValue JSStableArray::DoStableArrayJoin(JSThread *thread, JSHandle receiverValue, uint32_t len, + Container &arrElements, bool &isOneByte, uint32_t sep, + uint32_t sepLength, JSHandle sepStringHandle) +{ + auto context = thread->GetCurrentEcmaContext(); + uint64_t allocateLength = 0; + ProcessElements(thread, receiverValue, len, arrElements, isOneByte, allocateLength); + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, receiverValue); + + if (len > 0) { + allocateLength += static_cast(sepLength) * (len - 1); + } + if (allocateLength > EcmaString::MAX_STRING_LENGTH) { + context->JoinStackPopFastPath(receiverValue); + THROW_RANGE_ERROR_AND_RETURN(thread, "Invalid string length", JSTaggedValue::Exception()); + } + if (WorthUseTreeString(sepLength, allocateLength, len)) { + return JoinUseTreeString(thread, receiverValue, sepStringHandle, sepLength, arrElements, len); + } + + // 5. Let R be the empty String. + auto newString = + EcmaStringAccessor::CreateLineString(thread->GetEcmaVM(), static_cast(allocateLength), isOneByte); + int current = 0; + DISALLOW_GARBAGE_COLLECTION; + // 6. Repeat, while k < len + for (uint32_t k = 0; k < len; k++) { + // a. If k > 0, set R to the string-concatenation of R and sep. + if (k > 0) { + if (sepLength == 1) { + EcmaStringAccessor(newString).Set(current, static_cast(sep)); + } else if (sepLength > 1) { + EcmaStringAccessor::ReadData(newString, *sepStringHandle, current, + allocateLength - static_cast(current), sepLength); + } + current += static_cast(sepLength); + } + // b. Let element be ? Get(O, ToString(𝔽(k))). + JSHandle nextStr = arrElements[k]; + + // c. Set R to the string-concatenation of R and S + int nextLength = static_cast(EcmaStringAccessor(nextStr).GetLength()); + EcmaStringAccessor::ReadData(newString, *nextStr, current, allocateLength - static_cast(current), + nextLength); + current += nextLength; + } + ASSERT_PRINT(isOneByte == EcmaStringAccessor::CanBeCompressed(newString), + "isOneByte does not match the real value!"); + context->JoinStackPopFastPath(receiverValue); + // return R + return JSTaggedValue(newString); +} + +JSTaggedValue JSStableArray::Join(JSHandle receiver, EcmaRuntimeCallInfo *argv) +{ + JSThread *thread = argv->GetThread(); + const GlobalEnvConstants *globalConst = thread->GlobalConstants(); + auto context = thread->GetCurrentEcmaContext(); + + // 1. Let O be ToObject(this.value) + JSHandle receiverValue = JSHandle::Cast(receiver); + JSHandle obj(thread, receiverValue.GetTaggedValue()); + + // 2. Let len be ToLength(Get(O, "length")) + uint32_t len = receiver->GetArrayLength(); + + int sep = ','; + uint32_t sepLength = 1; + JSHandle sepHandle = base::BuiltinsBase::GetCallArg(argv, 0); + JSHandle sepStringHandle; + if (sepHandle->IsUndefined()) { + // 3. If separator is undefined, let sep be ",". + sepHandle = globalConst->GetHandledCommaString(); + sepStringHandle = JSTaggedValue::ToString(thread, sepHandle); + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, receiverValue); + } else { + // 4. Else, let sep be ? ToString(separator). + sepStringHandle = JSTaggedValue::ToString(thread, sepHandle); + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, receiverValue); + sepLength = EcmaStringAccessor(sepStringHandle).GetLength(); + if (sepLength == 1) { + sep = EcmaStringAccessor(sepStringHandle).Get(0); + } + } + + bool isOneByte = EcmaStringAccessor(sepStringHandle).IsUtf8(); + + // Fastpath should put after parsing "sep". Error may occur if sep cannout be transformed to string, + // which should be handled before fastpath return. + if (len == 0) { + context->JoinStackPopFastPath(receiverValue); + return globalConst->GetEmptyString(); + } + + if (len == 1) { + // sep unused, set isOneByte to default(true) + isOneByte = true; + } + + // Use stack memory if the number of elements is less than USE_STACK_MEMORY_THRESHOLD. + // arr can be faster then vector. + if (len <= USE_STACK_MEMORY_THRESHOLD) { + std::array, USE_STACK_MEMORY_THRESHOLD> arr; + return DoStableArrayJoin(thread, receiverValue, len, arr, isOneByte, sep, sepLength, sepStringHandle); + } else { + CVector> vec(len); + return DoStableArrayJoin(thread, receiverValue, len, vec, isOneByte, sep, sepLength, sepStringHandle); + } +} +#endif + +#if !ENABLE_NEXT_OPTIMIZATION void JSStableArray::SetSepValue(JSHandle sepStringHandle, int &sep, uint32_t &sepLength) { if (EcmaStringAccessor(sepStringHandle).IsUtf8() && EcmaStringAccessor(sepStringHandle).GetLength() == 1) { @@ -446,17 +639,18 @@ bool JSStableArray::WorthUseTreeString(int sep, size_t allocateLength, uint32_t return false; } -JSTaggedValue JSStableArray::JoinUseTreeString(const JSThread* thread, const JSHandle receiverValue, +JSTaggedValue JSStableArray::JoinUseTreeString(const JSThread *thread, + const JSHandle receiverValue, const JSHandle sepStringHandle, const int sep, - CVector>& vec) + CVector> &vec) { // Do not concat the elements one by one, it will make the tree string unbalanced. Concat each element with its // right neighbor first level by level, then the tree string will be balanced as possible. if (sep != JSStableArray::SeparatorFlag::MINUS_TWO) { auto last = std::prev(vec.end()); for (auto iter = vec.begin(); iter != last; ++iter) { - *iter = JSHandle( - thread, EcmaStringAccessor::Concat(thread->GetEcmaVM(), *iter, sepStringHandle)); + *iter = + JSHandle(thread, EcmaStringAccessor::Concat(thread->GetEcmaVM(), *iter, sepStringHandle)); RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, receiverValue); } } @@ -484,7 +678,8 @@ JSTaggedValue JSStableArray::Join(JSHandle receiver, EcmaRuntimeCallInf JSHandle sepHandle = base::BuiltinsBase::GetCallArg(argv, 0); int sep = ','; uint32_t sepLength = 1; - JSHandle sepStringHandle; + const GlobalEnvConstants *globalConst = thread->GlobalConstants(); + JSHandle sepStringHandle = JSHandle::Cast(globalConst->GetHandledCommaString()); auto context = thread->GetCurrentEcmaContext(); JSHandle receiverValue = JSHandle::Cast(receiver); if (!sepHandle->IsUndefined()) { @@ -497,7 +692,6 @@ JSTaggedValue JSStableArray::Join(JSHandle receiver, EcmaRuntimeCallInf SetSepValue(sepStringHandle, sep, sepLength); } if (length == 0) { - const GlobalEnvConstants *globalConst = thread->GlobalConstants(); context->JoinStackPopFastPath(receiverValue); return globalConst->GetEmptyString(); } @@ -505,7 +699,6 @@ JSTaggedValue JSStableArray::Join(JSHandle receiver, EcmaRuntimeCallInf uint64_t allocateLength = 0; bool isOneByte = (sep != JSStableArray::SeparatorFlag::MINUS_ONE) || EcmaStringAccessor(sepStringHandle).IsUtf8(); JSMutableHandle elementHandle(thread, JSTaggedValue::Undefined()); - const GlobalEnvConstants *globalConst = thread->GlobalConstants(); uint32_t elementsLength = ElementAccessor::GetElementsLength(obj); uint32_t len = elementsLength > length ? length : elementsLength; if (elementsLength == 0 && length != 0) { @@ -552,7 +745,7 @@ JSTaggedValue JSStableArray::Join(JSHandle receiver, EcmaRuntimeCallInf return JoinUseTreeString(thread, receiverValue, sepStringHandle, sep, vec); } auto newString = - EcmaStringAccessor::CreateLineString(thread->GetEcmaVM(), static_cast(allocateLength), isOneByte); + EcmaStringAccessor::CreateLineString(thread->GetEcmaVM(), static_cast(allocateLength), isOneByte); int current = 0; DISALLOW_GARBAGE_COLLECTION; for (uint32_t k = 0; k < len; k++) { @@ -561,21 +754,22 @@ JSTaggedValue JSStableArray::Join(JSHandle receiver, EcmaRuntimeCallInf EcmaStringAccessor(newString).Set(current, static_cast(sep)); } else if (sep != JSStableArray::SeparatorFlag::MINUS_TWO) { EcmaStringAccessor::ReadData(newString, *sepStringHandle, current, - allocateLength - static_cast(current), sepLength); + allocateLength - static_cast(current), sepLength); } current += static_cast(sepLength); } JSHandle nextStr = vec[k]; int nextLength = static_cast(EcmaStringAccessor(nextStr).GetLength()); - EcmaStringAccessor::ReadData(newString, *nextStr, current, - allocateLength - static_cast(current), nextLength); + EcmaStringAccessor::ReadData(newString, *nextStr, current, allocateLength - static_cast(current), + nextLength); current += nextLength; } - ASSERT_PRINT( - isOneByte == EcmaStringAccessor::CanBeCompressed(newString), "isOneByte does not match the real value!"); + ASSERT_PRINT(isOneByte == EcmaStringAccessor::CanBeCompressed(newString), + "isOneByte does not match the real value!"); context->JoinStackPopFastPath(receiverValue); return JSTaggedValue(newString); } +#endif JSTaggedValue JSStableArray::HandleFindIndexOfStable(JSThread *thread, JSHandle thisObjHandle, JSHandle callbackFnHandle, @@ -1478,13 +1672,110 @@ JSTaggedValue JSStableArray::Slice(JSThread *thread, JSHandle thisObjH return arrayObj.GetTaggedValue(); } -JSTaggedValue JSStableArray::Sort(JSThread *thread, const JSHandle &thisObj, - const JSHandle &callbackFnHandle) +JSHandle JSStableArray::SortIndexedProperties(JSThread *thread, const JSHandle &thisObjVal, + int64_t len, const JSHandle &callbackFnHandle, + base::HolesType holes) { - JSArray::SortElementsByObject(thread, thisObj, callbackFnHandle); + JSHandle thisObj(thread, thisObjVal.GetTaggedValue()); + JSHandle elements(thread, thisObj->GetElements()); + ElementsKind kind = thisObj->GetClass()->GetElementsKind(); + if (!elements->GetClass()->IsMutantTaggedArray()) { + kind = ElementsKind::GENERIC; + } + // 1. fill elements into items. + JSHandle items(thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len)); + bool kRead = false; + int64_t tmp = 0; + for (int k = 0; k < len; k++) { + JSTaggedValue kValue = ElementAccessor::FastGet(elements, k, kind); + if (holes == base::HolesType::SKIP_HOLES) { + kRead = (kValue != JSTaggedValue::Hole()); + } else { + ASSERT(holes == base::HolesType::READ_THROUGH_HOLES); + kRead = true; + } + if (kRead) { + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, items); + items->Set(thread, tmp++, kValue); + } + } + // 2. trim + if (len > tmp) { + items->Trim(thread, tmp); + } + // 3. Sort items using an implementation-defined sequence of calls to SortCompare. + // If any such call returns an abrupt completion, + // stop before performing any further calls to SortCompare and return that Completion Record. + base::TimSort::Sort(thread, items, callbackFnHandle); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, items); + // 4. Return items. + return items; +} + +JSTaggedValue JSStableArray::CopySortedListToReceiver(JSThread *thread, const JSHandle &thisObjVal, + JSHandle sortedList, uint32_t len) +{ + // 6. Let itemCount be the number of elements in sortedList. + uint32_t itemCount = sortedList->GetLength(); + + // grow elements if len > newLength. + JSHandle thisObj(thisObjVal); + uint32_t newLength = std::max(JSHandle::Cast(thisObjVal)->GetArrayLength(), itemCount); + TaggedArray *elements = TaggedArray::Cast(thisObj->GetElements().GetTaggedObject()); + if (newLength > ElementAccessor::GetElementsLength(thisObj)) { + elements = *JSObject::GrowElementsCapacity(thread, thisObj, newLength, true); + } + + JSMutableHandle valueHandle(thread, JSTaggedValue::Undefined()); + bool needTransition = true; + // 7. Let j be 0. + // 8. Repeat, while j < itemCount, + // a. Perform ! Set(obj, ! ToString((j)), sortedList[j], true). + // b. Set j to j + 1. + for (uint32_t j = 0; j < itemCount; j++) { + valueHandle.Update(sortedList->Get(j)); + ElementAccessor::Set(thread, thisObj, j, valueHandle, needTransition); + } + // 9. NOTE: The call to SortIndexedProperties in step 5 uses SKIP-HOLES.The remaining indices are deleted to + // preserve the number of holes that were detected and excluded from the sort. + // 10. Repeat, while j < len, + // a. Perform ? DeletePropertyOrThrow(obj, ! ToString((j))). + // b. Set j to j + 1. + valueHandle.Update(JSTaggedValue::Hole()); + for (uint32_t j = itemCount; j < len; j++) { + ElementAccessor::Set(thread, thisObj, j, valueHandle, needTransition); + } + JSHandle::Cast(thisObj)->SetArrayLength(thread, newLength); return thisObj.GetTaggedValue(); } +JSTaggedValue JSStableArray::Sort(JSThread *thread, const JSHandle &thisObjVal, + const JSHandle &callbackFnHandle) +{ + // 3. Let len be ?LengthOfArrayLike(obj). + uint32_t len = JSHandle::Cast(thisObjVal)->GetArrayLength(); + // ReturnIfAbrupt(len). + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + // If len is 0 or 1, no need to sort + if (len == 0 || len == 1) { + return thisObjVal.GetTaggedValue(); + } + if (callbackFnHandle->IsUndefined()) { + JSArray::SortElementsByObject(thread, JSHandle::Cast(thisObjVal), callbackFnHandle); + return thisObjVal.GetTaggedValue(); + } + JSHandle sortedList = JSStableArray::SortIndexedProperties( + thread, thisObjVal, len, callbackFnHandle, base::HolesType::SKIP_HOLES); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (thisObjVal->IsStableJSArray(thread)) { + CopySortedListToReceiver(thread, thisObjVal, sortedList, len); + } else { + JSArray::CopySortedListToReceiver(thread, thisObjVal, sortedList, len); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + } + return thisObjVal.GetTaggedValue(); +} + JSTaggedValue JSStableArray::Fill(JSThread *thread, const JSHandle &thisObj, const JSHandle &value, int64_t start, int64_t end, int64_t len) diff --git a/ecmascript/js_stable_array.h b/ecmascript/js_stable_array.h index 24ccd24fa480b3befaeff93b37fb0ac176d16e1e..094b442a1b8e85f356abb3f0374ac611a2537ae6 100644 --- a/ecmascript/js_stable_array.h +++ b/ecmascript/js_stable_array.h @@ -16,6 +16,7 @@ #ifndef ECMASCRIPT_JS_STABLE_ARRAY_H #define ECMASCRIPT_JS_STABLE_ARRAY_H +#include "ecmascript/base/array_helper.h" #include "ecmascript/base/typed_array_helper.h" #include "ecmascript/js_array.h" #include "ecmascript/js_dataview.h" @@ -26,7 +27,9 @@ namespace panda::ecmascript { class JSStableArray { public: +#if !ENABLE_NEXT_OPTIMIZATION enum SeparatorFlag : int { MINUS_ONE = -1, MINUS_TWO = -2 }; +#endif static JSTaggedValue Push(JSHandle receiver, EcmaRuntimeCallInfo *argv); static JSTaggedValue Push(JSHandle receiver, EcmaRuntimeCallInfo *argv); static JSTaggedValue Pop(JSHandle receiver, EcmaRuntimeCallInfo *argv); @@ -84,9 +87,13 @@ public: JSHandle callbackFnHandle, JSMutableHandle accumulator, int64_t &k, int64_t &len); static JSTaggedValue Slice(JSThread *thread, JSHandle thisObjHandle, int64_t &k, int64_t &count); - - static JSTaggedValue Sort(JSThread *thread, const JSHandle &thisObj, + static JSHandle SortIndexedProperties(JSThread *thread, const JSHandle &thisObj, + int64_t len, const JSHandle &callbackFnHandle, + base::HolesType holes); + static JSTaggedValue Sort(JSThread *thread, const JSHandle &thisObjVal, const JSHandle &callbackFnHandle); + static JSTaggedValue CopySortedListToReceiver(JSThread *thread, const JSHandle &thisObjVal, + JSHandle sortedList, uint32_t len); static JSTaggedValue Fill(JSThread *thread, const JSHandle &thisObj, const JSHandle &value, int64_t start, int64_t end, int64_t len); @@ -100,7 +107,6 @@ public: JSHandle thisArgHandle, int64_t &k); private: - static void SetSepValue(JSHandle sepStringHandle, int &sep, uint32_t &sepLength); enum class IndexOfType { IndexOf, LastIndexOf @@ -138,15 +144,37 @@ private: static void HandleArray(JSHandle &newArrayHandle, uint32_t &actualDeleteCount, JSThread *thread, uint32_t &start, JSHandle &thisObjHandle, JSHandle &holeHandle); - static JSTaggedValue JoinUseTreeString(const JSThread* thread, JSHandle receiverValue, - JSHandle sepStringHandle, int sep, - CVector>& vec); + +#if !ENABLE_NEXT_OPTIMIZATION + static void SetSepValue(JSHandle sepStringHandle, int &sep, uint32_t &sepLength); + static JSTaggedValue JoinUseTreeString(const JSThread *thread, + const JSHandle receiverValue, + const JSHandle sepStringHandle, const int sep, + CVector> &vec); inline static bool WorthUseTreeString(int sep, size_t allocateLength, uint32_t len); +#endif // Allocate object larger than 256 need liner search in the free object list, // so try to use tree string when the join result is larger than 256. static constexpr size_t TREE_STRING_THRESHOLD = 256; static constexpr size_t NUM_2 = 2; + +#if ENABLE_NEXT_OPTIMIZATION + // When Array length is no more than 64, use array (stack memory) instead of vector to store the elements. + static constexpr size_t USE_STACK_MEMORY_THRESHOLD = 64; + inline static bool WorthUseTreeString(uint32_t sepLength, size_t allocateLength, uint32_t len); + template + static void ProcessElements(JSThread *thread, JSHandle receiverValue, uint32_t len, + Container &arrElements, bool &isOneByte, uint64_t &allocateLength); + template + static JSTaggedValue DoStableArrayJoin(JSThread *thread, JSHandle receiverValue, uint32_t len, + Container &arrElements, bool &isOneByte, uint32_t sep, + uint32_t sepLength, JSHandle sepStringHandle); + template + static JSTaggedValue JoinUseTreeString(const JSThread *thread, JSHandle receiverValue, + JSHandle sepStringHandle, uint32_t sepLength, + Container &arrElements, int elemNum); +#endif }; } // namespace panda::ecmascript #endif // ECMASCRIPT_JS_STABLE_ARRAY_H diff --git a/ecmascript/js_tagged_value-inl.h b/ecmascript/js_tagged_value-inl.h index 915e2a3bba93f9721033f8502be794ffb02a39ad..2e3d709fa9da62d043aeba43c8494f176fe7dacd 100644 --- a/ecmascript/js_tagged_value-inl.h +++ b/ecmascript/js_tagged_value-inl.h @@ -978,9 +978,9 @@ inline bool JSTaggedValue::IsTransWithProtoHandler() const return IsHeapObject() && GetTaggedObject()->GetClass()->IsTransWithProtoHandler(); } -inline bool JSTaggedValue::IsStoreTSHandler() const +inline bool JSTaggedValue::IsStoreAOTHandler() const { - return IsHeapObject() && GetTaggedObject()->GetClass()->IsStoreTSHandler(); + return IsHeapObject() && GetTaggedObject()->GetClass()->IsStoreAOTHandler(); } inline bool JSTaggedValue::IsPropertyBox() const diff --git a/ecmascript/js_tagged_value.cpp b/ecmascript/js_tagged_value.cpp index 4e25e2744adbc955c5fce928cef6e86056f841ed..1b2702fb8e4141ab502e0ddd4ef6a05268530688 100644 --- a/ecmascript/js_tagged_value.cpp +++ b/ecmascript/js_tagged_value.cpp @@ -81,31 +81,31 @@ bool JSTaggedValue::ToBoolean() const JSTaggedNumber JSTaggedValue::ToNumber(JSThread *thread, JSTaggedValue tagged) { - DISALLOW_GARBAGE_COLLECTION; - if (tagged.IsInt() || tagged.IsDouble()) { - return JSTaggedNumber(tagged); - } - - switch (tagged.GetRawData()) { - case JSTaggedValue::VALUE_UNDEFINED: - case JSTaggedValue::VALUE_HOLE: { - return JSTaggedNumber(base::NAN_VALUE); - } - case JSTaggedValue::VALUE_TRUE: { - return JSTaggedNumber(1); - } - case JSTaggedValue::VALUE_FALSE: - case JSTaggedValue::VALUE_NULL: { - return JSTaggedNumber(0); + { + DISALLOW_GARBAGE_COLLECTION; + if (tagged.IsInt() || tagged.IsDouble()) { + return JSTaggedNumber(tagged); + } + switch (tagged.GetRawData()) { + case JSTaggedValue::VALUE_UNDEFINED: + case JSTaggedValue::VALUE_HOLE: { + return JSTaggedNumber(base::NAN_VALUE); + } + case JSTaggedValue::VALUE_TRUE: { + return JSTaggedNumber(1); + } + case JSTaggedValue::VALUE_FALSE: + case JSTaggedValue::VALUE_NULL: { + return JSTaggedNumber(0); + } + default: { + break; + } } - default: { - break; + if (tagged.IsString()) { + return StringToNumber(tagged); } } - - if (tagged.IsString()) { - return StringToNumber(tagged); - } if (tagged.IsECMAObject()) { JSHandletaggedHandle(thread, tagged); JSTaggedValue primValue = ToPrimitive(thread, taggedHandle, PREFER_NUMBER); @@ -353,13 +353,14 @@ bool JSTaggedValue::IsJSCOWArray() const bool JSTaggedValue::IsStableJSArray(JSThread *thread) const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsStableJSArray() && - !thread->IsStableArrayElementsGuardiansInvalid(); + !thread->IsArrayPrototypeChangedGuardiansInvalid() && + !GetTaggedObject()->GetClass()->IsJSArrayPrototypeModifiedFromBitField(); } bool JSTaggedValue::IsStableJSArguments(JSThread *thread) const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsStableJSArguments() && - !thread->IsStableArrayElementsGuardiansInvalid(); + !thread->IsArrayPrototypeChangedGuardiansInvalid(); } bool JSTaggedValue::IsTaggedArray() const @@ -385,7 +386,7 @@ bool JSTaggedValue::IsGeneratorContext() const bool JSTaggedValue::HasStableElements(JSThread *thread) const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsStableElements() && - !thread->IsStableArrayElementsGuardiansInvalid(); + !thread->IsArrayPrototypeChangedGuardiansInvalid(); } bool JSTaggedValue::WithinInt32() const @@ -806,6 +807,7 @@ JSTaggedValue JSTaggedValue::OrdinaryToPrimitive(JSThread *thread, const JSHandl } } } + DumpExceptionObject(thread, tagged); THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a illegal value to a Primitive", JSTaggedValue::Undefined()); } @@ -862,6 +864,7 @@ JSHandle JSTaggedValue::ToString(JSThread *thread, const JSHandle(emptyStr)); return ToString(thread, primValue); } + DumpExceptionObject(thread, tagged); // Already Include Symbol THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a illegal value to a String", JSHandle(emptyStr)); } @@ -1259,6 +1262,7 @@ bool JSTaggedValue::SetPrototype(JSThread *thread, const JSHandle JSTaggedValue JSTaggedValue::GetPrototype(JSThread *thread, const JSHandle &obj) { if (!obj->IsECMAObject()) { + DumpExceptionObject(thread, obj); THROW_TYPE_ERROR_AND_RETURN(thread, "Can not get Prototype on non ECMA Object", JSTaggedValue::Exception()); } if (obj->IsJSProxy()) { @@ -1799,4 +1803,14 @@ bool JSTaggedValue::SetJSAPIProperty(JSThread *thread, const JSHandle &obj) +{ + if (thread->GetEcmaVM()->GetJSOptions().EnableExceptionBacktrace()) { + std::ostringstream oss; + obj->Dump(oss, true); + std::regex reg("0x[0-9a-fA-F]+"); + std::string sensitiveStr = std::regex_replace(oss.str(), reg, ""); + LOG_ECMA(ERROR) << "DumpExceptionObject: " << sensitiveStr; + } +} } // namespace panda::ecmascript diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index de1b282a75ea34beb81b97db9987f1e255c26618..3b8b248003340259e00b1b5ae39e90845f3917a6 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -662,7 +662,7 @@ public: bool IsPrototypeHandler() const; bool IsTransitionHandler() const; bool IsTransWithProtoHandler() const; - bool IsStoreTSHandler() const; + bool IsStoreAOTHandler() const; bool IsPropertyBox() const; bool IsProtoChangeMarker() const; bool IsProtoChangeDetails() const; @@ -714,7 +714,7 @@ public: void DumpTaggedValue(std::ostream &os) const DUMP_API_ATTR; void DumpTaggedValueType(std::ostream &os) const DUMP_API_ATTR; - void Dump(std::ostream &os) const DUMP_API_ATTR; + void Dump(std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR; void D() const DUMP_API_ATTR; void DumpForSnapshot(std::vector &vec, bool isVmMode = true) const; static void DV(JSTaggedType val) DUMP_API_ATTR; @@ -766,6 +766,7 @@ private: ASSERT_PRINT(v.IsInt(), "can not convert JSTaggedValue to Int :" << std::hex << v.GetRawData()); return static_cast(v.GetRawData() & (~TAG_INT)); } + static void DumpExceptionObject(JSThread *thread, const JSHandle &obj); friend class PropertyAttributes; friend class ICRuntimeStub; diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index c7b1f7e5be8b080c45019259af26fb9ec6828965..684c011d2458312c3fb060bb6954675737106b15 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -17,10 +17,10 @@ #include "ecmascript/runtime.h" #include "ecmascript/debugger/js_debugger_manager.h" +#include "ecmascript/js_date.h" #include "ecmascript/js_object-inl.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/runtime_call_id.h" -#include "ecmascript/pgo_profiler/pgo_profiler_manager.h" #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS) #include @@ -97,7 +97,6 @@ JSThread *JSThread::Create(EcmaVM *vm) jsThread->glueData_.stackLimit_ = GetAsmStackLimit(); jsThread->glueData_.stackStart_ = GetCurrentStackPosition(); jsThread->glueData_.isEnableElementsKind_ = vm->IsEnableElementsKind(); - jsThread->glueData_.isEnableForceIC_ = ecmascript::pgo::PGOProfilerManager::GetInstance()->IsEnableForceIC(); jsThread->SetThreadId(); RegisterThread(jsThread); @@ -130,6 +129,7 @@ JSThread::JSThread(EcmaVM *vm) : id_(os::thread::GetCurrentThreadId()), vm_(vm) } vmThreadControl_ = new VmThreadControl(this); SetBCStubStatus(BCStubStatus::NORMAL_BC_STUB); + dateUtils_ = new DateUtils(); } JSThread::JSThread(EcmaVM *vm, ThreadType threadType) : id_(os::thread::GetCurrentThreadId()), @@ -181,6 +181,10 @@ JSThread::~JSThread() if (!IsDaemonThread()) { UnregisterThread(this); } + if (dateUtils_ != nullptr) { + delete dateUtils_; + dateUtils_ = nullptr; + } } ThreadId JSThread::GetCurrentThreadId() @@ -206,16 +210,6 @@ void JSThread::ClearException() glueData_.exception_ = JSTaggedValue::Hole(); } -void JSThread::SetEnableForceIC(bool isEnableForceIC) -{ - glueData_.isEnableForceIC_ = isEnableForceIC; -} - -bool JSThread::IsEnableForceIC() const -{ - return glueData_.isEnableForceIC_; -} - JSTaggedValue JSThread::GetCurrentLexenv() const { FrameHandler frameHandler(this); @@ -558,9 +552,9 @@ void JSThread::ShrinkHandleStorage(int prevIndex) GetCurrentEcmaContext()->ShrinkHandleStorage(prevIndex); } -void JSThread::NotifyStableArrayElementsGuardians(JSHandle receiver, StableArrayChangeKind changeKind) +void JSThread::NotifyArrayPrototypeChangedGuardians(JSHandle receiver) { - if (!glueData_.stableArrayElementsGuardians_) { + if (!glueData_.arrayPrototypeChangedGuardians_) { return; } if (!receiver->GetJSHClass()->IsPrototype() && !receiver->IsJSArray()) { @@ -569,17 +563,14 @@ void JSThread::NotifyStableArrayElementsGuardians(JSHandle receiver, S auto env = GetEcmaVM()->GetGlobalEnv(); if (receiver.GetTaggedValue() == env->GetObjectFunctionPrototype().GetTaggedValue() || receiver.GetTaggedValue() == env->GetArrayPrototype().GetTaggedValue()) { - glueData_.stableArrayElementsGuardians_ = false; + glueData_.arrayPrototypeChangedGuardians_ = false; return; } - if (changeKind == StableArrayChangeKind::PROTO && receiver->IsJSArray()) { - glueData_.stableArrayElementsGuardians_ = false; - } } void JSThread::ResetGuardians() { - glueData_.stableArrayElementsGuardians_ = true; + glueData_.arrayPrototypeChangedGuardians_ = true; } void JSThread::SetInitialBuiltinHClass( @@ -804,7 +795,7 @@ bool JSThread::CheckSafepoint() heap->HandleExitHighSensitiveEvent(); // Do not trigger local gc during the shared gc processRset process. - if (heap->IsProcessingRset()) { + if (IsProcessingLocalToSharedRset()) { return false; } // After concurrent mark finish, should trigger gc here to avoid create much floating garbage diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index fc37f7e2b5497de4a7b57b004813f72ba1669aaf..8b66a10e7c566ca552e0834d968703c0907c392d 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -40,6 +40,7 @@ #endif namespace panda::ecmascript { +class DateUtils; class EcmaContext; class EcmaVM; class EcmaHandleScope; @@ -54,7 +55,6 @@ class VmThreadControl; class GlobalEnvConstants; enum class ElementsKind : uint8_t; -// NOTE: remove class MachineCode; using JitCodeVector = std::vector>; using JitCodeMapVisitor = std::function&)>; @@ -83,8 +83,6 @@ enum class BCStubStatus: uint8_t { JIT_PROFILE_BC_STUB, }; -enum class StableArrayChangeKind { PROTO, NOT_PROTO }; - enum ThreadType : uint8_t { JS_THREAD, JIT_THREAD, @@ -294,10 +292,6 @@ public: void ClearException(); - void SetEnableForceIC(bool isEnableForceIC); - - bool IsEnableForceIC() const; - void SetGlobalObject(JSTaggedValue globalObject) { glueData_.globalObject_ = globalObject; @@ -338,11 +332,11 @@ public: return ctorHclassEntries_; } - void NotifyStableArrayElementsGuardians(JSHandle receiver, StableArrayChangeKind changeKind); + void NotifyArrayPrototypeChangedGuardians(JSHandle receiver); - bool IsStableArrayElementsGuardiansInvalid() const + bool IsArrayPrototypeChangedGuardiansInvalid() const { - return !glueData_.stableArrayElementsGuardians_; + return !glueData_.arrayPrototypeChangedGuardians_; } void ResetGuardians(); @@ -905,7 +899,7 @@ public: { glueData_.taskInfo_ = taskInfo; } - + uintptr_t GetTaskInfo() const { return glueData_.taskInfo_; @@ -959,13 +953,12 @@ public: base::AlignedPointer, base::AlignedPointer, base::AlignedUint32, - base::AlignedBool, base::AlignedBool> { enum class Index : size_t { BcStubEntriesIndex = 0, ExceptionIndex, GlobalObjIndex, - StableArrayElementsGuardiansIndex, + ArrayElementsGuardiansIndex, CurrentFrameIndex, LeaveFrameIndex, LastFpIndex, @@ -1003,7 +996,6 @@ public: StateAndFlagsIndex, TaskInfoIndex, IsEnableElementsKindIndex, - IsEnableForceIC, NumOfMembers }; static_assert(static_cast(Index::NumOfMembers) == NumOfTypes); @@ -1018,9 +1010,9 @@ public: return GetOffset(Index::GlobalObjIndex)>(isArch32); } - static size_t GetStableArrayElementsGuardiansOffset(bool isArch32) + static size_t GetArrayElementsGuardiansOffset(bool isArch32) { - return GetOffset(Index::StableArrayElementsGuardiansIndex)>(isArch32); + return GetOffset(Index::ArrayElementsGuardiansIndex)>(isArch32); } static size_t GetGlobalConstOffset(bool isArch32) @@ -1234,15 +1226,10 @@ public: return GetOffset(Index::IsEnableElementsKindIndex)>(isArch32); } - static size_t GetIsEnableForceICOffSet(bool isArch32) - { - return GetOffset(Index::IsEnableForceIC)>(isArch32); - } - alignas(EAS) BCStubEntries bcStubEntries_ {}; alignas(EAS) JSTaggedValue exception_ {JSTaggedValue::Hole()}; alignas(EAS) JSTaggedValue globalObject_ {JSTaggedValue::Hole()}; - alignas(EAS) bool stableArrayElementsGuardians_ {true}; + alignas(EAS) bool arrayPrototypeChangedGuardians_ {true}; alignas(EAS) JSTaggedType *currentFrame_ {nullptr}; alignas(EAS) JSTaggedType *leaveFrame_ {nullptr}; alignas(EAS) JSTaggedType *lastFp_ {nullptr}; @@ -1280,7 +1267,6 @@ public: alignas(EAS) ThreadStateAndFlags stateAndFlags_ {}; alignas(EAS) uintptr_t taskInfo_ {0}; alignas(EAS) bool isEnableElementsKind_ {false}; - alignas(EAS) bool isEnableForceIC_ {true}; }; STATIC_ASSERT_EQ_ARCH(sizeof(GlueData), GlueData::SizeArch32, GlueData::SizeArch64); @@ -1318,11 +1304,31 @@ public: void InitializeBuiltinObject(const std::string& key); void InitializeBuiltinObject(); + bool FullMarkRequest() const + { + return fullMarkRequest_; + } + void SetFullMarkRequest() { fullMarkRequest_ = true; } + void ResetFullMarkRequest() + { + fullMarkRequest_ = false; + } + + void SetProcessingLocalToSharedRset(bool processing) + { + processingLocalToSharedRset_ = processing; + } + + bool IsProcessingLocalToSharedRset() const + { + return processingLocalToSharedRset_; + } + inline bool IsThreadSafe() const { return IsMainThread() || HasSuspendRequest(); @@ -1474,7 +1480,10 @@ public: RegisterRTInterface(kungfu::RuntimeStubCSigns::ID_ASMFastWriteBarrier, asmCheckStub); } - + DateUtils *GetDateUtils() const + { + return dateUtils_; + } #ifndef NDEBUG inline void LaunchSuspendAll() @@ -1601,6 +1610,8 @@ private: // Shared heap bool isMainThread_ {false}; bool fullMarkRequest_ {false}; + // Shared heap collect local heap Rset + bool processingLocalToSharedRset_ {false}; // { ElementsKind, (hclass, hclassWithProto) } CMap> arrayHClassIndexMap_; @@ -1620,6 +1631,7 @@ private: RecursiveMutex jitMutex_; bool machineCodeLowMemory_ {false}; RecursiveMutex profileTypeAccessorLockMutex_; + DateUtils *dateUtils_ {nullptr}; #ifndef NDEBUG MutatorLock::MutatorLockState mutatorLockState_ = MutatorLock::MutatorLockState::UNLOCKED; diff --git a/ecmascript/js_type_metadata/accessor_data.json b/ecmascript/js_type_metadata/accessor_data.json new file mode 100644 index 0000000000000000000000000000000000000000..a9016195deee33f7a028d7fc55e537f96861e1a3 --- /dev/null +++ b/ecmascript/js_type_metadata/accessor_data.json @@ -0,0 +1,19 @@ +{ + "name": "ACCESSOR_DATA", + "offsets": [ + { + "name": "Getter", + "offset": 0, + "size": 8 + }, + { + "name": "Setter", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/aot_literal_info.json b/ecmascript/js_type_metadata/aot_literal_info.json new file mode 100644 index 0000000000000000000000000000000000000000..20b0f43f318100d0c59d1d552a0164ac456c726e --- /dev/null +++ b/ecmascript/js_type_metadata/aot_literal_info.json @@ -0,0 +1 @@ +{"name": "AOT_LITERAL_INFO", "offsets": [], "end_offset": 8, "parents": ["TAGGED_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/async_generator_request.json b/ecmascript/js_type_metadata/async_generator_request.json new file mode 100644 index 0000000000000000000000000000000000000000..6eab7aaafe91dfc61e75bf0f695e2abf93b86948 --- /dev/null +++ b/ecmascript/js_type_metadata/async_generator_request.json @@ -0,0 +1,19 @@ +{ + "name": "ASYNC_GENERATOR_REQUEST", + "offsets": [ + { + "name": "Completion", + "offset": 0, + "size": 8 + }, + { + "name": "Capability", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/async_iterator_record.json b/ecmascript/js_type_metadata/async_iterator_record.json new file mode 100644 index 0000000000000000000000000000000000000000..314f67bbe7a2f765fc59ecba5dc48b4a28cf3d52 --- /dev/null +++ b/ecmascript/js_type_metadata/async_iterator_record.json @@ -0,0 +1,19 @@ +{ + "name": "ASYNC_ITERATOR_RECORD", + "offsets": [ + { + "name": "Iterator", + "offset": 0, + "size": 8 + }, + { + "name": "NextMethod", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/bigint.json b/ecmascript/js_type_metadata/bigint.json new file mode 100644 index 0000000000000000000000000000000000000000..1aa9b5250225f7dcb4e37813ebf3dae325b8617e --- /dev/null +++ b/ecmascript/js_type_metadata/bigint.json @@ -0,0 +1 @@ +{"name": "BIGINT", "offsets": [], "end_offset": 8, "parents": ["TAGGED_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/byte_array.json b/ecmascript/js_type_metadata/byte_array.json new file mode 100644 index 0000000000000000000000000000000000000000..384f11df177b3a277b2936ec64ddbbfdff73db80 --- /dev/null +++ b/ecmascript/js_type_metadata/byte_array.json @@ -0,0 +1 @@ +{"name": "BYTE_ARRAY", "offsets": [], "end_offset": 8, "parents": ["TAGGED_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/cell_record.json b/ecmascript/js_type_metadata/cell_record.json new file mode 100644 index 0000000000000000000000000000000000000000..5da40c0d354a6608a60369c00d7c6b46a3e31810 --- /dev/null +++ b/ecmascript/js_type_metadata/cell_record.json @@ -0,0 +1,19 @@ +{ + "name": "CELL_RECORD", + "offsets": [ + { + "name": "WeakRefTarget", + "offset": 0, + "size": 8 + }, + { + "name": "HeldValue", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/class_info_extractor.json b/ecmascript/js_type_metadata/class_info_extractor.json new file mode 100644 index 0000000000000000000000000000000000000000..be726fb9afabb3faf34575342d8c204d104a4f2b --- /dev/null +++ b/ecmascript/js_type_metadata/class_info_extractor.json @@ -0,0 +1,44 @@ +{ + "name": "CLASS_INFO_EXTRACTOR", + "offsets": [ + { + "name": "NonStaticKeys", + "offset": 0, + "size": 8 + }, + { + "name": "NonStaticProperties", + "offset": 8, + "size": 8 + }, + { + "name": "NonStaticElements", + "offset": 16, + "size": 8 + }, + { + "name": "StaticKeys", + "offset": 24, + "size": 8 + }, + { + "name": "StaticProperties", + "offset": 32, + "size": 8 + }, + { + "name": "StaticElements", + "offset": 40, + "size": 8 + }, + { + "name": "ConstructorMethod", + "offset": 48, + "size": 8 + } + ], + "end_offset": 64, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/class_literal.json b/ecmascript/js_type_metadata/class_literal.json new file mode 100644 index 0000000000000000000000000000000000000000..7de485fc09a71c43296e0c88f8abe6458e389d58 --- /dev/null +++ b/ecmascript/js_type_metadata/class_literal.json @@ -0,0 +1,14 @@ +{ + "name": "CLASS_LITERAL", + "offsets": [ + { + "name": "Array", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/completion_record.json b/ecmascript/js_type_metadata/completion_record.json new file mode 100644 index 0000000000000000000000000000000000000000..ffb4e486db4f29e0b1ae33c2647808c1b0e59e0d --- /dev/null +++ b/ecmascript/js_type_metadata/completion_record.json @@ -0,0 +1,14 @@ +{ + "name": "COMPLETION_RECORD", + "offsets": [ + { + "name": "Value", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/constant_pool.json b/ecmascript/js_type_metadata/constant_pool.json new file mode 100644 index 0000000000000000000000000000000000000000..41ecdfe22c88c279efbc23e0d4d2a8db6bf88234 --- /dev/null +++ b/ecmascript/js_type_metadata/constant_pool.json @@ -0,0 +1 @@ +{"name": "CONSTANT_POOL", "offsets": [], "end_offset": 0, "parents": ["TAGGED_ARRAY"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/constant_string.json b/ecmascript/js_type_metadata/constant_string.json new file mode 100644 index 0000000000000000000000000000000000000000..dd3bcd91404caad033c615fc276dbdf3173ff9ef --- /dev/null +++ b/ecmascript/js_type_metadata/constant_string.json @@ -0,0 +1,14 @@ +{ + "name": "CONSTANT_STRING", + "offsets": [ + { + "name": "RelocatedData", + "offset": 0, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "ECMA_STRING" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/cow_mutant_tagged_array.json b/ecmascript/js_type_metadata/cow_mutant_tagged_array.json new file mode 100644 index 0000000000000000000000000000000000000000..744c232cb37086867781e7990a273dd2269520e0 --- /dev/null +++ b/ecmascript/js_type_metadata/cow_mutant_tagged_array.json @@ -0,0 +1 @@ +{"name": "COW_MUTANT_TAGGED_ARRAY", "offsets": [], "end_offset": 0, "parents": ["MUTANT_TAGGED_ARRAY"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/cow_tagged_array.json b/ecmascript/js_type_metadata/cow_tagged_array.json new file mode 100644 index 0000000000000000000000000000000000000000..5e56f353d54c09d7cf143728348243b6a4861bf6 --- /dev/null +++ b/ecmascript/js_type_metadata/cow_tagged_array.json @@ -0,0 +1 @@ +{"name": "COW_TAGGED_ARRAY", "offsets": [], "end_offset": 0, "parents": ["TAGGED_ARRAY"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/dictionary_layout.json b/ecmascript/js_type_metadata/dictionary_layout.json new file mode 100644 index 0000000000000000000000000000000000000000..0057605084670f6529f3b56e27912697dcd0f01e --- /dev/null +++ b/ecmascript/js_type_metadata/dictionary_layout.json @@ -0,0 +1,8 @@ +{ + "name": "Dictionary", + "key_index": 0, + "value_index": 1, + "detail_index": 2, + "entry_size": 3, + "header_size": 4 +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/ecma_object.json b/ecmascript/js_type_metadata/ecma_object.json new file mode 100644 index 0000000000000000000000000000000000000000..5ec437c61133c1f58c1f82e1b6f47d33510ffc1d --- /dev/null +++ b/ecmascript/js_type_metadata/ecma_object.json @@ -0,0 +1,14 @@ +{ + "name": "ECMA_OBJECT", + "offsets": [ + { + "name": "HashField", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/ecma_string.json b/ecmascript/js_type_metadata/ecma_string.json new file mode 100644 index 0000000000000000000000000000000000000000..8f282d89b53a8d4a2aa6e80ed729541059e12b7d --- /dev/null +++ b/ecmascript/js_type_metadata/ecma_string.json @@ -0,0 +1 @@ +{"name": "ECMA_STRING", "offsets": [], "end_offset": 8, "parents": ["TAGGED_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/extra_profile_type_info.json b/ecmascript/js_type_metadata/extra_profile_type_info.json new file mode 100644 index 0000000000000000000000000000000000000000..84fa356d0552d93119332658d1570cda7e71602e --- /dev/null +++ b/ecmascript/js_type_metadata/extra_profile_type_info.json @@ -0,0 +1,19 @@ +{ + "name": "EXTRA_PROFILE_TYPE_INFO", + "offsets": [ + { + "name": "ReceiverObject", + "offset": 0, + "size": 8 + }, + { + "name": "HolderObject", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/function_template.json b/ecmascript/js_type_metadata/function_template.json new file mode 100644 index 0000000000000000000000000000000000000000..119f6674dafb3a4a46600289f3b8337f104adc2f --- /dev/null +++ b/ecmascript/js_type_metadata/function_template.json @@ -0,0 +1,24 @@ +{ + "name": "FUNCTION_TEMPLATE", + "offsets": [ + { + "name": "Method", + "offset": 0, + "size": 8 + }, + { + "name": "Module", + "offset": 8, + "size": 8 + }, + { + "name": "RawProfileTypeInfo", + "offset": 16, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/global_env.json b/ecmascript/js_type_metadata/global_env.json new file mode 100644 index 0000000000000000000000000000000000000000..f7ad94ec90c3a020f5ebbce67b1643bb0fdc0f44 --- /dev/null +++ b/ecmascript/js_type_metadata/global_env.json @@ -0,0 +1 @@ +{"name": "GLOBAL_ENV", "offsets": [], "end_offset": 2384, "parents": ["TAGGED_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/hclass.json b/ecmascript/js_type_metadata/hclass.json new file mode 100644 index 0000000000000000000000000000000000000000..65962f7da0687562735276c53ef005db67aed1ed --- /dev/null +++ b/ecmascript/js_type_metadata/hclass.json @@ -0,0 +1 @@ +{"name": "HCLASS", "offsets": [{"name": "Proto", "offset": 0, "size": 8}, {"name": "Layout", "offset": 8, "size": 8}, {"name": "Transitions", "offset": 16, "size": 8}, {"name": "Parent", "offset": 24, "size": 8}, {"name": "ProtoChangeMarker", "offset": 32, "size": 8}, {"name": "ProtoChangeDetails", "offset": 40, "size": 8}, {"name": "EnumCache", "offset": 48, "size": 8}, {"name": "ProfilerType", "offset": 56, "size": 8}, {"name": "BitField", "offset": 64, "size": 4}, {"name": "BitField1", "offset": 68, "size": 4}], "end_offset": 72, "parents": ["TAGGED_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/importentry_record.json b/ecmascript/js_type_metadata/importentry_record.json new file mode 100644 index 0000000000000000000000000000000000000000..15dea4d4f89e5d45aec9038331f0c97eb09f4f4a --- /dev/null +++ b/ecmascript/js_type_metadata/importentry_record.json @@ -0,0 +1,24 @@ +{ + "name": "IMPORTENTRY_RECORD", + "offsets": [ + { + "name": "ModuleRequest", + "offset": 0, + "size": 8 + }, + { + "name": "ImportName", + "offset": 8, + "size": 8 + }, + { + "name": "LocalName", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/indirect_exportentry_record.json b/ecmascript/js_type_metadata/indirect_exportentry_record.json new file mode 100644 index 0000000000000000000000000000000000000000..bc947d2815262a7890b4f7f63d5b3b6f9035dff4 --- /dev/null +++ b/ecmascript/js_type_metadata/indirect_exportentry_record.json @@ -0,0 +1,24 @@ +{ + "name": "INDIRECT_EXPORTENTRY_RECORD", + "offsets": [ + { + "name": "ExportName", + "offset": 0, + "size": 8 + }, + { + "name": "ModuleRequest", + "offset": 8, + "size": 8 + }, + { + "name": "ImportName", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/internal_accessor.json b/ecmascript/js_type_metadata/internal_accessor.json new file mode 100644 index 0000000000000000000000000000000000000000..94c0ea9dae32470d537703616cc04a99e2836490 --- /dev/null +++ b/ecmascript/js_type_metadata/internal_accessor.json @@ -0,0 +1,19 @@ +{ + "name": "INTERNAL_ACCESSOR", + "offsets": [ + { + "name": "Getter", + "offset": 0, + "size": 8 + }, + { + "name": "Setter", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_aggregate_error.json b/ecmascript/js_type_metadata/js_aggregate_error.json new file mode 100644 index 0000000000000000000000000000000000000000..61c99883cbc9c426239f015eb855e37bd1686a12 --- /dev/null +++ b/ecmascript/js_type_metadata/js_aggregate_error.json @@ -0,0 +1,17 @@ +{ + "name": "JS_AGGREGATE_ERROR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_array_list.json b/ecmascript/js_type_metadata/js_api_array_list.json new file mode 100644 index 0000000000000000000000000000000000000000..15fa465650d32f22991ab4c6f93bde3b0e71b470 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_array_list.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_ARRAY_LIST", + "offsets": [ + { + "name": "Length", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_arraylist_iterator.json b/ecmascript/js_type_metadata/js_api_arraylist_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..cbd8be034e653acd31d4c91bc9de6c678b9d7c8e --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_arraylist_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_ARRAYLIST_ITERATOR", + "offsets": [ + { + "name": "IteratedArrayList", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_bitvector.json b/ecmascript/js_type_metadata/js_api_bitvector.json new file mode 100644 index 0000000000000000000000000000000000000000..23feac483533887c7f6ee9e86c1ce8e1c15741ed --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_bitvector.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_BITVECTOR", + "offsets": [ + { + "name": "NativePointer", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_bitvector_iterator.json b/ecmascript/js_type_metadata/js_api_bitvector_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..490c213aed3a6b118e4a70d78b02a8c3430eb14c --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_bitvector_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_BITVECTOR_ITERATOR", + "offsets": [ + { + "name": "IteratedBitVector", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_deque.json b/ecmascript/js_type_metadata/js_api_deque.json new file mode 100644 index 0000000000000000000000000000000000000000..4c0c0e0e0411672028da0f564ed016438ab41a61 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_deque.json @@ -0,0 +1 @@ +{"name": "JS_API_DEQUE", "offsets": [], "end_offset": 8, "parents": ["JS_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_deque_iterator.json b/ecmascript/js_type_metadata/js_api_deque_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..3b3782a562a9ccc9d3c8efee6130fa5f7ee8f5e1 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_deque_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_DEQUE_ITERATOR", + "offsets": [ + { + "name": "IteratedDeque", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_hash_map.json b/ecmascript/js_type_metadata/js_api_hash_map.json new file mode 100644 index 0000000000000000000000000000000000000000..e64524433d10c0010ccef37a5836b935f9f74e9b --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_hash_map.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_HASH_MAP", + "offsets": [ + { + "name": "Table", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_hash_set.json b/ecmascript/js_type_metadata/js_api_hash_set.json new file mode 100644 index 0000000000000000000000000000000000000000..7efdbcfe616d9dd203d9c72356b2fe76bdf5400d --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_hash_set.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_HASH_SET", + "offsets": [ + { + "name": "Table", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_hashmap_iterator.json b/ecmascript/js_type_metadata/js_api_hashmap_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..d1be38b0545cc7049d72c31acad74cdaee5bf117 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_hashmap_iterator.json @@ -0,0 +1,24 @@ +{ + "name": "JS_API_HASHMAP_ITERATOR", + "offsets": [ + { + "name": "IteratedHashMap", + "offset": 0, + "size": 8 + }, + { + "name": "TaggedQueue", + "offset": 8, + "size": 8 + }, + { + "name": "CurrentNodeResult", + "offset": 16, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_hashset_iterator.json b/ecmascript/js_type_metadata/js_api_hashset_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..7950c8f5babc1766a48f38a5cc0304b58adc037f --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_hashset_iterator.json @@ -0,0 +1,24 @@ +{ + "name": "JS_API_HASHSET_ITERATOR", + "offsets": [ + { + "name": "IteratedHashSet", + "offset": 0, + "size": 8 + }, + { + "name": "TaggedQueue", + "offset": 8, + "size": 8 + }, + { + "name": "CurrentNodeResult", + "offset": 16, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_light_weight_map.json b/ecmascript/js_type_metadata/js_api_light_weight_map.json new file mode 100644 index 0000000000000000000000000000000000000000..2931df949f0f642fbd15a012a0a71ccfab24eaa2 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_light_weight_map.json @@ -0,0 +1,24 @@ +{ + "name": "JS_API_LIGHT_WEIGHT_MAP", + "offsets": [ + { + "name": "Hashes", + "offset": 0, + "size": 8 + }, + { + "name": "Keys", + "offset": 8, + "size": 8 + }, + { + "name": "Values", + "offset": 16, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_light_weight_map_iterator.json b/ecmascript/js_type_metadata/js_api_light_weight_map_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..0cb5c018ba153d7aba82b774695ce5062fb45297 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_light_weight_map_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_LIGHT_WEIGHT_MAP_ITERATOR", + "offsets": [ + { + "name": "IteratedLightWeightMap", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_light_weight_set.json b/ecmascript/js_type_metadata/js_api_light_weight_set.json new file mode 100644 index 0000000000000000000000000000000000000000..72cafd9e15e1dbdb1a42bf51e4423038a290a540 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_light_weight_set.json @@ -0,0 +1,19 @@ +{ + "name": "JS_API_LIGHT_WEIGHT_SET", + "offsets": [ + { + "name": "Hashes", + "offset": 0, + "size": 8 + }, + { + "name": "Values", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_light_weight_set_iterator.json b/ecmascript/js_type_metadata/js_api_light_weight_set_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..0d47cbc47fe97156383d64cc70f95697fa78edb1 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_light_weight_set_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_LIGHT_WEIGHT_SET_ITERATOR", + "offsets": [ + { + "name": "IteratedLightWeightSet", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_linked_list.json b/ecmascript/js_type_metadata/js_api_linked_list.json new file mode 100644 index 0000000000000000000000000000000000000000..f976b88b9c35cdc71b652ee77e69dbf32a221292 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_linked_list.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_LINKED_LIST", + "offsets": [ + { + "name": "DoubleList", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_linked_list_iterator.json b/ecmascript/js_type_metadata/js_api_linked_list_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..6ee305c4d2935bf242df23aff431c3c81fc7a545 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_linked_list_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_LINKED_LIST_ITERATOR", + "offsets": [ + { + "name": "IteratedLinkedList", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_list.json b/ecmascript/js_type_metadata/js_api_list.json new file mode 100644 index 0000000000000000000000000000000000000000..7384eecd0b1053d641340fdced9fd2e98d6b415d --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_list.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_LIST", + "offsets": [ + { + "name": "SingleList", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_list_iterator.json b/ecmascript/js_type_metadata/js_api_list_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..c9fde387b67bd973a93c795c5a0f08f7bca55163 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_list_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_LIST_ITERATOR", + "offsets": [ + { + "name": "IteratedList", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_plain_array.json b/ecmascript/js_type_metadata/js_api_plain_array.json new file mode 100644 index 0000000000000000000000000000000000000000..62e5ddd1a1c7273b9a770f703d3fb234c03dc1d3 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_plain_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_API_PLAIN_ARRAY", + "offsets": [ + { + "name": "Keys", + "offset": 0, + "size": 8 + }, + { + "name": "Values", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_plain_array_iterator.json b/ecmascript/js_type_metadata/js_api_plain_array_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..00169ece5d79dd74591326c7690b8c13cada2be0 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_plain_array_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_PLAIN_ARRAY_ITERATOR", + "offsets": [ + { + "name": "IteratedPlainArray", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_queue.json b/ecmascript/js_type_metadata/js_api_queue.json new file mode 100644 index 0000000000000000000000000000000000000000..d0ecc6e6cb0a5b5f6216b19be638c32bc68a8ab3 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_queue.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_QUEUE", + "offsets": [ + { + "name": "Length", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_queue_iterator.json b/ecmascript/js_type_metadata/js_api_queue_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..90926cb7ba9d4730b1b6e634ce8f053350227ab5 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_queue_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_QUEUE_ITERATOR", + "offsets": [ + { + "name": "IteratedQueue", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_stack.json b/ecmascript/js_type_metadata/js_api_stack.json new file mode 100644 index 0000000000000000000000000000000000000000..397181269562ecd40d39e731f637a7d8817d7d20 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_stack.json @@ -0,0 +1 @@ +{"name": "JS_API_STACK", "offsets": [], "end_offset": 8, "parents": ["JS_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_stack_iterator.json b/ecmascript/js_type_metadata/js_api_stack_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..5ee9ecc3b762dfd1418d9953bf11de21a1fbf409 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_stack_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_STACK_ITERATOR", + "offsets": [ + { + "name": "IteratedStack", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_tree_map.json b/ecmascript/js_type_metadata/js_api_tree_map.json new file mode 100644 index 0000000000000000000000000000000000000000..73e2b7c8db06b5803d626938bd90851c965ee4a6 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_tree_map.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_TREE_MAP", + "offsets": [ + { + "name": "TreeMap", + "offset": 0, + "size":8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_tree_set.json b/ecmascript/js_type_metadata/js_api_tree_set.json new file mode 100644 index 0000000000000000000000000000000000000000..2d7d768ce8fb09e2b927ef18bda8ee6f12a51996 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_tree_set.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_TREE_SET", + "offsets": [ + { + "name": "TreeSet", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_treemap_iterator.json b/ecmascript/js_type_metadata/js_api_treemap_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..7fa52ef20040f0a62eeebeec8e85b24fdb4019b6 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_treemap_iterator.json @@ -0,0 +1,19 @@ +{ + "name": "JS_API_TREEMAP_ITERATOR", + "offsets": [ + { + "name": "IteratedMap", + "offset": 0, + "size": 8 + }, + { + "name": "Entries", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_treeset_iterator.json b/ecmascript/js_type_metadata/js_api_treeset_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..d941ccaf6f966b1f36ef1cfc32a85e9344db5c68 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_treeset_iterator.json @@ -0,0 +1,19 @@ +{ + "name": "JS_API_TREESET_ITERATOR", + "offsets": [ + { + "name": "IteratedSet", + "offset": 0, + "size": 8 + }, + { + "name": "Entries", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_vector.json b/ecmascript/js_type_metadata/js_api_vector.json new file mode 100644 index 0000000000000000000000000000000000000000..2ffe8cc5d5d6c2a93e89c91cdd3ddd0a848ab258 --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_vector.json @@ -0,0 +1 @@ +{"name": "JS_API_VECTOR", "offsets": [], "end_offset": 8, "parents": ["JS_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_api_vector_iterator.json b/ecmascript/js_type_metadata/js_api_vector_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..4063bfdcef3f4bed19405e04dbbad330cc987f8c --- /dev/null +++ b/ecmascript/js_type_metadata/js_api_vector_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_API_VECTOR_ITERATOR", + "offsets": [ + { + "name": "IteratedVector", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_arguments.json b/ecmascript/js_type_metadata/js_arguments.json new file mode 100644 index 0000000000000000000000000000000000000000..3fa62e7ec8e52e3706616a8ee915f7a08dc22fb6 --- /dev/null +++ b/ecmascript/js_type_metadata/js_arguments.json @@ -0,0 +1 @@ +{"name": "JS_ARGUMENTS", "offsets": [], "end_offset": 0, "parents": ["JS_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_array.json b/ecmascript/js_type_metadata/js_array.json new file mode 100644 index 0000000000000000000000000000000000000000..5da87b7085e6f20f7c2d7caadd81cc4675dc365b --- /dev/null +++ b/ecmascript/js_type_metadata/js_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_ARRAY", + "offsets": [ + { + "name": "Length", + "offset": 0, + "size": 4 + }, + { + "name": "TrackInfo", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_array_buffer.json b/ecmascript/js_type_metadata/js_array_buffer.json new file mode 100644 index 0000000000000000000000000000000000000000..8af4a4a75b9db5182d9710f426f34b6ff92bbc6d --- /dev/null +++ b/ecmascript/js_type_metadata/js_array_buffer.json @@ -0,0 +1,14 @@ +{ + "name": "JS_ARRAY_BUFFER", + "offsets": [ + { + "name": "ArrayBufferData", + "offset": 0, + "size":8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_array_iterator.json b/ecmascript/js_type_metadata/js_array_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..cbf374c233c7552ff78049812f99cc14fc820df9 --- /dev/null +++ b/ecmascript/js_type_metadata/js_array_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_ARRAY_ITERATOR", + "offsets": [ + { + "name": "IteratedArray", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_async_await_status_function.json b/ecmascript/js_type_metadata/js_async_await_status_function.json new file mode 100644 index 0000000000000000000000000000000000000000..b4a7d78eab6c62ec79eaa6bb0b3c93e4dfdcca9d --- /dev/null +++ b/ecmascript/js_type_metadata/js_async_await_status_function.json @@ -0,0 +1,14 @@ +{ + "name": "JS_ASYNC_AWAIT_STATUS_FUNCTION", + "offsets": [ + { + "name": "AsyncContext", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_async_from_sync_iter_unwarp_function.json b/ecmascript/js_type_metadata/js_async_from_sync_iter_unwarp_function.json new file mode 100644 index 0000000000000000000000000000000000000000..5cf08c42252f268bc8519edb33f495fd532434a1 --- /dev/null +++ b/ecmascript/js_type_metadata/js_async_from_sync_iter_unwarp_function.json @@ -0,0 +1,14 @@ +{ + "name": "JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION", + "offsets": [ + { + "name": "Done", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_async_from_sync_iterator.json b/ecmascript/js_type_metadata/js_async_from_sync_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..011c6c9e728acf724b6b4853c310ec54b1fb1a55 --- /dev/null +++ b/ecmascript/js_type_metadata/js_async_from_sync_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_ASYNC_FROM_SYNC_ITERATOR", + "offsets": [ + { + "name": "SyncIteratorRecord", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_async_func_object.json b/ecmascript/js_type_metadata/js_async_func_object.json new file mode 100644 index 0000000000000000000000000000000000000000..c23a1742731fefcfbf62db73a3e200c2596692c7 --- /dev/null +++ b/ecmascript/js_type_metadata/js_async_func_object.json @@ -0,0 +1,14 @@ +{ + "name": "JS_ASYNC_FUNC_OBJECT", + "offsets": [ + { + "name": "Promise", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_GENERATOR_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_async_function.json b/ecmascript/js_type_metadata/js_async_function.json new file mode 100644 index 0000000000000000000000000000000000000000..f6c2473e61d70dcb740cb23a589fda65f9be0bc7 --- /dev/null +++ b/ecmascript/js_type_metadata/js_async_function.json @@ -0,0 +1,8 @@ +{ + "name": "JS_ASYNC_FUNCTION", + "offsets": [], + "end_offset": 0, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_async_generator_function.json b/ecmascript/js_type_metadata/js_async_generator_function.json new file mode 100644 index 0000000000000000000000000000000000000000..fd1f56cf61773cf142b2f0a2f486db13548fc4a0 --- /dev/null +++ b/ecmascript/js_type_metadata/js_async_generator_function.json @@ -0,0 +1,8 @@ +{ + "name": "JS_ASYNC_GENERATOR_FUNCTION", + "offsets": [], + "end_offset": 0, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_async_generator_object.json b/ecmascript/js_type_metadata/js_async_generator_object.json new file mode 100644 index 0000000000000000000000000000000000000000..e235f97675843deaef3a568e5af9768704c870d7 --- /dev/null +++ b/ecmascript/js_type_metadata/js_async_generator_object.json @@ -0,0 +1,29 @@ +{ + "name": "JS_ASYNC_GENERATOR_OBJECT", + "offsets": [ + { + "name": "GeneratorContext", + "offset": 0, + "size": 8 + }, + { + "name": "AsyncGeneratorQueue", + "offset": 8, + "size": 8 + }, + { + "name": "GeneratorBrand", + "offset": 16, + "size": 8 + }, + { + "name": "ResumeResult", + "offset": 24, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_async_generator_resume_next.json b/ecmascript/js_type_metadata/js_async_generator_resume_next.json new file mode 100644 index 0000000000000000000000000000000000000000..94ae4472c45ee1b1f2ccc661be1262754b5a652c --- /dev/null +++ b/ecmascript/js_type_metadata/js_async_generator_resume_next.json @@ -0,0 +1,14 @@ +{ + "name": "JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN", + "offsets": [ + { + "name": "AsyncGeneratorObject", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_async_module_fulfilled_function.json b/ecmascript/js_type_metadata/js_async_module_fulfilled_function.json new file mode 100644 index 0000000000000000000000000000000000000000..85c2c72d3df579fab503cc9b6c4c6991e7f38bdf --- /dev/null +++ b/ecmascript/js_type_metadata/js_async_module_fulfilled_function.json @@ -0,0 +1,8 @@ +{ + "name": "JS_ASYNC_MODULE_FULFILLED_FUNCTION", + "offsets": [], + "end_offset": 0, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_async_module_rejected_function.json b/ecmascript/js_type_metadata/js_async_module_rejected_function.json new file mode 100644 index 0000000000000000000000000000000000000000..e4a92f0ece825afe9c7db8431920c453ad6deba4 --- /dev/null +++ b/ecmascript/js_type_metadata/js_async_module_rejected_function.json @@ -0,0 +1,8 @@ +{ + "name": "JS_ASYNC_MODULE_REJECTED_FUNCTION", + "offsets": [], + "end_offset": 0, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_asynciterator.json b/ecmascript/js_type_metadata/js_asynciterator.json new file mode 100644 index 0000000000000000000000000000000000000000..5eace6e921303960260d9eeda5e773f253a00e7d --- /dev/null +++ b/ecmascript/js_type_metadata/js_asynciterator.json @@ -0,0 +1,17 @@ +{ + "name": "JS_ASYNCITERATOR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_bigint64_array.json b/ecmascript/js_type_metadata/js_bigint64_array.json new file mode 100644 index 0000000000000000000000000000000000000000..972e38ca70fe24b539436e887b9c3395a3a713bc --- /dev/null +++ b/ecmascript/js_type_metadata/js_bigint64_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_BIGINT64_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_biguint64_array.json b/ecmascript/js_type_metadata/js_biguint64_array.json new file mode 100644 index 0000000000000000000000000000000000000000..c30321debbcf8f2b83a77b64cb1467e995569a91 --- /dev/null +++ b/ecmascript/js_type_metadata/js_biguint64_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_BIGUINT64_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_bound_function.json b/ecmascript/js_type_metadata/js_bound_function.json new file mode 100644 index 0000000000000000000000000000000000000000..86815c7766f24dc0e82789dc8b5561255f9d91ec --- /dev/null +++ b/ecmascript/js_type_metadata/js_bound_function.json @@ -0,0 +1,24 @@ +{ + "name": "JS_BOUND_FUNCTION", + "offsets": [ + { + "name": "BoundTarget", + "offset": 0, + "size": 8 + }, + { + "name": "BoundThis", + "offset": 8, + "size": 8 + }, + { + "name": "BoundArguments", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_cjs_exports.json b/ecmascript/js_type_metadata/js_cjs_exports.json new file mode 100644 index 0000000000000000000000000000000000000000..f588b5d886be855f00320e3a054dad837734a995 --- /dev/null +++ b/ecmascript/js_type_metadata/js_cjs_exports.json @@ -0,0 +1,14 @@ +{ + "name": "JS_CJS_EXPORTS", + "offsets": [ + { + "name": "Exports", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_cjs_module.json b/ecmascript/js_type_metadata/js_cjs_module.json new file mode 100644 index 0000000000000000000000000000000000000000..b932d7090fa808e0783bd577b7772b74bf9f0482 --- /dev/null +++ b/ecmascript/js_type_metadata/js_cjs_module.json @@ -0,0 +1,29 @@ +{ + "name": "JS_CJS_MODULE", + "offsets": [ + { + "name": "Id", + "offset": 0, + "size": 8 + }, + { + "name": "Path", + "offset": 8, + "size": 8 + }, + { + "name": "Exports", + "offset": 16, + "size": 8 + }, + { + "name": "Filename", + "offset": 24, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_cjs_require.json b/ecmascript/js_type_metadata/js_cjs_require.json new file mode 100644 index 0000000000000000000000000000000000000000..4c60e32e4d33a926b49311a3aa190d990eeb5962 --- /dev/null +++ b/ecmascript/js_type_metadata/js_cjs_require.json @@ -0,0 +1,19 @@ +{ + "name": "JS_CJS_REQUIRE", + "offsets": [ + { + "name": "Cache", + "offset": 0, + "size": 8 + }, + { + "name": "Parent", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_collator.json b/ecmascript/js_type_metadata/js_collator.json new file mode 100644 index 0000000000000000000000000000000000000000..fb03170d12986980e8ab03046aa98103f3f781c0 --- /dev/null +++ b/ecmascript/js_type_metadata/js_collator.json @@ -0,0 +1,29 @@ +{ + "name": "JS_COLLATOR", + "offsets": [ + { + "name": "IcuFiled", + "offset": 0, + "size": 8 + }, + { + "name": "Locale", + "offset": 8, + "size": 8 + }, + { + "name": "Collation", + "offset": 16, + "size": 8 + }, + { + "name": "BoundCompare", + "offset": 24, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_data_view.json b/ecmascript/js_type_metadata/js_data_view.json new file mode 100644 index 0000000000000000000000000000000000000000..ca3eeede1daf6ada6f5f5a83571721806084bd24 --- /dev/null +++ b/ecmascript/js_type_metadata/js_data_view.json @@ -0,0 +1,19 @@ +{ + "name": "JS_DATA_VIEW", + "offsets": [ + { + "name": "DataView", + "offset": 0, + "size": 8 + }, + { + "name": "ViewedArrayBuffer", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_date.json b/ecmascript/js_type_metadata/js_date.json new file mode 100644 index 0000000000000000000000000000000000000000..e4517a476d08bf7dde985a2367d1b5427f310db3 --- /dev/null +++ b/ecmascript/js_type_metadata/js_date.json @@ -0,0 +1,19 @@ +{ + "name": "JS_DATE", + "offsets": [ + { + "name": "TimeValue", + "offset": 0, + "size": 8 + }, + { + "name": "LocalOffset", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_date_time_format.json b/ecmascript/js_type_metadata/js_date_time_format.json new file mode 100644 index 0000000000000000000000000000000000000000..3705a359c9ffd17c524b42590f61d319290089e4 --- /dev/null +++ b/ecmascript/js_type_metadata/js_date_time_format.json @@ -0,0 +1,49 @@ +{ + "name": "JS_DATE_TIME_FORMAT", + "offsets": [ + { + "name": "Locale", + "offset": 0, + "size": 8 + }, + { + "name": "Calendar", + "offset": 8, + "size": 8 + }, + { + "name": "NumberingSystem", + "offset": 16, + "size": 8 + }, + { + "name": "TimeZone", + "offset": 24, + "size": 8 + }, + { + "name": "LocaleIcu", + "offset": 32, + "size": 8 + }, + { + "name": "SimpleDateTimeFormatIcu", + "offset": 40, + "size": 8 + }, + { + "name": "Iso8601", + "offset": 48, + "size": 8 + }, + { + "name": "BoundFormat", + "offset": 56, + "size": 8 + } + ], + "end_offset": 72, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_displaynames.json b/ecmascript/js_type_metadata/js_displaynames.json new file mode 100644 index 0000000000000000000000000000000000000000..7b532b0be9167ebbe78c385860c4764a70309399 --- /dev/null +++ b/ecmascript/js_type_metadata/js_displaynames.json @@ -0,0 +1,19 @@ +{ + "name": "JS_DISPLAYNAMES", + "offsets": [ + { + "name": "Locale", + "offset": 0, + "size": 8 + }, + { + "name": "IcuLDN", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_error.json b/ecmascript/js_type_metadata/js_error.json new file mode 100644 index 0000000000000000000000000000000000000000..bcdfd6b144f62f49654f0990adb79b7c707d5282 --- /dev/null +++ b/ecmascript/js_type_metadata/js_error.json @@ -0,0 +1,17 @@ +{ + "name": "JS_ERROR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_eval_error.json b/ecmascript/js_type_metadata/js_eval_error.json new file mode 100644 index 0000000000000000000000000000000000000000..31e43f923c29153223deb668d43e0da5ee25135b --- /dev/null +++ b/ecmascript/js_type_metadata/js_eval_error.json @@ -0,0 +1,17 @@ +{ + "name": "JS_EVAL_ERROR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_finalization_registry.json b/ecmascript/js_type_metadata/js_finalization_registry.json new file mode 100644 index 0000000000000000000000000000000000000000..6e69bf67bbfeb73deafa494b658df8b5aea959f7 --- /dev/null +++ b/ecmascript/js_type_metadata/js_finalization_registry.json @@ -0,0 +1,34 @@ +{ + "name": "JS_FINALIZATION_REGISTRY", + "offsets": [ + { + "name": "CleanupCallback", + "offset": 0, + "size": 8 + }, + { + "name": "NoUnregister", + "offset": 8, + "size": 8 + }, + { + "name": "MaybeUnregister", + "offset": 16, + "size": 8 + }, + { + "name": "Next", + "offset": 24, + "size": 8 + }, + { + "name": "Prev", + "offset": 32, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_float32_array.json b/ecmascript/js_type_metadata/js_float32_array.json new file mode 100644 index 0000000000000000000000000000000000000000..6eadcef9df2bef76f9aed39478986a5c2e72be12 --- /dev/null +++ b/ecmascript/js_type_metadata/js_float32_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_FLOAT32_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_float64_array.json b/ecmascript/js_type_metadata/js_float64_array.json new file mode 100644 index 0000000000000000000000000000000000000000..a1f809b48880d657d211f2a8b3d696de27d9076a --- /dev/null +++ b/ecmascript/js_type_metadata/js_float64_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_FLOAT64_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_forin_iterator.json b/ecmascript/js_type_metadata/js_forin_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..74cf1ea8c0d68beaa3fda52fe9496c7ee34fab2a --- /dev/null +++ b/ecmascript/js_type_metadata/js_forin_iterator.json @@ -0,0 +1,24 @@ +{ + "name": "JS_FORIN_ITERATOR", + "offsets": [ + { + "name": "Object", + "offset": 0, + "size": 8 + }, + { + "name": "CachedHclass", + "offset": 8, + "size": 8 + }, + { + "name": "Keys", + "offset": 16, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_function.json b/ecmascript/js_type_metadata/js_function.json new file mode 100644 index 0000000000000000000000000000000000000000..1e4d8b7bba528eb94a58949e5a1395da59410512 --- /dev/null +++ b/ecmascript/js_type_metadata/js_function.json @@ -0,0 +1,49 @@ +{ + "name": "JS_FUNCTION", + "offsets": [ + { + "name": "ProtoOrHClass", + "offset": 0, + "size": 8 + }, + { + "name": "LexicalEnv", + "offset": 8, + "size": 8 + }, + { + "name": "MachineCode", + "offset": 16, + "size": 8 + }, + { + "name": "BaselineCode", + "offset": 24, + "size": 8 + }, + { + "name": "RawProfileTypeInfo", + "offset": 32, + "size": 8 + }, + { + "name": "HomeObject", + "offset": 40, + "size": 8 + }, + { + "name": "Module", + "offset": 48, + "size": 8 + }, + { + "name": "ProtoTransRootHClass", + "offset": 56, + "size": 8 + } + ], + "end_offset": 72, + "parents": [ + "JS_FUNCTION_BASE" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_function_base.json b/ecmascript/js_type_metadata/js_function_base.json new file mode 100644 index 0000000000000000000000000000000000000000..16e6ab4630688842ee1b7ad74431a47ae3783049 --- /dev/null +++ b/ecmascript/js_type_metadata/js_function_base.json @@ -0,0 +1,14 @@ +{ + "name": "JS_FUNCTION_BASE", + "offsets": [ + { + "name": "Method", + "offset": 0, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_generator_context.json b/ecmascript/js_type_metadata/js_generator_context.json new file mode 100644 index 0000000000000000000000000000000000000000..182beeffcdf45871922833a44f888d9ff6f2e5d3 --- /dev/null +++ b/ecmascript/js_type_metadata/js_generator_context.json @@ -0,0 +1,39 @@ +{ + "name": "JS_GENERATOR_CONTEXT", + "offsets": [ + { + "name": "RegsArray", + "offset": 0, + "size": 8 + }, + { + "name": "Method", + "offset": 8, + "size": 8 + }, + { + "name": "This", + "offset": 16, + "size": 8 + }, + { + "name": "Acc", + "offset": 24, + "size": 8 + }, + { + "name": "GeneratorObject", + "offset": 32, + "size": 8 + }, + { + "name": "LexicalEnv", + "offset": 40, + "size": 8 + } + ], + "end_offset": 56, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_generator_function.json b/ecmascript/js_type_metadata/js_generator_function.json new file mode 100644 index 0000000000000000000000000000000000000000..ac9a19a782b29bbd17505ada67d6659f55ccc0f5 --- /dev/null +++ b/ecmascript/js_type_metadata/js_generator_function.json @@ -0,0 +1,8 @@ +{ + "name": "JS_GENERATOR_FUNCTION", + "offsets": [], + "end_offset": 0, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_generator_object.json b/ecmascript/js_type_metadata/js_generator_object.json new file mode 100644 index 0000000000000000000000000000000000000000..2d0358e391aad0652d83a6771b51ae670139b53f --- /dev/null +++ b/ecmascript/js_type_metadata/js_generator_object.json @@ -0,0 +1,19 @@ +{ + "name": "JS_GENERATOR_OBJECT", + "offsets": [ + { + "name": "GeneratorContext", + "offset": 0, + "size": 8 + }, + { + "name": "ResumeResult", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_global_object.json b/ecmascript/js_type_metadata/js_global_object.json new file mode 100644 index 0000000000000000000000000000000000000000..4bd4fdde7852ea202c1545eab74e4001338118c4 --- /dev/null +++ b/ecmascript/js_type_metadata/js_global_object.json @@ -0,0 +1,8 @@ +{ + "name": "JS_GLOBAL_OBJECT", + "offsets": [], + "end_offset": 0, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_int16_array.json b/ecmascript/js_type_metadata/js_int16_array.json new file mode 100644 index 0000000000000000000000000000000000000000..70d239fd9ad9e857707272465ffbcc74bdf1ef41 --- /dev/null +++ b/ecmascript/js_type_metadata/js_int16_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_INT16_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_int32_array.json b/ecmascript/js_type_metadata/js_int32_array.json new file mode 100644 index 0000000000000000000000000000000000000000..d4156cc682f4b7622272d3643e3d8bbedb5d1929 --- /dev/null +++ b/ecmascript/js_type_metadata/js_int32_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_INT32_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_int8_array.json b/ecmascript/js_type_metadata/js_int8_array.json new file mode 100644 index 0000000000000000000000000000000000000000..edc78368ca882b0d9404b0fea1ece8dd52f9420e --- /dev/null +++ b/ecmascript/js_type_metadata/js_int8_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_INT8_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_intl.json b/ecmascript/js_type_metadata/js_intl.json new file mode 100644 index 0000000000000000000000000000000000000000..ecce318e7c981cca89ad078f41ffaeb6ab0286dc --- /dev/null +++ b/ecmascript/js_type_metadata/js_intl.json @@ -0,0 +1,14 @@ +{ + "name": "JS_INTL", + "offsets": [ + { + "name": "FallbackSymbol", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_intl_bound_function.json b/ecmascript/js_type_metadata/js_intl_bound_function.json new file mode 100644 index 0000000000000000000000000000000000000000..28b60dedca381d655286dbb15f7a6eaef67c836a --- /dev/null +++ b/ecmascript/js_type_metadata/js_intl_bound_function.json @@ -0,0 +1,24 @@ +{ + "name": "JS_INTL_BOUND_FUNCTION", + "offsets": [ + { + "name": "NumberFormat", + "offset": 0, + "size": 8 + }, + { + "name": "DateTimeFormat", + "offset": 8, + "size": 8 + }, + { + "name": "Collator", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_iterator.json b/ecmascript/js_type_metadata/js_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..305d8b5dd61b34ba75f84c0edfcc8cadc5f01748 --- /dev/null +++ b/ecmascript/js_type_metadata/js_iterator.json @@ -0,0 +1,17 @@ +{ + "name": "JS_ITERATOR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_list_format.json b/ecmascript/js_type_metadata/js_list_format.json new file mode 100644 index 0000000000000000000000000000000000000000..aa843d5af56ca6fd3b13be9b14527e2daccc48a8 --- /dev/null +++ b/ecmascript/js_type_metadata/js_list_format.json @@ -0,0 +1,19 @@ +{ + "name": "JS_LIST_FORMAT", + "offsets": [ + { + "name": "Locale", + "offset": 0, + "size": 8 + }, + { + "name": "IcuLF", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_locale.json b/ecmascript/js_type_metadata/js_locale.json new file mode 100644 index 0000000000000000000000000000000000000000..4fefecec96478a2071f07757d9733220e30712b8 --- /dev/null +++ b/ecmascript/js_type_metadata/js_locale.json @@ -0,0 +1,14 @@ +{ + "name": "JS_LOCALE", + "offsets": [ + { + "name": "IcuField", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_map.json b/ecmascript/js_type_metadata/js_map.json new file mode 100644 index 0000000000000000000000000000000000000000..b94439055c01d953944520bff34d6d6195c4cc22 --- /dev/null +++ b/ecmascript/js_type_metadata/js_map.json @@ -0,0 +1,14 @@ +{ + "name": "JS_MAP", + "offsets": [ + { + "name": "LinkedMap", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_map_iterator.json b/ecmascript/js_type_metadata/js_map_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..d0071cb6b31261cf6cfa0770fb03203bc56f1991 --- /dev/null +++ b/ecmascript/js_type_metadata/js_map_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_MAP_ITERATOR", + "offsets": [ + { + "name": "IteratorMap", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_module_namespace.json b/ecmascript/js_type_metadata/js_module_namespace.json new file mode 100644 index 0000000000000000000000000000000000000000..f2b4439458f5db1fad5fb5ba1a64d53769383b35 --- /dev/null +++ b/ecmascript/js_type_metadata/js_module_namespace.json @@ -0,0 +1,24 @@ +{ + "name": "JS_MODULE_NAMESPACE", + "offsets": [ + { + "name": "Module", + "offset": 0, + "size": 8 + }, + { + "name": "Exports", + "offset": 8, + "size": 8 + }, + { + "name": "DeregisterProcession", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_native_pointer.json b/ecmascript/js_type_metadata/js_native_pointer.json new file mode 100644 index 0000000000000000000000000000000000000000..4a48827b6e1e19d37b0e24d52992e6f9b834c0ac --- /dev/null +++ b/ecmascript/js_type_metadata/js_native_pointer.json @@ -0,0 +1,14 @@ +{ + "name": "JS_NATIVE_POINTER", + "offsets": [ + { + "name": "BindingSize", + "offset": 24, + "size": 4 + } + ], + "end_offset": 32, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_number_format.json b/ecmascript/js_type_metadata/js_number_format.json new file mode 100644 index 0000000000000000000000000000000000000000..ce9e0d700bdcd1b5c1e426aa9794aae17154530b --- /dev/null +++ b/ecmascript/js_type_metadata/js_number_format.json @@ -0,0 +1,69 @@ +{ + "name": "JS_NUMBER_FORMAT", + "offsets": [ + { + "name": "Locale", + "offset": 0, + "size": 8 + }, + { + "name": "NumberingSystem", + "offset": 8, + "size": 8 + }, + { + "name": "Currency", + "offset": 16, + "size": 8 + }, + { + "name": "Unit", + "offset": 24, + "size": 8 + }, + { + "name": "MinimumIntegerDigits", + "offset": 32, + "size": 8 + }, + { + "name": "MinimumFractionDigits", + "offset": 40, + "size": 8 + }, + { + "name": "MaximumFractionDigits", + "offset": 48, + "size": 8 + }, + { + "name": "MinimumSignificantDigits", + "offset": 56, + "size": 8 + }, + { + "name": "MaximumSignificantDigits", + "offset": 64, + "size": 8 + }, + { + "name": "UseGrouping", + "offset": 72, + "size": 8 + }, + { + "name": "BoundFormat", + "offset": 80, + "size": 8 + }, + { + "name": "IcuField", + "offset": 88, + "size": 8 + } + ], + "end_offset": 104, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_object.json b/ecmascript/js_type_metadata/js_object.json new file mode 100644 index 0000000000000000000000000000000000000000..964141263d906f873cb8b9b11ef43c07c9e765e4 --- /dev/null +++ b/ecmascript/js_type_metadata/js_object.json @@ -0,0 +1,17 @@ +{ + "name": "JS_OBJECT", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_oom_error.json b/ecmascript/js_type_metadata/js_oom_error.json new file mode 100644 index 0000000000000000000000000000000000000000..7ef8a46d9977deb2aed29a57488236fe58603b88 --- /dev/null +++ b/ecmascript/js_type_metadata/js_oom_error.json @@ -0,0 +1,17 @@ +{ + "name": "JS_OOM_ERROR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_plural_rules.json b/ecmascript/js_type_metadata/js_plural_rules.json new file mode 100644 index 0000000000000000000000000000000000000000..86c63b0344a9c6c23fcdee4a4b388d27578df4c4 --- /dev/null +++ b/ecmascript/js_type_metadata/js_plural_rules.json @@ -0,0 +1,49 @@ +{ + "name": "JS_PLURAL_RULES", + "offsets": [ + { + "name": "Locale", + "offset": 0, + "size": 8 + }, + { + "name": "MinimumIntegerDigits", + "offset": 8, + "size": 8 + }, + { + "name": "MinimumFractionDigits", + "offset": 16, + "size": 8 + }, + { + "name": "MaximumFractionDigits", + "offset": 24, + "size": 8 + }, + { + "name": "MinimumSignificantDigits", + "offset": 32, + "size": 8 + }, + { + "name": "MaximumSignificantDigits", + "offset": 40, + "size": 8 + }, + { + "name": "IcuPR", + "offset": 48, + "size": 8 + }, + { + "name": "IcuNF", + "offset": 56, + "size": 8 + } + ], + "end_offset": 72, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_primitive_ref.json b/ecmascript/js_type_metadata/js_primitive_ref.json new file mode 100644 index 0000000000000000000000000000000000000000..32b41ffe49600438a1c63e1f122c72ec302c8b4b --- /dev/null +++ b/ecmascript/js_type_metadata/js_primitive_ref.json @@ -0,0 +1,14 @@ +{ + "name": "JS_PRIMITIVE_REF", + "offsets": [ + { + "name": "Value", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_promise.json b/ecmascript/js_type_metadata/js_promise.json new file mode 100644 index 0000000000000000000000000000000000000000..2976d4929b05f97224de93c40aaff0d232cb6579 --- /dev/null +++ b/ecmascript/js_type_metadata/js_promise.json @@ -0,0 +1,24 @@ +{ + "name": "JS_PROMISE", + "offsets": [ + { + "name": "PromiseResult", + "offset": 0, + "size": 8 + }, + { + "name": "PromiseFulfillReactions", + "offset": 8, + "size": 8 + }, + { + "name": "PromiseRejectReactions", + "offset": 16, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_promise_all_resolve_element_function.json b/ecmascript/js_type_metadata/js_promise_all_resolve_element_function.json new file mode 100644 index 0000000000000000000000000000000000000000..77cfb3099a70da8aee2ea4fc5405708c4c1b8796 --- /dev/null +++ b/ecmascript/js_type_metadata/js_promise_all_resolve_element_function.json @@ -0,0 +1,34 @@ +{ + "name": "JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION", + "offsets": [ + { + "name": "Index", + "offset": 0, + "size": 8 + }, + { + "name": "Values", + "offset": 8, + "size": 8 + }, + { + "name": "Capabilities", + "offset": 16, + "size": 8 + }, + { + "name": "RemainingElements", + "offset": 24, + "size": 8 + }, + { + "name": "AlreadyCalled", + "offset": 32, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_promise_all_settled_element_function.json b/ecmascript/js_type_metadata/js_promise_all_settled_element_function.json new file mode 100644 index 0000000000000000000000000000000000000000..daa46d31ff543544a4011ccfbf25c3b18276618c --- /dev/null +++ b/ecmascript/js_type_metadata/js_promise_all_settled_element_function.json @@ -0,0 +1,29 @@ +{ + "name": "JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION", + "offsets": [ + { + "name": "AlreadyCalled", + "offset": 0, + "size": 8 + }, + { + "name": "Values", + "offset": 8, + "size": 8 + }, + { + "name": "Capability", + "offset": 16, + "size": 8 + }, + { + "name": "RemainingElements", + "offset": 24, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_promise_any_reject_element_function.json b/ecmascript/js_type_metadata/js_promise_any_reject_element_function.json new file mode 100644 index 0000000000000000000000000000000000000000..a166f0649538392f622d9ee9d9d20c978684bc6d --- /dev/null +++ b/ecmascript/js_type_metadata/js_promise_any_reject_element_function.json @@ -0,0 +1,29 @@ +{ + "name": "JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION", + "offsets": [ + { + "name": "Errors", + "offset": 0, + "size": 8 + }, + { + "name": "Capability", + "offset": 8, + "size": 8 + }, + { + "name": "RemainingElements", + "offset": 16, + "size": 8 + }, + { + "name": "AlreadyCalled", + "offset": 24, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_promise_executor_function.json b/ecmascript/js_type_metadata/js_promise_executor_function.json new file mode 100644 index 0000000000000000000000000000000000000000..88a77c9d317c7cb981ee68f2f6df08741c63f43f --- /dev/null +++ b/ecmascript/js_type_metadata/js_promise_executor_function.json @@ -0,0 +1,14 @@ +{ + "name": "JS_PROMISE_EXECUTOR_FUNCTION", + "offsets": [ + { + "name": "Capability", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_promise_finally_function.json b/ecmascript/js_type_metadata/js_promise_finally_function.json new file mode 100644 index 0000000000000000000000000000000000000000..2a0c3475d24ee1ea981c7a33198530321e8a0fdb --- /dev/null +++ b/ecmascript/js_type_metadata/js_promise_finally_function.json @@ -0,0 +1,19 @@ +{ + "name": "JS_PROMISE_FINALLY_FUNCTION", + "offsets": [ + { + "name": "Constructor", + "offset": 0, + "size": 8 + }, + { + "name": "OnFinally", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_promise_reactions_function.json b/ecmascript/js_type_metadata/js_promise_reactions_function.json new file mode 100644 index 0000000000000000000000000000000000000000..824ed40d2383fac7280f1e250b1a4dc88cbfcfb7 --- /dev/null +++ b/ecmascript/js_type_metadata/js_promise_reactions_function.json @@ -0,0 +1,19 @@ +{ + "name": "JS_PROMISE_REACTIONS_FUNCTION", + "offsets": [ + { + "name": "Promise", + "offset": 0, + "size": 8 + }, + { + "name": "AlreadyResolved", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_promise_value_thunk_or_thrower_function.json b/ecmascript/js_type_metadata/js_promise_value_thunk_or_thrower_function.json new file mode 100644 index 0000000000000000000000000000000000000000..ff9c0781f52cf00832c4ed901227323bde0f8461 --- /dev/null +++ b/ecmascript/js_type_metadata/js_promise_value_thunk_or_thrower_function.json @@ -0,0 +1,14 @@ +{ + "name": "JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION", + "offsets": [ + { + "name": "Result", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_proxy.json b/ecmascript/js_type_metadata/js_proxy.json new file mode 100644 index 0000000000000000000000000000000000000000..20a23baf153d038090412bdb9c67ef97b9a9cf9e --- /dev/null +++ b/ecmascript/js_type_metadata/js_proxy.json @@ -0,0 +1,29 @@ +{ + "name": "JS_PROXY", + "offsets": [ + { + "name": "Target", + "offset": 0, + "size": 8 + }, + { + "name": "Handler", + "offset": 8, + "size": 8 + }, + { + "name": "Method", + "offset": 16, + "size": 8 + }, + { + "name": "PrivateField", + "offset": 24, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "ECMA_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_proxy_revoc_function.json b/ecmascript/js_type_metadata/js_proxy_revoc_function.json new file mode 100644 index 0000000000000000000000000000000000000000..4f12ba2f4f6f898f6064e12b017821d499ee1bc7 --- /dev/null +++ b/ecmascript/js_type_metadata/js_proxy_revoc_function.json @@ -0,0 +1,14 @@ +{ + "name": "JS_PROXY_REVOC_FUNCTION", + "offsets": [ + { + "name": "RevocableProxy", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_range_error.json b/ecmascript/js_type_metadata/js_range_error.json new file mode 100644 index 0000000000000000000000000000000000000000..91a1bd8fde90bf87ec8f1430273b0c3143c89131 --- /dev/null +++ b/ecmascript/js_type_metadata/js_range_error.json @@ -0,0 +1,17 @@ +{ + "name": "JS_RANGE_ERROR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_realm.json b/ecmascript/js_type_metadata/js_realm.json new file mode 100644 index 0000000000000000000000000000000000000000..24b2e560c39266bcc89afba97f145fe4fb40077c --- /dev/null +++ b/ecmascript/js_type_metadata/js_realm.json @@ -0,0 +1,19 @@ +{ + "name": "JS_REALM", + "offsets": [ + { + "name": "Value", + "offset": 0, + "size": 8 + }, + { + "name": "GlobalEnv", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_reference_error.json b/ecmascript/js_type_metadata/js_reference_error.json new file mode 100644 index 0000000000000000000000000000000000000000..ea378f1385c6b3e6f96f5c460ed202523ff7c73d --- /dev/null +++ b/ecmascript/js_type_metadata/js_reference_error.json @@ -0,0 +1,17 @@ +{ + "name": "JS_REFERENCE_ERROR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_reg_exp.json b/ecmascript/js_type_metadata/js_reg_exp.json new file mode 100644 index 0000000000000000000000000000000000000000..bcb13acf3b28d6152502f9a574807fa4036e5a3a --- /dev/null +++ b/ecmascript/js_type_metadata/js_reg_exp.json @@ -0,0 +1,29 @@ +{ + "name": "JS_REG_EXP", + "offsets": [ + { + "name": "ByteCodeBuffer", + "offset": 0, + "size": 8 + }, + { + "name": "OriginalSource", + "offset": 8, + "size": 8 + }, + { + "name": "OriginalFlags", + "offset": 16, + "size": 8 + }, + { + "name": "GroupName", + "offset": 24, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_reg_exp_iterator.json b/ecmascript/js_type_metadata/js_reg_exp_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..27ea6287d7d21fdf3a876d0dd75fe1fef694acbd --- /dev/null +++ b/ecmascript/js_type_metadata/js_reg_exp_iterator.json @@ -0,0 +1,19 @@ +{ + "name": "JS_REG_EXP_ITERATOR", + "offsets": [ + { + "name": "IteratingRegExp", + "offset": 0, + "size": 8 + }, + { + "name": "IteratedString", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_relative_time_format.json b/ecmascript/js_type_metadata/js_relative_time_format.json new file mode 100644 index 0000000000000000000000000000000000000000..b4d7afb8f9b2f248cc8dd3b6c471533a8d678515 --- /dev/null +++ b/ecmascript/js_type_metadata/js_relative_time_format.json @@ -0,0 +1,24 @@ +{ + "name": "JS_RELATIVE_TIME_FORMAT", + "offsets": [ + { + "name": "Locale", + "offset": 0, + "size": 8 + }, + { + "name": "NumberingSystem", + "offset": 8, + "size": 8 + }, + { + "name": "IcuField", + "offset": 16, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_segment_iterator.json b/ecmascript/js_type_metadata/js_segment_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..7be94b25f63ed8251bb53acdb2310e92afcd707f --- /dev/null +++ b/ecmascript/js_type_metadata/js_segment_iterator.json @@ -0,0 +1,24 @@ +{ + "name": "JS_SEGMENT_ITERATOR", + "offsets": [ + { + "name": "IcuField", + "offset": 0, + "size": 8 + }, + { + "name": "IteratedString", + "offset": 8, + "size": 8 + }, + { + "name": "UnicodeString", + "offset": 16, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_segmenter.json b/ecmascript/js_type_metadata/js_segmenter.json new file mode 100644 index 0000000000000000000000000000000000000000..f3cc15fab45e05a8f6beb9b13656d01f4e489b66 --- /dev/null +++ b/ecmascript/js_type_metadata/js_segmenter.json @@ -0,0 +1,19 @@ +{ + "name": "JS_SEGMENTER", + "offsets": [ + { + "name": "Locale", + "offset": 0, + "size": 8 + }, + { + "name": "IcuField", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_segments.json b/ecmascript/js_type_metadata/js_segments.json new file mode 100644 index 0000000000000000000000000000000000000000..bb17de135638635334e9a2ac8d7e053c9361d338 --- /dev/null +++ b/ecmascript/js_type_metadata/js_segments.json @@ -0,0 +1,24 @@ +{ + "name": "JS_SEGMENTS", + "offsets": [ + { + "name": "IcuField", + "offset": 0, + "size": 8 + }, + { + "name": "SegmentsString", + "offset": 8, + "size": 8 + }, + { + "name": "UnicodeString", + "offset": 16, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_sendable_array_buffer.json b/ecmascript/js_type_metadata/js_sendable_array_buffer.json new file mode 100644 index 0000000000000000000000000000000000000000..28ca47b89f62bba356c2f2e267c84adc0ad0e257 --- /dev/null +++ b/ecmascript/js_type_metadata/js_sendable_array_buffer.json @@ -0,0 +1,14 @@ +{ + "name": "JS_SENDABLE_ARRAY_BUFFER", + "offsets": [ + { + "name": "ArrayBufferData", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_set.json b/ecmascript/js_type_metadata/js_set.json new file mode 100644 index 0000000000000000000000000000000000000000..40f75a35d16a9dc4dc5b6323f86375ef92f3dd39 --- /dev/null +++ b/ecmascript/js_type_metadata/js_set.json @@ -0,0 +1,14 @@ +{ + "name": "JS_SET", + "offsets": [ + { + "name": "LinkedSet", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_set_iterator.json b/ecmascript/js_type_metadata/js_set_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..28313c03c593fa5e13151c5fd4515a66d2a2ee4d --- /dev/null +++ b/ecmascript/js_type_metadata/js_set_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_SET_ITERATOR", + "offsets": [ + { + "name": "IteratorSet", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_array.json b/ecmascript/js_type_metadata/js_shared_array.json new file mode 100644 index 0000000000000000000000000000000000000000..c89ac72c74ffa60e3509457eaa2bd91f3e6d308a --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_array.json @@ -0,0 +1,14 @@ +{ + "name": "JS_SHARED_ARRAY", + "offsets": [ + { + "name": "TrackInfo", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_array_buffer.json b/ecmascript/js_type_metadata/js_shared_array_buffer.json new file mode 100644 index 0000000000000000000000000000000000000000..d373cb3de9a9fcf89bf66a5380ca48beb1ed3cdc --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_array_buffer.json @@ -0,0 +1,14 @@ +{ + "name": "JS_SHARED_ARRAY_BUFFER", + "offsets": [ + { + "name": "ArrayBufferData", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_array_iterator.json b/ecmascript/js_type_metadata/js_shared_array_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..e56ae165d2e1b485c71aa4b51aea0e3bf6393dd3 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_array_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_SHARED_ARRAY_ITERATOR", + "offsets": [ + { + "name": "IteratedArray", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_async_function.json b/ecmascript/js_type_metadata/js_shared_async_function.json new file mode 100644 index 0000000000000000000000000000000000000000..c5d04a464e9155689767a55e888a1763fd1ca70d --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_async_function.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_ASYNC_FUNCTION", + "offsets": [], + "end_offset": 0, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_bigint64_array.json b/ecmascript/js_type_metadata/js_shared_bigint64_array.json new file mode 100644 index 0000000000000000000000000000000000000000..caeb681da776c95f58e2d3209695eefa83200960 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_bigint64_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_BIGINT64_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_biguint64_array.json b/ecmascript/js_type_metadata/js_shared_biguint64_array.json new file mode 100644 index 0000000000000000000000000000000000000000..3b82184edce3876cbfd7a609e51d1b7ee9e4ac6f --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_biguint64_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_BIGUINT64_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_float32_array.json b/ecmascript/js_type_metadata/js_shared_float32_array.json new file mode 100644 index 0000000000000000000000000000000000000000..6212a64b0ade5da59622109479b57e6e8ef6297c --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_float32_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_FLOAT32_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_float64_array.json b/ecmascript/js_type_metadata/js_shared_float64_array.json new file mode 100644 index 0000000000000000000000000000000000000000..a026fdbda21d3a84de7c7aba838c8272ddcdd3f3 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_float64_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_FLOAT64_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_function.json b/ecmascript/js_type_metadata/js_shared_function.json new file mode 100644 index 0000000000000000000000000000000000000000..433ca5b5b409aaac9983e18da1b884d33c353016 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_function.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_FUNCTION", + "offsets": [], + "end_offset": 0, + "parents": [ + "JS_FUNCTION" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_int16_array.json b/ecmascript/js_type_metadata/js_shared_int16_array.json new file mode 100644 index 0000000000000000000000000000000000000000..7dc01daa18e18e847ed354894c079151672a95fc --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_int16_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_INT16_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_int32_array.json b/ecmascript/js_type_metadata/js_shared_int32_array.json new file mode 100644 index 0000000000000000000000000000000000000000..cb5a11e22277971b1d4a66eb084cb80bb0c4c833 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_int32_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_INT32_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_int8_array.json b/ecmascript/js_type_metadata/js_shared_int8_array.json new file mode 100644 index 0000000000000000000000000000000000000000..7d47440911218a8b85c604da1b4abb5f5a71b955 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_int8_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_INT8_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_map.json b/ecmascript/js_type_metadata/js_shared_map.json new file mode 100644 index 0000000000000000000000000000000000000000..37564741e3b5db9669eb4f7dd1091f8c00898a39 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_map.json @@ -0,0 +1,14 @@ +{ + "name": "JS_SHARED_MAP", + "offsets": [ + { + "name": "LinkedMap", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_map_iterator.json b/ecmascript/js_type_metadata/js_shared_map_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..98f77ff3ef00a3be04ab107bf003420c2f7875bb --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_map_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_SHARED_MAP_ITERATOR", + "offsets": [ + { + "name": "IteratorMap", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_object.json b/ecmascript/js_type_metadata/js_shared_object.json new file mode 100644 index 0000000000000000000000000000000000000000..5e6102abb8cb376704a7ec148253ea191cc41d31 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_object.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_OBJECT", + "offsets": [], + "end_offset": 0, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_set.json b/ecmascript/js_type_metadata/js_shared_set.json new file mode 100644 index 0000000000000000000000000000000000000000..aad901e9e29563dc8532a84e8f1038d5d8c8480f --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_set.json @@ -0,0 +1,14 @@ +{ + "name": "JS_SHARED_SET", + "offsets": [ + { + "name": "LinkedSet", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_set_iterator.json b/ecmascript/js_type_metadata/js_shared_set_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..baae11a57e38289ebba6d0c7e39bedda96212539 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_set_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_SHARED_SET_ITERATOR", + "offsets": [ + { + "name": "IteratorSet", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_typed_array.json b/ecmascript/js_type_metadata/js_shared_typed_array.json new file mode 100644 index 0000000000000000000000000000000000000000..77697fb320baef82c023614d384675b3caf2e296 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_typed_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_TYPED_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_uint16_array.json b/ecmascript/js_type_metadata/js_shared_uint16_array.json new file mode 100644 index 0000000000000000000000000000000000000000..b97a62743989efd83697c97bdd6a22aba15b8da5 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_uint16_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_UINT16_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_uint32_array.json b/ecmascript/js_type_metadata/js_shared_uint32_array.json new file mode 100644 index 0000000000000000000000000000000000000000..4e052eb984261a2bb65fc06b22190d86086f0038 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_uint32_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_UINT32_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_uint8_array.json b/ecmascript/js_type_metadata/js_shared_uint8_array.json new file mode 100644 index 0000000000000000000000000000000000000000..f8fb184666f9a9d6beecab590677f95b73b6fa46 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_uint8_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_UINT8_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_shared_uint8_clamped_array.json b/ecmascript/js_type_metadata/js_shared_uint8_clamped_array.json new file mode 100644 index 0000000000000000000000000000000000000000..6fea48e2175dfbcb920c9ee1c57dd3510f3c0be6 --- /dev/null +++ b/ecmascript/js_type_metadata/js_shared_uint8_clamped_array.json @@ -0,0 +1,8 @@ +{ + "name": "JS_SHARED_UINT8_CLAMPED_ARRAY", + "offsets": [], + "end_offset": 8, + "parents": [ + "JS_TYPED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_string_iterator.json b/ecmascript/js_type_metadata/js_string_iterator.json new file mode 100644 index 0000000000000000000000000000000000000000..b81b80726b0adde222f0b60ee35044a7b4a7df3f --- /dev/null +++ b/ecmascript/js_type_metadata/js_string_iterator.json @@ -0,0 +1,14 @@ +{ + "name": "JS_STRING_ITERATOR", + "offsets": [ + { + "name": "IteratedString", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_syntax_error.json b/ecmascript/js_type_metadata/js_syntax_error.json new file mode 100644 index 0000000000000000000000000000000000000000..f229230394f04b675ba0ddea8958e89d3dd12f60 --- /dev/null +++ b/ecmascript/js_type_metadata/js_syntax_error.json @@ -0,0 +1,17 @@ +{ + "name": "JS_SYNTAX_ERROR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_termination_error.json b/ecmascript/js_type_metadata/js_termination_error.json new file mode 100644 index 0000000000000000000000000000000000000000..3cb60ba5c30b5df6a3e7453f4c0f6b550300227e --- /dev/null +++ b/ecmascript/js_type_metadata/js_termination_error.json @@ -0,0 +1,17 @@ +{ + "name": "JS_TERMINATION_ERROR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_type_error.json b/ecmascript/js_type_metadata/js_type_error.json new file mode 100644 index 0000000000000000000000000000000000000000..296d69208b924d63cd9f31c7647bc65c3bdd0690 --- /dev/null +++ b/ecmascript/js_type_metadata/js_type_error.json @@ -0,0 +1,17 @@ +{ + "name": "JS_TYPE_ERROR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_typed_array.json b/ecmascript/js_type_metadata/js_typed_array.json new file mode 100644 index 0000000000000000000000000000000000000000..58ed1ba26888c751e3d79e6f368c7377e5cf5900 --- /dev/null +++ b/ecmascript/js_type_metadata/js_typed_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_TYPED_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_uint16_array.json b/ecmascript/js_type_metadata/js_uint16_array.json new file mode 100644 index 0000000000000000000000000000000000000000..7932d0230caffd2c47f73ba73a85e9ec0faf299a --- /dev/null +++ b/ecmascript/js_type_metadata/js_uint16_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_UINT16_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_uint32_array.json b/ecmascript/js_type_metadata/js_uint32_array.json new file mode 100644 index 0000000000000000000000000000000000000000..3621dd852ac1e771fc8c0e37652c4b092fc443fb --- /dev/null +++ b/ecmascript/js_type_metadata/js_uint32_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_UINT32_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_uint8_array.json b/ecmascript/js_type_metadata/js_uint8_array.json new file mode 100644 index 0000000000000000000000000000000000000000..b40fb643cddaf2f3b225c4553ddbb1e85bb67e43 --- /dev/null +++ b/ecmascript/js_type_metadata/js_uint8_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_UINT8_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_uint8_clamped_array.json b/ecmascript/js_type_metadata/js_uint8_clamped_array.json new file mode 100644 index 0000000000000000000000000000000000000000..53982231567c0889b1b223ebc3472b23b002ba53 --- /dev/null +++ b/ecmascript/js_type_metadata/js_uint8_clamped_array.json @@ -0,0 +1,19 @@ +{ + "name": "JS_UINT8_CLAMPED_ARRAY", + "offsets": [ + { + "name": "ViewedArrayBufferOrByteArray", + "offset": 0, + "size": 8 + }, + { + "name": "TypedArrayName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_uri_error.json b/ecmascript/js_type_metadata/js_uri_error.json new file mode 100644 index 0000000000000000000000000000000000000000..58b3824b03ea9672816e62e5c8d741f02e9f8927 --- /dev/null +++ b/ecmascript/js_type_metadata/js_uri_error.json @@ -0,0 +1,17 @@ +{ + "name": "JS_URI_ERROR", + "offsets": [ + { + "name": "Properties", + "offset": 0, + "size": 8 + }, + { + "name": "Elements", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": ["ECMA_OBJECT"] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_weak_map.json b/ecmascript/js_type_metadata/js_weak_map.json new file mode 100644 index 0000000000000000000000000000000000000000..c455773fe9542f2698b63aab2cdb2fb0a93022dc --- /dev/null +++ b/ecmascript/js_type_metadata/js_weak_map.json @@ -0,0 +1,14 @@ +{ + "name": "JS_WEAK_MAP", + "offsets": [ + { + "name": "LinkedMap", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_weak_ref.json b/ecmascript/js_type_metadata/js_weak_ref.json new file mode 100644 index 0000000000000000000000000000000000000000..e14f2b1b4c0eb44254b6ed3154c3e97bcf71c2c2 --- /dev/null +++ b/ecmascript/js_type_metadata/js_weak_ref.json @@ -0,0 +1,14 @@ +{ + "name": "JS_WEAK_REF", + "offsets": [ + { + "name": "WeakObject", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/js_weak_set.json b/ecmascript/js_type_metadata/js_weak_set.json new file mode 100644 index 0000000000000000000000000000000000000000..7f9485762b4560bc342daf95188e332537d8c6d5 --- /dev/null +++ b/ecmascript/js_type_metadata/js_weak_set.json @@ -0,0 +1,14 @@ +{ + "name": "JS_WEAK_SET", + "offsets": [ + { + "name": "LinkedSet", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/lexical_env.json b/ecmascript/js_type_metadata/lexical_env.json new file mode 100644 index 0000000000000000000000000000000000000000..0877f1b4f04eae4df78a6ff53889d4c7e065bcf5 --- /dev/null +++ b/ecmascript/js_type_metadata/lexical_env.json @@ -0,0 +1,8 @@ +{ + "name": "LEXICAL_ENV", + "offsets": [], + "end_offset": 0, + "parents": [ + "TAGGED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/line_string.json b/ecmascript/js_type_metadata/line_string.json new file mode 100644 index 0000000000000000000000000000000000000000..d7cf3cc38dbdf612f3965c31e9f4bc14ddc8e1b8 --- /dev/null +++ b/ecmascript/js_type_metadata/line_string.json @@ -0,0 +1,8 @@ +{ + "name": "LINE_STRING", + "offsets": [], + "end_offset": 0, + "parents": [ + "ECMA_STRING" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/linked_node.json b/ecmascript/js_type_metadata/linked_node.json new file mode 100644 index 0000000000000000000000000000000000000000..365920106f841e9906b317fd1449c465470f8355 --- /dev/null +++ b/ecmascript/js_type_metadata/linked_node.json @@ -0,0 +1,14 @@ +{ + "name": "LINKED_NODE", + "offsets": [ + { + "name": "Next", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "TAGGED_NODE" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/local_exportentry_record.json b/ecmascript/js_type_metadata/local_exportentry_record.json new file mode 100644 index 0000000000000000000000000000000000000000..5a6dca449c9718c68b58adc9240cc174345c0be1 --- /dev/null +++ b/ecmascript/js_type_metadata/local_exportentry_record.json @@ -0,0 +1,19 @@ +{ + "name": "LOCAL_EXPORTENTRY_RECORD", + "offsets": [ + { + "name": "ExportName", + "offset": 0, + "size": 8 + }, + { + "name": "LocalName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/machine_code_object.json b/ecmascript/js_type_metadata/machine_code_object.json new file mode 100644 index 0000000000000000000000000000000000000000..70afbcc10333e1597fbae66cc033c96f2e678bb6 --- /dev/null +++ b/ecmascript/js_type_metadata/machine_code_object.json @@ -0,0 +1,8 @@ +{ + "name": "MACHINE_CODE_OBJECT", + "offsets": [], + "end_offset": 312, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/marker_cell.json b/ecmascript/js_type_metadata/marker_cell.json new file mode 100644 index 0000000000000000000000000000000000000000..f9d5a5f2c6dbca8ddcf52255d13d02243b3a5626 --- /dev/null +++ b/ecmascript/js_type_metadata/marker_cell.json @@ -0,0 +1,8 @@ +{ + "name": "MARKER_CELL", + "offsets": [], + "end_offset": 8, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/method.json b/ecmascript/js_type_metadata/method.json new file mode 100644 index 0000000000000000000000000000000000000000..4195866a418380ecd8403fdad15f1b37fce5c751 --- /dev/null +++ b/ecmascript/js_type_metadata/method.json @@ -0,0 +1,14 @@ +{ + "name": "METHOD", + "offsets": [ + { + "name": "ConstantPool", + "offset": 0, + "size": 8 + } + ], + "end_offset": 48, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/micro_job_queue.json b/ecmascript/js_type_metadata/micro_job_queue.json new file mode 100644 index 0000000000000000000000000000000000000000..aca34378a880761bc22bd789d583d7c18f368ed2 --- /dev/null +++ b/ecmascript/js_type_metadata/micro_job_queue.json @@ -0,0 +1,19 @@ +{ + "name": "MICRO_JOB_QUEUE", + "offsets": [ + { + "name": "PromiseJobQueue", + "offset": 0, + "size": 8 + }, + { + "name": "ScriptJobQueue", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/module_record.json b/ecmascript/js_type_metadata/module_record.json new file mode 100644 index 0000000000000000000000000000000000000000..6c1d82caa8e2d1381c9d5f4f02edc1bfdcf1e41d --- /dev/null +++ b/ecmascript/js_type_metadata/module_record.json @@ -0,0 +1,8 @@ +{ + "name": "MODULE_RECORD", + "offsets": [], + "end_offset": 0, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/mutant_tagged_array.json b/ecmascript/js_type_metadata/mutant_tagged_array.json new file mode 100644 index 0000000000000000000000000000000000000000..e118144210baa29bf1ff435b59ef4705b7e2755f --- /dev/null +++ b/ecmascript/js_type_metadata/mutant_tagged_array.json @@ -0,0 +1,8 @@ +{ + "name": "MUTANT_TAGGED_ARRAY", + "offsets": [], + "end_offset": 0, + "parents": [ + "TAGGED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/native_module_failure_info.json b/ecmascript/js_type_metadata/native_module_failure_info.json new file mode 100644 index 0000000000000000000000000000000000000000..3a77dabc9d987c00315025c7d43f0a8a191b8bb8 --- /dev/null +++ b/ecmascript/js_type_metadata/native_module_failure_info.json @@ -0,0 +1,14 @@ +{ + "name": "NATIVE_MODULE_FAILURE_INFO", + "offsets": [ + { + "name": "ArkNativeModuleFailureInfo", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "JS_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/pending_job.json b/ecmascript/js_type_metadata/pending_job.json new file mode 100644 index 0000000000000000000000000000000000000000..e62d742c76bedabe5bf5d7c3bd8b99b48345bf0a --- /dev/null +++ b/ecmascript/js_type_metadata/pending_job.json @@ -0,0 +1,19 @@ +{ + "name": "PENDING_JOB", + "offsets": [ + { + "name": "Job", + "offset": 0, + "size": 8 + }, + { + "name": "Arguments", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/profile_type_info.json b/ecmascript/js_type_metadata/profile_type_info.json new file mode 100644 index 0000000000000000000000000000000000000000..a9b8f37728992075b2d0d1fc7b2599aea293f55e --- /dev/null +++ b/ecmascript/js_type_metadata/profile_type_info.json @@ -0,0 +1,8 @@ +{ + "name": "PROFILE_TYPE_INFO", + "offsets": [], + "end_offset": 0, + "parents": [ + "TAGGED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/profile_type_info_cell_0.json b/ecmascript/js_type_metadata/profile_type_info_cell_0.json new file mode 100644 index 0000000000000000000000000000000000000000..0dc65df6c6053f14c91140cece0ff0000e584996 --- /dev/null +++ b/ecmascript/js_type_metadata/profile_type_info_cell_0.json @@ -0,0 +1,24 @@ +{ + "name": "PROFILE_TYPE_INFO_CELL_0", + "offsets": [ + { + "name": "Value", + "offset": 0, + "size": 8 + }, + { + "name": "MachineCode", + "offset": 8, + "size": 8 + }, + { + "name": "Handle", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/profile_type_info_cell_1.json b/ecmascript/js_type_metadata/profile_type_info_cell_1.json new file mode 100644 index 0000000000000000000000000000000000000000..63d04f3254eb53237da84ec2baa5908682e85629 --- /dev/null +++ b/ecmascript/js_type_metadata/profile_type_info_cell_1.json @@ -0,0 +1,24 @@ +{ + "name": "PROFILE_TYPE_INFO_CELL_1", + "offsets": [ + { + "name": "Value", + "offset": 0, + "size": 8 + }, + { + "name": "MachineCode", + "offset": 8, + "size": 8 + }, + { + "name": "Handle", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/profile_type_info_cell_n.json b/ecmascript/js_type_metadata/profile_type_info_cell_n.json new file mode 100644 index 0000000000000000000000000000000000000000..cc6ae0dee3a199eb339dc6a535d7e222bee7d99c --- /dev/null +++ b/ecmascript/js_type_metadata/profile_type_info_cell_n.json @@ -0,0 +1,24 @@ +{ + "name": "PROFILE_TYPE_INFO_CELL_N", + "offsets": [ + { + "name": "Value", + "offset": 0, + "size": 8 + }, + { + "name": "MachineCode", + "offset": 8, + "size": 8 + }, + { + "name": "Handle", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/program.json b/ecmascript/js_type_metadata/program.json new file mode 100644 index 0000000000000000000000000000000000000000..a0b1897edf1bbc1419d12e8d9affacedcd4e5ac7 --- /dev/null +++ b/ecmascript/js_type_metadata/program.json @@ -0,0 +1,14 @@ +{ + "name": "PROGRAM", + "offsets": [ + { + "name": "MainFunction", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "ECMA_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/promise_capability.json b/ecmascript/js_type_metadata/promise_capability.json new file mode 100644 index 0000000000000000000000000000000000000000..b72c600ce699ed2b4f958e444b141172af2cb651 --- /dev/null +++ b/ecmascript/js_type_metadata/promise_capability.json @@ -0,0 +1,24 @@ +{ + "name": "PROMISE_CAPABILITY", + "offsets": [ + { + "name": "Promise", + "offset": 0, + "size": 8 + }, + { + "name": "Resolve", + "offset": 8, + "size": 8 + }, + { + "name": "Reject", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/promise_iterator_record.json b/ecmascript/js_type_metadata/promise_iterator_record.json new file mode 100644 index 0000000000000000000000000000000000000000..b1d84971cae5514123056e8050deb012a6b86686 --- /dev/null +++ b/ecmascript/js_type_metadata/promise_iterator_record.json @@ -0,0 +1,14 @@ +{ + "name": "PROMISE_ITERATOR_RECORD", + "offsets": [ + { + "name": "Iterator", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/promise_reactions.json b/ecmascript/js_type_metadata/promise_reactions.json new file mode 100644 index 0000000000000000000000000000000000000000..030bdc792175eae19ef2f322b9af7751a3ac2ebf --- /dev/null +++ b/ecmascript/js_type_metadata/promise_reactions.json @@ -0,0 +1,19 @@ +{ + "name": "PROMISE_REACTIONS", + "offsets": [ + { + "name": "PromiseCapability", + "offset": 0, + "size": 8 + }, + { + "name": "Handler", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/promise_record.json b/ecmascript/js_type_metadata/promise_record.json new file mode 100644 index 0000000000000000000000000000000000000000..38249d6253dd9c24d881f426a4cdbf762a36e03c --- /dev/null +++ b/ecmascript/js_type_metadata/promise_record.json @@ -0,0 +1,14 @@ +{ + "name": "PROMISE_RECORD", + "offsets": [ + { + "name": "Value", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/property_box.json b/ecmascript/js_type_metadata/property_box.json new file mode 100644 index 0000000000000000000000000000000000000000..d4fdeaf90c8fcdd97b13de3831af61f2a557ab61 --- /dev/null +++ b/ecmascript/js_type_metadata/property_box.json @@ -0,0 +1,14 @@ +{ + "name": "PROPERTY_BOX", + "offsets": [ + { + "name": "Value", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/proto_change_marker.json b/ecmascript/js_type_metadata/proto_change_marker.json new file mode 100644 index 0000000000000000000000000000000000000000..2e2da67077f3e6c22fd2b1b6cc9ecc0c1bd888f0 --- /dev/null +++ b/ecmascript/js_type_metadata/proto_change_marker.json @@ -0,0 +1,8 @@ +{ + "name": "PROTO_CHANGE_MARKER", + "offsets": [], + "end_offset": 8, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/prototype_handler.json b/ecmascript/js_type_metadata/prototype_handler.json new file mode 100644 index 0000000000000000000000000000000000000000..42b4d1b5fc811f54fd66df8316909d9a0eece46f --- /dev/null +++ b/ecmascript/js_type_metadata/prototype_handler.json @@ -0,0 +1,29 @@ +{ + "name": "PROTOTYPE_HANDLER", + "offsets": [ + { + "name": "HandlerInfo", + "offset": 0, + "size": 8 + }, + { + "name": "ProtoCell", + "offset": 8, + "size": 8 + }, + { + "name": "Holder", + "offset": 16, + "size": 8 + }, + { + "name": "AccessorJSFunction", + "offset": 24, + "size": 8 + } + ], + "end_offset": 40, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/prototype_info.json b/ecmascript/js_type_metadata/prototype_info.json new file mode 100644 index 0000000000000000000000000000000000000000..62f6a33b80a035694d724d0ecd93cbce37eaf281 --- /dev/null +++ b/ecmascript/js_type_metadata/prototype_info.json @@ -0,0 +1,14 @@ +{ + "name": "PROTOTYPE_INFO", + "offsets": [ + { + "name": "ChangeListener", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/rb_treenode.json b/ecmascript/js_type_metadata/rb_treenode.json new file mode 100644 index 0000000000000000000000000000000000000000..f77298e4d075d34cb701efe702ab8e7b8004b67c --- /dev/null +++ b/ecmascript/js_type_metadata/rb_treenode.json @@ -0,0 +1,24 @@ +{ + "name": "RB_TREENODE", + "offsets": [ + { + "name": "Left", + "offset": 0, + "size": 8 + }, + { + "name": "Right", + "offset": 8, + "size": 8 + }, + { + "name": "IsRed", + "offset": 16, + "size": 8 + } + ], + "end_offset": 32, + "parents": [ + "TAGGED_NODE" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/record.json b/ecmascript/js_type_metadata/record.json new file mode 100644 index 0000000000000000000000000000000000000000..3bcf47d3257e76f1d2040a8ae8893c8931054549 --- /dev/null +++ b/ecmascript/js_type_metadata/record.json @@ -0,0 +1,8 @@ +{ + "name": "RECORD", + "offsets": [], + "end_offset": 0, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/resolvedbinding_record.json b/ecmascript/js_type_metadata/resolvedbinding_record.json new file mode 100644 index 0000000000000000000000000000000000000000..89155f112b4d213003da455065a3f62a040477e4 --- /dev/null +++ b/ecmascript/js_type_metadata/resolvedbinding_record.json @@ -0,0 +1,19 @@ +{ + "name": "RESOLVEDBINDING_RECORD", + "offsets": [ + { + "name": "Module", + "offset": 0, + "size": 8 + }, + { + "name": "BindingName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/resolvedindexbinding_record.json b/ecmascript/js_type_metadata/resolvedindexbinding_record.json new file mode 100644 index 0000000000000000000000000000000000000000..ae3a5dcf283549adedbd65cf7478dd137baa5346 --- /dev/null +++ b/ecmascript/js_type_metadata/resolvedindexbinding_record.json @@ -0,0 +1,19 @@ +{ + "name": "RESOLVEDINDEXBINDING_RECORD", + "offsets": [ + { + "name": "Module", + "offset": 0, + "size": 8 + }, + { + "name": "Index", + "offset": 8, + "size": 4 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/resolvedrecordbinding_record.json b/ecmascript/js_type_metadata/resolvedrecordbinding_record.json new file mode 100644 index 0000000000000000000000000000000000000000..efeae4e21dcd491901fdd7860b8633e9c59d5692 --- /dev/null +++ b/ecmascript/js_type_metadata/resolvedrecordbinding_record.json @@ -0,0 +1,19 @@ +{ + "name": "RESOLVEDRECORDBINDING_RECORD", + "offsets": [ + { + "name": "ModuleRecord", + "offset": 0, + "size": 8 + }, + { + "name": "BindingName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/resolvedrecordindexbinding_record.json b/ecmascript/js_type_metadata/resolvedrecordindexbinding_record.json new file mode 100644 index 0000000000000000000000000000000000000000..25c9fe98a06446285e6f8021cf5522671c02200a --- /dev/null +++ b/ecmascript/js_type_metadata/resolvedrecordindexbinding_record.json @@ -0,0 +1,19 @@ +{ + "name": "RESOLVEDRECORDINDEXBINDING_RECORD", + "offsets": [ + { + "name": "ModuleRecord", + "offset": 0, + "size": 8 + }, + { + "name": "AbcFileName", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/resolving_functions_record.json b/ecmascript/js_type_metadata/resolving_functions_record.json new file mode 100644 index 0000000000000000000000000000000000000000..51a76e4ffdb10669efe8c2e37bf29e7870399090 --- /dev/null +++ b/ecmascript/js_type_metadata/resolving_functions_record.json @@ -0,0 +1,19 @@ +{ + "name": "RESOLVING_FUNCTIONS_RECORD", + "offsets": [ + { + "name": "ResolveFunction", + "offset": 0, + "size": 8 + }, + { + "name": "RejectFunction", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/sendable_env.json b/ecmascript/js_type_metadata/sendable_env.json new file mode 100644 index 0000000000000000000000000000000000000000..c9f97907730e0f1ae153636686c0b49c18e20560 --- /dev/null +++ b/ecmascript/js_type_metadata/sendable_env.json @@ -0,0 +1,8 @@ +{ + "name": "SENDABLE_ENV", + "offsets": [], + "end_offset": 0, + "parents": [ + "TAGGED_ARRAY" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/sliced_string.json b/ecmascript/js_type_metadata/sliced_string.json new file mode 100644 index 0000000000000000000000000000000000000000..a62b8cf9f7f54b095d7b36329c1e9a1ac2486d2f --- /dev/null +++ b/ecmascript/js_type_metadata/sliced_string.json @@ -0,0 +1,14 @@ +{ + "name": "SLICED_STRING", + "offsets": [ + { + "name": "Parent", + "offset": 0, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "ECMA_STRING" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/source_text_module_record.json b/ecmascript/js_type_metadata/source_text_module_record.json new file mode 100644 index 0000000000000000000000000000000000000000..d892e22b8098e81e42a82eb7eada6de7b3eed354 --- /dev/null +++ b/ecmascript/js_type_metadata/source_text_module_record.json @@ -0,0 +1,69 @@ +{ + "name": "SOURCE_TEXT_MODULE_RECORD", + "offsets": [ + { + "name": "Environment", + "offset": 0, + "size": 8 + }, + { + "name": "Namespace", + "offset": 8, + "size": 8 + }, + { + "name": "RequestedModules", + "offset": 16, + "size": 8 + }, + { + "name": "ImportEntries", + "offset": 24, + "size": 8 + }, + { + "name": "LocalExportEntries", + "offset": 32, + "size": 8 + }, + { + "name": "IndirectExportEntries", + "offset": 40, + "size": 8 + }, + { + "name": "StarExportEntries", + "offset": 48, + "size": 8 + }, + { + "name": "NameDictionary", + "offset": 56, + "size": 8 + }, + { + "name": "CycleRoot", + "offset": 64, + "size": 8 + }, + { + "name": "TopLevelCapability", + "offset": 72, + "size": 8 + }, + { + "name": "AsyncParentModules", + "offset": 80, + "size": 8 + }, + { + "name": "SendableEnv", + "offset": 88, + "size": 8 + } + ], + "end_offset": 144, + "parents": [ + "MODULE_RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/star_exportentry_record.json b/ecmascript/js_type_metadata/star_exportentry_record.json new file mode 100644 index 0000000000000000000000000000000000000000..1418ca7a0412872ee3e65da96ac5155fc6d25a19 --- /dev/null +++ b/ecmascript/js_type_metadata/star_exportentry_record.json @@ -0,0 +1,14 @@ +{ + "name": "STAR_EXPORTENTRY_RECORD", + "offsets": [ + { + "name": "ModuleRequest", + "offset": 0, + "size": 8 + } + ], + "end_offset": 8, + "parents": [ + "RECORD" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/store_ts_handler.json b/ecmascript/js_type_metadata/store_ts_handler.json new file mode 100644 index 0000000000000000000000000000000000000000..35f5109d774fab8bce2ab6dbdc05011258cde4dc --- /dev/null +++ b/ecmascript/js_type_metadata/store_ts_handler.json @@ -0,0 +1,24 @@ +{ + "name": "STORE_TS_HANDLER", + "offsets": [ + { + "name": "HandlerInfo", + "offset": 0, + "size": 8 + }, + { + "name": "ProtoCell", + "offset": 8, + "size": 8 + }, + { + "name": "Holder", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/symbol.json b/ecmascript/js_type_metadata/symbol.json new file mode 100644 index 0000000000000000000000000000000000000000..b67aaf13f762a77c26069172bd4b9d6e7bd5b1a9 --- /dev/null +++ b/ecmascript/js_type_metadata/symbol.json @@ -0,0 +1,14 @@ +{ + "name": "SYMBOL", + "offsets": [ + { + "name": "Description", + "offset": 0, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/tagged_array.json b/ecmascript/js_type_metadata/tagged_array.json new file mode 100644 index 0000000000000000000000000000000000000000..519b8992d9889212e6e20ff546af7a99f533f4eb --- /dev/null +++ b/ecmascript/js_type_metadata/tagged_array.json @@ -0,0 +1,20 @@ +{ + "name": "TAGGED_ARRAY", + "offsets": [ + { + "name": "Length", + "offset": 0, + "size": 4 + }, + { + "name": "Data", + "offset": 8, + "size": 8 + } + ], + "end_offset": 0, + "parents": [ + "TAGGED_OBJECT" + ], + "visit_type": "Array" +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/tagged_dictionary.json b/ecmascript/js_type_metadata/tagged_dictionary.json new file mode 100644 index 0000000000000000000000000000000000000000..756db47c30d1213608007c0090d12ac24dcd85a3 --- /dev/null +++ b/ecmascript/js_type_metadata/tagged_dictionary.json @@ -0,0 +1 @@ +{"name": "TAGGED_DICTIONARY", "offsets": [], "end_offset": 8, "parents": ["TAGGED_ARRAY"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/tagged_node.json b/ecmascript/js_type_metadata/tagged_node.json new file mode 100644 index 0000000000000000000000000000000000000000..4edf6efca6f9118e37b64427af6e8cc9c9e7bb79 --- /dev/null +++ b/ecmascript/js_type_metadata/tagged_node.json @@ -0,0 +1,24 @@ +{ + "name": "TAGGED_NODE", + "offsets": [ + { + "name": "Hash", + "offset": 0, + "size": 8 + }, + { + "name": "Key", + "offset": 8, + "size": 8 + }, + { + "name": "Value", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/tagged_object.json b/ecmascript/js_type_metadata/tagged_object.json new file mode 100644 index 0000000000000000000000000000000000000000..b3ff6ecb1e6491a3e0b29a6efc199cf16bbc25d2 --- /dev/null +++ b/ecmascript/js_type_metadata/tagged_object.json @@ -0,0 +1 @@ +{"name": "TAGGED_OBJECT", "offsets": [], "end_offset": 8, "parents": []} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/template_map.json b/ecmascript/js_type_metadata/template_map.json new file mode 100644 index 0000000000000000000000000000000000000000..591f518674c0d7187f55a89a7e683b20e9fcf713 --- /dev/null +++ b/ecmascript/js_type_metadata/template_map.json @@ -0,0 +1 @@ +{"name": "TEMPLATE_MAP", "offsets": [], "end_offset": 8, "parents": ["TAGGED_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/track_info.json b/ecmascript/js_type_metadata/track_info.json new file mode 100644 index 0000000000000000000000000000000000000000..4398ea12d178029978a1b9ebd8e328686dc7fe1c --- /dev/null +++ b/ecmascript/js_type_metadata/track_info.json @@ -0,0 +1,19 @@ +{ + "name": "TRACK_INFO", + "offsets": [ + { + "name": "CachedHClass", + "offset": 0, + "size": 8 + }, + { + "name": "CachedFunc", + "offset": 8, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/trans_with_proto_handler.json b/ecmascript/js_type_metadata/trans_with_proto_handler.json new file mode 100644 index 0000000000000000000000000000000000000000..88742c840046319fdbcf77e04815048ba336734b --- /dev/null +++ b/ecmascript/js_type_metadata/trans_with_proto_handler.json @@ -0,0 +1,24 @@ +{ + "name": "TRANS_WITH_PROTO_HANDLER", + "offsets": [ + { + "name": "HandlerInfo", + "offset": 0, + "size": 8 + }, + { + "name": "TransitionHClass", + "offset": 8, + "size": 8 + }, + { + "name": "ProtoCell", + "offset": 16, + "size": 8 + } + ], + "end_offset": 24, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/transition_handler.json b/ecmascript/js_type_metadata/transition_handler.json new file mode 100644 index 0000000000000000000000000000000000000000..e9a7dc3bc568e451dda1dd6a9faa554f2d2e8216 --- /dev/null +++ b/ecmascript/js_type_metadata/transition_handler.json @@ -0,0 +1,19 @@ +{ + "name": "TRANSITION_HANDLER", + "offsets": [ + { + "name": "HandlerInfo", + "offset": 0, + "size": 8 + }, + { + "name": "TransitionHClass", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "TAGGED_OBJECT" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/tree_string.json b/ecmascript/js_type_metadata/tree_string.json new file mode 100644 index 0000000000000000000000000000000000000000..74648135547ab63534aadc869fe49cb4293d3b1f --- /dev/null +++ b/ecmascript/js_type_metadata/tree_string.json @@ -0,0 +1,19 @@ +{ + "name": "TREE_STRING", + "offsets": [ + { + "name": "First", + "offset": 0, + "size": 8 + }, + { + "name": "Second", + "offset": 8, + "size": 8 + } + ], + "end_offset": 16, + "parents": [ + "ECMA_STRING" + ] +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/type_enums.json b/ecmascript/js_type_metadata/type_enums.json new file mode 100644 index 0000000000000000000000000000000000000000..c8ad11d1a6320c5ff86b58c63d6a63926e03ecea --- /dev/null +++ b/ecmascript/js_type_metadata/type_enums.json @@ -0,0 +1,217 @@ +{ + "type_enum": { + "INVALID":8, + "JS_OBJECT":3, + "JS_SHARED_OBJECT":3, + "JS_REALM":8, + "JS_FUNCTION_BASE":8, + "JS_FUNCTION":5, + "JS_SHARED_FUNCTION":5, + "JS_PROXY_REVOC_FUNCTION":5, + "JS_PROMISE_REACTIONS_FUNCTION":5, + "JS_PROMISE_EXECUTOR_FUNCTION":5, + "JS_ASYNC_MODULE_FULFILLED_FUNCTION":5, + "JS_ASYNC_MODULE_REJECTED_FUNCTION":5, + "JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION":5, + "JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION":5, + "JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN":5, + "JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION":5, + "JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION":5, + "JS_PROMISE_FINALLY_FUNCTION":5, + "JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION":5, + "JS_GENERATOR_FUNCTION":5, + "JS_ASYNC_GENERATOR_FUNCTION":5, + "JS_ASYNC_FUNCTION":5, + "JS_SHARED_ASYNC_FUNCTION":5, + "JS_INTL_BOUND_FUNCTION":5, + "JS_ASYNC_AWAIT_STATUS_FUNCTION":5, + "JS_BOUND_FUNCTION":8, + "JS_ERROR":8, + "JS_EVAL_ERROR":8, + "JS_RANGE_ERROR":8, + "JS_REFERENCE_ERROR":8, + "JS_TYPE_ERROR":8, + "JS_AGGREGATE_ERROR":8, + "JS_URI_ERROR":8, + "JS_SYNTAX_ERROR":8, + "JS_OOM_ERROR":8, + "JS_TERMINATION_ERROR":8, + "JS_REG_EXP":6, + "JS_SET":8, + "JS_SHARED_SET":8, + "JS_MAP":8, + "JS_SHARED_MAP":8, + "JS_WEAK_MAP":8, + "JS_WEAK_SET":8, + "JS_WEAK_REF":8, + "JS_FINALIZATION_REGISTRY":8, + "JS_DATE":8, + "JS_ITERATOR":8, + "JS_ASYNCITERATOR":8, + "JS_ASYNC_FROM_SYNC_ITERATOR":8, + "JS_FORIN_ITERATOR":8, + "JS_MAP_ITERATOR":8, + "JS_SHARED_MAP_ITERATOR":8, + "JS_SET_ITERATOR":8, + "JS_SHARED_SET_ITERATOR":8, + "JS_REG_EXP_ITERATOR":8, + "JS_API_ARRAYLIST_ITERATOR":8, + "JS_API_DEQUE_ITERATOR":8, + "JS_API_HASHMAP_ITERATOR":8, + "JS_API_HASHSET_ITERATOR":8, + "JS_API_LIGHT_WEIGHT_MAP_ITERATOR":8, + "JS_API_LIGHT_WEIGHT_SET_ITERATOR":8, + "JS_API_PLAIN_ARRAY_ITERATOR":8, + "JS_API_QUEUE_ITERATOR":8, + "JS_API_STACK_ITERATOR":8, + "JS_API_TREEMAP_ITERATOR":8, + "JS_API_TREESET_ITERATOR":8, + "JS_API_VECTOR_ITERATOR":8, + "JS_API_BITVECTOR_ITERATOR":8, + "JS_API_LINKED_LIST_ITERATOR":8, + "JS_API_LIST_ITERATOR":8, + "JS_ARRAY_ITERATOR":8, + "JS_SHARED_ARRAY_ITERATOR":8, + "JS_SEGMENT_ITERATOR":8, + "JS_STRING_ITERATOR":8, + "JS_INTL":8, + "JS_LOCALE":8, + "JS_DATE_TIME_FORMAT":8, + "JS_RELATIVE_TIME_FORMAT":8, + "JS_NUMBER_FORMAT":8, + "JS_COLLATOR":8, + "JS_PLURAL_RULES":8, + "JS_DISPLAYNAMES":8, + "JS_LIST_FORMAT":8, + "JS_SEGMENTER":8, + "JS_SEGMENTS":8, + "JS_ARRAY_BUFFER":8, + "JS_SHARED_ARRAY_BUFFER":8, + "JS_SENDABLE_ARRAY_BUFFER":8, + "JS_PROMISE":8, + "JS_DATA_VIEW":8, + "JS_ARGUMENTS":8, + "JS_GENERATOR_OBJECT":8, + "JS_ASYNC_GENERATOR_OBJECT":8, + "JS_ASYNC_FUNC_OBJECT":8, + "JS_ARRAY":3, + "JS_SHARED_ARRAY":8, + "JS_API_ARRAY_LIST":8, + "JS_API_LIGHT_WEIGHT_MAP":8, + "JS_API_LIGHT_WEIGHT_SET":8, + "JS_API_VECTOR":8, + "JS_API_BITVECTOR":8, + "JS_API_LINKED_LIST":8, + "JS_API_LIST":8, + "JS_API_HASH_MAP":8, + "JS_API_HASH_SET":8, + "JS_API_TREE_MAP":8, + "JS_API_TREE_SET":8, + "JS_API_DEQUE":8, + "JS_API_STACK":8, + "JS_API_PLAIN_ARRAY":8, + "JS_API_QUEUE":8, + "JS_TYPED_ARRAY":3, + "JS_INT8_ARRAY":8, + "JS_UINT8_ARRAY":8, + "JS_UINT8_CLAMPED_ARRAY":8, + "JS_INT16_ARRAY":8, + "JS_UINT16_ARRAY":8, + "JS_INT32_ARRAY":8, + "JS_UINT32_ARRAY":8, + "JS_FLOAT32_ARRAY":8, + "JS_FLOAT64_ARRAY":8, + "JS_BIGINT64_ARRAY":8, + "JS_BIGUINT64_ARRAY":8, + "JS_SHARED_TYPED_ARRAY":8, + "JS_SHARED_INT8_ARRAY":8, + "JS_SHARED_UINT8_ARRAY":8, + "JS_SHARED_UINT8_CLAMPED_ARRAY":8, + "JS_SHARED_INT16_ARRAY":8, + "JS_SHARED_UINT16_ARRAY":8, + "JS_SHARED_INT32_ARRAY":8, + "JS_SHARED_UINT32_ARRAY":8, + "JS_SHARED_FLOAT32_ARRAY":8, + "JS_SHARED_FLOAT64_ARRAY":8, + "JS_SHARED_BIGINT64_ARRAY":8, + "JS_SHARED_BIGUINT64_ARRAY":8, + "JS_PRIMITIVE_REF":7, + "JS_MODULE_NAMESPACE":8, + "JS_CJS_MODULE":8, + "JS_CJS_EXPORTS":8, + "JS_CJS_REQUIRE":8, + "NATIVE_MODULE_FAILURE_INFO":8, + "JS_GLOBAL_OBJECT":8, + "JS_PROXY":8, + "HCLASS":8, + "LINE_STRING":2, + "CONSTANT_STRING":2, + "SLICED_STRING":2, + "TREE_STRING":2, + "BIGINT":13, + "TAGGED_ARRAY":1, + "MUTANT_TAGGED_ARRAY":1, + "BYTE_ARRAY":8, + "LEXICAL_ENV":1, + "SENDABLE_ENV":1, + "TAGGED_DICTIONARY":1, + "CONSTANT_POOL":1, + "PROFILE_TYPE_INFO":1, + "COW_MUTANT_TAGGED_ARRAY":1, + "COW_TAGGED_ARRAY":1, + "LINKED_NODE":8, + "RB_TREENODE":8, + "FREE_OBJECT_WITH_ONE_FIELD":8, + "FREE_OBJECT_WITH_NONE_FIELD":8, + "FREE_OBJECT_WITH_TWO_FIELD":8, + "JS_NATIVE_POINTER":8, + "GLOBAL_ENV":8, + "ACCESSOR_DATA":8, + "INTERNAL_ACCESSOR":8, + "SYMBOL":12, + "JS_GENERATOR_CONTEXT":8, + "PROTOTYPE_HANDLER":8, + "TRANSITION_HANDLER":8, + "TRANS_WITH_PROTO_HANDLER":8, + "STORE_TS_HANDLER":8, + "PROPERTY_BOX":8, + "PROTO_CHANGE_MARKER":8, + "MARKER_CELL":8, + "TRACK_INFO":8, + "PROTOTYPE_INFO":8, + "TEMPLATE_MAP":8, + "PROGRAM":8, + "METHOD":8, + "CLASS_LITERAL":8, + "PROMISE_CAPABILITY":8, + "PROMISE_RECORD":8, + "RESOLVING_FUNCTIONS_RECORD":8, + "PROMISE_REACTIONS":8, + "ASYNC_GENERATOR_REQUEST":8, + "ASYNC_ITERATOR_RECORD":8, + "PROMISE_ITERATOR_RECORD":8, + "MICRO_JOB_QUEUE":8, + "PENDING_JOB":8, + "MODULE_RECORD":8, + "SOURCE_TEXT_MODULE_RECORD":8, + "IMPORTENTRY_RECORD":8, + "LOCAL_EXPORTENTRY_RECORD":8, + "INDIRECT_EXPORTENTRY_RECORD":8, + "STAR_EXPORTENTRY_RECORD":8, + "RESOLVEDBINDING_RECORD":8, + "RESOLVEDINDEXBINDING_RECORD":8, + "RESOLVEDRECORDINDEXBINDING_RECORD":8, + "RESOLVEDRECORDBINDING_RECORD":8, + "CELL_RECORD":8, + "COMPLETION_RECORD":8, + "MACHINE_CODE_OBJECT":8, + "CLASS_INFO_EXTRACTOR":8, + "PROFILE_TYPE_INFO_CELL_0":8, + "PROFILE_TYPE_INFO_CELL_1":8, + "PROFILE_TYPE_INFO_CELL_N":8, + "EXTRA_PROFILE_TYPE_INFO":8, + "FUNCTION_TEMPLATE":8, + "VTABLE":1, + "AOT_LITERAL_INFO":1 + } +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/type_range.json b/ecmascript/js_type_metadata/type_range.json new file mode 100644 index 0000000000000000000000000000000000000000..5a5984747fd68733b36701a6090252001bbf28d4 --- /dev/null +++ b/ecmascript/js_type_metadata/type_range.json @@ -0,0 +1,6 @@ +{ + "string_first": "LINE_STRING", + "string_last": "TREE_STRING", + "js_object_first": "JS_OBJECT", + "js_object_last": "JS_GLOBAL_OBJECT" +} \ No newline at end of file diff --git a/ecmascript/js_type_metadata/vtable.json b/ecmascript/js_type_metadata/vtable.json new file mode 100644 index 0000000000000000000000000000000000000000..01a78d526595f54fa1cfdda64e4b83c859c342b1 --- /dev/null +++ b/ecmascript/js_type_metadata/vtable.json @@ -0,0 +1 @@ +{"name": "VTABLE", "offsets": [], "end_offset": 8, "parents": ["TAGGED_OBJECT"]} \ No newline at end of file diff --git a/ecmascript/js_typed_array.cpp b/ecmascript/js_typed_array.cpp index 70db6dea1d8887e9d821458ce32a0d6de0b7fe35..f49c8c2b3b98498e56c41a871cfe26715591caa0 100644 --- a/ecmascript/js_typed_array.cpp +++ b/ecmascript/js_typed_array.cpp @@ -429,7 +429,10 @@ OperationResult JSTypedArray::IntegerIndexedElementGet(JSThread *thread, const J // arrayTypeName. uint32_t elementSize = TypedArrayHelper::GetElementSize(typedarrayObj); // 12. Let indexedPosition = (index × elementSize) + offset. - uint32_t k = static_cast(JSTaggedValue::ToInteger(thread, indexHandle).ToInt32()); + JSTaggedNumber integerValue = JSTaggedValue::ToInteger(thread, indexHandle); + RETURN_VALUE_IF_ABRUPT_COMPLETION( + thread, OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + uint32_t k = static_cast(integerValue.ToInt32()); uint32_t byteIndex = k * elementSize + offset; // 13. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName. DataViewType elementType = TypedArrayHelper::GetType(typedarrayObj); @@ -628,7 +631,9 @@ bool JSTypedArray::IntegerIndexedElementSet(JSThread *thread, const JSHandleGetArrayLength(); diff --git a/ecmascript/jspandafile/class_info_extractor.cpp b/ecmascript/jspandafile/class_info_extractor.cpp index 58a74ca496cb0603768d4a58f3f0370cda064fdc..4a9937609d0da2b2de623db68331b9b3b1b60ff3 100644 --- a/ecmascript/jspandafile/class_info_extractor.cpp +++ b/ecmascript/jspandafile/class_info_extractor.cpp @@ -15,6 +15,7 @@ #include "ecmascript/jspandafile/class_info_extractor.h" +#include "ecmascript/js_api/js_api_bitvector.h" #include "ecmascript/js_object-inl.h" #include "ecmascript/jspandafile/program_object.h" #include "ecmascript/shared_objects/js_sendable_arraybuffer.h" @@ -1179,6 +1180,8 @@ std::pair SendableClassDefiner::GetSizeAndMaxInlineByType(JS return { JSSharedSet::SIZE, JSSharedSet::MAX_INLINE }; case JSType::JS_SENDABLE_ARRAY_BUFFER: return { JSSendableArrayBuffer::SIZE, JSSendableArrayBuffer::MAX_INLINE }; + case JSType::JS_API_BITVECTOR: + return { JSAPIBitVector::SIZE, JSAPIBitVector::MAX_INLINE }; default: if (JSType::JS_SHARED_TYPED_ARRAY_FIRST < type && type <= JSType::JS_SHARED_TYPED_ARRAY_LAST) { return { JSSharedTypedArray::SIZE, JSSharedTypedArray::MAX_INLINE }; diff --git a/ecmascript/jspandafile/js_pandafile.cpp b/ecmascript/jspandafile/js_pandafile.cpp index b81d4c2e1a8d4590ce4b949f19cf2d29dba9d93a..ee7100c998e1a5b478b6b341fb977aa620aa6bae 100644 --- a/ecmascript/jspandafile/js_pandafile.cpp +++ b/ecmascript/jspandafile/js_pandafile.cpp @@ -103,7 +103,13 @@ JSPandaFile::~JSPandaFile() methodLiteralMap_.clear(); ClearNameMap(); if (methodLiterals_ != nullptr) { - JSPandaFileManager::FreeBuffer(methodLiterals_); + if (isBundlePack_) { + JSPandaFileManager::FreeBuffer(methodLiterals_); + } else { + auto size = AlignUp(sizeof(MethodLiteral) * numMethods_, PageSize()); + PageClearTag(methodLiterals_, size); + PageUnmap(MemMap(methodLiterals_, size)); + } methodLiterals_ = nullptr; } } @@ -220,8 +226,10 @@ void JSPandaFile::InitializeMergedPF() delete info; } } + auto size = AlignUp(sizeof(MethodLiteral) * numMethods_, PageSize()); methodLiterals_ = - static_cast(JSPandaFileManager::AllocateBuffer(sizeof(MethodLiteral) * numMethods_)); + static_cast(PageMap(size, PAGE_PROT_READWRITE).GetMem()); + PageTag(methodLiterals_, size, PageTagType::METHOD_LITERAL); methodLiteralMap_.reserve(numMethods_); } diff --git a/ecmascript/jspandafile/js_pandafile.h b/ecmascript/jspandafile/js_pandafile.h index 8d936bd1c542b38a77f8e1399ded8879e1cde8e7..f128c14a80e417d3eeb1fefddc16e40acbc6e351 100644 --- a/ecmascript/jspandafile/js_pandafile.h +++ b/ecmascript/jspandafile/js_pandafile.h @@ -151,7 +151,7 @@ public: methodLiteralMap_.emplace(methodLiteral->GetMethodId().GetOffset(), methodLiteral); } - const CUnorderedMap &GetMethodLiteralMap() const + const std::unordered_map &GetMethodLiteralMap() const { return methodLiteralMap_; } @@ -384,6 +384,12 @@ public: jsRecordInfo_.insert({recordName, info}); } + // note : it only uses in TDD + void InsertNpmEntries(const CString &recordName, const CString &fieldName) + { + npmEntries_.insert({recordName, fieldName}); + } + const CUnorderedMap &GetJSRecordInfo() const { return jsRecordInfo_; @@ -475,8 +481,8 @@ private: CString hapPath_; uint32_t constpoolIndex_ {0}; uint32_t checksum_ {0}; - CUnorderedMap methodLiteralMap_; - CUnorderedMap methodNameMap_; + std::unordered_map methodLiteralMap_; + std::unordered_map methodNameMap_; CUnorderedMap recordNameMap_; Mutex methodNameMapMutex_; Mutex recordNameMapMutex_; diff --git a/ecmascript/jspandafile/method_literal.h b/ecmascript/jspandafile/method_literal.h index 286d7997401f6c9d66fd78770ab885f2bf3da5b6..3249d1dde1a3bfd94e8e566f7e20815dcc90475c 100644 --- a/ecmascript/jspandafile/method_literal.h +++ b/ecmascript/jspandafile/method_literal.h @@ -19,6 +19,7 @@ #include #include "ecmascript/base/aligned_struct.h" +#include "ecmascript/compiler/builtins/builtins_call_signature.h" #include "ecmascript/js_function_kind.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/c_string.h" @@ -229,6 +230,10 @@ public: using IsSharedBit = EmptyBit::NextFlag; // offset 30 using CanTypedCall = IsSharedBit::NextFlag; // offset 31 + // one placeholder 0xffff (INVALID) in kungfu::BuiltinsStubCSigns::ID + static_assert(static_cast(kungfu::BuiltinsStubCSigns::ID::NUM_OF_BUILTINS_ID) < (1 << BUILTINID_NUM_BITS)); + static_assert(static_cast(FunctionKind::LAST_FUNCTION_KIND) <= (1 << FUNCTION_KIND_NUM_BITS)); + inline NO_THREAD_SANITIZE void SetHotnessCounter(int16_t counter) { literalInfo_ = HotnessCounterBits::Update(literalInfo_, counter); diff --git a/ecmascript/jspandafile/program_object.cpp b/ecmascript/jspandafile/program_object.cpp index f8bb9b9a43cafbb3782d6c97b63582c2643a3ae8..d4a4216907ecea976fb1fa851863b78e213b5e93 100644 --- a/ecmascript/jspandafile/program_object.cpp +++ b/ecmascript/jspandafile/program_object.cpp @@ -172,7 +172,7 @@ void ConstantPool::MergeObjectLiteralHClassCache(EcmaVM *vm, const JSHandleGet(i); // If already merged, stop to merge. - if (curValue.IsJSHClass() && JSHClass::Cast(curValue.GetTaggedObject())->IsTS()) { + if (curValue.IsJSHClass() && JSHClass::Cast(curValue.GetTaggedObject())->IsAOT()) { break; } JSHClass::Cast(newValue.GetTaggedObject())->SetPrototype(thread, prototype); diff --git a/ecmascript/jspandafile/tests/BUILD.gn b/ecmascript/jspandafile/tests/BUILD.gn index 22bca7fa5233812cc9be52859259e0e0261c52ac..1987593e101e7b318bb7341a09e38ec21502da54 100644 --- a/ecmascript/jspandafile/tests/BUILD.gn +++ b/ecmascript/jspandafile/tests/BUILD.gn @@ -90,7 +90,7 @@ foreach(filename, _test_js_file_name_) { } } -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("JSPandaFileTest") { module_out_path = module_output_path diff --git a/ecmascript/layout_info-inl.h b/ecmascript/layout_info-inl.h index 0de9fd342183fd1fb84f13a0768b48aefd5db3bf..d3cf8262a1ed9582b251235581325c2c085484fe 100644 --- a/ecmascript/layout_info-inl.h +++ b/ecmascript/layout_info-inl.h @@ -217,7 +217,6 @@ template void LayoutInfo::AddKey(const JSThread *thread, [[maybe_unused]] int index, const JSTaggedValue &key, const PropertyAttributes &attr) { - DISALLOW_GARBAGE_COLLECTION; int number = NumberOfElements(); ASSERT(attr.GetOffset() == static_cast(number)); ASSERT(number + 1 <= GetPropertiesCapacity()); diff --git a/ecmascript/layout_info.cpp b/ecmascript/layout_info.cpp index ab9fabcd5ed996ddb30bb1ebd7cb80d45a2e8bb6..5f3efce21c5c8cd5e15072d835f8245a79d75c4f 100644 --- a/ecmascript/layout_info.cpp +++ b/ecmascript/layout_info.cpp @@ -28,8 +28,7 @@ void LayoutInfo::Initialize(const JSThread *thread, int num) } } -void LayoutInfo::GetAllKeys(const JSThread *thread, int end, int offset, TaggedArray *keyArray, - const JSHandle object) +void LayoutInfo::GetAllKeys(const JSThread *thread, int end, int offset, TaggedArray *keyArray) { ASSERT(end <= NumberOfElements()); ASSERT_PRINT(offset + end <= static_cast(keyArray->GetLength()), @@ -40,9 +39,6 @@ void LayoutInfo::GetAllKeys(const JSThread *thread, int end, int offset, TaggedA for (int i = 0; i < end; i++) { JSTaggedValue key = GetKey(i); if (key.IsString()) { - if (IsUninitializedProperty(*object, i)) { - continue; - } keyArray->Set(thread, enumKeys + offset, key); enumKeys++; } @@ -59,7 +55,7 @@ void LayoutInfo::GetAllKeys(const JSThread *thread, int end, int offset, TaggedA } } void LayoutInfo::GetAllKeysByFilter(const JSThread *thread, uint32_t numberOfProps, uint32_t &keyArrayEffectivelength, - TaggedArray *keyArray, const JSHandle object, uint32_t filter) + TaggedArray *keyArray, uint32_t filter) { ASSERT(numberOfProps <= static_cast(NumberOfElements())); ASSERT_PRINT(keyArrayEffectivelength + numberOfProps <= keyArray->GetLength(), @@ -70,9 +66,6 @@ void LayoutInfo::GetAllKeysByFilter(const JSThread *thread, uint32_t numberOfPro for (uint32_t i = 0; i < numberOfProps; i++) { JSTaggedValue key = GetKey(static_cast(i)); if (key.IsString() && !(filter & NATIVE_KEY_SKIP_STRINGS)) { - if (IsUninitializedProperty(*object, i)) { - continue; - } PropertyAttributes attr = GetAttr(static_cast(i)); bool bIgnore = FilterHelper::IgnoreKeyByFilter(attr, filter); if (bIgnore) { @@ -111,7 +104,7 @@ void LayoutInfo::GetAllKeysForSerialization(int end, std::vector } } -std::pair LayoutInfo::GetNumOfEnumKeys(int end, const JSObject *object) const +std::pair LayoutInfo::GetNumOfEnumKeys(int end) const { ASSERT(end <= NumberOfElements()); uint32_t enumKeys = 0; @@ -121,9 +114,6 @@ std::pair LayoutInfo::GetNumOfEnumKeys(int end, const JSObje if (!key.IsString()) { continue; } - if (IsUninitializedProperty(object, i)) { - continue; - } if (GetAttr(i).IsEnumerable()) { enumKeys++; } else { @@ -134,8 +124,7 @@ std::pair LayoutInfo::GetNumOfEnumKeys(int end, const JSObje } void LayoutInfo::GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle keyArray, - uint32_t *keys, JSHandle shadowQueue, const JSHandle object, - int32_t lastLength) + uint32_t *keys, JSHandle shadowQueue, int32_t lastLength) { ASSERT(end <= NumberOfElements()); ASSERT_PRINT(offset <= static_cast(keyArray->GetLength()), @@ -147,9 +136,6 @@ void LayoutInfo::GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle< if (!keyHandle->IsString()) { continue; } - if (IsUninitializedProperty(*object, i)) { - continue; - } if (GetAttr(i).IsEnumerable()) { bool isDuplicated = JSObject::IsDepulicateKeys(thread, keyArray, lastLength, shadowQueue, keyHandle); if (isDuplicated) { @@ -164,8 +150,7 @@ void LayoutInfo::GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle< *keys += enumKeys; } -void LayoutInfo::GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle keyArray, - uint32_t *keys, const JSHandle object) +void LayoutInfo::GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle keyArray, uint32_t *keys) { ASSERT(end <= NumberOfElements()); ASSERT_PRINT(offset <= static_cast(keyArray->GetLength()), @@ -175,9 +160,6 @@ void LayoutInfo::GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle< for (int i = 0; i < end; i++) { keyHandle.Update(GetKey(i)); if (keyHandle->IsString() && GetAttr(i).IsEnumerable()) { - if (IsUninitializedProperty(*object, i)) { - continue; - } keyArray->Set(thread, enumKeys + offset, keyHandle); enumKeys++; } @@ -185,17 +167,6 @@ void LayoutInfo::GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle< *keys += enumKeys; } -bool LayoutInfo::IsUninitializedProperty(const JSObject *object, uint32_t index) const -{ - PropertyAttributes attr = GetAttr(index); - if (!attr.IsInlinedProps()) { - return false; - } - - JSTaggedValue val = object->GetPropertyInlinedPropsWithRep(attr.GetOffset(), attr); - return val.IsHole(); -} - CString LayoutInfo::GetSymbolKeyString(JSTaggedValue key) { auto symbol = JSSymbol::Cast(key); @@ -214,7 +185,7 @@ CString LayoutInfo::GetSymbolKeyString(JSTaggedValue key) if (str != "method") { return ""; } - return str + '_' + ToCString(id); + return str.append("_").append(ToCString(id)); } void LayoutInfo::DumpFieldIndexByPGO(int index, pgo::HClassLayoutDesc* desc) diff --git a/ecmascript/layout_info.h b/ecmascript/layout_info.h index 8a9e71d2f3353e371c45578141d523a262307864..6f15e78e3023cbba1975925c05dde4192d6a96a6 100644 --- a/ecmascript/layout_info.h +++ b/ecmascript/layout_info.h @@ -94,25 +94,19 @@ public: int FindElementWithCache(const JSThread *thread, JSHClass *cls, JSTaggedValue key, int propertiesNumber); int BinarySearch(JSTaggedValue key, int propertiesNumber); - void GetAllKeys(const JSThread *thread, int end, int offset, TaggedArray *keyArray, - const JSHandle object); + void GetAllKeys(const JSThread *thread, int end, int offset, TaggedArray *keyArray); void GetAllKeysForSerialization(int end, std::vector &keyVector); void GetAllKeysByFilter(const JSThread *thread, uint32_t numberOfProps, uint32_t &keyArrayEffectivelength, - TaggedArray *keyArray, const JSHandle object, uint32_t filter); - std::pair GetNumOfEnumKeys(int end, const JSObject *object) const; + TaggedArray *keyArray, uint32_t filter); + std::pair GetNumOfEnumKeys(int end) const; void GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle keyArray, uint32_t *keys, - JSHandle shadowQueue, const JSHandle object, - int32_t lastLength); - void GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle keyArray, uint32_t *keys, - const JSHandle object); + JSHandle shadowQueue, int32_t lastLength); + void GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle keyArray, uint32_t *keys); void DumpFieldIndexByPGO(int index, pgo::HClassLayoutDesc* desc); bool UpdateFieldIndexByPGO(int index, pgo::HClassLayoutDesc* desc); CString GetSymbolKeyString(JSTaggedValue key); DECL_DUMP() - -private: - bool IsUninitializedProperty(const JSObject* object, uint32_t index) const; }; } // namespace panda::ecmascript diff --git a/ecmascript/mem/assert_scope.h b/ecmascript/mem/assert_scope.h index 4a73c6f49a09f42bf6549aaf74a2f17338a79550..d11538e36b7281784ec06fa68966170898cd1a40 100644 --- a/ecmascript/mem/assert_scope.h +++ b/ecmascript/mem/assert_scope.h @@ -119,10 +119,6 @@ using AllowLocalToShareWeakRefHandle = AssertScopeT(0) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define CHECK_NO_HEAP_ALLOC ASSERT_PRINT(AllowHeapAlloc::IsAllowed(), "disallow execute heap alloc.") diff --git a/ecmascript/mem/barriers-inl.h b/ecmascript/mem/barriers-inl.h index 4bfd8d9e7501433c196c60905586394c36360349..f25c51ee1f411d36362107c4bd9a7d02053f063a 100644 --- a/ecmascript/mem/barriers-inl.h +++ b/ecmascript/mem/barriers-inl.h @@ -116,26 +116,27 @@ template ARK_NOINLINE bool BatchBitSet(const JSThread* thread, Region* objectRegion, JSTaggedValue* dst, size_t count); template -void Barriers::CopyObject(const JSThread* thread, JSTaggedValue* dst, JSTaggedValue* src, size_t count) +void Barriers::CopyObject(const JSThread *thread, const TaggedObject *dstObj, JSTaggedValue *dstAddr, + JSTaggedValue *srcAddr, size_t count) { // NOTE: The logic in CopyObject should be synced with WriteBarrier. // if any new feature/bugfix be added in CopyObject, it should also be added to WriteBarrier. // step 1. copy from src to dst directly. - CopyObjectPrimitive(dst, src, count); + CopyObjectPrimitive(dstAddr, srcAddr, count); if constexpr (!needWriteBarrier) { return; } // step 2. According to object region, update the corresponding bit set batch. - Region* objectRegion = Region::ObjectAddressToRange(ToUintPtr(dst)); + Region* objectRegion = Region::ObjectAddressToRange(ToUintPtr(dstObj)); if (!objectRegion->InSharedHeap()) { bool allValueNotHeap = false; if (objectRegion->InYoungSpace()) { - allValueNotHeap = BatchBitSet(thread, objectRegion, dst, count); + allValueNotHeap = BatchBitSet(thread, objectRegion, dstAddr, count); } else if (objectRegion->InGeneralOldSpace()) { - allValueNotHeap = BatchBitSet(thread, objectRegion, dst, count); + allValueNotHeap = BatchBitSet(thread, objectRegion, dstAddr, count); } else { - allValueNotHeap = BatchBitSet(thread, objectRegion, dst, count); + allValueNotHeap = BatchBitSet(thread, objectRegion, dstAddr, count); } if (allValueNotHeap) { return; @@ -148,14 +149,14 @@ void Barriers::CopyObject(const JSThread* thread, JSTaggedValue* dst, JSTaggedVa return; } for (uint32_t i = 0; i < count; i++) { - JSTaggedValue taggedValue = *(dst + i); + JSTaggedValue taggedValue = *(dstAddr + i); if (!taggedValue.IsHeapObject()) { continue; } Region* valueRegion = Region::ObjectAddressToRange(taggedValue.GetTaggedObject()); ASSERT(!objectRegion->InSharedHeap() || valueRegion->InSharedHeap()); if (marking && !valueRegion->InSharedHeap()) { - const uintptr_t slotAddr = ToUintPtr(dst) + JSTaggedValue::TaggedTypeSize() * i; + const uintptr_t slotAddr = ToUintPtr(dstAddr) + JSTaggedValue::TaggedTypeSize() * i; Barriers::Update(thread, slotAddr, objectRegion, taggedValue.GetTaggedObject(), valueRegion); // NOTE: ConcurrentMarking and SharedConcurrentMarking can be enabled at the same time, but a specific // value can't be "not shared heap" and "in SharedSweepableSpace" at the same time. So using "if - else if" diff --git a/ecmascript/mem/barriers.h b/ecmascript/mem/barriers.h index b6200f3c0513512c0b9c992c0d5a8433f04f1f3a..0a6806da0537caaf653475fcf3257d2f095629de 100644 --- a/ecmascript/mem/barriers.h +++ b/ecmascript/mem/barriers.h @@ -48,9 +48,18 @@ public: template static void SetObject(const JSThread *thread, void *obj, size_t offset, JSTaggedType value); + // dstAddr/srcAddr is the address will be copied to/from. + // It can be a derived pointer point to the middle of an object. + // + // Note: dstObj is the object address for dstAddr, it must point to the head of an object. template - static void CopyObject(const JSThread *thread, JSTaggedValue* dst, JSTaggedValue* src, size_t count); + static void CopyObject(const JSThread *thread, const TaggedObject *dstObj, JSTaggedValue *dstAddr, + JSTaggedValue *srcAddr, size_t count); + // dstAddr/srcAddr is the address will be copied to/from. + // It can be a derived pointer point to the middle of an object. + // + // Note: dstObj is the object address for dstAddr, it must point to the head of an object. template static void CopyObjectPrimitive(JSTaggedValue* dst, JSTaggedValue* src, size_t count); static void SynchronizedSetClass(const JSThread *thread, void *obj, JSTaggedType value); diff --git a/ecmascript/mem/concurrent_sweeper.cpp b/ecmascript/mem/concurrent_sweeper.cpp index 687135836f631e4b49f0204a366893020bdd6802..3eb8b931783b33e2b11dd668be6d560077f27431 100644 --- a/ecmascript/mem/concurrent_sweeper.cpp +++ b/ecmascript/mem/concurrent_sweeper.cpp @@ -28,14 +28,15 @@ ConcurrentSweeper::ConcurrentSweeper(Heap *heap, EnableConcurrentSweepType type) void ConcurrentSweeper::PostTask(bool fullGC) { if (ConcurrentSweepEnabled()) { + auto tid = heap_->GetJSThread()->GetThreadId(); if (!fullGC) { Taskpool::GetCurrentTaskpool()->PostTask( - std::make_unique(heap_->GetJSThread()->GetThreadId(), this, OLD_SPACE)); + std::make_unique(tid, this, OLD_SPACE, startSpaceType_)); } Taskpool::GetCurrentTaskpool()->PostTask( - std::make_unique(heap_->GetJSThread()->GetThreadId(), this, NON_MOVABLE)); + std::make_unique(tid, this, NON_MOVABLE, startSpaceType_)); Taskpool::GetCurrentTaskpool()->PostTask( - std::make_unique(heap_->GetJSThread()->GetThreadId(), this, MACHINE_CODE_SPACE)); + std::make_unique(tid, this, MACHINE_CODE_SPACE, startSpaceType_)); } } @@ -160,9 +161,9 @@ void ConcurrentSweeper::ClearRSetInRange(Region *current, uintptr_t freeStart, u bool ConcurrentSweeper::SweeperTask::Run([[maybe_unused]] uint32_t threadIndex) { - uint32_t 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_); + uint32_t sweepTypeNum = FREE_LIST_NUM - startSpaceType_; + for (size_t i = startSpaceType_; i < FREE_LIST_NUM; i++) { + auto type = static_cast(((i + type_) % sweepTypeNum) + startSpaceType_); sweeper_->AsyncSweepSpace(type, false); } return true; diff --git a/ecmascript/mem/concurrent_sweeper.h b/ecmascript/mem/concurrent_sweeper.h index e53f1c019d10484fae97a68ea3d11be39799cad4..6dd04b38f63d09650c5934b03086d5efd834bc56 100644 --- a/ecmascript/mem/concurrent_sweeper.h +++ b/ecmascript/mem/concurrent_sweeper.h @@ -92,8 +92,8 @@ public: private: class SweeperTask : public Task { public: - SweeperTask(int32_t id, ConcurrentSweeper *sweeper, MemSpaceType type) - : Task(id), sweeper_(sweeper), type_(type) {}; + SweeperTask(int32_t id, ConcurrentSweeper *sweeper, MemSpaceType type, MemSpaceType startSpaceType) + : Task(id), sweeper_(sweeper), type_(type), startSpaceType_(startSpaceType) {}; ~SweeperTask() override = default; bool Run(uint32_t threadIndex) override; @@ -103,6 +103,7 @@ private: private: ConcurrentSweeper *sweeper_; MemSpaceType type_; + MemSpaceType startSpaceType_; }; void AsyncSweepSpace(MemSpaceType type, bool isMain); diff --git a/ecmascript/mem/free_object_set.h b/ecmascript/mem/free_object_set.h index c5a470f35a6dbb4a861f7f51368318d58b94f115..1313a7a8e738bc5322f7d2662b69a5afcf7bbc09 100644 --- a/ecmascript/mem/free_object_set.h +++ b/ecmascript/mem/free_object_set.h @@ -22,7 +22,7 @@ #include "ecmascript/mem/jit_fort_memdesc.h" namespace panda::ecmascript { -using SetType = int32_t; +using SetType = int8_t; class FreeObject; diff --git a/ecmascript/mem/full_gc.cpp b/ecmascript/mem/full_gc.cpp index 8151d50a95fad1aed433c8c02b851c740af1f916..1b94fe786d9d699e953c916a2809d3c77e02b8bc 100644 --- a/ecmascript/mem/full_gc.cpp +++ b/ecmascript/mem/full_gc.cpp @@ -187,6 +187,7 @@ void FullGC::Finish() heap_->Resume(FULL_GC); } heap_->GetSweeper()->TryFillSweptRegion(); + heap_->SetFullMarkRequestedState(false); } bool FullGC::HasEvacuated(Region *region) diff --git a/ecmascript/mem/gc_stats.cpp b/ecmascript/mem/gc_stats.cpp index 3a332f3f57f5131e1c2c7bd4b09028d8c6924e91..57c5e522fd5694be8a3387fd1602da1c5699d6e9 100644 --- a/ecmascript/mem/gc_stats.cpp +++ b/ecmascript/mem/gc_stats.cpp @@ -433,6 +433,7 @@ void GCStats::RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason) void GCStats::RecordStatisticAfterGC() { + ASSERT(heap_ != nullptr); SetRecordData(RecordData::END_OBJ_SIZE, heap_->GetHeapObjectSize()); SetRecordData(RecordData::END_COMMIT_SIZE, heap_->GetCommittedSize()); diff --git a/ecmascript/mem/heap-inl.h b/ecmascript/mem/heap-inl.h index 9b55170fd3b371768299ddeb9179b4270395d402..17975662955b5683b2f3e81d26657ca7c76e863d 100644 --- a/ecmascript/mem/heap-inl.h +++ b/ecmascript/mem/heap-inl.h @@ -41,7 +41,7 @@ namespace panda::ecmascript { size_t oomOvershootSize = vm->GetEcmaParamConfiguration().GetOutOfMemoryOvershootSize(); \ (space)->IncreaseOutOfMemoryOvershootSize(oomOvershootSize); \ if ((space)->IsOOMDumpSpace()) { \ - DumpHeapSnapshotBeforeOOM(); \ + DumpHeapSnapshotBeforeOOM(false); \ } \ StatisticHeapDetail(); \ ThrowOutOfMemoryError(GetJSThread(), size, message); \ @@ -52,7 +52,7 @@ namespace panda::ecmascript { if (UNLIKELY((object) == nullptr)) { \ size_t oomOvershootSize = GetEcmaParamConfiguration().GetOutOfMemoryOvershootSize(); \ (space)->IncreaseOutOfMemoryOvershootSize(oomOvershootSize); \ - DumpHeapSnapshotBeforeOOM(true, thread); \ + DumpHeapSnapshotBeforeOOM(false, thread, SharedHeapOOMSource::NORMAL_ALLOCATION); \ ThrowOutOfMemoryError(thread, size, message); \ (object) = reinterpret_cast((space)->Allocate(thread, size)); \ } @@ -355,6 +355,7 @@ TaggedObject *Heap::AllocateReadOnlyOrHugeObject(JSHClass *hclass, size_t size) } else { object = reinterpret_cast(readOnlySpace_->Allocate(size)); CHECK_OBJ_AND_THROW_OOM_ERROR(object, size, readOnlySpace_, "Heap::AllocateReadOnlyOrHugeObject"); + ASSERT(object != nullptr); object->SetClass(thread_, hclass); } #if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER) @@ -436,7 +437,7 @@ TaggedObject *Heap::AllocateHugeObject(size_t size) // if allocate huge object OOM, temporarily increase space size to avoid vm crash size_t oomOvershootSize = config_.GetOutOfMemoryOvershootSize(); oldSpace_->IncreaseOutOfMemoryOvershootSize(oomOvershootSize); - DumpHeapSnapshotBeforeOOM(); + DumpHeapSnapshotBeforeOOM(false); StatisticHeapDetail(); object = reinterpret_cast(hugeObjectSpace_->Allocate(size, thread_)); ThrowOutOfMemoryError(thread_, size, "Heap::AllocateHugeObject"); @@ -495,7 +496,7 @@ TaggedObject *Heap::AllocateMachineCodeObject(JSHClass *hclass, size_t size, Mac // Jit Fort enabled ASSERT(GetEcmaVM()->GetJSOptions().GetEnableJitFort()); - if (!GetEcmaVM()->GetJSOptions().GetEnableAsyncCopyToFort() || !desc->isAsyncCompileMode) { + if (!GetEcmaVM()->GetJSOptions().GetEnableAsyncCopyToFort()) { desc->instructionsAddr = 0; if (size <= MAX_REGULAR_HEAP_OBJECT_SIZE) { // for non huge code cache obj, allocate fort space before allocating the code object @@ -534,6 +535,16 @@ uintptr_t Heap::AllocateSnapshotSpace(size_t size) TaggedObject *Heap::AllocateSharedNonMovableSpaceFromTlab(JSThread *thread, size_t size) { ASSERT(!thread->IsJitThread()); + if (GetEcmaVM()->GetThreadCheckStatus()) { + if (thread->IsJitThread()) { + LOG_ECMA(FATAL) << "jit thread not allowed"; + } + if (thread->GetThreadId() != JSThread::GetCurrentThreadId() && !thread->IsCrossThreadExecutionEnable()) { + LOG_FULL(FATAL) << "Fatal: ecma_vm cannot run in multi-thread!" + << "thread:" << thread->GetThreadId() + << " currentThread:" << JSThread::GetCurrentThreadId(); + } + } size = AlignUp(size, static_cast(MemAlignment::MEM_ALIGN_OBJECT)); TaggedObject *object = reinterpret_cast(sNonMovableTlab_->Allocate(size)); if (object != nullptr) { @@ -561,6 +572,16 @@ TaggedObject *Heap::AllocateSharedNonMovableSpaceFromTlab(JSThread *thread, size TaggedObject *Heap::AllocateSharedOldSpaceFromTlab(JSThread *thread, size_t size) { ASSERT(!thread->IsJitThread()); + if (GetEcmaVM()->GetThreadCheckStatus()) { + if (thread->IsJitThread()) { + LOG_ECMA(FATAL) << "jit thread not allowed"; + } + if (thread->GetThreadId() != JSThread::GetCurrentThreadId() && !thread->IsCrossThreadExecutionEnable()) { + LOG_FULL(FATAL) << "Fatal: ecma_vm cannot run in multi-thread!" + << "thread:" << thread->GetThreadId() + << " currentThread:" << JSThread::GetCurrentThreadId(); + } + } size = AlignUp(size, static_cast(MemAlignment::MEM_ALIGN_OBJECT)); TaggedObject *object = reinterpret_cast(sOldTlab_->Allocate(size)); if (object != nullptr) { @@ -761,29 +782,6 @@ void SharedHeap::TryTriggerConcurrentMarking(JSThread *thread) } } -void SharedHeap::CollectGarbageFinish(bool inDaemon, TriggerGCType gcType) -{ - if (inDaemon) { - ASSERT(JSThread::GetCurrent() == dThread_); -#ifndef NDEBUG - ASSERT(dThread_->HasLaunchedSuspendAll()); -#endif - dThread_->FinishRunningTask(); - NotifyGCCompleted(); - // Update to forceGC_ is in DaemeanSuspendAll, and protected by the Runtime::mutatorLock_, - // so do not need lock. - smartGCStats_.forceGC_ = false; - } - localFullMarkTriggered_ = false; - // Record alive object size after shared gc and other stats - UpdateHeapStatsAfterGC(gcType); - // Adjust shared gc trigger threshold - AdjustGlobalSpaceAllocLimit(); - GetEcmaGCStats()->RecordStatisticAfterGC(); - GetEcmaGCStats()->PrintGCStatistic(); - ProcessAllGCListeners(); -} - TaggedObject *SharedHeap::AllocateNonMovableOrHugeObject(JSThread *thread, JSHClass *hclass) { size_t size = hclass->GetObjectSize(); @@ -924,7 +922,7 @@ TaggedObject *SharedHeap::AllocateHugeObject(JSThread *thread, size_t size) // if allocate huge object OOM, temporarily increase space size to avoid vm crash size_t oomOvershootSize = config_.GetOutOfMemoryOvershootSize(); sHugeObjectSpace_->IncreaseOutOfMemoryOvershootSize(oomOvershootSize); - DumpHeapSnapshotBeforeOOM(true, thread); + DumpHeapSnapshotBeforeOOM(false, thread, SharedHeapOOMSource::NORMAL_ALLOCATION); ThrowOutOfMemoryError(thread, size, "SharedHeap::AllocateHugeObject"); object = reinterpret_cast(sHugeObjectSpace_->Allocate(thread, size)); if (UNLIKELY(object == nullptr)) { @@ -1022,6 +1020,24 @@ void SharedHeap::CollectGarbage(JSThread *thread) WaitGCFinished(thread); } +template +void SharedHeap::PostGCTaskForTest(JSThread *thread) +{ + ASSERT(gcType == TriggerGCType::SHARED_GC || gcType == TriggerGCType::SHARED_FULL_GC); +#ifndef NDEBUG + ASSERT(!thread->HasLaunchedSuspendAll()); +#endif + if (dThread_->IsRunning()) { + // Some UT may run without Daemon Thread. + LockHolder lock(waitGCFinishedMutex_); + if (dThread_->CheckAndPostTask(TriggerCollectGarbageTask(thread))) { + ASSERT(gcFinished_); + gcFinished_ = false; + } + ASSERT(!gcFinished_); + } +} + static void SwapBackAndPop(CVector& vec, CVector::iterator& iter) { *iter = vec.back(); diff --git a/ecmascript/mem/heap.cpp b/ecmascript/mem/heap.cpp index 4865a0d82b41c8888a8f3bacfbb6f7c4fc999199..b49342f9b055e6a5021600f5bdd2f92227258e56 100644 --- a/ecmascript/mem/heap.cpp +++ b/ecmascript/mem/heap.cpp @@ -57,6 +57,7 @@ static constexpr uint64_t HEAP_DUMP_REPORT_INTERVAL = 24 * 3600 * 1000; static bool g_betaVersion = OHOS::system::GetParameter("const.logsystem.versiontype", "unknown") == "beta"; static bool g_developMode = (OHOS::system::GetParameter("persist.hiview.leak_detector", "unknown") == "enable") || (OHOS::system::GetParameter("persist.hiview.leak_detector", "unknown") == "true"); +static bool g_futVersion = OHOS::system::GetIntParameter("const.product.dfx.fans.stage", 0) == 1; #endif namespace panda::ecmascript { @@ -607,6 +608,36 @@ size_t SharedHeap::VerifyHeapObjects(VerifyKind verifyKind) const return failCount; } +void SharedHeap::CollectGarbageFinish(bool inDaemon, TriggerGCType gcType) +{ + if (inDaemon) { + ASSERT(JSThread::GetCurrent() == dThread_); +#ifndef NDEBUG + ASSERT(dThread_->HasLaunchedSuspendAll()); +#endif + dThread_->FinishRunningTask(); + NotifyGCCompleted(); + // Update to forceGC_ is in DaemeanSuspendAll, and protected by the Runtime::mutatorLock_, + // so do not need lock. + smartGCStats_.forceGC_ = false; + } + localFullMarkTriggered_ = false; + // Record alive object size after shared gc and other stats + UpdateHeapStatsAfterGC(gcType); + // Adjust shared gc trigger threshold + AdjustGlobalSpaceAllocLimit(); + GetEcmaGCStats()->RecordStatisticAfterGC(); + GetEcmaGCStats()->PrintGCStatistic(); + ProcessAllGCListeners(); + if (shouldThrowOOMError_ || shouldForceThrowOOMError_) { + // LocalHeap could do FullGC later instead of Fatal at once if only set `shouldThrowOOMError_` because there + // is kind of partial compress GC in LocalHeap, but SharedHeap differs. + DumpHeapSnapshotBeforeOOM(false, Runtime::GetInstance()->GetMainThread(), SharedHeapOOMSource::SHARED_GC); + LOG_GC(FATAL) << "SharedHeap OOM"; + UNREACHABLE(); + } +} + bool SharedHeap::IsReadyToConcurrentMark() const { return dThread_->IsReadyToConcurrentMark(); @@ -643,10 +674,10 @@ void SharedHeap::MoveOldSpaceToAppspawn() #ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING sAppSpawnSpace_->SwapAllocationCounter(sOldSpace_); #endif - auto threadId = Runtime::GetInstance()->GetMainThread()->GetThreadId(); sOldSpace_->EnumerateRegions([&](Region *region) { region->SetRegionSpaceFlag(RegionSpaceFlag::IN_SHARED_APPSPAWN_SPACE); - PageTag(region, region->GetCapacity(), PageTagType::HEAP, region->GetSpaceTypeName(), threadId); + // Region in SharedHeap do not need PageTag threadId. + PageTag(region, region->GetCapacity(), PageTagType::HEAP, region->GetSpaceTypeName()); sAppSpawnSpace_->AddRegion(region); sAppSpawnSpace_->IncreaseLiveObjectSize(region->AliveObject()); }); @@ -668,28 +699,41 @@ void SharedHeap::ReclaimForAppSpawn() sHugeObjectSpace_->EnumerateRegions(cb); } -void SharedHeap::DumpHeapSnapshotBeforeOOM([[maybe_unused]]bool isFullGC, [[maybe_unused]]JSThread *thread) +void SharedHeap::DumpHeapSnapshotBeforeOOM([[maybe_unused]]bool isFullGC, [[maybe_unused]]JSThread *thread, + [[maybe_unused]] SharedHeapOOMSource source) { #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT) && defined(PANDA_TARGET_OHOS) && defined(ENABLE_HISYSEVENT) - if (!g_betaVersion && !g_developMode) { - LOG_GC(INFO) << "current device is not development or beta! do not dump"; + if (!g_betaVersion && !g_developMode && !g_futVersion) { + LOG_ECMA(INFO) + << "SharedHeap::DumpHeapSnapshotBeforeOOM, current device is not development or beta! do not dump"; return; } #endif #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT) #if defined(ENABLE_DUMP_IN_FAULTLOG) EcmaVM *vm = thread->GetEcmaVM(); - if (vm->GetHeapProfile() != nullptr) { - LOG_FULL(INFO) << "GetHeapProfile nullptr"; - return; + HeapProfilerInterface *heapProfile = nullptr; + if (source == SharedHeapOOMSource::SHARED_GC) { +#ifndef NDEBUG + // If OOM during SharedGC, use main JSThread and create a new HeapProfile instancre to dump when GC completed. + ASSERT(thread == Runtime::GetInstance()->GetMainThread() && JSThread::GetCurrent()->HasLaunchedSuspendAll()); +#endif + heapProfile = HeapProfilerInterface::CreateNewInstance(vm); + } else { + if (vm->GetHeapProfile() != nullptr) { + LOG_ECMA(ERROR) << "SharedHeap::DumpHeapSnapshotBeforeOOM, HeapProfile is nullptr"; + return; + } + heapProfile = HeapProfilerInterface::GetInstance(vm); } // Filter appfreeze when dump. - LOG_ECMA(INFO) << " DumpHeapSnapshotBeforeOOM, isFullGC" << isFullGC; + LOG_ECMA(INFO) << "SharedHeap::DumpHeapSnapshotBeforeOOM, isFullGC = " << isFullGC; base::BlockHookScope blockScope; - HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(vm); if (appfreezeCallback_ != nullptr && appfreezeCallback_(getprocpid())) { - LOG_ECMA(INFO) << " DumpHeapSnapshotBeforeOOM Success. "; + LOG_ECMA(INFO) << "SharedHeap::DumpHeapSnapshotBeforeOOM, appfreezeCallback_ success. "; } + vm->GetEcmaGCKeyStats()->SendSysEventBeforeDump("OOMDump", GetEcmaParamConfiguration().GetMaxHeapSize(), + GetHeapObjectSize()); DumpSnapShotOption dumpOption; dumpOption.dumpFormat = DumpFormat::BINARY; dumpOption.isVmMode = true; @@ -700,8 +744,13 @@ void SharedHeap::DumpHeapSnapshotBeforeOOM([[maybe_unused]]bool isFullGC, [[mayb dumpOption.isSync = true; dumpOption.isBeforeFill = false; dumpOption.isDumpOOM = true; - heapProfile->DumpHeapSnapshot(dumpOption); - HeapProfilerInterface::Destroy(vm); + if (source == SharedHeapOOMSource::SHARED_GC) { + heapProfile->DumpHeapSnapshotForOOM(dumpOption, true); + HeapProfilerInterface::DestroyInstance(heapProfile); + } else { + heapProfile->DumpHeapSnapshotForOOM(dumpOption); + HeapProfilerInterface::Destroy(vm); + } #endif // ENABLE_DUMP_IN_FAULTLOG #endif // ECMASCRIPT_SUPPORT_SNAPSHOT } @@ -712,6 +761,7 @@ Heap::Heap(EcmaVM *ecmaVm) void Heap::Initialize() { + enablePageTagThreadId_ = ecmaVm_->GetJSOptions().EnablePageTagThreadId(); memController_ = new MemController(this); nativeAreaAllocator_ = ecmaVm_->GetNativeAreaAllocator(); heapRegionAllocator_ = ecmaVm_->GetHeapRegionAllocator(); @@ -833,6 +883,10 @@ void Heap::ProcessSharedGCRSetWorkList() ASSERT(thread_->IsSharedConcurrentMarkingOrFinished()); ASSERT(this == sharedGCData_.rSetWorkListHandler_->GetHeap()); sHeap_->GetSharedGCMarker()->ProcessThenMergeBackRSetFromBoundJSThread(sharedGCData_.rSetWorkListHandler_); + // The current thread may end earlier than the deamon thread. + // To ensure the accuracy of the state range, set true is executed on js thread and deamon thread. + // Reentrant does not cause exceptions because all the values are set to false. + thread_->SetProcessingLocalToSharedRset(false); ASSERT(sharedGCData_.rSetWorkListHandler_ == nullptr); } } @@ -1267,9 +1321,9 @@ void Heap::CollectGarbage(TriggerGCType gcType, GCReason reason) } // OOMError object is not allowed to be allocated during gc process, so throw OOMError after gc if (shouldThrowOOMError_ && gcType_ == TriggerGCType::FULL_GC) { - sweeper_->EnsureAllTaskFinished(); oldSpace_->ResetCommittedOverSizeLimit(); if (oldSpace_->CommittedSizeExceed()) { // LCOV_EXCL_BR_LINE + sweeper_->EnsureAllTaskFinished(); DumpHeapSnapshotBeforeOOM(false); StatisticHeapDetail(); ThrowOutOfMemoryError(thread_, oldSpace_->GetMergeSize(), " OldSpace::Merge"); @@ -1277,6 +1331,13 @@ void Heap::CollectGarbage(TriggerGCType gcType, GCReason reason) oldSpace_->ResetMergeSize(); shouldThrowOOMError_ = false; } + // Allocate region failed during GC, MUST throw OOM here + if (shouldForceThrowOOMError_) { + sweeper_->EnsureAllTaskFinished(); + DumpHeapSnapshotBeforeOOM(false); + StatisticHeapDetail(); + ThrowOutOfMemoryError(thread_, DEFAULT_REGION_SIZE, " HeapRegionAllocator::AllocateAlignedRegion"); + } // Update record heap object size after gc if in sensitive status if (GetSensitiveStatus() == AppSensitiveStatus::ENTER_HIGH_SENSITIVE) { SetRecordHeapObjectSizeBeforeSensitive(GetHeapObjectSize()); @@ -1529,22 +1590,24 @@ void BaseHeap::OnAllocateEvent([[maybe_unused]] EcmaVM *ecmaVm, [[maybe_unused]] void Heap::DumpHeapSnapshotBeforeOOM([[maybe_unused]] bool isFullGC) { #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT) && defined(PANDA_TARGET_OHOS) && defined(ENABLE_HISYSEVENT) - if (!g_betaVersion && !g_developMode) { - LOG_GC(INFO) << "current device is not development or beta! do not dump"; + if (!g_betaVersion && !g_developMode && !g_futVersion) { + LOG_ECMA(INFO) + << "Heap::DumpHeapSnapshotBeforeOOM, current device is not development or beta! do not dump"; return; } #endif #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT) #if defined(ENABLE_DUMP_IN_FAULTLOG) if (ecmaVm_->GetHeapProfile() != nullptr) { + LOG_ECMA(ERROR) << "Heap::DumpHeapSnapshotBeforeOOM, HeapProfile is nullptr"; return; } // Filter appfreeze when dump. - LOG_ECMA(INFO) << " DumpHeapSnapshotBeforeOOM, isFullGC" << isFullGC; + LOG_ECMA(INFO) << " Heap::DumpHeapSnapshotBeforeOOM, isFullGC = " << isFullGC; base::BlockHookScope blockScope; HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(ecmaVm_); if (appfreezeCallback_ != nullptr && appfreezeCallback_(getprocpid())) { - LOG_ECMA(INFO) << " DumpHeapSnapshotBeforeOOM Success. "; + LOG_ECMA(INFO) << "Heap::DumpHeapSnapshotBeforeOOM, appfreezeCallback_ success. "; } #ifdef ENABLE_HISYSEVENT GetEcmaGCKeyStats()->SendSysEventBeforeDump("OOMDump", GetHeapLimitSize(), GetLiveObjectSize()); @@ -1561,7 +1624,7 @@ void Heap::DumpHeapSnapshotBeforeOOM([[maybe_unused]] bool isFullGC) dumpOption.isSync = true; dumpOption.isBeforeFill = false; dumpOption.isDumpOOM = true; - heapProfile->DumpHeapSnapshot(dumpOption); + heapProfile->DumpHeapSnapshotForOOM(dumpOption); HeapProfilerInterface::Destroy(ecmaVm_); #endif // ENABLE_DUMP_IN_FAULTLOG #endif // ECMASCRIPT_SUPPORT_SNAPSHOT @@ -1658,6 +1721,8 @@ void Heap::RecomputeLimits() globalSpaceNativeLimit_ = memController_->CalculateAllocLimit(GetGlobalNativeSize(), MIN_HEAP_SIZE, MAX_GLOBAL_NATIVE_LIMIT, newSpaceCapacity, growingFactor); + globalSpaceNativeLimit_ = std::max(globalSpaceNativeLimit_, GetGlobalNativeSize() + + config_.GetMinNativeLimitGrowingStep()); OPTIONAL_LOG(ecmaVm_, INFO) << "RecomputeLimits oldSpaceAllocLimit_: " << newOldSpaceLimit << " globalSpaceAllocLimit_: " << globalSpaceAllocLimit_ << " globalSpaceNativeLimit_:" << globalSpaceNativeLimit_; @@ -2359,14 +2424,15 @@ bool Heap::NeedStopCollection() size_t objSize = GetHeapObjectSize(); size_t recordSizeBeforeSensitive = GetRecordHeapObjectSizeBeforeSensitive(); if (recordSizeBeforeSensitive == 0) { - SetRecordHeapObjectSizeBeforeSensitive(objSize); + recordSizeBeforeSensitive = objSize; + SetRecordHeapObjectSizeBeforeSensitive(recordSizeBeforeSensitive); } if (objSize < recordSizeBeforeSensitive + config_.GetIncObjSizeThresholdInSensitive() && !ObjectExceedMaxHeapSize()) { if (!IsNearGCInSensitive() && objSize > (recordSizeBeforeSensitive + config_.GetIncObjSizeThresholdInSensitive()) - * MIN_OBJECT_SURVIVAL_RATE) { + * MIN_SENSITIVE_OBJECT_SURVIVAL_RATE) { SetNearGCInSensitive(true); } return true; @@ -2732,7 +2798,7 @@ void Heap::ThresholdReachedDump() dumpOption.isSync = false; dumpOption.isBeforeFill = false; dumpOption.isDumpOOM = true; // aim's to do binary dump - heapProfile->DumpHeapSnapshot(dumpOption); + heapProfile->DumpHeapSnapshotForOOM(dumpOption); hasOOMDump_ = false; HeapProfilerInterface::Destroy(ecmaVm_); } diff --git a/ecmascript/mem/heap.h b/ecmascript/mem/heap.h index b447cb7b6ad6c2c3a720233ad5a70351229bdab3..8dbad37494304a2967a9459d03af2d5b77af6170 100644 --- a/ecmascript/mem/heap.h +++ b/ecmascript/mem/heap.h @@ -31,6 +31,7 @@ namespace panda::test { class GCTest_CallbackTask_Test; class HProfTestHelper; +class HeapTestHelper; } namespace panda::ecmascript { @@ -125,6 +126,12 @@ enum class VerifyKind { VERIFY_END, }; +enum class SharedHeapOOMSource { + NORMAL_ALLOCATION, + DESERIALIZE, + SHARED_GC, +}; + class BaseHeap { public: BaseHeap(const EcmaParamConfiguration &config) : config_(config) {} @@ -241,12 +248,17 @@ public: { shouldThrowOOMError_ = shouldThrow; } - + + void ShouldForceThrowOOMError() + { + shouldForceThrowOOMError_ = true; + } + void SetCanThrowOOMError(bool canThrow) { canThrowOOMError_ = canThrow; } - + bool CanThrowOOMError() { return canThrowOOMError_; @@ -322,6 +334,11 @@ public: return shouldVerifyHeap_; } + bool EnablePageTagThreadId() const + { + return enablePageTagThreadId_; + } + void ThrowOutOfMemoryErrorForDefault(JSThread *thread, size_t size, std::string functionName, bool NonMovableObjNearOOM = false); @@ -423,11 +440,15 @@ protected: bool clearTaskFinished_ {true}; bool inBackground_ {false}; bool shouldThrowOOMError_ {false}; + // Diffs from `shouldThrowOOMError_`, this is set due to allocating region failed during GC, and thus make + // MemMapAllocator infinite to complete this GC. After GC, if this flag is set, we MUST throw OOM force. + bool shouldForceThrowOOMError_ {false}; bool canThrowOOMError_ {true}; bool oldGCRequested_ {false}; // ONLY used for heap verification. bool shouldVerifyHeap_ {false}; bool isVerifying_ {false}; + bool enablePageTagThreadId_ {false}; bool inGC_ {false}; int32_t recursionDepth_ {0}; #ifndef NDEBUG @@ -610,6 +631,11 @@ public: return sOldSpace_; } + SharedOldSpace *GetCompressSpace() const + { + return sCompressSpace_; + } + SharedNonMovableSpace *GetNonMovableSpace() const { return sNonMovableSpace_; @@ -646,6 +672,9 @@ public: template void CollectGarbage(JSThread *thread); + + template + void PostGCTaskForTest(JSThread *thread); void CollectGarbageNearOOM(JSThread *thread); // Only means the main body of SharedGC is finished, i.e. if parallel_gc is enabled, this flags will be set @@ -819,7 +848,7 @@ public: inline void MergeToOldSpaceSync(SharedLocalSpace *localSpace); - void DumpHeapSnapshotBeforeOOM(bool isFullGC, JSThread *thread); + void DumpHeapSnapshotBeforeOOM(bool isFullGC, JSThread *thread, SharedHeapOOMSource source); inline void ProcessSharedNativeDelete(const WeakRootVisitor& visitor); inline void PushToSharedNativePointerList(JSNativePointer* pointer); @@ -839,7 +868,7 @@ public: private: void ProcessAllGCListeners(); - inline void CollectGarbageFinish(bool inDaemon, TriggerGCType gcType); + void CollectGarbageFinish(bool inDaemon, TriggerGCType gcType); void MoveOldSpaceToAppspawn(); @@ -955,6 +984,11 @@ public: return oldSpace_; } + OldSpace *GetCompressSpace() const + { + return compressSpace_; + } + NonMovableSpace *GetNonMovableSpace() const { return nonMovableSpace_; @@ -1465,6 +1499,11 @@ public: return nativeBindingSize_; } + size_t GetNativeBindingSizeAfterLastGC() const + { + return nativeBindingSizeAfterLastGC_; + } + size_t GetGlobalNativeSize() const { return GetNativeBindingSize() + nativeAreaAllocator_->GetNativeMemoryUsage(); @@ -1528,16 +1567,6 @@ public: return gcType_ == TriggerGCType::YOUNG_GC || gcType_ == TriggerGCType::EDEN_GC; } - bool IsProcessingRset() const - { - return isProcessingRset_; - } - - void SetProcessingRset(bool processing) - { - isProcessingRset_ = processing; - } - void EnableEdenGC(); void TryEnableEdenGC(); @@ -1761,7 +1790,6 @@ private: bool fullMarkRequested_ {false}; bool oldSpaceLimitAdjusted_ {false}; bool enableIdleGC_ {false}; - bool isProcessingRset_ {false}; std::atomic_bool isCSetClearing_ {false}; HeapMode mode_ { HeapMode::NORMAL }; @@ -1819,6 +1847,7 @@ private: friend panda::test::HProfTestHelper; friend panda::test::GCTest_CallbackTask_Test; + friend panda::test::HeapTestHelper; }; } // namespace panda::ecmascript diff --git a/ecmascript/mem/heap_region_allocator.cpp b/ecmascript/mem/heap_region_allocator.cpp index 52c0b47d155378f8fed68eb6b73d2a6f07206edb..5a5dd6c7663adc87d71fb6f1b418c79a854cfce2 100644 --- a/ecmascript/mem/heap_region_allocator.cpp +++ b/ecmascript/mem/heap_region_allocator.cpp @@ -21,6 +21,11 @@ namespace panda::ecmascript { constexpr size_t PANDA_POOL_ALIGNMENT_IN_BYTES = 256_KB; +HeapRegionAllocator::HeapRegionAllocator(JSRuntimeOptions &option) +{ + enablePageTagThreadId_ = option.EnablePageTagThreadId(); +} + Region *HeapRegionAllocator::AllocateAlignedRegion(Space *space, size_t capacity, JSThread* thread, BaseHeap *heap, bool isFresh) { @@ -35,23 +40,38 @@ Region *HeapRegionAllocator::AllocateAlignedRegion(Space *space, size_t capacity flags != RegionSpaceFlag::IN_SHARED_HUGE_OBJECT_SPACE); bool isMachineCode = (flags == RegionSpaceFlag::IN_MACHINE_CODE_SPACE || flags == RegionSpaceFlag::IN_HUGE_MACHINE_CODE_SPACE); - auto tid = thread ? thread->GetThreadId() : JSThread::GetCurrentThreadId(); + JSThread::ThreadId tid = 0; + bool shouldPageTag = AllocateRegionShouldPageTag(space); + if (enablePageTagThreadId_) { + tid = thread ? thread->GetThreadId() : JSThread::GetCurrentThreadId(); + } auto pool = MemMapAllocator::GetInstance()->Allocate(tid, capacity, DEFAULT_REGION_SIZE, - ToSpaceTypeName(space->GetSpaceType()), - isRegular, isMachineCode, - Jit::GetInstance()->IsEnableJitFort()); + ToSpaceTypeName(space->GetSpaceType()), isRegular, isMachineCode, Jit::GetInstance()->IsEnableJitFort(), + shouldPageTag); void *mapMem = pool.GetMem(); if (mapMem == nullptr) { // LOCV_EXCL_BR_LINE - if (thread != nullptr && thread->GetEcmaVM()->IsInitialized()) { - Heap *localHeap = const_cast(thread->GetEcmaVM()->GetHeap()); - if (!localHeap->InGC()) { + if (heap->InGC()) { + // Donot crash in GC. + TemporarilyEnsureAllocateionAlwaysSuccess(heap); + pool = MemMapAllocator::GetInstance()->Allocate(tid, capacity, DEFAULT_REGION_SIZE, + ToSpaceTypeName(space->GetSpaceType()), isRegular, isMachineCode, + Jit::GetInstance()->IsEnableJitFort(), shouldPageTag); + mapMem = pool.GetMem(); + if (mapMem == nullptr) { + // This should not happen + LOG_ECMA_MEM(FATAL) << "pool is empty in GC unexpectedly"; + UNREACHABLE(); + } + } else { + if (thread != nullptr && thread->GetEcmaVM()->IsInitialized()) { + Heap *localHeap = const_cast(thread->GetEcmaVM()->GetHeap()); localHeap->DumpHeapSnapshotBeforeOOM(); + heap->ThrowOutOfMemoryErrorForDefault(thread, DEFAULT_REGION_SIZE, + "HeapRegionAllocator::AllocateAlignedRegion", false); } - heap->ThrowOutOfMemoryErrorForDefault(thread, DEFAULT_REGION_SIZE, - "HeapRegionAllocator::AllocateAlignedRegion", false); + LOG_ECMA_MEM(FATAL) << "pool is empty " << annoMemoryUsage_.load(std::memory_order_relaxed); + UNREACHABLE(); } - LOG_ECMA_MEM(FATAL) << "pool is empty " << annoMemoryUsage_.load(std::memory_order_relaxed); - UNREACHABLE(); } #if ECMASCRIPT_ENABLE_ZAP_MEM if (memset_s(mapMem, capacity, 0, capacity) != EOK) { // LOCV_EXCL_BR_LINE @@ -80,6 +100,7 @@ void HeapRegionAllocator::FreeRegion(Region *region, size_t cachedSize) bool isRegular = !region->InHugeObjectSpace() && !region->InHugeMachineCodeSpace() && !region->InSharedHugeObjectSpace(); auto allocateBase = region->GetAllocateBase(); + bool shouldPageTag = FreeRegionShouldPageTag(region); DecreaseAnnoMemoryUsage(size); region->Invalidate(); @@ -91,6 +112,32 @@ void HeapRegionAllocator::FreeRegion(Region *region, size_t cachedSize) } #endif MemMapAllocator::GetInstance()->CacheOrFree(ToVoidPtr(allocateBase), - size, isRegular, cachedSize); + size, isRegular, cachedSize, shouldPageTag); +} + +void HeapRegionAllocator::TemporarilyEnsureAllocateionAlwaysSuccess(BaseHeap *heap) +{ + // Make MemMapAllocator infinite, and record to Dump&Fatal when GC completed. + heap->ShouldForceThrowOOMError(); + MemMapAllocator::GetInstance()->TransferToInfiniteModeForGC(); +} + +bool HeapRegionAllocator::AllocateRegionShouldPageTag(Space *space) const +{ + if (enablePageTagThreadId_) { + return true; + } + MemSpaceType type = space->GetSpaceType(); + // Both LocalSpace and OldSpace belong to OldSpace. + return type != MemSpaceType::OLD_SPACE && type != MemSpaceType::LOCAL_SPACE; +} + +bool HeapRegionAllocator::FreeRegionShouldPageTag(Region *region) const +{ + if (enablePageTagThreadId_) { + return true; + } + // There is no LocalSpace tag in region. + return !region->InOldSpace(); } } // namespace panda::ecmascript diff --git a/ecmascript/mem/heap_region_allocator.h b/ecmascript/mem/heap_region_allocator.h index 91680c6500bded380ef2c71c2a6d34634a01ce07..2657281e5e13cdc7ce78123830a37dabd44c5a6c 100644 --- a/ecmascript/mem/heap_region_allocator.h +++ b/ecmascript/mem/heap_region_allocator.h @@ -27,7 +27,9 @@ class Space; class HeapRegionAllocator { public: + // For `Runtime::heapRegionAllocator_`, since it's for SharedHeap, so do not need enable PageTag threadId. HeapRegionAllocator() = default; + HeapRegionAllocator(JSRuntimeOptions &option); virtual ~HeapRegionAllocator() = default; Region *AllocateAlignedRegion(Space *space, size_t capacity, JSThread* thread, BaseHeap *heap, @@ -61,8 +63,18 @@ private: NO_COPY_SEMANTIC(HeapRegionAllocator); NO_MOVE_SEMANTIC(HeapRegionAllocator); + // Can not throw OOM during GC, so just make MemMapAllocator infinite to make allocating region always + // success to complete this GC, and then do HeapDump and Fatal. + // This will temporarily lead that all JSThread could always AllcationRegion success, + // breaking the global region limit, but thread calling this will soon complete GC and then fatal. + void TemporarilyEnsureAllocateionAlwaysSuccess(BaseHeap *heap); + + bool AllocateRegionShouldPageTag(Space *space) const; + bool FreeRegionShouldPageTag(Region *region) const; + std::atomic annoMemoryUsage_ {0}; std::atomic maxAnnoMemoryUsage_ {0}; + bool enablePageTagThreadId_ {false}; }; } // namespace panda::ecmascript diff --git a/ecmascript/mem/idle_gc_trigger.cpp b/ecmascript/mem/idle_gc_trigger.cpp index 5616377013566949bd8ad332b5291b1b7c0ad915..ec92030599136f83cf63de695dad549b10563c6f 100644 --- a/ecmascript/mem/idle_gc_trigger.cpp +++ b/ecmascript/mem/idle_gc_trigger.cpp @@ -76,6 +76,11 @@ bool IdleGCTrigger::TryTriggerIdleLocalOldGC() !heap_->CheckCanTriggerConcurrentMarking()) { return true; } + if (heap_->GetJSThread()->FullMarkRequest() && !heap_->NeedStopCollection()) { + heap_->GetJSThread()->ResetFullMarkRequest(); + PostIdleGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK); + return true; + } if (CheckIdleOrHintOldGC(heap_) && ReachIdleLocalOldGCThresholds() && !heap_->NeedStopCollection()) { PostIdleGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK); return true; @@ -161,6 +166,21 @@ bool IdleGCTrigger::CheckIdleYoungGC() const return newSpace->GetAllocatedSizeSinceGC(newSpace->GetTop()) > IDLE_MIN_EXPECT_RECLAIM_SIZE; } +bool IdleGCTrigger::CheckLocalBindingNativeTriggerFullGC() const +{ + size_t nativeBindingSize = heap_->GetNativeBindingSize(); + size_t nativeBindingSizeLastGC = heap_->GetNativeBindingSizeAfterLastGC(); + if (nativeBindingSize <= nativeBindingSizeLastGC) { + return false; + } + size_t expectIncrementalNative = std::max(IDLE_BINDING_NATIVE_MIN_INC_SIZE, + static_cast(nativeBindingSizeLastGC * IDLE_BINDING_NATIVE_MIN_INC_RATIO)); + size_t incrementalNative = nativeBindingSize - nativeBindingSizeLastGC; + LOG_GC(DEBUG) << "IdleGCTrigger: check full GC expectIncrementalNative:" << expectIncrementalNative + << ";incrementalNative:" << incrementalNative; + return incrementalNative > expectIncrementalNative; +} + void IdleGCTrigger::TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE gcType) { LOG_GC(DEBUG) << "IdleGCTrigger: recv once notify of " << GetGCTypeName(gcType); @@ -169,6 +189,9 @@ void IdleGCTrigger::TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE gcType) if (CheckIdleOrHintFullGC(heap_) && !heap_->NeedStopCollection()) { LOG_GC(INFO) << "IdleGCTrigger: trigger " << GetGCTypeName(gcType); heap_->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE); + } else if (CheckLocalBindingNativeTriggerFullGC() && !heap_->NeedStopCollection()) { + LOG_GC(INFO) << "IdleGCTrigger: trigger local full GC by native binding size."; + heap_->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE_NATIVE); } else if (CheckIdleYoungGC() && !heap_->NeedStopCollection()) { LOG_GC(INFO) << "IdleGCTrigger: trigger young gc"; heap_->CollectGarbage(TriggerGCType::YOUNG_GC, GCReason::IDLE); diff --git a/ecmascript/mem/idle_gc_trigger.h b/ecmascript/mem/idle_gc_trigger.h index fc3ff3e2559683313ed047ccc7917ec248bcfdf9..ee094ef1bc335c80ddc6a23b6f4bf07eeabedf09 100644 --- a/ecmascript/mem/idle_gc_trigger.h +++ b/ecmascript/mem/idle_gc_trigger.h @@ -103,6 +103,7 @@ public: void TryPostHandleMarkFinished(); void TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE gcType); bool CheckIdleYoungGC() const; + bool CheckLocalBindingNativeTriggerFullGC() const; template bool CheckIdleOrHintOldGC(const T *baseHeap) const { diff --git a/ecmascript/mem/jit_fort.cpp b/ecmascript/mem/jit_fort.cpp index 9e33a6de4582c7d61ac3377e9f3e7c9183023b40..3736feb9d3d61e110ff2184bf54411acd10d6a6d 100644 --- a/ecmascript/mem/jit_fort.cpp +++ b/ecmascript/mem/jit_fort.cpp @@ -51,11 +51,17 @@ JitFort::~JitFort() { constexpr size_t numRegions = JIT_FORT_REG_SPACE_MAX / DEFAULT_REGION_SIZE; for (size_t i = 0; i < numRegions; i++) { - regions_[i]->DestroyFreeObjectSets(); - delete regions_[i]; + if (regions_[i] != nullptr) { + regions_[i]->DestroyFreeObjectSets(); + delete regions_[i]; + } + } + if (allocator_ != nullptr) { + delete allocator_; + } + if (memDescPool_ != nullptr) { + delete memDescPool_; } - delete allocator_; - delete memDescPool_; PageUnmap(jitFortMem_); } diff --git a/ecmascript/mem/linear_space.cpp b/ecmascript/mem/linear_space.cpp index 7d4961bf2710f496ee082ef694836a42a3924d63..c1038249e93b42f093c9685341a01a3980a3830e 100644 --- a/ecmascript/mem/linear_space.cpp +++ b/ecmascript/mem/linear_space.cpp @@ -177,8 +177,12 @@ EdenSpace::EdenSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity) { size_t memSize = AlignUp(maximumCapacity_, DEFAULT_REGION_SIZE); memMap_ = PageMap(memSize, PAGE_PROT_READWRITE, DEFAULT_REGION_SIZE); + JSThread::ThreadId threadId = 0; + if (heap->EnablePageTagThreadId()) { + threadId = heap->GetJSThread()->GetThreadId(); + } PageTag(memMap_.GetMem(), memMap_.GetSize(), PageTagType::HEAP, ToSpaceTypeName(MemSpaceType::EDEN_SPACE), - localHeap_->GetJSThread()->GetThreadId()); + threadId); auto mem = ToUintPtr(memMap_.GetMem()); auto count = memMap_.GetSize() / DEFAULT_REGION_SIZE; while (count-- > 0) { @@ -446,19 +450,20 @@ bool SemiSpace::AdjustCapacity(size_t allocatedSizeSinceGC, JSThread *thread) if (allocatedSizeSinceGC <= initialCapacity_ * GROW_OBJECT_SURVIVAL_RATE / GROWING_FACTOR) { return false; } + size_t committedSize = GetCommittedSize(); double curObjectSurvivalRate = static_cast(survivalObjectSize_) / allocatedSizeSinceGC; - double initialObjectRate = static_cast(survivalObjectSize_) / initialCapacity_; - if (curObjectSurvivalRate > GROW_OBJECT_SURVIVAL_RATE || initialObjectRate > GROW_OBJECT_SURVIVAL_RATE) { - if (GetCommittedSize() > maximumCapacity_ - && GetHeapObjectSize() > GetCommittedSize() * GROW_OBJECT_SURVIVAL_RATE) { - // Overshoot size is too large. Avoid heapObjectSize is too close to committed size. - AddOverShootSize(GetCommittedSize() * SHRINK_OBJECT_SURVIVAL_RATE); - } - if (initialCapacity_ >= maximumCapacity_) { - return false; - } + double committedSurvivalRate = static_cast(committedSize) / initialCapacity_; + SetOverShootSize(0); + if (curObjectSurvivalRate > GROW_OBJECT_SURVIVAL_RATE || committedSurvivalRate > GROW_OBJECT_SURVIVAL_RATE) { size_t newCapacity = initialCapacity_ * GROWING_FACTOR; + while (committedSize >= newCapacity && newCapacity < maximumCapacity_) { + newCapacity = newCapacity * GROWING_FACTOR; + } SetInitialCapacity(std::min(newCapacity, maximumCapacity_)); + if (committedSize >= initialCapacity_ * GROW_OBJECT_SURVIVAL_RATE) { + // Overshoot size is too large. Avoid heapObjectSize is too close to committed size. + SetOverShootSize(committedSize); + } if (newCapacity == maximumCapacity_) { localHeap_->GetJSObjectResizingStrategy()->UpdateGrowStep( thread, diff --git a/ecmascript/mem/mem.h b/ecmascript/mem/mem.h index a5b9c4e3079e3f1a7a430fcfcae74dac310e8815..eff0eff5d18a25db04a12069b0406a8b0796c7a0 100644 --- a/ecmascript/mem/mem.h +++ b/ecmascript/mem/mem.h @@ -67,6 +67,7 @@ static constexpr size_t DEFAULT_REGION_MASK = DEFAULT_REGION_SIZE - 1; static constexpr size_t DEFAULT_MARK_STACK_SIZE = 4_KB; static constexpr double MIN_OBJECT_SURVIVAL_RATE = 0.75; +static constexpr double MIN_SENSITIVE_OBJECT_SURVIVAL_RATE = 0.9; static constexpr double GROW_OBJECT_SURVIVAL_RATE = 0.8; static constexpr double SHRINK_OBJECT_SURVIVAL_RATE = 0.2; static constexpr double LOW_ALLOCATION_SPEED_PER_MS = 1000; @@ -96,9 +97,11 @@ static constexpr double LOW_ALLOCATION_RATE_PER_MS = 10; static constexpr double IDLE_SPACE_SIZE_LIMIT_RATE = 0.8f; static constexpr double IDLE_SPACE_SIZE_MIN_INC_RATIO = 1.1f; static constexpr double IDLE_FRAGMENT_SIZE_RATIO = 0.1f; +static constexpr double IDLE_BINDING_NATIVE_MIN_INC_RATIO = 0.2f; static constexpr size_t IDLE_SPACE_SIZE_MIN_INC_STEP = 5_MB; static constexpr size_t IDLE_SPACE_SIZE_MIN_INC_STEP_FULL = 1_MB; static constexpr size_t IDLE_MIN_EXPECT_RECLAIM_SIZE = 1_MB; +static constexpr size_t IDLE_BINDING_NATIVE_MIN_INC_SIZE = 10_MB; using TaggedType = uint64_t; static constexpr uint32_t TAGGED_TYPE_SIZE = sizeof(TaggedType); diff --git a/ecmascript/mem/mem_controller.cpp b/ecmascript/mem/mem_controller.cpp index a2aeee69d6155104fa1f15963891e65cb6212a53..f8f84b2113f0f24a9a34a2be2149683ad975ff44 100644 --- a/ecmascript/mem/mem_controller.cpp +++ b/ecmascript/mem/mem_controller.cpp @@ -21,6 +21,7 @@ namespace panda::ecmascript { MemController::MemController(Heap *heap) : heap_(heap), allocTimeMs_(GetSystemTimeInMs()) { + ASSERT(heap != nullptr); minAllocLimitGrowingStep_ = heap->GetEcmaVM()->GetEcmaParamConfiguration().GetMinAllocLimitGrowingStep(); } @@ -209,6 +210,7 @@ void MemController::StopCalculationAfterGC(TriggerGCType gcType) void MemController::RecordAfterConcurrentMark(MarkType markType, const ConcurrentMarker *marker) { + ASSERT(marker != nullptr); double duration = marker->GetDuration(); if (markType == MarkType::MARK_FULL) { recordedConcurrentMarks_.Push(MakeBytesAndDuration(marker->GetHeapObjectSize(), duration)); diff --git a/ecmascript/mem/mem_map_allocator.cpp b/ecmascript/mem/mem_map_allocator.cpp index 2d4ce26cc3dce9a6f2f1be0fdcc874d5fef1aae7..e75f6cb0f647537ca622e1775b222d91c43d7e53 100644 --- a/ecmascript/mem/mem_map_allocator.cpp +++ b/ecmascript/mem/mem_map_allocator.cpp @@ -33,7 +33,7 @@ void MemMapAllocator::InitializeRegularRegionMap([[maybe_unused]] size_t alignme i * STEP_INCREASE_MEM_MAP_ADDR); MemMap memMap = PageMap(initialRegularObjectCapacity, PAGE_PROT_NONE, alignment, addr); if (ToUintPtr(memMap.GetMem()) >= ToUintPtr(addr)) { - PageTag(memMap.GetMem(), memMap.GetSize(), PageTagType::MEMPOOL_CACHE); + PageTag(memMap.GetMem(), memMap.GetSize(), PageTagType::HEAP); PageRelease(memMap.GetMem(), memMap.GetSize()); memMapPool_.InsertMemMap(memMap); memMapPool_.SplitMemMapToCache(memMap); @@ -57,7 +57,7 @@ void MemMapAllocator::InitializeHugeRegionMap(size_t alignment) i * STEP_INCREASE_MEM_MAP_ADDR); MemMap memMap = PageMap(initialHugeObjectCapacity, PAGE_PROT_NONE, alignment, addr); if (ToUintPtr(memMap.GetMem()) >= ToUintPtr(addr) || i == MEM_MAP_RETRY_NUM) { - PageTag(memMap.GetMem(), memMap.GetSize(), PageTagType::MEMPOOL_CACHE); + PageTag(memMap.GetMem(), memMap.GetSize(), PageTagType::HEAP); PageRelease(memMap.GetMem(), memMap.GetSize()); memMapFreeList_.Initialize(memMap, capacity_); break; @@ -69,7 +69,7 @@ void MemMapAllocator::InitializeHugeRegionMap(size_t alignment) } #else MemMap hugeMemMap = PageMap(initialHugeObjectCapacity, PAGE_PROT_NONE, alignment); - PageTag(hugeMemMap.GetMem(), hugeMemMap.GetSize(), PageTagType::MEMPOOL_CACHE); + PageTag(hugeMemMap.GetMem(), hugeMemMap.GetSize(), PageTagType::HEAP); PageRelease(hugeMemMap.GetMem(), hugeMemMap.GetSize()); memMapFreeList_.Initialize(hugeMemMap, capacity_); #endif @@ -103,7 +103,8 @@ static bool PageProtectMem(bool machineCodeSpace, void *mem, size_t size, [[mayb } MemMap MemMapAllocator::Allocate(const uint32_t threadId, size_t size, size_t alignment, - const std::string &spaceName, bool regular, bool isMachineCode, bool isEnableJitFort) + const std::string &spaceName, bool regular, bool isMachineCode, bool isEnableJitFort, + bool shouldPageTag) { MemMap mem; PageTagType type = isMachineCode ? PageTagType::MACHINE_CODE : PageTagType::HEAP; @@ -115,7 +116,9 @@ MemMap MemMapAllocator::Allocate(const uint32_t threadId, size_t size, size_t al if (!res) { return MemMap(); } - PageTag(mem.GetMem(), size, type, spaceName, threadId); + if (shouldPageTag) { + PageTag(mem.GetMem(), size, type, spaceName, threadId); + } return mem; } if (UNLIKELY(memMapTotalSize_ + size > capacity_)) { @@ -129,7 +132,9 @@ MemMap MemMapAllocator::Allocate(const uint32_t threadId, size_t size, size_t al if (!res) { return MemMap(); } - PageTag(mem.GetMem(), size, type, spaceName, threadId); + if (shouldPageTag) { + PageTag(mem.GetMem(), size, type, spaceName, threadId); + } return mem; } mem = PageMap(REGULAR_REGION_MMAP_SIZE, PAGE_PROT_NONE, alignment); @@ -147,19 +152,22 @@ MemMap MemMapAllocator::Allocate(const uint32_t threadId, size_t size, size_t al if (!res) { return MemMap(); } - PageTag(mem.GetMem(), mem.GetSize(), type, spaceName, threadId); + if (shouldPageTag) { + PageTag(mem.GetMem(), mem.GetSize(), type, spaceName, threadId); + } memMapTotalSize_ += mem.GetSize(); } return mem; } -void MemMapAllocator::CacheOrFree(void *mem, size_t size, bool isRegular, size_t cachedSize) +void MemMapAllocator::CacheOrFree(void *mem, size_t size, bool isRegular, size_t cachedSize, bool shouldPageTag) { + // Clear ThreadId tag and tag the mem with ARKTS HEAP. + if (shouldPageTag) { + PageTag(mem, size, PageTagType::HEAP); + } if (isRegular && !memMapPool_.IsRegularCommittedFull(cachedSize)) { // Cache regions to accelerate allocation. - // Clear ThreadId tag and tag the mem with ARKTS HEAP. - PageClearTag(mem, size); - PageTag(mem, size, PageTagType::HEAP); memMapPool_.AddMemToCommittedCache(mem, size); return; } @@ -180,7 +188,6 @@ void MemMapAllocator::CacheOrFree(void *mem, size_t size, bool isRegular, size_t void MemMapAllocator::Free(void *mem, size_t size, bool isRegular) { memMapTotalSize_ -= size; - PageTag(mem, size, PageTagType::MEMPOOL_CACHE); if (!PageProtect(mem, size, PAGE_PROT_NONE)) { // LCOV_EXCL_BR_LINE return; } @@ -198,4 +205,10 @@ void MemMapAllocator::AdapterSuitablePoolCapacity() capacity_ = std::min(physicalSize * DEFAULT_CAPACITY_RATE, MAX_MEM_POOL_CAPACITY); LOG_GC(INFO) << "Ark Auto adapter memory pool capacity:" << capacity_; } + +void MemMapAllocator::TransferToInfiniteModeForGC() +{ + capacity_ = std::numeric_limits::max(); + LOG_GC(INFO) << "MemMapAllocator transfer to infinite mode:" << capacity_; +} } // namespace panda::ecmascript diff --git a/ecmascript/mem/mem_map_allocator.h b/ecmascript/mem/mem_map_allocator.h index 87650645adbb5523dcac4a3fc3d0d6645c044c72..d25c0a616d6c902c2b590ad55e599caf23f57d2d 100644 --- a/ecmascript/mem/mem_map_allocator.h +++ b/ecmascript/mem/mem_map_allocator.h @@ -57,8 +57,8 @@ public: ASSERT(size == REGULAR_MMAP_SIZE); LockHolder lock(lock_); if (!memMapCache_.empty()) { - MemMap mem = memMapCache_.front(); - memMapCache_.pop_front(); + MemMap mem = memMapCache_.back(); + memMapCache_.pop_back(); return mem; } return MemMap(); @@ -273,9 +273,15 @@ public: MemMap Allocate(const uint32_t threadId, size_t size, size_t alignment, const std::string &spaceName, bool regular, bool isMachineCode, - bool isEnableJitFort); + bool isEnableJitFort, bool shouldPageTag); - void CacheOrFree(void *mem, size_t size, bool isRegular, size_t cachedSize); + void CacheOrFree(void *mem, size_t size, bool isRegular, size_t cachedSize, bool shouldPageTag); + + // This is only used when allocating region failed during GC, since it's unsafe to do HeapDump or throw OOM, + // just make MemMapAllocator infinite to complete this GC, this will temporarily lead that all JSThread could + // always AllcationRegion success, breaking the global region limit, but thread calling this will soon complete + // GC and then fatal. + void TransferToInfiniteModeForGC(); private: void InitializeRegularRegionMap(size_t alignment); diff --git a/ecmascript/mem/object_xray.h b/ecmascript/mem/object_xray.h index 62029f5a97585a30edeea3c284c27eb4dcb438af..6390bac1b3677281f3cf7ad06994024cd7f7d292 100644 --- a/ecmascript/mem/object_xray.h +++ b/ecmascript/mem/object_xray.h @@ -498,7 +498,7 @@ public: TransWithProtoHandler::Cast(object)->VisitRangeSlot(visitor); break; case JSType::STORE_TS_HANDLER: - StoreTSHandler::Cast(object)->VisitRangeSlot(visitor); + StoreAOTHandler::Cast(object)->VisitRangeSlot(visitor); break; case JSType::PROPERTY_BOX: PropertyBox::Cast(object)->VisitRangeSlot(visitor); diff --git a/ecmascript/mem/parallel_evacuator.cpp b/ecmascript/mem/parallel_evacuator.cpp index 7f102f85da1c04aacab0c4a1b7f838ddaed60ce5..ec70a525d72ac094eba560803745e6a524704d81 100644 --- a/ecmascript/mem/parallel_evacuator.cpp +++ b/ecmascript/mem/parallel_evacuator.cpp @@ -112,10 +112,6 @@ void ParallelEvacuator::EvacuateSpace() GCStats::Scope sp2(GCStats::Scope::ScopeId::WaitFinish, heap_->GetEcmaVM()->GetEcmaGCStats()); WaitFinished(); } - - if (heap_->GetJSThread()->IsPGOProfilerEnable()) { - UpdateTrackInfo(); - } } bool ParallelEvacuator::EvacuateSpace(TlabAllocator *allocator, uint32_t threadIndex, uint32_t idOrder, bool isMain) @@ -200,7 +196,7 @@ void ParallelEvacuator::EvacuateRegion(TlabAllocator *allocator, Region *region, edenToYoungSize += size; } } - LOG_ECMA_IF(address == 0, FATAL) << "Evacuate object failed:" << size; + ASSERT(address != 0); if (memcpy_s(ToVoidPtr(address), size, ToVoidPtr(ToUintPtr(mem)), size) != EOK) { // LOCV_EXCL_BR_LINE LOG_FULL(FATAL) << "memcpy_s failed"; @@ -296,10 +292,14 @@ void ParallelEvacuator::UpdateReference() } } { - GCStats::Scope sp2(GCStats::Scope::ScopeId::ProceeWorkload, heap_->GetEcmaVM()->GetEcmaGCStats());\ + GCStats::Scope sp2(GCStats::Scope::ScopeId::ProceeWorkload, heap_->GetEcmaVM()->GetEcmaGCStats()); ProcessWorkloads(true); } WaitFinished(); + + if (heap_->GetJSThread()->IsPGOProfilerEnable()) { + UpdateTrackInfo(); + } } void ParallelEvacuator::UpdateRoot() diff --git a/ecmascript/mem/parallel_marker-inl.h b/ecmascript/mem/parallel_marker-inl.h index ab58effe0d8cb5d65a302ed8a21259b29fa92e07..49f26a592c6a78f9fde9d5a09fc9d7c65eb44b35 100644 --- a/ecmascript/mem/parallel_marker-inl.h +++ b/ecmascript/mem/parallel_marker-inl.h @@ -279,20 +279,12 @@ inline uintptr_t MovableMarker::AllocateDstSpace(uint32_t threadId, size_t size, uintptr_t forwardAddress = 0; if (shouldPromote) { forwardAddress = workManager_->GetTlabAllocator(threadId)->Allocate(size, COMPRESS_SPACE); - if (UNLIKELY(forwardAddress == 0)) { - LOG_ECMA_MEM(FATAL) << "EvacuateObject alloc failed: " - << " size: " << size; - UNREACHABLE(); - } + ASSERT(forwardAddress != 0); } else { forwardAddress = workManager_->GetTlabAllocator(threadId)->Allocate(size, SEMI_SPACE); if (UNLIKELY(forwardAddress == 0)) { forwardAddress = workManager_->GetTlabAllocator(threadId)->Allocate(size, COMPRESS_SPACE); - if (UNLIKELY(forwardAddress == 0)) { - LOG_ECMA_MEM(FATAL) << "EvacuateObject alloc failed: " - << " size: " << size; - UNREACHABLE(); - } + ASSERT(forwardAddress != 0); shouldPromote = true; } } diff --git a/ecmascript/mem/regexp_cached_chunk.cpp b/ecmascript/mem/regexp_cached_chunk.cpp index 48f9c2a3e4ce760818fc828e26ebaeab4e16a5aa..5128880b33b0646f33750702e677eb89d34176ce 100644 --- a/ecmascript/mem/regexp_cached_chunk.cpp +++ b/ecmascript/mem/regexp_cached_chunk.cpp @@ -21,6 +21,7 @@ namespace panda::ecmascript { RegExpCachedChunk::RegExpCachedChunk(JSThread *JSThread) : jsThread_(JSThread) { + ASSERT(jsThread_ != nullptr); allocator_ = jsThread_->GetNativeAreaAllocator(); currentArea_ = jsThread_->GetOrCreateRegExpCache(); ptr_ = currentArea_->GetBegin(); diff --git a/ecmascript/mem/rset_worklist_handler-inl.h b/ecmascript/mem/rset_worklist_handler-inl.h index de8c43f9b5c86109c1fdfa719bb0f1e697b1b48a..5172c6aec5d2413c3ca82eaf894c75c05e3cf55c 100644 --- a/ecmascript/mem/rset_worklist_handler-inl.h +++ b/ecmascript/mem/rset_worklist_handler-inl.h @@ -23,7 +23,7 @@ #include "ecmascript/mem/heap.h" namespace panda::ecmascript { -inline RSetWorkListHandler::RSetWorkListHandler(Heap *heap) : heap_(heap) +inline RSetWorkListHandler::RSetWorkListHandler(Heap *heap, JSThread *thread) : heap_(heap), ownerThread_(thread) { CollectRSetItemsInHeap(heap); } @@ -140,15 +140,6 @@ inline void RSetWorkListHandler::MergeBackForAllItem() } } -inline void RSetWorkListHandler::NotifyProcessRsetFinished() -{ - LockHolder lock(mutex_); - if (!processRsetFinished_) { - heap_->SetProcessingRset(false); - processRsetFinished_ = true; - } -} - inline bool RSetWorkListHandler::MergeBack() { ASSERT((JSThread::GetCurrent()->IsJSThread() && JSThread::GetCurrent()->IsInRunningState()) || diff --git a/ecmascript/mem/rset_worklist_handler.h b/ecmascript/mem/rset_worklist_handler.h index 8ecc357d939cd76849754a1b1cef21f9fbe6ec94..8aafa504b93b8ee77586faf2b8df8f8779e9f130 100644 --- a/ecmascript/mem/rset_worklist_handler.h +++ b/ecmascript/mem/rset_worklist_handler.h @@ -40,7 +40,7 @@ private: class RSetWorkListHandler { public: - explicit RSetWorkListHandler(Heap *heap); + explicit RSetWorkListHandler(Heap *heap, JSThread *thread); ~RSetWorkListHandler() = default; inline void Initialize(); @@ -62,7 +62,10 @@ public: inline void MergeBackForAllItem(); - inline void NotifyProcessRsetFinished(); + JSThread *GetOwnerThreadUnsafe() const + { + return ownerThread_; + } private: inline void CollectRSetItemsInHeap(const Heap *heap); @@ -73,6 +76,8 @@ private: inline bool TryMergeBack(); Heap *heap_ {nullptr}; + // The thread is not guaranteed to be alive. The caller must ensure that the thread is alive. + JSThread *ownerThread_ {nullptr}; /** * This value represent whether there are some items to process, this is set to true in Initialize when collecting * the RSet in heap(call from daemon thread in SuspendAll), and use CAS to set to false when try to merge back and @@ -85,7 +90,6 @@ private: * And thus WaitFinishedThenMergeBack should ONLY be called from the bound js thread in RUNNING state. */ bool initialized_ {false}; - bool processRsetFinished_ {false}; std::vector items_; std::atomic nextItemIndex_ {-1}; int remainItems_ {0}; diff --git a/ecmascript/mem/shared_heap/shared_concurrent_sweeper.cpp b/ecmascript/mem/shared_heap/shared_concurrent_sweeper.cpp index 60fff073d04c9741f99a5f5092c2e214d8e65c77..82d8e81c99226c376de5b68671b0f1d68b8acadd 100644 --- a/ecmascript/mem/shared_heap/shared_concurrent_sweeper.cpp +++ b/ecmascript/mem/shared_heap/shared_concurrent_sweeper.cpp @@ -29,10 +29,10 @@ void SharedConcurrentSweeper::PostTask(bool isFullGC) if (ConcurrentSweepEnabled()) { if (!isFullGC) { Taskpool::GetCurrentTaskpool()->PostTask( - std::make_unique(tid, this, SHARED_OLD_SPACE)); + std::make_unique(tid, this, SHARED_OLD_SPACE, isFullGC)); } Taskpool::GetCurrentTaskpool()->PostTask( - std::make_unique(tid, this, SHARED_NON_MOVABLE)); + std::make_unique(tid, this, SHARED_NON_MOVABLE, isFullGC)); } } @@ -145,12 +145,12 @@ bool SharedConcurrentSweeper::SweeperTask::Run([[maybe_unused]] uint32_t threadI { if (type_ == SHARED_NON_MOVABLE) { sweeper_->AsyncSweepSpace(SHARED_NON_MOVABLE, false); - if (!sweeper_->isFullGC_) { + if (!isFullGC_) { sweeper_->AsyncSweepSpace(SHARED_OLD_SPACE, false); } } else { ASSERT(type_ == SHARED_OLD_SPACE); - if (!sweeper_->isFullGC_) { + if (!isFullGC_) { sweeper_->AsyncSweepSpace(SHARED_OLD_SPACE, false); } sweeper_->AsyncSweepSpace(SHARED_NON_MOVABLE, false); diff --git a/ecmascript/mem/shared_heap/shared_concurrent_sweeper.h b/ecmascript/mem/shared_heap/shared_concurrent_sweeper.h index 206197aaa4ff620a00b69a4c3f3664dd53f164b3..106a240a1fc0d910c18f9c75c0301fea049f1748 100644 --- a/ecmascript/mem/shared_heap/shared_concurrent_sweeper.h +++ b/ecmascript/mem/shared_heap/shared_concurrent_sweeper.h @@ -76,8 +76,8 @@ public: private: class SweeperTask : public Task { public: - SweeperTask(int32_t id, SharedConcurrentSweeper *sweeper, MemSpaceType type) - : Task(id), sweeper_(sweeper), type_(type) {}; + SweeperTask(int32_t id, SharedConcurrentSweeper *sweeper, MemSpaceType type, bool isFullGC) + : Task(id), sweeper_(sweeper), type_(type), isFullGC_(isFullGC) {}; ~SweeperTask() override = default; bool Run(uint32_t threadIndex) override; @@ -87,6 +87,7 @@ private: private: SharedConcurrentSweeper *sweeper_; MemSpaceType type_; + bool isFullGC_; }; void AsyncSweepSpace(MemSpaceType type, bool isMain); diff --git a/ecmascript/mem/shared_heap/shared_gc_marker-inl.h b/ecmascript/mem/shared_heap/shared_gc_marker-inl.h index 2ecacffd5b060c625822b84ef8f5e1f1e62a0ae5..7066ac313ce0aa4cf15949202619bd56756514ea 100644 --- a/ecmascript/mem/shared_heap/shared_gc_marker-inl.h +++ b/ecmascript/mem/shared_heap/shared_gc_marker-inl.h @@ -173,7 +173,9 @@ inline void SharedGCMarkerBase::ProcessVisitorOfDoMark(uint32_t threadId) for (RSetWorkListHandler *handler : rSetHandlers_) { ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGCMarker::ProcessRSet"); handler->ProcessAll(visitor); - handler->NotifyProcessRsetFinished(); + // To ensure the accuracy of the state range, notify finished is executed on js thread and deamon thread. + // Reentrant does not cause exceptions because all the values are set to false. + NotifyThreadProcessRsetFinished(handler->GetOwnerThreadUnsafe()); } } @@ -220,7 +222,25 @@ inline void SharedGCMarkerBase::ProcessThenMergeBackRSetFromBoundJSThread(RSetWo ASSERT(JSThread::GetCurrent()->IsInRunningState()); ProcessVisitor(handler); handler->WaitFinishedThenMergeBack(); - handler->NotifyProcessRsetFinished(); +} + +inline void SharedGCMarkerBase::NotifyThreadProcessRsetStart(JSThread *localThread) +{ + // This method is called within the GCIterateThreadList method, + // so the thread lock problem does not need to be considered. + ASSERT(localThread != nullptr); + localThread->SetProcessingLocalToSharedRset(true); +} + +inline void SharedGCMarkerBase::NotifyThreadProcessRsetFinished(JSThread *localThread) +{ + // The localThread may have been released or reused. + Runtime::GetInstance()->GCIterateThreadList([localThread](JSThread *thread) { + if (localThread == thread) { + thread->SetProcessingLocalToSharedRset(false); + return; + } + }); } void SharedGCMovableMarker::MarkObject(uint32_t threadId, TaggedObject *object, ObjectSlot &slot) diff --git a/ecmascript/mem/shared_heap/shared_gc_marker.cpp b/ecmascript/mem/shared_heap/shared_gc_marker.cpp index f4d6b6b2bfb15bd58a6e980f48969964dd08c877..c3b93203d598b320512fd756438ac9ee2100abf5 100644 --- a/ecmascript/mem/shared_heap/shared_gc_marker.cpp +++ b/ecmascript/mem/shared_heap/shared_gc_marker.cpp @@ -66,9 +66,9 @@ void SharedGCMarkerBase::CollectLocalVMRSet(EcmaVM *localVm) { ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGCMarkerBase::CollectLocalVMRSet"); Heap *heap = const_cast(localVm->GetHeap()); - RSetWorkListHandler *handler = new RSetWorkListHandler(heap); + RSetWorkListHandler *handler = new RSetWorkListHandler(heap, localVm->GetJSThreadNoCheck()); heap->SetRSetWorkListHandler(handler); - heap->SetProcessingRset(true); + NotifyThreadProcessRsetStart(handler->GetOwnerThreadUnsafe()); rSetHandlers_.emplace_back(handler); } diff --git a/ecmascript/mem/shared_heap/shared_gc_marker.h b/ecmascript/mem/shared_heap/shared_gc_marker.h index ceaaa251a9ab6f1cf58c21f4de2dcc23a773c5d6..7c5a71bcafb092766454e858070fc65f59e6f8bc 100644 --- a/ecmascript/mem/shared_heap/shared_gc_marker.h +++ b/ecmascript/mem/shared_heap/shared_gc_marker.h @@ -91,6 +91,11 @@ protected: SharedGCWorkManager *sWorkManager_ {nullptr}; private: + // This method is called within the GCIterateThreadList method, + // so the thread lock problem does not need to be considered. + inline void NotifyThreadProcessRsetStart(JSThread *localThread); + inline void NotifyThreadProcessRsetFinished(JSThread *localThread); + template inline auto GenerateRSetVisitor(uint32_t threadId); inline void RecordObject(JSTaggedValue value, uint32_t threadId, void *mem); diff --git a/ecmascript/mem/shared_heap/shared_space.cpp b/ecmascript/mem/shared_heap/shared_space.cpp index 0f7ccbbc3494c8cf6e8076e1954c08b1540f631b..9194625ab164739fe263fa3418cfcd3dd6e222d2 100644 --- a/ecmascript/mem/shared_heap/shared_space.cpp +++ b/ecmascript/mem/shared_heap/shared_space.cpp @@ -203,7 +203,10 @@ uintptr_t SharedSparseSpace::AllocateAfterSweepingCompleted([[maybe_unused]] JST void SharedSparseSpace::PrepareSweeping() { liveObjectSize_ = 0; + ASSERT(GetSweepingRegionSafe() == nullptr); + ASSERT(GetSweptRegionSafe() == nullptr); EnumerateRegions([this](Region *current) { + ASSERT(!current->IsGCFlagSet(RegionGCFlags::HAS_BEEN_SWEPT)); IncreaseLiveObjectSize(current->AliveObject()); current->ResetWasted(); AddSweepingRegion(current); @@ -484,14 +487,24 @@ void SharedLocalSpace::Stop() } } +void SharedLocalSpace::ForceExpandInSharedGC(JSThread *thread) +{ + Region *region = heapRegionAllocator_->AllocateAlignedRegion(this, DEFAULT_REGION_SIZE, thread, sHeap_); + AddRegion(region); + allocator_->AddFree(region); +} + uintptr_t SharedLocalSpace::Allocate(size_t size, bool isExpand) { auto object = allocator_->Allocate(size); - if (object == 0) { + if (object == 0 && isExpand) { // Shared Full GC will compress all regions and cannot recognize all threads' region. - if (isExpand && Expand(Runtime::GetInstance()->GetMainThread())) { - object = allocator_->Allocate(size); + if (!Expand(Runtime::GetInstance()->GetMainThread())) { + ForceExpandInSharedGC(Runtime::GetInstance()->GetMainThread()); + sHeap_->ShouldThrowOOMError(true); } + object = allocator_->Allocate(size); + ASSERT(object != 0); } if (object != 0) { Region::ObjectAddressToRange(object)->IncreaseAliveObject(size); diff --git a/ecmascript/mem/shared_heap/shared_space.h b/ecmascript/mem/shared_heap/shared_space.h index 7e03ba5f0e5bb8934bd7b9d8acd0203e88e26bb1..e4fe482a71ecca2be0faa942d25c9046b5e7ed83 100644 --- a/ecmascript/mem/shared_heap/shared_space.h +++ b/ecmascript/mem/shared_heap/shared_space.h @@ -177,6 +177,8 @@ public: bool AddRegionToList(Region *region); void FreeBumpPoint(); void Stop(); +private: + void ForceExpandInSharedGC(JSThread *thread); }; class SharedReadOnlySpace : public Space { diff --git a/ecmascript/mem/space.h b/ecmascript/mem/space.h index b865daa853e867c4c9f28532aae635ac291b901d..f98a20857cd976ec1380a003d36e80bdfcfdc295 100644 --- a/ecmascript/mem/space.h +++ b/ecmascript/mem/space.h @@ -77,6 +77,7 @@ static inline std::string ToSpaceTypeName(MemSpaceType type) { switch (type) { case OLD_SPACE: + case LOCAL_SPACE: return "old space"; case NON_MOVABLE: return "non movable space"; @@ -92,8 +93,6 @@ static inline std::string ToSpaceTypeName(MemSpaceType type) return "snapshot space"; case COMPRESS_SPACE: return "compress space"; - case LOCAL_SPACE: - return "local space"; case READ_ONLY_SPACE: return "read only space"; case APPSPAWN_SPACE: @@ -103,6 +102,7 @@ static inline std::string ToSpaceTypeName(MemSpaceType type) case SHARED_NON_MOVABLE: return "shared non movable space"; case SHARED_OLD_SPACE: + case SHARED_LOCAL_SPACE: return "shared old space"; case SHARED_READ_ONLY_SPACE: return "shared read only space"; @@ -110,8 +110,6 @@ static inline std::string ToSpaceTypeName(MemSpaceType type) return "shared huge object space"; case SHARED_COMPRESS_SPACE: return "compress space"; - case SHARED_LOCAL_SPACE: - return "shared local space"; case SHARED_APPSPAWN_SPACE: return "shared appspawn space"; default: diff --git a/ecmascript/mem/sparse_space.cpp b/ecmascript/mem/sparse_space.cpp index b4fd9f5331ff2e0bacfd0f77d3e2f7b389bff33d..dbe95d76d487ea7d9168bfe6d96db784988d699a 100644 --- a/ecmascript/mem/sparse_space.cpp +++ b/ecmascript/mem/sparse_space.cpp @@ -116,8 +116,11 @@ uintptr_t SparseSpace::AllocateAfterSweepingCompleted(size_t size) void SparseSpace::PrepareSweeping() { liveObjectSize_ = 0; + ASSERT(GetSweepingRegionSafe() == nullptr); + ASSERT(GetSweptRegionSafe() == nullptr); EnumerateRegions([this](Region *current) { if (!current->InCollectSet()) { + ASSERT(!current->IsGCFlagSet(RegionGCFlags::HAS_BEEN_SWEPT)); if (UNLIKELY(localHeap_->ShouldVerifyHeap() && current->IsGCFlagSet(RegionGCFlags::HAS_BEEN_SWEPT))) { // LOCV_EXCL_BR_LINE LOG_ECMA(FATAL) << "Region should not be swept before PrepareSweeping: " << current; @@ -605,16 +608,25 @@ void AppSpawnSpace::IterateOverMarkedObjects(const std::functionGetJSThread(); + Region *region = heapRegionAllocator_->AllocateAlignedRegion(this, DEFAULT_REGION_SIZE, thread, localHeap_); + region->SetLocalHeap(reinterpret_cast(localHeap_)); + AddRegion(region); + allocator_->AddFree(region); +} + uintptr_t LocalSpace::Allocate(size_t size, bool isExpand) { auto object = allocator_->Allocate(size); if (object == 0 && isExpand) { - if (Expand()) { - object = allocator_->Allocate(size); - } else { - localHeap_->ThrowOutOfMemoryErrorForDefault(localHeap_->GetJSThread(), size, - " LocalSpace::Allocate", false); + if (!Expand()) { + ForceExpandInGC(); + localHeap_->ShouldThrowOOMError(true); } + object = allocator_->Allocate(size); + ASSERT(object != 0); } if (object != 0) { Region::ObjectAddressToRange(object)->IncreaseAliveObject(size); diff --git a/ecmascript/mem/sparse_space.h b/ecmascript/mem/sparse_space.h index b6b907ec2506ab07b68dda1d7325a82106facd6d..147a744bd76e140f50f7de2a8d625f000ad9abc7 100644 --- a/ecmascript/mem/sparse_space.h +++ b/ecmascript/mem/sparse_space.h @@ -261,6 +261,8 @@ public: bool AddRegionToList(Region *region); void FreeBumpPoint(); void Stop(); +private: + void ForceExpandInGC(); }; class MachineCode; diff --git a/ecmascript/mem/verification.cpp b/ecmascript/mem/verification.cpp index 2ad27ac805aefd8450b5f86d7017c4e9277a3bf6..1c91e7b85e7d0a8e59908cfed006a114d41580ed 100644 --- a/ecmascript/mem/verification.cpp +++ b/ecmascript/mem/verification.cpp @@ -120,7 +120,7 @@ void VerifyObjectVisitor::VerifyObjectSlotLegal(ObjectSlot slot, TaggedObject *o LogErrorForObjSlot(heap_, "Heap verify detected an invalid value.", object, slot, value.GetTaggedWeakRef()); } - if (!heap_->IsAlive(value.GetTaggedWeakRef())) { + if (!heap_->IsAlive(value.GetTaggedWeakRef()) && failCount_ != nullptr) { LogErrorForObjSlot(heap_, "Heap verify detected a dead weak object.", object, slot, value.GetTaggedWeakRef()); ++(*failCount_); @@ -139,7 +139,7 @@ void VerifyObjectVisitor::VerifyHeapObjectSlotLegal(ObjectSlot slot, LogErrorForObjSlot(heap_, "Heap verify detected an invalid value.", object, slot, slotValue.GetTaggedObject()); } - if (!heap_->IsAlive(slotValue.GetTaggedObject())) { + if (!heap_->IsAlive(slotValue.GetTaggedObject()) && failCount_ != nullptr) { LogErrorForObjSlot(heap_, "Heap verify detected a dead object.", object, slot, slotValue.GetTaggedObject()); ++(*failCount_); @@ -417,7 +417,7 @@ void VerifyObjectVisitor::operator()(TaggedObject *obj, JSTaggedValue value) TaggedObject *object = value.GetRawTaggedObject(); auto region = Region::ObjectAddressToRange(object); - if (region->InGeneralOldSpace()) { // LCOV_EXCL_START + if (region->InGeneralOldSpace() && failCount_ != nullptr) { // LCOV_EXCL_START LOG_GC(ERROR) << "Heap object(" << slot.GetTaggedType() << ") old to new rset fail: value(" << slot.GetTaggedObject() << "/" << JSHClass::DumpJSType(slot.GetTaggedObject()->GetClass()->GetObjectType()) diff --git a/ecmascript/mem/work_manager.cpp b/ecmascript/mem/work_manager.cpp index 6f0dfd400a3fa816fb5b80d767eeb9b41ab240d3..0fe60832f01864509306cf78a358c947777a01e1 100644 --- a/ecmascript/mem/work_manager.cpp +++ b/ecmascript/mem/work_manager.cpp @@ -87,7 +87,9 @@ void WorkManager::PushWorkNodeToGlobal(uint32_t threadId, bool postTask) WorkNode *&inNode = works_.at(threadId).inNode_; if (!inNode->IsEmpty()) { workStack_.Push(inNode); - inNode = AllocateWorkNode(); + inNode = works_.at(threadId).cachedInNode_; + ASSERT(inNode != nullptr); + works_.at(threadId).cachedInNode_ = AllocateWorkNode(); if (postTask && heap_->IsParallelGCEnabled() && heap_->CheckCanDistributeTask() && !(heap_->IsMarking() && heap_->GetIncrementalMarker()->IsTriggeredIncrementalMark())) { heap_->PostParallelGCTask(parallelGCTaskPhase_); @@ -162,6 +164,7 @@ void WorkManager::Initialize(TriggerGCType gcType, ParallelGCTaskPhase taskPhase for (uint32_t i = 0; i < threadNum_; i++) { WorkNodeHolder &holder = works_.at(i); holder.inNode_ = AllocateWorkNode(); + holder.cachedInNode_ = AllocateWorkNode(); holder.outNode_ = AllocateWorkNode(); holder.weakQueue_ = new ProcessQueue(); holder.weakQueue_->BeginMarking(continuousQueue_.at(i)); @@ -204,6 +207,7 @@ void SharedGCWorkManager::Initialize(TriggerGCType gcType, SharedParallelMarkPha for (uint32_t i = 0; i < threadNum_; i++) { SharedGCWorkNodeHolder &holder = works_.at(i); holder.inNode_ = AllocateWorkNode(); + holder.cachedInNode_ = AllocateWorkNode(); holder.outNode_ = AllocateWorkNode(); holder.weakQueue_ = new ProcessQueue(); holder.weakQueue_->BeginMarking(continuousQueue_.at(i)); @@ -270,7 +274,9 @@ void SharedGCWorkManager::PushWorkNodeToGlobal(uint32_t threadId, bool postTask) WorkNode *&inNode = works_.at(threadId).inNode_; if (!inNode->IsEmpty()) { workStack_.Push(inNode); - inNode = AllocateWorkNode(); + inNode = works_.at(threadId).cachedInNode_; + ASSERT(inNode != nullptr); + works_.at(threadId).cachedInNode_ = AllocateWorkNode(); if (postTask && sHeap_->IsParallelGCEnabled() && sHeap_->CheckCanDistributeTask()) { sHeap_->PostGCMarkingTask(sharedTaskPhase_); } diff --git a/ecmascript/mem/work_manager.h b/ecmascript/mem/work_manager.h index 2fed3d807f25e56c225794f8d7636c4edb8dfb74..8cc3311b74a73ec8fdfbe4fe1db6e02776ec0634 100644 --- a/ecmascript/mem/work_manager.h +++ b/ecmascript/mem/work_manager.h @@ -133,6 +133,7 @@ private: struct WorkNodeHolder { WorkNode *inNode_ {nullptr}; WorkNode *outNode_ {nullptr}; + WorkNode *cachedInNode_ {nullptr}; ProcessQueue *weakQueue_ {nullptr}; std::vector pendingUpdateSlots_; TlabAllocator *allocator_ {nullptr}; @@ -264,6 +265,7 @@ private: struct SharedGCWorkNodeHolder { WorkNode *inNode_ {nullptr}; + WorkNode *cachedInNode_ {nullptr}; WorkNode *outNode_ {nullptr}; ProcessQueue *weakQueue_ {nullptr}; SharedTlabAllocator *allocator_ {nullptr}; diff --git a/ecmascript/module/js_module_manager.cpp b/ecmascript/module/js_module_manager.cpp index b0404b7dcf76b4c69473079b6c44bb8b9bb3f8a5..71a5b237c32efbead542821008c917bfac0c671f 100644 --- a/ecmascript/module/js_module_manager.cpp +++ b/ecmascript/module/js_module_manager.cpp @@ -181,7 +181,7 @@ JSTaggedValue ModuleManager::GetLazyModuleValueOutterInternal(int32_t index, JST if (resolvedBinding.IsResolvedIndexBinding()) { JSHandle binding(thread, resolvedBinding); JSTaggedValue resolvedModule = binding->GetModule(); - JSHandle module(thread, resolvedModule); + JSMutableHandle module(thread, resolvedModule); ASSERT(resolvedModule.IsSourceTextModule()); // Support for only modifying var value of HotReload. // Cause patchFile exclude the record of importing modifying var. Can't reresolve moduleRecord. @@ -191,13 +191,12 @@ JSTaggedValue ModuleManager::GetLazyModuleValueOutterInternal(int32_t index, JST context->FindPatchModule(module->GetEcmaModuleRecordNameString()); if (!resolvedModuleOfHotReload->IsHole()) { resolvedModule = resolvedModuleOfHotReload.GetTaggedValue(); - JSHandle moduleOfHotReload(thread, resolvedModule); - SourceTextModule::Evaluate(thread, moduleOfHotReload, nullptr); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); - return ModuleManagerHelper::GetModuleValue(thread, moduleOfHotReload, binding->GetIndex()); + module.Update(resolvedModule); } } - SourceTextModule::Evaluate(thread, module, nullptr); + if (module->GetStatus() != ModuleStatus::EVALUATED) { + SourceTextModule::Evaluate(thread, module, nullptr, 0, context->IsInPendingJob()); + } RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); return ModuleManagerHelper::GetModuleValue(thread, module, binding->GetIndex()); } @@ -254,7 +253,7 @@ void ModuleManager::StoreModuleValueInternal(JSHandle ¤t } JSThread *thread = vm_->GetJSThread(); JSHandle valueHandle(thread, value); - currentModule->StoreModuleValue(thread, index, valueHandle); + SourceTextModule::StoreModuleValue(thread, currentModule, index, valueHandle); } JSTaggedValue ModuleManager::GetModuleValueInner(JSTaggedValue key) @@ -342,7 +341,7 @@ void ModuleManager::StoreModuleValueInternal(JSHandle ¤t JSThread *thread = vm_->GetJSThread(); JSHandle keyHandle(thread, key); JSHandle valueHandle(thread, value); - currentModule->StoreModuleValue(thread, keyHandle, valueHandle); + SourceTextModule::StoreModuleValue(thread, currentModule, keyHandle, valueHandle); } JSHandle ModuleManager::GetImportedModule(const CString &referencing) { @@ -610,7 +609,7 @@ JSHandle ModuleManager::ExecuteNativeModuleMayThrowError(JSThread JSHandle(thread, JSTaggedValue::Undefined())); nativeModule->SetStatus(ModuleStatus::EVALUATED); nativeModule->SetLoadingTypes(LoadingTypes::STABLE_MODULE); - nativeModule->StoreModuleValue(thread, 0, JSNApiHelper::ToJSHandle(exportObject)); + SourceTextModule::StoreModuleValue(thread, nativeModule, 0, JSNApiHelper::ToJSHandle(exportObject)); AddResolveImportedModule(recordName, moduleRecord.GetTaggedValue()); return JSNApiHelper::ToJSHandle(exportObject); } diff --git a/ecmascript/module/js_module_namespace.cpp b/ecmascript/module/js_module_namespace.cpp index 686316fdc93549c8a20b0fa6e4fa358d53f75397..1207aa242261ac7fb45e85954f0cd4b97cf00544 100644 --- a/ecmascript/module/js_module_namespace.cpp +++ b/ecmascript/module/js_module_namespace.cpp @@ -177,7 +177,7 @@ JSHandle ModuleNamespace::OwnPropertyKeys(JSThread *thread, const J JSHandle moduleNamespace = JSHandle::Cast(obj); JSHandle exports(thread, moduleNamespace->GetExports()); JSHandle exportsArray = JSArray::ToTaggedArray(thread, exports); - if (!moduleNamespace->ValidateKeysAvailable(thread, exportsArray)) { + if (!ModuleNamespace::ValidateKeysAvailable(thread, moduleNamespace, exportsArray)) { return exportsArray; } @@ -196,7 +196,7 @@ JSHandle ModuleNamespace::OwnEnumPropertyKeys(JSThread *thread, con JSHandle moduleNamespace = JSHandle::Cast(obj); JSHandle exports(thread, moduleNamespace->GetExports()); JSHandle exportsArray = JSArray::ToTaggedArray(thread, exports); - if (!moduleNamespace->ValidateKeysAvailable(thread, exportsArray)) { + if (!ModuleNamespace::ValidateKeysAvailable(thread, moduleNamespace, exportsArray)) { return exportsArray; } @@ -351,9 +351,10 @@ bool ModuleNamespace::DeleteProperty(JSThread *thread, const JSHandle &exports) +// static +bool ModuleNamespace::ValidateKeysAvailable(JSThread *thread, const JSHandle &moduleNamespace, + const JSHandle &exports) { - JSHandle moduleNamespace(thread, this); JSHandle mm(thread, moduleNamespace->GetModule()); uint32_t exportsLength = exports->GetLength(); for (uint32_t idx = 0; idx < exportsLength; idx++) { diff --git a/ecmascript/module/js_module_namespace.h b/ecmascript/module/js_module_namespace.h index cbd44fac23cfe7d6100c1fdad9962f7418f308f3..00fe8ec2871f5fba89b7673ee2c5bbef0a146a3e 100644 --- a/ecmascript/module/js_module_namespace.h +++ b/ecmascript/module/js_module_namespace.h @@ -58,7 +58,8 @@ public: static JSHandle OwnEnumPropertyKeys(JSThread *thread, const JSHandle &obj); - bool ValidateKeysAvailable(JSThread *thread, const JSHandle &exports); + static bool ValidateKeysAvailable(JSThread *thread, const JSHandle &moduleNamespace, + const JSHandle &exports); static constexpr size_t MODULE_OFFSET = JSObject::SIZE; ACCESSORS(Module, MODULE_OFFSET, EXPORTS_OFFSET) diff --git a/ecmascript/module/js_module_source_text.cpp b/ecmascript/module/js_module_source_text.cpp index 01fc67bc8dc85d369a6a40ce5111706738210d54..0d3b3f31ef95bed86f3cb3648d317e321d3b6bec 100644 --- a/ecmascript/module/js_module_source_text.cpp +++ b/ecmascript/module/js_module_source_text.cpp @@ -389,12 +389,12 @@ bool SourceTextModule::LoadNativeModule(JSThread *thread, const JSHandleIsNativeModuleFailureInfoObject(vm))) { - requiredModule->StoreModuleValue(thread, 0, JSNApiHelper::ToJSHandle(exportObject)); + SourceTextModule::StoreModuleValue(thread, requiredModule, 0, JSNApiHelper::ToJSHandle(exportObject)); LOG_FULL(ERROR) << "loading fails, NativeModuleErrorObject is returned"; return false; } ASSERT(!thread->HasPendingException()); - requiredModule->StoreModuleValue(thread, 0, JSNApiHelper::ToJSHandle(exportObject)); + SourceTextModule::StoreModuleValue(thread, requiredModule, 0, JSNApiHelper::ToJSHandle(exportObject)); return true; } @@ -558,10 +558,13 @@ int SourceTextModule::InnerModuleInstantiation(JSThread *thread, const JSHandle< if (status == ModuleStatus::INSTANTIATING || status == ModuleStatus::INSTANTIATED || status == ModuleStatus::EVALUATING_ASYNC || - status == ModuleStatus::EVALUATING || status == ModuleStatus::EVALUATED) { return index; } + if (SourceTextModule::IsSharedModule(module) && status == ModuleStatus::EVALUATING) { + LOG_FULL(INFO) << "circular dependency occurred of shared-module"; + return index; + } // 3. Assert: module.[[Status]] is "uninstantiated". ASSERT(status == ModuleStatus::UNINSTANTIATED); // 4. Set module.[[Status]] to "instantiating". @@ -1282,7 +1285,6 @@ void SourceTextModule::AddStarExportEntry(JSThread *thread, const JSHandle &value) +// static +void SourceTextModule::StoreModuleValue(JSThread *thread, const JSHandle &module, int32_t index, + const JSHandle &value) { - JSHandle module(thread, this); if (UNLIKELY(IsSharedModule(module)) && !value->IsSharedType()) { CString msg = "Export non-shared object from shared-module, module name is :" + module->GetEcmaModuleRecordNameString(); @@ -1383,11 +1385,11 @@ void SourceTextModule::StoreModuleValue(JSThread *thread, int32_t index, const J arr->Set(thread, index, value); } -// discard instructions won't consider shared-module. -void SourceTextModule::StoreModuleValue(JSThread *thread, const JSHandle &key, - const JSHandle &value) +// static +// discard instructions won't consider shared-module. +void SourceTextModule::StoreModuleValue(JSThread *thread, const JSHandle &module, + const JSHandle &key, const JSHandle &value) { - JSHandle module(thread, this); if (UNLIKELY(IsSharedModule(module)) && !value->IsSharedType()) { CString msg = "Export non-shared object from shared-module, module name is :" + module->GetEcmaModuleRecordNameString(); diff --git a/ecmascript/module/js_module_source_text.h b/ecmascript/module/js_module_source_text.h index 33eaa70bbfacfe367518073adf8ce6fe0b684ca3..3cdd718a4791326f11bf55cf15e98694b130fafe 100644 --- a/ecmascript/module/js_module_source_text.h +++ b/ecmascript/module/js_module_source_text.h @@ -345,10 +345,12 @@ public: ModuleTypes moduleType); JSTaggedValue GetModuleValue(JSThread *thread, int32_t index, bool isThrow); - void StoreModuleValue(JSThread *thread, int32_t index, const JSHandle &value); + static void StoreModuleValue(JSThread *thread, const JSHandle &module, int32_t index, + const JSHandle &value); JSTaggedValue GetModuleValue(JSThread *thread, JSTaggedValue key, bool isThrow); - void StoreModuleValue(JSThread *thread, const JSHandle &key, const JSHandle &value); + static void StoreModuleValue(JSThread *thread, const JSHandle &module, + const JSHandle &key, const JSHandle &value); static JSTaggedValue GetValueFromExportObject(JSThread *thread, JSHandle &exportObject, int32_t index); diff --git a/ecmascript/module/module_data_extractor.cpp b/ecmascript/module/module_data_extractor.cpp index 693aa728cf3833c4005a125befc82a4085fd209a..377d18c4450ea5ccf1d3112ed7eb1f92602b7474 100644 --- a/ecmascript/module/module_data_extractor.cpp +++ b/ecmascript/module/module_data_extractor.cpp @@ -122,7 +122,7 @@ JSHandle ModuleDataExtractor::ParseJsonModule(JSThread *thread, c defaultName, LocalExportEntry::LOCAL_DEFAULT_INDEX, SharedTypes::UNSENDABLE_MODULE); SourceTextModule::AddLocalExportEntry(thread, moduleRecord, localExportEntry, 0, 1); // 1 means len JSTaggedValue jsonData = JsonParse(thread, jsPandaFile, recordName); - moduleRecord->StoreModuleValue(thread, 0, JSHandle(thread, jsonData)); // index = 0 + SourceTextModule::StoreModuleValue(thread, moduleRecord, 0, JSHandle(thread, jsonData)); // index = 0 moduleRecord->SetEcmaModuleFilenameString(moduleFilename); @@ -149,7 +149,7 @@ JSHandle ModuleDataExtractor::ParseNativeModule(JSThread *thread, moduleRecord->SetTypes(moduleType); moduleRecord->SetIsNewBcVersion(true); moduleRecord->SetStatus(ModuleStatus::INSTANTIATED); - moduleRecord->StoreModuleValue(thread, 0, thread->GlobalConstants()->GetHandledUndefined()); + SourceTextModule::StoreModuleValue(thread, moduleRecord, 0, thread->GlobalConstants()->GetHandledUndefined()); return JSHandle::Cast(moduleRecord); } diff --git a/ecmascript/module/tests/BUILD.gn b/ecmascript/module/tests/BUILD.gn index c383baf4f565e829e745064c6fd19f56360eec76..16c444d12de40a278401e154e34571a0b1696a89 100644 --- a/ecmascript/module/tests/BUILD.gn +++ b/ecmascript/module/tests/BUILD.gn @@ -52,7 +52,7 @@ foreach(file, test_js_files) { } } -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("ModuleTest") { module_out_path = module_output_path diff --git a/ecmascript/module/tests/ecma_module_test.cpp b/ecmascript/module/tests/ecma_module_test.cpp index 1b4d1b379f4612684fe219f54bf0650496cf6045..7b88311c9f51784ed4b2f215ba8f5cc9ec5630af 100644 --- a/ecmascript/module/tests/ecma_module_test.cpp +++ b/ecmascript/module/tests/ecma_module_test.cpp @@ -108,6 +108,7 @@ Local EcmaModuleTest::MockRequireNapiException(JsiRuntimeCallInfo *r JSNApi::ThrowException(vm, error); return message; } + /* * Feature: Module * Function: AddImportEntry @@ -209,7 +210,7 @@ HWTEST_F_L0(EcmaModuleTest, StoreModuleValue) JSHandle storeKey = JSHandle::Cast(objFactory->NewFromUtf8(localName)); JSHandle valueHandle = JSHandle::Cast(objFactory->NewFromUtf8(value)); - module->StoreModuleValue(thread, storeKey, valueHandle); + SourceTextModule::StoreModuleValue(thread, module, storeKey, valueHandle); JSHandle loadKey = JSHandle::Cast(objFactory->NewFromUtf8(localName)); JSTaggedValue loadValue = module->GetModuleValue(thread, loadKey.GetTaggedValue(), false); @@ -241,7 +242,7 @@ HWTEST_F_L0(EcmaModuleTest, GetModuleValue) SourceTextModule::AddLocalExportEntry(thread, moduleExport, localExportEntry, 0, 1); // store module value JSHandle exportValueHandle = JSHandle::Cast(objFactory->NewFromUtf8(exportValue)); - moduleExport->StoreModuleValue(thread, exportLocalNameHandle, exportValueHandle); + SourceTextModule::StoreModuleValue(thread, moduleExport, exportLocalNameHandle, exportValueHandle); JSTaggedValue importDefaultValue = moduleExport->GetModuleValue(thread, exportLocalNameHandle.GetTaggedValue(), false); @@ -287,11 +288,11 @@ HWTEST_F_L0(EcmaModuleTest, FindByExport) JSHandle storeKey = JSHandle::Cast(objFactory->NewFromUtf8(localName1)); JSHandle valueHandle = JSHandle::Cast(objFactory->NewFromUtf8(value)); - module->StoreModuleValue(thread, storeKey, valueHandle); + SourceTextModule::StoreModuleValue(thread, module, storeKey, valueHandle); JSHandle storeKey2 = JSHandle::Cast(objFactory->NewFromUtf8(localName2)); JSHandle valueHandle2 = JSHandle::Cast(objFactory->NewFromUtf8(value2)); - module->StoreModuleValue(thread, storeKey2, valueHandle2); + SourceTextModule::StoreModuleValue(thread, module, storeKey2, valueHandle2); // FindByExport cannot find key from exportEntries, returns Hole() JSHandle loadKey1 = JSHandle::Cast(objFactory->NewFromUtf8(localName3)); @@ -521,6 +522,12 @@ HWTEST_F_L0(EcmaModuleTest, TranstaleExpressionInput) CString requestPath = "@arkui-x.test/moduleName/requestModuleName"; ModulePathHelper::TranstaleExpressionInput(pf.get(), requestPath); EXPECT_EQ(requestPath, "@ohos:test/moduleName/requestModuleName"); + + requestPath = "@ohos.app:@native.system.app"; + CString fieldName = requestPath; + pf->InsertNpmEntries(requestPath, fieldName); + ModulePathHelper::TranstaleExpressionInput(pf.get(), requestPath); + EXPECT_EQ(requestPath, "@ohos:app:@native.system.app"); } HWTEST_F_L0(EcmaModuleTest, ParseFileNameToVMAName2) @@ -755,6 +762,13 @@ HWTEST_F_L0(EcmaModuleTest, ConcatFileNameWithMerge1) moduleRequestName); EXPECT_EQ(result, entryPoint); + // Test moduleRequestName start with "@package:" + moduleRequestName = "@package:test"; + result = "test"; + entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, pf.get(), baseFilename, moduleRecordName, + moduleRequestName); + EXPECT_EQ(result, entryPoint); + // Test cross application moduleRecordName = "@bundle:com.bundleName1.test/moduleName/requestModuleName1"; CString newBaseFileName = "/data/storage/el1/bundle/com.bundleName.test/moduleName/moduleName/ets/modules.abc"; @@ -928,6 +942,37 @@ HWTEST_F_L0(EcmaModuleTest, ConcatFileNameWithMerge4) recordInfo.erase(result); } +HWTEST_F_L0(EcmaModuleTest, ConcatFileNameWithMerge5) +{ + instance->SetBundleName("com.example.myapplication"); + CString baseFilename = "merge.abc"; + const char *data = R"( + .language ECMAScript + .function any func_main_0(any a0, any a1, any a2) { + ldai 1 + return + } + )"; + JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance(); + Parser parser; + auto res = parser.Parse(data); + std::unique_ptr pfPtr = pandasm::AsmEmitter::Emit(res.Value()); + std::shared_ptr pf = pfManager->NewJSPandaFile(pfPtr.release(), baseFilename); + + CString baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + CString requestName = "ets/Test"; + CString recordName = "com.example.myapplication/entry/ets/pages/Index"; + CString expectRes = "com.example.myapplication/entry/ets/Test"; + CString result = ModulePathHelper::ConcatFileNameWithMerge(thread, pf.get(), baseFileName, recordName, + requestName); + EXPECT_EQ(result, ""); + + pf->InsertJSRecordInfo(expectRes); + result = ModulePathHelper::ConcatFileNameWithMerge(thread, pf.get(), baseFileName, recordName, + requestName); + EXPECT_EQ(result, expectRes); +} + HWTEST_F_L0(EcmaModuleTest, NormalizePath) { @@ -1298,6 +1343,45 @@ HWTEST_F_L0(EcmaModuleTest, ConcatNotSoNormalizedOhmurl) EXPECT_EQ(outFileName, exceptOutFileName); } +HWTEST_F_L0(EcmaModuleTest, TransformToNormalizedOhmUrl2) +{ + CString inputFileName = "/data/storage/el1/bundle/hsp/ets/modules.abc"; + CString outBaseFileName = "/data/storage/el1/bundle/com.example.application/hsp/hsp/ets/modules.abc"; + CString entryPoint = "com.example.myapplication/hsp/ets/pages/Index"; + CString res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); + EXPECT_EQ(res, "com.example.myapplication/hsp/ets/pages/Index"); +} + +HWTEST_F_L0(EcmaModuleTest, TransformToNormalizedOhmUrl3) +{ + // currentModuleName.size() is 0 + CString inputFileName = "/data/storage/el1/bundle"; + CString outBaseFileName = "/data/storage/el1/bundle"; + CString entryPoint = "com.example.myapplication/entry@har/ets/pages/Index"; + CString res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); + EXPECT_EQ(res, "com.example.myapplication/entry@har/ets/pages/Index"); + + // pkgname.size() is 0 + CMap list; + list["har"] = ""; + instance->SetPkgNameList(list); + inputFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + outBaseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + entryPoint = "com.example.myapplication/entry@har/ets/pages/Index"; + res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); + EXPECT_EQ(res, entryPoint); + + // oldEntryPoint equal ENTRY_MAIN_FUNCTION + entryPoint = "_GLOBAL::func_main_0"; + res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); + EXPECT_EQ(res, "_GLOBAL::func_main_0"); + + // oldEntryPoint is not equal ENTRY_MAIN_FUNCTION but start with & + entryPoint = "&test"; + res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); + EXPECT_EQ(res, "&test"); +} + HWTEST_F_L0(EcmaModuleTest, TranslateExpressionToNormalized) { instance->SetBundleName("com.example.myapplication"); @@ -1556,308 +1640,112 @@ HWTEST_F_L0(EcmaModuleTest, NeedTranslateToNormalized) EXPECT_EQ(res, true); } -HWTEST_F_L0(EcmaModuleTest, ModuleLogger) { +HWTEST_F_L0(EcmaModuleTest, GetCurrentModuleName) +{ + ThreadNativeScope nativeScope(thread); + std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_module.abc"; + JSNApi::EnableUserUncaughtErrorHandler(instance); + JSNApi::Execute(instance, baseFileName, "module_test_module_test_module"); + Local res = JSNApi::GetExportObject(instance, "module_test_module_test_module", "moduleName"); + JSHandle result = JSNApiHelper::ToJSHandle(res); + CString moduleName = ConvertToString(result.GetTaggedValue()); + EXPECT_EQ(moduleName, ""); +} + +HWTEST_F_L0(EcmaModuleTest, ReviseLoadedModuleCount2) { ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); - JSHandle module1 = objectFactory->NewSourceTextModule(); - CString baseFileName = "modules.abc"; - module1->SetEcmaModuleFilenameString(baseFileName); - CString recordName1 = "a"; - module1->SetEcmaModuleRecordNameString(recordName1); JSHandle module2 = objectFactory->NewSourceTextModule(); - module2->SetEcmaModuleFilenameString(baseFileName); CString recordName2 = "b"; - module2->SetEcmaModuleRecordNameString(recordName2); - JSHandle moduleRequest = JSHandle::Cast(objectFactory->NewFromUtf8("c")); - JSHandle importName = JSHandle::Cast(objectFactory->NewFromUtf8("ccc")); - JSHandle localName = JSHandle::Cast(objectFactory->NewFromUtf8("ccc")); - JSHandle importEntry = objectFactory->NewImportEntry(moduleRequest, importName, - localName, SharedTypes::UNSENDABLE_MODULE); - SourceTextModule::AddImportEntry(thread, module2, importEntry, 0, 1); - JSHandle module3 = objectFactory->NewSourceTextModule(); - module2->SetEcmaModuleFilenameString(baseFileName); - CString recordName3 = "c"; - module2->SetEcmaModuleRecordNameString(recordName3); - ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM()); - moduleLogger->SetStartTime(recordName1); - moduleLogger->SetEndTime(recordName1); - moduleLogger->SetStartTime(recordName2); - moduleLogger->SetEndTime(recordName2); - moduleLogger->SetStartTime(recordName3); - moduleLogger->InsertEntryPointModule(module1); - moduleLogger->InsertParentModule(module1, module2); - moduleLogger->InsertModuleLoadInfo(module2, module3, -1); - moduleLogger->InsertModuleLoadInfo(module2, module3, 0); - moduleLogger->PrintModuleLoadInfo(); - Local nativeFunc = SourceTextModule::GetRequireNativeModuleFunc(thread->GetEcmaVM(), - module3->GetTypes()); - bool isFunc = nativeFunc->IsFunction(thread->GetEcmaVM()); - EXPECT_EQ(isFunc, false); -} + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + moduleManager->AddResolveImportedModule(recordName2, module2.GetTaggedValue()); + module2->SetLoadingTypes(LoadingTypes::STABLE_MODULE); -HWTEST_F_L0(EcmaModuleTest, GetRequireNativeModuleFunc) { - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - uint16_t registerNum = module->GetRegisterCounts(); - module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED); - module->SetRegisterCounts(registerNum); - Local nativeFunc = SourceTextModule::GetRequireNativeModuleFunc(thread->GetEcmaVM(), - module->GetTypes()); - bool isFunc = nativeFunc->IsFunction(thread->GetEcmaVM()); - EXPECT_EQ(isFunc, false); + ModuleDeregister::ReviseLoadedModuleCount(thread, recordName2); + EXPECT_EQ(module2->GetLoadingTypes(), LoadingTypes::STABLE_MODULE); } -/* - * Feature: Module - * Function: StoreModuleValue - * SubFunction: StoreModuleValue/GetModuleValue - * FunctionPoints: store a module export item in module - * CaseDescription: Simulated implementation of "export foo as bar", set foo as "hello world", - * use "import bar" in same js file - */ -HWTEST_F_L0(EcmaModuleTest, StoreModuleValue2) +HWTEST_F_L0(EcmaModuleTest, IncreaseRegisterCounts2) { - ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory(); - CString localName = "foo"; - CString exportName = "bar"; - CString value = "hello world"; - CString value2 = "hello world1"; - int32_t index = 1; - - JSHandle localNameHandle = JSHandle::Cast(objFactory->NewFromUtf8(localName)); - JSHandle exportNameHandle = JSHandle::Cast(objFactory->NewFromUtf8(exportName)); - JSHandle localExportEntry = - objFactory->NewLocalExportEntry(exportNameHandle, localNameHandle, LocalExportEntry::LOCAL_DEFAULT_INDEX, - SharedTypes::UNSENDABLE_MODULE); - JSHandle module = objFactory->NewSourceTextModule(); - SourceTextModule::AddLocalExportEntry(thread, module, localExportEntry, 0, 1); - - JSHandle storeKey = JSHandle::Cast(objFactory->NewFromUtf8(localName)); - JSHandle valueHandle = JSHandle::Cast(objFactory->NewFromUtf8(value)); - JSHandle valueHandle1 = JSHandle::Cast(objFactory->NewFromUtf8(value2)); - module->StoreModuleValue(thread, storeKey, valueHandle); - module->StoreModuleValue(thread, index, valueHandle1); - JSHandle loadKey = JSHandle::Cast(objFactory->NewFromUtf8(localName)); - JSTaggedValue loadValue = module->GetModuleValue(thread, loadKey.GetTaggedValue(), false); - JSTaggedValue loadValue1 = module->GetModuleValue(thread, index, false); - EXPECT_EQ(valueHandle.GetTaggedValue(), loadValue); - EXPECT_EQ(valueHandle1.GetTaggedValue(), loadValue1); -} - -HWTEST_F_L0(EcmaModuleTest, MakeAppArgs1) { - std::vector> arguments; - CString soPath = "@normalized:Y&&&libentry.so&"; - CString moduleName = "entry"; - CString requestName = "@normalized:"; - arguments.emplace_back(StringRef::NewFromUtf8(thread->GetEcmaVM(), soPath.c_str())); - SourceTextModule::MakeAppArgs(thread->GetEcmaVM(), arguments, soPath, moduleName, requestName); - std::string res1 = arguments[0]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); - std::string res2 = arguments[1]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); - std::string res3 = arguments[2]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); - EXPECT_TRUE(res1 == "entry"); - EXPECT_TRUE(res2 == "true"); - EXPECT_TRUE(res3 == "/entry"); -} - -HWTEST_F_L0(EcmaModuleTest, MakeAppArgs2) { - std::vector> arguments; - CString soPath = "@app:com.example.myapplication/entry"; - CString moduleName = "entry"; - CString requestName = "@app:"; - arguments.emplace_back(StringRef::NewFromUtf8(thread->GetEcmaVM(), soPath.c_str())); - SourceTextModule::MakeAppArgs(thread->GetEcmaVM(), arguments, soPath, moduleName, requestName); - std::string res1 = arguments[0]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); - std::string res2 = arguments[1]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); - std::string res3 = arguments[2]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); - EXPECT_TRUE(res1 == "entry"); - EXPECT_TRUE(res2 == "true"); - EXPECT_TRUE(res3 == "@app:com.example.myapplication"); + std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; + JSNApi::EnableUserUncaughtErrorHandler(instance); + bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); + EXPECT_TRUE(result); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); + std::set increaseModule; + increaseModule.insert("module_test_module_test_B"); + increaseModule.insert("b"); + module->SetSharedType(SharedTypes::SHARED_MODULE); + ModuleDeregister::IncreaseRegisterCounts(thread, module, increaseModule); + EXPECT_EQ(module->GetRequestedModules().IsUndefined(), false); } -HWTEST_F_L0(EcmaModuleTest, ConcatHspFileNameCrossBundle) +HWTEST_F_L0(EcmaModuleTest, DecreaseRegisterCounts2) { - CString bundleName = "com.example.application"; - CString moduleName = "entry"; - CString expectRes = "/data/storage/el1/bundle/com.example.application/entry/entry/ets/modules.abc"; - CString res = ModulePathHelper::ConcatHspFileNameCrossBundle(bundleName, moduleName); - EXPECT_EQ(res, expectRes); + std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; + JSNApi::EnableUserUncaughtErrorHandler(instance); + bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); + EXPECT_TRUE(result); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); + std::set decreaseModule; + decreaseModule.insert("module_test_module_test_B"); + decreaseModule.insert("b"); + module->SetSharedType(SharedTypes::SHARED_MODULE); + ModuleDeregister::DecreaseRegisterCounts(thread, module, decreaseModule); + EXPECT_EQ(module->GetRequestedModules().IsUndefined(), false); } -HWTEST_F_L0(EcmaModuleTest, ConcatHspFileName) +HWTEST_F_L0(EcmaModuleTest, GenerateSendableFuncModule) { - CString moduleName = "entry"; - CString expectRes = "/data/storage/el1/bundle/entry/ets/modules.abc"; - CString res = ModulePathHelper::ConcatHspFileName(moduleName); - EXPECT_EQ(res, expectRes); + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + module->SetSharedType(SharedTypes::SHARED_MODULE); + JSHandle moduleRecord = JSHandle::Cast(module); + SendableClassModule::GenerateSendableFuncModule(thread, moduleRecord); + JSHandle currentModule = JSHandle::Cast(moduleRecord); + EXPECT_TRUE(SourceTextModule::IsModuleInSharedHeap(currentModule)); } -HWTEST_F_L0(EcmaModuleTest, ParseNormalizedOhmUrl) +HWTEST_F_L0(EcmaModuleTest, ConcatMergeFileNameToNormalized) { - CString baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; - CString recordName = "&har/Index&1.0.0"; - CString requestName = "@normalized:N&&&har/src/main/page/Test&1.0.0"; - CString expectRes = "&har/src/main/page/Test&1.0.0"; - CString exceptBaseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; - CString res = ModulePathHelper::ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName); - EXPECT_EQ(res, expectRes); - EXPECT_EQ(baseFileName, exceptBaseFileName); - - baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; - requestName = "@normalized:N&hsp&&hsp/src/main/page/Test&1.0.0"; - expectRes = "&hsp/src/main/page/Test&1.0.0"; - exceptBaseFileName = "/data/storage/el1/bundle/hsp/ets/modules.abc"; - CString res2 = ModulePathHelper::ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName); - EXPECT_EQ(res2, expectRes); - EXPECT_EQ(baseFileName, exceptBaseFileName); - - baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; - requestName = "@normalized:N&hsp&com.example.application&hsp/src/main/page/Test&1.0.0"; - exceptBaseFileName = "/data/storage/el1/bundle/com.example.application/hsp/hsp/ets/modules.abc"; - expectRes = "com.example.application&hsp/src/main/page/Test&1.0.0"; - CString res3 = ModulePathHelper::ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName); - EXPECT_EQ(res3, expectRes); - EXPECT_EQ(baseFileName, exceptBaseFileName); - - baseFileName = ""; - recordName = "&har/Index&1.0.0"; - requestName = "@normalized:N&&&har/src/main/page/Test&1.0.0"; - CString res4 = ModulePathHelper::ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName); - EXPECT_EQ(baseFileName, ""); -} - -HWTEST_F_L0(EcmaModuleTest, GetModuleNameWithBaseFile) -{ - CString baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; - CString expectRes = "entry"; - CString res = ModulePathHelper::GetModuleNameWithBaseFile(baseFileName); - EXPECT_EQ(res, expectRes); - - baseFileName = "/data/storage/el1/bundle/com.example.application/hsp/hsp/ets/modules.abc"; - expectRes = "hsp"; - res = ModulePathHelper::GetModuleNameWithBaseFile(baseFileName); - EXPECT_EQ(res, expectRes); -} - -HWTEST_F_L0(EcmaModuleTest, GetBundleNameWithRecordName) -{ - CString recordName = "com.example.myapplication/library"; - CString expectRes = "com.example.myapplication"; - CString res = ModulePathHelper::GetBundleNameWithRecordName(instance, recordName); - EXPECT_EQ(res, expectRes); - - CMap>> list; - CMap> childList; - list["hsp"] = childList; - instance->SetpkgContextInfoList(list); - - recordName = "&hsp&com.example.application&hsp/src/main/page/Test&1.0.0"; - expectRes = "com.example.application"; - res = ModulePathHelper::GetBundleNameWithRecordName(instance, recordName); - EXPECT_EQ(res, expectRes); - - instance->SetBundleName("com.example1.application"); - recordName = "&har/src/main/page/Test&1.0.0"; - expectRes = "com.example1.application"; - res = ModulePathHelper::GetBundleNameWithRecordName(instance, recordName); - EXPECT_EQ(res, expectRes); -} - -HWTEST_F_L0(EcmaModuleTest, TransformToNormalizedOhmUrl) -{ - CMap>> pkgList; - CMap> entryList; - entryList["entry"] = { - "packageName", "entry", - "bundleName", "", - "moduleName", "", - "version", "", - "entryPath", "src/main/", - "isSO", "false" - }; - entryList["har"] = { - "packageName", "har", - "bundleName", "", - "moduleName", "", - "version", "1.2.0", - "entryPath", "", - "isSO", "false" - }; - pkgList["entry"] = entryList; - CMap> ohosTestList; - ohosTestList["ohosTest"] = { - "packageName", "ohosTest", - "bundleName", "", - "moduleName", "", - "version", "", - "entryPath", "src/", - "isSO", "false" - }; - pkgList["ohosTest"] = ohosTestList; - instance->SetpkgContextInfoList(pkgList); - - CString inputFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; - CString outBaseFileName = ""; - CString entryPoint = "ENTRY_MAIN_FUNCTION"; - CString res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); - EXPECT_EQ(res, "ENTRY_MAIN_FUNCTION"); - - outBaseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; - entryPoint = "com.example.myapplication/entry@har/ets/pages/Index"; - res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); - EXPECT_EQ(res, "&har/src/main/ets/pages/Index&1.2.0"); - - outBaseFileName = "/data/storage/el1/bundle/ohosTest/ets/modules.abc"; - entryPoint = "com.example.myapplication/ohosTest/ets/pages/Index"; - res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); - EXPECT_EQ(res, "&ohosTest/src/ets/pages/Index&"); - - outBaseFileName = "/data/storage/el1/bundle/entry/.test/ets/modules.abc"; - entryPoint = "com.example.myapplication/entry/.test/ets/pages/Index"; - res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); - EXPECT_EQ(res, "&entry/.test/ets/pages/Index&"); -} - -HWTEST_F_L0(EcmaModuleTest, TransformToNormalizedOhmUrl2) -{ - CString inputFileName = "/data/storage/el1/bundle/hsp/ets/modules.abc"; - CString outBaseFileName = "/data/storage/el1/bundle/com.example.application/hsp/hsp/ets/modules.abc"; - CString entryPoint = "com.example.myapplication/hsp/ets/pages/Index"; - CString res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); - EXPECT_EQ(res, "com.example.myapplication/hsp/ets/pages/Index"); -} - -HWTEST_F_L0(EcmaModuleTest, TransformToNormalizedOhmUrl3) -{ - // currentModuleName.size() is 0 - CString inputFileName = "/data/storage/el1/bundle"; - CString outBaseFileName = "/data/storage/el1/bundle"; - CString entryPoint = "com.example.myapplication/entry@har/ets/pages/Index"; - CString res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); - EXPECT_EQ(res, "com.example.myapplication/entry@har/ets/pages/Index"); + CString baseFilename = "merge.abc"; + const char *data = R"( + .language ECMAScript + .function any func_main_0(any a0, any a1, any a2) { + ldai 1 + return + } + )"; + JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance(); + Parser parser; + auto res = parser.Parse(data); + std::unique_ptr pfPtr = pandasm::AsmEmitter::Emit(res.Value()); + std::shared_ptr pf = pfManager->NewJSPandaFile(pfPtr.release(), baseFilename); - // pkgname.size() is 0 - CMap list; - list["har"] = ""; - instance->SetPkgNameList(list); - inputFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; - outBaseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; - entryPoint = "com.example.myapplication/entry@har/ets/pages/Index"; - res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); - EXPECT_EQ(res, entryPoint); + CString requestPath = "@normalized:N&&&har/Index&1.0.0"; + CString recordName = ""; + CString result = "&har/Index&1.0.0"; + CString entryPoint = ModulePathHelper::ConcatMergeFileNameToNormalized(thread, pf.get(), baseFilename, recordName, + requestPath); + EXPECT_EQ(result, entryPoint); - // oldEntryPoint equal ENTRY_MAIN_FUNCTION - entryPoint = "_GLOBAL::func_main_0"; - res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); - EXPECT_EQ(res, "_GLOBAL::func_main_0"); + requestPath = "&index"; + result = "&index"; + entryPoint = ModulePathHelper::ConcatMergeFileNameToNormalized(thread, pf.get(), baseFilename, recordName, + requestPath); + EXPECT_EQ(result, entryPoint); - // oldEntryPoint is not equal ENTRY_MAIN_FUNCTION but start with & - entryPoint = "&test"; - res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); - EXPECT_EQ(res, "&test"); + requestPath = "./@normalized:N&&&har/Index&1.0.0"; + result = "@normalized:N&&&har/Index&1.0.0&"; + pf->InsertJSRecordInfo(result); + entryPoint = ModulePathHelper::ConcatMergeFileNameToNormalized(thread, pf.get(), baseFilename, recordName, + requestPath); + EXPECT_EQ(result, entryPoint); } -HWTEST_F_L0(EcmaModuleTest, TranslateExpressionInputWithEts) +HWTEST_F_L0(EcmaModuleTest, ConcatImportFileNormalizedOhmurlWithRecordName) { - instance->SetBundleName("com.example.myapplication"); CString baseFilename = "merge.abc"; const char *data = R"( .language ECMAScript @@ -1872,650 +1760,525 @@ HWTEST_F_L0(EcmaModuleTest, TranslateExpressionInputWithEts) std::unique_ptr pfPtr = pandasm::AsmEmitter::Emit(res.Value()); std::shared_ptr pf = pfManager->NewJSPandaFile(pfPtr.release(), baseFilename); - CString baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; - CString requestName = "ets/Test"; - CString recordName = "com.example.myapplication/entry/ets/pages/Index"; - CString expectRes = "com.example.myapplication/entry/ets/Test"; - CString result = ModulePathHelper::TranslateExpressionInputWithEts(thread, pf.get(), baseFileName, requestName); - EXPECT_EQ(result, ""); + CString requestPath = "@normalized:N&&&har/Index&1.0.0"; + CString recordName = ""; + CString entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), + baseFilename, recordName, requestPath); + EXPECT_EQ(CString(), entryPoint); - pf->InsertJSRecordInfo(expectRes); - result = ModulePathHelper::TranslateExpressionInputWithEts(thread, pf.get(), baseFileName, requestName); - EXPECT_EQ(result, expectRes); -} + requestPath = "@normalized:N&&&har/Index&1.0.0"; + CString result = "&har/Index&1:0.0"; + pf->InsertJSRecordInfo(result); + entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), baseFilename, + recordName, requestPath); + EXPECT_EQ(result, entryPoint); -HWTEST_F_L0(EcmaModuleTest, ReviseLoadedModuleCount1) { - CString moduleName = "testModule"; - ModuleDeregister::ReviseLoadedModuleCount(thread, moduleName); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - bool res = moduleManager->IsLocalModuleLoaded(moduleName); - EXPECT_EQ(res, false); + requestPath = "@normalized:N&&&har/Index&1.0.0"; + result = "@normalized:N&&&har/Index&1.0.0/index&"; + pf->InsertJSRecordInfo(result); + entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), baseFilename, + recordName, requestPath); + EXPECT_EQ(result, entryPoint); + + requestPath = "@normalized:N&&&har/Index&1.0.0"; + result = "@normalized:N&&&har/Index&1.0.0&"; + pf->InsertJSRecordInfo(result); + entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), baseFilename, + recordName, requestPath); + EXPECT_EQ(result, entryPoint); + + requestPath = "./@normalized:N&&&har/Index&1.0.0"; + entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), baseFilename, + recordName, requestPath); + EXPECT_EQ(result, entryPoint); + + requestPath = "./Test2"; + recordName = "&entry/ets/pages/Index&"; + result = "&entry/ets/pages/Test2&"; + pf->InsertJSRecordInfo(result); + entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), baseFilename, + recordName, requestPath); + EXPECT_EQ(result, entryPoint); } -HWTEST_F_L0(EcmaModuleTest, IncreaseRegisterCounts) +HWTEST_F_L0(EcmaModuleTest, HostResolveImportedModuleWithMerge) { - std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; - JSNApi::EnableUserUncaughtErrorHandler(instance); - bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); - EXPECT_TRUE(result); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle module1 = objectFactory->NewSourceTextModule(); + module1->SetEcmaModuleRecordNameString("test"); JSHandle module2 = objectFactory->NewSourceTextModule(); - std::set increaseModule; - - ModuleDeregister::IncreaseRegisterCounts(thread, module, increaseModule); - EXPECT_EQ(module->GetRequestedModules().IsUndefined(), false); + CString recordName2 = "@ohos:hilog"; + module2->SetEcmaModuleRecordNameString(recordName2); + module2->SetTypes(ModuleTypes::NATIVE_MODULE); - module->SetRegisterCounts(INT8_MAX); - ModuleDeregister::IncreaseRegisterCounts(thread, module, increaseModule); - EXPECT_EQ(module->GetRequestedModules().IsUndefined(), false); + JSHandle nativeName = JSHandle::Cast(objectFactory->NewFromUtf8("@ohos:hilog")); + JSHandle res1 = + ModuleResolver::HostResolveImportedModule(thread, module1, nativeName, false); + EXPECT_TRUE(res1->IsSourceTextModule()); - module2->SetRegisterCounts(INT8_MAX); - ModuleDeregister::IncreaseRegisterCounts(thread, module2, increaseModule); - EXPECT_EQ(module2->GetRequestedModules().IsUndefined(), true); - - module2->SetLoadingTypes(LoadingTypes::STABLE_MODULE); - ModuleDeregister::IncreaseRegisterCounts(thread, module2, increaseModule); - bool res = module2->GetLoadingTypes() == LoadingTypes::STABLE_MODULE; - EXPECT_EQ(res, true); + thread->GetCurrentEcmaContext()->GetModuleManager()->AddResolveImportedModule( + recordName2, module2.GetTaggedValue()); + JSHandle res2 = + ModuleResolver::HostResolveImportedModule(thread, module1, nativeName, false); + EXPECT_TRUE(res2->IsSourceTextModule()); } -HWTEST_F_L0(EcmaModuleTest, DecreaseRegisterCounts) +HWTEST_F_L0(EcmaModuleTest, ModuleResolverHostResolveImportedModule) { - std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; - JSNApi::EnableUserUncaughtErrorHandler(instance); - bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); - EXPECT_TRUE(result); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); - JSHandle module2 = objectFactory->NewSourceTextModule(); - std::set decreaseModule; - - ModuleDeregister::DecreaseRegisterCounts(thread, module, decreaseModule); - bool res1 = module->GetLoadingTypes() != LoadingTypes::DYNAMITC_MODULE; - EXPECT_EQ(res1, true); - - module->SetRegisterCounts(INT8_MAX); - ModuleDeregister::DecreaseRegisterCounts(thread, module, decreaseModule); - EXPECT_EQ(module->GetRequestedModules().IsUndefined(), false); - - module2->SetLoadingTypes(LoadingTypes::DYNAMITC_MODULE); - ModuleDeregister::DecreaseRegisterCounts(thread, module2, decreaseModule); - bool res2 = module2->GetLoadingTypes() != LoadingTypes::DYNAMITC_MODULE; - EXPECT_EQ(res2, false); -} - -HWTEST_F_L0(EcmaModuleTest, GetSendableModuleValueImpl) { ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); JSHandle module1 = objectFactory->NewSourceTextModule(); - SharedModuleManager* manager1 = SharedModuleManager::GetInstance(); - int32_t index = 2; - JSTaggedValue currentModule1 = module1.GetTaggedValue(); - JSTaggedValue res1 = manager1->GetSendableModuleValueImpl( - thread, index, currentModule1); - EXPECT_EQ(res1, thread->GlobalConstants()->GetUndefined()); - SharedModuleManager* manager2 = SharedModuleManager::GetInstance(); - std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; - JSNApi::EnableUserUncaughtErrorHandler(instance); - bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); - EXPECT_TRUE(result); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - JSHandle module2 = moduleManager->HostGetImportedModule("module_test_module_test_C"); - JSTaggedValue currentModule2 = module2.GetTaggedValue(); - JSTaggedValue res2 = manager2->GetSendableModuleValueImpl( - thread, index, currentModule2); - EXPECT_NE(res2, thread->GlobalConstants()->GetUndefined()); + JSHandle module2 = objectFactory->NewSourceTextModule(); + CString recordName2 = "@ohos:hilog"; + module2->SetEcmaModuleRecordNameString(recordName2); + module2->SetTypes(ModuleTypes::NATIVE_MODULE); + + JSHandle nativeName = JSHandle::Cast(objectFactory->NewFromUtf8("@ohos:hilog")); + thread->GetCurrentEcmaContext()->GetModuleManager()->AddResolveImportedModule( + recordName2, module2.GetTaggedValue()); + JSHandle res1 = + ModuleResolver::HostResolveImportedModule(thread, module1, nativeName, false); + EXPECT_TRUE(res1->IsSourceTextModule()); } -HWTEST_F_L0(EcmaModuleTest, GetLazySendableModuleValueImpl) { +HWTEST_F_L0(EcmaModuleTest, ResolveExportObject) +{ ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); JSHandle module1 = objectFactory->NewSourceTextModule(); - SharedModuleManager* manager1 = SharedModuleManager::GetInstance(); - int32_t index = 2; - JSTaggedValue currentModule1 = module1.GetTaggedValue(); - JSTaggedValue res1 = manager1->GetLazySendableModuleValueImpl( - thread, index, currentModule1); - EXPECT_EQ(res1, thread->GlobalConstants()->GetUndefined()); -} - -HWTEST_F_L0(EcmaModuleTest, ResolveImportedModuleWithMerge) { - std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; - JSNApi::EnableUserUncaughtErrorHandler(instance); - bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); - EXPECT_TRUE(result); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); - module->SetSharedType(SharedTypes::SHARED_MODULE); - - CString recordName2 = "testModule"; - bool executeFromJob = false; - JSHandle res = ModuleResolver::ResolveImportedModuleWithMerge( - thread, baseFileName.c_str(), recordName2, executeFromJob); - EXPECT_EQ(res.GetTaggedValue(), JSTaggedValue::Exception()); -} -HWTEST_F_L0(EcmaModuleTest, ResolveImportedModuleWithMerge2) { - CString moduleName1; - CString recordName1; + JSHandle exportName = JSHandle::Cast(objectFactory->NewFromUtf8("notExist")); + JSHandle nativeModuleFailureInfo = objectFactory->NewNativeModuleFailureInfo(); + JSHandle res1 = SourceTextModule::ResolveExportObject( + thread, module1, JSHandle::Cast(nativeModuleFailureInfo), exportName); + EXPECT_TRUE(res1->IsResolvedIndexBinding()); - bool executeFromJob = false; - JSHandle res = ModuleResolver::ResolveImportedModuleWithMerge( - thread, moduleName1, recordName1, executeFromJob); - EXPECT_EQ(res.GetTaggedValue(), JSTaggedValue::Exception()); -} + JSHandle ctor(thread->GetEcmaVM()->GetGlobalEnv()->GetObjectFunction()); + JSHandle obj(objectFactory->NewJSObjectByConstructor(ctor)); + JSHandle exportArr = objectFactory->NewTaggedArray(2); + obj->SetProperties(thread, exportArr); + JSHandle jsHclass(thread, obj->GetJSHClass()); + JSHandle layout = objectFactory->CreateLayoutInfo(0, MemSpaceType::OLD_SPACE, GrowMode::KEEP); + jsHclass->SetLayout(thread, layout); + JSHandle res2 = SourceTextModule::ResolveExportObject( + thread, module1, JSHandle::Cast(obj), exportName); + EXPECT_TRUE(res2->IsHole()); -HWTEST_F_L0(EcmaModuleTest, IsInstantiatedSModule) { - SharedModuleManager* manager1 = SharedModuleManager::GetInstance(); - std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; - JSNApi::EnableUserUncaughtErrorHandler(instance); - bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); - EXPECT_TRUE(result); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); - bool res = manager1->IsInstantiatedSModule(thread, module); - EXPECT_EQ(res, true); + JSHandle obj1(objectFactory->NewJSObjectByConstructor(ctor)); + JSHandle dict = NameDictionary::Create(thread, NameDictionary::ComputeHashTableSize(2)); + obj1->SetProperties(thread, JSHandle::Cast(dict)); + JSHandle res3 = SourceTextModule::ResolveExportObject( + thread, module1, JSHandle::Cast(obj1), exportName); + EXPECT_TRUE(res3->IsHole()); } -HWTEST_F_L0(EcmaModuleTest, ProcessModuleLoadInfoForESM) +HWTEST_F_L0(EcmaModuleTest, ResolveNativeStarExport) { ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); - JSHandle module1 = objectFactory->NewSourceTextModule(); - CString baseFileName = "modules.abc"; - module1->SetEcmaModuleFilenameString(baseFileName); - CString recordName1 = "a"; - module1->SetEcmaModuleRecordNameString(recordName1); + JSHandle module = objectFactory->NewSourceTextModule(); + CString recordName = "@ohos:hilog"; + module->SetEcmaModuleRecordNameString(recordName); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle importEntry = - objectFactory->NewImportEntry(val, val, val, SharedTypes::UNSENDABLE_MODULE); - SourceTextModule::AddImportEntry(thread, module1, importEntry, 0, 1); - - JSHandle module2 = objectFactory->NewSourceTextModule(); - module2->SetEcmaModuleFilenameString(baseFileName); - CString recordName2 = "b"; - module2->SetEcmaModuleRecordNameString(recordName2); JSHandle localExportEntry = objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); - module2->SetLocalExportEntries(thread, localExportEntries); - module2->StoreModuleValue(thread, 0, val); - module2->SetStatus(ModuleStatus::EVALUATED); - ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM()); - thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); - // test ResolvedIndexBinding - JSHandle indexBinding = - objectFactory->NewResolvedIndexBindingRecord(module2, 0); - JSTaggedValue res1 = ModuleTools::ProcessModuleLoadInfo(thread, module1, indexBinding.GetTaggedValue(), 0); - EXPECT_EQ(res1, val.GetTaggedValue()); - - JSTaggedValue res2 = ModuleTools::ProcessModuleNameSpaceLoadInfo(thread, module1, module2); - EXPECT_NE(res2, JSTaggedValue::Exception()); + module->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module, 0, val); + module->SetTypes(ModuleTypes::NATIVE_MODULE); - // test HotReload - thread->GetCurrentEcmaContext()->SetStageOfHotReload(StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN); - JSTaggedValue res3 = ModuleTools::ProcessModuleLoadInfo(thread, module1, indexBinding.GetTaggedValue(), 0); - EXPECT_EQ(res3, val.GetTaggedValue()); + JSHandle res1 = SourceTextModule::ResolveNativeStarExport(thread, module, val); + EXPECT_TRUE(res1->IsNull()); - thread->GetCurrentEcmaContext()->AddPatchModule(recordName2, JSHandle::Cast(module2)); - JSTaggedValue res4 = ModuleTools::ProcessModuleLoadInfo(thread, module1, indexBinding.GetTaggedValue(), 0); - EXPECT_EQ(res4, val.GetTaggedValue()); + module->SetStatus(ModuleStatus::EVALUATED); + JSHandle res2 = SourceTextModule::ResolveNativeStarExport(thread, module, val); + EXPECT_TRUE(res2->IsNull()); +} - thread->GetCurrentEcmaContext()->SetModuleLogger(nullptr); - delete moduleLogger; +HWTEST_F_L0(EcmaModuleTest, MakeInternalArgs) +{ + std::vector> arguments; + auto vm = thread->GetEcmaVM(); + CString soName = "@ohos:hilig"; + arguments.emplace_back(StringRef::NewFromUtf8(vm, soName.c_str())); + SourceTextModule::MakeInternalArgs(vm, arguments, soName); + EXPECT_TRUE(!thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, ProcessModuleLoadInfoForCJS) +HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleImpl) { - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); - JSHandle module1 = objectFactory->NewSourceTextModule(); - CString baseFileName = "modules.abc"; - module1->SetEcmaModuleFilenameString(baseFileName); - CString recordName1 = "a"; - module1->SetEcmaModuleRecordNameString(recordName1); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle importEntry = - objectFactory->NewImportEntry(val, val, val, SharedTypes::UNSENDABLE_MODULE); - SourceTextModule::AddImportEntry(thread, module1, importEntry, 0, 1); - - JSHandle module2 = objectFactory->NewSourceTextModule(); - module2->SetEcmaModuleFilenameString(baseFileName); - CString recordName2 = "cjs"; - module2->SetEcmaModuleRecordNameString(recordName2); JSHandle localExportEntry = objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); - module2->SetLocalExportEntries(thread, localExportEntries); - module2->StoreModuleValue(thread, 0, val); - module2->SetTypes(ModuleTypes::CJS_MODULE); - module2->SetStatus(ModuleStatus::EVALUATED); - JSHandle moduleCjs = objectFactory->NewCjsModule(); - JSHandle recordName2Hdl = - JSHandle::Cast(objectFactory->NewFromUtf8(recordName2.c_str())); - JSHandle baseFileNameHdl = - JSHandle::Cast(objectFactory->NewFromUtf8(baseFileName.c_str())); - CjsModule::InitializeModule(thread, moduleCjs, recordName2Hdl, baseFileNameHdl); - CjsModule::PutIntoCache(thread, moduleCjs, recordName2Hdl); - - JSHandle envRec = objectFactory->NewTaggedArray(1); - JSHandle resolution = - JSHandle::Cast(objectFactory->NewResolvedBindingRecord(module2, val)); - envRec->Set(thread, 0, resolution); - module1->SetEnvironment(thread, envRec); - - ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM()); + module->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module, 0, val); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + ModuleLogger *moduleLogger = new ModuleLogger(vm); thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); + // app module + module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + SourceTextModule::LoadNativeModuleImpl(vm, thread, module, ModuleTypes::APP_MODULE); + EXPECT_TRUE(!thread->HasPendingException()); - // test ResolvedBinding - JSTaggedValue res1 = ModuleTools::ProcessModuleNameSpaceLoadInfo(thread, module1, module2); - EXPECT_NE(res1, JSTaggedValue::Exception()); + // internal module + Local globalObject = JSNApi::GetGlobalObject(vm); + globalObject->Set(vm, StringRef::NewFromUtf8(vm, "requireNapi"), + FunctionRef::New(const_cast(vm), MockRequireNapiUndefined)); + module->SetEcmaModuleRecordNameString("@hms:xxxxx"); + SourceTextModule::LoadNativeModuleImpl(vm, thread, module, ModuleTypes::INTERNAL_MODULE); + EXPECT_TRUE(!thread->HasPendingException()); - JSTaggedValue res2 = ModuleTools::ProcessModuleLoadInfo(thread, module1, resolution.GetTaggedValue(), 0); - EXPECT_EQ(res2, JSTaggedValue::Exception()); thread->GetCurrentEcmaContext()->SetModuleLogger(nullptr); delete moduleLogger; + SourceTextModule::LoadNativeModuleImpl(vm, thread, module, ModuleTypes::INTERNAL_MODULE); + EXPECT_TRUE(!thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, ProcessModuleLoadInfoForNativeModule) +HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleMayThrowError1) { - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); - JSHandle module1 = objectFactory->NewSourceTextModule(); - CString baseFileName = "modules.abc"; - module1->SetEcmaModuleFilenameString(baseFileName); - CString recordName1 = "a"; - module1->SetEcmaModuleRecordNameString(recordName1); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle importEntry = - objectFactory->NewImportEntry(val, val, val, SharedTypes::UNSENDABLE_MODULE); - SourceTextModule::AddImportEntry(thread, module1, importEntry, 0, 1); - - JSHandle module2 = objectFactory->NewSourceTextModule(); - module2->SetEcmaModuleFilenameString(baseFileName); - CString recordName2 = "nativeModule"; - module2->SetEcmaModuleRecordNameString(recordName2); JSHandle localExportEntry = objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); - module2->SetLocalExportEntries(thread, localExportEntries); - module2->StoreModuleValue(thread, 0, val); - module2->SetTypes(ModuleTypes::NATIVE_MODULE); - module2->SetStatus(ModuleStatus::EVALUATED); - - JSHandle envRec = objectFactory->NewTaggedArray(1); - JSHandle resolution = JSHandle::Cast( - objectFactory->NewResolvedBindingRecord(module2, val)); - envRec->Set(thread, 0, resolution); - module1->SetEnvironment(thread, envRec); - - ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM()); - thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); - - JSTaggedValue res1 = ModuleTools::ProcessModuleLoadInfo(thread, module1, resolution.GetTaggedValue(), 0); - EXPECT_EQ(res1, JSTaggedValue::Exception()); - - JSTaggedValue res2 = ModuleTools::ProcessModuleNameSpaceLoadInfo(thread, module1, module2); - EXPECT_NE(res2, JSTaggedValue::Exception()); - thread->GetCurrentEcmaContext()->SetModuleLogger(nullptr); - delete moduleLogger; + module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + module->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module, 0, val); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); + Local globalObject = JSNApi::GetGlobalObject(vm); + globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiFailure)); + SourceTextModule::LoadNativeModuleMayThrowError(thread, module, ModuleTypes::APP_MODULE); + EXPECT_TRUE(thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, ResolvedBindingForLog) +HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleMayThrowError2) { - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); - JSHandle module1 = objectFactory->NewSourceTextModule(); - CString baseFileName = "modules.abc"; - module1->SetEcmaModuleFilenameString(baseFileName); - CString recordName1 = "a"; - module1->SetEcmaModuleRecordNameString(recordName1); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle importEntry = - objectFactory->NewImportEntry(val, val, val, SharedTypes::UNSENDABLE_MODULE); - SourceTextModule::AddImportEntry(thread, module1, importEntry, 0, 1); - - JSHandle module2 = objectFactory->NewSourceTextModule(); - module2->SetEcmaModuleFilenameString(baseFileName); - CString recordName2 = "b"; - module2->SetEcmaModuleRecordNameString(recordName2); JSHandle localExportEntry = objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); - module2->SetLocalExportEntries(thread, localExportEntries); - module2->StoreModuleValue(thread, 0, val); - module2->SetStatus(ModuleStatus::EVALUATED); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - moduleManager->AddResolveImportedModule(recordName2, module2.GetTaggedValue()); - - ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM()); - thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); - // test ResolvedRecordIndexBinding - JSHandle recordNameHdl = objectFactory->NewFromUtf8(recordName2); - JSHandle baseFileNameHdl = objectFactory->NewFromUtf8(baseFileName); - JSHandle recordIndexBinding = - objectFactory->NewSResolvedRecordIndexBindingRecord(recordNameHdl, baseFileNameHdl, 0); - JSTaggedValue res1 = ModuleTools::ProcessModuleLoadInfo(thread, module1, recordIndexBinding.GetTaggedValue(), 0); - EXPECT_EQ(res1, val.GetTaggedValue()); - - // test ResolvedRecordBinding - JSHandle nameBinding = - objectFactory->NewSResolvedRecordBindingRecord(recordNameHdl, val); - JSTaggedValue res2 = ModuleTools::ProcessModuleLoadInfo(thread, module1, nameBinding.GetTaggedValue(), 0); - EXPECT_EQ(res2, JSTaggedValue::Exception()); - thread->GetCurrentEcmaContext()->SetModuleLogger(nullptr); - delete moduleLogger; + module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + module->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module, 0, val); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); + Local globalObject = JSNApi::GetGlobalObject(vm); + globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiUndefined)); + SourceTextModule::LoadNativeModuleMayThrowError(thread, module, ModuleTypes::APP_MODULE); + EXPECT_TRUE(thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, ToStringWithPrecision) +HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleMayThrowError3) { - std::string res = ModuleLogger::ToStringWithPrecision(4.550, 3); - EXPECT_EQ(res, "4.55"); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + JSHandle localExportEntry = + objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); + JSHandle localExportEntries = objectFactory->NewTaggedArray(1); + localExportEntries->Set(thread, 0, localExportEntry); + module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + module->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module, 0, val); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); + Local globalObject = JSNApi::GetGlobalObject(vm); + globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiException)); + SourceTextModule::LoadNativeModuleMayThrowError(thread, module, ModuleTypes::APP_MODULE); + EXPECT_TRUE(thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, GetCurrentModuleName) +HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleMayThrowError4) { - ThreadNativeScope nativeScope(thread); - std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_module.abc"; - JSNApi::EnableUserUncaughtErrorHandler(instance); - JSNApi::Execute(instance, baseFileName, "module_test_module_test_module"); - Local res = JSNApi::GetExportObject(instance, "module_test_module_test_module", "moduleName"); - JSHandle result = JSNApiHelper::ToJSHandle(res); - CString moduleName = ConvertToString(result.GetTaggedValue()); - EXPECT_EQ(moduleName, ""); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + JSHandle localExportEntry = + objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); + JSHandle localExportEntries = objectFactory->NewTaggedArray(1); + localExportEntries->Set(thread, 0, localExportEntry); + module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + module->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module, 0, val); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); + Local globalObject = JSNApi::GetGlobalObject(vm); + globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiValue)); + SourceTextModule::LoadNativeModuleMayThrowError(thread, module, ModuleTypes::APP_MODULE); + EXPECT_TRUE(!thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, ReviseLoadedModuleCount2) { - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); - JSHandle module2 = objectFactory->NewSourceTextModule(); - CString recordName2 = "b"; - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - moduleManager->AddResolveImportedModule(recordName2, module2.GetTaggedValue()); - module2->SetLoadingTypes(LoadingTypes::STABLE_MODULE); +HWTEST_F_L0(EcmaModuleTest, LoadNativeModule1) +{ + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + JSHandle localExportEntry = + objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); + JSHandle localExportEntries = objectFactory->NewTaggedArray(1); + localExportEntries->Set(thread, 0, localExportEntry); + module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + module->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module, 0, val); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); + Local globalObject = JSNApi::GetGlobalObject(vm); + globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiValue)); + SourceTextModule::LoadNativeModule(thread, module, ModuleTypes::APP_MODULE); + EXPECT_TRUE(!thread->HasPendingException()); +} - ModuleDeregister::ReviseLoadedModuleCount(thread, recordName2); - EXPECT_EQ(module2->GetLoadingTypes(), LoadingTypes::STABLE_MODULE); +HWTEST_F_L0(EcmaModuleTest, LoadNativeModule2) +{ + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + JSHandle localExportEntry = + objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); + JSHandle localExportEntries = objectFactory->NewTaggedArray(1); + localExportEntries->Set(thread, 0, localExportEntry); + module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + module->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module, 0, val); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); + Local globalObject = JSNApi::GetGlobalObject(vm); + globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiFailure)); + SourceTextModule::LoadNativeModule(thread, module, ModuleTypes::APP_MODULE); + EXPECT_TRUE(!thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, IncreaseRegisterCounts2) +HWTEST_F_L0(EcmaModuleTest, EvaluateNativeModule1) { - std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; - JSNApi::EnableUserUncaughtErrorHandler(instance); - bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); - EXPECT_TRUE(result); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); - std::set increaseModule; - increaseModule.insert("module_test_module_test_B"); - increaseModule.insert("b"); - module->SetSharedType(SharedTypes::SHARED_MODULE); - ModuleDeregister::IncreaseRegisterCounts(thread, module, increaseModule); - EXPECT_EQ(module->GetRequestedModules().IsUndefined(), false); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + module->SetStatus(ModuleStatus::EVALUATED); + SourceTextModule::EvaluateNativeModule(thread, module, ModuleTypes::APP_MODULE); + EXPECT_TRUE(!thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, DecreaseRegisterCounts2) +HWTEST_F_L0(EcmaModuleTest, EvaluateNativeModule2) { - std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; - JSNApi::EnableUserUncaughtErrorHandler(instance); - bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); - EXPECT_TRUE(result); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); - std::set decreaseModule; - decreaseModule.insert("module_test_module_test_B"); - decreaseModule.insert("b"); - module->SetSharedType(SharedTypes::SHARED_MODULE); - ModuleDeregister::DecreaseRegisterCounts(thread, module, decreaseModule); - EXPECT_EQ(module->GetRequestedModules().IsUndefined(), false); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + JSHandle localExportEntry = + objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); + JSHandle localExportEntries = objectFactory->NewTaggedArray(1); + localExportEntries->Set(thread, 0, localExportEntry); + module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + module->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module, 0, val); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + module->SetStatus(ModuleStatus::INSTANTIATED); + Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); + Local globalObject = JSNApi::GetGlobalObject(vm); + globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiFailure)); + SourceTextModule::EvaluateNativeModule(thread, module, ModuleTypes::APP_MODULE); + EXPECT_TRUE(!thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, GenerateSendableFuncModule) +HWTEST_F_L0(EcmaModuleTest, EvaluateNativeModule3) { - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); JSHandle module = objectFactory->NewSourceTextModule(); - module->SetSharedType(SharedTypes::SHARED_MODULE); - JSHandle moduleRecord = JSHandle::Cast(module); - SendableClassModule::GenerateSendableFuncModule(thread, moduleRecord); - JSHandle currentModule = JSHandle::Cast(moduleRecord); - EXPECT_TRUE(SourceTextModule::IsModuleInSharedHeap(currentModule)); + JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + JSHandle localExportEntry = + objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); + JSHandle localExportEntries = objectFactory->NewTaggedArray(1); + localExportEntries->Set(thread, 0, localExportEntry); + module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + module->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module, 0, val); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + module->SetStatus(ModuleStatus::INSTANTIATED); + Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); + Local globalObject = JSNApi::GetGlobalObject(vm); + globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiValue)); + SourceTextModule::EvaluateNativeModule(thread, module, ModuleTypes::APP_MODULE); + EXPECT_TRUE(!thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, ConcatMergeFileNameToNormalized) + +HWTEST_F_L0(EcmaModuleTest, InnerModuleInstantiation) { - CString baseFilename = "merge.abc"; - const char *data = R"( - .language ECMAScript - .function any func_main_0(any a0, any a1, any a2) { - ldai 1 - return - } - )"; - JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance(); - Parser parser; - auto res = parser.Parse(data); - std::unique_ptr pfPtr = pandasm::AsmEmitter::Emit(res.Value()); - std::shared_ptr pf = pfManager->NewJSPandaFile(pfPtr.release(), baseFilename); - - CString requestPath = "@normalized:N&&&har/Index&1.0.0"; - CString recordName = ""; - CString result = "&har/Index&1.0.0"; - CString entryPoint = ModulePathHelper::ConcatMergeFileNameToNormalized(thread, pf.get(), baseFilename, recordName, - requestPath); - EXPECT_EQ(result, entryPoint); - - requestPath = "&index"; - result = "&index"; - entryPoint = ModulePathHelper::ConcatMergeFileNameToNormalized(thread, pf.get(), baseFilename, recordName, - requestPath); - EXPECT_EQ(result, entryPoint); - - requestPath = "./@normalized:N&&&har/Index&1.0.0"; - result = "@normalized:N&&&har/Index&1.0.0&"; - pf->InsertJSRecordInfo(result); - entryPoint = ModulePathHelper::ConcatMergeFileNameToNormalized(thread, pf.get(), baseFilename, recordName, - requestPath); - EXPECT_EQ(result, entryPoint); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + module->SetEcmaModuleFilenameString("modules.abc"); + module->SetEcmaModuleRecordNameString("b"); + module->SetTypes(ModuleTypes::ECMA_MODULE); + module->SetStatus(ModuleStatus::UNINSTANTIATED); + module->SetIsNewBcVersion(false); + CVector> stack; + int index = SourceTextModule::InnerModuleInstantiation(thread, JSHandle::Cast(module), stack, 1, 0); + EXPECT_EQ(index, 2); } -HWTEST_F_L0(EcmaModuleTest, ConcatImportFileNormalizedOhmurlWithRecordName) +HWTEST_F_L0(EcmaModuleTest, ModuleDeclarationEnvironmentSetup) { - CString baseFilename = "merge.abc"; - const char *data = R"( - .language ECMAScript - .function any func_main_0(any a0, any a1, any a2) { - ldai 1 - return - } - )"; - JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance(); - Parser parser; - auto res = parser.Parse(data); - std::unique_ptr pfPtr = pandasm::AsmEmitter::Emit(res.Value()); - std::shared_ptr pf = pfManager->NewJSPandaFile(pfPtr.release(), baseFilename); - - CString requestPath = "@normalized:N&&&har/Index&1.0.0"; - CString recordName = ""; - CString entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), - baseFilename, recordName, requestPath); - EXPECT_EQ(CString(), entryPoint); - - requestPath = "@normalized:N&&&har/Index&1.0.0"; - CString result = "&har/Index&1:0.0"; - pf->InsertJSRecordInfo(result); - entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), baseFilename, - recordName, requestPath); - EXPECT_EQ(result, entryPoint); - - requestPath = "@normalized:N&&&har/Index&1.0.0"; - result = "@normalized:N&&&har/Index&1.0.0/index&"; - pf->InsertJSRecordInfo(result); - entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), baseFilename, - recordName, requestPath); - EXPECT_EQ(result, entryPoint); - - requestPath = "@normalized:N&&&har/Index&1.0.0"; - result = "@normalized:N&&&har/Index&1.0.0&"; - pf->InsertJSRecordInfo(result); - entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), baseFilename, - recordName, requestPath); - EXPECT_EQ(result, entryPoint); - - requestPath = "./@normalized:N&&&har/Index&1.0.0"; - entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), baseFilename, - recordName, requestPath); - EXPECT_EQ(result, entryPoint); - - requestPath = "./Test2"; - recordName = "&entry/ets/pages/Index&"; - result = "&entry/ets/pages/Test2&"; - pf->InsertJSRecordInfo(result); - entryPoint = ModulePathHelper::ConcatImportFileNormalizedOhmurlWithRecordName(thread, pf.get(), baseFilename, - recordName, requestPath); - EXPECT_EQ(result, entryPoint); -} + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + CString baseFileName = "modules.abc"; + CString recordName = "a"; + CString recordName1 = "@ohos:hilog"; + module->SetEcmaModuleFilenameString(baseFileName); + module->SetEcmaModuleRecordNameString(recordName); + module->SetTypes(ModuleTypes::NATIVE_MODULE); + module->SetStatus(ModuleStatus::UNINSTANTIATED); + JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + JSHandle moduleRequest = + JSHandle::Cast(objectFactory->NewFromUtf8(recordName1.c_str())); + JSHandle importName = val; + JSHandle localName = val; + JSHandle importEntry1 = + objectFactory->NewImportEntry(moduleRequest, importName, localName, SharedTypes::UNSENDABLE_MODULE); + SourceTextModule::AddImportEntry(thread, module, importEntry1, 0, 2); + JSHandle starString = thread->GlobalConstants()->GetHandledStarString(); + JSHandle importEntry2 = + objectFactory->NewImportEntry(moduleRequest, starString, localName, SharedTypes::UNSENDABLE_MODULE); + SourceTextModule::AddImportEntry(thread, module, importEntry2, 1, 2); -HWTEST_F_L0(EcmaModuleTest, HostResolveImportedModuleWithMerge) -{ - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); JSHandle module1 = objectFactory->NewSourceTextModule(); - module1->SetEcmaModuleRecordNameString("test"); - JSHandle module2 = objectFactory->NewSourceTextModule(); - CString recordName2 = "@ohos:hilog"; - module2->SetEcmaModuleRecordNameString(recordName2); - module2->SetTypes(ModuleTypes::NATIVE_MODULE); - - JSHandle nativeName = JSHandle::Cast(objectFactory->NewFromUtf8("@ohos:hilog")); - JSHandle res1 = - ModuleResolver::HostResolveImportedModule(thread, module1, nativeName, false); - EXPECT_TRUE(res1->IsSourceTextModule()); + module1->SetEcmaModuleFilenameString(baseFileName); + module1->SetEcmaModuleRecordNameString(recordName1); + JSHandle localExportEntry = + objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); + JSHandle localExportEntries = objectFactory->NewTaggedArray(1); + localExportEntries->Set(thread, 0, localExportEntry); + module1->SetLocalExportEntries(thread, localExportEntries); + module1->SetTypes(ModuleTypes::NATIVE_MODULE); + module1->SetStatus(ModuleStatus::EVALUATED); + + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + moduleManager->AddResolveImportedModule(recordName.c_str(), module.GetTaggedValue()); + moduleManager->AddResolveImportedModule(recordName1.c_str(), module1.GetTaggedValue()); + CVector> stack; + SourceTextModule::ModuleDeclarationEnvironmentSetup(thread, module); + EXPECT_TRUE(!thread->HasPendingException()); - thread->GetCurrentEcmaContext()->GetModuleManager()->AddResolveImportedModule( - recordName2, module2.GetTaggedValue()); - JSHandle res2 = - ModuleResolver::HostResolveImportedModule(thread, module1, nativeName, false); - EXPECT_TRUE(res2->IsSourceTextModule()); + module->SetEcmaModuleRecordNameString(""); + SourceTextModule::ModuleDeclarationEnvironmentSetup(thread, module); + EXPECT_TRUE(!thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, ModuleResolverHostResolveImportedModule) +HWTEST_F_L0(EcmaModuleTest, ModuleDeclarationArrayEnvironmentSetup) { - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); - JSHandle module1 = objectFactory->NewSourceTextModule(); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(thread, module); + EXPECT_TRUE(!thread->HasPendingException()); - JSHandle module2 = objectFactory->NewSourceTextModule(); - CString recordName2 = "@ohos:hilog"; - module2->SetEcmaModuleRecordNameString(recordName2); - module2->SetTypes(ModuleTypes::NATIVE_MODULE); + module->SetSharedType(SharedTypes::SHARED_MODULE); + SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(thread, module); + EXPECT_TRUE(!thread->HasPendingException()); - JSHandle nativeName = JSHandle::Cast(objectFactory->NewFromUtf8("@ohos:hilog")); - thread->GetCurrentEcmaContext()->GetModuleManager()->AddResolveImportedModule( - recordName2, module2.GetTaggedValue()); - JSHandle res1 = - ModuleResolver::HostResolveImportedModule(thread, module1, nativeName, false); - EXPECT_TRUE(res1->IsSourceTextModule()); + module->SetStatus(ModuleStatus::EVALUATED); + SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(thread, module); + EXPECT_TRUE(!thread->HasPendingException()); + + module->SetSharedType(SharedTypes::UNSENDABLE_MODULE); + SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(thread, module); + EXPECT_TRUE(!thread->HasPendingException()); } -HWTEST_F_L0(EcmaModuleTest, ResolveExportObject) +HWTEST_F_L0(EcmaModuleTest, Evaluate) { - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); - JSHandle module1 = objectFactory->NewSourceTextModule(); - - JSHandle exportName = JSHandle::Cast(objectFactory->NewFromUtf8("notExist")); - JSHandle nativeModuleFailureInfo = objectFactory->NewNativeModuleFailureInfo(); - JSHandle res1 = SourceTextModule::ResolveExportObject( - thread, module1, JSHandle::Cast(nativeModuleFailureInfo), exportName); - EXPECT_TRUE(res1->IsResolvedIndexBinding()); - - JSHandle ctor(thread->GetEcmaVM()->GetGlobalEnv()->GetObjectFunction()); - JSHandle obj(objectFactory->NewJSObjectByConstructor(ctor)); - JSHandle exportArr = objectFactory->NewTaggedArray(2); - obj->SetProperties(thread, exportArr); - JSHandle jsHclass(thread, obj->GetJSHClass()); - JSHandle layout = objectFactory->CreateLayoutInfo(0, MemSpaceType::OLD_SPACE, GrowMode::KEEP); - jsHclass->SetLayout(thread, layout); - JSHandle res2 = SourceTextModule::ResolveExportObject( - thread, module1, JSHandle::Cast(obj), exportName); - EXPECT_TRUE(res2->IsHole()); - - JSHandle obj1(objectFactory->NewJSObjectByConstructor(ctor)); - JSHandle dict = NameDictionary::Create(thread, NameDictionary::ComputeHashTableSize(2)); - obj1->SetProperties(thread, JSHandle::Cast(dict)); - JSHandle res3 = SourceTextModule::ResolveExportObject( - thread, module1, JSHandle::Cast(obj1), exportName); - EXPECT_TRUE(res3->IsHole()); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); + JSHandle module = objectFactory->NewSourceTextModule(); + CString recordName = "a"; + module->SetEcmaModuleRecordNameString(recordName); + module->SetStatus(ModuleStatus::EVALUATED); + module->SetCycleRoot(thread, module); + SourceTextModule::Evaluate(thread, module, nullptr, 0, 0); + EXPECT_TRUE(!thread->HasPendingException()); + SourceTextModule::Evaluate(thread, module, nullptr, 0, 1); + EXPECT_TRUE(!thread->HasPendingException()); + ModuleLogger *moduleLogger = new ModuleLogger(vm); + thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); + SourceTextModule::Evaluate(thread, module, nullptr, 0, 0); + EXPECT_TRUE(!thread->HasPendingException()); + SourceTextModule::Evaluate(thread, module, nullptr, 0, 1); + EXPECT_TRUE(!thread->HasPendingException()); + thread->GetCurrentEcmaContext()->SetModuleLogger(nullptr); + delete moduleLogger; } -HWTEST_F_L0(EcmaModuleTest, ResolveNativeStarExport) +HWTEST_F_L0(EcmaModuleTest, LoadNativeModule) { - ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + auto vm = thread->GetEcmaVM(); + ObjectFactory *objectFactory = vm->GetFactory(); JSHandle module = objectFactory->NewSourceTextModule(); - CString recordName = "@ohos:hilog"; - module->SetEcmaModuleRecordNameString(recordName); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); JSHandle localExportEntry = objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); + module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); + SourceTextModule::StoreModuleValue(thread, module, 0, val); module->SetTypes(ModuleTypes::NATIVE_MODULE); - - JSHandle res1 = SourceTextModule::ResolveNativeStarExport(thread, module, val); - EXPECT_TRUE(res1->IsNull()); - - module->SetStatus(ModuleStatus::EVALUATED); - JSHandle res2 = SourceTextModule::ResolveNativeStarExport(thread, module, val); - EXPECT_TRUE(res2->IsNull()); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle res = moduleManager->LoadNativeModule( + thread, "@app:bundleName/moduleName/lib*.so"); + EXPECT_EQ(res.GetTaggedValue(), JSTaggedValue::Undefined()); } -HWTEST_F_L0(EcmaModuleTest, MakeInternalArgs) -{ - std::vector> arguments; - auto vm = thread->GetEcmaVM(); - CString soName = "@ohos:hilig"; - arguments.emplace_back(StringRef::NewFromUtf8(vm, soName.c_str())); - SourceTextModule::MakeInternalArgs(vm, arguments, soName); - EXPECT_TRUE(!thread->HasPendingException()); -} - -HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleImpl) +HWTEST_F_L0(EcmaModuleTest, ExecuteNativeModuleMayThrowError) { auto vm = thread->GetEcmaVM(); ObjectFactory *objectFactory = vm->GetFactory(); + CString recordName = "@app:bundleName/moduleName/lib*.so"; JSHandle module = objectFactory->NewSourceTextModule(); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); JSHandle localExportEntry = objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); + module->SetEcmaModuleRecordNameString(recordName); module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); + SourceTextModule::StoreModuleValue(thread, module, 0, val); module->SetTypes(ModuleTypes::NATIVE_MODULE); - ModuleLogger *moduleLogger = new ModuleLogger(vm); - thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); - // app module - module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); - SourceTextModule::LoadNativeModuleImpl(vm, thread, module, ModuleTypes::APP_MODULE); - EXPECT_TRUE(!thread->HasPendingException()); - - // internal module - Local globalObject = JSNApi::GetGlobalObject(vm); - globalObject->Set(vm, StringRef::NewFromUtf8(vm, "requireNapi"), - FunctionRef::New(const_cast(vm), MockRequireNapiUndefined)); - module->SetEcmaModuleRecordNameString("@hms:xxxxx"); - SourceTextModule::LoadNativeModuleImpl(vm, thread, module, ModuleTypes::INTERNAL_MODULE); - EXPECT_TRUE(!thread->HasPendingException()); + module->SetStatus(ModuleStatus::EVALUATED); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle res = moduleManager->ExecuteNativeModuleMayThrowError( + thread, recordName); + EXPECT_EQ(res.GetTaggedValue(), JSTaggedValue::Undefined()); - thread->GetCurrentEcmaContext()->SetModuleLogger(nullptr); - delete moduleLogger; - SourceTextModule::LoadNativeModuleImpl(vm, thread, module, ModuleTypes::INTERNAL_MODULE); - EXPECT_TRUE(!thread->HasPendingException()); + thread->GetCurrentEcmaContext()->GetModuleManager()->AddResolveImportedModule( + recordName, module.GetTaggedValue()); + JSHandle res2 = moduleManager->ExecuteNativeModuleMayThrowError( + thread, recordName); + EXPECT_NE(res2.GetTaggedValue(), JSTaggedValue::Undefined()); } -HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleMayThrowError1) +HWTEST_F_L0(EcmaModuleTest, ExecuteNativeModule) { auto vm = thread->GetEcmaVM(); + CString recordName = "@app:bundleName/moduleName/lib*.so"; ObjectFactory *objectFactory = vm->GetFactory(); JSHandle module = objectFactory->NewSourceTextModule(); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); @@ -2523,20 +2286,25 @@ HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleMayThrowError1) objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + module->SetEcmaModuleRecordNameString(recordName); module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); + SourceTextModule::StoreModuleValue(thread, module, 0, val); module->SetTypes(ModuleTypes::NATIVE_MODULE); - Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); - Local globalObject = JSNApi::GetGlobalObject(vm); - globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiFailure)); - SourceTextModule::LoadNativeModuleMayThrowError(thread, module, ModuleTypes::APP_MODULE); - EXPECT_TRUE(thread->HasPendingException()); + + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED); + thread->GetCurrentEcmaContext()->GetModuleManager()->AddResolveImportedModule( + recordName, module.GetTaggedValue()); + moduleManager->ExecuteNativeModule(thread, recordName); + module->SetStatus(ModuleStatus::EVALUATED); + JSHandle res = moduleManager->ExecuteNativeModule(thread, recordName); + EXPECT_NE(res.GetTaggedValue(), JSTaggedValue::Undefined()); } -HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleMayThrowError2) +HWTEST_F_L0(EcmaModuleTest, ExecuteNativeModule2) { auto vm = thread->GetEcmaVM(); + CString recordName = "@app:bundleName/moduleName/lib*.so"; ObjectFactory *objectFactory = vm->GetFactory(); JSHandle module = objectFactory->NewSourceTextModule(); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); @@ -2544,372 +2312,662 @@ HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleMayThrowError2) objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); + module->SetEcmaModuleRecordNameString(recordName); module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); + SourceTextModule::StoreModuleValue(thread, module, 0, val); module->SetTypes(ModuleTypes::NATIVE_MODULE); - Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); - Local globalObject = JSNApi::GetGlobalObject(vm); - globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiUndefined)); - SourceTextModule::LoadNativeModuleMayThrowError(thread, module, ModuleTypes::APP_MODULE); - EXPECT_TRUE(thread->HasPendingException()); + + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle res = moduleManager->ExecuteNativeModule(thread, recordName); + EXPECT_NE(res.GetTaggedValue(), JSTaggedValue::Undefined()); } -HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleMayThrowError3) -{ - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle localExportEntry = - objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); - JSHandle localExportEntries = objectFactory->NewTaggedArray(1); - localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); - module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); - Local globalObject = JSNApi::GetGlobalObject(vm); - globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiException)); - SourceTextModule::LoadNativeModuleMayThrowError(thread, module, ModuleTypes::APP_MODULE); - EXPECT_TRUE(thread->HasPendingException()); +HWTEST_F_L0(EcmaModuleTest, ModuleLogger) { + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle module1 = objectFactory->NewSourceTextModule(); + CString baseFileName = "modules.abc"; + module1->SetEcmaModuleFilenameString(baseFileName); + CString recordName1 = "a"; + module1->SetEcmaModuleRecordNameString(recordName1); + JSHandle module2 = objectFactory->NewSourceTextModule(); + module2->SetEcmaModuleFilenameString(baseFileName); + CString recordName2 = "b"; + module2->SetEcmaModuleRecordNameString(recordName2); + JSHandle moduleRequest = JSHandle::Cast(objectFactory->NewFromUtf8("c")); + JSHandle importName = JSHandle::Cast(objectFactory->NewFromUtf8("ccc")); + JSHandle localName = JSHandle::Cast(objectFactory->NewFromUtf8("ccc")); + JSHandle importEntry = objectFactory->NewImportEntry(moduleRequest, importName, + localName, SharedTypes::UNSENDABLE_MODULE); + SourceTextModule::AddImportEntry(thread, module2, importEntry, 0, 1); + JSHandle module3 = objectFactory->NewSourceTextModule(); + module2->SetEcmaModuleFilenameString(baseFileName); + CString recordName3 = "c"; + module2->SetEcmaModuleRecordNameString(recordName3); + ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM()); + moduleLogger->SetStartTime(recordName1); + moduleLogger->SetEndTime(recordName1); + moduleLogger->SetStartTime(recordName2); + moduleLogger->SetEndTime(recordName2); + moduleLogger->SetStartTime(recordName3); + moduleLogger->InsertEntryPointModule(module1); + moduleLogger->InsertParentModule(module1, module2); + moduleLogger->InsertModuleLoadInfo(module2, module3, -1); + moduleLogger->InsertModuleLoadInfo(module2, module3, 0); + moduleLogger->PrintModuleLoadInfo(); + Local nativeFunc = SourceTextModule::GetRequireNativeModuleFunc(thread->GetEcmaVM(), + module3->GetTypes()); + bool isFunc = nativeFunc->IsFunction(thread->GetEcmaVM()); + EXPECT_EQ(isFunc, false); } -HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleMayThrowError4) -{ - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); +HWTEST_F_L0(EcmaModuleTest, GetRequireNativeModuleFunc) { + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); JSHandle module = objectFactory->NewSourceTextModule(); - JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle localExportEntry = - objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); - JSHandle localExportEntries = objectFactory->NewTaggedArray(1); - localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); - module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); - Local globalObject = JSNApi::GetGlobalObject(vm); - globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiValue)); - SourceTextModule::LoadNativeModuleMayThrowError(thread, module, ModuleTypes::APP_MODULE); - EXPECT_TRUE(!thread->HasPendingException()); + uint16_t registerNum = module->GetRegisterCounts(); + module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED); + module->SetRegisterCounts(registerNum); + Local nativeFunc = SourceTextModule::GetRequireNativeModuleFunc(thread->GetEcmaVM(), + module->GetTypes()); + bool isFunc = nativeFunc->IsFunction(thread->GetEcmaVM()); + EXPECT_EQ(isFunc, false); } -HWTEST_F_L0(EcmaModuleTest, LoadNativeModule1) +/* + * Feature: Module + * Function: StoreModuleValue + * SubFunction: StoreModuleValue/GetModuleValue + * FunctionPoints: store a module export item in module + * CaseDescription: Simulated implementation of "export foo as bar", set foo as "hello world", + * use "import bar" in same js file + */ +HWTEST_F_L0(EcmaModuleTest, StoreModuleValue2) { - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory(); + CString localName = "foo"; + CString exportName = "bar"; + CString value = "hello world"; + CString value2 = "hello world1"; + int32_t index = 1; + + JSHandle localNameHandle = JSHandle::Cast(objFactory->NewFromUtf8(localName)); + JSHandle exportNameHandle = JSHandle::Cast(objFactory->NewFromUtf8(exportName)); JSHandle localExportEntry = - objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); - JSHandle localExportEntries = objectFactory->NewTaggedArray(1); - localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); - module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); - Local globalObject = JSNApi::GetGlobalObject(vm); - globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiValue)); - SourceTextModule::LoadNativeModule(thread, module, ModuleTypes::APP_MODULE); - EXPECT_TRUE(!thread->HasPendingException()); + objFactory->NewLocalExportEntry(exportNameHandle, localNameHandle, LocalExportEntry::LOCAL_DEFAULT_INDEX, + SharedTypes::UNSENDABLE_MODULE); + JSHandle module = objFactory->NewSourceTextModule(); + SourceTextModule::AddLocalExportEntry(thread, module, localExportEntry, 0, 1); + + JSHandle storeKey = JSHandle::Cast(objFactory->NewFromUtf8(localName)); + JSHandle valueHandle = JSHandle::Cast(objFactory->NewFromUtf8(value)); + JSHandle valueHandle1 = JSHandle::Cast(objFactory->NewFromUtf8(value2)); + SourceTextModule::StoreModuleValue(thread, module, storeKey, valueHandle); + SourceTextModule::StoreModuleValue(thread, module, index, valueHandle1); + JSHandle loadKey = JSHandle::Cast(objFactory->NewFromUtf8(localName)); + JSTaggedValue loadValue = module->GetModuleValue(thread, loadKey.GetTaggedValue(), false); + JSTaggedValue loadValue1 = module->GetModuleValue(thread, index, false); + EXPECT_EQ(valueHandle.GetTaggedValue(), loadValue); + EXPECT_EQ(valueHandle1.GetTaggedValue(), loadValue1); } -HWTEST_F_L0(EcmaModuleTest, LoadNativeModule2) -{ - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle localExportEntry = - objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); - JSHandle localExportEntries = objectFactory->NewTaggedArray(1); - localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); - module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); - Local globalObject = JSNApi::GetGlobalObject(vm); - globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiFailure)); - SourceTextModule::LoadNativeModule(thread, module, ModuleTypes::APP_MODULE); - EXPECT_TRUE(!thread->HasPendingException()); +HWTEST_F_L0(EcmaModuleTest, MakeAppArgs1) { + std::vector> arguments; + CString soPath = "@normalized:Y&&&libentry.so&"; + CString moduleName = "entry"; + CString requestName = "@normalized:"; + arguments.emplace_back(StringRef::NewFromUtf8(thread->GetEcmaVM(), soPath.c_str())); + SourceTextModule::MakeAppArgs(thread->GetEcmaVM(), arguments, soPath, moduleName, requestName); + std::string res1 = arguments[0]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); + std::string res2 = arguments[1]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); + std::string res3 = arguments[2]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); + EXPECT_TRUE(res1 == "entry"); + EXPECT_TRUE(res2 == "true"); + EXPECT_TRUE(res3 == "/entry"); } -HWTEST_F_L0(EcmaModuleTest, EvaluateNativeModule1) -{ - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - module->SetStatus(ModuleStatus::EVALUATED); - SourceTextModule::EvaluateNativeModule(thread, module, ModuleTypes::APP_MODULE); - EXPECT_TRUE(!thread->HasPendingException()); +HWTEST_F_L0(EcmaModuleTest, MakeAppArgs2) { + std::vector> arguments; + CString soPath = "@app:com.example.myapplication/entry"; + CString moduleName = "entry"; + CString requestName = "@app:"; + arguments.emplace_back(StringRef::NewFromUtf8(thread->GetEcmaVM(), soPath.c_str())); + SourceTextModule::MakeAppArgs(thread->GetEcmaVM(), arguments, soPath, moduleName, requestName); + std::string res1 = arguments[0]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); + std::string res2 = arguments[1]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); + std::string res3 = arguments[2]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM()); + EXPECT_TRUE(res1 == "entry"); + EXPECT_TRUE(res2 == "true"); + EXPECT_TRUE(res3 == "@app:com.example.myapplication"); } -HWTEST_F_L0(EcmaModuleTest, EvaluateNativeModule2) +HWTEST_F_L0(EcmaModuleTest, ConcatHspFileNameCrossBundle) { - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle localExportEntry = - objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); - JSHandle localExportEntries = objectFactory->NewTaggedArray(1); - localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); - module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - module->SetStatus(ModuleStatus::INSTANTIATED); - Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); - Local globalObject = JSNApi::GetGlobalObject(vm); - globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiFailure)); - SourceTextModule::EvaluateNativeModule(thread, module, ModuleTypes::APP_MODULE); - EXPECT_TRUE(!thread->HasPendingException()); + CString bundleName = "com.example.application"; + CString moduleName = "entry"; + CString expectRes = "/data/storage/el1/bundle/com.example.application/entry/entry/ets/modules.abc"; + CString res = ModulePathHelper::ConcatHspFileNameCrossBundle(bundleName, moduleName); + EXPECT_EQ(res, expectRes); } -HWTEST_F_L0(EcmaModuleTest, EvaluateNativeModule3) +HWTEST_F_L0(EcmaModuleTest, ConcatHspFileName) { - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle localExportEntry = - objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); - JSHandle localExportEntries = objectFactory->NewTaggedArray(1); - localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); - module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - module->SetStatus(ModuleStatus::INSTANTIATED); - Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); - Local globalObject = JSNApi::GetGlobalObject(vm); - globalObject->Set(vm, requireNapi, FunctionRef::New(const_cast(vm), MockRequireNapiValue)); - SourceTextModule::EvaluateNativeModule(thread, module, ModuleTypes::APP_MODULE); - EXPECT_TRUE(!thread->HasPendingException()); + CString moduleName = "entry"; + CString expectRes = "/data/storage/el1/bundle/entry/ets/modules.abc"; + CString res = ModulePathHelper::ConcatHspFileName(moduleName); + EXPECT_EQ(res, expectRes); } +HWTEST_F_L0(EcmaModuleTest, ParseNormalizedOhmUrl) +{ + CString baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + CString recordName = "&har/Index&1.0.0"; + CString requestName = "@normalized:N&&&har/src/main/page/Test&1.0.0"; + CString expectRes = "&har/src/main/page/Test&1.0.0"; + CString exceptBaseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + CString res = ModulePathHelper::ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName); + EXPECT_EQ(res, expectRes); + EXPECT_EQ(baseFileName, exceptBaseFileName); -HWTEST_F_L0(EcmaModuleTest, InnerModuleInstantiation) + requestName = "@normalized:N&&har/src/main/page/Test&1.0.0"; + res = ModulePathHelper::ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName); + EXPECT_TRUE((thread)->HasPendingException()); + EXPECT_EQ(res, requestName); + + baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + requestName = "@normalized:N&hsp&&hsp/src/main/page/Test&1.0.0"; + expectRes = "&hsp/src/main/page/Test&1.0.0"; + exceptBaseFileName = "/data/storage/el1/bundle/hsp/ets/modules.abc"; + CString res2 = ModulePathHelper::ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName); + EXPECT_EQ(res2, expectRes); + EXPECT_EQ(baseFileName, exceptBaseFileName); + + baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + requestName = "@normalized:N&hsp&com.example.application&hsp/src/main/page/Test&1.0.0"; + exceptBaseFileName = "/data/storage/el1/bundle/com.example.application/hsp/hsp/ets/modules.abc"; + expectRes = "com.example.application&hsp/src/main/page/Test&1.0.0"; + CString res3 = ModulePathHelper::ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName); + EXPECT_EQ(res3, expectRes); + EXPECT_EQ(baseFileName, exceptBaseFileName); + + baseFileName = ""; + recordName = "&har/Index&1.0.0"; + requestName = "@normalized:N&&&har/src/main/page/Test&1.0.0"; + CString res4 = ModulePathHelper::ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName); + EXPECT_EQ(baseFileName, ""); + + baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + requestName = "@normalized:N&&com.example.application&hsp/src/main/page/Test&1.0.0"; + expectRes = "com.example.application&hsp/src/main/page/Test&1.0.0"; + CString res5 = ModulePathHelper::ParseNormalizedOhmUrl(thread, baseFileName, recordName, requestName); + EXPECT_EQ(res5, expectRes); +} + +HWTEST_F_L0(EcmaModuleTest, GetModuleNameWithBaseFile) { - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - module->SetEcmaModuleFilenameString("modules.abc"); - module->SetEcmaModuleRecordNameString("b"); - module->SetTypes(ModuleTypes::ECMA_MODULE); - module->SetStatus(ModuleStatus::UNINSTANTIATED); - module->SetIsNewBcVersion(false); - CVector> stack; - int index = SourceTextModule::InnerModuleInstantiation(thread, JSHandle::Cast(module), stack, 1, 0); - EXPECT_EQ(index, 2); + CString baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + CString expectRes = "entry"; + CString res = ModulePathHelper::GetModuleNameWithBaseFile(baseFileName); + EXPECT_EQ(res, expectRes); + + baseFileName = "/data/storage/el1/bundle/com.example.application/hsp/hsp/ets/modules.abc"; + expectRes = "hsp"; + res = ModulePathHelper::GetModuleNameWithBaseFile(baseFileName); + EXPECT_EQ(res, expectRes); } -HWTEST_F_L0(EcmaModuleTest, InnerModuleInstantiation_ReEnter) + +HWTEST_F_L0(EcmaModuleTest, GetBundleNameWithRecordName) +{ + CString recordName = "com.example.myapplication/library"; + CString expectRes = "com.example.myapplication"; + CString res = ModulePathHelper::GetBundleNameWithRecordName(instance, recordName); + EXPECT_EQ(res, expectRes); + + CMap>> list; + CMap> childList; + list["hsp"] = childList; + instance->SetpkgContextInfoList(list); + + recordName = "&hsp&com.example.application&hsp/src/main/page/Test&1.0.0"; + expectRes = "com.example.application"; + res = ModulePathHelper::GetBundleNameWithRecordName(instance, recordName); + EXPECT_EQ(res, expectRes); + + instance->SetBundleName("com.example1.application"); + recordName = "&har/src/main/page/Test&1.0.0"; + expectRes = "com.example1.application"; + res = ModulePathHelper::GetBundleNameWithRecordName(instance, recordName); + EXPECT_EQ(res, expectRes); +} + +HWTEST_F_L0(EcmaModuleTest, InnerModuleInstantiation_ReEnterTest) { auto vm = thread->GetEcmaVM(); ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); + JSHandle module = objectFactory->NewSSourceTextModule(); module->SetEcmaModuleFilenameString("modules.abc"); module->SetEcmaModuleRecordNameString("b"); module->SetTypes(ModuleTypes::ECMA_MODULE); module->SetStatus(ModuleStatus::EVALUATING); module->SetIsNewBcVersion(true); + module->SetSharedType(SharedTypes::SHARED_MODULE); CVector> stack; int index = SourceTextModule::InnerModuleInstantiation(thread, JSHandle::Cast(module), stack, 1, 0); EXPECT_EQ(index, 1); } -HWTEST_F_L0(EcmaModuleTest, ModuleDeclarationEnvironmentSetup) +HWTEST_F_L0(EcmaModuleTest, TransformToNormalizedOhmUrl) { - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); + CMap>> pkgList; + CMap> entryList; + entryList["entry"] = { + "packageName", "entry", + "bundleName", "", + "moduleName", "", + "version", "", + "entryPath", "src/main/", + "isSO", "false" + }; + entryList["har"] = { + "packageName", "har", + "bundleName", "", + "moduleName", "", + "version", "1.2.0", + "entryPath", "", + "isSO", "false" + }; + pkgList["entry"] = entryList; + CMap> ohosTestList; + ohosTestList["ohosTest"] = { + "packageName", "ohosTest", + "bundleName", "", + "moduleName", "", + "version", "", + "entryPath", "src/", + "isSO", "false" + }; + pkgList["ohosTest"] = ohosTestList; + instance->SetpkgContextInfoList(pkgList); + + CString inputFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + CString outBaseFileName = ""; + CString entryPoint = "ENTRY_MAIN_FUNCTION"; + CString res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); + EXPECT_EQ(res, "ENTRY_MAIN_FUNCTION"); + + outBaseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + entryPoint = "com.example.myapplication/entry@har/ets/pages/Index"; + res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); + EXPECT_EQ(res, "&har/src/main/ets/pages/Index&1.2.0"); + + outBaseFileName = "/data/storage/el1/bundle/ohosTest/ets/modules.abc"; + entryPoint = "com.example.myapplication/ohosTest/ets/pages/Index"; + res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); + EXPECT_EQ(res, "&ohosTest/src/ets/pages/Index&"); + + outBaseFileName = "/data/storage/el1/bundle/entry/.test/ets/modules.abc"; + entryPoint = "com.example.myapplication/entry/.test/ets/pages/Index"; + res = ModulePathHelper::TransformToNormalizedOhmUrl(instance, inputFileName, outBaseFileName, entryPoint); + EXPECT_EQ(res, "&entry/.test/ets/pages/Index&"); +} + +HWTEST_F_L0(EcmaModuleTest, TranslateExpressionInputWithEts) +{ + instance->SetBundleName("com.example.myapplication"); + CString baseFilename = "merge.abc"; + const char *data = R"( + .language ECMAScript + .function any func_main_0(any a0, any a1, any a2) { + ldai 1 + return + } + )"; + JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance(); + Parser parser; + auto res = parser.Parse(data); + std::unique_ptr pfPtr = pandasm::AsmEmitter::Emit(res.Value()); + std::shared_ptr pf = pfManager->NewJSPandaFile(pfPtr.release(), baseFilename); + + CString baseFileName = "/data/storage/el1/bundle/entry/ets/modules.abc"; + CString requestName = "ets/Test"; + CString recordName = "com.example.myapplication/entry/ets/pages/Index"; + CString expectRes = "com.example.myapplication/entry/ets/Test"; + CString result = ModulePathHelper::TranslateExpressionInputWithEts(thread, pf.get(), baseFileName, requestName); + EXPECT_EQ(result, ""); + + pf->InsertJSRecordInfo(expectRes); + result = ModulePathHelper::TranslateExpressionInputWithEts(thread, pf.get(), baseFileName, requestName); + EXPECT_EQ(result, expectRes); +} + +HWTEST_F_L0(EcmaModuleTest, ReviseLoadedModuleCount1) { + CString moduleName = "testModule"; + ModuleDeregister::ReviseLoadedModuleCount(thread, moduleName); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + bool res = moduleManager->IsLocalModuleLoaded(moduleName); + EXPECT_EQ(res, false); +} + +HWTEST_F_L0(EcmaModuleTest, IncreaseRegisterCounts) +{ + std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; + JSNApi::EnableUserUncaughtErrorHandler(instance); + bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); + EXPECT_TRUE(result); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle module2 = objectFactory->NewSourceTextModule(); + std::set increaseModule; + + ModuleDeregister::IncreaseRegisterCounts(thread, module, increaseModule); + EXPECT_EQ(module->GetRequestedModules().IsUndefined(), false); + + module->SetRegisterCounts(INT8_MAX); + ModuleDeregister::IncreaseRegisterCounts(thread, module, increaseModule); + EXPECT_EQ(module->GetRequestedModules().IsUndefined(), false); + + module2->SetRegisterCounts(INT8_MAX); + ModuleDeregister::IncreaseRegisterCounts(thread, module2, increaseModule); + EXPECT_EQ(module2->GetRequestedModules().IsUndefined(), true); + + module2->SetLoadingTypes(LoadingTypes::STABLE_MODULE); + ModuleDeregister::IncreaseRegisterCounts(thread, module2, increaseModule); + bool res = module2->GetLoadingTypes() == LoadingTypes::STABLE_MODULE; + EXPECT_EQ(res, true); +} + +HWTEST_F_L0(EcmaModuleTest, DecreaseRegisterCounts) +{ + std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; + JSNApi::EnableUserUncaughtErrorHandler(instance); + bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); + EXPECT_TRUE(result); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle module2 = objectFactory->NewSourceTextModule(); + std::set decreaseModule; + + ModuleDeregister::DecreaseRegisterCounts(thread, module, decreaseModule); + bool res1 = module->GetLoadingTypes() != LoadingTypes::DYNAMITC_MODULE; + EXPECT_EQ(res1, true); + + module->SetRegisterCounts(INT8_MAX); + ModuleDeregister::DecreaseRegisterCounts(thread, module, decreaseModule); + EXPECT_EQ(module->GetRequestedModules().IsUndefined(), false); + + module2->SetLoadingTypes(LoadingTypes::DYNAMITC_MODULE); + ModuleDeregister::DecreaseRegisterCounts(thread, module2, decreaseModule); + bool res2 = module2->GetLoadingTypes() != LoadingTypes::DYNAMITC_MODULE; + EXPECT_EQ(res2, false); +} + +HWTEST_F_L0(EcmaModuleTest, GetSendableModuleValueImpl) { + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle module1 = objectFactory->NewSourceTextModule(); + SharedModuleManager* manager1 = SharedModuleManager::GetInstance(); + int32_t index = 2; + JSTaggedValue currentModule1 = module1.GetTaggedValue(); + JSTaggedValue res1 = manager1->GetSendableModuleValueImpl( + thread, index, currentModule1); + EXPECT_EQ(res1, thread->GlobalConstants()->GetUndefined()); + + SharedModuleManager* manager2 = SharedModuleManager::GetInstance(); + std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; + JSNApi::EnableUserUncaughtErrorHandler(instance); + bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); + EXPECT_TRUE(result); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle module2 = moduleManager->HostGetImportedModule("module_test_module_test_C"); + JSTaggedValue currentModule2 = module2.GetTaggedValue(); + JSTaggedValue res2 = manager2->GetSendableModuleValueImpl( + thread, index, currentModule2); + EXPECT_NE(res2, thread->GlobalConstants()->GetUndefined()); +} + +HWTEST_F_L0(EcmaModuleTest, GetLazySendableModuleValueImpl) { + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle module1 = objectFactory->NewSourceTextModule(); + SharedModuleManager* manager1 = SharedModuleManager::GetInstance(); + int32_t index = 2; + JSTaggedValue currentModule1 = module1.GetTaggedValue(); + JSTaggedValue res1 = manager1->GetLazySendableModuleValueImpl( + thread, index, currentModule1); + EXPECT_EQ(res1, thread->GlobalConstants()->GetUndefined()); +} + +HWTEST_F_L0(EcmaModuleTest, ResolveImportedModuleWithMerge) { + std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; + JSNApi::EnableUserUncaughtErrorHandler(instance); + bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); + EXPECT_TRUE(result); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); + module->SetSharedType(SharedTypes::SHARED_MODULE); + + CString recordName2 = "testModule"; + bool executeFromJob = false; + JSHandle res = ModuleResolver::ResolveImportedModuleWithMerge( + thread, baseFileName.c_str(), recordName2, executeFromJob); + EXPECT_EQ(res.GetTaggedValue(), JSTaggedValue::Exception()); +} + +HWTEST_F_L0(EcmaModuleTest, ResolveImportedModuleWithMerge2) { + CString moduleName1; + CString recordName1; + + bool executeFromJob = false; + JSHandle res = ModuleResolver::ResolveImportedModuleWithMerge( + thread, moduleName1, recordName1, executeFromJob); + EXPECT_EQ(res.GetTaggedValue(), JSTaggedValue::Exception()); +} + +HWTEST_F_L0(EcmaModuleTest, IsInstantiatedSModule) { + SharedModuleManager* manager1 = SharedModuleManager::GetInstance(); + std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc"; + JSNApi::EnableUserUncaughtErrorHandler(instance); + bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C"); + EXPECT_TRUE(result); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle module = moduleManager->HostGetImportedModule("module_test_module_test_C"); + bool res = manager1->IsInstantiatedSModule(thread, module); + EXPECT_EQ(res, true); +} + +HWTEST_F_L0(EcmaModuleTest, ProcessModuleLoadInfoForESM) +{ + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle module1 = objectFactory->NewSourceTextModule(); CString baseFileName = "modules.abc"; - CString recordName = "a"; - CString recordName1 = "@ohos:hilog"; - module->SetEcmaModuleFilenameString(baseFileName); - module->SetEcmaModuleRecordNameString(recordName); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - module->SetStatus(ModuleStatus::UNINSTANTIATED); + module1->SetEcmaModuleFilenameString(baseFileName); + CString recordName1 = "a"; + module1->SetEcmaModuleRecordNameString(recordName1); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle moduleRequest = - JSHandle::Cast(objectFactory->NewFromUtf8(recordName1.c_str())); - JSHandle importName = val; - JSHandle localName = val; - JSHandle importEntry1 = - objectFactory->NewImportEntry(moduleRequest, importName, localName, SharedTypes::UNSENDABLE_MODULE); - SourceTextModule::AddImportEntry(thread, module, importEntry1, 0, 2); - JSHandle starString = thread->GlobalConstants()->GetHandledStarString(); - JSHandle importEntry2 = - objectFactory->NewImportEntry(moduleRequest, starString, localName, SharedTypes::UNSENDABLE_MODULE); - SourceTextModule::AddImportEntry(thread, module, importEntry2, 1, 2); + JSHandle importEntry = + objectFactory->NewImportEntry(val, val, val, SharedTypes::UNSENDABLE_MODULE); + SourceTextModule::AddImportEntry(thread, module1, importEntry, 0, 1); + + JSHandle module2 = objectFactory->NewSourceTextModule(); + module2->SetEcmaModuleFilenameString(baseFileName); + CString recordName2 = "b"; + module2->SetEcmaModuleRecordNameString(recordName2); + JSHandle localExportEntry = + objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); + JSHandle localExportEntries = objectFactory->NewTaggedArray(1); + localExportEntries->Set(thread, 0, localExportEntry); + module2->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module2, 0, val); + module2->SetStatus(ModuleStatus::EVALUATED); + ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM()); + thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); + // test ResolvedIndexBinding + JSHandle indexBinding = + objectFactory->NewResolvedIndexBindingRecord(module2, 0); + JSTaggedValue res1 = ModuleTools::ProcessModuleLoadInfo(thread, module1, indexBinding.GetTaggedValue(), 0); + EXPECT_EQ(res1, val.GetTaggedValue()); + + JSTaggedValue res2 = ModuleTools::ProcessModuleNameSpaceLoadInfo(thread, module1, module2); + EXPECT_NE(res2, JSTaggedValue::Exception()); + + // test HotReload + thread->GetCurrentEcmaContext()->SetStageOfHotReload(StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN); + JSTaggedValue res3 = ModuleTools::ProcessModuleLoadInfo(thread, module1, indexBinding.GetTaggedValue(), 0); + EXPECT_EQ(res3, val.GetTaggedValue()); + + thread->GetCurrentEcmaContext()->AddPatchModule(recordName2, JSHandle::Cast(module2)); + JSTaggedValue res4 = ModuleTools::ProcessModuleLoadInfo(thread, module1, indexBinding.GetTaggedValue(), 0); + EXPECT_EQ(res4, val.GetTaggedValue()); + + thread->GetCurrentEcmaContext()->SetModuleLogger(nullptr); + delete moduleLogger; +} +HWTEST_F_L0(EcmaModuleTest, ProcessModuleLoadInfoForCJS) +{ + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); JSHandle module1 = objectFactory->NewSourceTextModule(); + CString baseFileName = "modules.abc"; module1->SetEcmaModuleFilenameString(baseFileName); + CString recordName1 = "a"; module1->SetEcmaModuleRecordNameString(recordName1); + JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + JSHandle importEntry = + objectFactory->NewImportEntry(val, val, val, SharedTypes::UNSENDABLE_MODULE); + SourceTextModule::AddImportEntry(thread, module1, importEntry, 0, 1); + + JSHandle module2 = objectFactory->NewSourceTextModule(); + module2->SetEcmaModuleFilenameString(baseFileName); + CString recordName2 = "cjs"; + module2->SetEcmaModuleRecordNameString(recordName2); JSHandle localExportEntry = objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); - module1->SetLocalExportEntries(thread, localExportEntries); - module1->SetTypes(ModuleTypes::NATIVE_MODULE); - module1->SetStatus(ModuleStatus::EVALUATED); - - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - moduleManager->AddResolveImportedModule(recordName.c_str(), module.GetTaggedValue()); - moduleManager->AddResolveImportedModule(recordName1.c_str(), module1.GetTaggedValue()); - CVector> stack; - SourceTextModule::ModuleDeclarationEnvironmentSetup(thread, module); - EXPECT_TRUE(!thread->HasPendingException()); - - module->SetEcmaModuleRecordNameString(""); - SourceTextModule::ModuleDeclarationEnvironmentSetup(thread, module); - EXPECT_TRUE(!thread->HasPendingException()); -} - -HWTEST_F_L0(EcmaModuleTest, ModuleDeclarationArrayEnvironmentSetup) -{ - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(thread, module); - EXPECT_TRUE(!thread->HasPendingException()); + module2->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module2, 0, val); + module2->SetTypes(ModuleTypes::CJS_MODULE); + module2->SetStatus(ModuleStatus::EVALUATED); + JSHandle moduleCjs = objectFactory->NewCjsModule(); + JSHandle recordName2Hdl = + JSHandle::Cast(objectFactory->NewFromUtf8(recordName2.c_str())); + JSHandle baseFileNameHdl = + JSHandle::Cast(objectFactory->NewFromUtf8(baseFileName.c_str())); + CjsModule::InitializeModule(thread, moduleCjs, recordName2Hdl, baseFileNameHdl); + CjsModule::PutIntoCache(thread, moduleCjs, recordName2Hdl); - module->SetSharedType(SharedTypes::SHARED_MODULE); - SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(thread, module); - EXPECT_TRUE(!thread->HasPendingException()); + JSHandle envRec = objectFactory->NewTaggedArray(1); + JSHandle resolution = + JSHandle::Cast(objectFactory->NewResolvedBindingRecord(module2, val)); + envRec->Set(thread, 0, resolution); + module1->SetEnvironment(thread, envRec); - module->SetStatus(ModuleStatus::EVALUATED); - SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(thread, module); - EXPECT_TRUE(!thread->HasPendingException()); + ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM()); + thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); - module->SetSharedType(SharedTypes::UNSENDABLE_MODULE); - SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(thread, module); - EXPECT_TRUE(!thread->HasPendingException()); -} + // test ResolvedBinding + JSTaggedValue res1 = ModuleTools::ProcessModuleNameSpaceLoadInfo(thread, module1, module2); + EXPECT_NE(res1, JSTaggedValue::Exception()); -HWTEST_F_L0(EcmaModuleTest, Evaluate) -{ - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - CString recordName = "a"; - module->SetEcmaModuleRecordNameString(recordName); - module->SetStatus(ModuleStatus::EVALUATED); - module->SetCycleRoot(thread, module); - SourceTextModule::Evaluate(thread, module, nullptr, 0, 0); - EXPECT_TRUE(!thread->HasPendingException()); - SourceTextModule::Evaluate(thread, module, nullptr, 0, 1); - EXPECT_TRUE(!thread->HasPendingException()); - ModuleLogger *moduleLogger = new ModuleLogger(vm); - thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); - SourceTextModule::Evaluate(thread, module, nullptr, 0, 0); - EXPECT_TRUE(!thread->HasPendingException()); - SourceTextModule::Evaluate(thread, module, nullptr, 0, 1); - EXPECT_TRUE(!thread->HasPendingException()); + JSTaggedValue res2 = ModuleTools::ProcessModuleLoadInfo(thread, module1, resolution.GetTaggedValue(), 0); + EXPECT_EQ(res2, JSTaggedValue::Exception()); thread->GetCurrentEcmaContext()->SetModuleLogger(nullptr); delete moduleLogger; } -HWTEST_F_L0(EcmaModuleTest, LoadNativeModule) +HWTEST_F_L0(EcmaModuleTest, ProcessModuleLoadInfoForNativeModule) { - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle module1 = objectFactory->NewSourceTextModule(); + CString baseFileName = "modules.abc"; + module1->SetEcmaModuleFilenameString(baseFileName); + CString recordName1 = "a"; + module1->SetEcmaModuleRecordNameString(recordName1); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle localExportEntry = - objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); - JSHandle localExportEntries = objectFactory->NewTaggedArray(1); - localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); - module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - JSHandle res = moduleManager->LoadNativeModule( - thread, "@app:bundleName/moduleName/lib*.so"); - EXPECT_EQ(res.GetTaggedValue(), JSTaggedValue::Undefined()); -} + JSHandle importEntry = + objectFactory->NewImportEntry(val, val, val, SharedTypes::UNSENDABLE_MODULE); + SourceTextModule::AddImportEntry(thread, module1, importEntry, 0, 1); -HWTEST_F_L0(EcmaModuleTest, ExecuteNativeModuleMayThrowError) -{ - auto vm = thread->GetEcmaVM(); - ObjectFactory *objectFactory = vm->GetFactory(); - CString recordName = "@app:bundleName/moduleName/lib*.so"; - JSHandle module = objectFactory->NewSourceTextModule(); - JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + JSHandle module2 = objectFactory->NewSourceTextModule(); + module2->SetEcmaModuleFilenameString(baseFileName); + CString recordName2 = "nativeModule"; + module2->SetEcmaModuleRecordNameString(recordName2); JSHandle localExportEntry = objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString(recordName); - module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - module->SetStatus(ModuleStatus::EVALUATED); - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - JSHandle res = moduleManager->ExecuteNativeModuleMayThrowError( - thread, recordName); - EXPECT_EQ(res.GetTaggedValue(), JSTaggedValue::Undefined()); + module2->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module2, 0, val); + module2->SetTypes(ModuleTypes::NATIVE_MODULE); + module2->SetStatus(ModuleStatus::EVALUATED); - thread->GetCurrentEcmaContext()->GetModuleManager()->AddResolveImportedModule( - recordName, module.GetTaggedValue()); - JSHandle res2 = moduleManager->ExecuteNativeModuleMayThrowError( - thread, recordName); - EXPECT_NE(res2.GetTaggedValue(), JSTaggedValue::Undefined()); + JSHandle envRec = objectFactory->NewTaggedArray(1); + JSHandle resolution = JSHandle::Cast( + objectFactory->NewResolvedBindingRecord(module2, val)); + envRec->Set(thread, 0, resolution); + module1->SetEnvironment(thread, envRec); + + ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM()); + thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); + + JSTaggedValue res1 = ModuleTools::ProcessModuleLoadInfo(thread, module1, resolution.GetTaggedValue(), 0); + EXPECT_EQ(res1, JSTaggedValue::Exception()); + + JSTaggedValue res2 = ModuleTools::ProcessModuleNameSpaceLoadInfo(thread, module1, module2); + EXPECT_NE(res2, JSTaggedValue::Exception()); + thread->GetCurrentEcmaContext()->SetModuleLogger(nullptr); + delete moduleLogger; } -HWTEST_F_L0(EcmaModuleTest, ExecuteNativeModule) +HWTEST_F_L0(EcmaModuleTest, ResolvedBindingForLog) { - auto vm = thread->GetEcmaVM(); - CString recordName = "@app:bundleName/moduleName/lib*.so"; - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); + ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle module1 = objectFactory->NewSourceTextModule(); + CString baseFileName = "modules.abc"; + module1->SetEcmaModuleFilenameString(baseFileName); + CString recordName1 = "a"; + module1->SetEcmaModuleRecordNameString(recordName1); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); + JSHandle importEntry = + objectFactory->NewImportEntry(val, val, val, SharedTypes::UNSENDABLE_MODULE); + SourceTextModule::AddImportEntry(thread, module1, importEntry, 0, 1); + + JSHandle module2 = objectFactory->NewSourceTextModule(); + module2->SetEcmaModuleFilenameString(baseFileName); + CString recordName2 = "b"; + module2->SetEcmaModuleRecordNameString(recordName2); JSHandle localExportEntry = objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString(recordName); - module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - + module2->SetLocalExportEntries(thread, localExportEntries); + SourceTextModule::StoreModuleValue(thread, module2, 0, val); + module2->SetStatus(ModuleStatus::EVALUATED); ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED); - thread->GetCurrentEcmaContext()->GetModuleManager()->AddResolveImportedModule( - recordName, module.GetTaggedValue()); - moduleManager->ExecuteNativeModule(thread, recordName); - module->SetStatus(ModuleStatus::EVALUATED); - JSHandle res = moduleManager->ExecuteNativeModule(thread, recordName); - EXPECT_NE(res.GetTaggedValue(), JSTaggedValue::Undefined()); + moduleManager->AddResolveImportedModule(recordName2, module2.GetTaggedValue()); + + ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM()); + thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); + // test ResolvedRecordIndexBinding + JSHandle recordNameHdl = objectFactory->NewFromUtf8(recordName2); + JSHandle baseFileNameHdl = objectFactory->NewFromUtf8(baseFileName); + JSHandle recordIndexBinding = + objectFactory->NewSResolvedRecordIndexBindingRecord(recordNameHdl, baseFileNameHdl, 0); + JSTaggedValue res1 = ModuleTools::ProcessModuleLoadInfo(thread, module1, recordIndexBinding.GetTaggedValue(), 0); + EXPECT_EQ(res1, val.GetTaggedValue()); + + // test ResolvedRecordBinding + JSHandle nameBinding = + objectFactory->NewSResolvedRecordBindingRecord(recordNameHdl, val); + JSTaggedValue res2 = ModuleTools::ProcessModuleLoadInfo(thread, module1, nameBinding.GetTaggedValue(), 0); + EXPECT_EQ(res2, JSTaggedValue::Exception()); + thread->GetCurrentEcmaContext()->SetModuleLogger(nullptr); + delete moduleLogger; } -HWTEST_F_L0(EcmaModuleTest, ExecuteNativeModule2) +HWTEST_F_L0(EcmaModuleTest, ToStringWithPrecision) { - auto vm = thread->GetEcmaVM(); - CString recordName = "@app:bundleName/moduleName/lib*.so"; - ObjectFactory *objectFactory = vm->GetFactory(); - JSHandle module = objectFactory->NewSourceTextModule(); - JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("val")); - JSHandle localExportEntry = - objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE); - JSHandle localExportEntries = objectFactory->NewTaggedArray(1); - localExportEntries->Set(thread, 0, localExportEntry); - module->SetEcmaModuleRecordNameString(recordName); - module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); - module->SetTypes(ModuleTypes::NATIVE_MODULE); - - ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); - JSHandle res = moduleManager->ExecuteNativeModule(thread, recordName); - EXPECT_NE(res.GetTaggedValue(), JSTaggedValue::Undefined()); + std::string res = ModuleLogger::ToStringWithPrecision(4.550, 3); + EXPECT_EQ(res, "4.55"); } HWTEST_F_L0(EcmaModuleTest, GetResolvedRecordIndexBindingModule) @@ -2997,7 +3055,6 @@ HWTEST_F_L0(EcmaModuleTest, GetLazyModuleValueFromRecordBindingTest) module1->SetEcmaModuleRecordNameString(recordName1); JSHandle val = JSHandle::Cast(objectFactory->NewFromUtf8("default")); - // test GetLazyModuleValueFromRecordBinding JSHandle recordNameHdl = objectFactory->NewFromUtf8(recordName1); JSHandle nameBinding = @@ -3136,7 +3193,7 @@ HWTEST_F_L0(EcmaModuleTest, GetLazyModuleValueFromRecordBinding) JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); module2->SetLocalExportEntries(thread, localExportEntries); - module2->StoreModuleValue(thread, 0, val); + SourceTextModule::StoreModuleValue(thread, module2, 0, val); module2->SetStatus(ModuleStatus::EVALUATED); module2->SetTypes(ModuleTypes::NATIVE_MODULE); ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); @@ -3333,7 +3390,7 @@ HWTEST_F_L0(EcmaModuleTest, StoreModuleValue4) localExportEntries->Set(thread, 0, localExportEntry); module->SetLocalExportEntries(thread, localExportEntries); module->SetSharedType(SharedTypes::SHARED_MODULE); - module->StoreModuleValue(thread, 0, val); + SourceTextModule::StoreModuleValue(thread, module, 0, val); EXPECT_TRUE(!thread->HasPendingException()); } @@ -3863,7 +3920,7 @@ HWTEST_F_L0(EcmaModuleTest, ResolveNativeStarExport2) JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); + SourceTextModule::StoreModuleValue(thread, module, 0, val); module->SetTypes(ModuleTypes::NATIVE_MODULE); int arkProperties = thread->GetEcmaVM()->GetJSOptions().GetArkProperties(); @@ -3883,7 +3940,7 @@ HWTEST_F_L0(EcmaModuleTest, LoadNativeModuleImpl2) JSHandle localExportEntries = objectFactory->NewTaggedArray(1); localExportEntries->Set(thread, 0, localExportEntry); module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); + SourceTextModule::StoreModuleValue(thread, module, 0, val); module->SetTypes(ModuleTypes::NATIVE_MODULE); ModuleLogger *moduleLogger = new ModuleLogger(vm); thread->GetCurrentEcmaContext()->SetModuleLogger(moduleLogger); @@ -3913,7 +3970,7 @@ HWTEST_F_L0(EcmaModuleTest, LoadNativeModule3) localExportEntries->Set(thread, 0, localExportEntry); module->SetEcmaModuleRecordNameString("@app:bundleName/moduleName/lib*.so"); module->SetLocalExportEntries(thread, localExportEntries); - module->StoreModuleValue(thread, 0, val); + SourceTextModule::StoreModuleValue(thread, module, 0, val); module->SetTypes(ModuleTypes::NATIVE_MODULE); Local requireNapi = StringRef::NewFromUtf8(vm, "requireNapi"); Local globalObject = JSNApi::GetGlobalObject(vm); @@ -4013,6 +4070,22 @@ HWTEST_F_L0(EcmaModuleTest, ValidateAbcPath) baseFileName = ""; res = ModulePathHelper::ValidateAbcPath(baseFileName, ValidateFilePath::ETS_MODULES); EXPECT_EQ(res, false); + + baseFileName = "/data/storage/el1/bundle1/com.bundleName.test"; + res = ModulePathHelper::ValidateAbcPath(baseFileName, ValidateFilePath::ETS_MODULES); + EXPECT_EQ(res, false); + + baseFileName = "/data/storage/el1/bundle/"; + res = ModulePathHelper::ValidateAbcPath(baseFileName, ValidateFilePath::ETS_MODULES); + EXPECT_EQ(res, false); + + baseFileName = "/data/storage/el1/bundle/com.bundleName.test/moduleName/moduleName/ets/modules.ab"; + res = ModulePathHelper::ValidateAbcPath(baseFileName, ValidateFilePath::ETS_MODULES); + EXPECT_EQ(res, false); + + baseFileName = "/data/storage/el1/bundle/com.bundleName.test/moduleName/moduleName/ets/modules.ab"; + res = ModulePathHelper::ValidateAbcPath(baseFileName, ValidateFilePath::ABC); + EXPECT_EQ(res, false); } @@ -4038,6 +4111,16 @@ HWTEST_F_L0(EcmaModuleTest, ParseCrossModuleFile) requestPath="moduleName/src"; ModulePathHelper::ParseCrossModuleFile(pf.get(), requestPath); EXPECT_EQ(requestPath, "moduleName/src"); + + requestPath="moduleName/src"; + pf->InsertNpmEntries("moduleName", "/src"); + ModulePathHelper::ParseCrossModuleFile(pf.get(), requestPath); + EXPECT_EQ(requestPath, "/src"); + + requestPath="moduleName/src/main/a/b/c"; + pf->InsertNpmEntries("moduleName", "/src/main/a/b/c"); + ModulePathHelper::ParseCrossModuleFile(pf.get(), requestPath); + EXPECT_EQ(requestPath, "/a/b/c"); } } // namespace panda::test diff --git a/ecmascript/napi/include/jsnapi_expo.h b/ecmascript/napi/include/jsnapi_expo.h index 72f345aac654d0c41f5c3ef1f69cb774e5cc6308..6650a417904cb9f52d29b23cbf5057c322305d83 100644 --- a/ecmascript/napi/include/jsnapi_expo.h +++ b/ecmascript/napi/include/jsnapi_expo.h @@ -602,6 +602,7 @@ public: bool IsTreeMap(const EcmaVM *vm); bool IsTreeSet(const EcmaVM *vm); bool IsVector(const EcmaVM *vm); + bool IsBitVector(const EcmaVM *vm); bool IsSendableObject(const EcmaVM *vm); bool IsJSShared(const EcmaVM *vm); bool IsSharedArray(const EcmaVM *vm); @@ -1753,8 +1754,6 @@ public: static bool IsMultiThreadCheckEnabled(const EcmaVM *vm); static uint32_t GetCurrentThreadId(); private: - static int vmCount_; - static bool initialize_; static bool isForked_; static bool CreateRuntime(const RuntimeOption &option); static bool DestroyRuntime(); diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index 362b98998755282b97686c8fad611cb2e7c5f15d..e535d21d44f4df29d0878710c3fa969e6310935c 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -460,6 +460,9 @@ JSTaggedValue Callback::RegisterCallback(ecmascript::EcmaRuntimeCallInfo *ecmaRu Local result; { ecmascript::ThreadNativeScope nativeScope(thread); +#if ECMASCRIPT_ENABLE_INTERPRETER_ARKUINAITVE_TRACE + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "ArkUI::NativeCallBack"); +#endif result = nativeFunc(jsiRuntimeCallInfo); } #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER) diff --git a/ecmascript/napi/jsnapi_expo.cpp b/ecmascript/napi/jsnapi_expo.cpp index a087581ec5c9d455a3e5b6825dce2a81c67b2ffb..e2d3555ad7cedc7d58a260ba9a3b87d124522dbf 100644 --- a/ecmascript/napi/jsnapi_expo.cpp +++ b/ecmascript/napi/jsnapi_expo.cpp @@ -20,7 +20,6 @@ #include "ecmascript/base/json_stringifier.h" #include "ecmascript/base/typed_array_helper-inl.h" #include "ecmascript/builtins/builtins_object.h" -#include "ecmascript/pgo_profiler/pgo_profiler_manager.h" #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER) #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h" #endif @@ -148,8 +147,6 @@ namespace { constexpr std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0"; } -int JSNApi::vmCount_ = 0; -bool JSNApi::initialize_ = false; bool JSNApi::isForked_ = false; static Mutex *mutex = new panda::Mutex(); StartIdleMonitorCallback JSNApi::startIdleMonitorCallback_ = nullptr; @@ -1006,6 +1003,12 @@ bool JSValueRef::IsVector(const EcmaVM *vm) return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIVector(); } +bool JSValueRef::IsBitVector(const EcmaVM *vm) +{ + ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); + return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIBitVector(); +} + bool JSValueRef::IsSendableObject(const EcmaVM *vm) { ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); @@ -2950,7 +2953,7 @@ void ObjectRef::SetNativePointerFieldCount(const EcmaVM *vm, int32_t count) // So we need do special value check before use it. DCHECK_SPECIAL_VALUE(this); JSHandle object(JSNApiHelper::ToJSHandle(this)); - object->SetNativePointerFieldCount(thread, count); + ECMAObject::SetNativePointerFieldCount(thread, object, count); } int32_t ObjectRef::GetNativePointerFieldCount(const EcmaVM *vm) @@ -2982,7 +2985,7 @@ void ObjectRef::SetNativePointerField(const EcmaVM *vm, int32_t index, void *nat // So we need do special value check before use it. DCHECK_SPECIAL_VALUE(this); JSHandle object(JSNApiHelper::ToJSHandle(this)); - object->SetNativePointerField(thread, index, nativePointer, callBack, data, nativeBindingsize); + ECMAObject::SetNativePointerField(thread, object, index, nativePointer, callBack, data, nativeBindingsize); } void ObjectRef::SetConcurrentNativePointerField(const EcmaVM *vm, int32_t index, void *nativePointer, @@ -2994,7 +2997,8 @@ void ObjectRef::SetConcurrentNativePointerField(const EcmaVM *vm, int32_t index, // So we need do special value check before use it. DCHECK_SPECIAL_VALUE(this); JSHandle object(JSNApiHelper::ToJSHandle(this)); - object->SetNativePointerField(thread, index, nativePointer, callBack, data, nativeBindingsize, Concurrent::YES); + ECMAObject::SetNativePointerField(thread, object, index, nativePointer, callBack, data, + nativeBindingsize, Concurrent::YES); } // -------------------------------- NativePointerRef ------------------------------------ @@ -3287,7 +3291,8 @@ Local FunctionRef::New(EcmaVM *vm, FunctionCallback nativeFunc, ObjectFactory *factory = vm->GetFactory(); JSHandle env = vm->GetGlobalEnv(); JSHandle current(factory->NewJSFunction(env, reinterpret_cast(Callback::RegisterCallback))); - current->SetFunctionExtraInfo(thread, reinterpret_cast(nativeFunc), deleter, data, nativeBindingsize); + JSFunction::SetFunctionExtraInfo(thread, current, reinterpret_cast(nativeFunc), + deleter, data, nativeBindingsize); current->SetCallNapi(callNapi); return JSNApiHelper::ToLocal(JSHandle(current)); } @@ -3300,8 +3305,8 @@ Local FunctionRef::NewConcurrent(EcmaVM *vm, FunctionCallback nativ ObjectFactory *factory = vm->GetFactory(); JSHandle env = vm->GetGlobalEnv(); JSHandle current(factory->NewJSFunction(env, reinterpret_cast(Callback::RegisterCallback))); - current->SetFunctionExtraInfo(thread, reinterpret_cast(nativeFunc), deleter, - data, nativeBindingsize, Concurrent::YES); + JSFunction::SetFunctionExtraInfo(thread, current, reinterpret_cast(nativeFunc), deleter, + data, nativeBindingsize, Concurrent::YES); current->SetCallNapi(callNapi); return JSNApiHelper::ToLocal(JSHandle(current)); } @@ -3314,7 +3319,7 @@ Local FunctionRef::New(EcmaVM *vm, InternalFunctionCallback nativeF ObjectFactory *factory = vm->GetFactory(); JSHandle env = vm->GetGlobalEnv(); JSHandle current(factory->NewJSFunction(env, reinterpret_cast(nativeFunc))); - current->SetFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingsize); + JSFunction::SetFunctionExtraInfo(thread, current, nullptr, deleter, data, nativeBindingsize); current->SetCallNapi(callNapi); return JSNApiHelper::ToLocal(JSHandle(current)); } @@ -3331,7 +3336,7 @@ Local FunctionRef::NewSendable(EcmaVM *vm, ObjectFactory *factory = vm->GetFactory(); JSHandle env = vm->GetGlobalEnv(); JSHandle current(factory->NewSFunction(env, reinterpret_cast(nativeFunc))); - current->SetSFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingsize); + JSFunction::SetSFunctionExtraInfo(thread, current, nullptr, deleter, data, nativeBindingsize); current->SetCallNapi(callNapi); return JSNApiHelper::ToLocal(JSHandle(current)); } @@ -3344,7 +3349,7 @@ Local FunctionRef::NewConcurrent(EcmaVM *vm, InternalFunctionCallba ObjectFactory *factory = vm->GetFactory(); JSHandle env = vm->GetGlobalEnv(); JSHandle current(factory->NewJSFunction(env, reinterpret_cast(nativeFunc))); - current->SetFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingsize, Concurrent::YES); + JSFunction::SetFunctionExtraInfo(thread, current, nullptr, deleter, data, nativeBindingsize, Concurrent::YES); current->SetCallNapi(callNapi); return JSNApiHelper::ToLocal(JSHandle(current)); } @@ -3383,7 +3388,8 @@ Local FunctionRef::NewClassFunction(EcmaVM *vm, FunctionCallback na factory->NewJSFunctionByHClass(reinterpret_cast(Callback::RegisterCallback), hclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR); InitClassFunction(vm, current, callNapi); - current->SetFunctionExtraInfo(thread, reinterpret_cast(nativeFunc), deleter, data, nativeBindingsize); + JSFunction::SetFunctionExtraInfo(thread, current, reinterpret_cast(nativeFunc), + deleter, data, nativeBindingsize); Local result = JSNApiHelper::ToLocal(JSHandle(current)); return scope.Escape(result); } @@ -3401,7 +3407,7 @@ Local FunctionRef::NewConcurrentClassFunction(EcmaVM *vm, InternalF factory->NewJSFunctionByHClass(reinterpret_cast(nativeFunc), hclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR); InitClassFunction(vm, current, callNapi); - current->SetFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingsize, Concurrent::YES); + JSFunction::SetFunctionExtraInfo(thread, current, nullptr, deleter, data, nativeBindingsize, Concurrent::YES); Local result = JSNApiHelper::ToLocal(JSHandle(current)); return scope.Escape(result); } @@ -3419,7 +3425,7 @@ Local FunctionRef::NewClassFunction(EcmaVM *vm, InternalFunctionCal factory->NewJSFunctionByHClass(reinterpret_cast(nativeFunc), hclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR); InitClassFunction(vm, current, callNapi); - current->SetFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingsize); + JSFunction::SetFunctionExtraInfo(thread, current, nullptr, deleter, data, nativeBindingsize); Local result = JSNApiHelper::ToLocal(JSHandle(current)); return scope.Escape(result); } @@ -3439,7 +3445,6 @@ Local FunctionRef::NewSendableClassFunction(const EcmaVM *vm, EscapeLocalScope scope(vm); ObjectFactory *factory = vm->GetFactory(); - bool hasParent = !parent->IsNull(); JSNapiSendable sendable(thread, infos, name); JSHandle prototypeHClass = JSHClass::CreateSPrototypeHClass(thread, sendable.GetNonStaticDescs()); JSHandle prototype = factory->NewSharedOldSpaceJSObject(prototypeHClass); @@ -3451,7 +3456,15 @@ Local FunctionRef::NewSendableClassFunction(const EcmaVM *vm, JSObject::SetSProperties(thread, prototype, sendable.GetNonStaticDescs()); JSObject::SetSProperties(thread, JSHandle::Cast(constructor), sendable.GetStaticDescs()); - if (hasParent) { + if (parent->IsHole()) { + JSHandle env = vm->GetGlobalEnv(); + prototypeHClass->SetPrototype(thread, env->GetSObjectFunctionPrototype()); + constructorHClass->SetPrototype(thread, env->GetSFunctionPrototype()); + } else if (parent->IsNull()) { + JSHandle env = vm->GetGlobalEnv(); + prototypeHClass->SetPrototype(thread, JSTaggedValue::Null()); + constructorHClass->SetPrototype(thread, env->GetSFunctionPrototype()); + } else { auto parentPrototype = parent->GetFunctionPrototype(vm); prototypeHClass->SetPrototype(thread, JSNApiHelper::ToJSHandle(parentPrototype)); constructorHClass->SetPrototype(thread, JSNApiHelper::ToJSHandle(parent)); @@ -3461,10 +3474,10 @@ Local FunctionRef::NewSendableClassFunction(const EcmaVM *vm, constructor->SetProtoOrHClass(thread, prototype); constructor->SetLexicalEnv(thread, constructor); constructor->SetCallNapi(callNapi); - constructor->SetSFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingSize); + JSFunction::SetSFunctionExtraInfo(thread, constructor, nullptr, deleter, data, nativeBindingSize); JSHClass *parentIHClass{nullptr}; - if (hasParent) { + if (!parent->IsHole() && !parent->IsNull()) { JSHandle parentHandle(JSNApiHelper::ToJSHandle(parent)); parentIHClass = reinterpret_cast(parentHandle->GetProtoOrHClass().GetTaggedObject()); } @@ -3673,9 +3686,9 @@ bool FunctionRef::Inherit(const EcmaVM *vm, Local parent) return false; } // Set this.Prototype.__proto__ to parent.Prototype - JSHandle parentProtoType(thread, JSFunction::PrototypeGetter(thread, parentHandle)); - JSHandle thisProtoType(thread, JSFunction::PrototypeGetter(thread, thisHandle)); - return JSObject::SetPrototype(thread, JSHandle::Cast(thisProtoType), parentProtoType); + JSHandle parentPrototype(thread, JSFunction::PrototypeGetter(thread, parentHandle)); + JSHandle thisPrototype(thread, JSFunction::PrototypeGetter(thread, thisHandle)); + return JSObject::SetPrototype(thread, JSHandle::Cast(thisPrototype), parentPrototype); } void FunctionRef::SetName(const EcmaVM *vm, Local name) @@ -3752,9 +3765,9 @@ void FunctionRef::SetData(const EcmaVM *vm, void *data, NativePointerCallback de JSHandle funcValue = JSNApiHelper::ToJSHandle(this); JSHandle function(funcValue); if (function->IsJSShared()) { - function->SetSFunctionExtraInfo(thread, nullptr, deleter, data, 0); + JSFunction::SetSFunctionExtraInfo(thread, function, nullptr, deleter, data, 0); } else { - function->SetFunctionExtraInfo(thread, nullptr, deleter, data, 0); + JSFunction::SetFunctionExtraInfo(thread, function, nullptr, deleter, data, 0); } } @@ -4178,6 +4191,7 @@ bool JSNApi::InitForConcurrentFunction(EcmaVM *vm, Local function, v LOG_ECMA(ERROR) << "Function is not concurrent"; return false; } + JSFunction::SetFunctionExtraInfo(thread, transFunc, nullptr, nullptr, taskInfo); transFunc->SetTaskConcurrentFuncFlag(1); // 1 : concurrent function flag thread->SetTaskInfo(reinterpret_cast(taskInfo)); thread->SetIsInConcurrentScope(true); @@ -5323,10 +5337,8 @@ void JSNApi::PostFork(EcmaVM *vm, const RuntimeOption &option) jsOption.SetEnableJIT(option.GetEnableJIT()); jsOption.SetEnableBaselineJIT(option.GetEnableBaselineJIT()); jsOption.SetMaxAotMethodSize(JSRuntimeOptions::MAX_APP_COMPILE_METHOD_SIZE); - jsOption.SetEnableForceIC(false); ecmascript::pgo::PGOProfilerManager::GetInstance()->SetBundleName(option.GetBundleName()); ecmascript::pgo::PGOProfilerManager::GetInstance()->SetMaxAotMethodSize(jsOption.GetMaxAotMethodSize()); - ecmascript::pgo::PGOProfilerManager::GetInstance()->SetEnableForceIC(jsOption.IsEnableForceIC()); JSRuntimeOptions runtimeOptions; runtimeOptions.SetLogLevel(Log::LevelToString(Log::ConvertFromRuntime(option.GetLogLevel()))); Log::Initialize(runtimeOptions); diff --git a/ecmascript/napi/test/BUILD.gn b/ecmascript/napi/test/BUILD.gn index 0714993bb0dae429c9cbc887bd82eb6ed7c30980..b38547466207814dbd5f45808ab089f24a1eab0c 100644 --- a/ecmascript/napi/test/BUILD.gn +++ b/ecmascript/napi/test/BUILD.gn @@ -40,7 +40,7 @@ foreach(file, test_js_files) { } } -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("Jsnapi_001_Test") { module_out_path = module_output_path diff --git a/ecmascript/napi/test/ffi_workload.cpp b/ecmascript/napi/test/ffi_workload.cpp index 7e291a092ba039397b9ed5e630275a12e3b53b50..380887119854feccf7f14eb636ceaaade63042f8 100644 --- a/ecmascript/napi/test/ffi_workload.cpp +++ b/ecmascript/napi/test/ffi_workload.cpp @@ -7985,7 +7985,7 @@ HWTEST_F_L0(JSNApiSplTest, FunctionRef_GetFunctionPrototype) Local setLocal = JSNApiHelper::ToLocal(set); gettimeofday(&g_beginTime, nullptr); for (int i = 0; i < NUM_COUNT; i++) { - [[maybe_unused]] Local funcProtoType = setLocal->GetFunctionPrototype(vm_); + [[maybe_unused]] Local funcPrototype = setLocal->GetFunctionPrototype(vm_); } gettimeofday(&g_endTime, nullptr); TEST_TIME(FunctionRef::GetFunctionPrototype); diff --git a/ecmascript/napi/test/jsnapi_first_tests.cpp b/ecmascript/napi/test/jsnapi_first_tests.cpp index 32b03415421f3e8b53afe860515c75055bd04db5..e6183887be56b391e6a4f9eadce3387aee726e9f 100644 --- a/ecmascript/napi/test/jsnapi_first_tests.cpp +++ b/ecmascript/napi/test/jsnapi_first_tests.cpp @@ -579,13 +579,13 @@ HWTEST_F_L0(JSNApiTests, DeleteProperty) /** * @tc.number: ffi_interface_api_011 - * @tc.name: GetProtoType + * @tc.name: GetPrototype * @tc.desc:Verify that the GetPrototype method correctly returns the prototype of the function or object, * and verify that the returned prototype is of an object type. * @tc.type: FUNC * @tc.require: parameter */ -HWTEST_F_L0(JSNApiTests, GetProtoType) +HWTEST_F_L0(JSNApiTests, GetPrototype) { LocalScope scope(vm_); Local function = FunctionRef::New(vm_, nullptr); diff --git a/ecmascript/napi/test/jsnapi_sendable_tests.cpp b/ecmascript/napi/test/jsnapi_sendable_tests.cpp index a0c84bdff661f765552a76580b0a53bad9880cc6..206d3000a2a5d2544811da27312e5dbb95ab0e59 100644 --- a/ecmascript/napi/test/jsnapi_sendable_tests.cpp +++ b/ecmascript/napi/test/jsnapi_sendable_tests.cpp @@ -16,6 +16,7 @@ #include "ecmascript/napi/jsnapi_helper.h" #include "ecmascript/tests/test_helper.h" #include "gtest/gtest.h" +#include "jsnapi_expo.h" using namespace panda::ecmascript; @@ -164,7 +165,7 @@ Local GetNewSendableClassFunction( HWTEST_F_L0(JSNApiTests, NewSendableClassFunction) { LocalScope scope(vm_); - Local constructor = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_)); + Local constructor = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_)); ASSERT_EQ("name", constructor->GetName(vm_)->ToString(vm_)); ASSERT_TRUE(constructor->IsFunction(vm_)); @@ -187,7 +188,7 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunction) HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionProperties) { LocalScope scope(vm_); - Local constructor = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_)); + Local constructor = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_)); Local prototype = constructor->GetFunctionPrototype(vm_); ASSERT_EQ("static", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString(vm_)); @@ -221,7 +222,7 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionProperties) HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictProperties) { LocalScope scope(vm_); - Local constructor = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_), true); + Local constructor = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_), true); Local prototype = constructor->GetFunctionPrototype(vm_); ASSERT_EQ("static", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString(vm_)); @@ -255,10 +256,9 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictProperties) HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInstance) { LocalScope scope(vm_); - Local constructor = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_)); - Local argv[1] = {NumberRef::New(vm_, 0)}; - Local obj = constructor->Constructor(vm_, argv, 0); - Local obj0 = constructor->Constructor(vm_, argv, 0); + Local constructor = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_)); + Local obj = constructor->Constructor(vm_, nullptr, 0); + Local obj0 = constructor->Constructor(vm_, nullptr, 0); ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor))); ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj0), JSNApiHelper::ToJSHandle(constructor))); @@ -298,10 +298,9 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInstance) HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictInstance) { LocalScope scope(vm_); - Local constructor = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_), true); - Local argv[1] = {NumberRef::New(vm_, 0)}; - Local obj = constructor->Constructor(vm_, argv, 0); - Local obj0 = constructor->Constructor(vm_, argv, 0); + Local constructor = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_), true); + Local obj = constructor->Constructor(vm_, nullptr, 0); + Local obj0 = constructor->Constructor(vm_, nullptr, 0); ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor))); ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj0), JSNApiHelper::ToJSHandle(constructor))); @@ -341,14 +340,12 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictInstance) HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInherit) { LocalScope scope(vm_); - Local parent = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_), false, false, true); + Local parent = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_), false, false, true); Local constructor = GetNewSendableClassFunction(vm_, parent); - Local argv[1] = {NumberRef::New(vm_, 0)}; - Local obj = constructor->Constructor(vm_, argv, 0); - Local obj0 = constructor->Constructor(vm_, argv, 0); + Local obj = constructor->Constructor(vm_, nullptr, 0); + ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor))); ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(parent))); - ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj0), JSNApiHelper::ToJSHandle(parent))); // set parent instance property on instance Local parentInstanceKey = StringRef::NewFromUtf8(vm_, "parentInstance"); @@ -368,14 +365,12 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInherit) HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictInherit) { LocalScope scope(vm_); - Local parent = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_), true, false, true); + Local parent = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_), true, false, true); Local constructor = GetNewSendableClassFunction(vm_, parent); - Local argv[1] = {NumberRef::New(vm_, 0)}; - Local obj = constructor->Constructor(vm_, argv, 0); - Local obj0 = constructor->Constructor(vm_, argv, 0); + Local obj = constructor->Constructor(vm_, nullptr, 0); + ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor))); ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(parent))); - ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj0), JSNApiHelper::ToJSHandle(parent))); // set parent instance property on instance Local parentInstanceKey = StringRef::NewFromUtf8(vm_, "parentInstance"); @@ -395,11 +390,11 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictInherit) HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInheritWithDuplicatedKey) { LocalScope scope(vm_); - Local parent = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_), false, false, true); + Local parent = GetNewSendableClassFunction(vm_, JSValueRef::Hole(vm_), false, false, true); Local constructor = GetNewSendableClassFunction(vm_, parent, false, true); - Local argv[1] = {NumberRef::New(vm_, 0)}; - Local obj = constructor->Constructor(vm_, argv, 0); + Local obj = constructor->Constructor(vm_, nullptr, 0); + ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor))); ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(parent))); // set duplicated instance property on instance @@ -443,7 +438,7 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionFunction) infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(func, true, true, true)); Local constructor = FunctionRef::NewSendableClassFunction( - vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"), infos, FunctionRef::Null(vm_)); + vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"), infos, JSValueRef::Hole(vm_)); Local staticValue = constructor->Get(vm_, staticKey); ASSERT_TRUE(staticValue->IsFunction(vm_)); @@ -486,7 +481,7 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionGetterSetter) infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(staticValue, true, true, true)); Local constructor = FunctionRef::NewSendableClassFunction( - vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"), infos, FunctionRef::Null(vm_)); + vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"), infos, JSValueRef::Hole(vm_)); ASSERT_EQ("getterSetter", constructor->Get(vm_, getterSetter)->ToString(vm_)->ToString(vm_)); ASSERT_EQ("getterSetter", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString(vm_)); @@ -495,6 +490,18 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionGetterSetter) ASSERT_EQ("getterSetter0", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString(vm_)); } +HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionStringify) +{ + LocalScope scope(vm_); + + FunctionRef::SendablePropertiesInfos infos; + Local constructor = FunctionRef::NewSendableClassFunction( + vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"), infos, JSValueRef::Hole(vm_)); + + Local obj = constructor->Constructor(vm_, nullptr, 0); + ASSERT_EQ("[object Object]", obj->ToString(vm_)->ToString(vm_)); +} + HWTEST_F_L0(JSNApiTests, NewObjectWithProperties) { LocalScope scope(vm_); diff --git a/ecmascript/napi/test/jsnapi_third_tests.cpp b/ecmascript/napi/test/jsnapi_third_tests.cpp index 735981acb561bc995447248b56e4784b239c86b7..e194085e8df7b24898c3b168312e73757ed73cda 100644 --- a/ecmascript/napi/test/jsnapi_third_tests.cpp +++ b/ecmascript/napi/test/jsnapi_third_tests.cpp @@ -1350,4 +1350,89 @@ HWTEST_F_L0(JSNApiTests, SetExecuteMode) ecmascript::ModuleExecuteMode res2 = moduleManager->GetExecuteMode(); EXPECT_EQ(res2, ecmascript::ModuleExecuteMode::ExecuteBufferMode); } + +HWTEST_F_L0(JSNApiTests, ToEcmaObject) +{ + LocalScope scope(vm_); + Local res = ObjectRef::New(vm_); + res->ToEcmaObject(vm_); + ASSERT_TRUE(res->IsObject(vm_)); +} + +HWTEST_F_L0(JSNApiTests, GetValueInt64) +{ + LocalScope scope(vm_); + bool isNumber = true; + int32_t input = 4; + Local res = IntegerRef::New(vm_, input); + res->ToBigInt(vm_); + ASSERT_TRUE(res->GetValueInt64(isNumber)); + res->ToNumber(vm_); + ASSERT_TRUE(res->GetValueInt64(isNumber)); + isNumber = false; + ASSERT_TRUE(res->GetValueInt64(isNumber)); +} + +HWTEST_F_L0(JSNApiTests, GetDataViewInfo) +{ + LocalScope scope(vm_); + Local key = StringRef::NewFromUtf8(vm_, "TestKey"); + bool isDataView = false; + key->GetDataViewInfo(vm_, isDataView, nullptr, nullptr, nullptr, nullptr); + ASSERT_FALSE(isDataView); + isDataView = true; + key->GetDataViewInfo(vm_, isDataView, nullptr, nullptr, nullptr, nullptr); + ASSERT_FALSE(isDataView); +} + +HWTEST_F_L0(JSNApiTests, TryGetArrayLength) +{ + LocalScope scope(vm_); + int32_t length = 4; + Local tag = ArrayRef::New(vm_, length); + EXPECT_FALSE(tag->IsArrayIterator(vm_)); + uint32_t arrayLength = 4; // define array length + bool isArrayOrSharedArray = true; + tag->TryGetArrayLength(vm_, &isArrayOrSharedArray, &arrayLength); + ASSERT_TRUE(isArrayOrSharedArray); +} + +HWTEST_F_L0(JSNApiTests, ByteLength002) +{ + LocalScope scope(vm_); + const int32_t length = 4; // define array length + Local array = ArrayBufferRef::New(vm_, length); + int32_t arrayLen = array->ByteLength(vm_); + EXPECT_EQ(length, arrayLen); +} + +HWTEST_F_L0(JSNApiTests, SetData) +{ + LocalScope scope(vm_); + Local functioncallback = FunctionRef::New(vm_, FunctionCallback); + struct Data { + int32_t length; + }; + const int32_t length = 15; + Data *data = new Data(); + data->length = length; + functioncallback->SetData(vm_, data); +} + +HWTEST_F_L0(JSNApiTests, GetData) +{ + LocalScope scope(vm_); + Local functioncallback = FunctionRef::New(vm_, FunctionCallback); + functioncallback->GetData(vm_); +} + +HWTEST_F_L0(JSNApiTests, GetData002) +{ + LocalScope scope(vm_); + int32_t argvLength = 10; + auto ecmaRuntimeCallInfo = + TestHelper::CreateEcmaRuntimeCallInfo(vm_->GetJSThread(), JSTaggedValue::Undefined(), argvLength); + JsiRuntimeCallInfo *jsiRuntimeCallInfo = reinterpret_cast(ecmaRuntimeCallInfo); + jsiRuntimeCallInfo->GetData(); +} } // namespace panda::test diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index 4ccaaf56243652937dc0cd781ffe7bf281bc240a..d862e7246b27e9aed36bb5e5947a3d0f3586cbfa 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -1534,6 +1534,7 @@ void ObjectFactory::InitializeJSObject(const JSHandle &obj, const JSHa break; } case JSType::JS_API_BITVECTOR: { + JSAPIBitVector::Cast(*obj)->SetNativePointer(thread_, JSTaggedValue::Undefined()); JSAPIBitVector::Cast(*obj)->SetLength(0); JSAPIBitVector::Cast(*obj)->SetModRecord(0); break; @@ -1666,7 +1667,7 @@ void ObjectFactory::InitializeJSObject(const JSHandle &obj, const JSHa CjsRequire::Cast(*obj)->SetParent(thread_, JSTaggedValue::Undefined()); break; default: - LOG_ECMA(FATAL) << "this branch is unreachable"; + LOG_ECMA(FATAL) << "this branch is unreachable, type: " << static_cast(type); UNREACHABLE(); } } @@ -1734,7 +1735,7 @@ void ObjectFactory::InitializeExtraProperties(const JSHandle &hclass, auto paddr = reinterpret_cast(obj) + hclass->GetObjectSize(); // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist, // to follow ECMA spec. - JSTaggedType initVal = hclass->IsTS() ? JSTaggedValue::VALUE_HOLE : JSTaggedValue::VALUE_UNDEFINED; + JSTaggedType initVal = hclass->IsAOT() ? JSTaggedValue::VALUE_HOLE : JSTaggedValue::VALUE_UNDEFINED; for (uint32_t i = 0; i < inobjPropCount; ++i) { paddr -= JSTaggedValue::TaggedTypeSize(); *reinterpret_cast(paddr) = initVal; @@ -1942,6 +1943,12 @@ JSHandle ObjectFactory::CreateDefaultClassConstructorHClass(JSHClass * return defaultHclass; } +void ObjectFactory::SetCodeEntryToFunctionFromMethod(const JSHandle &func, const JSHandle &mothed) +{ + uintptr_t entry = mothed->GetCodeEntryOrLiteral(); + func->SetCodeEntry(entry); +} + JSHandle ObjectFactory::NewJSFunctionByHClass(const JSHandle &method, const JSHandle &clazz, MemSpaceType type) @@ -1969,6 +1976,8 @@ JSHandle ObjectFactory::NewJSFunctionByHClass(const JSHandle if (method->IsAotWithCallField()) { thread_->GetEcmaVM()->GetAOTFileManager()-> SetAOTFuncEntry(method->GetJSPandaFile(), *function, *method); + } else { + SetCodeEntryToFunctionFromMethod(function, method); } return function; } @@ -2271,7 +2280,8 @@ JSHandle ObjectFactory::NewJSPrimitiveRef(PrimitiveType type, co function = env->GetBigIntFunction(); break; default: - break; + LOG_ECMA(FATAL) << "this branch is unreachable, type: " << static_cast(type); + UNREACHABLE(); } JSHandle funcHandle(function); return factory->NewJSPrimitiveRef(funcHandle, object); @@ -3802,9 +3812,8 @@ EcmaString *ObjectFactory::InternString(const JSHandle &key) JSHandle ObjectFactory::NewTransitionHandler() { NewObjectHook(); - TransitionHandler *handler = - TransitionHandler::Cast(heap_->AllocateYoungOrHugeObject( - JSHClass::Cast(thread_->GlobalConstants()->GetTransitionHandlerClass().GetTaggedObject()))); + TransitionHandler *handler = TransitionHandler::Cast(heap_->AllocateYoungOrHugeObject( + JSHClass::Cast(thread_->GlobalConstants()->GetTransitionHandlerClass().GetTaggedObject()))); handler->SetHandlerInfo(thread_, JSTaggedValue::Undefined()); handler->SetTransitionHClass(thread_, JSTaggedValue::Undefined()); return JSHandle(thread_, handler); @@ -3838,13 +3847,13 @@ JSHandle ObjectFactory::NewTransWithProtoHandler() return handler; } -JSHandle ObjectFactory::NewStoreTSHandler() +JSHandle ObjectFactory::NewStoreAOTHandler() { NewObjectHook(); - StoreTSHandler *header = - StoreTSHandler::Cast(heap_->AllocateYoungOrHugeObject( - JSHClass::Cast(thread_->GlobalConstants()->GetStoreTSHandlerClass().GetTaggedObject()))); - JSHandle handler(thread_, header); + StoreAOTHandler *header = + StoreAOTHandler::Cast(heap_->AllocateYoungOrHugeObject( + JSHClass::Cast(thread_->GlobalConstants()->GetStoreAOTHandlerClass().GetTaggedObject()))); + JSHandle handler(thread_, header); handler->SetHandlerInfo(thread_, JSTaggedValue::Undefined()); handler->SetProtoCell(thread_, JSTaggedValue::Undefined()); handler->SetHolder(thread_, JSTaggedValue::Undefined()); @@ -4531,7 +4540,7 @@ JSHandle ObjectFactory::NewJSAPIVectorIterator(const JSHand JSHandle ObjectFactory::NewJSAPIBitVector(uint32_t capacity) { NewObjectHook(); - JSHandle builtinObj(thread_, thread_->GlobalConstants()->GetBitVectorFunction()); + JSHandle builtinObj(thread_->GetEcmaVM()->GetGlobalEnv()->GetBitVectorFunction()); JSHandle obj = JSHandle(NewJSObjectByConstructor(builtinObj)); uint32_t taggedArrayCapacity = (capacity >> JSAPIBitVector::TAGGED_VALUE_BIT_SIZE) + 1; auto *newBitSetVector = new std::vector>(); @@ -4546,7 +4555,8 @@ JSHandle ObjectFactory::NewJSAPIBitVectorIterator(const { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); - JSHandle proto(thread_, globalConst->GetBitVectorIteratorPrototype()); + JSHandle env = thread_->GetEcmaVM()->GetGlobalEnv(); + JSHandle proto(env->GetBitVectorIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPIBitVectorIteratorClass()); hclassHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(hclassHandle)); diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index cc196ba75323b92f4f464f1a1a7e4405cc88bc1a..22069cf6cf76a9ddd12f59c52af19d616f9c1a04 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -168,7 +168,7 @@ class PendingJob; class TransitionHandler; class PrototypeHandler; class TransWithProtoHandler; -class StoreTSHandler; +class StoreAOTHandler; class PropertyBox; class ProtoChangeMarker; class ProtoChangeDetails; @@ -225,7 +225,7 @@ public: JSHandle NewTransWithProtoHandler(); - JSHandle NewStoreTSHandler(); + JSHandle NewStoreAOTHandler(); JSHandle NewEmptyJSObject(uint32_t inlinedProps = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); @@ -892,6 +892,8 @@ public: JSHandle NewSendableEnv(int numSlots); JSHandle NewJSSendableFunction(const JSHandle &methodHandle); + void SetCodeEntryToFunctionFromMethod(const JSHandle &func, const JSHandle &mothed); + private: friend class GlobalEnv; friend class GlobalEnvConstants; diff --git a/ecmascript/object_fast_operator-inl.h b/ecmascript/object_fast_operator-inl.h index 6100ff7ac78cc84518dde699372ea1119d611abf..ab0b320245c7bd6537446a379fb48d7aedc314d9 100644 --- a/ecmascript/object_fast_operator-inl.h +++ b/ecmascript/object_fast_operator-inl.h @@ -59,7 +59,7 @@ namespace panda::ecmascript { std::pair ObjectFastOperator::HasOwnProperty(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key) { - [[maybe_unused]] DisallowGarbageCollection noGc; + DISALLOW_GARBAGE_COLLECTION; if (!receiver.IsHeapObject() || !(receiver.IsRegularObject())) { return std::make_pair(JSTaggedValue::Hole(), false); } @@ -372,7 +372,7 @@ JSTaggedValue ObjectFastOperator::TrySetPropertyByNameThroughCacheAtLocal(JSThre THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(SetReadOnlyProperty), JSTaggedValue::Exception()); } - if (hclass->IsTS()) { + if (hclass->IsAOT()) { auto attrVal = JSObject::Cast(receiver)->GetProperty(hclass, attr); if (attrVal.IsHole()) { return JSTaggedValue::Hole(); @@ -455,7 +455,7 @@ JSTaggedValue ObjectFastOperator::SetPropertyByName(JSThread *thread, JSTaggedVa THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(SetReadOnlyProperty), JSTaggedValue::Exception()); } - if (hclass->IsTS()) { + if (hclass->IsAOT()) { auto attrVal = JSObject::Cast(holder)->GetProperty(hclass, attr); if (attrVal.IsHole()) { if (receiverHoleEntry == -1 && holder == receiver) { @@ -821,10 +821,11 @@ JSTaggedValue ObjectFastOperator::FastGetPropertyByValue(JSThread *thread, JSTag SCheckMode sCheckMode) { INTERPRETER_TRACE(thread, FastGetPropertyByValue); + JSHandle receiverHandler(thread, receiver); + JSHandle keyHandler(thread, key); JSTaggedValue result = ObjectFastOperator::GetPropertyByValue(thread, receiver, key); if (result.IsHole()) { - return JSTaggedValue::GetProperty(thread, JSHandle(thread, receiver), - JSHandle(thread, key), sCheckMode).GetValue().GetTaggedValue(); + return JSTaggedValue::GetProperty(thread, receiverHandler, keyHandler, sCheckMode).GetValue().GetTaggedValue(); } return result; } diff --git a/ecmascript/object_operator.cpp b/ecmascript/object_operator.cpp index 0addc5934628b0689c77943e33af4fae5ba91840..8de99552ad27954f2fa2622998ef17ca551a217d 100644 --- a/ecmascript/object_operator.cpp +++ b/ecmascript/object_operator.cpp @@ -94,18 +94,6 @@ void ObjectOperator::UpdateHolder() } } -void ObjectOperator::UpdateIsTSHClass() -{ - if (!holder_->IsECMAObject()) { - SetIsTSHClass(false); - return; - } - auto hclass = JSHandle::Cast(holder_)->GetClass(); - if (hclass->IsTS()) { - SetIsTSHClass(true); - } -} - void ObjectOperator::StartLookUp(OperatorType type) { UpdateHolder(); @@ -424,7 +412,6 @@ SharedFieldType ObjectOperator::GetSharedFieldType() const void ObjectOperator::ToPropertyDescriptor(PropertyDescriptor &desc) const { - DISALLOW_GARBAGE_COLLECTION; if (!IsFound()) { return; } @@ -487,7 +474,6 @@ void ObjectOperator::LookupProperty() if (holder_->IsJSProxy()) { return; } - UpdateIsTSHClass(); LookupPropertyInHolder(); if (IsFound()) { return; @@ -966,7 +952,6 @@ void ObjectOperator::ResetState() SetAttr(0); SetIsOnPrototype(false); SetHasReceiver(false); - SetIsTSHClass(false); } void ObjectOperator::ResetStateForAddProperty() @@ -1076,7 +1061,6 @@ void ObjectOperator::AddPropertyInternal(const JSHandle &value) } uint32_t index = attr.IsInlinedProps() ? attr.GetOffset() : attr.GetOffset() - obj->GetJSHClass()->GetInlinedProperties(); - SetIsTSHClass(true); SetIsOnPrototype(false); SetFound(index, value.GetTaggedValue(), attr.GetValue(), true); return; diff --git a/ecmascript/object_operator.h b/ecmascript/object_operator.h index 38f507f1e956252f1581f4b4043875bd6036c804..baf73ee0e9b8370b3d4e4c51f1863d55940025f0 100644 --- a/ecmascript/object_operator.h +++ b/ecmascript/object_operator.h @@ -99,7 +99,7 @@ public: IsFoundDictField::Set(flag, &metaData_); } - inline bool IsFoundDict() + inline bool IsFoundDict() const { return IsFoundDictField::Get(metaData_); } @@ -157,16 +157,6 @@ public: IsTransitionField::Set(flag, &metaData_); } - inline bool IsTSHClass() const - { - return IsTSHClassField::Get(metaData_); - } - - inline void SetIsTSHClass(bool flag) - { - IsTSHClassField::Set(flag, &metaData_); - } - inline PropertyAttributes GetAttr() const { return attributes_; @@ -332,19 +322,14 @@ public: void DefineGetter(const JSHandle &value); private: - static constexpr uint64_t ATTR_LENGTH = 5; - static constexpr uint64_t INDEX_LENGTH = 32; - using IsFastModeField = BitField; using IsOnPrototypeField = IsFastModeField::NextFlag; // 1: on prototype using HasReceiverField = IsOnPrototypeField::NextFlag; using IsTransitionField = HasReceiverField::NextFlag; - using IsTSHClassField = IsTransitionField::NextFlag; // found dictionary obj between receriver and holder - using IsFoundDictField = IsTSHClassField::NextFlag; + using IsFoundDictField = IsTransitionField::NextFlag; void UpdateHolder(); - void UpdateIsTSHClass(); void StartLookUp(OperatorType type); void StartGlobalLookUp(OperatorType type); void HandleKey(const JSHandle &key); diff --git a/ecmascript/ohos/app_aot_jit_enable_list.conf b/ecmascript/ohos/app_aot_jit_enable_list.conf index 854856ba1284d19b3ab9ba448890e2d1d61675b3..36cda220f1ec3ed52ca4a09e856112fa6ff71414 100644 --- a/ecmascript/ohos/app_aot_jit_enable_list.conf +++ b/ecmascript/ohos/app_aot_jit_enable_list.conf @@ -1,16 +1,4 @@ # Apps in this configuration file can be compiled by aot or jit compiler, enable list can be written as below, first is enable aot, second is enable jit, third is enable both aot and jit: # {bundleName}:aot # {bundleName}:jit -# {bundleName} -cn.cnr.cnrnetohos:aot -com.huawei.hmos.soundrecorder:aot -com.huawei.hmos.finddevice:aot -com.huawei.hmos.photos:aot -yylx.danmaku.bili -com.cmbchina.harmony -com.bankcomm.app.maidanba -com.gotokeep.hm.keep -com.qunar.hos -com.ss.dcar.auto -io.gitee.marchosius.hmapp -com.xiaotian.voyagerevealed \ No newline at end of file +# {bundleName} \ No newline at end of file diff --git a/ecmascript/ohos/jit_tools.h b/ecmascript/ohos/jit_tools.h index 29e182282aafc2a52c766c892112cc2b9f03ea7b..240830b161fd39776473648e2b2f2f063dbfe489 100644 --- a/ecmascript/ohos/jit_tools.h +++ b/ecmascript/ohos/jit_tools.h @@ -94,6 +94,14 @@ public: return value; } + static bool IsSupportJitCodeSigner() + { + #ifdef JIT_ENABLE_CODE_SIGN + return OHOS::Security::CodeSign::IsSupportJitCodeSigner(); + #endif + return false; + } + static bool GetEnableJitFort(bool value) { #ifdef GET_PARAMETER_FOR_JIT diff --git a/ecmascript/ohos/ohos_pkg_verifier.h b/ecmascript/ohos/ohos_pkg_verifier.h index 402465ae7454cfd37c39c082c0f3843f0f18e927..04e77b3c69a6c18f75063a2fef477cf85a9279ed 100644 --- a/ecmascript/ohos/ohos_pkg_verifier.h +++ b/ecmascript/ohos/ohos_pkg_verifier.h @@ -88,9 +88,15 @@ public: return false; } for (const auto& pkg : cPreprocessor.GetPkgsArgs()) { - fd_t fd = open(pkg.second->GetPath().c_str(), FILE_RDONLY); + std::string realPath; + if (!RealPath(pkg.second->GetPath().c_str(), realPath, true)) { + LOG_ECMA(ERROR) << "Fail to get realPath: " << pkg.second->GetPath().c_str(); + dlclose(handle); + return false; + } + fd_t fd = open(realPath.c_str(), FILE_RDONLY); if (fd == INVALID_FD) { - LOG_ECMA(ERROR) << pkg.second->GetPath().c_str() << " file open failed"; + LOG_ECMA(ERROR) << realPath.c_str() << " file open failed"; dlclose(handle); return false; } diff --git a/ecmascript/ohos/tests/BUILD.gn b/ecmascript/ohos/tests/BUILD.gn index f00abe5ce119a34ac15c13173f0f5696b4d5b4a6..41e781240c98d7f7ffbc2b158c7d3ed2d241dcc4 100644 --- a/ecmascript/ohos/tests/BUILD.gn +++ b/ecmascript/ohos/tests/BUILD.gn @@ -14,7 +14,7 @@ import("../../../js_runtime_config.gni") import("../../../test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("OhosTest") { module_out_path = module_output_path diff --git a/ecmascript/on_heap.h b/ecmascript/on_heap.h index d10df457ccfa604a96c6de5a8a1e2581b447dceb..6e92eea2a39b533fa806022b68a0c2ac8c74c224 100644 --- a/ecmascript/on_heap.h +++ b/ecmascript/on_heap.h @@ -32,6 +32,16 @@ public: return !(mode == OnHeapMode::ON_HEAP || mode == OnHeapMode::NOT_ON_HEAP); } + static bool IsOnHeap(OnHeapMode mode) + { + return mode == OnHeapMode::ON_HEAP; + } + + static bool IsNotOnHeap(OnHeapMode mode) + { + return mode == OnHeapMode::NOT_ON_HEAP; + } + static OnHeapMode Merge(OnHeapMode first, OnHeapMode second) { if (IsNone(first) || IsNone(second) || (first != second)) { diff --git a/ecmascript/patch/patch_loader.cpp b/ecmascript/patch/patch_loader.cpp index b1a458bc13dfca3513c275346dbfdb517fed3010..79700d00060a0acd585f0b6feca1222377798e57 100644 --- a/ecmascript/patch/patch_loader.cpp +++ b/ecmascript/patch/patch_loader.cpp @@ -22,24 +22,23 @@ PatchErrorCode PatchLoader::LoadPatchInternal(JSThread *thread, const JSPandaFil const JSPandaFile *patchFile, PatchInfo &patchInfo, const CMap &baseClassInfo) { - DISALLOW_GARBAGE_COLLECTION; EcmaVM *vm = thread->GetEcmaVM(); - - // hot reload and hot patch only support merge-abc file. - if (baseFile->IsBundlePack() || patchFile->IsBundlePack()) { - LOG_ECMA(ERROR) << "base or patch is not merge abc!"; - return PatchErrorCode::PACKAGE_NOT_ESMODULE; - } - - // Generate patchInfo for hot reload, hot patch and cold patch. - patchInfo = PatchLoader::GeneratePatchInfo(patchFile); - - if (!thread->GetCurrentEcmaContext()->HasCachedConstpool(baseFile)) { - LOG_ECMA(INFO) << "cold patch!"; - vm->GetJsDebuggerManager()->GetHotReloadManager()->NotifyPatchLoaded(baseFile, patchFile); - return PatchErrorCode::SUCCESS; + { + DISALLOW_GARBAGE_COLLECTION; + // hot reload and hot patch only support merge-abc file. + if (baseFile->IsBundlePack() || patchFile->IsBundlePack()) { + LOG_ECMA(ERROR) << "base or patch is not merge abc!"; + return PatchErrorCode::PACKAGE_NOT_ESMODULE; + } + // Generate patchInfo for hot reload, hot patch and cold patch. + patchInfo = PatchLoader::GeneratePatchInfo(patchFile); + if (!thread->GetCurrentEcmaContext()->HasCachedConstpool(baseFile)) { + LOG_ECMA(INFO) << "cold patch!"; + vm->GetJsDebuggerManager()->GetHotReloadManager()->NotifyPatchLoaded(baseFile, patchFile); + return PatchErrorCode::SUCCESS; + } } - + [[maybe_unused]] EcmaHandleScope handleScope(thread); // store base constpool in global object for avoid gc. diff --git a/ecmascript/patch/quick_fix_manager.cpp b/ecmascript/patch/quick_fix_manager.cpp index 4f136ebfe3783602a50d653f9d791d550f47d818..e6febcfe7c75b983acd5563b0eba801a3517e0b5 100644 --- a/ecmascript/patch/quick_fix_manager.cpp +++ b/ecmascript/patch/quick_fix_manager.cpp @@ -250,7 +250,7 @@ bool QuickFixManager::IsQuickFixCausedException(JSThread *thread, CUnorderedSet methodNames = ParseStackInfo(stackInfo); // check whether the methodNames contains a patch method name. - CUnorderedMap patchMethodLiterals = patchFile->GetMethodLiteralMap(); + std::unordered_map patchMethodLiterals = patchFile->GetMethodLiteralMap(); for (const auto &item : patchMethodLiterals) { MethodLiteral *patch = item.second; auto methodId = patch->GetMethodId(); diff --git a/ecmascript/pgo_profiler/ap_file/pgo_file_info.cpp b/ecmascript/pgo_profiler/ap_file/pgo_file_info.cpp index 5ff1f922365067c365a91c3e7d50ca4ca609e8a8..8b81ba798314ac2e28d32aed48b7a8ec9ed7f244 100644 --- a/ecmascript/pgo_profiler/ap_file/pgo_file_info.cpp +++ b/ecmascript/pgo_profiler/ap_file/pgo_file_info.cpp @@ -33,11 +33,13 @@ bool PGOProfilerHeader::BuildFromLegacy(void *buffer, PGOProfilerHeader **header Build(header, desSize); // copy header base. if (memcpy_s(*header, sizeof(FileHeaderBase), inHeader, sizeof(FileHeaderBase)) != EOK) { + LOG_ECMA(FATAL) << "PGOProfilerHeader BuildFromLegacy copy header base memcpy failed!"; UNREACHABLE(); } // skip elastic header field, and copy section info from incoming buffer. auto sectionSize = desSize - sizeof(FileHeaderElastic); if (memcpy_s(&((*header)->sectionNumber_), sectionSize, &(inHeader->GetSectionNumber()), sectionSize) != EOK) { + LOG_ECMA(FATAL) << "PGOProfilerHeader BuildFromLegacy copy section info memcpy failed!"; UNREACHABLE(); } return true; @@ -56,6 +58,7 @@ bool PGOProfilerHeader::BuildFromElastic(void *buffer, size_t bufferSize, PGOPro } Build(header, desSize); if (memcpy_s(*header, desSize, inHeader, desSize) != EOK) { + LOG_ECMA(FATAL) << "PGOProfilerHeader BuildFromElastic memcpy failed!"; UNREACHABLE(); } return true; diff --git a/ecmascript/pgo_profiler/pgo_profiler.cpp b/ecmascript/pgo_profiler/pgo_profiler.cpp index 4ee14acb1c8b8fb4733dca948646903409523238..19975b144ec8cff5dec047c075dee6d635879222 100644 --- a/ecmascript/pgo_profiler/pgo_profiler.cpp +++ b/ecmascript/pgo_profiler/pgo_profiler.cpp @@ -414,7 +414,7 @@ void PGOProfiler::DispatchPGODumpTask() std::make_unique(this, vm_->GetJSThread()->GetThreadId())); } -PGOProfiler::State PGOProfiler::GetState() +PGOProfiler::State PGOProfiler::GetState() const { return state_.load(std::memory_order_acquire); } @@ -448,7 +448,7 @@ void PGOProfiler::WaitPGODumpFinish() return; } LockHolder lock(mutex_); - while (GetState() == State::START) { + while (GetState() == State::START || GetState() == State::MERGE) { WaitingPGODump(); } } @@ -690,6 +690,7 @@ void PGOProfiler::MergeProfilerAndDispatchAsyncSaveTask(bool force) LOG_ECMA(DEBUG) << "Sample: post task to save profiler"; { ClockScope start; + SetState(State::MERGE); PGOProfilerManager::GetInstance()->Merge(this); if (PGOTrace::GetInstance()->IsEnable()) { PGOTrace::GetInstance()->SetMergeTime(start.TotalSpentTime()); @@ -1105,13 +1106,13 @@ bool PGOProfiler::DumpICByNameWithHandler(ApEntityId abcId, const CString &recor auto accessorMethodId = prototypeHandler->GetAccessorMethodId(); return AddObjectInfo( abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId); - } else if (secondValue.IsStoreTSHandler()) { - StoreTSHandler *storeTSHandler = StoreTSHandler::Cast(secondValue.GetTaggedObject()); - auto cellValue = storeTSHandler->GetProtoCell(); + } else if (secondValue.IsStoreAOTHandler()) { + StoreAOTHandler *storeAOTHandler = StoreAOTHandler::Cast(secondValue.GetTaggedObject()); + auto cellValue = storeAOTHandler->GetProtoCell(); if (CheckProtoChangeMarker(cellValue)) { return false; } - auto holder = storeTSHandler->GetHolder(); + auto holder = storeAOTHandler->GetHolder(); auto holderHClass = holder.GetTaggedObject()->GetClass(); return AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass); } @@ -1267,8 +1268,8 @@ void PGOProfiler::TryDumpProtoTransitionType(JSHClass *hclass) return; } JSTaggedValue phc1Root = JSHClass::FindProtoRootHClass(ihc1); - auto transitionProtoType = GetProfileType(JSHClass::Cast(phc1Root.GetTaggedObject()), true); - if (!transitionProtoType.IsRootType()) { + auto transitionPrototype = GetProfileType(JSHClass::Cast(phc1Root.GetTaggedObject()), true); + if (!transitionPrototype.IsRootType()) { LOG_ECMA(DEBUG) << "Set as the prototype of a function again after transition happened for this prototype!"; return; } @@ -1300,7 +1301,7 @@ void PGOProfiler::TryDumpProtoTransitionType(JSHClass *hclass) PGOProtoTransitionType protoTransitionType(ihc0RootType); protoTransitionType.SetBaseType(baseRootType, baseType); protoTransitionType.SetTransitionType(transitionType); - protoTransitionType.SetTransitionProtoPt(transitionProtoType); + protoTransitionType.SetTransitionProtoPt(transitionPrototype); recordInfos_->GetProtoTransitionPool()->Add(protoTransitionType); } @@ -1375,7 +1376,7 @@ void PGOProfiler::DumpDefineClass(ApEntityId abcId, const CString &recordName, E if (!prototypeType.IsRootType()) { LOG_ECMA(DEBUG) << "The profileType of prototype root hclass was not found."; } else { - objDefType.SetProtoTypePt(prototypeType); + objDefType.SetPrototypePt(prototypeType); recordInfos_->AddRootLayout(JSTaggedType(prototypeRootHClass), prototypeType); } } diff --git a/ecmascript/pgo_profiler/pgo_profiler.h b/ecmascript/pgo_profiler/pgo_profiler.h index 438a4c6aa25fca6b80cc82ce9d602c6459c18997..851ffb5a3f099c5ecbbb5771f5ff57def3f0150c 100644 --- a/ecmascript/pgo_profiler/pgo_profiler.h +++ b/ecmascript/pgo_profiler/pgo_profiler.h @@ -121,21 +121,21 @@ private: LOAD, }; - void ProfileBytecode(ApEntityId abcId, const CString& recordName, JSTaggedValue funcValue); - enum class State : uint8_t { + MERGE, STOP, PAUSE, START, FORCE_SAVE, FORCE_SAVE_PAUSE, }; - static std::string StateToString(State state) { switch (state) { case State::STOP: return "STOP"; + case State::MERGE: + return "MERGE"; case State::PAUSE: return "PAUSE"; case State::START: @@ -148,8 +148,7 @@ private: return "UNKNOWN"; } } - - State GetState(); + State GetState() const; void SetState(State state); void NotifyGC(std::string tag = ""); void NotifyAll(std::string tag = ""); @@ -160,6 +159,7 @@ private: bool IsGCWaiting(); void DispatchPGODumpTask(); + void ProfileBytecode(ApEntityId abcId, const CString& recordName, JSTaggedValue funcValue); void DumpICByName(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId, ProfileTypeInfo *profileTypeInfo, BCType type); void DumpICByValue(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, diff --git a/ecmascript/pgo_profiler/pgo_profiler_info.cpp b/ecmascript/pgo_profiler/pgo_profiler_info.cpp index 837248274143b0fb3d0c1e3db4bad1cd6d6f1c53..1fc23b43f9e74407d89fe465795234f4e65569bc 100644 --- a/ecmascript/pgo_profiler/pgo_profiler_info.cpp +++ b/ecmascript/pgo_profiler/pgo_profiler_info.cpp @@ -623,10 +623,10 @@ bool PGORecordDetailInfos::AddDefine( PGOHClassTreeDesc descInfo(type.GetProfileType()); auto iter = hclassTreeDescInfos_.find(descInfo); if (iter == hclassTreeDescInfos_.end()) { - descInfo.SetProtoPt(type.GetProtoTypePt()); + descInfo.SetProtoPt(type.GetPrototypePt()); hclassTreeDescInfos_.emplace(descInfo); } else { - const_cast(*iter).SetProtoPt(type.GetProtoTypePt()); + const_cast(*iter).SetProtoPt(type.GetPrototypePt()); } return true; } @@ -702,10 +702,10 @@ bool PGORecordDetailInfos::IsDumped(ProfileType rootType, ProfileType curType) c void PGORecordDetailInfos::Merge(const PGORecordDetailInfos &recordInfos) { - CMap methodInfos = recordInfos.recordInfos_; - for (auto iter = methodInfos.begin(); iter != methodInfos.end(); iter++) { - auto recordType = iter->first; - auto fromMethodInfos = iter->second; + const auto& methodInfos = recordInfos.recordInfos_; + for (auto& iter: methodInfos) { + auto recordType = iter.first; + auto fromMethodInfos = iter.second; auto recordInfosIter = recordInfos_.find(recordType); PGOMethodInfoMap *toMethodInfos = nullptr; @@ -723,10 +723,8 @@ void PGORecordDetailInfos::Merge(const PGORecordDetailInfos &recordInfos) recordPool_->Merge(*recordInfos.recordPool_); protoTransitionPool_->Merge(*recordInfos.protoTransitionPool_); // Merge global layout desc infos to global method info map - std::set hclassTreeDescInfos = recordInfos.hclassTreeDescInfos_; - for (auto info = hclassTreeDescInfos.begin(); info != hclassTreeDescInfos.end(); - info++) { - auto &fromInfo = *info; + const auto& hclassTreeDescInfos = recordInfos.hclassTreeDescInfos_; + for (auto& fromInfo: hclassTreeDescInfos) { auto result = hclassTreeDescInfos_.find(fromInfo); if (result == hclassTreeDescInfos_.end()) { PGOHClassTreeDesc descInfo(fromInfo.GetProfileType()); @@ -777,6 +775,8 @@ bool PGORecordDetailInfos::ParseFromBinary(void *buffer, PGOProfilerHeader *cons ASSERT(methodInfos != nullptr); if (methodInfos->ParseFromBinary(chunk_.get(), *this, &addr)) { recordInfos_.emplace(recordType, methodInfos); + } else { + nativeAreaAllocator_.Delete(methodInfos); } } @@ -1049,6 +1049,8 @@ void PGORecordSimpleInfos::ParseFromBinary(void *buffer, PGOProfilerHeader *cons // check record name, the default record name of the framework abc does not enter the aot compilation FrameworkHelper::GetRealRecordName(recordName); (methodIdsResult.first->second).emplace(recordName, methodIds); + } else { + nativeAreaAllocator_.Delete(methodIds); } } diff --git a/ecmascript/pgo_profiler/pgo_profiler_manager.h b/ecmascript/pgo_profiler/pgo_profiler_manager.h index cb8e8fa37bfb028cea8d19ec7fa83a7b2d667866..f1baefcf806b83992f6ffad4c290946159abc821 100644 --- a/ecmascript/pgo_profiler/pgo_profiler_manager.h +++ b/ecmascript/pgo_profiler/pgo_profiler_manager.h @@ -279,16 +279,6 @@ public: return maxAotMethodSize_ != 0 && methodSize > maxAotMethodSize_; } - bool IsEnableForceIC() const - { - return isEnableForceIC_; - } - - void SetEnableForceIC(bool isEnableForceIC) - { - isEnableForceIC_ = isEnableForceIC; - } - private: bool InitializeData() { @@ -310,7 +300,6 @@ private: os::memory::Mutex *mutex_ = new os::memory::Mutex(); std::set> profilers_; bool isApFileCompatible_ {true}; - bool isEnableForceIC_ {true}; uint32_t maxAotMethodSize_ {0}; }; } // namespace panda::ecmascript::pgo diff --git a/ecmascript/pgo_profiler/tests/BUILD.gn b/ecmascript/pgo_profiler/tests/BUILD.gn index 20f9a668ece96d22c3d124635a118d8d29f33cc6..0746545ff7527a5ead21bcec94187afabf00a9d0 100644 --- a/ecmascript/pgo_profiler/tests/BUILD.gn +++ b/ecmascript/pgo_profiler/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" test_js_path = "//arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/pgo_test_case/" diff --git a/ecmascript/pgo_profiler/tests/pgo_profiler_test.cpp b/ecmascript/pgo_profiler/tests/pgo_profiler_test.cpp index 1b655713595c0392ea46b59aec54ce2b05313f31..a7085ce6731003d1e96090357ca6be1f1f4073fd 100644 --- a/ecmascript/pgo_profiler/tests/pgo_profiler_test.cpp +++ b/ecmascript/pgo_profiler/tests/pgo_profiler_test.cpp @@ -51,7 +51,6 @@ #include "ecmascript/pgo_profiler/tests/pgo_context_mock.h" #include "ecmascript/pgo_profiler/tests/pgo_encoder_mock.h" #include "ecmascript/tests/test_helper.h" -#include "ecmascript/napi/include/jsnapi_expo.h" using namespace panda; using namespace panda::ecmascript; @@ -1452,22 +1451,4 @@ HWTEST_F_L0(PGOProfilerTest, PGODisableUnderAOTFailTest) } } -HWTEST_F_L0(PGOProfilerTest, EnableForceICTest) -{ - RuntimeOption option; - EcmaVM* ecmaVM = JSNApi::CreateJSVM(option); - JSThread* jsThread = ecmaVM->GetJSThread(); - JSRuntimeOptions& jsOption = ecmaVM->GetJSOptions(); - EXPECT_TRUE(jsThread->IsEnableForceIC()); - EXPECT_TRUE(jsOption.IsEnableForceIC()); - EXPECT_TRUE(ecmascript::pgo::PGOProfilerManager::GetInstance()->IsEnableForceIC()); - - JSNApi::PreFork(ecmaVM); - JSNApi::PostFork(ecmaVM, option); - EXPECT_FALSE(jsThread->IsEnableForceIC()); - EXPECT_FALSE(jsOption.IsEnableForceIC()); - EXPECT_FALSE(ecmascript::pgo::PGOProfilerManager::GetInstance()->IsEnableForceIC()); - - JSNApi::DestroyJSVM(ecmaVM); -} } // namespace panda::test diff --git a/ecmascript/pgo_profiler/types/pgo_profiler_type.h b/ecmascript/pgo_profiler/types/pgo_profiler_type.h index e1f4c13fcc65f5cfdcc4362c3ab76451575d7078..7866440914b03cb7d9df9ea59451d6ae3b0035de 100644 --- a/ecmascript/pgo_profiler/types/pgo_profiler_type.h +++ b/ecmascript/pgo_profiler/types/pgo_profiler_type.h @@ -859,7 +859,7 @@ public: { type_ = PGOProfileType(context, from.GetProfileType()); ctorPt_ = PGOProfileType(context, from.GetCtorPt()); - protoPt_ = PGOProfileType(context, from.GetProtoTypePt()); + protoPt_ = PGOProfileType(context, from.GetPrototypePt()); kind_ = from.GetElementsKind(); elementsLength_ = from.GetElementsLength(); spaceFlag_ = from.GetSpaceFlag(); @@ -923,12 +923,12 @@ public: return ctorPt_; } - void SetProtoTypePt(PGOProfileType type) + void SetPrototypePt(PGOProfileType type) { protoPt_ = type; } - PGOProfileType GetProtoTypePt() const + PGOProfileType GetPrototypePt() const { return protoPt_; } diff --git a/ecmascript/platform/common/map.cpp b/ecmascript/platform/common/map.cpp index 438beef9cf1eb8c63033d549523a06e9117f101e..1f917d139ccec9760758088127dd1adf7995c335 100644 --- a/ecmascript/platform/common/map.cpp +++ b/ecmascript/platform/common/map.cpp @@ -31,6 +31,8 @@ const std::string GetPageTagString(PageTagType type, const std::string &spaceNam return std::string(CODE_TAG).append(std::to_string(threadId)); case PageTagType::MEMPOOL_CACHE: return "ArkTS MemPoolCache"; + case PageTagType::METHOD_LITERAL: + return "ArkTS MethodLiteral"; default: { LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); @@ -47,6 +49,8 @@ const char *GetPageTagString(PageTagType type) return CODE_TAG; case PageTagType::MEMPOOL_CACHE: return "ArkTS MemPoolCache"; + case PageTagType::METHOD_LITERAL: + return "ArkTS MethodLiteral"; default: { LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); diff --git a/ecmascript/platform/map.h b/ecmascript/platform/map.h index 4851082fc1d2b2dc442db7942637fd43f2c9af82..bb1cf3c37c1fbf35de557a346ccfc5892a61b6a2 100644 --- a/ecmascript/platform/map.h +++ b/ecmascript/platform/map.h @@ -60,6 +60,7 @@ enum class PageTagType : uint8_t { HEAP, MACHINE_CODE, MEMPOOL_CACHE, + METHOD_LITERAL, }; #ifdef PANDA_TARGET_WINDOWS diff --git a/ecmascript/platform/unix/linux/backtrace.cpp b/ecmascript/platform/unix/linux/backtrace.cpp index 3ef946656ff1677227f8a68b36cb29fa6e02dd5f..01cf5e5488fd68d97bd8eaa4a0b7379bef4c7be8 100644 --- a/ecmascript/platform/unix/linux/backtrace.cpp +++ b/ecmascript/platform/unix/linux/backtrace.cpp @@ -21,8 +21,7 @@ #include "ecmascript/mem/mem.h" namespace panda::ecmascript { -static const int MAX_STACK_SIZE = 256; -static const int FRAMES_LEN = 16; +static const int MAX_STACK_SIZE = 16; void Backtrace(std::ostringstream &stack, [[maybe_unused]] bool enableCache) { @@ -35,7 +34,7 @@ void Backtrace(std::ostringstream &stack, [[maybe_unused]] bool enableCache) } stack << "=====================Backtrace========================"; - for (int i = 0; i < FRAMES_LEN; ++i) { + for (int i = 0; i < framesLen; ++i) { if (stackList[i] == nullptr) { break; } diff --git a/ecmascript/regexp/tests/BUILD.gn b/ecmascript/regexp/tests/BUILD.gn index 97a04c02454eb02056ba25125d4bcfa19a90fba6..85b53d68efb396979d276aa2636177c7568595b1 100644 --- a/ecmascript/regexp/tests/BUILD.gn +++ b/ecmascript/regexp/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("RegexpTest") { module_out_path = module_output_path diff --git a/ecmascript/require/tests/BUILD.gn b/ecmascript/require/tests/BUILD.gn index 7f67b777d526716798573306714378866651b7eb..8f1c3e31b414abd1b04deb8a40378adacc4177f0 100644 --- a/ecmascript/require/tests/BUILD.gn +++ b/ecmascript/require/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("RequireTest") { module_out_path = module_output_path diff --git a/ecmascript/runtime.cpp b/ecmascript/runtime.cpp index e8f6f6bf7c1cf377ff49c64aa75064fd85c3b3c2..5542fc0f482882c72587725b9fc24128a77baf40 100644 --- a/ecmascript/runtime.cpp +++ b/ecmascript/runtime.cpp @@ -60,7 +60,6 @@ void Runtime::CreateIfFirstVm(const JSRuntimeOptions &options) MemMapAllocator::GetInstance()->Initialize(ecmascript::DEFAULT_REGION_SIZE); PGOProfilerManager::GetInstance()->Initialize(options.GetPGOProfilerPath(), options.GetPGOHotnessThreshold()); - PGOProfilerManager::GetInstance()->SetEnableForceIC(options.IsEnableForceIC()); ASSERT(instance_ == nullptr); instance_ = new Runtime(); SharedHeap::CreateNewInstance(); diff --git a/ecmascript/runtime_call_id.h b/ecmascript/runtime_call_id.h index f107063a46c230ce6dba516cee00d6c424703aca..1092c8edf7829877019eae67ecf833776e10ced1 100644 --- a/ecmascript/runtime_call_id.h +++ b/ecmascript/runtime_call_id.h @@ -212,26 +212,7 @@ namespace panda::ecmascript { V(LdSuperByValue) \ V(StSuperByValue) \ V(ThrowDeleteSuperProperty) \ - V(ModWithTSType) \ - V(MulWithTSType) \ - V(SubWithTSType) \ - V(DivWithTSType) \ - V(AddWithTSType) \ - V(GetBitOPDate) \ - V(ShlWithTSType) \ - V(ShrWithTSType) \ - V(AshrWithTSType) \ - V(AndWithTSType) \ - V(OrWithTSType) \ - V(XorWithTSType) \ - V(EqualWithIC) \ - V(NotEqualWithIC) \ - V(Compare) \ - V(LessWithIC) \ - V(LessEqWithIC) \ - V(GreaterWithIC) \ V(SetPropertyByName) \ - V(GreaterEqWithIC) \ V(LdBigInt) \ V(Tonumeric) \ V(CreateAsyncGeneratorObj) \ @@ -337,6 +318,8 @@ namespace panda::ecmascript { V(SharedArray, Every) \ V(SharedArray, Some) \ V(SharedArray, LastIndexOf) \ + V(SharedArray, Of) \ + V(SharedArray, CopyWithin) \ V(ArrayBuffer, Constructor) \ V(ArrayBuffer, Slice) \ V(ArrayBuffer, Species) \ diff --git a/ecmascript/sdk/BUILD.gn b/ecmascript/sdk/BUILD.gn index f92098c2bad638a3a5c7c04e4ed959e3aa0cbeb5..bb7b9155c73749ddef5af3f1f0a5854789801c91 100644 --- a/ecmascript/sdk/BUILD.gn +++ b/ecmascript/sdk/BUILD.gn @@ -76,11 +76,7 @@ if (is_standard_system) { ] # Add dynamic library "libshared_libz" - zlib_path = - get_label_info("//third_party/zlib:shared_libz", "root_out_dir") - deps += [ "//third_party/zlib:shared_libz" ] - sources += - [ zlib_path + "/thirdparty/zlib/libshared_libz${dylib_suffix}" ] + external_deps = [ "zlib:shared_libz" ] # Set the output directory for all dynamic libraries. outputs = [ target_out_dir + "/ets/build-tools/ets-loader/bin/ark/build-win/bin/{{source_file_part}}" ] @@ -157,11 +153,7 @@ if (is_standard_system) { ] # Add dynamic library "libshared_libz" - zlib_path = - get_label_info("//third_party/zlib:shared_libz", "root_out_dir") - deps += [ "//third_party/zlib:shared_libz" ] - sources += - [ zlib_path + "/thirdparty/zlib/libshared_libz${dylib_suffix}" ] + external_deps = [ "zlib:shared_libz" ] # Set the output directory for all dynamic libraries. outputs = [ target_out_dir + "/ets/build-tools/ets-loader/bin/ark/build/bin/{{source_file_part}}" ] @@ -223,11 +215,7 @@ if (is_standard_system) { ] # Add dynamic library "libshared_libz" - zlib_path = - get_label_info("//third_party/zlib:shared_libz", "root_out_dir") - deps += [ "//third_party/zlib:shared_libz" ] - sources += - [ zlib_path + "/thirdparty/zlib/libshared_libz${dylib_suffix}" ] + external_deps = [ "zlib:shared_libz" ] # Add dynamic library "hilog" hilog_path = get_label_info("$hilog_root:libhilog", "root_out_dir") diff --git a/ecmascript/serializer/base_deserializer.cpp b/ecmascript/serializer/base_deserializer.cpp index 02e4df1f491dae6b152b2f0ea42cb7da11dc4f37..57d94644db9e0b1b2ae101d69a7ae6e9c7865de4 100644 --- a/ecmascript/serializer/base_deserializer.cpp +++ b/ecmascript/serializer/base_deserializer.cpp @@ -480,6 +480,8 @@ JSTaggedType BaseDeserializer::RelocateObjectProtoAddr(uint8_t objectType) return env->GetArrayPrototype().GetTaggedType(); case (uint8_t)JSType::JS_SHARED_ARRAY: return env->GetSharedArrayPrototype().GetTaggedType(); + case (uint8_t)JSType::JS_API_BITVECTOR: + return env->GetBitVectorPrototype().GetTaggedType(); case (uint8_t)JSType::JS_MAP: return env->GetMapPrototype().GetTaggedType(); case (uint8_t)JSType::JS_SHARED_MAP: @@ -590,7 +592,9 @@ void BaseDeserializer::AllocateMultiRegion(SparseSpace *space, size_t spaceObjSi size_t regionNum = regionAlignedSize / Region::GetRegionAvailableSize(); while (regionNum > 1) { // 1: one region have allocated before std::vector regionRemainSizeVector = data_->GetRegionRemainSizeVector(); - space->ResetTopPointer(space->GetCurrentRegion()->GetEnd() - regionRemainSizeVector[regionRemainSizeIndex_++]); + auto regionAliveObjSize = Region::GetRegionAvailableSize() - regionRemainSizeVector[regionRemainSizeIndex_++]; + space->GetCurrentRegion()->IncreaseAliveObject(regionAliveObjSize); + space->ResetTopPointer(space->GetCurrentRegion()->GetBegin() + regionAliveObjSize); if (!space->Expand()) { DeserializeFatalOutOfMemory(spaceObjSize); } @@ -600,6 +604,7 @@ void BaseDeserializer::AllocateMultiRegion(SparseSpace *space, size_t spaceObjSi regionNum--; } size_t lastRegionRemainSize = regionAlignedSize - spaceObjSize; + space->GetCurrentRegion()->IncreaseAliveObject(Region::GetRegionAvailableSize() - lastRegionRemainSize); space->ResetTopPointer(space->GetCurrentRegion()->GetEnd() - lastRegionRemainSize); } diff --git a/ecmascript/serializer/base_deserializer.h b/ecmascript/serializer/base_deserializer.h index c55e289a4f92b6dc3ea7f84674a1178cce917b64..56a88fb14f8e40f2615850f84ebf0feddc7a84a2 100644 --- a/ecmascript/serializer/base_deserializer.h +++ b/ecmascript/serializer/base_deserializer.h @@ -174,7 +174,7 @@ private: { if (isShared) { if (dump) { - sheap_->DumpHeapSnapshotBeforeOOM(true, thread_); + sheap_->DumpHeapSnapshotBeforeOOM(false, thread_, SharedHeapOOMSource::DESERIALIZE); } LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize shared obj size: " << size << ", old space heap object size: " @@ -190,7 +190,7 @@ private: } else { if (dump) { heap_->StatisticHeapDetail(); - heap_->DumpHeapSnapshotBeforeOOM(); + heap_->DumpHeapSnapshotBeforeOOM(false); } LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize obj size: " << size << ", old space heap object size: " diff --git a/ecmascript/serializer/tests/BUILD.gn b/ecmascript/serializer/tests/BUILD.gn index 6cdddf2685a6376573e9eec6e1829e78b46bc7d5..5b99e3add68968a2a3070d5aea36dcdd1ca320bc 100644 --- a/ecmascript/serializer/tests/BUILD.gn +++ b/ecmascript/serializer/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("SerializerTest") { module_out_path = module_output_path diff --git a/ecmascript/serializer/tests/serializer_test.cpp b/ecmascript/serializer/tests/serializer_test.cpp index 0a9663528686eb507e035273e26f9a75ec5a0ea5..cdc61768ecfc1ec03e52d5759628758f3f482bbf 100644 --- a/ecmascript/serializer/tests/serializer_test.cpp +++ b/ecmascript/serializer/tests/serializer_test.cpp @@ -240,6 +240,21 @@ public: Destroy(); } + void PrimitiveTest(SerializeData* data) + { + Init(); + + BaseDeserializer deserializer(thread, data); + JSHandle objValue = deserializer.ReadValue(); + ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC); + ecmaVm->CollectGarbage(TriggerGCType::OLD_GC); + + EXPECT_FALSE(objValue.IsEmpty()); + EXPECT_TRUE(objValue->IsJSObject()); + + Destroy(); + } + void JSErrorTest1(SerializeData* data) { Init(); @@ -1368,7 +1383,6 @@ HWTEST_F_L0(JSSerializerTest, SerializeBigInt) JSObject::SetProperty(thread, JSHandle(obj), JSHandle(key2), JSHandle(bigInt2)); - ValueSerializer *serializer = new ValueSerializer(thread); bool success = serializer->WriteValue(thread, JSHandle(obj), JSHandle(thread, JSTaggedValue::Undefined()), @@ -1382,6 +1396,51 @@ HWTEST_F_L0(JSSerializerTest, SerializeBigInt) delete serializer; }; +HWTEST_F_L0(JSSerializerTest, SerializePrimitive) +{ + ObjectFactory *factory = ecmaVm->GetFactory(); + JSHandle obj = factory->NewEmptyJSObject(); + JSHandle keyInt(factory->NewFromASCII("int")); + JSHandle keyDouble(factory->NewFromASCII("double")); + JSHandle keyBoolean(factory->NewFromASCII("boolean")); + JSHandle keyString(factory->NewFromASCII("string")); + + int32_t intValue = 42; + double doubleValue = 3.14159; + bool booleanValue = true; + JSHandle stringValue(factory->NewFromASCII("Hello World")); + + JSHandle intPrimitive = factory->NewJSPrimitiveRef( + PrimitiveType::PRIMITIVE_NUMBER, JSHandle(thread, JSTaggedValue(intValue))); + JSHandle doublePrimitive = factory->NewJSPrimitiveRef( + PrimitiveType::PRIMITIVE_NUMBER, JSHandle(thread, JSTaggedValue(doubleValue))); + JSHandle booleanPrimitive = factory->NewJSPrimitiveRef( + PrimitiveType::PRIMITIVE_BOOLEAN, JSHandle(thread, JSTaggedValue(booleanValue))); + JSHandle stringPrimitive = factory->NewJSPrimitiveRef( + PrimitiveType::PRIMITIVE_STRING, JSHandle(stringValue)); + + JSObject::SetProperty(thread, JSHandle(obj), JSHandle(keyInt), + JSHandle(intPrimitive)); + JSObject::SetProperty(thread, JSHandle(obj), JSHandle(keyDouble), + JSHandle(doublePrimitive)); + JSObject::SetProperty(thread, JSHandle(obj), JSHandle(keyBoolean), + JSHandle(booleanPrimitive)); + JSObject::SetProperty(thread, JSHandle(obj), JSHandle(keyString), + JSHandle(stringPrimitive)); + + ValueSerializer *serializer = new ValueSerializer(thread); + bool success = serializer->WriteValue(thread, JSHandle(obj), + JSHandle(thread, JSTaggedValue::Undefined()), + JSHandle(thread, JSTaggedValue::Undefined())); + EXPECT_TRUE(success) << "Serialize primitive types failed"; + std::unique_ptr data = serializer->Release(); + JSDeserializerTest jsDeserializerTest; + std::thread t1(&JSDeserializerTest::PrimitiveTest, jsDeserializerTest, data.release()); + ThreadSuspensionScope scope(thread); + t1.join(); + delete serializer; +} + static void* Detach(void *param1, void *param2, void *hint, void *detachData) { GTEST_LOG_(INFO) << "detach is running"; diff --git a/ecmascript/serializer/value_serializer.cpp b/ecmascript/serializer/value_serializer.cpp index b0c0b535e82e7d360cd4fff02e3d9a59d1011ba2..2f49dff78b2809752930373f876246980fb341d4 100644 --- a/ecmascript/serializer/value_serializer.cpp +++ b/ecmascript/serializer/value_serializer.cpp @@ -27,6 +27,7 @@ bool ValueSerializer::CheckObjectCanSerialize(TaggedObject *object, bool &findSh return true; } switch (type) { + case JSType::JS_PRIMITIVE_REF: case JSType::JS_ERROR: case JSType::JS_EVAL_ERROR: case JSType::JS_RANGE_ERROR: @@ -62,6 +63,7 @@ bool ValueSerializer::CheckObjectCanSerialize(TaggedObject *object, bool &findSh case JSType::JS_OBJECT: case JSType::JS_ASYNC_FUNCTION: // means CONCURRENT_FUNCTION return true; + case JSType::JS_API_BITVECTOR: case JSType::JS_SHARED_SET: case JSType::JS_SHARED_MAP: case JSType::JS_SENDABLE_ARRAY_BUFFER: diff --git a/ecmascript/shared_object_factory.cpp b/ecmascript/shared_object_factory.cpp index 8a3b30681e6d70fbeb97d084a3a42709e0aa9633..7c4b3b672d325e6fd74ca550764f31ff1df346bb 100644 --- a/ecmascript/shared_object_factory.cpp +++ b/ecmascript/shared_object_factory.cpp @@ -245,6 +245,8 @@ JSHandle ObjectFactory::NewSFunctionByHClass(const JSHandle if (method->IsAotWithCallField()) { thread_->GetEcmaVM()->GetAOTFileManager()-> SetAOTFuncEntry(method->GetJSPandaFile(), *function, *method); + } else { + SetCodeEntryToFunctionFromMethod(function, method); } return function; } diff --git a/ecmascript/shared_objects/js_shared_array.cpp b/ecmascript/shared_objects/js_shared_array.cpp index 62bcddcaaed3971572f3eb4526953beda7be18ac..28fb20ee8f56adf9b41add6804a3fcec5f0ffaf1 100644 --- a/ecmascript/shared_objects/js_shared_array.cpp +++ b/ecmascript/shared_objects/js_shared_array.cpp @@ -222,7 +222,7 @@ void JSSharedArray::SetCapacity(JSThread *thread, const JSHandle &arra if (newLen <= capacity) { // judge if need to cut down the array size, else fill the unused tail with holes CheckAndCopyArray(thread, JSHandle(array)); - array->FillElementsWithHoles(thread, newLen, oldLen < capacity ? oldLen : capacity); + JSObject::FillElementsWithHoles(thread, array, newLen, oldLen < capacity ? oldLen : capacity); } if (newLen > capacity) { JSObject::GrowElementsCapacity(thread, array, newLen, isNew); diff --git a/ecmascript/snapshot/tests/BUILD.gn b/ecmascript/snapshot/tests/BUILD.gn index 14f78768966aff8a17953c8223b85459aaa8e569..c658d8c8b045c8efddccf09da030fa1b030221c6 100644 --- a/ecmascript/snapshot/tests/BUILD.gn +++ b/ecmascript/snapshot/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("SnapshotTest") { module_out_path = module_output_path diff --git a/ecmascript/stubs/runtime_stub_list.h b/ecmascript/stubs/runtime_stub_list.h index 0326ec5eefe5889fd78cb4b610e12bd94c15507c..1ae8cc1f0dc051659991d0348666f6ea6ada3f16 100644 --- a/ecmascript/stubs/runtime_stub_list.h +++ b/ecmascript/stubs/runtime_stub_list.h @@ -129,6 +129,7 @@ namespace panda::ecmascript { V(DebugPrint) \ V(DebugPrintCustom) \ V(DebugPrintInstruction) \ + V(CollectingOpcodes) \ V(DebugOsrEntry) \ V(Comment) \ V(FatalPrint) \ @@ -141,9 +142,8 @@ namespace panda::ecmascript { V(MarkingBarrier) \ V(MarkingBarrierWithEden) \ V(SharedGCMarkingBarrier) \ - V(StoreBarrier) \ V(DoubleToInt) \ - V(DoubleToLength) \ + V(SaturateTruncDoubleToInt32) \ V(FloatMod) \ V(FloatAcos) \ V(FloatAcosh) \ @@ -170,11 +170,7 @@ namespace panda::ecmascript { V(FloatPow) \ V(FloatCeil) \ V(CallDateNow) \ - V(NumberIsFinite) \ - V(FindElementWithCache) \ V(UpdateFieldType) \ - V(CreateArrayFromList) \ - V(StringsAreEquals) \ V(BigIntEquals) \ V(TimeClip) \ V(SetDateValues) \ @@ -190,6 +186,8 @@ namespace panda::ecmascript { V(StringGetStart) \ V(StringGetEnd) \ V(ArrayTrim) \ + V(SortTypedArray) \ + V(ReverseTypedArray) \ V(CopyTypedArrayBuffer) \ V(IsFastRegExp) @@ -296,6 +294,7 @@ namespace panda::ecmascript { V(StOwnByValue) \ V(LdSuperByValue) \ V(StSuperByValue) \ + V(StObjByValue) \ V(LdObjByIndex) \ V(StObjByIndex) \ V(StOwnByIndex) \ diff --git a/ecmascript/stubs/runtime_stubs-inl.h b/ecmascript/stubs/runtime_stubs-inl.h index 7ae1b7fef6c6e3797059e47cd70472e0ebda0b86..7813bcfe0be03efca26b2b12b185ad33e17f6213 100644 --- a/ecmascript/stubs/runtime_stubs-inl.h +++ b/ecmascript/stubs/runtime_stubs-inl.h @@ -99,7 +99,7 @@ JSTaggedValue RuntimeStubs::RuntimeExp(JSThread *thread, JSTaggedValue base, JST } double doubleBase = valBase->GetNumber(); double doubleExponent = valExponent->GetNumber(); - if (std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) { + if ((std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) || std::isnan(doubleExponent)) { return JSTaggedValue(base::NAN_VALUE); } if (((doubleBase == 0) && @@ -584,7 +584,6 @@ JSTaggedValue RuntimeStubs::RuntimeGetIteratorNext(JSThread *thread, const JSHan ASSERT(method->IsCallable()); JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, method, obj, undefined, 0); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSTaggedValue ret = JSFunction::Call(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); if (!ret.IsECMAObject()) { @@ -602,7 +601,7 @@ JSTaggedValue RuntimeStubs::RuntimeSetObjectWithProto(JSThread *thread, const JS if (UNLIKELY(proto->IsJSShared())) { THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(SetProtoWithSendable), JSTaggedValue::Exception()); } - JSObject::SetPrototype(thread, obj, proto); + JSObject::SetPrototype(thread, obj, proto, true); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return JSTaggedValue::True(); } @@ -1142,7 +1141,7 @@ JSTaggedValue RuntimeStubs::RuntimeSetClassInheritanceRelationship(JSThread *thr // ctor -> hclass -> EnableProtoChangeMarker auto constructor = JSFunction::Cast(ctor.GetTaggedValue().GetTaggedObject()); - if (constructor->GetClass()->IsTS()) { + if (constructor->GetClass()->IsAOT()) { JSHClass::EnableProtoChangeMarker(thread, JSHandle(thread, constructor->GetClass())); // prototype -> hclass -> EnableProtoChangeMarker JSHClass::EnableProtoChangeMarker(thread, @@ -1155,13 +1154,13 @@ JSTaggedValue RuntimeStubs::RuntimeSetClassInheritanceRelationship(JSThread *thr JSTaggedValue protoOrHClass = JSHandle(ctor)->GetProtoOrHClass(); if (protoOrHClass.IsJSHClass()) { JSHClass *ihc = JSHClass::Cast(protoOrHClass.GetTaggedObject()); - if (ihc->IsTS()) { + if (ihc->IsAOT()) { JSHandle ihcHandle(thread, ihc); JSHClass::EnableProtoChangeMarker(thread, ihcHandle); } } else { JSHandle protoHandle(thread, protoOrHClass); - if (protoHandle->GetJSHClass()->IsTS()) { + if (protoHandle->GetJSHClass()->IsAOT()) { JSHClass::EnablePHCProtoChangeMarker(thread, JSHandle(thread, protoHandle->GetJSHClass())); } } @@ -1544,7 +1543,6 @@ JSTaggedValue RuntimeStubs::RuntimeLdPrivateProperty(JSThread *thread, JSTaggedV JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); // 0: getter has 0 arg EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, handleKey, handleObj, undefined, 0); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSTaggedValue resGetter = JSFunction::Call(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return resGetter; @@ -2563,7 +2561,7 @@ JSTaggedValue RuntimeStubs::RuntimeDefineGetterSetterByValue(JSThread *thread, c JSObject::DefineOwnProperty(thread, obj, propKey, desc); auto holderTraHClass = obj->GetJSHClass(); if (receiverHClass != holderTraHClass) { - if (holderTraHClass->IsTS()) { + if (holderTraHClass->IsAOT()) { JSHandle phcHandle(thread, holderTraHClass); JSHClass::EnablePHCProtoChangeMarker(thread, phcHandle); } @@ -2676,6 +2674,7 @@ JSTaggedValue RuntimeStubs::RuntimeCallBigIntAsIntN(JSThread *thread, JSTaggedVa { auto biginteger = JSHandle(thread, bigint); JSTaggedNumber bitness = JSTaggedValue::ToNumber(thread, bits); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return BigInt::AsintN(thread, bitness, biginteger); } @@ -2683,6 +2682,7 @@ JSTaggedValue RuntimeStubs::RuntimeCallBigIntAsUintN(JSThread *thread, JSTaggedV { auto biginteger = JSHandle(thread, bigint); JSTaggedNumber bitness = JSTaggedValue::ToNumber(thread, bits); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return BigInt::AsUintN(thread, bitness, biginteger); } diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index b5feaea769e544e5df91d41a9a2ef5f33903ab2e..53b2b8c55808783163501a20b51d9038bb554ac0 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -25,6 +25,7 @@ #include "ecmascript/builtins/builtins_array.h" #include "ecmascript/builtins/builtins_arraybuffer.h" #include "ecmascript/js_stable_array.h" +#include "ecmascript/builtins/builtins_arraybuffer.h" #include "ecmascript/builtins/builtins_bigint.h" #include "ecmascript/builtins/builtins_function.h" #include "ecmascript/builtins/builtins_iterator.h" @@ -280,8 +281,8 @@ void RuntimeStubs::CopyTypedArrayBuffer(JSTypedArray *srcArray, JSTypedArray *ta } JSTaggedValue srcBuffer = srcArray->GetViewedArrayBufferOrByteArray(); JSTaggedValue targetBuffer = targetArray->GetViewedArrayBufferOrByteArray(); - uint32_t srcByteIndex = static_cast(srcStartPos * elementSize + srcArray->GetByteOffset()); - uint32_t targetByteIndex = static_cast(tarStartPos * elementSize + targetArray->GetByteOffset()); + uint32_t srcByteIndex = static_cast(srcStartPos * elementSize) + srcArray->GetByteOffset(); + uint32_t targetByteIndex = static_cast(tarStartPos * elementSize) + targetArray->GetByteOffset(); uint8_t *srcBuf = (uint8_t *)builtins::BuiltinsArrayBuffer::GetDataPointFromBuffer(srcBuffer, srcByteIndex); uint8_t *targetBuf = (uint8_t *)builtins::BuiltinsArrayBuffer::GetDataPointFromBuffer(targetBuffer, targetByteIndex); @@ -656,6 +657,7 @@ DEF_RUNTIME_STUBS(RuntimeDump) void RuntimeStubs::Dump(JSTaggedType rawValue) { + DISALLOW_GARBAGE_COLLECTION; std::ostringstream oss; auto value = JSTaggedValue(rawValue); value.Dump(oss); @@ -664,11 +666,13 @@ void RuntimeStubs::Dump(JSTaggedType rawValue) void RuntimeStubs::DebugDump(JSTaggedType rawValue) { + DISALLOW_GARBAGE_COLLECTION; DebugDumpWithHint(reinterpret_cast(nullptr), rawValue); } void RuntimeStubs::DumpWithHint(uintptr_t hintStrAddress, JSTaggedType rawValue) { + DISALLOW_GARBAGE_COLLECTION; const char *origHintStr = reinterpret_cast(hintStrAddress); // May be nullptr const char *hintStr = (origHintStr == nullptr) ? "" : origHintStr; DumpToStreamWithHint(std::cout, hintStr, JSTaggedValue(rawValue)); @@ -677,6 +681,7 @@ void RuntimeStubs::DumpWithHint(uintptr_t hintStrAddress, JSTaggedType rawValue) void RuntimeStubs::DebugDumpWithHint(uintptr_t hintStrAddress, JSTaggedType rawValue) { + DISALLOW_GARBAGE_COLLECTION; const char *origHintStr = reinterpret_cast(hintStrAddress); // May be nullptr const char *hintStr = (origHintStr == nullptr) ? "" : origHintStr; // The immediate lambda expression call is not evaluated when the logger is unabled. @@ -731,6 +736,29 @@ void RuntimeStubs::DebugPrintInstruction([[maybe_unused]] uintptr_t argGlue, con LOG_INTERPRETER(DEBUG) << inst; } +void RuntimeStubs::CollectingOpcodes([[maybe_unused]] uintptr_t argGlue, const uint8_t *pc) +{ +#if ECMASCRIPT_ENABLE_COLLECTING_OPCODES + BytecodeInstruction inst(pc); + auto thread = JSThread::GlueToJSThread(argGlue); + auto vm = thread->GetEcmaVM(); + auto opcode = inst.GetOpcode(); + std::stack> &bytecodeStatsStack_ = + vm->GetBytecodeStatsStack(); + if (bytecodeStatsStack_.empty()) { + return; + } + std::unordered_map &bytecodeStatsMap_ = bytecodeStatsStack_.top(); + auto foundInst = bytecodeStatsMap_.find(opcode); + if (foundInst != bytecodeStatsMap_.end()) { + ++foundInst->second; + } else { + bytecodeStatsMap_[opcode] = 1; + } + LOG_INTERPRETER(DEBUG) << inst; +#endif +} + void RuntimeStubs::DebugOsrEntry([[maybe_unused]] uintptr_t argGlue, const uint8_t *codeEntry) { LOG_JIT(DEBUG) << "[OSR]: Enter OSR Code: " << reinterpret_cast(codeEntry); @@ -900,7 +928,7 @@ DEF_RUNTIME_STUBS(Exp) // fast path double doubleBase = baseValue.IsInt() ? baseValue.GetInt() : baseValue.GetDouble(); double doubleExponent = exponentValue.IsInt() ? exponentValue.GetInt() : exponentValue.GetDouble(); - if (std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) { + if ((std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) || std::isnan(doubleExponent)) { return JSTaggedValue(base::NAN_VALUE).GetRawData(); } if ((doubleBase == 0 && @@ -1369,6 +1397,15 @@ DEF_RUNTIME_STUBS(GetArrayLiteralFromCache) thread, cp, index.GetInt(), module.GetTaggedValue()).GetRawData(); } +DEF_RUNTIME_STUBS(StObjByValue) +{ + RUNTIME_STUBS_HEADER(StObjByValue); + JSHandle receiver = GetHArg(argv, argc, 0); // 0: means the zeroth parameter + JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter + JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter + return RuntimeStObjByValue(thread, receiver, key, value).GetRawData(); +} + DEF_RUNTIME_STUBS(LdObjByIndex) { RUNTIME_STUBS_HEADER(LdObjByIndex); @@ -1592,7 +1629,7 @@ DEF_RUNTIME_STUBS(JitCompile) RUNTIME_STUBS_HEADER(JitCompile); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue offset = GetArg(argv, argc, 1); // 1: means the first parameter - Jit::Compile(thread->GetEcmaVM(), thisFunc, CompilerTier::FAST, offset.GetInt(), JitCompileMode::ASYNC); + Jit::Compile(thread->GetEcmaVM(), thisFunc, CompilerTier::Tier::FAST, offset.GetInt(), JitCompileMode::Mode::ASYNC); return JSTaggedValue::Undefined().GetRawData(); } @@ -1600,8 +1637,8 @@ DEF_RUNTIME_STUBS(BaselineJitCompile) { RUNTIME_STUBS_HEADER(BaselineJitCompile); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter - Jit::Compile(thread->GetEcmaVM(), thisFunc, CompilerTier::BASELINE, - MachineCode::INVALID_OSR_OFFSET, JitCompileMode::ASYNC); + Jit::Compile(thread->GetEcmaVM(), thisFunc, CompilerTier::Tier::BASELINE, + MachineCode::INVALID_OSR_OFFSET, JitCompileMode::Mode::ASYNC); return JSTaggedValue::Undefined().GetRawData(); } @@ -3114,35 +3151,6 @@ DEF_RUNTIME_STUBS(DecodeURIComponent) return result.GetRawData(); } -JSTaggedType RuntimeStubs::CreateArrayFromList([[maybe_unused]] uintptr_t argGlue, int32_t argc, - JSTaggedValue *argvPtr) -{ - auto thread = JSThread::GlueToJSThread(argGlue); - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle taggedArray = factory->NewTaggedArray(argc - NUM_MANDATORY_JSFUNC_ARGS); - for (int index = NUM_MANDATORY_JSFUNC_ARGS; index < argc; ++index) { - taggedArray->Set(thread, index - NUM_MANDATORY_JSFUNC_ARGS, argvPtr[index]); - } - JSHandle arrHandle = JSArray::CreateArrayFromList(thread, taggedArray); - return arrHandle.GetTaggedValue().GetRawData(); -} - -int32_t RuntimeStubs::FindElementWithCache(uintptr_t argGlue, JSTaggedType hclass, - JSTaggedType key, int32_t num) -{ - auto thread = JSThread::GlueToJSThread(argGlue); - auto cls = reinterpret_cast(hclass); - JSTaggedValue propKey = JSTaggedValue(key); - auto layoutInfo = LayoutInfo::Cast(cls->GetLayout().GetTaggedObject()); - PropertiesCache *cache = thread->GetPropertiesCache(); - int index = cache->Get(cls, propKey); - if (index == PropertiesCache::NOT_FOUND) { - index = layoutInfo->BinarySearch(propKey, num); - cache->Set(cls, propKey, index); - } - return index; -} - void RuntimeStubs::UpdateFieldType(JSTaggedType hclass, uint64_t value) { auto cls = reinterpret_cast(hclass); @@ -3152,6 +3160,7 @@ void RuntimeStubs::UpdateFieldType(JSTaggedType hclass, uint64_t value) JSTaggedType RuntimeStubs::GetActualArgvNoGC(uintptr_t argGlue) { + DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); JSTaggedType *current = const_cast(thread->GetLastLeaveFrame()); FrameIterator it(current, thread); @@ -3292,11 +3301,6 @@ double RuntimeStubs::FloatPow(double base, double exp) return std::pow(base, exp); } -bool RuntimeStubs::NumberIsFinite(double x) -{ - return std::isfinite(x); -} - double RuntimeStubs::CallDateNow() { // time from now is in ms. @@ -3313,16 +3317,9 @@ int32_t RuntimeStubs::DoubleToInt(double x, size_t bits) return base::NumberHelper::DoubleToInt(x, bits); } -JSTaggedType RuntimeStubs::DoubleToLength(double x) +int32_t RuntimeStubs::SaturateTruncDoubleToInt32(double x) { - double length = base::NumberHelper::TruncateDouble(x); - if (length < 0.0) { - return JSTaggedNumber(static_cast(0)).GetRawData(); - } - if (length > SAFE_NUMBER) { - return JSTaggedNumber(static_cast(SAFE_NUMBER)).GetRawData(); - } - return JSTaggedNumber(length).GetRawData(); + return base::NumberHelper::SaturateTruncDoubleToInt32(x); } void RuntimeStubs::InsertNewToEdenRSet([[maybe_unused]] uintptr_t argGlue, @@ -3414,52 +3411,21 @@ void RuntimeStubs::SharedGCMarkingBarrier([[maybe_unused]] uintptr_t argGlue, Ta Barriers::UpdateShared(thread, value, valueRegion); } -void RuntimeStubs::StoreBarrier([[maybe_unused]] uintptr_t argGlue, - uintptr_t object, size_t offset, TaggedObject *value) -{ - uintptr_t slotAddr = object + offset; - Region *objectRegion = Region::ObjectAddressToRange(object); - Region *valueRegion = Region::ObjectAddressToRange(value); - auto thread = JSThread::GlueToJSThread(argGlue); -#if ECMASCRIPT_ENABLE_BARRIER_CHECK - if (!thread->GetEcmaVM()->GetHeap()->IsAlive(JSTaggedValue(value).GetHeapObject())) { - LOG_FULL(FATAL) << "RuntimeStubs::StoreBarrier checked value:" << value << " is invalid!"; - } -#endif - if (objectRegion->InGeneralOldSpace() && valueRegion->InGeneralNewSpace()) { - // Should align with '8' in 64 and 32 bit platform - ASSERT((slotAddr % static_cast(MemAlignment::MEM_ALIGN_OBJECT)) == 0); - objectRegion->InsertOldToNewRSet(slotAddr); - } else if (!objectRegion->InSharedHeap() && valueRegion->InSharedSweepableSpace()) { - objectRegion->InsertLocalToShareRSet(slotAddr); - } else if (valueRegion->InEdenSpace() && objectRegion->InYoungSpace()) { - objectRegion->InsertNewToEdenRSet(slotAddr); - } - if (!valueRegion->InSharedHeap() && thread->IsConcurrentMarkingOrFinished()) { - Barriers::Update(thread, slotAddr, objectRegion, value, valueRegion); - } - if (valueRegion->InSharedSweepableSpace() && thread->IsSharedConcurrentMarkingOrFinished()) { - Barriers::UpdateShared(thread, value, valueRegion); - } -} - -bool RuntimeStubs::StringsAreEquals(EcmaString *str1, EcmaString *str2) -{ - return EcmaStringAccessor::StringsAreEqualDiffUtfEncoding(str1, str2); -} - bool RuntimeStubs::BigIntEquals(JSTaggedType left, JSTaggedType right) { + DISALLOW_GARBAGE_COLLECTION; return BigInt::Equal(JSTaggedValue(left), JSTaggedValue(right)); } bool RuntimeStubs::BigIntSameValueZero(JSTaggedType left, JSTaggedType right) { + DISALLOW_GARBAGE_COLLECTION; return BigInt::SameValueZero(JSTaggedValue(left), JSTaggedValue(right)); } JSTaggedValue RuntimeStubs::JSHClassFindProtoTransitions(JSHClass *cls, JSTaggedValue key, JSTaggedValue proto) { + DISALLOW_GARBAGE_COLLECTION; return JSTaggedValue(cls->FindProtoTransitions(key, proto)); } @@ -3477,17 +3443,20 @@ JSTaggedValue RuntimeStubs::NumberHelperStringToDouble(EcmaString *numberString) JSTaggedValue RuntimeStubs::GetStringToListCacheArray(uintptr_t argGlue) { + DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); return thread->GetCurrentEcmaContext()->GetStringToListResultCache().GetTaggedValue(); } double RuntimeStubs::TimeClip(double time) { + DISALLOW_GARBAGE_COLLECTION; return JSDate::TimeClip(time); } double RuntimeStubs::SetDateValues(double year, double month, double day) { + DISALLOW_GARBAGE_COLLECTION; if (std::isnan(year) || !std::isfinite(year) || std::isnan(month) || !std::isfinite(month) || std::isnan(day) || !std::isfinite(day)) { return base::NAN_VALUE; @@ -3702,6 +3671,7 @@ DEF_RUNTIME_STUBS(HClassCloneWithAddProto) void RuntimeStubs::StartCallTimer(uintptr_t argGlue, JSTaggedType func, bool isAot) { + DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); JSTaggedValue callTarget(func); Method *method = Method::Cast(JSFunction::Cast(callTarget)->GetMethod()); @@ -3716,6 +3686,7 @@ void RuntimeStubs::StartCallTimer(uintptr_t argGlue, JSTaggedType func, bool isA void RuntimeStubs::EndCallTimer(uintptr_t argGlue, JSTaggedType func) { + DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); JSTaggedValue callTarget(func); Method *method = Method::Cast(JSFunction::Cast(callTarget)->GetMethod()); @@ -3892,6 +3863,10 @@ DEF_RUNTIME_STUBS(LocaleCompareCacheable) JSHandle locales = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle thatHandle = GetHArg(argv, argc, 2); // 2: means the second parameter +#if ENABLE_NEXT_OPTIMIZATION + const CompareStringsOption csOption = JSCollator::CompareStringsOptionFor(thread, locales); + JSTaggedValue result = JSCollator::FastCachedCompareStrings(thread, locales, thisHandle, thatHandle, csOption); +#else auto collator = JSCollator::GetCachedIcuCollator(thread, locales); JSTaggedValue result = JSTaggedValue::Undefined(); if (collator != nullptr) { @@ -3899,6 +3874,7 @@ DEF_RUNTIME_STUBS(LocaleCompareCacheable) thread, locales); result = JSCollator::CompareStrings(thread, collator, thisHandle, thatHandle, csOption); } +#endif return result.GetRawData(); } @@ -3919,11 +3895,109 @@ void RuntimeStubs::ArrayTrim(uintptr_t argGlue, TaggedArray *array, int64_t newL bool RuntimeStubs::IsFastRegExp(uintptr_t argGlue, JSTaggedValue thisValue) { - DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); - [[maybe_unused]] EcmaHandleScope handleScope(thread); - JSHandle thisObjVal(thread, thisValue); - return builtins::BuiltinsRegExp::IsFastRegExp(thread, thisObjVal); + return builtins::BuiltinsRegExp::IsFastRegExp(thread, thisValue); +} + +template +static bool CompareFloat(T x, T y) +{ + if (x < y) { + return true; + } + if (x > y) { + return false; + } + if constexpr (!std::is_integral::value) { + double doubleX = x, doubleY = y; + if (x == 0 && x == y) { + /* -0.0 is less than +0.0 */ + return std::signbit(doubleX) && !std::signbit(doubleY); + } + if (!std::isnan(doubleX) && std::isnan(doubleY)) { + /* number is less than NaN */ + return true; + } + } + return false; +} + +void RuntimeStubs::SortTypedArray(JSTypedArray *typedArray) +{ + DISALLOW_GARBAGE_COLLECTION; + JSHClass *hclass = typedArray->GetClass(); + const JSType jsType = hclass->GetObjectType(); + JSTaggedValue buffer = typedArray->GetViewedArrayBufferOrByteArray(); + const uint32_t len = typedArray->GetArrayLength(); + void *pointer = builtins::BuiltinsArrayBuffer::GetDataPointFromBuffer(buffer); + switch (jsType) { + case JSType::JS_INT8_ARRAY: + std::sort(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_UINT8_ARRAY: + case JSType::JS_UINT8_CLAMPED_ARRAY: + std::sort(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_INT16_ARRAY: + std::sort(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_UINT16_ARRAY: + std::sort(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_INT32_ARRAY: + std::sort(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_UINT32_ARRAY: + std::sort(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_FLOAT32_ARRAY: + std::sort(static_cast(pointer), static_cast(pointer) + len, CompareFloat); + break; + case JSType::JS_FLOAT64_ARRAY: + std::sort(static_cast(pointer), static_cast(pointer) + len, CompareFloat); + break; + default: + UNREACHABLE(); + } +} + +void RuntimeStubs::ReverseTypedArray(JSTypedArray *typedArray) +{ + DISALLOW_GARBAGE_COLLECTION; + JSHClass *hclass = typedArray->GetClass(); + const JSType jsType = hclass->GetObjectType(); + JSTaggedValue buffer = typedArray->GetViewedArrayBufferOrByteArray(); + const uint32_t len = typedArray->GetArrayLength(); + void *pointer = builtins::BuiltinsArrayBuffer::GetDataPointFromBuffer(buffer); + switch (jsType) { + case JSType::JS_INT8_ARRAY: + std::reverse(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_UINT8_ARRAY: + case JSType::JS_UINT8_CLAMPED_ARRAY: + std::reverse(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_INT16_ARRAY: + std::reverse(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_UINT16_ARRAY: + std::reverse(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_INT32_ARRAY: + std::reverse(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_UINT32_ARRAY: + std::reverse(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_FLOAT32_ARRAY: + std::reverse(static_cast(pointer), static_cast(pointer) + len); + break; + case JSType::JS_FLOAT64_ARRAY: + std::reverse(static_cast(pointer), static_cast(pointer) + len); + break; + default: + UNREACHABLE(); + } } DEF_RUNTIME_STUBS(ArrayForEachContinue) diff --git a/ecmascript/stubs/runtime_stubs.h b/ecmascript/stubs/runtime_stubs.h index c4125cc9687634cd30b49810a24942ba32a8a816..8460653aec35fe1656bb22a3f520bc82b834233b 100644 --- a/ecmascript/stubs/runtime_stubs.h +++ b/ecmascript/stubs/runtime_stubs.h @@ -86,6 +86,7 @@ public: static void DebugPrint(int fmtMessageId, ...); static void DebugPrintCustom(uintptr_t fmt, ...); static void DebugPrintInstruction([[maybe_unused]] uintptr_t argGlue, const uint8_t *pc); + static void CollectingOpcodes([[maybe_unused]] uintptr_t argGlue, const uint8_t *pc); static void DebugOsrEntry([[maybe_unused]] uintptr_t argGlue, const uint8_t *codeEntry); static void Comment(uintptr_t argStr); static void FatalPrint(int fmtMessageId, ...); @@ -95,9 +96,6 @@ public: static void MarkingBarrierWithEden([[maybe_unused]] uintptr_t argGlue, uintptr_t object, size_t offset, TaggedObject *value); static void SharedGCMarkingBarrier([[maybe_unused]] uintptr_t argGlue, TaggedObject *value); - static void StoreBarrier([[maybe_unused]] uintptr_t argGlue, - uintptr_t object, size_t offset, TaggedObject *value); - static JSTaggedType CreateArrayFromList([[maybe_unused]] uintptr_t argGlue, int32_t argc, JSTaggedValue *argvPtr); static JSTaggedType GetActualArgvNoGC(uintptr_t argGlue); static void InsertNewToEdenRSet([[maybe_unused]] uintptr_t argGlue, uintptr_t object, size_t offset); static void InsertOldToNewRSet([[maybe_unused]] uintptr_t argGlue, uintptr_t object, size_t offset); @@ -105,7 +103,7 @@ public: static void SetBitAtomic(GCBitset::GCBitsetWord *word, GCBitset::GCBitsetWord mask, GCBitset::GCBitsetWord oldValue); static int32_t DoubleToInt(double x, size_t bits); - static JSTaggedType DoubleToLength(double x); + static int32_t SaturateTruncDoubleToInt32(double x); static double FloatMod(double x, double y); static double FloatAcos(double x); static double FloatAcosh(double x); @@ -131,12 +129,8 @@ public: static double FloatPow(double base, double exp); static double FloatCbrt(double x); static double FloatCeil(double x); - static bool NumberIsFinite(double x); static double CallDateNow(); - static int32_t FindElementWithCache(uintptr_t argGlue, JSTaggedType hclass, - JSTaggedType key, int32_t num); static void UpdateFieldType(JSTaggedType hclass, uint64_t value); - static bool StringsAreEquals(EcmaString *str1, EcmaString *str2); static bool BigIntEquals(JSTaggedType left, JSTaggedType right); static bool BigIntSameValueZero(JSTaggedType key, JSTaggedType other); static JSTaggedValue JSHClassFindProtoTransitions(JSHClass *cls, JSTaggedValue key, JSTaggedValue proto); @@ -159,6 +153,8 @@ public: static void CopyTypedArrayBuffer(JSTypedArray *srcArray, JSTypedArray *targetArray, int32_t srcStartPos, int32_t tarStartPos, int32_t count, int32_t elementSize); static inline uint32_t RuntimeGetBytecodePcOfstForBaseline(const JSHandle &func, uintptr_t nativePc); + static void ReverseTypedArray(JSTypedArray *typedArray); + static void SortTypedArray(JSTypedArray *typedArray); private: static void DumpToStreamWithHint(std::ostream &out, std::string_view prompt, JSTaggedValue value); diff --git a/ecmascript/tagged_array-inl.h b/ecmascript/tagged_array-inl.h index 73931cc6bd288e8d6d616c7aca5601b66155eeb0..8105f3b42ae4ed1294d22a495e467b8fd9d00ff7 100644 --- a/ecmascript/tagged_array-inl.h +++ b/ecmascript/tagged_array-inl.h @@ -74,7 +74,7 @@ inline void TaggedArray::Copy(const JSThread* thread, uint32_t dstStart, uint32_ size_t taggedTypeSize = JSTaggedValue::TaggedTypeSize(); JSTaggedValue* to = reinterpret_cast(ToUintPtr(GetData()) + taggedTypeSize * dstStart); JSTaggedValue* from = reinterpret_cast(ToUintPtr(srcArray->GetData()) + taggedTypeSize * srcStart); - Barriers::CopyObject(thread, to, from, count); + Barriers::CopyObject(thread, this, to, from, count); } } // namespace panda::ecmascript #endif // ECMASCRIPT_TAGGED_ARRAY_INL_H diff --git a/ecmascript/tagged_dictionary.h b/ecmascript/tagged_dictionary.h index 3030fabbcde2064d7b594c77b9e2dd4ece219862..33b21a65aada69bdf30ceb2dd2a4149a539bc02f 100644 --- a/ecmascript/tagged_dictionary.h +++ b/ecmascript/tagged_dictionary.h @@ -84,7 +84,12 @@ public: { return a.GetDictionaryOrder() < b.GetDictionaryOrder(); } - DECL_DUMP() + void Dump(std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR; + void Dump() const DUMP_API_ATTR + { + Dump(std::cout); + } + void DumpForSnapshot(std::vector &vec) const; static constexpr int ENTRY_KEY_INDEX = 0; static constexpr int ENTRY_VALUE_INDEX = 1; @@ -139,7 +144,12 @@ public: ASSERT(a.IsNumber() && b.IsNumber()); return a.GetNumber() < b.GetNumber(); } - DECL_DUMP() + void Dump(std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR; + void Dump() const DUMP_API_ATTR + { + Dump(std::cout); + } + void DumpForSnapshot(std::vector &vec) const; static constexpr int ENTRY_KEY_INDEX = 0; static constexpr int ENTRY_VALUE_INDEX = 1; diff --git a/ecmascript/tagged_hash_array.cpp b/ecmascript/tagged_hash_array.cpp index 08eed91084844c97fee49e9d51baaeb4f9582162..5c1564ba036d55eaf528591c7d04cfc87de09454 100644 --- a/ecmascript/tagged_hash_array.cpp +++ b/ecmascript/tagged_hash_array.cpp @@ -249,7 +249,7 @@ JSTaggedValue TaggedHashArray::RemoveNode(JSThread *thread, int hash, JSTaggedVa Set(thread, index, JSTaggedValue::Hole()); return oldValue; } - //set root node as red + //set root node as black RBTreeNode *root = RBTreeNode::Cast(rootTreeNodeVa.GetTaggedObject()); if (root->GetIsRed().ToBoolean()) { root->SetIsRed(thread, JSTaggedValue(false)); diff --git a/ecmascript/tagged_tree.cpp b/ecmascript/tagged_tree.cpp index cd7bfaa648bc39d893bcd4669cc26310753584b2..4c554b08e790df3ab25cc3271940fea6008e48bb 100644 --- a/ecmascript/tagged_tree.cpp +++ b/ecmascript/tagged_tree.cpp @@ -363,7 +363,6 @@ ComparisonResult TaggedTree::EntryCompare(JSThread *thread, const JSHan EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, compareFn, thisArgHandle, undefined, argsLength); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); - ASSERT(info != nullptr); info->SetCallArg(valueX.GetTaggedValue(), valueY.GetTaggedValue()); JSTaggedValue callResult = JSFunction::Call(info); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); @@ -372,6 +371,7 @@ ComparisonResult TaggedTree::EntryCompare(JSThread *thread, const JSHan // if callResult is true, compareResult = -1. if (callResult.IsFalse()) { info = EcmaInterpreter::NewRuntimeCallInfo(thread, compareFn, thisArgHandle, undefined, argsLength); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); info->SetCallArg(valueY.GetTaggedValue(), valueX.GetTaggedValue()); callResult = JSFunction::Call(info); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED); @@ -433,7 +433,7 @@ JSHandle TaggedTree::Insert(JSThread *thread, JSHandle(thread, JSTaggedValue::Exception())); if (res == ComparisonResult::EQUAL) { newTree->SetValue(thread, parentIndex, value.GetTaggedValue()); - return tree; + return newTree; } else if (res == ComparisonResult::LESS) { JSTaggedValue child = newTree->GetLeftChild(parentIndex); if (child.IsHole()) { diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index bb58b70faf7e3fdbeee9de523f31303803cbc582..34c5da30fb7b82b110d3e6e8022f4da803f7a7c8 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//arkcompiler/ets_runtime/js_runtime_config.gni") import("//arkcompiler/ets_runtime/test/test_helper.gni") -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("EcmaVm_001_Test") { module_out_path = module_output_path @@ -1461,6 +1461,7 @@ host_unittest_action("EcmaVm_054_Test") { sources = [ # test file + "heap_helper_test.cpp", "machine_code_test.cpp", ] diff --git a/ecmascript/tests/barrier_test.cpp b/ecmascript/tests/barrier_test.cpp index dff784719480290fa00880126d44a454209bed60..6ec1b1e85b6d4d34fc8accdf9583d67f9ae3b665 100644 --- a/ecmascript/tests/barrier_test.cpp +++ b/ecmascript/tests/barrier_test.cpp @@ -49,7 +49,7 @@ HWTEST_F_L0(BarrierTest, YoungToYoungBatchCopy) JSTaggedValue* to = reinterpret_cast(ToUintPtr(dstArray->GetData())); JSTaggedValue* from = reinterpret_cast(ToUintPtr(srcArray->GetData())); - Barriers::CopyObject(thread, to, from, arrayLength); + Barriers::CopyObject(thread, *dstArray, to, from, arrayLength); // young to young, all the bitset should not be changed. dstRegion->IterateAllNewToEdenBits([&NewToEdenBeforeCopy](void* mem) { @@ -112,7 +112,7 @@ HWTEST_F_L0(BarrierTest, BatchCopyNoBarrier) JSTaggedValue* to2 = reinterpret_cast(ToUintPtr(dstArray2->GetData())); JSTaggedValue* from2 = reinterpret_cast(ToUintPtr(srcArray->GetData())); // barrier should also work for no heap value - Barriers::CopyObject(thread, to2, from2, arrayLength); + Barriers::CopyObject(thread, *dstArray, to2, from2, arrayLength); // check for (uint32_t i = 0; i < arrayLength; i++) { EXPECT_EQ(dstArray2->Get(thread, i), srcArray->Get(thread, i)); @@ -146,7 +146,7 @@ HWTEST_F_L0(BarrierTest, LocalToShareBatchCopy) JSTaggedValue* to = reinterpret_cast(ToUintPtr(dstArray->GetData())); JSTaggedValue* from = reinterpret_cast(ToUintPtr(srcArray->GetData())); - Barriers::CopyObject(thread, to, from, arrayLength); + Barriers::CopyObject(thread, *dstArray, to, from, arrayLength); std::set LocalToShareSlot; for (uint32_t i = 0; i < arrayLength; i++) { @@ -202,7 +202,7 @@ HWTEST_F_L0(BarrierTest, LocalToReadOnlyShareBatchCopy) JSTaggedValue* to = reinterpret_cast(ToUintPtr(dstArray->GetData())); JSTaggedValue* from = reinterpret_cast(ToUintPtr(srcArray->GetData())); - Barriers::CopyObject(thread, to, from, arrayLength); + Barriers::CopyObject(thread, *dstArray, to, from, arrayLength); std::set LocalToShareSlot; for (uint32_t i = 0; i < arrayLength; i++) { @@ -256,7 +256,7 @@ HWTEST_F_L0(BarrierTest, LocalToShareMixBatchCopy) JSTaggedValue* to = reinterpret_cast(ToUintPtr(dstArray->GetData())); JSTaggedValue* from = reinterpret_cast(ToUintPtr(srcArray->GetData())); - Barriers::CopyObject(thread, to, from, arrayLength); + Barriers::CopyObject(thread, *dstArray, to, from, arrayLength); std::set LocalToShareSlot; for (uint32_t i = 0; i < arrayLength; i++) { @@ -324,7 +324,7 @@ HWTEST_F_L0(BarrierTest, OldToNewBatchCopy) JSTaggedValue* to = reinterpret_cast(ToUintPtr(dstArray->GetData())); JSTaggedValue* from = reinterpret_cast(ToUintPtr(srcArray->GetData())); - Barriers::CopyObject(thread, to, from, arrayLength); + Barriers::CopyObject(thread, *dstArray, to, from, arrayLength); // young to young, all the bitset should not be changed. dstRegion->IterateAllNewToEdenBits([&OldToNewSlot, &OldToNewBeforeCopy, &dstArray, arrayLength](void* mem) { diff --git a/ecmascript/tests/dump_test.cpp b/ecmascript/tests/dump_test.cpp index ea2e26b654b5915abc85d91aa53a9172de799365..0ee4f46ebf359c05ef3ae7a0129732a7ffde1091 100644 --- a/ecmascript/tests/dump_test.cpp +++ b/ecmascript/tests/dump_test.cpp @@ -1081,9 +1081,9 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump) break; } case JSType::STORE_TS_HANDLER: { - CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), StoreTSHandler::SIZE, 3U); - JSHandle storeTSHandler = factory->NewStoreTSHandler(); - DUMP_FOR_HANDLE(storeTSHandler); + CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), StoreAOTHandler::SIZE, 3U); + JSHandle storeAOTHandler = factory->NewStoreAOTHandler(); + DUMP_FOR_HANDLE(storeAOTHandler); break; } case JSType::PROPERTY_BOX: { diff --git a/ecmascript/tests/ecma_context_test.cpp b/ecmascript/tests/ecma_context_test.cpp index 9b1e67449c55720029f352b64a9b241a46937b38..0b5e4507bf5ba0947a6a81ffd5b3dfee6f28d140 100644 --- a/ecmascript/tests/ecma_context_test.cpp +++ b/ecmascript/tests/ecma_context_test.cpp @@ -18,6 +18,9 @@ #include "ecmascript/object_factory.h" #include "ecmascript/tests/test_helper.h" #include "ecmascript/global_env.h" +#include "ecmascript/js_primitive_ref.h" +#include "ecmascript/js_symbol.h" +#include "ecmascript/js_tagged_value-inl.h" using namespace panda::ecmascript; using namespace panda::ecmascript::base; @@ -82,4 +85,55 @@ HWTEST_F_L0(EcmaContextTest, SwitchCurrentContext) EXPECT_EQ(contextVector.size(), 2); // 3: size of contexts. EcmaContext::CheckAndDestroy(thread, context1); } + +HWTEST_F_L0(EcmaContextTest, CStringTest001) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle testString = factory->NewFromASCII("bar2bazJavaScriptbaz"); + CString str = ConvertToString(EcmaString::Cast(testString.GetObject()), + StringConvertedUsage::LOGICOPERATION, false); + EXPECT_EQ(str, CString("bar2bazJavaScriptbaz")); +} + +HWTEST_F_L0(EcmaContextTest, CStringTest002) +{ + CString str = ConvertToString(nullptr, StringConvertedUsage::LOGICOPERATION, false); + EXPECT_EQ(str, CString("")); +} + +HWTEST_F_L0(EcmaContextTest, CStringTest003) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle testString = factory->NewFromASCII("test"); + EcmaString *ecmaString = EcmaString::Cast(testString.GetObject()); + JSTaggedValue key = JSTaggedValue(ecmaString); + CString str = ConvertToString(key); + EXPECT_EQ(str, CString("test")); +} + +HWTEST_F_L0(EcmaContextTest, CStringTest004) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle symbol = factory->NewPublicSymbolWithChar("bbb"); + JSHandle value5(symbol); + JSTaggedValue key = + JSTaggedValue(JSHandle::Cast(JSTaggedValue::ToObject(thread, value5))->GetValue()); + CString str = ConvertToString(key); + EXPECT_EQ(str, CString("bbb")); +} + +HWTEST_F_L0(EcmaContextTest, CStringTest005) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle symbol = factory->NewPublicSymbolWithChar(""); + symbol->SetDescription(thread, JSTaggedValue::Undefined()); + symbol->SetFlags(0); + symbol->SetHashField(0); + JSHandle value5(symbol); + JSTaggedValue key = + JSTaggedValue(JSHandle::Cast(JSTaggedValue::ToObject(thread, value5))->GetValue()); + CString str = ConvertToString(key); + EXPECT_EQ(str, CString("Symbol()")); +} + } // namespace panda::test \ No newline at end of file diff --git a/ecmascript/tests/ecma_string_accessor_test.cpp b/ecmascript/tests/ecma_string_accessor_test.cpp index d86da56c32263bfaa3e973b85bc713008b1f0164..f9cef98aac0520695980a60f835823685356341e 100644 --- a/ecmascript/tests/ecma_string_accessor_test.cpp +++ b/ecmascript/tests/ecma_string_accessor_test.cpp @@ -518,6 +518,13 @@ HWTEST_F_L0(EcmaStringAccessorTest, WriteToFlatUtf8) EXPECT_EQ(arrayU8CompCopyTo[i], arrayU16CompCopyFrom[i]); } EXPECT_EQ(arrayU8CompCopyTo[lengthReturnU16Comp - 1], 0U); + + uint8_t buffer[200] = {0}; + std::string str( + "您订单尾号为:1442的车辆提车点已由重庆市渝北区龙兴镇新能源办公大楼变更为重庆市江北区鱼嘴镇永和路39号2屋208室,请携带好相关材料按照预约时间前往提车点提车2,如有296ss"); + JSHandle ecmaStr = thread->GetEcmaVM()->GetFactory()->NewFromStdString(str); + uint32_t len = EcmaStringAccessor(ecmaStr).WriteToFlatUtf8(buffer, 198, true); + EXPECT_EQ(len, 197); } /* diff --git a/ecmascript/tests/ecma_vm_test.cpp b/ecmascript/tests/ecma_vm_test.cpp index 60155b5bfa37833875b16edd916e1d705d6e4567..126cabacb06dde33802b04c83c0fc60acaaed0dc 100644 --- a/ecmascript/tests/ecma_vm_test.cpp +++ b/ecmascript/tests/ecma_vm_test.cpp @@ -90,4 +90,16 @@ HWTEST_F_L0(EcmaVMTest, CreateEcmaVMInTwoWays) t1.join(); JSNApi::DestroyJSVM(ecmaVm1); } + +HWTEST_F_L0(EcmaVMTest, DumpExceptionObject) +{ + RuntimeOption option; + option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); + EcmaVM *ecmaVm = JSNApi::CreateJSVM(option); + auto thread = ecmaVm->GetJSThread(); + int arkProperties = thread->GetEcmaVM()->GetJSOptions().GetArkProperties(); + ecmaVm->GetJSOptions().SetArkProperties(arkProperties | ArkProperties::EXCEPTION_BACKTRACE); + EXPECT_TRUE(ecmaVm->GetJSOptions().EnableExceptionBacktrace()); + JSNApi::DestroyJSVM(ecmaVm); +} } // namespace panda::ecmascript diff --git a/ecmascript/tests/gc_first_test.cpp b/ecmascript/tests/gc_first_test.cpp index 81c661ace5959a4a1281b3fe232afa65d8b973f4..1a7dadb8291e3e7f4cb77f47c0dd13d5ff277153 100644 --- a/ecmascript/tests/gc_first_test.cpp +++ b/ecmascript/tests/gc_first_test.cpp @@ -313,73 +313,4 @@ HWTEST_F_L0(GCTest, Destroy) heap = nullptr; }; -HWTEST_F_L0(GCTest, WeakRefTest) -{ - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - std::vector> srcArrayHandleRecord; - std::vector> dstOldArrayHandleRecord; - std::vector> dstNewArrayHandleRecord; - for (int i = 0; i < 1024; i++) { - JSHandle arrayHandle = factory->NewTaggedArray(64, JSTaggedValue::True(), - MemSpaceType::OLD_SPACE); - srcArrayHandleRecord.emplace_back(arrayHandle); - } - for (int i = 0; i < 1024; i++) { - JSHandle arrayHandle = factory->NewTaggedArray(128, JSTaggedValue::True(), - MemSpaceType::OLD_SPACE); - dstOldArrayHandleRecord.emplace_back(arrayHandle); - } - for (int i = 0; i < 1024; i++) { - JSHandle arrayHandle = factory->NewTaggedArray(128, JSTaggedValue::True(), - MemSpaceType::SEMI_SPACE); - dstNewArrayHandleRecord.emplace_back(arrayHandle); - } - for (auto it : srcArrayHandleRecord) { - uint32_t countIndex = 0; - std::random_device randomDevice; - std::shuffle(dstOldArrayHandleRecord.begin(), dstOldArrayHandleRecord.end(), std::mt19937(randomDevice())); - for (auto it2 : dstOldArrayHandleRecord) { - if (Region::ObjectAddressToRange(it2.GetTaggedValue().GetTaggedObject())->InGeneralOldSpace()) { - JSTaggedValue valueWeak = it2.GetTaggedValue().CreateAndGetWeakRef(); - it->Set(thread, countIndex, valueWeak); - if (++countIndex >= 40) { - break; - } - } - } - } - auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); - heap->SetMarkType(MarkType::MARK_FULL); - auto concurrentMarker = heap->GetConcurrentMarker(); - concurrentMarker->Mark(); - std::this_thread::sleep_for(std::chrono::seconds(5)); - for (auto it : srcArrayHandleRecord) { - uint32_t countIndex = 0; - std::random_device randomDevice; - std::shuffle(dstNewArrayHandleRecord.begin(), dstNewArrayHandleRecord.end(), std::mt19937(randomDevice())); - for (auto it2 : dstNewArrayHandleRecord) { - if (Region::ObjectAddressToRange(it2.GetTaggedValue().GetTaggedObject())->InGeneralNewSpace()) { - JSTaggedValue valueWeak = it2.GetTaggedValue().CreateAndGetWeakRef(); - it->Set(thread, countIndex, valueWeak); - if (++countIndex >= 40) { - break; - } - } - } - } - auto partialGc = heap->GetPartialGC(); - partialGc->RunPhases(); - for (auto it : dstOldArrayHandleRecord) { - EXPECT_TRUE(it.GetTaggedValue() != JSTaggedValue::Undefined()); - } - for (auto it : dstNewArrayHandleRecord) { - EXPECT_TRUE(it.GetTaggedValue() != JSTaggedValue::Undefined()); - } - for (auto it : srcArrayHandleRecord) { - for (uint32_t i = 0; i < 40; i++) { - EXPECT_TRUE(it->Get(i) != JSTaggedValue::Undefined()); - } - } -} - } // namespace panda::test diff --git a/ecmascript/tests/gc_second_test.cpp b/ecmascript/tests/gc_second_test.cpp index c582dbf892bd05c510cc6abe919da8ca5aa06fd5..762d9ccde2081440d53f096756c7e084bec3a127 100644 --- a/ecmascript/tests/gc_second_test.cpp +++ b/ecmascript/tests/gc_second_test.cpp @@ -29,6 +29,7 @@ #include "ecmascript/mem/shared_mem_controller.h" #include "ecmascript/mem/mem_controller_utils.h" #include "ecmascript/mem/mem_controller.h" +#include "ecmascript/mem/incremental_marker.h" using namespace panda; @@ -307,7 +308,7 @@ HWTEST_F_L0(GCTest, AdjustCapacity) size = space->GetSurvivalObjectSize() / GROW_OBJECT_SURVIVAL_RATE - 1; size_t oldMaxCapacity = space->GetMaximumCapacity(); space->SetMaximumCapacity(space->GetInitialCapacity()); - EXPECT_FALSE(space->AdjustCapacity(size, thread)); + EXPECT_TRUE(space->AdjustCapacity(size, thread)); space->SetMaximumCapacity(oldMaxCapacity); EXPECT_TRUE(space->AdjustCapacity(size, thread)); #endif @@ -468,4 +469,84 @@ HWTEST_F_L0(GCTest, RecordAllocationForIdleTest003) controller->RecordAllocationForIdle(); } +HWTEST_F_L0(GCTest, TryTriggerIdleCollectionTest001) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->SetIdleTask(IdleTaskType::YOUNG_GC); + heap->TryTriggerIdleCollection(); +} + +HWTEST_F_L0(GCTest, WaitAllTasksFinishedTest001) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->GetJSThread()->SetMarkStatus(MarkStatus::MARKING); + heap->WaitAllTasksFinished(); +} + +HWTEST_F_L0(GCTest, WaitAllTasksFinishedTest002) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->GetJSThread()->SetMarkStatus(MarkStatus::MARKING); + heap->GetConcurrentMarker()->Mark(); + heap->WaitAllTasksFinished(); +} + +HWTEST_F_L0(GCTest, ChangeGCParamsTest001) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->GetOldSpace()->IncreaseLiveObjectSize(2098000); + heap->ChangeGCParams(true); +} + +HWTEST_F_L0(GCTest, ChangeGCParamsTest002) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->GetOldSpace()->IncreaseLiveObjectSize(2098000); + heap->GetOldSpace()->IncreaseCommitted(31457300); + heap->ChangeGCParams(true); +} + +HWTEST_F_L0(GCTest, ChangeGCParamsTest003) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + auto sHeap = SharedHeap::GetInstance(); + sHeap->GetOldSpace()->IncreaseLiveObjectSize(2098000); + heap->ChangeGCParams(true); +} + +HWTEST_F_L0(GCTest, ChangeGCParamsTest004) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->SetMemGrowingType(MemGrowingType::HIGH_THROUGHPUT); + heap->ChangeGCParams(true); +} + +HWTEST_F_L0(GCTest, IncrementMarkerTest001) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->GetIncrementalMarker()->TriggerIncrementalMark(100); + heap->GetIncrementalMarker()->TriggerIncrementalMark(100); +} + +HWTEST_F_L0(GCTest, IncrementMarkerTest002) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->GetIncrementalMarker()->TriggerIncrementalMark(0); +} + +HWTEST_F_L0(GCTest, IncrementMarkerTest003) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->GetIncrementalMarker()->SetMarkingFinished(true); + heap->GetIncrementalMarker()->TriggerIncrementalMark(100); +} + +HWTEST_F_L0(GCTest, IncrementMarkerTest004) +{ + thread->GetEcmaVM()->GetJSOptions().SetArkProperties(0); + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->GetIncrementalMarker()->SetMarkingFinished(true); + heap->GetIncrementalMarker()->TriggerIncrementalMark(100); +} + } // namespace panda::test diff --git a/ecmascript/tests/gc_third_test.cpp b/ecmascript/tests/gc_third_test.cpp index 96086c368a9d1812d870334382a08af3ab4ac2fb..7c30bad47189fe09a7923b218e67771b528fdff7 100644 --- a/ecmascript/tests/gc_third_test.cpp +++ b/ecmascript/tests/gc_third_test.cpp @@ -92,13 +92,10 @@ HWTEST_F_L0(GCTest, ArkToolsHintGC) } { #ifdef NDEBUG - size_t originSize = heap->GetCommittedSize(); size_t newSize = 0; size_t finalSize = 0; bool res = getSizeAfterCreateAndCallHintGC(newSize, finalSize); EXPECT_TRUE(res); - EXPECT_TRUE(newSize > originSize); - EXPECT_TRUE(finalSize < newSize); #endif } } @@ -111,27 +108,29 @@ HWTEST_F_L0(GCTest, LargeOverShootSizeTest) EXPECT_FALSE(heap->GetNewSpace()->CommittedSizeIsLarge()); heap->GetConcurrentMarker()->ConfigConcurrentMark(false); heap->NotifyHighSensitive(true); + size_t originalCapacity = heap->GetNewSpace()->GetInitialCapacity(); + size_t originalOverShootSize = heap->GetNewSpace()->GetOvershootSize(); { [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread); - for (int i = 0; i < 500; i++) { + for (int i = 0; i < 300; i++) { [[maybe_unused]] JSHandle array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray( 10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE); } - } - size_t newYoungSize = heap->GetNewSpace()->GetCommittedSize(); - size_t originalOverShootSize = heap->GetNewSpace()->GetOvershootSize(); - EXPECT_TRUE(heap->GetNewSpace()->CommittedSizeIsLarge()); - EXPECT_TRUE(originalYoungSize < newYoungSize); - - heap->NotifyHighSensitive(false); - heap->CollectGarbage(TriggerGCType::YOUNG_GC); - newYoungSize = heap->GetNewSpace()->GetCommittedSize(); - size_t newOverShootSize = heap->GetNewSpace()->GetOvershootSize(); - - EXPECT_TRUE(originalYoungSize < newYoungSize); - EXPECT_TRUE(originalOverShootSize < newOverShootSize); - EXPECT_TRUE(0 < newOverShootSize); + size_t newYoungSize = heap->GetNewSpace()->GetCommittedSize(); + EXPECT_TRUE(originalYoungSize < newYoungSize); + heap->NotifyHighSensitive(false); + heap->CollectGarbage(TriggerGCType::YOUNG_GC); + newYoungSize = heap->GetNewSpace()->GetCommittedSize(); + size_t newOverShootSize = heap->GetNewSpace()->GetOvershootSize(); + size_t newCapacity = heap->GetNewSpace()->GetInitialCapacity(); + EXPECT_TRUE(originalYoungSize < newYoungSize); + EXPECT_TRUE(originalOverShootSize < newOverShootSize); + EXPECT_TRUE(0 < newOverShootSize); + EXPECT_TRUE(originalCapacity < newCapacity); + EXPECT_TRUE(heap->GetNewSpace()->GetMaximumCapacity() == newCapacity); + } + originalOverShootSize = heap->GetNewSpace()->GetOvershootSize(); { [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread); for (int i = 0; i < 2049; i++) { @@ -737,13 +736,4 @@ HWTEST_F_L0(GCTest, InvokeAllocationInspectorTest001) counter->InvokeAllocationInspector(10000, 100, 100); } -HWTEST_F_L0(GCTest, AddGCStatsToKeyTest001) -{ - auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); - auto stats = new GCKeyStats(heap); - for (size_t i = 0; i < 200; i++) { - stats->AddGCStatsToKey(); - } -} - } // namespace panda::test diff --git a/ecmascript/tests/heap_helper_test.cpp b/ecmascript/tests/heap_helper_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4aa131a0467c6764558940990a414c2b05d7769 --- /dev/null +++ b/ecmascript/tests/heap_helper_test.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ecmascript/mem/heap.h" +#include "ecmascript/mem/incremental_marker.h" +#include "ecmascript/mem/concurrent_marker.h" +#include "ecmascript/mem/mem_controller.h" +#include "ecmascript/tests/ecma_test_common.h" + +using namespace panda::ecmascript; + +namespace panda::test { + +class HeapTest : public BaseTestWithScope { +public: + void SetUp() override + { + JSRuntimeOptions options; + instance = JSNApi::CreateEcmaVM(options); + ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM"; + thread = instance->GetJSThread(); + thread->ManagedCodeBegin(); + } +}; + +class HeapTestHelper { +public: + explicit HeapTestHelper(Heap *heap) : heap_(heap) {} + + ~HeapTestHelper() = default; + + void SetIdleGCState(bool flag) + { + ASSERT_NE(heap_, nullptr); + heap_->enableIdleGC_ = flag; + } + + Heap *GetHeap() + { + return heap_; + } + +private: + Heap *heap_{nullptr}; +}; + +HWTEST_F_L0(HeapTest, TryTriggerIdleCollectionTest001) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + auto helper = new HeapTestHelper(heap); + helper->SetIdleGCState(true); + helper->GetHeap()->SetIdleTask(IdleTaskType::NO_TASK); + helper->GetHeap()->GetJSThread()->SetMarkStatus(MarkStatus::READY_TO_MARK); + helper->GetHeap()->CollectGarbage(TriggerGCType::EDEN_GC, GCReason::TRIGGER_BY_TASKPOOL); + helper->GetHeap()->TryTriggerIdleCollection(); +} + +HWTEST_F_L0(HeapTest, TryTriggerIncrementalMarkingTest001) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + auto helper = new HeapTestHelper(heap); + helper->SetIdleGCState(true); + helper->GetHeap()->SetIdleTask(IdleTaskType::NO_TASK); + helper->GetHeap()->GetJSThread()->SetMarkStatus(MarkStatus::READY_TO_MARK); + helper->GetHeap()->CollectGarbage(TriggerGCType::EDEN_GC, GCReason::TRIGGER_BY_TASKPOOL); + helper->GetHeap()->TryTriggerIncrementalMarking(); +} + +HWTEST_F_L0(HeapTest, TryTriggerIncrementalMarkingTest002) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + auto helper = new HeapTestHelper(heap); + helper->SetIdleGCState(true); + helper->GetHeap()->GetOldSpace()->IncreaseLiveObjectSize(467664896); + helper->GetHeap()->SetIdleTask(IdleTaskType::NO_TASK); + helper->GetHeap()->GetJSThread()->SetMarkStatus(MarkStatus::READY_TO_MARK); + helper->GetHeap()->CollectGarbage(TriggerGCType::EDEN_GC, GCReason::TRIGGER_BY_TASKPOOL); + helper->GetHeap()->TryTriggerIncrementalMarking(); +} + +} \ No newline at end of file diff --git a/ecmascript/tests/js_forin_iterator_test.cpp b/ecmascript/tests/js_forin_iterator_test.cpp index d2e875f05ad01bfbcc55a6cbbce3e9438a41b0bb..a09c5c9a9ccfd8e88b837d23bc42fc18362254f3 100644 --- a/ecmascript/tests/js_forin_iterator_test.cpp +++ b/ecmascript/tests/js_forin_iterator_test.cpp @@ -62,4 +62,14 @@ HWTEST_F_L0(JSForinIteratorTest, Create) JSTaggedValue n4 = JSForInIterator::NextInternal(thread, it); EXPECT_EQ(n4, JSTaggedValue::Undefined()); } + +HWTEST_F_L0(JSForinIteratorTest, ForinNativePointer) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + int pointArr[10]; + auto *nativePointer = pointArr; + JSHandle pointer = factory->NewJSNativePointer(nativePointer); + JSHandle it = JSObject::EnumerateObjectProperties(thread, JSHandle(pointer)); + EXPECT_EQ(it->GetLength(), 0); +} } // namespace panda::test diff --git a/ecmascript/tests/js_map_test.cpp b/ecmascript/tests/js_map_test.cpp index bb2b9a8f97d1e678411447db2e5cdfd75d77f5b9..55b73f8e234b0a9b28fcdbafb7801c95d895173b 100644 --- a/ecmascript/tests/js_map_test.cpp +++ b/ecmascript/tests/js_map_test.cpp @@ -91,6 +91,73 @@ HWTEST_F_L0(JSMapTest, DeleteAndGet) EXPECT_EQ(map->GetSize(), 39); } +HWTEST_F_L0(JSMapTest, DeleteAndGet2) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + // create jsMap + JSHandle map(thread, CreateMap()); + JSHandle mapvalue(map); + JSHandle taggedArray = factory->NewTaggedArray(10); + int pointArr[10]; + for (uint32_t i = 0; i < 10; i++) { + JSHandle obj = factory->NewEmptyJSObject(0); + auto *nativePointer = pointArr + i; + JSHandle pointer = factory->NewJSNativePointer(nativePointer); + Barriers::SetObject(thread, *obj, ECMAObject::HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); + taggedArray->Set(thread, i, obj); + } + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC); + JSHandle setfunc = + JSObject::GetProperty(thread, mapvalue, thread->GlobalConstants()->GetHandledSetString()).GetValue(); + JSHandle getfunc = thread->GlobalConstants()->GetHandledMapGet(); + JSHandle deletefunc = thread->GlobalConstants()->GetHandledMapDelete(); + + for (int i = 0; i < 10; i++) { + JSHandle key(thread, taggedArray->Get(i)); + JSHandle value(thread, JSTaggedValue(i)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + ecmaRuntimeCallInfo->SetFunction(setfunc.GetTaggedValue()); + ecmaRuntimeCallInfo->SetThis(map.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(key.GetTaggedValue(), value.GetTaggedValue()); + auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); + JSFunction::Call(ecmaRuntimeCallInfo); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue hashField = + JSTaggedValue(Barriers::GetValue(key->GetTaggedObject(), ECMAObject::HASH_OFFSET)); + EXPECT_TRUE(hashField.IsTaggedArray()); + } + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC); + for (int i = 0; i < 10; i++) { + JSHandle key(thread, taggedArray->Get(i)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(getfunc.GetTaggedValue()); + ecmaRuntimeCallInfo->SetThis(map.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(key.GetTaggedValue()); + auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); + auto res = JSFunction::Call(ecmaRuntimeCallInfo); + EXPECT_TRUE(res.GetInt() == i); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue hashField = + JSTaggedValue(Barriers::GetValue(key->GetTaggedObject(), ECMAObject::HASH_OFFSET)); + EXPECT_TRUE(hashField.IsTaggedArray()); + } + thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC); + for (int i = 0; i < 10; i++) { + JSHandle key(thread, taggedArray->Get(i)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(deletefunc.GetTaggedValue()); + ecmaRuntimeCallInfo->SetThis(map.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(key.GetTaggedValue()); + auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); + auto res = JSFunction::Call(ecmaRuntimeCallInfo); + EXPECT_TRUE(res.IsTrue()); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue hashField = + JSTaggedValue(Barriers::GetValue(key->GetTaggedObject(), ECMAObject::HASH_OFFSET)); + EXPECT_TRUE(hashField.IsTaggedArray()); + } +} + HWTEST_F_L0(JSMapTest, Iterator) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); diff --git a/ecmascript/tests/js_object_test.cpp b/ecmascript/tests/js_object_test.cpp index ac3d91171cf1acda0caee3bbc61277b52949f62a..4e71947811a1d91f530d7f63039fba4fc3c942a4 100644 --- a/ecmascript/tests/js_object_test.cpp +++ b/ecmascript/tests/js_object_test.cpp @@ -343,7 +343,7 @@ HWTEST_F_L0(JSObjectTest, HasProperty) EXPECT_FALSE(flag); } -HWTEST_F_L0(JSObjectTest, HasPropertyWithProtoType) +HWTEST_F_L0(JSObjectTest, HasPropertyWithPrototype) { JSHandle nullHandle(thread, JSTaggedValue::Null()); JSHandle grandfather = JSObject::ObjectCreate(thread, nullHandle); @@ -1255,9 +1255,9 @@ HWTEST_F_L0(JSObjectTest, NativePointerField) ECMAObject::SetHash(thread, 87, JSHandle::Cast(obj)); EXPECT_TRUE(obj->GetHash() == 87); - obj->SetNativePointerFieldCount(thread, 1); + ECMAObject::SetNativePointerFieldCount(thread, obj, 1); char array[] = "Hello World!"; - obj->SetNativePointerField(thread, 0, array, nullptr, nullptr); + ECMAObject::SetNativePointerField(thread, obj, 0, array, nullptr, nullptr); int32_t count = obj->GetNativePointerFieldCount(); EXPECT_TRUE(count == 1); void *pointer = obj->GetNativePointerField(0); diff --git a/ecmascript/tests/js_stable_array_test.cpp b/ecmascript/tests/js_stable_array_test.cpp index f29302becf6b2160d085a1eeae5e142443c04534..b5295b1daaf1c3fe55328b05b0bd50d26d575a38 100644 --- a/ecmascript/tests/js_stable_array_test.cpp +++ b/ecmascript/tests/js_stable_array_test.cpp @@ -37,20 +37,32 @@ enum class StableArrayIndex { namespace panda::test { class JSStableArrayTest : public BaseTestWithScope { public: - JSHandle CallJoin(JSHandle handleTagArr, std::string& sep, int64_t lengthArr) const + JSHandle CallJoin(JSHandle handleTagArr, JSTaggedValue sepValue) const { - ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory(); JSHandle handleArr(JSArray::CreateArrayFromList(thread, handleTagArr)); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); - ecmaRuntimeCallInfo->SetCallArg(0, - JSHandle::Cast(objFactory->NewFromStdString(sep)).GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(0, sepValue); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); JSHandle handleTagValEcmaStrRet(thread, JSStableArray::Join(handleArr, ecmaRuntimeCallInfo)); TestHelper::TearDownFrame(thread, prev); return handleTagValEcmaStrRet; } + + // tests for sep is Undefined + JSHandle CallJoin(JSHandle handleTagArr, int64_t lengthArr) const + { + JSTaggedValue sepValue = JSTaggedValue::Undefined(); + return CallJoin(handleTagArr, sepValue); + } + + JSHandle CallJoin(JSHandle handleTagArr, std::string& sep, int64_t lengthArr) const + { + ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory(); + JSTaggedValue sepValue = JSHandle::Cast(objFactory->NewFromStdString(sep)).GetTaggedValue(); + return CallJoin(handleTagArr, sepValue); + } }; /** @@ -501,6 +513,178 @@ HWTEST_F_L0(JSStableArrayTest, Join_StringElements_LargeString3) EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString()); } +/** + * @tc.name: Join_StringElements_Stack + * @tc.desc: Use stack to store the preprocessed elements of the source Array. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSStableArrayTest, Join_StringElements_Stack) +{ + int32_t lengthArr = 32; + // tiny string join should not use tree string. + ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleTagArr(objFactory->NewTaggedArray(lengthArr)); + JSHandle handleTagValElementEcmaStr(objFactory->NewFromStdString("a")); + for (int i = 0; i < lengthArr; i++) { + handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue()); + } + // sep is Undefined + JSHandle handleTagValEcmaStrRet = CallJoin(handleTagArr, lengthArr); + JSHandle handleEcmaStrRet(handleTagValEcmaStrRet); + // 32 x a + EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), + "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a"); + EXPECT_FALSE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString()); +} + +/** + * @tc.name: Join_StringElements_Stack1 + * @tc.desc: Use stack to store the preprocessed elements of the source Array. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSStableArrayTest, Join_StringElements_Stack1) +{ + int32_t lengthArr = 4; + // large string should use tree string. + ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleTagArr(objFactory->NewTaggedArray(lengthArr)); + // 64 x a + JSHandle handleTagValElementEcmaStr( + objFactory->NewFromStdString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); + for (int i = 0; i < lengthArr; i++) { + handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue()); + } + // sep is Undefined + JSHandle handleTagValEcmaStrRet = CallJoin(handleTagArr, lengthArr); + JSHandle handleEcmaStrRet(handleTagValEcmaStrRet); + EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa," + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa," + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa," + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString()); +} + +/** + * @tc.name: Join_StringElements_Vector + * @tc.desc: Use vector to store the preprocessed elements of the source Array. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSStableArrayTest, Join_StringElements_Vector) +{ + int32_t lengthArr = 128; + // tiny string join should not use tree string. + ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleTagArr(objFactory->NewTaggedArray(lengthArr)); + JSHandle handleTagValElementEcmaStr(objFactory->NewFromStdString("a")); + for (int i = 0; i < lengthArr; i++) { + handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue()); + } + // sep is Undefined + JSHandle handleTagValEcmaStrRet = CallJoin(handleTagArr, lengthArr); + JSHandle handleEcmaStrRet(handleTagValEcmaStrRet); + // 128 x a + EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), + "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a," + "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a," + "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a," + "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a"); + EXPECT_FALSE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString()); +} + +/** + * @tc.name: Join_StringElements_Vector1 + * @tc.desc: Use vector to store the preprocessed elements of the source Array. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSStableArrayTest, Join_StringElements_Vector1) +{ + int32_t lengthArr = 65; + std::string sep = ""; + // large string should use tree string. + ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleTagArr(objFactory->NewTaggedArray(lengthArr)); + // 40 x a + JSHandle handleTagValElementEcmaStr( + objFactory->NewFromStdString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); + for (int i = 0; i < lengthArr; i++) { + handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue()); + } + JSHandle handleTagValEcmaStrRet = CallJoin(handleTagArr, sep, lengthArr); + JSHandle handleEcmaStrRet(handleTagValEcmaStrRet); + EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString()); +} + /** * @tc.name: At * @tc.desc: Create a source Array whose elements are Numbers and an EcmaRuntimeCallInfo, define the first arg of the diff --git a/ecmascript/tests/layout_info_test.cpp b/ecmascript/tests/layout_info_test.cpp index 42086842890725cb3ae545255a11130c0448761f..ec0a0cb8f191785ebdc9ab1d7ab4d65b6d23f82d 100644 --- a/ecmascript/tests/layout_info_test.cpp +++ b/ecmascript/tests/layout_info_test.cpp @@ -117,7 +117,6 @@ void GetAllKeysCommon(JSThread *thread, bool enumKeys = false) PropertyAttributes defaultAttr = PropertyAttributes::Default(); JSHandle key3(factory->NewFromASCII("3")); - JSHandle objectHandle = factory->NewEmptyJSObject(); JSHandle keyArray = factory->NewTaggedArray(infoLength); JSHandle layoutInfoHandle = factory->CreateLayoutInfo(infoLength); EXPECT_TRUE(*layoutInfoHandle != nullptr); @@ -138,11 +137,11 @@ void GetAllKeysCommon(JSThread *thread, bool enumKeys = false) } if (enumKeys) { uint32_t keys = 0; - layoutInfoHandle->GetAllEnumKeys(thread, infoLength, 0, keyArray, &keys, objectHandle); // 0: offset + layoutInfoHandle->GetAllEnumKeys(thread, infoLength, 0, keyArray, &keys); // 0: offset EXPECT_EQ(keyArray->Get(0), key3.GetTaggedValue()); EXPECT_EQ(keys, 1U); } else { - layoutInfoHandle->GetAllKeys(thread, infoLength, 0, *keyArray, objectHandle); // 0: offset + layoutInfoHandle->GetAllKeys(thread, infoLength, 0, *keyArray); // 0: offset layoutInfoHandle->GetAllKeysForSerialization(infoLength, keyVector); EXPECT_EQ(keyArray->GetLength(), keyVector.size()); diff --git a/ecmascript/tests/mem_map_allocator_test.cpp b/ecmascript/tests/mem_map_allocator_test.cpp index 8e9938567ea36400c31fb121981c7f43d8443c3d..429ab9d9e69537f8dbe753dec3945958c55681dd 100644 --- a/ecmascript/tests/mem_map_allocator_test.cpp +++ b/ecmascript/tests/mem_map_allocator_test.cpp @@ -64,7 +64,7 @@ HWTEST_F_L0(MemMapAllocatorTest, GetMemOverflow) MemMap mem = MemMapAllocator::GetInstance()->Allocate(thread->GetThreadId(), 2048_MB, DEFAULT_REGION_SIZE, ToSpaceTypeName(space->GetSpaceType()), false, true, - Jit::GetInstance()->IsEnableJitFort()); + Jit::GetInstance()->IsEnableJitFort(), true); EXPECT_EQ(mem.GetSize(), 0_MB); } diff --git a/ecmascript/tests/test_helper.h b/ecmascript/tests/test_helper.h index 26c9b60d61e5eb3f28251bf5f5b0d1f385310899..580f6a3f1a479ddb61b9dc5d034f6d96cb84e94f 100644 --- a/ecmascript/tests/test_helper.h +++ b/ecmascript/tests/test_helper.h @@ -106,7 +106,8 @@ public: // If you want to call once create, you can refer to BuiltinsMathTest for detail. static void CreateEcmaVMWithScope(EcmaVM *&instance, JSThread *&thread, EcmaHandleScope *&scope, - bool tryLoadStubFile = false, bool useCInterpreter = false, bool startManagedCode = true) + bool tryLoadStubFile = false, bool useCInterpreter = false, bool startManagedCode = true, + bool enableFastJit = false) { JSRuntimeOptions options; options.SetEnableForceGC(true); @@ -116,6 +117,9 @@ public: if (useCInterpreter) { options.SetEnableAsmInterpreter(false); } + if (enableFastJit) { + options.SetEnableJIT(true); + } instance = JSNApi::CreateEcmaVM(options); instance->SetEnableForceGC(true); ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM"; diff --git a/ecmascript/tests/weak_ref_old_gc_test.cpp b/ecmascript/tests/weak_ref_old_gc_test.cpp index ba9b693842b513caae6ffb773bf694d9d5b22564..f0e56431fd8a0e398d4db5732b2dc00e7e4a586a 100644 --- a/ecmascript/tests/weak_ref_old_gc_test.cpp +++ b/ecmascript/tests/weak_ref_old_gc_test.cpp @@ -18,12 +18,28 @@ #include "ecmascript/js_handle.h" #include "ecmascript/object_factory.h" #include "ecmascript/tagged_array-inl.h" +#include "ecmascript/mem/concurrent_marker.h" +#include "ecmascript/mem/partial_gc.h" #include "ecmascript/tests/ecma_test_common.h" using namespace panda::ecmascript; namespace panda::test { class WeakRefOldGCTest : public BaseTestWithScope { +public: + void SetUp() override + { + JSRuntimeOptions options; + options.SetEnableEdenGC(true); + instance = JSNApi::CreateEcmaVM(options); + ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM"; + thread = instance->GetJSThread(); + thread->ManagedCodeBegin(); + scope = new EcmaHandleScope(thread); + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + heap->GetConcurrentMarker()->EnableConcurrentMarking(EnableConcurrentMarkType::ENABLE); + heap->GetSweeper()->EnableConcurrentSweep(EnableConcurrentSweepType::ENABLE); + } }; static JSObject *JSObjectTestCreate(JSThread *thread) @@ -98,4 +114,75 @@ HWTEST_F_L0(WeakRefOldGCTest, ObjectKeep) value.CreateWeakRef(); EXPECT_EQ(newObj1->GetElements(), value); } + +HWTEST_F_L0(WeakRefOldGCTest, WeakRefTest) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + std::vector> srcArrayHandleRecord; + std::vector> dstOldArrayHandleRecord; + std::vector> dstNewArrayHandleRecord; + for (int i = 0; i < 128; i++) { + JSHandle arrayHandle = factory->NewTaggedArray(64, JSTaggedValue::True(), + MemSpaceType::OLD_SPACE); + srcArrayHandleRecord.emplace_back(arrayHandle); + } + for (int i = 0; i < 128; i++) { + JSHandle arrayHandle = factory->NewTaggedArray(128, JSTaggedValue::True(), + MemSpaceType::OLD_SPACE); + dstOldArrayHandleRecord.emplace_back(arrayHandle); + } + for (int i = 0; i < 128; i++) { + JSHandle arrayHandle = factory->NewTaggedArray(128, JSTaggedValue::True(), + MemSpaceType::SEMI_SPACE); + dstNewArrayHandleRecord.emplace_back(arrayHandle); + } + for (auto it : srcArrayHandleRecord) { + uint32_t countIndex = 0; + std::random_device randomDevice; + std::shuffle(dstOldArrayHandleRecord.begin(), dstOldArrayHandleRecord.end(), std::mt19937(randomDevice())); + for (auto it2 : dstOldArrayHandleRecord) { + if (Region::ObjectAddressToRange(it2.GetTaggedValue().GetTaggedObject())->InGeneralOldSpace()) { + JSTaggedValue valueWeak = it2.GetTaggedValue().CreateAndGetWeakRef(); + it->Set(thread, countIndex, valueWeak); + if (++countIndex >= 40) { + break; + } + } + } + } + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + if (heap->CheckOngoingConcurrentMarking()) { + heap->GetConcurrentMarker()->Reset(); + } + heap->SetMarkType(MarkType::MARK_FULL); + heap->TriggerConcurrentMarking(); + std::this_thread::sleep_for(std::chrono::seconds(3)); + for (auto it : srcArrayHandleRecord) { + uint32_t countIndex = 0; + std::random_device randomDevice; + std::shuffle(dstNewArrayHandleRecord.begin(), dstNewArrayHandleRecord.end(), std::mt19937(randomDevice())); + for (auto it2 : dstNewArrayHandleRecord) { + if (Region::ObjectAddressToRange(it2.GetTaggedValue().GetTaggedObject())->InGeneralNewSpace()) { + JSTaggedValue valueWeak = it2.GetTaggedValue().CreateAndGetWeakRef(); + it->Set(thread, countIndex, valueWeak); + if (++countIndex >= 40) { + break; + } + } + } + } + auto partialGc = heap->GetPartialGC(); + partialGc->RunPhases(); + for (auto it : dstOldArrayHandleRecord) { + EXPECT_TRUE(it.GetTaggedValue() != JSTaggedValue::Undefined()); + } + for (auto it : dstNewArrayHandleRecord) { + EXPECT_TRUE(it.GetTaggedValue() != JSTaggedValue::Undefined()); + } + for (auto it : srcArrayHandleRecord) { + for (uint32_t i = 0; i < 40; i++) { + EXPECT_TRUE(it->Get(i) != JSTaggedValue::Undefined()); + } + } +} } // namespace panda::test diff --git a/js_runtime_config.gni b/js_runtime_config.gni index a5d38a29fd50bc93c63111905835f03d02408bc2..d4d73a4f71b092a6d337509c8d18c1f83f6f4e4f 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -40,6 +40,8 @@ declare_args() { is_qemu_runtime = false + disable_hilog = false + TARGET = "x86_64" HOST_ARCH = 64 @@ -117,8 +119,9 @@ sdk_libc_secshared_config = "$ark_third_party_root/bounds_checking_function:libsec_public_config" # ohos device, windows previewer, mac previewer -enable_hilog = !ark_standalone_build && !(defined(is_arkui_x) && is_arkui_x) && - (is_ohos || is_mingw || is_mac) && !is_qemu_runtime +enable_hilog = + !ark_standalone_build && !(defined(is_arkui_x) && is_arkui_x) && + (is_ohos || is_mingw || is_mac) && !is_qemu_runtime && !disable_hilog enable_hisysevent = !ark_standalone_build && !(defined(is_arkui_x) && is_arkui_x) && is_ohos && is_standard_system && !is_qemu_runtime diff --git a/libark_jsruntime.map b/libark_jsruntime.map index d9d3822ccde2c9ccff7b255a7b421c6d994a709d..a840014688ed757a2ec2356382d61f11332a446d 100644 --- a/libark_jsruntime.map +++ b/libark_jsruntime.map @@ -251,7 +251,8 @@ panda::ecmascript::MethodLiteral::ParseFunctionName*; panda::ecmascript::ModuleManager::GetRecordName*; panda::ecmascript::ModuleManager::HostGetImportedModule*; - panda::ecmascript::ModuleManager::HostResolveImportedModuleWithMerge*; + panda::ecmascript::ModuleResolver::HostResolveImportedModuleWithMerge*; + panda::ecmascript::ModuleResolver::ResolveImportedModuleWithMerge*; panda::ecmascript::ModuleManagerHelper::GetModuleValue*; panda::ecmascript::ModuleManagerHelper::GetNativeModuleValue*; panda::ecmascript::ModuleManagerHelper::GetModuleValueFromIndexBinding*; @@ -331,7 +332,6 @@ panda::ecmascript::kungfu::ArkStackMapBuilder::Run*; panda::ecmascript::kungfu::PGOBCInfo::Record*; panda::ecmascript::SharedModuleManager::GetInstance*; - panda::ecmascript::SharedModuleManager::ResolveImportedModuleWithMerge*; panda::ecmascript::SharedModuleManager::TransferSModule*; panda::ecmascript::kungfu::PGOTypeManager::GetConstantPoolIDByMethodOffset*; panda::ecmascript::kungfu::PGOTypeManager::GetConstantPoolByMethodOffset*; diff --git a/script/metadata_copy_for_test.py b/script/metadata_copy_for_test.py new file mode 100755 index 0000000000000000000000000000000000000000..c82303a92cb6c401f4dc4a6eb0af225f9e8b173c --- /dev/null +++ b/script/metadata_copy_for_test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2024 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Description: metadata.json generate +""" +import argparse +import os +from shutil import copyfile + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument('--metadata', + type=str, + required=True, + help='metadata folder path') + parser.add_argument('--outputs', + type=str, + required=True, + help='copy destination') + args = parser.parse_args() + return args + + +def copy_metadata(input_path, output_path): + if not os.path.exists(output_path): + os.makedirs(output_path, 0o777, True) + for file_name in os.listdir(input_path): + if os.path.isfile(os.path.join(input_path, file_name)) and file_name.endswith('.json'): + copyfile(os.path.join(input_path, file_name), os.path.join(output_path, file_name)) + + +if __name__ == '__main__': + arguments = parse_args() + copy_metadata(arguments.metadata, arguments.outputs) diff --git a/script/metadata_generate.py b/script/metadata_generate.py new file mode 100755 index 0000000000000000000000000000000000000000..e6b1291222c6ca669ec14baec1908287481c6e6b --- /dev/null +++ b/script/metadata_generate.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2024 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Description: metadata.json generate +""" + +import argparse +import os +import json + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument('--enum', + type=str, + required=True, + help='type_enum.json file path') + parser.add_argument('--metadata', + type=str, + required=True, + help='metadata folder path') + parser.add_argument('--output', + type=str, + required=True, + help='generated metadata.json file path') + parser.add_argument('--version', + type=str, + required=True, + help='version number') + args = parser.parse_args() + return args + + +def parse_type_enums(file_path): + with open(file_path, 'r') as f: + type_enums = json.load(f) + return type_enums["type_enum"] + + +def parse_type_list(dir_path): + type_list, type_layout = [], {} + for file_name in os.listdir(dir_path): + if not os.path.isfile(os.path.join(dir_path, file_name)) or not _is_metadata_file(file_name): + continue + with open(os.path.join(dir_path, file_name), 'r') as f: + metadata = json.load(f) + if file_name.endswith("_layout.json"): + type_layout["Dictionary_layout"] = metadata + elif file_name == "type_range.json": + type_layout["Type_range"] = metadata + else: + type_list.append(metadata) + return type_list, type_layout + + +def _is_metadata_file(file_name): + return file_name.endswith(".json") and file_name != "type_enums.json" + + +def generate_metadata_json(enum_list, metadata_list, type_layout, file_path, version): + metadata_dict = {"type_enum": enum_list, "type_list": [], "type_layout": type_layout, "version": version} + for metadata in metadata_list: + metadata_dict["type_list"].append(metadata) + with os.fdopen(os.open(file_path, os.O_RDWR | os.O_CREAT | os.O_TRUNC, 0o777), 'w+') as f: + json_str = json.dumps(metadata_dict) + f.write(json_str) + + +if __name__ == '__main__': + arguments = parse_args() + type_enum_list = parse_type_enums(arguments.enum) + type_metadata_list, type_layout_list = parse_type_list(arguments.metadata) + generate_metadata_json(type_enum_list, type_metadata_list, type_layout_list, arguments.output, arguments.version) diff --git a/test/aottest/BUILD.gn b/test/aottest/BUILD.gn index d17efd974dfd04654291250f9d66e310c0f76bd2..1d84e983842de90a3903662e37a9a49d10e8dd1f 100644 --- a/test/aottest/BUILD.gn +++ b/test/aottest/BUILD.gn @@ -91,6 +91,7 @@ group("ark_aot_ts_test") { "compiler_test", "constpool", "construct_deopt_frame_stack_overflow", + "construct_deopt_frame_stack_overflow2", "continue_from_finally", "copyrestargs", "createarray_meta_data", @@ -178,6 +179,7 @@ group("ark_aot_ts_test") { "isfalse", "isin", "isomorphism", + "isprototype", "istrue", "jsonstringify", "large_func", @@ -240,7 +242,6 @@ group("ark_aot_ts_test") { "pgo_forof_set", "pgo_forof_string", "pgo_forof_typed_array", - "pgo_force_ic", "pgo_function_prototype", "pgo_gettersetter", "pgo_extrainfomap_expand", @@ -258,6 +259,7 @@ group("ark_aot_ts_test") { "pgo_profiletypeinfo", "pgo_call_deopt_js", "pgo_call_recursive_js", + "pgo_storemiss", #"pgo_call_with_repetitive_method_id", "pgo_char_to_string_deopt", @@ -284,6 +286,7 @@ group("ark_aot_ts_test") { "stlettoglobalrecord", "stobjbyindex", "stobjbyname", + "stobjbyname1", "stobjbyvalue", "stownbyindex", "stownbyname", @@ -295,6 +298,7 @@ group("ark_aot_ts_test") { "string", "string_add", "string_equal", + "string_inline", "string_localecompare", "stsuperbyname", "sub", @@ -330,6 +334,7 @@ group("ark_aot_ts_test") { "unaryop_special_value", "useless_gate_elimination", "xor", + "sharedbitvector", "sharedcheck", "sharedarray", "sharedcollectionsexception", @@ -341,6 +346,7 @@ group("ark_aot_ts_test") { "sendablefunc", "sendablecontext", "createarraywithbuffer2", + "createarraywithbuffer3", "builtins_number", "builtins_number2", "builtins_parseint", @@ -353,6 +359,7 @@ group("ark_aot_ts_test") { "retype_isnan", "inline_abs", "retype_test", + "retype_test2", "retype_unreachable_test", ] diff --git a/test/aottest/builtin_inlining/Array/BUILD.gn b/test/aottest/builtin_inlining/Array/BUILD.gn index 0b87c852497cca064e1322091d7db59111d3a09f..7f83b523742589ef47e94cc19765af3138af9795 100644 --- a/test/aottest/builtin_inlining/Array/BUILD.gn +++ b/test/aottest/builtin_inlining/Array/BUILD.gn @@ -24,6 +24,7 @@ group("ark_aot_builtin_inlining_Array_test") { "IndexOf", "Keys", "Pop", + "Push", "PopProtoChange", "Values", ] diff --git a/test/aottest/builtin_inlining/Array/Filter/builtinArrayFilter.ts b/test/aottest/builtin_inlining/Array/Filter/builtinArrayFilter.ts index d5c3c010c1478526bdfb7921b73ba9dfd4ddd178..7495e18d0bf01bf087df61d0916486ebaf767089 100644 --- a/test/aottest/builtin_inlining/Array/Filter/builtinArrayFilter.ts +++ b/test/aottest/builtin_inlining/Array/Filter/builtinArrayFilter.ts @@ -155,8 +155,9 @@ function filterCase4() { } Object.setPrototypeOf(arr2, notArray) - //aot: [trace] Check Type: NotStableArray1 + //aot: [trace] aot inline builtin: Array.prototype.filter, caller function name:#*#filterCase4@builtinArrayFilter print(arr1.filter(x => x == 1)); //: 1 + //aot: [trace] aot inline function name: #*@3*#filter@builtinArrayFilter caller function name: #*#filterCase4@builtinArrayFilter //aot: [trace] aot inline function name: #*@3*#^1@builtinArrayFilter caller function name: #*@3*#filter@builtinArrayFilter print(arr2.filter(x => x == 1)); //: false } @@ -170,7 +171,7 @@ function filterCase5() { return x(1) } - //aot: [trace] Check Type: NotStableArray1 + //aot: [trace] aot inline function name: #*@4*#@builtinArrayFilter caller function name: #*#filterCase5@builtinArrayFilter //aot: [trace] aot inline function name: #*@4*#^1@builtinArrayFilter caller function name: #*@4*#@builtinArrayFilter print(arr1.filter(x => x == 1)); //: true } diff --git a/test/aottest/builtin_inlining/Array/FindFindIndex/builtinArrayFindFindIndex.ts b/test/aottest/builtin_inlining/Array/FindFindIndex/builtinArrayFindFindIndex.ts index 828c2fbbc03c56ab46d86b8fec950a594627e395..67c666bfd17cbe6e5fa3ebec85cd946df3ba5bdf 100644 --- a/test/aottest/builtin_inlining/Array/FindFindIndex/builtinArrayFindFindIndex.ts +++ b/test/aottest/builtin_inlining/Array/FindFindIndex/builtinArrayFindFindIndex.ts @@ -214,9 +214,9 @@ function findIndexCase3() { findIndex: true_findIndex } - print(marr.findIndex(x => x == 1)); //aot: [trace] Check Type: NotStableArray1 + print(marr.findIndex(x => x == 1)); //aot: [trace] aot inline builtin: Array.prototype.findIndex, caller function name:#*#findIndexCase3@builtinArrayFindFindIndex //: 0 - + //aot: [trace] Check Type: BuiltinInstanceHClassMismatch Object.setPrototypeOf(marr, mimicArray) print(marr.findIndex(x => x == 1)); //: 0 @@ -235,9 +235,9 @@ function findCase4() { } } Object.setPrototypeOf(arr2, notArray) - - //aot: [trace] Check Type: NotStableArray1 + //aot: [trace] aot inline builtin: Array.prototype.find, caller function name:#*#findCase4@builtinArrayFindFindIndex print(arr1.find(x => x == 1)); //: 1 + //aot: [trace] aot inline function name: #*@6*#find@builtinArrayFindFindIndex caller function name: #*#findCase4@builtinArrayFindFindIndex //aot: [trace] aot inline function name: #*@6*#^1@builtinArrayFindFindIndex caller function name: #*@6*#find@builtinArrayFindFindIndex print(arr2.find(x => x == 1)); //: false } @@ -252,8 +252,9 @@ function findIndexCase4() { } Object.setPrototypeOf(arr2, notArray) - //aot: [trace] Check Type: NotStableArray1 + //aot: [trace] aot inline builtin: Array.prototype.findIndex, caller function name:#*#findIndexCase4@builtinArrayFindFindIndex print(arr1.findIndex(x => x == 1)); //: 0 + //aot: [trace] aot inline function name: #*@7*#findIndex@builtinArrayFindFindIndex caller function name: #*#findIndexCase4@builtinArrayFindFindIndex //aot: [trace] aot inline function name: #*@7*#^1@builtinArrayFindFindIndex caller function name: #*@7*#findIndex@builtinArrayFindFindIndex print(arr2.findIndex(x => x == 1)); //: false } @@ -268,7 +269,7 @@ function findCase5() { return x(1) } - //aot: [trace] Check Type: NotStableArray1 + //aot: [trace] aot inline function name: #*@8*#@builtinArrayFindFindIndex caller function name: #*#findCase5@builtinArrayFindFindIndex //aot: [trace] aot inline function name: #*@8*#^1@builtinArrayFindFindIndex caller function name: #*@8*#@builtinArrayFindFindIndex print(arr1.find(x => x == 1)); //: true } @@ -279,7 +280,7 @@ function findIndexCase5() { return x(1) } - //aot: [trace] Check Type: NotStableArray1 + //aot: [trace] aot inline function name: #*@9*#@builtinArrayFindFindIndex caller function name: #*#findIndexCase5@builtinArrayFindFindIndex //aot: [trace] aot inline function name: #*@9*#^1@builtinArrayFindFindIndex caller function name: #*@9*#@builtinArrayFindFindIndex print(arr1.findIndex(x => x == 1)); //: true } diff --git a/test/aottest/builtin_inlining/Array/ForEach/builtinArrayForEach.ts b/test/aottest/builtin_inlining/Array/ForEach/builtinArrayForEach.ts index a2eb3d23642349447f00130b064a18f7d11eafd5..b28b0fd89a239968dc9e03454d950d39fdef0df9 100644 --- a/test/aottest/builtin_inlining/Array/ForEach/builtinArrayForEach.ts +++ b/test/aottest/builtin_inlining/Array/ForEach/builtinArrayForEach.ts @@ -162,8 +162,9 @@ function forEachCase4() { } Object.setPrototypeOf(arr2, notArray) - //aot: [trace] Check Type: NotStableArray1 + //aot: [trace] aot inline builtin: Array.prototype.foreach, caller function name:#*#forEachCase4@builtinArrayForEach print(arr1.forEach(x => x == 1)); //: undefined + //aot: [trace] aot inline function name: #*@4*#forEach@builtinArrayForEach caller function name: #*#forEachCase4@builtinArrayForEach //aot: [trace] aot inline function name: #*@4*#^1@builtinArrayForEach caller function name: #*@4*#forEach@builtinArrayForEach print(arr2.forEach(x => x == 1)); //: false } diff --git a/test/aottest/builtin_inlining/Array/Pop/builtinArrayPop.ts b/test/aottest/builtin_inlining/Array/Pop/builtinArrayPop.ts index d4c8a616b81367ecb583849c0f058577b19a71e8..db87738225fb98deb9d47dec465af02e94265f3d 100644 --- a/test/aottest/builtin_inlining/Array/Pop/builtinArrayPop.ts +++ b/test/aottest/builtin_inlining/Array/Pop/builtinArrayPop.ts @@ -169,8 +169,9 @@ function popCase4() { } Object.setPrototypeOf(arr2, notArray) - //aot: [trace] Check Type: NotStableArray1 + //aot: [trace] aot inline builtin: Array.prototype.pop, caller function name:#*#popCase4@builtinArrayPop print(arr1.pop(1)); //: 2 + //aot: [trace] aot inline function name: #*@3*#pop@builtinArrayPop caller function name: #*#popCase4@builtinArrayPop print(arr2.pop(1)); //: -100 } popCase4() @@ -183,7 +184,6 @@ function popCase5() { return x } - //aot: [trace] Check Type: NotStableArray1 print(arr1.pop(1)); //: 1 } popCase5() diff --git a/test/aottest/builtin_inlining/Array/Push/BUILD.gn b/test/aottest/builtin_inlining/Array/Push/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..a9d15ec40e1a03eab02e3c14be1e2840df7b2a97 --- /dev/null +++ b/test/aottest/builtin_inlining/Array/Push/BUILD.gn @@ -0,0 +1,17 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_builtin_inlining_test_action("builtinArrayPush") { +} diff --git a/test/aottest/builtin_inlining/Array/Push/builtinArrayPush.ts b/test/aottest/builtin_inlining/Array/Push/builtinArrayPush.ts new file mode 100644 index 0000000000000000000000000000000000000000..45a32d141cf644cadd261a8173c58a59f4de34f9 --- /dev/null +++ b/test/aottest/builtin_inlining/Array/Push/builtinArrayPush.ts @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare interface ArkTools { + isAOTCompiled(args: any): boolean; +} +declare function print(arg:any):string; +let arr = ["a",2,3,4]; +print(arr.push()) //: 4 + +function testArrayPushagrs1() { + print("testArrayPushagrs1") //: testArrayPushagrs1 + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushagrs1@builtinArrayPush + let arr = ["a",2,3,4]; + let x = arr.push("s"); + print(arr.length) //: 5 + print(arr[4]) //: s + print(x) //: 5 + + let arr2 = new Array() + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushagrs1@builtinArrayPush + let y = arr2.push(1); + print(y) //: 1 +} +testArrayPushagrs1(); + +//aot: [trace] aot inline function name: #*#testArrayPushagrs2@builtinArrayPush caller function name: func_main_0@builtinArrayPush +function testArrayPushagrs2() { + print("testArrayPushagrs2") //: testArrayPushagrs2 + let arr = ["a",2,3,4]; + print(arr.push(1,2)) //: 6 + print(arr[4]) //: 1 + print(arr[5]) //: 2 +} +testArrayPushagrs2() +//aot: [trace] aot inline function name: #*#testArrayPushNotStableArray@builtinArrayPush caller function name: func_main_0@builtinArrayPush +function testArrayPushNotStableArray() { + print("testArrayPushNotStableArray") //: testArrayPushNotStableArray + let arr = new Array(1025); + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushNotStableArray@builtinArrayPush + //aot: [trace] Check Type: NotStableArray2 + print(arr.push(0)); //: 1026 +} +testArrayPushNotStableArray() + + +function testPushToNonWritableLength() { + print("testPushToNonWritableLength") //: testPushToNonWritableLength + var arr_push = []; + Object.defineProperty(arr_push, "length", { writable : false}); + try { + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testPushToNonWritableLength@builtinArrayPush + //aot: [trace] Check Type: BuiltinInstanceHClassMismatch + arr_push.push("5"); + } catch (e) { + print(e instanceof TypeError); //: true + } +} +testPushToNonWritableLength(); + + + + +function testArrayPushNotStableArray4() { + print("testArrayPushNotStableArray4") //: testArrayPushNotStableArray4 + var arr = new Array(1023) + for(let i = 0; i < 5; i++){ + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushNotStableArray4@builtinArrayPush + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushNotStableArray4@builtinArrayPush + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushNotStableArray4@builtinArrayPush + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushNotStableArray4@builtinArrayPush + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushNotStableArray4@builtinArrayPush + arr.push(i); + } + print(arr.push()) //: 1028 +} +testArrayPushNotStableArray4() + + + +function testArrayPushException(){ + print("testArrayPushException") //: testArrayPushException + Object.freeze(arr); + let error = null; + try { + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushException@builtinArrayPush + //aot: [trace] Check Type: NotStableArray2 + arr.push(1); + } catch (e) { + error = e; + print("exception happend") //: exception happend + } + } +testArrayPushException() + +function testArrayPushMaxLength(){ + print("testArrayPushMaxLength") //: testArrayPushMaxLength + let arr = []; + //aot: [trace] aot inline builtin: Math.pow, caller function name:#*#testArrayPushMaxLength@builtinArrayPush + arr.length = Math.pow(2, 32) - 1; // 设置数组长度为最大值 + try { + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushMaxLength@builtinArrayPush + //aot: [trace] Check Type: NotStableArray2 + arr.push(1); + } catch (e) { + print("exception happend") //: exception happend + } + } + testArrayPushMaxLength() + + function testArrayLikePush(){ + print("testArrayLikePush"); //: testArrayLikePush + let arrayLike = { + length: 0, + 0: "initialValue" + }; + + try { + Array.prototype.push.call(arrayLike, 1); + Array.prototype.push.call(arrayLike, 2); + if (arrayLike.length === 2 && arrayLike[0] === 1 && arrayLike[1] === 2) { + print("Array-like push succeeded"); //: Array-like push succeeded + } else { + print("Array-like push failed"); + } + } catch (e) { + print("exception happened"); + } +} +testArrayLikePush() + +function testArrayPushAsProto(){ + print("testArrayPushAsProto") //: testArrayPushAsProto + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushAsProto@builtinArrayPush + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushAsProto@builtinArrayPush + var arr = new Array() + arr.push(0) + let temp = new Array(); + temp.__proto__ = arr; + print(arr.push(0)) //: 2 + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushAsProto@builtinArrayPush + //aot: [trace] Check Type: BuiltinInstanceHClassMismatch + print(temp.push(0)) //: 1 +} +testArrayPushAsProto() + +function testArrayPushNotStableArray2() { + print("testArrayPushNotStableArray2") //: testArrayPushNotStableArray2 + var arr = [,]; + arr.__proto__.push(0); + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushNotStableArray2@builtinArrayPush + //aot: [trace] Check Type: BuiltinInstanceHClassMismatch + print(arr.push(0)); //: 2 +} +testArrayPushNotStableArray2() + +function testArrayPushNotStableArray3() { + print("testArrayPushNotStableArray3") //: testArrayPushNotStableArray3 + var arr = [,]; + let k = function push() { + return arr.push(1); + } + //aot: [trace] aot inline builtin: Array.prototype.push, caller function name:#*#testArrayPushNotStableArray3@builtinArrayPush + //aot: [trace] Check Type: NotStableArray1 + arr.__proto__.push(0); + //aot: [trace] Check Type: NotStableArray1 + print(k()); //: 2 +} +testArrayPushNotStableArray3() \ No newline at end of file diff --git a/test/aottest/builtin_inlining/String/BUILD.gn b/test/aottest/builtin_inlining/String/BUILD.gn index ee60eea3e180d37a33c788758d2b2cff43e74af9..61b52b44bcd66108b8d35e3e6deb24e636188772 100644 --- a/test/aottest/builtin_inlining/String/BUILD.gn +++ b/test/aottest/builtin_inlining/String/BUILD.gn @@ -13,7 +13,10 @@ group("ark_aot_builtin_inlining_String_test") { testonly = true - test_list = [ "CharCodeAt" ] + test_list = [ + "CharCodeAt", + "LocaleCompare", + ] deps = [] foreach(test, test_list) { diff --git a/test/aottest/builtin_inlining/String/LocaleCompare/BUILD.gn b/test/aottest/builtin_inlining/String/LocaleCompare/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..b38347e349b42947c2d8bd6f36bfb2ace98dc9a2 --- /dev/null +++ b/test/aottest/builtin_inlining/String/LocaleCompare/BUILD.gn @@ -0,0 +1,17 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_builtin_inlining_test_action("builtinStringLocaleCompare") { +} diff --git a/test/aottest/builtin_inlining/String/LocaleCompare/builtinStringLocaleCompare.ts b/test/aottest/builtin_inlining/String/LocaleCompare/builtinStringLocaleCompare.ts new file mode 100644 index 0000000000000000000000000000000000000000..6d69b96681d64e60da2150f1e8a02e401d89e544 --- /dev/null +++ b/test/aottest/builtin_inlining/String/LocaleCompare/builtinStringLocaleCompare.ts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +declare function print(arg:any):string; + +function func() { + let a = "hijklmn"; + let b = "abcdefg"; + //aot: [trace] aot inline function name: #*#func@builtinStringLocaleCompare caller function name: func_main_0@builtinStringLocaleCompare + //: 1 + print(a.localeCompare(b)); +} +func(); \ No newline at end of file diff --git a/test/aottest/builtin_inlining/map/BUILD.gn b/test/aottest/builtin_inlining/map/BUILD.gn index 14bfa8fa5ae58e24dd0d2153d03d1fb69ddd64f5..3d3bb798ed4264a65a660e11ddd5dce47955195c 100644 --- a/test/aottest/builtin_inlining/map/BUILD.gn +++ b/test/aottest/builtin_inlining/map/BUILD.gn @@ -17,7 +17,8 @@ group("ark_aot_builtin_inlining_map_test") { "Delete", "Clear", "Entries", - "Get", + + # "Get", "GetSize", "Has", "Keys", diff --git a/test/aottest/builtin_inlining/math/BUILD.gn b/test/aottest/builtin_inlining/math/BUILD.gn index 3763ebedc73690c56758c0705a13d83ce01f94d4..2d21632b2b894e6a3cc7ec0ba42a84708e1b637c 100644 --- a/test/aottest/builtin_inlining/math/BUILD.gn +++ b/test/aottest/builtin_inlining/math/BUILD.gn @@ -46,7 +46,8 @@ group("ark_aot_builtin_inlining_math_test") { "Fround", "Imul", "Ceil", - "Floor", + + # "Floor", ] deps = [] diff --git a/test/aottest/builtin_math1/BUILD.gn b/test/aottest/builtin_math1/BUILD.gn index fb534995cc5750de26188607da7d6de65ed040fe..e1225807cfc4833a5453790039738d32e75bf067 100644 --- a/test/aottest/builtin_math1/BUILD.gn +++ b/test/aottest/builtin_math1/BUILD.gn @@ -17,5 +17,6 @@ host_aot_test_action("builtin_math1") { deps = [] is_only_typed_path = true is_enable_trace_deopt = true + is_enable_typed_op_profiler = true log_option = " --log-info=trace" } diff --git a/test/aottest/builtin_math1/builtin_math1.ts b/test/aottest/builtin_math1/builtin_math1.ts index f96ff42b5f9d57c6de5d375d8c27b770b4076def..d356416b703a523eb10f70fa553d2ea3fbcf2ee8 100644 --- a/test/aottest/builtin_math1/builtin_math1.ts +++ b/test/aottest/builtin_math1/builtin_math1.ts @@ -13,5 +13,22 @@ * limitations under the License. */ +declare var ArkTools:any; +declare function print(arg:any):string; + +function Test1() { + const LOOP_NUM = 10; + for (let i = 0; i < LOOP_NUM; i ++) { + let sr = Math.sin(i); + let cr = Math.cos(i); + let pr = Math.pow(2, i); + } +} + +Test1(); + +ArkTools.clearTypedOpProfiler(); +print(ArkTools.isAOTDeoptimized(Test1)); + Object.defineProperty(Math, 1, {}); print(Math.abs(1)); diff --git a/test/aottest/builtin_math1/expect_output.txt b/test/aottest/builtin_math1/expect_output.txt index 99a4bf8661d4b60e82801f845b7624459e8fe7b3..927f00f1502b1703348317b7b9bd73c0d5911f2c 100644 --- a/test/aottest/builtin_math1/expect_output.txt +++ b/test/aottest/builtin_math1/expect_output.txt @@ -11,5 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. +false [trace] Check Type: InconsistentHClass14 1 diff --git a/test/aottest/builtins_parseint/expect_output.txt b/test/aottest/builtins_parseint/expect_output.txt index fca0704f14991dfcd3c1cb4ed7464f0d6ab41ce2..03ccfbc4b6032750da41b8795b951d57b46c3c02 100644 --- a/test/aottest/builtins_parseint/expect_output.txt +++ b/test/aottest/builtins_parseint/expect_output.txt @@ -26,6 +26,7 @@ [trace] aot inline builtin: Number.parseInt, caller function name:#*#randomStrId@builtins_parseint [trace] aot inline builtin: Number.parseInt, caller function name:#*#randomStrId@builtins_parseint [trace] aot inline builtin: Number.parseInt, caller function name:#*#randomStrId@builtins_parseint +[trace] aot inline builtin: Array.prototype.push, caller function name:#*#testFileInfo@builtins_parseint 1 [trace] aot inline builtin: Number.parseInt, caller function name:func_main_0@builtins_parseint 4 diff --git a/test/aottest/builtins_string/builtins_string.ts b/test/aottest/builtins_string/builtins_string.ts index 330af6885a2d77c2c95c869cdf002b31e27d1b5e..aaf131e6960016d18ec315c8423618410bc3ff60 100644 --- a/test/aottest/builtins_string/builtins_string.ts +++ b/test/aottest/builtins_string/builtins_string.ts @@ -54,6 +54,8 @@ print(str.substring(-100, undefined)); print(str.substring(num1, num4)); +print(str.substring(-9007199254740992)); + print(str.substr(0)); print(str.substr(-0.01)); diff --git a/test/aottest/builtins_string/expect_output.txt b/test/aottest/builtins_string/expect_output.txt index c99701c2321ae7b4c3573415a8631518a7692d7c..51d9dc6e7cdc702c3f6f88349a4baa5d0912e0be 100644 --- a/test/aottest/builtins_string/expect_output.txt +++ b/test/aottest/builtins_string/expect_output.txt @@ -29,6 +29,7 @@ sd-93u498t sd-93u498thikefnow8y3-0rh1nalksfnwo8y3t19-3r8hoiefnw sd-93u498thikefnow8y3-0rh1nalksfnwo8y3t19-3r8hoiefnw sd-93u498thikefnow8y3-0rh1nalksfnwo8y3t19-3r8hoiefnw +sd-93u498thikefnow8y3-0rh1nalksfnwo8y3t19-3r8hoiefnw sd-93u498thikefnow8y3-0rh1nalksfnwo8y3t19-3r8hoiefnw hikefnow8y3-0rh1nalksfnwo8y3t19-3r8hoiefnw diff --git a/test/aottest/construct_deopt_frame_stack_overflow2/BUILD.gn b/test/aottest/construct_deopt_frame_stack_overflow2/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..a78ab5bc58d8f5a4a8016f15fbd9c6210700420b --- /dev/null +++ b/test/aottest/construct_deopt_frame_stack_overflow2/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("construct_deopt_frame_stack_overflow2") { + deps = [] + is_only_typed_path = true + is_enable_pgo = true + is_enable_opt_inlining = true + is_enable_enableArkTools = true + log_option = " --log-info=fatal" +} diff --git a/test/aottest/construct_deopt_frame_stack_overflow2/construct_deopt_frame_stack_overflow2.ts b/test/aottest/construct_deopt_frame_stack_overflow2/construct_deopt_frame_stack_overflow2.ts new file mode 100644 index 0000000000000000000000000000000000000000..2db8079f3f21cb5f74a6c75fdad72a29eb0dd232 --- /dev/null +++ b/test/aottest/construct_deopt_frame_stack_overflow2/construct_deopt_frame_stack_overflow2.ts @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +function test() { + function f0() { + const o18 = { + proto: "p", + n(a5) { + let v6; + try { v6 = a5(this); } catch (e) { } + function f7() { + return v6; + } + return this; + }, + set a(a9) { + }, + }; + return o18; + } + const v19 = f0(); + const v21 = f0(); + function f22(a23) { + try { a23.n(f22); } catch (e) { } + const o30 = { + m() { + return a23; + }, + proto: a23, + "d": f0, + }; + return o30; + } + f22(v21); + const v33 = f22(v19); + const v45 = new Set(); + for (let [i71, i72] = (() => { + return [0, 5]; + })(); + i71 < i72; + ) { + i72--; + } +} + +test() +print(ArkTools.isAOTCompiled(test)); \ No newline at end of file diff --git a/test/aottest/pgo_force_ic/slowpath_expect_output.txt b/test/aottest/construct_deopt_frame_stack_overflow2/expect_output.txt similarity index 99% rename from test/aottest/pgo_force_ic/slowpath_expect_output.txt rename to test/aottest/construct_deopt_frame_stack_overflow2/expect_output.txt index 3e50a9459dafadbe4d614898e1a2f1bfc6e11bd2..e8a583802fa636d0d7b4dde7d65c9f12e95add7c 100644 --- a/test/aottest/pgo_force_ic/slowpath_expect_output.txt +++ b/test/aottest/construct_deopt_frame_stack_overflow2/expect_output.txt @@ -11,5 +11,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -hello true diff --git a/test/aottest/pgo_force_ic/pgo_expect_output.txt b/test/aottest/construct_deopt_frame_stack_overflow2/pgo_expect_output.txt similarity index 99% rename from test/aottest/pgo_force_ic/pgo_expect_output.txt rename to test/aottest/construct_deopt_frame_stack_overflow2/pgo_expect_output.txt index daa7d198af7de204908478ae5aeb063cf4cf02cd..9516261d5e9d7c65455a1d3734cd2569e578b0ef 100644 --- a/test/aottest/pgo_force_ic/pgo_expect_output.txt +++ b/test/aottest/construct_deopt_frame_stack_overflow2/pgo_expect_output.txt @@ -11,5 +11,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -hello false diff --git a/test/aottest/pgo_force_ic/BUILD.gn b/test/aottest/createarraywithbuffer3/BUILD.gn similarity index 82% rename from test/aottest/pgo_force_ic/BUILD.gn rename to test/aottest/createarraywithbuffer3/BUILD.gn index b2c24e32cbf13c058ae8d7553f79cb5d08e104e9..b50cc76bc8444d54381c4b42a5e659067a06c51e 100644 --- a/test/aottest/pgo_force_ic/BUILD.gn +++ b/test/aottest/createarraywithbuffer3/BUILD.gn @@ -13,10 +13,9 @@ import("//arkcompiler/ets_runtime/test/test_helper.gni") -host_aot_test_action("pgo_force_ic") { +host_aot_test_action("createarraywithbuffer3") { deps = [] is_enable_pgo = true - is_enable_force_ic = false - log_option = " --log-info=trace" - use_distinct_slowpath_expect_path = true + is_enable_opt_inlining = true + is_enable_native_inline = true } diff --git a/test/aottest/createarraywithbuffer3/createarraywithbuffer3.ts b/test/aottest/createarraywithbuffer3/createarraywithbuffer3.ts new file mode 100644 index 0000000000000000000000000000000000000000..9edbbf5aa3d7bff6349d5b084d2ac31aca0ebafc --- /dev/null +++ b/test/aottest/createarraywithbuffer3/createarraywithbuffer3.ts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +declare function print(str: any): string; +declare var ArkTools: any; +function foo() { + class a { + toString() { + // @ts-ignore + new Proxy(undefined, {}); + } + } + // @ts-ignore + parseInt(new a()); + [0]; +} +print(ArkTools.isAOTCompiled(foo)); +try { + foo(); +} catch (e) { + print(e); +} diff --git a/test/aottest/createarraywithbuffer3/expect_output.txt b/test/aottest/createarraywithbuffer3/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..349dba4e572d9879fecc1712284e89509cc75c17 --- /dev/null +++ b/test/aottest/createarraywithbuffer3/expect_output.txt @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +true +TypeError: ProxyCreate: target is not Object diff --git a/test/aottest/createarraywithbuffer3/pgo_expect_output.txt b/test/aottest/createarraywithbuffer3/pgo_expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..d5d50d5bc1b02a23af05f383b6f526c6df1f66a3 --- /dev/null +++ b/test/aottest/createarraywithbuffer3/pgo_expect_output.txt @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +false +TypeError: ProxyCreate: target is not Object diff --git a/test/aottest/elements_kind/elements_kind.ts b/test/aottest/elements_kind/elements_kind.ts index 854f6dc5a39177abf52811543c9241bcbbfa761b..1ed1b2dd737e25c17cf72aa98bdbffc60db01f57 100644 --- a/test/aottest/elements_kind/elements_kind.ts +++ b/test/aottest/elements_kind/elements_kind.ts @@ -116,3 +116,76 @@ function testProto2() { print(ArkTools.isAOTCompiled(testProto2)); testProto2(); + +function testEmptyArrNotDic(){ + let arr = []; + arr.length = 1024; + print(ArkTools.getElementsKind(arr)); +} +print(ArkTools.isAOTCompiled(testEmptyArrNotDic)); +testEmptyArrNotDic(); + + +function testEmptyArrDic(){ + let arr = []; + arr.length = 1025 + print(ArkTools.getElementsKind(arr)); +} +print(ArkTools.isAOTCompiled(testEmptyArrDic)); +testEmptyArrDic(); + + +function testArrayStOwnByIndex(){ + let arr = [,,,,,,,,,,,,1]; + print(ArkTools.getElementsKind(arr)); +} +print(ArkTools.isAOTCompiled(testArrayStOwnByIndex)); +testArrayStOwnByIndex(); + + +function testEmptyArrayHasLength(){ + let arr = [,,,,,,]; + print(ArkTools.getElementsKind(arr)); + arr.length = 3 + print(ArkTools.getElementsKind(arr)); +} +print(ArkTools.isAOTCompiled(testEmptyArrayHasLength)); +testEmptyArrayHasLength(); + + +function testCutArrayToEmptyThanExtend(){ + let arr = [1,2,3,4] + arr.length = 0; + print(ArkTools.getElementsKind(arr)); + arr.length = 3; + print(ArkTools.getElementsKind(arr)); + arr.length = 0; + print(ArkTools.getElementsKind(arr)); +} +print(ArkTools.isAOTCompiled(testCutArrayToEmptyThanExtend)); +testCutArrayToEmptyThanExtend(); + + +function testNewEmptyArrayCut(){ + let arr = new Array(10) + print(ArkTools.getElementsKind(arr)); + arr.length = 0; + print(ArkTools.getElementsKind(arr)); +} +print(ArkTools.isAOTCompiled(testNewEmptyArrayCut)); +testNewEmptyArrayCut(); + +function testNoneToNone(){ + let arr = []; + print(ArkTools.getElementsKind(arr)); + arr.length = 0; + print(ArkTools.getElementsKind(arr)); + arr.length = 1000; + print(ArkTools.getElementsKind(arr)); + arr.length = 0; + print(ArkTools.getElementsKind(arr)); + arr.length = 0; + print(ArkTools.getElementsKind(arr)); +} +print(ArkTools.isAOTCompiled(testNoneToNone)); +testNoneToNone(); \ No newline at end of file diff --git a/test/aottest/elements_kind/expect_output.txt b/test/aottest/elements_kind/expect_output.txt index d25c694dd2907b0acd8b2cea3294e1757485c4de..7375620125dae2196ada4189a3bd87431dd71690 100644 --- a/test/aottest/elements_kind/expect_output.txt +++ b/test/aottest/elements_kind/expect_output.txt @@ -32,4 +32,25 @@ true 6 2 6 - +true +1 +true +31 +true +3 +true +1 +1 +true +0 +1 +0 +true +31 +31 +true +0 +0 +1 +0 +0 diff --git a/test/aottest/elements_kind/pgo_expect_output.txt b/test/aottest/elements_kind/pgo_expect_output.txt index 56f256d40402e06a0e30a63c9835fac7b12318b8..c529b87e3b80c56176372b644b25398da3ce4427 100644 --- a/test/aottest/elements_kind/pgo_expect_output.txt +++ b/test/aottest/elements_kind/pgo_expect_output.txt @@ -32,4 +32,25 @@ false 6 2 6 - +false +1 +false +31 +false +3 +false +1 +1 +false +0 +1 +0 +false +31 +31 +false +0 +0 +1 +0 +0 diff --git a/test/aottest/isprototype/BUILD.gn b/test/aottest/isprototype/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..7a2075214410a1c5a97759d61484de8efc65f84e --- /dev/null +++ b/test/aottest/isprototype/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("isprototype") { + deps = [] +} diff --git a/test/aottest/isprototype/expect_output.txt b/test/aottest/isprototype/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..25cfbddbf743e38b6778087249a0291dca53fe96 --- /dev/null +++ b/test/aottest/isprototype/expect_output.txt @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Hello World +Hello World +Hello World diff --git a/test/aottest/isprototype/isprototype.ts b/test/aottest/isprototype/isprototype.ts new file mode 100644 index 0000000000000000000000000000000000000000..ca9daa764733b2d151eeb45901c681c3dfef9646 --- /dev/null +++ b/test/aottest/isprototype/isprototype.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function foo(a8) { + const o19 = { + "a": 123, + ...a8, + __proto__: a8, + "b": 456, + }; + print("Hello World"); + return o19; +} + +const v1 = foo(123); +const v2 = foo(v1); +const v3 = foo(v1); diff --git a/test/aottest/object/object_assign/expect_output.txt b/test/aottest/object/object_assign/expect_output.txt index ab78ca9638c36f3960ca463b80ac2b7c8dc6676e..acd627418a76ca11146d3d8a062bd4cf878e3ef7 100644 --- a/test/aottest/object/object_assign/expect_output.txt +++ b/test/aottest/object/object_assign/expect_output.txt @@ -17,3 +17,4 @@ 3 false a,b,c +true diff --git a/test/aottest/object/object_assign/object_assign.ts b/test/aottest/object/object_assign/object_assign.ts index 39cec94a7cacff7322b1cc3fe2cfd7e568b32b1a..cc37a35430c7252662e25b3987ba8991cf43b918 100644 --- a/test/aottest/object/object_assign/object_assign.ts +++ b/test/aottest/object/object_assign/object_assign.ts @@ -54,4 +54,16 @@ const v3 = 10; const v4 = Symbol("foo"); const obj3 = Object.assign({}, v1, null, v2, undefined, v3, v4); -print(Object.values(obj3)) +print(Object.values(obj3)); + +const v5 = new Uint8Array(); +const o7 = { + __proto__ : v5, +}; +const o8 = { + get f() { + return this; + }, +}; +Object.assign(o7, o8); +print(o7.f === o8); diff --git a/test/aottest/pgo_storemiss/BUILD.gn b/test/aottest/pgo_storemiss/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..7a706cdcf87f65a7565ac9db5b675ed2dd94a82e --- /dev/null +++ b/test/aottest/pgo_storemiss/BUILD.gn @@ -0,0 +1,20 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("pgo_storemiss") { + deps = [] + is_enable_pgo = true + is_enable_opt_inlining = true +} diff --git a/test/aottest/pgo_storemiss/expect_output.txt b/test/aottest/pgo_storemiss/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..9d6dbd0259117661a56ecde2814cc716f7716074 --- /dev/null +++ b/test/aottest/pgo_storemiss/expect_output.txt @@ -0,0 +1,16 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +test accessor ic successful1! +test accessor ic successful2! +set proto diff --git a/test/aottest/pgo_storemiss/pgo_expect_output.txt b/test/aottest/pgo_storemiss/pgo_expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..cc08845e8f12e01174745df0544c9818fbf57a98 --- /dev/null +++ b/test/aottest/pgo_storemiss/pgo_expect_output.txt @@ -0,0 +1,16 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +test accessor ic successful1! +test accessor ic successful2! +set proto diff --git a/test/moduletest/arrayConcat/arrayConcat.js b/test/aottest/pgo_storemiss/pgo_storemiss.ts similarity index 32% rename from test/moduletest/arrayConcat/arrayConcat.js rename to test/aottest/pgo_storemiss/pgo_storemiss.ts index 0a4d9b92728cfb563bdc3cfeecb66e86a405a652..93e99f813a4c0ca477bd626369012015094a44b6 100644 --- a/test/moduletest/arrayConcat/arrayConcat.js +++ b/test/aottest/pgo_storemiss/pgo_storemiss.ts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -12,70 +12,65 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const array1 = ['a', 'b', 'c']; -const array2 = ['d', 'e', 'f']; -const array3 = array1.concat(array2); -print(array3); -const letters = ["a", "b", "c"]; -const numbers = [1, 2, 3]; - -const alphaNumeric = letters.concat(numbers); -print(alphaNumeric); - -const num1 = [1, 2, 3]; -const num2 = [4, 5, 6]; -const num3 = [7, 8, 9]; - -const numbers1 = num1.concat(num2, num3); - -print(numbers1); - - -const letters1 = ["a", "b", "c"]; - -const alphaNumeric1 = letters1.concat(1, [2, 3]); - -print(alphaNumeric1); - -const num11 = [[1]]; -const num22 = [2, [3]]; - -const numbers2 = num1.concat(num22); - -print(numbers2); -// [[1], 2, [3]] - -num11[0].push(4); - -print(numbers2); - -var target = {0:"a",1:"b",[Symbol.isConcatSpreadable]:"truish"}; -var obj=new Proxy(target,{ - get(a,p){ - print(p.toString()); - return a[p]; - } -}) -[].concat(obj); -print([1, , 3].concat([4, 5])); // [1, empty, 3, 4, 5] -print([1, 2].concat([3, , 5])); // [1, 2, 3, empty, 5] - -const emptyArr = []; -print(emptyArr.concat([]).length); - -let px = new Proxy([], {}); - -let idx = 0; -class A extends Array { +declare function print(str:any):string; +//for Store Accessor ic miss, shouldn't update op +class C { constructor() { - super(2); - idx++; - if (idx == 1) { - this.concat(A); - } - return px; + this.x = 1; + this.y = 1; + this.z = 1; + this.w = 1; + this.t = 1; + } + + set u(value) { + Object.defineProperty(this, "u", { + set () {} + }) } } -let a = new A(); -print("proxy defineproperty success!"); \ No newline at end of file + +function foo(obj) { + obj.u = 123; +} + +let c1 = new C(); +let c2 = new C(); +foo(c1); +foo(c2); +print("test accessor ic successful1!"); + +//for Store Accessor ic miss, if change to DictionaryMode, SetAsMega +const v1 = new BigInt64Array(); +const o5 = { + set d(a4) { + Object.defineProperty(this, 2, {writable: true, value: 5}); + }, +}; +o5.d = v1; +print("test accessor ic successful2!"); + +// ic hint wrong object +var o3 = { + set d(a4) { + print("set proto") + Object.defineProperty(o2,"d",{ + writable: true, + value:1 + }) + }, + x:123 +}; + +var o2 = { + __proto__:o3, + y:234 +} +var o1 = { + __proto__:o2, + z:345 +} +for(let i=0;i<5;i++){ + o1.d = v1; +} \ No newline at end of file diff --git a/test/aottest/retype_test2/BUILD.gn b/test/aottest/retype_test2/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..963d9b2aafe95a5fe3d9033ee0facd1b6fb43090 --- /dev/null +++ b/test/aottest/retype_test2/BUILD.gn @@ -0,0 +1,20 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("retype_test2") { + deps = [] + is_enable_opt_inlining = true + is_enable_native_inline = true +} diff --git a/test/aottest/retype_test2/expect_output.txt b/test/aottest/retype_test2/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..b1cd2fac9147177f8d51e337cf62bfbd3a86158b --- /dev/null +++ b/test/aottest/retype_test2/expect_output.txt @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +isAOTCompiled: true +true \ No newline at end of file diff --git a/test/fuzztest/dataviewref_fuzzer/dataviewref_fuzzer.h b/test/aottest/retype_test2/retype_test2.ts similarity index 62% rename from test/fuzztest/dataviewref_fuzzer/dataviewref_fuzzer.h rename to test/aottest/retype_test2/retype_test2.ts index 3fcac2295350cd93e2e732f273f5f800449555ce..e38e4b3d5078677ce5c2365a5e31336cafc92924 100644 --- a/test/fuzztest/dataviewref_fuzzer/dataviewref_fuzzer.h +++ b/test/aottest/retype_test2/retype_test2.ts @@ -1,10 +1,10 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -13,9 +13,14 @@ * limitations under the License. */ -#ifndef DATAVIEWREF_FUZZER_H -#define DATAVIEWREF_FUZZER_H +function func(x) { + if (x++ < -1) { + x++; + } + return x +} -#define FUZZ_PROJECT_NAME "dataviewref_fuzzer" - -#endif \ No newline at end of file +func(-200); +func(12345678912345); +print("isAOTCompiled: " + ArkTools.isAOTCompiled(func)); +print(func(-12345678912345) == -12345678912343); \ No newline at end of file diff --git a/test/aottest/sharedbitvector/BUILD.gn b/test/aottest/sharedbitvector/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..b7acde5648fb9ca921d71407f7d58e75e01e4626 --- /dev/null +++ b/test/aottest/sharedbitvector/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("sharedbitvector") { + deps = [] + src_dir = "$js_root/test/sharedtest/sharedbitvector" + is_enable_pgo = true + use_one_expect_path = true +} diff --git a/test/aottest/stobjbyname1/BUILD.gn b/test/aottest/stobjbyname1/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8038061bfbaf1b7fa491040b5c75f2641fd84f04 --- /dev/null +++ b/test/aottest/stobjbyname1/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("stobjbyname1") { + deps = [] + is_only_typed_path = true + is_enable_pgo = true + is_enable_trace_deopt = true + log_option = " --log-info=trace" +} diff --git a/test/aottest/stobjbyname1/expect_output.txt b/test/aottest/stobjbyname1/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..875c58cf525db4fd9fba9c08ec34a95dd022a2da --- /dev/null +++ b/test/aottest/stobjbyname1/expect_output.txt @@ -0,0 +1,15 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +true +[trace] Check Type: InconsistentHClass6 diff --git a/test/aottest/stobjbyname1/pgo_expect_output.txt b/test/aottest/stobjbyname1/pgo_expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..6728f3b86c74c65c2cc90a702035b3f3c8686d2e --- /dev/null +++ b/test/aottest/stobjbyname1/pgo_expect_output.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +false diff --git a/test/aottest/stobjbyname1/stobjbyname1.ts b/test/aottest/stobjbyname1/stobjbyname1.ts new file mode 100644 index 0000000000000000000000000000000000000000..7bbb79a4abaf74b7af3579e13679d57bc5cf89f2 --- /dev/null +++ b/test/aottest/stobjbyname1/stobjbyname1.ts @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function A() { + this.a = 0; + this.b = 2; +} + +function test(a) { + a.c = 9 +} + +test(new A()); + +if (ArkTools.isAOTCompiled(test)) { + print(true); + let a = new A(); + function B() {} + B.prototype = a; + test(a); +} else { + print(false); +} diff --git a/test/aottest/string_inline/BUILD.gn b/test/aottest/string_inline/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..82539c816d5fd20c42b0475975ec0ad5aee0c50d --- /dev/null +++ b/test/aottest/string_inline/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("string_inline") { + deps = [] + is_enable_pgo = true + is_enable_enableArkTools = true + is_enable_opt_inlining = true + is_enable_native_inline = true +} diff --git a/test/aottest/string_inline/expect_output.txt b/test/aottest/string_inline/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..086adb55e8dac5f09891330530a8643928f98d78 --- /dev/null +++ b/test/aottest/string_inline/expect_output.txt @@ -0,0 +1,30 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +52 +4 +5 +52 +5678901234567890 +5 +8 +57 +true +true +h +undefined +true + + + +true diff --git a/test/aottest/string_inline/pgo_expect_output.txt b/test/aottest/string_inline/pgo_expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..9c4e547691f538a051a7e75a4a615e52f2e7f2c8 --- /dev/null +++ b/test/aottest/string_inline/pgo_expect_output.txt @@ -0,0 +1,30 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +52 +4 +5 +52 +5678901234567890 +5 +8 +57 +false +false +h +undefined +false + + + +false diff --git a/test/aottest/string_inline/string_inline.ts b/test/aottest/string_inline/string_inline.ts new file mode 100644 index 0000000000000000000000000000000000000000..8e589886b824401d34cbf23c25bb4485307ef6f0 --- /dev/null +++ b/test/aottest/string_inline/string_inline.ts @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +declare function print(arg:any, arg1?:any):string; + +class cpu { + public mode: number = 1; + constructor() { + this.mode = 4; + } + public static add(a: string):number { + let i : number = 3; + let b : string = a.substring(3); + print(b); + let d : number = b.charCodeAt(4); + print(a[i]); + print(b[i]); + return d; + } +} + +function foo(a: string):number { + let b : string = a.substring(1); + let d : number = b.charCodeAt(1); + return d; +} + +function foo1(a: string):number { + let i : number = 2; + let b : string = a.substring(1); + let d : number = b.charCodeAt(1); + print(a[i]); + print(b[i]); + return d; +} +var a : string = "12345678901234567890" +var b : string = a.substring(1); +print(foo(b)) +print(foo1(b)) +print(cpu.add(b)) +print(ArkTools.isAOTCompiled(foo)); +print(ArkTools.isAOTCompiled(foo1)); + + +function foo2(a: any, b: string) { + let v2 = b.substring(a, b); + print(v2); +} + +let v0 = 2 >= 1; +let v1 = "hello" +print(foo2(v0, v1)); +print(ArkTools.isAOTCompiled(foo2)); + +class c3 { + constructor(a8) { + let a7 = -4294967297; + let v67 = ("Hello, world!").substring(a8, a7); + let v68 = ("Hello, world!").slice(a8, a7); + let v69 = ("Hello, world!").substr(a8, a7); + print(v67); + print(v68); + print(v69); + } +} + +function testc3 () { + new c3(-4294967297); +} +testc3 () +print(ArkTools.isAOTCompiled(testc3)); diff --git a/test/aottest/supercallforward/expect_output.txt b/test/aottest/supercallforward/expect_output.txt index 0827ac5800148e0348669b37755a823f04c64720..86a77ccd12b999dbc4916c81fdafd28e80d51040 100644 --- a/test/aottest/supercallforward/expect_output.txt +++ b/test/aottest/supercallforward/expect_output.txt @@ -12,9 +12,9 @@ # limitations under the License. ChildNull -TypeError: Super constructor is not a constructor +TypeError ChildObj -TypeError: Super constructor is not a constructor +TypeError ChildArrow -TypeError: Super constructor is not a constructor +TypeError success diff --git a/test/aottest/supercallforward/supercallforward.ts b/test/aottest/supercallforward/supercallforward.ts index 8c58c5841d1fad8f7cf6aad7db6a226ffd8ec50a..e10a0eab4b274f23419791b13f173dd389c31103 100644 --- a/test/aottest/supercallforward/supercallforward.ts +++ b/test/aottest/supercallforward/supercallforward.ts @@ -244,7 +244,7 @@ function runChildCornerCase(ctor: Function, replacement: any) { new ctor(); } catch (e) { print(ctor.name); - print(e); + print(e.name); } } assert_true(ArkTools.isAOTCompiled(ctor)); diff --git a/test/aottest/ts_inline_accessor_symbol/expected_output.txt b/test/aottest/ts_inline_accessor_symbol/expected_output.txt index d939493616e878322baa577d083f33ebb550280b..278712c91d585a61001cedaf3ce794210cd74306 100644 --- a/test/aottest/ts_inline_accessor_symbol/expected_output.txt +++ b/test/aottest/ts_inline_accessor_symbol/expected_output.txt @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -[trace] Check Type: ProtoTypeChanged2 +[trace] Check Type: PrototypeChanged2 [trace] Check Type: InconsistentHClass8 [trace] Check Type: InconsistentHClass13 [trace] Check Type: InconsistentHClass8 diff --git a/test/executiontest/BUILD.gn b/test/executiontest/BUILD.gn index 5beff209a5f6ef466ad308494163af18a5c7fec7..fcf23054275e1ff10c2222172b08e13d7228c625 100644 --- a/test/executiontest/BUILD.gn +++ b/test/executiontest/BUILD.gn @@ -42,7 +42,7 @@ foreach(file, test_js_files) { } } -module_output_path = "arkcompiler/ets_runtime" +module_output_path = "ets_runtime" host_unittest_action("ThreadTerminationTest") { module_out_path = module_output_path diff --git a/test/fuzztest/BUILD.gn b/test/fuzztest/BUILD.gn index a3f18083cc4115abb534cc33210cdc8fd94838a8..60059fe2e0a58457652e3bdfa1ce45b6839a96d1 100644 --- a/test/fuzztest/BUILD.gn +++ b/test/fuzztest/BUILD.gn @@ -19,7 +19,6 @@ group("fuzztest") { "arraybufferrefnew_fuzzer:fuzztest", "arraybufferrefnewwithtwoparameters_fuzzer:fuzztest", "arraylist_fuzzer:fuzztest", - "arrayref_fuzzer:fuzztest", "bigint64arrayrefnew_fuzzer:fuzztest", "bigintrefgetwordsarraysize_fuzzer:fuzztest", "bigintrefnew_fuzzer:fuzztest", @@ -200,10 +199,8 @@ group("fuzztest") { "copyableglobalisempty_fuzzer:fuzztest", "copyableglobalsetandclearweak_fuzzer:fuzztest", "createbigwords_fuzzer:fuzztest", - "dataviewref_fuzzer:fuzztest", "dataviewrefnew_fuzzer:fuzztest", "daterefnew_fuzzer:fuzztest", - "deleteworker_fuzzer:fuzztest", "dumpheapsnapshot1_fuzzer:fuzztest", "dumpheapsnapshot2_fuzzer:fuzztest", "dumpheapsnapshot3_fuzzer:fuzztest", @@ -213,7 +210,6 @@ group("fuzztest") { "exceptionevalerror_fuzzer:fuzztest", "exceptionoomerror_fuzzer:fuzztest", "exceptiontypeerror_fuzzer:fuzztest", - "executionscope_fuzzer:fuzztest", "float32arrayrefnew_fuzzer:fuzztest", "float64arrayrefnew_fuzzer:fuzztest", "functionrefcall_fuzzer:fuzztest", @@ -226,26 +222,22 @@ group("fuzztest") { "functionrefnewclassfunction_fuzzer:fuzztest", "generatorfunctionref_fuzzer:fuzztest", "getallocationprofile_fuzzer:fuzztest", - "getassetpath_fuzzer:fuzztest", "getbundlename_fuzzer:fuzztest", "getformatfunction_fuzzer:fuzztest", "getjspandafile_fuzzer:fuzztest", "getmodulename_fuzzer:fuzztest", "getnativepointerfield_fuzzer:fuzztest", "getwordsarray_fuzzer:fuzztest", - "globalclass_fuzzer:fuzztest", "int16arrayrefnew_fuzzer:fuzztest", "int32arrayrefnew_fuzzer:fuzztest", "int8arrayrefnew_fuzzer:fuzztest", "integerrefnewvalue_fuzzer:fuzztest", - "isquickfixcausedexception_fuzzer:fuzztest", "jsnapiaddworker_fuzzer:fuzztest", "jsnapicontext_fuzzer:fuzztest", "jsnapideleteserializationdata_fuzzer:fuzztest", "jsnapideserializevalue_fuzzer:fuzztest", "jsnapiexception_fuzzer:fuzztest", "jsnapiexceptions_fuzzer:fuzztest", - "jsnapifork_fuzzer:fuzztest", "jsnapihaspendingexception_fuzzer:fuzztest", "jsnapiinformation_fuzzer:fuzztest", "jsnapiisarrayiterator_fuzzer:fuzztest", @@ -266,7 +258,6 @@ group("fuzztest") { "jsnapitriggergc_fuzzer:fuzztest", "jsnapiuncaughtclearexception_fuzzer:fuzztest", "jsnapiuncaughtexception_fuzzer:fuzztest", - "jsnapiunloadpatch_fuzzer:fuzztest", "jsnapivalue_fuzzer:fuzztest", "jsonparse_fuzzer:fuzztest", "jsonstringify_fuzzer:fuzztest", @@ -307,7 +298,6 @@ group("fuzztest") { "jsvaluerefuint32value_fuzzer:fuzztest", "jsvaluerefwithinint32_fuzzer:fuzztest", "loadapbinaryfile_fuzzer:fuzztest", - "loadpatch_fuzzer:fuzztest", "loadpatchlong_fuzzer:fuzztest", "mapiteratorefget_fuzzer:fuzztest", "maprefgetsetkeyvaluesize_fuzzer:fuzztest", @@ -324,7 +314,6 @@ group("fuzztest") { "numberrefnewuint32_fuzzer:fuzztest", "numberrefvalue_fuzzer:fuzztest", "objectbool_fuzzer:fuzztest", - "objectcast_fuzzer:fuzztest", "objectdelete_fuzzer:fuzztest", "objectget_fuzzer:fuzztest", "objectgetinformation_fuzzer:fuzztest", @@ -338,18 +327,14 @@ group("fuzztest") { "objectset_fuzzer:fuzztest", "parsefromtext_fuzzer:fuzztest", "primitiverefgetvalue_fuzzer:fuzztest", - "promisecapabilityref_fuzzer:fuzztest", "promiseref_fuzzer:fuzztest", "promiserejectinfo_fuzzer:fuzztest", "propertyattribute_fuzzer:fuzztest", "proxyrefisrevoked_fuzzer:fuzztest", "publicapicollatorrefget_fuzzer:fuzztest", "publicapigeneratorobjectref_fuzzer:fuzztest", - "publicapilocal_fuzzer:fuzztest", - "publicapilocaloperatorsymbol_fuzzer:fuzztest", "publicapilocalregexpref_fuzzer:fuzztest", "readenablelist_fuzzer:fuzztest", - "registerquickfixqueryfunc_fuzzer:fuzztest", "setbundlename_fuzzer:fuzztest", "setcpusamplinginterval_fuzzer:fuzztest", "setiteratorrefget_fuzzer:fuzztest", @@ -377,10 +362,7 @@ group("fuzztest") { "stringrefwriteutf16_fuzzer:fuzztest", "symbolnew_fuzzer:fuzztest", "symbolrefgetdescription_fuzzer:fuzztest", - "templateclassglobal_fuzzer:fuzztest", "tonativepointer_fuzzer:fuzztest", - "trycatch_fuzzer:fuzztest", - "typedarrayref_fuzzer:fuzztest", "uint16arrayrefnew_fuzzer:fuzztest", "uint32arrayrefbytelength_fuzzer:fuzztest", "uint32arrayrefnew_fuzzer:fuzztest", diff --git a/test/fuzztest/arrayref_fuzzer/BUILD.gn b/test/fuzztest/arrayref_fuzzer/BUILD.gn deleted file mode 100644 index ce65517e21e968122f89f61bb6fbf6836fa3f5ac..0000000000000000000000000000000000000000 --- a/test/fuzztest/arrayref_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("ArrayRefFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/arrayref_fuzzer" - - sources = [ "arrayref_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":ArrayRefFuzzTest" ] -} diff --git a/test/fuzztest/arrayref_fuzzer/arrayref_fuzzer.cpp b/test/fuzztest/arrayref_fuzzer/arrayref_fuzzer.cpp deleted file mode 100644 index 3695c011423f4e0fce0dbc86e1686fa206aa2e20..0000000000000000000000000000000000000000 --- a/test/fuzztest/arrayref_fuzzer/arrayref_fuzzer.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "arrayref_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - void ArrayRefNewFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - ArrayRef::New(vm, (uint32_t)size); - JSNApi::DestroyJSVM(vm); - } - - void ArrayRefGetValueAtFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - Local globalObject = JSNApi::GetGlobalObject(vm); - Local property = ArrayRef::New(vm, (uint32_t)size); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - [[maybe_unused]]Local value = property->GetValueAt(vm, globalObject, (uint32_t)size); - JSNApi::DestroyJSVM(vm); - } - - void ArrayRefLengthFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Local property = ArrayRef::New(vm, (uint32_t)size); - property->Length(vm); - JSNApi::DestroyJSVM(vm); - } - - void ArrayRefSetValueAtFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Local globalObject = JSNApi::GetGlobalObject(vm); - Local property = ArrayRef::New(vm, (uint32_t)size); - Local value = ObjectRef::New(vm); - [[maybe_unused]]bool result = property->SetValueAt(vm, globalObject, (uint32_t)size, value); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::ArrayRefNewFuzzerTest(data, size); - OHOS::ArrayRefGetValueAtFuzzerTest(data, size); - OHOS::ArrayRefLengthFuzzerTest(data, size); - OHOS::ArrayRefSetValueAtFuzzerTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/dataviewref_fuzzer/BUILD.gn b/test/fuzztest/dataviewref_fuzzer/BUILD.gn deleted file mode 100644 index 0dbaec0afb0a7faff65a1ddcc94e504e6eb4023d..0000000000000000000000000000000000000000 --- a/test/fuzztest/dataviewref_fuzzer/BUILD.gn +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -##################################hydra-fuzz################################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -##################################fuzztest##################################### -ohos_fuzztest("DataViewRefFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/dataviewref_fuzzer" - - resource_config_file = "$js_root/test/resource/js_runtime/ohos_test.xml" - - sources = [ "dataviewref_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime_test", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":DataViewRefFuzzTest" ] -} diff --git a/test/fuzztest/dataviewref_fuzzer/corpus/init b/test/fuzztest/dataviewref_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/dataviewref_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/dataviewref_fuzzer/dataviewref_fuzzer.cpp b/test/fuzztest/dataviewref_fuzzer/dataviewref_fuzzer.cpp deleted file mode 100644 index 6d74730211616d551cb62e5c9d80375164d66d7f..0000000000000000000000000000000000000000 --- a/test/fuzztest/dataviewref_fuzzer/dataviewref_fuzzer.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "dataviewref_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/base/utf_helper.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { -void DataViewRefByteOffSetFuzzTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - const int32_t length = 15; - Local arrayBuffer = ArrayBufferRef::New(vm, length); - const uint32_t byteOffset = 5; - const uint32_t byteLength = 7; - Local dataView = DataViewRef::New(vm, arrayBuffer, byteOffset, byteLength); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - (void)dataView->ByteOffset(); - JSNApi::DestroyJSVM(vm); -} - -void DataViewRefByteLengthFuzzTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - const int32_t length = 15; - Local arrayBuffer = ArrayBufferRef::New(vm, length); - const uint32_t byteOffset = 5; - const uint32_t byteLength = 7; - Local dataView = DataViewRef::New(vm, arrayBuffer, byteOffset, byteLength); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - (void)dataView->ByteLength(); - JSNApi::DestroyJSVM(vm); -} - -void DataViewRefGetArrayBufferFuzzTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - const int32_t length = 15; - Local arrayBuffer = ArrayBufferRef::New(vm, length); - const uint32_t byteOffset = 5; - const uint32_t byteLength = 7; - Local dataView = DataViewRef::New(vm, arrayBuffer, byteOffset, byteLength); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - (void)dataView->GetArrayBuffer(vm); - JSNApi::DestroyJSVM(vm); -} -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - // Run your code on data. - OHOS::DataViewRefByteOffSetFuzzTest(data, size); - OHOS::DataViewRefByteLengthFuzzTest(data, size); - OHOS::DataViewRefGetArrayBufferFuzzTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/deleteworker_fuzzer/BUILD.gn b/test/fuzztest/deleteworker_fuzzer/BUILD.gn deleted file mode 100644 index e3423347937eb0ff26c17caaabf63f41ef406243..0000000000000000000000000000000000000000 --- a/test/fuzztest/deleteworker_fuzzer/BUILD.gn +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -##################################hydra-fuzz################################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -##################################fuzztest##################################### -ohos_fuzztest("DeleteWorkerFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/deleteworker_fuzzer" - - resource_config_file = "$js_root/test/resource/js_runtime/ohos_test.xml" - - sources = [ "deleteworker_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime_test", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":DeleteWorkerFuzzTest" ] -} diff --git a/test/fuzztest/deleteworker_fuzzer/corpus/init b/test/fuzztest/deleteworker_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/deleteworker_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/deleteworker_fuzzer/deleteworker_fuzzer.cpp b/test/fuzztest/deleteworker_fuzzer/deleteworker_fuzzer.cpp deleted file mode 100644 index 1b05f28dad02835d86cdceb5bb3b956234704a37..0000000000000000000000000000000000000000 --- a/test/fuzztest/deleteworker_fuzzer/deleteworker_fuzzer.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "deleteworker_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/base/utf_helper.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; -using namespace panda::ecmascript::base::utf_helper; - -namespace OHOS { - void DeleteWorkerFuzzTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - JSNApi::DeleteWorker(vm, nullptr); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::DeleteWorkerFuzzTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/deleteworker_fuzzer/deleteworker_fuzzer.h b/test/fuzztest/deleteworker_fuzzer/deleteworker_fuzzer.h deleted file mode 100644 index b01cce81126853721106052eccdd304444379407..0000000000000000000000000000000000000000 --- a/test/fuzztest/deleteworker_fuzzer/deleteworker_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DELETEWORKER_FUZZER_H -#define DELETEWORKER_FUZZER_H - -#define FUZZ_PROJECT_NAME "deleteworker_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/executionscope_fuzzer/BUILD.gn b/test/fuzztest/executionscope_fuzzer/BUILD.gn deleted file mode 100644 index 1c95cefcc2af298b8611f818a9fcb7d1d0017491..0000000000000000000000000000000000000000 --- a/test/fuzztest/executionscope_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -############################hydra-fuzz############################## -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -############################fuzztest################################ -ohos_fuzztest("ExecutionScopeFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/executionscope_fuzzer" - - sources = [ "executionscope_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":ExecutionScopeFuzzTest" ] -} diff --git a/test/fuzztest/executionscope_fuzzer/corpus/init b/test/fuzztest/executionscope_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/executionscope_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/executionscope_fuzzer/executionscope_fuzzer.cpp b/test/fuzztest/executionscope_fuzzer/executionscope_fuzzer.cpp deleted file mode 100644 index c51372b92106d88726eef27f4a193290ba66b99f..0000000000000000000000000000000000000000 --- a/test/fuzztest/executionscope_fuzzer/executionscope_fuzzer.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "executionscope_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/base/utf_helper.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; -namespace OHOS { - void ExecutionScopeFuzzTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetGcType(RuntimeOption::GC_TYPE::GEN_GC); - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - auto vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - JSExecutionScope jsexecutionScope(vm); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::ExecutionScopeFuzzTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/executionscope_fuzzer/executionscope_fuzzer.h b/test/fuzztest/executionscope_fuzzer/executionscope_fuzzer.h deleted file mode 100644 index 8b8e74c49fedbdbc5457f8b6bdfae31fa0f22960..0000000000000000000000000000000000000000 --- a/test/fuzztest/executionscope_fuzzer/executionscope_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef EXECUTIONSCOPE_FUZZER_H -#define EXECUTIONSCOPE_FUZZER_H - -#define FUZZ_PROJECT_NAME "executionscope_fuzzer" - -#endif \ No newline at end of file diff --git a/test/fuzztest/arrayref_fuzzer/project.xml b/test/fuzztest/functionrefgetfunctionprototype_fuzzer/project.xml similarity index 100% rename from test/fuzztest/arrayref_fuzzer/project.xml rename to test/fuzztest/functionrefgetfunctionprototype_fuzzer/project.xml diff --git a/test/fuzztest/functionrefgetfunctionprototype_fuzzer/projiect.xml b/test/fuzztest/functionrefgetfunctionprototype_fuzzer/projiect.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/functionrefgetfunctionprototype_fuzzer/projiect.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/dataviewref_fuzzer/project.xml b/test/fuzztest/functionrefisnative_fuzzer/project.xml similarity index 100% rename from test/fuzztest/dataviewref_fuzzer/project.xml rename to test/fuzztest/functionrefisnative_fuzzer/project.xml diff --git a/test/fuzztest/functionrefisnative_fuzzer/projiect.xml b/test/fuzztest/functionrefisnative_fuzzer/projiect.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/functionrefisnative_fuzzer/projiect.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/deleteworker_fuzzer/project.xml b/test/fuzztest/functionrefname_fuzzer/project.xml similarity index 100% rename from test/fuzztest/deleteworker_fuzzer/project.xml rename to test/fuzztest/functionrefname_fuzzer/project.xml diff --git a/test/fuzztest/functionrefname_fuzzer/projiect.xml b/test/fuzztest/functionrefname_fuzzer/projiect.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/functionrefname_fuzzer/projiect.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/getassetpath_fuzzer/BUILD.gn b/test/fuzztest/getassetpath_fuzzer/BUILD.gn deleted file mode 100644 index 9cbcf356e8283e8e8fab70ed2a32a06a2f5321f9..0000000000000000000000000000000000000000 --- a/test/fuzztest/getassetpath_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("GetAssetPathFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/getassetpath_fuzzer" - - sources = [ "getassetpath_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":GetAssetPathFuzzTest" ] -} diff --git a/test/fuzztest/getassetpath_fuzzer/corpus/init b/test/fuzztest/getassetpath_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/getassetpath_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/getassetpath_fuzzer/getassetpath_fuzzer.cpp b/test/fuzztest/getassetpath_fuzzer/getassetpath_fuzzer.cpp deleted file mode 100644 index 4c83a4683391f693e67a80a4b4d524f01e1e6abf..0000000000000000000000000000000000000000 --- a/test/fuzztest/getassetpath_fuzzer/getassetpath_fuzzer.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "getassetpath_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - void GetAssetPathFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - std::string str = "/data/storage/el1/bundle/moduleName/ets/modules.abc"; - JSNApi::SetAssetPath(vm, str); - [[maybe_unused]]std::string res = JSNApi::GetAssetPath(vm); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::GetAssetPathFuzzerTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/getassetpath_fuzzer/getassetpath_fuzzer.h b/test/fuzztest/getassetpath_fuzzer/getassetpath_fuzzer.h deleted file mode 100644 index 92de07a8b491a7052dcd23f60be34da5e58d0788..0000000000000000000000000000000000000000 --- a/test/fuzztest/getassetpath_fuzzer/getassetpath_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef GETASSETPATH_FUZZER_H -#define GETASSETPATH_FUZZER_H - -#define FUZZ_PROJECT_NAME "getassetpath_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/getassetpath_fuzzer/project.xml b/test/fuzztest/getassetpath_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/getassetpath_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/globalclass_fuzzer/BUILD.gn b/test/fuzztest/globalclass_fuzzer/BUILD.gn deleted file mode 100644 index 468dd66e93c11046f9bc598b4099f33977c9f4b4..0000000000000000000000000000000000000000 --- a/test/fuzztest/globalclass_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("GlobalClassFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/globalclass_fuzzer" - - sources = [ "globalclass_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":GlobalClassFuzzTest" ] -} diff --git a/test/fuzztest/globalclass_fuzzer/corpus/init b/test/fuzztest/globalclass_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/globalclass_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/globalclass_fuzzer/globalclass_fuzzer.cpp b/test/fuzztest/globalclass_fuzzer/globalclass_fuzzer.cpp deleted file mode 100644 index d08a99cad93503f2550c0549bc0c95f44be25798..0000000000000000000000000000000000000000 --- a/test/fuzztest/globalclass_fuzzer/globalclass_fuzzer.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" -#include "globalclass_fuzzer.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { -void GlobalFuzzerTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - { - JsiFastNativeScope scope(vm); - Global param; - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - [[maybe_unused]]Global global(param); - } - JSNApi::DestroyJSVM(vm); -} - -void GlobalOperatorEqualFuzzerTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - { - JsiFastNativeScope scope(vm); - Global param; - Global global; - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - global = param; - } - JSNApi::DestroyJSVM(vm); -} - -void GlobalMoveFuzzerTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - { - JsiFastNativeScope scope(vm); - Global param; - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - [[maybe_unused]]Global global(std::move(param)); - } - JSNApi::DestroyJSVM(vm); -} - -void GlobalOperatorEqualMoveFuzzerTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - { - JsiFastNativeScope scope(vm); - Global param; - Global global; - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - global = std::move(param); - } - JSNApi::DestroyJSVM(vm); -} - -void GlobalVMLocalFuzzerTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - { - JsiFastNativeScope scope(vm); - Local current = BooleanRef::New(vm, true); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global(vm, current); - } - JSNApi::DestroyJSVM(vm); -} -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - // Run your code on data. - OHOS::GlobalFuzzerTest(data, size); - OHOS::GlobalOperatorEqualFuzzerTest(data, size); - OHOS::GlobalMoveFuzzerTest(data, size); - OHOS::GlobalOperatorEqualMoveFuzzerTest(data, size); - OHOS::GlobalVMLocalFuzzerTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/globalclass_fuzzer/globalclass_fuzzer.h b/test/fuzztest/globalclass_fuzzer/globalclass_fuzzer.h deleted file mode 100644 index 56ea37ff9f531a5474e1855889c25161a31c6aac..0000000000000000000000000000000000000000 --- a/test/fuzztest/globalclass_fuzzer/globalclass_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef GLOBALCLASS_FUZZER_H -#define GLOBALCLASS_FUZZER_H - -#define FUZZ_PROJECT_NAME "globalclass_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/globalclass_fuzzer/project.xml b/test/fuzztest/globalclass_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/globalclass_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/isquickfixcausedexception_fuzzer/BUILD.gn b/test/fuzztest/isquickfixcausedexception_fuzzer/BUILD.gn deleted file mode 100644 index 709a5743c90a5bc0e7c7abc325bf12c2383fbd8c..0000000000000000000000000000000000000000 --- a/test/fuzztest/isquickfixcausedexception_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("IsQuickFixCausedExceptionFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/isquickfixcausedexception_fuzzer" - - sources = [ "isquickfixcausedexception_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":IsQuickFixCausedExceptionFuzzTest" ] -} diff --git a/test/fuzztest/isquickfixcausedexception_fuzzer/corpus/init b/test/fuzztest/isquickfixcausedexception_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/isquickfixcausedexception_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/isquickfixcausedexception_fuzzer/isquickfixcausedexception_fuzzer.cpp b/test/fuzztest/isquickfixcausedexception_fuzzer/isquickfixcausedexception_fuzzer.cpp deleted file mode 100644 index 55cfad21a2417c5d536153d17c11fc7e6eb010e8..0000000000000000000000000000000000000000 --- a/test/fuzztest/isquickfixcausedexception_fuzzer/isquickfixcausedexception_fuzzer.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "isquickfixcausedexception_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - void IsQuickFixCausedExceptionFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - std::string patchFileName = "index.abc"; - Local exception = JSNApi::GetAndClearUncaughtException(vm); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - JSNApi::IsQuickFixCausedException(vm, exception, patchFileName); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::IsQuickFixCausedExceptionFuzzerTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/isquickfixcausedexception_fuzzer/isquickfixcausedexception_fuzzer.h b/test/fuzztest/isquickfixcausedexception_fuzzer/isquickfixcausedexception_fuzzer.h deleted file mode 100644 index 31205d046530bffc906fe7d8380cf721dfc5cf2c..0000000000000000000000000000000000000000 --- a/test/fuzztest/isquickfixcausedexception_fuzzer/isquickfixcausedexception_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ISQUICKFIXCAUSEDEXCEPTION_FUZZER_H -#define ISQUICKFIXCAUSEDEXCEPTION_FUZZER_H - -#define FUZZ_PROJECT_NAME "isquickfixcausedexception_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/isquickfixcausedexception_fuzzer/project.xml b/test/fuzztest/isquickfixcausedexception_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/isquickfixcausedexception_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/jsnapiexceptions_fuzzer/jsnapiexceptions_fuzzer.cpp b/test/fuzztest/jsnapiexceptions_fuzzer/jsnapiexceptions_fuzzer.cpp index 30533ff990c091ef95206f1434412a5c44df04ac..d2b7b6653d8675b4afaa297fac773bc8a8a20fb7 100644 --- a/test/fuzztest/jsnapiexceptions_fuzzer/jsnapiexceptions_fuzzer.cpp +++ b/test/fuzztest/jsnapiexceptions_fuzzer/jsnapiexceptions_fuzzer.cpp @@ -34,19 +34,8 @@ void JSNApiGetAndClearUncaughtExceptionFuzzTest(const uint8_t *data, size_t size Local message = StringRef::NewFromUtf8(vm, (char *)data, (int)size); Local error = Exception::Error(vm, message); JSNApi::ThrowException(vm, error); - JSNApi::GetAndClearUncaughtException(vm); - JSNApi::DestroyJSVM(vm); -} - -void JSNApiPrintExceptionInfoFuzzTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - return; - } JSNApi::PrintExceptionInfo(vm); + JSNApi::GetAndClearUncaughtException(vm); JSNApi::DestroyJSVM(vm); } @@ -71,7 +60,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Run your code on data. OHOS::JSNApiGetAndClearUncaughtExceptionFuzzTest(data, size); - OHOS::JSNApiPrintExceptionInfoFuzzTest(data, size); OHOS::JSNApiThrowExceptionFuzzTest(data, size); return 0; } \ No newline at end of file diff --git a/test/fuzztest/jsnapifork_fuzzer/corpus/init b/test/fuzztest/jsnapifork_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/jsnapifork_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/jsnapifork_fuzzer/project.xml b/test/fuzztest/jsnapifork_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/jsnapifork_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/executionscope_fuzzer/project.xml b/test/fuzztest/jsnapistopdebugger_fuzzer/project.xml similarity index 100% rename from test/fuzztest/executionscope_fuzzer/project.xml rename to test/fuzztest/jsnapistopdebugger_fuzzer/project.xml diff --git a/test/fuzztest/jsnapistopdebugger_fuzzer/projiect.xml b/test/fuzztest/jsnapistopdebugger_fuzzer/projiect.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/jsnapistopdebugger_fuzzer/projiect.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/jsnapiunloadpatch_fuzzer/BUILD.gn b/test/fuzztest/jsnapiunloadpatch_fuzzer/BUILD.gn deleted file mode 100644 index 7d77999b0c6b14b4866ae7ee694ff62c7aa5bfb2..0000000000000000000000000000000000000000 --- a/test/fuzztest/jsnapiunloadpatch_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("JSNApiUnloadPatchFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/jsnapiunloadpatch_fuzzer" - - sources = [ "jsnapiunloadpatch_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":JSNApiUnloadPatchFuzzTest" ] -} diff --git a/test/fuzztest/jsnapiunloadpatch_fuzzer/corpus/init b/test/fuzztest/jsnapiunloadpatch_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/jsnapiunloadpatch_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/jsnapiunloadpatch_fuzzer/jsnapiunloadpatch_fuzzer.cpp b/test/fuzztest/jsnapiunloadpatch_fuzzer/jsnapiunloadpatch_fuzzer.cpp deleted file mode 100644 index 4bc50d02960952d6bca38c6b5baec5a5bf253f2a..0000000000000000000000000000000000000000 --- a/test/fuzztest/jsnapiunloadpatch_fuzzer/jsnapiunloadpatch_fuzzer.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "jsnapiunloadpatch_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - void JSNApiUnloadPatchTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - std::string patchFileName = "index.abc"; - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - JSNApi::UnloadPatch(vm, patchFileName); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::JSNApiUnloadPatchTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/jsnapiunloadpatch_fuzzer/jsnapiunloadpatch_fuzzer.h b/test/fuzztest/jsnapiunloadpatch_fuzzer/jsnapiunloadpatch_fuzzer.h deleted file mode 100644 index 2dbb059769d875ebf730a7313f7e83d007982445..0000000000000000000000000000000000000000 --- a/test/fuzztest/jsnapiunloadpatch_fuzzer/jsnapiunloadpatch_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef JSNAPIUNLOADPATCH_FUZZER_H -#define JSNAPIUNLOADPATCH_FUZZER_H - -#define FUZZ_PROJECT_NAME "jsnapiunloadpatch_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/jsnapiunloadpatch_fuzzer/project.xml b/test/fuzztest/jsnapiunloadpatch_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/jsnapiunloadpatch_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/loadpatch_fuzzer/BUILD.gn b/test/fuzztest/loadpatch_fuzzer/BUILD.gn deleted file mode 100644 index 89bd7c8205fc24846e3fef152df86e1c186d1d85..0000000000000000000000000000000000000000 --- a/test/fuzztest/loadpatch_fuzzer/BUILD.gn +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -##################################hydra-fuzz################################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -##################################fuzztest##################################### -ohos_fuzztest("LoadPatchFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/loadpatch_fuzzer" - - resource_config_file = "$js_root/test/resource/js_runtime/ohos_test.xml" - - sources = [ "loadpatch_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime_test", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":LoadPatchFuzzTest" ] -} diff --git a/test/fuzztest/loadpatch_fuzzer/corpus/init b/test/fuzztest/loadpatch_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/loadpatch_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/loadpatch_fuzzer/loadpatch_fuzzer.cpp b/test/fuzztest/loadpatch_fuzzer/loadpatch_fuzzer.cpp deleted file mode 100644 index 9e050313f4068ffa1c2e9f7e1f84cbb90ed32c2e..0000000000000000000000000000000000000000 --- a/test/fuzztest/loadpatch_fuzzer/loadpatch_fuzzer.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "loadpatch_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - void LoadPatchFuzzTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - std::string baseFileName = "index.abc"; - std::string patchFileName = "index.abc"; - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - JSNApi::LoadPatch(vm, patchFileName, baseFileName); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::LoadPatchFuzzTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/loadpatch_fuzzer/loadpatch_fuzzer.h b/test/fuzztest/loadpatch_fuzzer/loadpatch_fuzzer.h deleted file mode 100644 index 6a3cba24ca8d5e63cc8ed549f7f5d412443d96ab..0000000000000000000000000000000000000000 --- a/test/fuzztest/loadpatch_fuzzer/loadpatch_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LOADPATCH_FUZZER_H -#define LOADPATCH_FUZZER_H - -#define FUZZ_PROJECT_NAME "loadpatch_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/loadpatch_fuzzer/project.xml b/test/fuzztest/loadpatch_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/loadpatch_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/objectcast_fuzzer/BUILD.gn b/test/fuzztest/objectcast_fuzzer/BUILD.gn deleted file mode 100644 index f92ed495bcfd9da42f36c157f808918ab4a50928..0000000000000000000000000000000000000000 --- a/test/fuzztest/objectcast_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("ObjectCastFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/objectcast_fuzzer" - - sources = [ "objectcast_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":ObjectCastFuzzTest" ] -} diff --git a/test/fuzztest/objectcast_fuzzer/corpus/init b/test/fuzztest/objectcast_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/objectcast_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/objectcast_fuzzer/objectcast_fuzzer.h b/test/fuzztest/objectcast_fuzzer/objectcast_fuzzer.h deleted file mode 100644 index c8172afd2b5acbf665a5d283f64bb70ae3cce15f..0000000000000000000000000000000000000000 --- a/test/fuzztest/objectcast_fuzzer/objectcast_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OBJECTCAST_FUZZER_H -#define OBJECTCAST_FUZZER_H - -#define FUZZ_PROJECT_NAME "objectcast_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/objectcast_fuzzer/project.xml b/test/fuzztest/objectcast_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/objectcast_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/primitiverefgetvalue_fuzzer/BUILD.gn b/test/fuzztest/primitiverefgetvalue_fuzzer/BUILD.gn index e47e59bcab2d853b05964b43b238a0c21cbefabf..8df77b2db9b49e3d0e9d01eab15c11ca33203971 100644 --- a/test/fuzztest/primitiverefgetvalue_fuzzer/BUILD.gn +++ b/test/fuzztest/primitiverefgetvalue_fuzzer/BUILD.gn @@ -18,7 +18,7 @@ import("//build/config/features.gni") import("//build/ohos.gni") ##################################fuzztest##################################### -ohos_fuzztest("PrimitiveRefGetValueFuzztest") { +ohos_fuzztest("PrimitiveRefGetValueFuzzTest") { module_out_path = ets_runtime_output_path fuzz_config_file = "$js_root/test/fuzztest/primitiverefgetvalue_fuzzer" @@ -40,5 +40,5 @@ ohos_fuzztest("PrimitiveRefGetValueFuzztest") { group("fuzztest") { testonly = true deps = [] - deps += [ ":PrimitiveRefGetValueFuzztest" ] + deps += [ ":PrimitiveRefGetValueFuzzTest" ] } diff --git a/test/fuzztest/primitiverefgetvalue_fuzzer/primitiverefgetvalue_fuzzer.cpp b/test/fuzztest/primitiverefgetvalue_fuzzer/primitiverefgetvalue_fuzzer.cpp index 68d9c488b3cda454317f42875bce6ac3f24c58ea..45544989a85dd71780603b4b3a20193be6fe6888 100644 --- a/test/fuzztest/primitiverefgetvalue_fuzzer/primitiverefgetvalue_fuzzer.cpp +++ b/test/fuzztest/primitiverefgetvalue_fuzzer/primitiverefgetvalue_fuzzer.cpp @@ -28,7 +28,7 @@ using namespace panda; using namespace panda::ecmascript; namespace OHOS { -void PrimitiveRefGetValueFuzztest([[maybe_unused]]const uint8_t *data, size_t size) +void PrimitiveRefGetValueFuzzTest([[maybe_unused]]const uint8_t *data, size_t size) { RuntimeOption option; option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); @@ -56,6 +56,6 @@ void PrimitiveRefGetValueFuzztest([[maybe_unused]]const uint8_t *data, size_t si extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Run your code on data. - OHOS::PrimitiveRefGetValueFuzztest(data, size); + OHOS::PrimitiveRefGetValueFuzzTest(data, size); return 0; } \ No newline at end of file diff --git a/test/fuzztest/promisecapabilityref_fuzzer/BUILD.gn b/test/fuzztest/promisecapabilityref_fuzzer/BUILD.gn deleted file mode 100644 index 65161ed0b86c2d143c4af328ffb187f39ea2eb07..0000000000000000000000000000000000000000 --- a/test/fuzztest/promisecapabilityref_fuzzer/BUILD.gn +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -##################################hydra-fuzz################################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -##################################fuzztest##################################### -ohos_fuzztest("PromiseCapabilityRefFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/promisecapabilityref_fuzzer" - - resource_config_file = "$js_root/test/resource/js_runtime/ohos_test.xml" - - sources = [ "promisecapabilityref_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime_test", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":PromiseCapabilityRefFuzzTest" ] -} diff --git a/test/fuzztest/promisecapabilityref_fuzzer/corpus/init b/test/fuzztest/promisecapabilityref_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/promisecapabilityref_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/promisecapabilityref_fuzzer/project.xml b/test/fuzztest/promisecapabilityref_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/promisecapabilityref_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/promisecapabilityref_fuzzer/promisecapabilityref_fuzzer.cpp b/test/fuzztest/promisecapabilityref_fuzzer/promisecapabilityref_fuzzer.cpp deleted file mode 100644 index d6217b9c19ca35d05c643683e23d12fd77dc7aca..0000000000000000000000000000000000000000 --- a/test/fuzztest/promisecapabilityref_fuzzer/promisecapabilityref_fuzzer.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "promisecapabilityref_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - void PromiseCapabilityRefNewFuzzTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - [[maybe_unused]]Local capability = PromiseCapabilityRef::New(vm); - JSNApi::DestroyJSVM(vm); - } - - void PromiseCapabilityRefResolveFuzzTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Local capability = PromiseCapabilityRef::New(vm); - Local value = NumberRef::New(vm, (double)size); - capability->Resolve(vm, value); - JSNApi::DestroyJSVM(vm); - } - - void PromiseCapabilityRefRejectFuzzTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Local capability = PromiseCapabilityRef::New(vm); - Local value = NumberRef::New(vm, (double)size); - capability->Resolve(vm, value); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::PromiseCapabilityRefNewFuzzTest(data, size); - OHOS::PromiseCapabilityRefResolveFuzzTest(data, size); - OHOS::PromiseCapabilityRefRejectFuzzTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/promisecapabilityref_fuzzer/promisecapabilityref_fuzzer.h b/test/fuzztest/promisecapabilityref_fuzzer/promisecapabilityref_fuzzer.h deleted file mode 100644 index c36dc3524b783c3b451542c492675915516f39c4..0000000000000000000000000000000000000000 --- a/test/fuzztest/promisecapabilityref_fuzzer/promisecapabilityref_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PROMISECAPABILITYREF_FUZZER_H -#define PROMISECAPABILITYREF_FUZZER_H - -#define FUZZ_PROJECT_NAME "promisecapabilityref_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/promiserejectinfo_fuzzer/promiserejectinfo_fuzzer.cpp b/test/fuzztest/promiserejectinfo_fuzzer/promiserejectinfo_fuzzer.cpp index 9de846a11e81adf2729e83549f79e698c70e5996..24060cbe4304a7d8304c0c746a9c594a813b627e 100644 --- a/test/fuzztest/promiserejectinfo_fuzzer/promiserejectinfo_fuzzer.cpp +++ b/test/fuzztest/promiserejectinfo_fuzzer/promiserejectinfo_fuzzer.cpp @@ -42,20 +42,6 @@ namespace OHOS { JSNApi::DestroyJSVM(vm); } - void GetPromiseFuzzTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Local capability = PromiseCapabilityRef::New(vm); - [[maybe_unused]]Local promise = capability->GetPromise(vm); - JSNApi::DestroyJSVM(vm); - } - void GetDataFuzzTest(const uint8_t* data, size_t size) { RuntimeOption option; @@ -138,7 +124,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Run your code on data. OHOS::PromiseRejectInfoNewFuzzTest(data, size); - OHOS::GetPromiseFuzzTest(data, size); OHOS::GetDataFuzzTest(data, size); OHOS::PromiseRejectInfoGetPromiseFuzzTest(data, size); OHOS::PromiseRejectInfoGetReasonFuzzTest(data, size); diff --git a/test/fuzztest/publicapilocal_fuzzer/BUILD.gn b/test/fuzztest/publicapilocal_fuzzer/BUILD.gn deleted file mode 100644 index 798e6d96f625d04cf24e1201fb9b7655f0a23536..0000000000000000000000000000000000000000 --- a/test/fuzztest/publicapilocal_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("PublicApiLocalFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/publicapilocal_fuzzer" - - sources = [ "publicapilocal_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":PublicApiLocalFuzzTest" ] -} diff --git a/test/fuzztest/publicapilocal_fuzzer/corpus/init b/test/fuzztest/publicapilocal_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/publicapilocal_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/publicapilocal_fuzzer/project.xml b/test/fuzztest/publicapilocal_fuzzer/project.xml deleted file mode 100644 index 864ad9ba8ea52c43faa7644a41ecd048a03c5b32..0000000000000000000000000000000000000000 --- a/test/fuzztest/publicapilocal_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/publicapilocal_fuzzer/publicapilocal_fuzzer.cpp b/test/fuzztest/publicapilocal_fuzzer/publicapilocal_fuzzer.cpp deleted file mode 100644 index c1cef9942af8a20e782ccdf896fe4450a5c5b5df..0000000000000000000000000000000000000000 --- a/test/fuzztest/publicapilocal_fuzzer/publicapilocal_fuzzer.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "publicapilocal_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { -void LocalIsEmptyFuzzTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Local intValue = IntegerRef::New(vm, (int)size); - intValue.IsEmpty(); - JSNApi::DestroyJSVM(vm); -} - -void LocalIsNullFuzzTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Local intValue = IntegerRef::New(vm, (int)size); - intValue.IsNull(); - JSNApi::DestroyJSVM(vm); -} -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - // Run your code on data. - OHOS::LocalIsEmptyFuzzTest(data, size); - OHOS::LocalIsNullFuzzTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/publicapilocal_fuzzer/publicapilocal_fuzzer.h b/test/fuzztest/publicapilocal_fuzzer/publicapilocal_fuzzer.h deleted file mode 100644 index cf5114438b14e81e04bbcbe6fb69583d2f1adba0..0000000000000000000000000000000000000000 --- a/test/fuzztest/publicapilocal_fuzzer/publicapilocal_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PUBLICAPILOCAL_FUZZER_H -#define PUBLICAPILOCAL_FUZZER_H - -#define FUZZ_PROJECT_NAME "publicapilocal_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/BUILD.gn b/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/BUILD.gn deleted file mode 100644 index 7b3ade8526c7ae0985c3cf96a40109ff606b5513..0000000000000000000000000000000000000000 --- a/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/BUILD.gn +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("PublicApiLocalOperatorSymbolFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = - "$js_root/test/fuzztest/publicapilocaloperatorsymbol_fuzzer" - - sources = [ "publicapilocaloperatorsymbol_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":PublicApiLocalOperatorSymbolFuzzTest" ] -} diff --git a/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/corpus/init b/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/project.xml b/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/project.xml deleted file mode 100644 index 864ad9ba8ea52c43faa7644a41ecd048a03c5b32..0000000000000000000000000000000000000000 --- a/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/publicapilocaloperatorsymbol_fuzzer.cpp b/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/publicapilocaloperatorsymbol_fuzzer.cpp deleted file mode 100644 index 352c18480cfbed5aeaeac772032fe43c91ff35e1..0000000000000000000000000000000000000000 --- a/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/publicapilocaloperatorsymbol_fuzzer.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "publicapilocaloperatorsymbol_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { -void LocalOperatorOneFuzzTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Local intValue = IntegerRef::New(vm, (int)size); - intValue.operator->(); - JSNApi::DestroyJSVM(vm); -} - -void LocalOperatorTowFuzzTest([[maybe_unused]]const uint8_t *data, size_t size) -{ - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Local intValue = IntegerRef::New(vm, (int)size); - intValue.operator*(); - JSNApi::DestroyJSVM(vm); -} -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - // Run your code on data. - OHOS::LocalOperatorOneFuzzTest(data, size); - OHOS::LocalOperatorTowFuzzTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/publicapilocaloperatorsymbol_fuzzer.h b/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/publicapilocaloperatorsymbol_fuzzer.h deleted file mode 100644 index c575cca3410147a796190ced54cc1edc189d6b60..0000000000000000000000000000000000000000 --- a/test/fuzztest/publicapilocaloperatorsymbol_fuzzer/publicapilocaloperatorsymbol_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PUBLICAPILOCALOPERATORSYMBOL_FUZZER_H -#define PUBLICAPILOCALOPERATORSYMBOL_FUZZER_H - -#define FUZZ_PROJECT_NAME "publicapilocaloperatorsymbol_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/registerquickfixqueryfunc_fuzzer/BUILD.gn b/test/fuzztest/registerquickfixqueryfunc_fuzzer/BUILD.gn deleted file mode 100644 index 63cb4502bcf8e769a6f245cef6d0e9905f52bcf6..0000000000000000000000000000000000000000 --- a/test/fuzztest/registerquickfixqueryfunc_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("RegisterQuickFixQueryFuncFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/registerquickfixqueryfunc_fuzzer" - - sources = [ "registerquickfixqueryfunc_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":RegisterQuickFixQueryFuncFuzzTest" ] -} diff --git a/test/fuzztest/registerquickfixqueryfunc_fuzzer/corpus/init b/test/fuzztest/registerquickfixqueryfunc_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/registerquickfixqueryfunc_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/registerquickfixqueryfunc_fuzzer/project.xml b/test/fuzztest/registerquickfixqueryfunc_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/registerquickfixqueryfunc_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/registerquickfixqueryfunc_fuzzer/registerquickfixqueryfunc_fuzzer.cpp b/test/fuzztest/registerquickfixqueryfunc_fuzzer/registerquickfixqueryfunc_fuzzer.cpp deleted file mode 100644 index 51f8d14e61a63edf9ae92c9857abc07cd554efb9..0000000000000000000000000000000000000000 --- a/test/fuzztest/registerquickfixqueryfunc_fuzzer/registerquickfixqueryfunc_fuzzer.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "registerquickfixqueryfunc_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - bool QuickFixQueryFunc(std::string baseFileName, std::string &patchFileName, uint8_t **patchBuffer, - size_t &patchBufferSize) - { - if (baseFileName != "multi_file/base/merge.abc") { - return false; - } - patchFileName = "__index.pa"; - const char *data = R"( - .function void foo() {} - )"; - char *bufferData = new char[strlen(data) + 1]; - size_t dataSize = strlen(data) + 1; - strcpy_s(bufferData, dataSize, data); - *patchBuffer = reinterpret_cast(bufferData); - patchBufferSize = strlen(data); - return true; - } - void RegisterQuickFixQueryFuncFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - JSNApi::RegisterQuickFixQueryFunc(vm, QuickFixQueryFunc); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::RegisterQuickFixQueryFuncFuzzerTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/registerquickfixqueryfunc_fuzzer/registerquickfixqueryfunc_fuzzer.h b/test/fuzztest/registerquickfixqueryfunc_fuzzer/registerquickfixqueryfunc_fuzzer.h deleted file mode 100644 index 3a32ac25a488ca96c5b85b7a870674020b2b5a6a..0000000000000000000000000000000000000000 --- a/test/fuzztest/registerquickfixqueryfunc_fuzzer/registerquickfixqueryfunc_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef REGISTERQUICKFIXQUERYFUNC_FUZZER_H -#define REGISTERQUICKFIXQUERYFUNC_FUZZER_H - -#define FUZZ_PROJECT_NAME "registerquickfixqueryfunc_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/setiteratorrefget_fuzzer/BUILD.gn b/test/fuzztest/setiteratorrefget_fuzzer/BUILD.gn index f5d570ebed6668f4b9a535331585ac3205eabaa5..3d7bfa7ee830b2ad33fc0bc80996710c0998fd2e 100644 --- a/test/fuzztest/setiteratorrefget_fuzzer/BUILD.gn +++ b/test/fuzztest/setiteratorrefget_fuzzer/BUILD.gn @@ -18,7 +18,7 @@ import("//build/config/features.gni") import("//build/ohos.gni") ##################################fuzztest##################################### -ohos_fuzztest("SetIteratorRefGetFuzztest") { +ohos_fuzztest("SetIteratorRefGetFuzzTest") { module_out_path = ets_runtime_output_path fuzz_config_file = "$js_root/test/fuzztest/setiteratorrefget_fuzzer" @@ -40,5 +40,5 @@ ohos_fuzztest("SetIteratorRefGetFuzztest") { group("fuzztest") { testonly = true deps = [] - deps += [ ":SetIteratorRefGetFuzztest" ] + deps += [ ":SetIteratorRefGetFuzzTest" ] } diff --git a/test/fuzztest/setiteratorrefget_fuzzer/setiteratorrefget_fuzzer.cpp b/test/fuzztest/setiteratorrefget_fuzzer/setiteratorrefget_fuzzer.cpp index 9f2d4471830c45e9192662d70b5cf0ee6c486904..9c24c8ff505fae62a5d46cdeccf3865c9a8360d0 100644 --- a/test/fuzztest/setiteratorrefget_fuzzer/setiteratorrefget_fuzzer.cpp +++ b/test/fuzztest/setiteratorrefget_fuzzer/setiteratorrefget_fuzzer.cpp @@ -43,7 +43,7 @@ JSSet *CreateJSSet(JSThread *thread) return JSSet::Cast(set.GetTaggedValue().GetTaggedObject()); } -void SetIteratorRefGetFuzztest([[maybe_unused]]const uint8_t *data, size_t size) +void SetIteratorRefGetFuzzTest([[maybe_unused]]const uint8_t *data, size_t size) { RuntimeOption option; option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); @@ -74,6 +74,6 @@ void SetIteratorRefGetFuzztest([[maybe_unused]]const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Run your code on data. - OHOS::SetIteratorRefGetFuzztest(data, size); + OHOS::SetIteratorRefGetFuzzTest(data, size); return 0; } \ No newline at end of file diff --git a/test/fuzztest/templateclassglobal_fuzzer/BUILD.gn b/test/fuzztest/templateclassglobal_fuzzer/BUILD.gn deleted file mode 100644 index f3add3f11e1b98c1ea531cb410a2d6f63316e04c..0000000000000000000000000000000000000000 --- a/test/fuzztest/templateclassglobal_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("TemplateClassGlobalFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/templateclassglobal_fuzzer" - - sources = [ "templateclassglobal_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":TemplateClassGlobalFuzzTest" ] -} diff --git a/test/fuzztest/templateclassglobal_fuzzer/corpus/init b/test/fuzztest/templateclassglobal_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/templateclassglobal_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/templateclassglobal_fuzzer/project.xml b/test/fuzztest/templateclassglobal_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/templateclassglobal_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/templateclassglobal_fuzzer/templateclassglobal_fuzzer.cpp b/test/fuzztest/templateclassglobal_fuzzer/templateclassglobal_fuzzer.cpp deleted file mode 100644 index 9123972d4e8556c93269c060b52cc8dff8e0d363..0000000000000000000000000000000000000000 --- a/test/fuzztest/templateclassglobal_fuzzer/templateclassglobal_fuzzer.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "templateclassglobal_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - void TemplateGlobalFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Local current = BooleanRef::New(vm, true); - [[maybe_unused]]Global global(vm, current); - JSNApi::DestroyJSVM(vm); - } - - void TemplateToLocalFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global(vm, BooleanRef::New(vm, true)); - [[maybe_unused]]Local local = global.ToLocal(); - JSNApi::DestroyJSVM(vm); - } - - void TemplateToLocalFromVMFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global(vm, BooleanRef::New(vm, true)); - [[maybe_unused]]Local local = global.ToLocal(vm); - JSNApi::DestroyJSVM(vm); - } - - void TemplateEmptyFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global(vm, BooleanRef::New(vm, true)); - global.Empty(); - JSNApi::DestroyJSVM(vm); - } - - void TemplateFreeGlobalHandleAddrFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global(vm, BooleanRef::New(vm, true)); - global.FreeGlobalHandleAddr(); - JSNApi::DestroyJSVM(vm); - } - - void GlobalOperatorStarFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global(vm, BooleanRef::New(vm, true)); - [[maybe_unused]]bool b = (*global)->BooleaValue(vm); - JSNApi::DestroyJSVM(vm); - } - - void GlobalOperatorPointToFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global(vm, BooleanRef::New(vm, true)); - [[maybe_unused]]bool b = global->BooleaValue(vm); - JSNApi::DestroyJSVM(vm); - } - - void GlobalIsEmptyFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global; - [[maybe_unused]]bool b = global.IsEmpty(); - JSNApi::DestroyJSVM(vm); - } - - void GlobalSetWeakFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global(vm, BooleanRef::New(vm, true)); - global.SetWeak(); - bool res = global.IsWeak(); - if (!res) { - LOG_ECMA(ERROR) << "SetWeak failed"; - return; - } - - JSNApi::DestroyJSVM(vm); - } - - void GlobalClearWeakFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global(vm, BooleanRef::New(vm, true)); - global.ClearWeak(); - JSNApi::DestroyJSVM(vm); - } - - void GlobalIsWeakFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - Global global(vm, BooleanRef::New(vm, true)); - global.SetWeak(); - [[maybe_unused]]bool b = global.IsWeak(); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::TemplateGlobalFuzzerTest(data, size); - OHOS::TemplateToLocalFuzzerTest(data, size); - OHOS::TemplateToLocalFromVMFuzzerTest(data, size); - OHOS::TemplateEmptyFuzzerTest(data, size); - OHOS::TemplateFreeGlobalHandleAddrFuzzerTest(data, size); - OHOS::GlobalOperatorStarFuzzerTest(data, size); - OHOS::GlobalOperatorPointToFuzzerTest(data, size); - OHOS::GlobalIsEmptyFuzzerTest(data, size); - OHOS::GlobalSetWeakFuzzerTest(data, size); - OHOS::GlobalClearWeakFuzzerTest(data, size); - OHOS::GlobalIsWeakFuzzerTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/templateclassglobal_fuzzer/templateclassglobal_fuzzer.h b/test/fuzztest/templateclassglobal_fuzzer/templateclassglobal_fuzzer.h deleted file mode 100644 index 3311e67b0614a771e44f9119722aad0024246694..0000000000000000000000000000000000000000 --- a/test/fuzztest/templateclassglobal_fuzzer/templateclassglobal_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TEMPLATECLASSGLOBAL_FUZZER_H -#define TEMPLATECLASSGLOBAL_FUZZER_H - -#define FUZZ_PROJECT_NAME "templateclassglobal_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/trycatch_fuzzer/BUILD.gn b/test/fuzztest/trycatch_fuzzer/BUILD.gn deleted file mode 100644 index 448b75fc33613e79e0c1d524abe447943735ce38..0000000000000000000000000000000000000000 --- a/test/fuzztest/trycatch_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("TryCatchFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/trycatch_fuzzer" - - sources = [ "trycatch_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime_test", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":TryCatchFuzzTest" ] -} diff --git a/test/fuzztest/trycatch_fuzzer/corpus/init b/test/fuzztest/trycatch_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/trycatch_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/trycatch_fuzzer/project.xml b/test/fuzztest/trycatch_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/trycatch_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/trycatch_fuzzer/trycatch_fuzzer.cpp b/test/fuzztest/trycatch_fuzzer/trycatch_fuzzer.cpp deleted file mode 100644 index 8b442f091c79326ac63cce9a5939398c923e646f..0000000000000000000000000000000000000000 --- a/test/fuzztest/trycatch_fuzzer/trycatch_fuzzer.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "trycatch_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - void TryCatchNewFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - TryCatch trycatch(vm); - JSNApi::DestroyJSVM(vm); - } - - void TryCatchHasCaughtFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - TryCatch trycatch(vm); - trycatch.HasCaught(); - JSNApi::DestroyJSVM(vm); - } - - void TryCatchRethrowFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - TryCatch trycatch(vm); - trycatch.Rethrow(); - JSNApi::DestroyJSVM(vm); - } - - void GetAndClearExceptionFuzzTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - TryCatch trycatch(vm); - trycatch.GetAndClearException(); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::TryCatchNewFuzzerTest(data, size); - OHOS::TryCatchHasCaughtFuzzerTest(data, size); - OHOS::TryCatchRethrowFuzzerTest(data, size); - OHOS::GetAndClearExceptionFuzzTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/trycatch_fuzzer/trycatch_fuzzer.h b/test/fuzztest/trycatch_fuzzer/trycatch_fuzzer.h deleted file mode 100644 index 93dfc09d2aceda4bb213551977308c5cb0cc31ca..0000000000000000000000000000000000000000 --- a/test/fuzztest/trycatch_fuzzer/trycatch_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TRYCATCH_FUZZER_H -#define TRYCATCH_FUZZER_H - -#define FUZZ_PROJECT_NAME "trycatch_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/typedarrayref_fuzzer/BUILD.gn b/test/fuzztest/typedarrayref_fuzzer/BUILD.gn deleted file mode 100644 index e41af57b53e0069a916bc78197d568f96192e0ff..0000000000000000000000000000000000000000 --- a/test/fuzztest/typedarrayref_fuzzer/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("TypedArrayrefFuzzTest") { - module_out_path = ets_runtime_output_path - - fuzz_config_file = "$js_root/test/fuzztest/typedarrayref_fuzzer" - - sources = [ "typedarrayref_fuzzer.cpp" ] - - configs = [ "$js_root:ecma_test_config" ] - - deps = [ - "$js_root:libark_jsruntime", - sdk_libc_secshared_dep, - ] - - # hiviewdfx libraries - external_deps = hiviewdfx_ext_deps - deps += hiviewdfx_deps -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":TypedArrayrefFuzzTest" ] -} diff --git a/test/fuzztest/typedarrayref_fuzzer/corpus/init b/test/fuzztest/typedarrayref_fuzzer/corpus/init deleted file mode 100644 index 69c5791762c2df3d7e43cb066be9cd8b56f80621..0000000000000000000000000000000000000000 --- a/test/fuzztest/typedarrayref_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/typedarrayref_fuzzer/project.xml b/test/fuzztest/typedarrayref_fuzzer/project.xml deleted file mode 100644 index 4fdbc407f205680885fa42663163b5c987f123a6..0000000000000000000000000000000000000000 --- a/test/fuzztest/typedarrayref_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/test/fuzztest/typedarrayref_fuzzer/typedarrayref_fuzzer.cpp b/test/fuzztest/typedarrayref_fuzzer/typedarrayref_fuzzer.cpp deleted file mode 100644 index 44cb5c5415bd21795b885d522ff598c22cf20e46..0000000000000000000000000000000000000000 --- a/test/fuzztest/typedarrayref_fuzzer/typedarrayref_fuzzer.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "typedarrayref_fuzzer.h" -#include "ecmascript/base/string_helper.h" -#include "ecmascript/napi/include/dfx_jsnapi.h" -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - void TypedArrayrefArrayLengthFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - constexpr int byteOffset = 5; - constexpr int length = 6; - Local arrayBuffer = ArrayBufferRef::New(vm, (int32_t)size); - Local typedArray = Int8ArrayRef::New(vm, arrayBuffer, byteOffset, length); - typedArray->ArrayLength(vm); - JSNApi::DestroyJSVM(vm); - } - - void TypedArrayrefByteOffSetFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - constexpr int byteOffset = 5; - constexpr int length = 6; - Local arrayBuffer = ArrayBufferRef::New(vm, (int32_t)size); - Local typedArray = Int8ArrayRef::New(vm, arrayBuffer, byteOffset, length); - typedArray->ByteOffset(vm); - JSNApi::DestroyJSVM(vm); - } - - void TypedArrayrefGetArrayBufferFuzzerTest([[maybe_unused]]const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - LOG_ECMA(ERROR) << "illegal input!"; - return; - } - constexpr int byteOffset = 5; - constexpr int length = 6; - Local arrayBuffer = ArrayBufferRef::New(vm, (int32_t)size); - Local typedArray = Int8ArrayRef::New(vm, arrayBuffer, byteOffset, length); - typedArray->GetArrayBuffer(vm); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::TypedArrayrefArrayLengthFuzzerTest(data, size); - OHOS::TypedArrayrefByteOffSetFuzzerTest(data, size); - OHOS::TypedArrayrefGetArrayBufferFuzzerTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/typedarrayref_fuzzer/typedarrayref_fuzzer.h b/test/fuzztest/typedarrayref_fuzzer/typedarrayref_fuzzer.h deleted file mode 100644 index 67b7a24be476848bd492f815ccd57173fed65b2d..0000000000000000000000000000000000000000 --- a/test/fuzztest/typedarrayref_fuzzer/typedarrayref_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TYPEDARRAYREF_FUZZER_H -#define TYPEDARRAYREF_FUZZER_H - -#define FUZZ_PROJECT_NAME "typedarrayref_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/jittest/BUILD.gn b/test/jittest/BUILD.gn index 5e7c1e4aba3ec56b606f87676dc99629381a04fd..d0d4ec82ac890cbd278531558b0d5cbee555ca8e 100644 --- a/test/jittest/BUILD.gn +++ b/test/jittest/BUILD.gn @@ -31,6 +31,7 @@ group("ark_jit_ts_test") { "addition_assignment", "catch_with_osr", "jit_test_0001", + "jit_test_0002", "string_length", "ts_inline", "proxy_fast_call", diff --git a/test/jittest/jit_test_0002/BUILD.gn b/test/jittest/jit_test_0002/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9c31b4d9c22e6d60d6aa3a9f6526a7b740368782 --- /dev/null +++ b/test/jittest/jit_test_0002/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_jit_test_action("jit_test_0002") { + deps = [] + extra_option = " --log-info=trace --compiler-trace-deopt=true " +} diff --git a/test/jittest/jit_test_0002/expect_output.txt b/test/jittest/jit_test_0002/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..e7e8963e8903716dee04017294c38cce70f60fc4 --- /dev/null +++ b/test/jittest/jit_test_0002/expect_output.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[trace] Check Type: InconsistentHClass6 diff --git a/test/jittest/jit_test_0002/jit_test_0002.ts b/test/jittest/jit_test_0002/jit_test_0002.ts new file mode 100644 index 0000000000000000000000000000000000000000..50b2a60d7deefd379d65ea3d507f4903f5e08019 --- /dev/null +++ b/test/jittest/jit_test_0002/jit_test_0002.ts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function A() { + this.a = 0; + this.b = 2; +} + +function test(a) { + a.c = 9 +} + +test(new A()); + +ArkTools.jitCompileAsync(test); +ArkTools.waitJitCompileFinish(test); + +let a = new A(); +function B() {} +B.prototype = a; +test(a); diff --git a/test/jittest/uncheck_float64_to_int32/expect_output.txt b/test/jittest/uncheck_float64_to_int32/expect_output.txt index ae2f3c3be6c861b31db2317656f029494e55ee70..ff0f80d4450408ed52456a7a668a02a6a39e0cf9 100644 --- a/test/jittest/uncheck_float64_to_int32/expect_output.txt +++ b/test/jittest/uncheck_float64_to_int32/expect_output.txt @@ -20,3 +20,6 @@ left shift result: 4 right shift result: 1 -2 true -3 +true +[trace] Check Type: NotInt7 +true diff --git a/test/jittest/uncheck_float64_to_int32/uncheck_float64_to_int32.ts b/test/jittest/uncheck_float64_to_int32/uncheck_float64_to_int32.ts index c7750935bcb3549da4be858fcd5acaaa9ce5bb5e..fa705650c1e09d21121f2a78a6c23216747fbcec 100644 --- a/test/jittest/uncheck_float64_to_int32/uncheck_float64_to_int32.ts +++ b/test/jittest/uncheck_float64_to_int32/uncheck_float64_to_int32.ts @@ -50,3 +50,17 @@ f3(1.1); ArkTools.jitCompileAsync(f3); print(ArkTools.waitJitCompileFinish(f3)); f3(2.2); + +// Test scenario: No deopt check when performing conversions between int32 and float64. +function f4(x) { + if (x++ < -1) { + x++; + } + return x +} + +f4(-200); +f4(12345678912345); +ArkTools.jitCompileAsync(f4); +print(ArkTools.waitJitCompileFinish(f4)); +print(f4(-12345678912345) == -12345678912343); diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index 9d6219d1b5af9d50fc89596b88187fd5a9952d95..f7d78fe169184965cc2c5c61c84cff1b2c7f90ae 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -17,6 +17,7 @@ group("ark_js_moduletest") { "addelementinternal", "allocatearraybuffer", "array", + "arrayderived", "arrayfindlast", "arrayflat", "arrayflatmap", @@ -26,9 +27,7 @@ group("ark_js_moduletest") { "arrayfrom", "arrayjoin", "arraymap", - - # (issue 18938) - #"arraypop", + "arraypop", "arraytoreversed", "arraytospliced", "arraywith", @@ -73,6 +72,7 @@ group("ark_js_moduletest") { "equal", "errorhelper", "errorcause", + "exp", "flatten", "forawaitof", "forin", @@ -163,8 +163,11 @@ group("ark_js_moduletest") { "typedarrayfill", "typedarrayfilter", "typedarrayfindlast", - "typedarrayfrom", + + #"typedarrayfrom", + "typedarrayfrom_in_api14", "typedarraynan", + "typedarrayreverse", "typedarraysort", "typedarraysubarray", "typedarraytosorted", @@ -260,6 +263,11 @@ group("ark_asm_test") { "allocatearraybuffer", "allocatesizeoverflow", "array", + "arraypushproto", + "arrayspliceproto", + "arrayunshiftproto", + "arrayfillproto", + "arrayconcat", "arrayfindlast", "arrayfill", "arrayflat", @@ -269,9 +277,8 @@ group("ark_asm_test") { "arrayforeach", "arrayjoin", "arraymap", - - # (issue 18938) - #"arraypop", + "arraypop", + "arraystablecheck", "arraysort", "arrayspread", "arrayprotochange", @@ -307,6 +314,7 @@ group("ark_asm_test") { "elements_kind", "equal", "errorcause", + "exp", "flatten", "forin", "forin_delete_property", @@ -342,7 +350,6 @@ group("ark_asm_test") { "multiprotoic", "negintmin", "newobjdynrange", - "number", "objectcloneproperties", "objecthasownproperty", "objectkeys", @@ -372,8 +379,11 @@ group("ark_asm_test") { "typedarrayfill", "typedarrayfilter", "typedarrayfindlast", - "typedarrayfrom", + + #"typedarrayfrom", + "typedarrayfrom_in_api14", "typedarraynan", + "typedarrayreverse", "typedarraysort", "typedarraytosorted", "typedarraywith", @@ -472,9 +482,7 @@ group("ark_asm_single_step_test") { "arrayforeach", "arrayjoin", "arraymap", - - # (issue 18938) - #"arraypop", + "arraypop", "arrayprotochange", "arrayshift", "arrayslice", @@ -499,6 +507,7 @@ group("ark_asm_single_step_test") { "dyninstruction", "ecmastringtable", "errorcause", + "exp", "forin", "forin_delete_property", "forin_dictionary_mode", @@ -530,6 +539,7 @@ group("ark_asm_single_step_test") { "multiprotoic", "negintmin", "newobjdynrange", + "number", "objectcloneproperties", "objecthasownproperty", "objectkeys", @@ -557,8 +567,11 @@ group("ark_asm_single_step_test") { "typedarrayfill", "typedarrayfilter", "typedarrayfindlast", - "typedarrayfrom", + + #"typedarrayfrom", + "typedarrayfrom_in_api14", "typedarraynan", + "typedarrayreverse", "typedarraysort", "typedarraytosorted", "typedarraywith", diff --git a/test/moduletest/array/array.js b/test/moduletest/array/array.js index b98147a058de1914081ae3ab59d544cfd3f85386..c6eb422faadae17b2e5aee276a0a16590bddde23 100644 --- a/test/moduletest/array/array.js +++ b/test/moduletest/array/array.js @@ -1683,6 +1683,14 @@ testCases.forEach(({ array, target }) => { let singleElementArr = [1]; singleElementArr.push(2); print(singleElementArr); + + var ve = ['']; + try { + for (var item in ve) { + var vee = ve[item]; + Array.prototype.push.call(vee[item],[,,]); + } + } catch(e) { print(e); } } /* @@ -2032,4 +2040,45 @@ try { arr_push.push(3); } catch (e) { print(e instanceof TypeError); +} + +// find index object +let findIndexArray = new Array(4); +const obj0 = { ["obj0"]: 0 }; +const obj1 = { ["obj1"]: 1 }; +const obj2 = { ["obj2"]: 2 }; +const obj3 = { ["obj3"]: 3 }; +findIndexArray[0] = obj0; +findIndexArray[1] = obj1; +findIndexArray[2] = obj2; +findIndexArray[3] = obj3; +print(findIndexArray.findIndex(element => element == obj1)); +print(findIndexArray.findIndex(element => element == { ["obj3"]: 3 })); + +// find index bigint +findIndexArray = new Array(4); +findIndexArray[0] = 1n; +findIndexArray[1] = 2n; +findIndexArray[2] = 3n; +findIndexArray[3] = 4n; +print(findIndexArray.findIndex(element => element == 2n)); +print(findIndexArray.findIndex(element => element == 0n)); + + +// find index string +findIndexArray = new Array(4); +findIndexArray[0] = "a"; +findIndexArray[1] = "b"; +findIndexArray[2] = "c"; +findIndexArray[3] = "d"; +print(findIndexArray.findIndex(element => element == "b")); +print(findIndexArray.findIndex(element => element == "e")); + +{ + Array.prototype.__proto__ = null; + var vp = Array.prototype; + vp.map(function(vp) {}); + vp.filter(function(vp) {}); + print("succ"); + Array.prototype.__proto__ = Object.prototype; } \ No newline at end of file diff --git a/test/moduletest/array/expect_output.txt b/test/moduletest/array/expect_output.txt index 6f513e997a05ee9584d8f36c7f7b65bba8e2be93..ce49315af06ff91a20c45f37eae4d849e363d730 100644 --- a/test/moduletest/array/expect_output.txt +++ b/test/moduletest/array/expect_output.txt @@ -468,6 +468,7 @@ apple 1,2,3,4 1,2,3, 1,2 +TypeError: Cannot convert a UNDEFINED value to a JSObject 15 0 1 @@ -559,3 +560,10 @@ false false false true +1 +-1 +1 +-1 +1 +-1 +succ \ No newline at end of file diff --git a/test/moduletest/arrayConcat/BUILD.gn b/test/moduletest/arrayconcat/BUILD.gn similarity index 94% rename from test/moduletest/arrayConcat/BUILD.gn rename to test/moduletest/arrayconcat/BUILD.gn index 6534cb435800be36b71616c71922a2a94c3b3f37..32dda9fb22784fc839763569b93b9ae22f4951c6 100644 --- a/test/moduletest/arrayConcat/BUILD.gn +++ b/test/moduletest/arrayconcat/BUILD.gn @@ -13,6 +13,6 @@ import("//arkcompiler/ets_runtime/test/test_helper.gni") -host_moduletest_action("arrayConcat") { +host_moduletest_action("arrayconcat") { deps = [] } diff --git a/test/moduletest/arrayconcat/arrayconcat.js b/test/moduletest/arrayconcat/arrayconcat.js new file mode 100644 index 0000000000000000000000000000000000000000..e9ab1c22d2c439e0698431fbe3b1411faeb37db6 --- /dev/null +++ b/test/moduletest/arrayconcat/arrayconcat.js @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const array1 = ['a', 'b', 'c']; +const array2 = ['d', 'e', 'f']; +const array3 = array1.concat(array2); +print(array3); + +const letters = ["a", "b", "c"]; +const numbers = [1, 2, 3]; + +const alphaNumeric = letters.concat(numbers); +print(alphaNumeric); + +const num1 = [1, 2, 3]; +const num2 = [4, 5, 6]; +const num3 = [7, 8, 9]; + +const numbers1 = num1.concat(num2, num3); + +print(numbers1); + + +const letters1 = ["a", "b", "c"]; + +const alphaNumeric1 = letters1.concat(1, [2, 3]); + +print(alphaNumeric1); + +const num11 = [[1]]; +const num22 = [2, [3]]; + +const numbers2 = num1.concat(num22); + +print(numbers2); +// [[1], 2, [3]] + +num11[0].push(4); + +print(numbers2); + +print([1, , 3].concat([4, 5])); // [1, empty, 3, 4, 5] +print([1, 2].concat([3, , 5])); // [1, 2, 3, empty, 5] + +const emptyArr = []; +print(emptyArr.concat([]).length); + +/* + * @tc.name:Array concat1 + * @tc.desc:test long Array Concat long Array and change proto + * @tc.type: FUNC + */ +{ + let arr1 = new Array(2000); + arr1[0] = 1; + arr1[1] = 1; + let arr2 = new Array(2000); + arr2.__proto__ = arr1; + arr2[1] = 3; + arr2[2] = 2; + arr2[3] = "ab"; + arr2[4] = 1; + let arr3 = new Array(2000); + let arr4 = arr3.concat(arr2); + print(arr4[2000], arr4[2001], arr4[2002], arr4[2003], arr4[2004]); +} + +/* + * @tc.name:Array concat2 + * @tc.desc:test long Array Concat short Array and change proto + * @tc.type: FUNC + */ +{ + let arr1 = new Array(10); + arr1[0] = 1; + arr1[1] = 1; + let arr2 = new Array(10); + arr2.__proto__ = arr1; + arr2[1] = 3; + arr2[2] = 2; + arr2[3] = "ab"; + arr2[4] = 1; + let arr3 = new Array(2000); + let arr4 = arr3.concat(arr2); + print(arr4[2000], arr4[2001], arr4[2002], arr4[2003], arr4[2004]); +} + +/* + * @tc.name:Array concat3 + * @tc.desc:test short Array Concat long Array and change proto + * @tc.type: FUNC + */ +{ + let arr1 = new Array(2000); + arr1[0] = 1; + arr1[1] = 1; + let arr2 = new Array(2000); + arr2.__proto__ = arr1; + arr2[1] = 3; + arr2[2] = 2; + arr2[3] = "ab"; + arr2[4] = 1; + let arr3 = new Array(10); + let arr4 = arr3.concat(arr2); + print(arr4[10], arr4[11], arr4[12], arr4[13], arr4[14]); +} + +/* + * @tc.name:Array concat4 + * @tc.desc:test long Array Concat long Array + * @tc.type: FUNC + */ +{ + let arr2 = new Array(2000); + arr2[1] = 3; + arr2[2] = 2; + arr2[3] = "ab"; + arr2[4] = 1; + let arr3 = new Array(2000); + let arr4 = arr3.concat(arr2); + print(arr4[2000], arr4[2001], arr4[2002], arr4[2003], arr4[2004]); +} + +/* + * @tc.name:Array concat5 + * @tc.desc:test long Array Concat short Array + * @tc.type: FUNC + */ +{ + let arr2 = new Array(10); + arr2[1] = 3; + arr2[2] = 2; + arr2[3] = "ab"; + arr2[4] = 1; + let arr3 = new Array(2000); + let arr4 = arr3.concat(arr2); + print(arr4[2000], arr4[2001], arr4[2002], arr4[2003], arr4[2004]); +} + +/* + * @tc.name:Array concat6 + * @tc.desc:test short Array Concat long Array + * @tc.type: FUNC + */ +{ + let arr2 = new Array(2000); + arr2[1] = 3; + arr2[2] = 2; + arr2[3] = "ab"; + arr2[4] = 1; + let arr3 = new Array(10); + let arr4 = arr3.concat(arr2); + print(arr4[10], arr4[11], arr4[12], arr4[13], arr4[14]); +} + +/* + * @tc.name:Array concat7 + * @tc.desc:test long Array Concat long Array change origin prototype + * @tc.type: FUNC + */ +{ + let arr2 = new Array(2000); + arr2.__proto__[0] = "??"; + arr2[1] = 3; + arr2[2] = 2; + arr2[3] = "ab"; + arr2[4] = 1; + let arr3 = new Array(2000); + let arr4 = arr3.concat(arr2); + print(arr4[0], arr4[2000], arr4[2001], arr4[2002], arr4[2003], arr4[2004]); +} + +/* + * @tc.name:Array concat8 + * @tc.desc:test long Array Concat long Array change origin prototype + * @tc.type: FUNC + */ +{ + let arr2 = new Array(2000); + arr2.__proto__[0] = "??"; + arr2[1] = 3; + arr2[2] = 2; + arr2[3] = "ab"; + arr2[4] = 1; + let arr3 = new Array(2000); + let arr4 = arr3.concat(arr2); + print(arr4[0], arr4[2000], arr4[2001], arr4[2002], arr4[2003], arr4[2004]); +} +print("test arrayconcat success!"); \ No newline at end of file diff --git a/test/moduletest/arrayConcat/expect_output.txt b/test/moduletest/arrayconcat/expect_output.txt similarity index 80% rename from test/moduletest/arrayConcat/expect_output.txt rename to test/moduletest/arrayconcat/expect_output.txt index ede8f6d4ad65c2d952c68230ee12e800be333394..14590f14c115f2dedf10016f693c1779c0498fbb 100644 --- a/test/moduletest/arrayConcat/expect_output.txt +++ b/test/moduletest/arrayconcat/expect_output.txt @@ -17,9 +17,15 @@ a,b,c,1,2,3 a,b,c,1,2,3 1,2,3,2,3 1,2,3,2,3 -Symbol(Symbol.isConcatSpreadable) -length -1, undefined, 3, 4, 5 -1, 2, 3, undefined, 5 +1,,3,4,5 +1,2,3,,5 0 -proxy defineproperty success! \ No newline at end of file +1 3 2 ab 1 +1 3 2 ab 1 +1 3 2 ab 1 +undefined 3 2 ab 1 +undefined 3 2 ab 1 +undefined 3 2 ab 1 +?? ?? 3 2 ab 1 +?? ?? 3 2 ab 1 +test arrayconcat success! \ No newline at end of file diff --git a/test/moduletest/arrayderived/BUILD.gn b/test/moduletest/arrayderived/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..185dab893841209d30eec420e59deb20f34ee25f --- /dev/null +++ b/test/moduletest/arrayderived/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("arrayderived") { + deps = [] +} diff --git a/test/moduletest/arrayderived/arrayderived.js b/test/moduletest/arrayderived/arrayderived.js new file mode 100755 index 0000000000000000000000000000000000000000..d2a344cee6a8c02edc2347d2e0a0b167305b6f1d --- /dev/null +++ b/test/moduletest/arrayderived/arrayderived.js @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class CustomArray extends Array {} + +// 测试受 `constructor` 属性影响的方法 +function testConstructorEffect() { + let custom = new CustomArray(1, 2, 3); + + print("Testing methods affected by constructor:"); + + // Array.prototype.concat + let result = custom.concat([4, 5]); + print("concat:", result instanceof CustomArray); // true + + // Array.prototype.map + result = custom.map(x => x * 2); + print("map:", result instanceof CustomArray); // true + + // Array.prototype.filter + result = custom.filter(x => x > 1); + print("filter:", result instanceof CustomArray); // true + + // Array.prototype.slice + result = custom.slice(1); + print("slice:", result instanceof CustomArray); // true + + // Array.prototype.flatMap + result = custom.flatMap(x => [x, x * 2]); + print("flatMap:", result instanceof CustomArray); // true + + // Array.prototype.flat + result = custom.flat(); + print("flat:", result instanceof CustomArray); // true + +} + +function testArrayprototypechange() { + print("Testing array when Array's prototype changed.") + let newProto = {}; + Object.defineProperty(newProto, '1', { + get: function() { + return 1; + } + }) + Array.prototype.__proto__ = newProto; + let a = new Array(10); + print(a[1]); +} + +testConstructorEffect() + +testArrayprototypechange() \ No newline at end of file diff --git a/test/moduletest/arrayderived/expect_output.txt b/test/moduletest/arrayderived/expect_output.txt new file mode 100755 index 0000000000000000000000000000000000000000..bc4856fe588cfa1f9d2da30c2bb945e17bd370f6 --- /dev/null +++ b/test/moduletest/arrayderived/expect_output.txt @@ -0,0 +1,22 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Testing methods affected by constructor: +concat: true +map: true +filter: true +slice: true +flatMap: true +flat: true +Testing array when Array's prototype changed. +1 \ No newline at end of file diff --git a/test/moduletest/arrayfillproto/BUILD.gn b/test/moduletest/arrayfillproto/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3d93459c01a7a86fdd7f90f280b93b541d0c9ff3 --- /dev/null +++ b/test/moduletest/arrayfillproto/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("arrayfillproto") { + deps = [] +} diff --git a/test/moduletest/arrayfillproto/arrayfillproto.js b/test/moduletest/arrayfillproto/arrayfillproto.js new file mode 100644 index 0000000000000000000000000000000000000000..78170888ce10919c764334bdea5a155aaf23de49 --- /dev/null +++ b/test/moduletest/arrayfillproto/arrayfillproto.js @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/* + * @tc.name:array fill proto + * @tc.desc:test array fill proto + */ +let arr1 = new Array(500); +arr1.__proto__.length = 10; +arr1.__proto__.fill(233, 0, 7); +let arr2 = new Array(500); +let arr3 = arr1.concat(arr2); +print(arr3[0], arr3[1], arr3[2], arr3[500], arr3[501], arr3[502]); \ No newline at end of file diff --git a/test/moduletest/arrayfillproto/expect_output.txt b/test/moduletest/arrayfillproto/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..6b22c2372cff2098a01fd080fbb516ff3c652f25 --- /dev/null +++ b/test/moduletest/arrayfillproto/expect_output.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +233 233 233 233 233 233 \ No newline at end of file diff --git a/test/moduletest/arrayjoin/arrayjoin.js b/test/moduletest/arrayjoin/arrayjoin.js index 380b856df50c6b9141bd5d3cbbbb892b794c6e02..6260307d573d1b51d118cdc28b6e45b631075f21 100644 --- a/test/moduletest/arrayjoin/arrayjoin.js +++ b/test/moduletest/arrayjoin/arrayjoin.js @@ -111,4 +111,9 @@ const element = { } }; const arr_join = [element, ,'c']; -print("abc" == arr_join.join('')); \ No newline at end of file +print("abc" == arr_join.join('')); + +const v9 = new Int16Array(128); +const v10 = new Int8Array(128); +v9[11] = [v9, v10]; +print(v9[11]); \ No newline at end of file diff --git a/test/moduletest/arrayjoin/expect_output.txt b/test/moduletest/arrayjoin/expect_output.txt index bdf2840104a1f4904182bbc2a3261e16a05f75f1..950574f9e1ca73c0543f72bd9c66177a8dbcb87e 100644 --- a/test/moduletest/arrayjoin/expect_output.txt +++ b/test/moduletest/arrayjoin/expect_output.txt @@ -30,3 +30,4 @@ NaN NaN NaN0 true +0 diff --git a/test/moduletest/arraypop/arraypop.js b/test/moduletest/arraypop/arraypop.js index ad2988a11e6853c75ef83cd4b6dc0922c679d9f4..b5f758155c2ef4189457bf1cb75326001b12735d 100644 --- a/test/moduletest/arraypop/arraypop.js +++ b/test/moduletest/arraypop/arraypop.js @@ -38,7 +38,7 @@ function testSetCapacity() { let arr = new Array(); - for (let i = 0; i < 100000; i++) { + for (let i = 0; i < 10000; i++) { arr.push(i); } print("Test completed"); diff --git a/test/moduletest/arraypushproto/BUILD.gn b/test/moduletest/arraypushproto/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..40d37db4668d2b1cf15d956c8d0e52a2685295ab --- /dev/null +++ b/test/moduletest/arraypushproto/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("arraypushproto") { + deps = [] +} diff --git a/test/fuzztest/jsnapifork_fuzzer/jsnapifork_fuzzer.h b/test/moduletest/arraypushproto/arraypushproto.js similarity index 69% rename from test/fuzztest/jsnapifork_fuzzer/jsnapifork_fuzzer.h rename to test/moduletest/arraypushproto/arraypushproto.js index ef85ac4fa30f329ae76718383b03af7874497834..141116edf12382de7b1c59ebe6c29a1f21c45467 100644 --- a/test/fuzztest/jsnapifork_fuzzer/jsnapifork_fuzzer.h +++ b/test/moduletest/arraypushproto/arraypushproto.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,9 +13,13 @@ * limitations under the License. */ -#ifndef JSNAPIFORK_FUZZER_H -#define JSNAPIFORK_FUZZER_H -#define FUZZ_PROJECT_NAME "jsnapifork_fuzzer.h" - -#endif \ No newline at end of file +/* + * @tc.name:array push proto + * @tc.desc:test array push proto + */ +let arr1 = new Array(500); +arr1.__proto__.push(1); +let arr2 = new Array(500); +let arr3 = arr1.concat(arr2); +print(arr3[0], arr3[500]); \ No newline at end of file diff --git a/test/aottest/pgo_force_ic/expect_output.txt b/test/moduletest/arraypushproto/expect_output.txt similarity index 98% rename from test/aottest/pgo_force_ic/expect_output.txt rename to test/moduletest/arraypushproto/expect_output.txt index daa7d198af7de204908478ae5aeb063cf4cf02cd..8bbcbbbc7dbe3285db1ea4d8d85d25e1c8d29183 100644 --- a/test/aottest/pgo_force_ic/expect_output.txt +++ b/test/moduletest/arraypushproto/expect_output.txt @@ -11,5 +11,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -hello -false +1 1 \ No newline at end of file diff --git a/test/moduletest/arraysort/arraysort.js b/test/moduletest/arraysort/arraysort.js index 75898af09eff7e4cfed3062a66b44d2f03ce3cef..6af0c2444edc5e245a9ebe6ba52609d52059ecd1 100644 --- a/test/moduletest/arraysort/arraysort.js +++ b/test/moduletest/arraysort/arraysort.js @@ -376,3 +376,110 @@ print("sort Test Success!"); array1[0] = `g`; print(array1.toSorted()); } + +// Test sort if array has hole +function HoleSort() +{ + let sortNumber= []; + for (let i = 0; i < 10; i++) { + sortNumber.push(parseInt(i)); + } + sortNumber[100] = parseInt(100); + print(sortNumber.length); + print(sortNumber); + + sortNumber.sort((a, b) => { + return a < b; + }); + + print(sortNumber.length); + print(sortNumber); +} + +HoleSort(); + +let sortNumber = [0,3,2,,4,5,6]; +sortNumber.sort((a,b) => { + sortNumber[10000] = 1; + return a-b; +}); +print(sortNumber.length); +print(sortNumber); + +let sortNumber2 = [0,3,2,,4,5,6]; +sortNumber2.sort((a,b) => { + sortNumber2[3] = 1; + return a-b; +}); +print(sortNumber2.length); +print(sortNumber2); + +let sortNumber3 = [0,3,2,,4,5,6]; +sortNumber3.sort((a,b) => { + sortNumber3 = 1; // stlexvar + return a-b; +}); +print(sortNumber3.length); +print(sortNumber3[0]); +print(sortNumber3[2]); +print(sortNumber3[4]); +print(sortNumber3[6]); + +let sortNumber4 = [0,3,2,,4,5,6]; +sortNumber4.sort((a,b) => { + sortNumber4.push(1); + return a-b; +}); +print(sortNumber4.length); +print(sortNumber4[0]); +print(sortNumber4[2]); +print(sortNumber4[4]); +print(sortNumber4[6]); + +let sortNumber5 = [-1, 2, 4, 1, 0]; +sortNumber5.sort((x, y) => { + Object.defineProperty(sortNumber5, '2', { + get() { + print("get second element:"); + return this.value; + }, + set(newValue) { + print("set second element:", newValue); + this.value = newValue; + } + }); + return x - y; +}) +print(sortNumber5.length); +print(sortNumber5.value); +print(sortNumber5); + +let sortNumber6 = [-1, 2, 4, 1, 0]; +sortNumber6.sort((x, y) => { + Object.defineProperty(sortNumber6, '100', { + get() { + print("get 10000th element:"); + return this.value; + }, + set(newValue) { + print("set 10000th element:", newValue); + this.value = newValue; + }, + configurable: true // 允许重新定义 + }); + return x - y; +}) +print(sortNumber6.length); +print(sortNumber6.value); +print(sortNumber6); + +let sortNumber7 = [0,3,2,,4,5,6]; +sortNumber7.sort((a,b) => { + sortNumber7.pop(); + return a-b; +}); +print(sortNumber7.length); +print(sortNumber7[0]); +print(sortNumber7[2]); +print(sortNumber7[4]); +print(sortNumber7[6]); diff --git a/test/moduletest/arraysort/expect_output.txt b/test/moduletest/arraysort/expect_output.txt index 40ed159503437d4cf3c72d5ad95a116220ba5dbb..fe03168e5a52ab2ec3d17850c9ed8b42b16c0753 100644 --- a/test/moduletest/arraysort/expect_output.txt +++ b/test/moduletest/arraysort/expect_output.txt @@ -59,3 +59,35 @@ string.0,string.1 string.0,string.1 a,b,c,d,e,f,g a,b,c,d,e,f,g +101 +0,1,2,3,4,5,6,7,8,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100 +101 +0,1,2,3,4,5,6,7,8,9,100,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +10001 +0,2,3,4,5,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1 +7 +0,2,3,4,5,6, +undefined +undefined +undefined +undefined +undefined +17 +0 +3 +5 +undefined +set second element: 1 +5 +1 +get second element: +-1,0,1,2,4 +101 +undefined +get 10000th element: +-1,0,1,2,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +6 +0 +3 +5 +undefined diff --git a/test/moduletest/arrayspliceproto/BUILD.gn b/test/moduletest/arrayspliceproto/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3108455263e11eaf1faa13cbcb324e408b28de28 --- /dev/null +++ b/test/moduletest/arrayspliceproto/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("arrayspliceproto") { + deps = [] +} diff --git a/test/moduletest/arrayspliceproto/arrayspliceproto.js b/test/moduletest/arrayspliceproto/arrayspliceproto.js new file mode 100644 index 0000000000000000000000000000000000000000..44d2be1faec2e32169433d063c9c90b2925a2ef3 --- /dev/null +++ b/test/moduletest/arrayspliceproto/arrayspliceproto.js @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/* + * @tc.name:array splice proto + * @tc.desc:test array splice proto + */ +let arr1 = new Array(500); +arr1.__proto__.splice(1, 0, 1, 2, 3); +let arr2 = new Array(500); +let arr3 = arr1.concat(arr2); +print(arr3[0], arr3[1], arr3[2], arr3[500], arr3[501], arr3[502]); \ No newline at end of file diff --git a/test/moduletest/arrayspliceproto/expect_output.txt b/test/moduletest/arrayspliceproto/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..839814613b9ff09c7da7648b1a388f07db49ca44 --- /dev/null +++ b/test/moduletest/arrayspliceproto/expect_output.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +1 2 3 1 2 3 \ No newline at end of file diff --git a/test/moduletest/arraystablecheck/BUILD.gn b/test/moduletest/arraystablecheck/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9e6bcff086dc2855121741a687c1f87ed1c56337 --- /dev/null +++ b/test/moduletest/arraystablecheck/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("arraystablecheck") { + deps = [] +} diff --git a/test/moduletest/arraystablecheck/arraystablecheck.js b/test/moduletest/arraystablecheck/arraystablecheck.js new file mode 100644 index 0000000000000000000000000000000000000000..0de9a54d219584c584e181b8ed4628dd0cad6874 --- /dev/null +++ b/test/moduletest/arraystablecheck/arraystablecheck.js @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:arraystablecheck1 + * @tc.desc:test array stable or not + */ + +{ + let arr1 = new Array(1023); + let arr2 = new Array(1023); + print(ArkTools.isStableJsArray(arr1)); + print(ArkTools.isStableJsArray(arr2)); + print(ArkTools.isStableJsArray(arr2.__proto__)); +} + + +/* + * @tc.name:arraystablecheck2 + * @tc.desc:test array stable or not + */ + +{ + let arr1 = new Array(1023); + let arr2 = new Array(1023); + arr1.__proto__ = arr2; + print(ArkTools.isStableJsArray(arr1)); + print(ArkTools.isStableJsArray(arr2)); +} + +/* + * @tc.name:arraystablecheck3 + * @tc.desc:test array stable or not + */ +{ + let arr1 = new Array(1026); + let arr2 = new Array(1026); + print(ArkTools.isStableJsArray(arr1)); + print(ArkTools.isStableJsArray(arr2)); +} + +/* + * @tc.name:arraystablecheck4 + * @tc.desc:test array stable or not + */ +{ + class MyArray extends Array { + + }; + let arr1 = new MyArray(1023); + let arr2 = new MyArray(1023); + let arr3 = arr1.concat(arr2); + let arr4 = new Array(1023); + print(ArkTools.isStableJsArray(arr1)); + print(ArkTools.isStableJsArray(arr2)); + print(ArkTools.isStableJsArray(arr3)); + print(ArkTools.isStableJsArray(arr4)); +} + +/* + * @tc.name:arraystablecheck5 + * @tc.desc:test array stable or not + */ +{ + class MyArray extends Array { + + }; + let arr1 = new MyArray(); + let arr2 = new MyArray(); + let arr3 = arr1.concat(); + let arr4 = new Array(); + print(ArkTools.isStableJsArray(arr1)); + print(ArkTools.isStableJsArray(arr2)); + print(ArkTools.isStableJsArray(arr3)); + print(ArkTools.isStableJsArray(arr4)); +} + +/* + * @tc.name:arraystablecheck6 + * @tc.desc:test array stable or not + */ +{ + class MyArray extends Array { + + }; + let arr1 = new MyArray(1, 2, 3, 4, 5); + let arr2 = new MyArray(1, 2, 3, 4, 5); + let arr3 = arr1.concat(); + let arr4 = new Array(1, 2, 3, 4, 5); + print(ArkTools.isStableJsArray(arr1)); + print(ArkTools.isStableJsArray(arr2)); + print(ArkTools.isStableJsArray(arr3)); + print(ArkTools.isStableJsArray(arr4)); +} + +/* + * @tc.name:arraystablecheck7 + * @tc.desc:test array stable or not + */ +{ + let arr1 = new Array(1023); + print(ArkTools.isStableJsArray(arr1)); + arr1.__proto__.fill(233, 0, 0); + print(ArkTools.isStableJsArray(arr1)); + arr1.__proto__.fill(); + print(ArkTools.isStableJsArray(arr1)); + arr1.__proto__.push(); + print(ArkTools.isStableJsArray(arr1)); + arr1.__proto__.unshift(); + print(ArkTools.isStableJsArray(arr1)); + arr1.__proto__.splice(); + print(ArkTools.isStableJsArray(arr1)); +} + +/* + * @tc.name:arraystablecheck8 + * @tc.desc:test array stable or not + */ +{ + let arr1 = new Array(1023); + let arr2 = new Array(1023); + arr1.__proto__.push(1); + print(ArkTools.isStableJsArray(arr1.__proto__)); + print(ArkTools.isStableJsArray(arr1)); + print(ArkTools.isStableJsArray(arr2)); +} \ No newline at end of file diff --git a/test/moduletest/arraystablecheck/expect_output.txt b/test/moduletest/arraystablecheck/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..d02fd7ded5fbc5349ce4015c1e655bbffad43ab6 --- /dev/null +++ b/test/moduletest/arraystablecheck/expect_output.txt @@ -0,0 +1,41 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +true +true +false +false +true +false +false +false +false +false +true +false +false +false +true +false +false +false +true +true +true +true +true +true +true +false +false +false \ No newline at end of file diff --git a/test/moduletest/arrayunshiftproto/BUILD.gn b/test/moduletest/arrayunshiftproto/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..497d5d4bfb6a8e946f455a22a40aa1b1594cfd8a --- /dev/null +++ b/test/moduletest/arrayunshiftproto/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("arrayunshiftproto") { + deps = [] +} diff --git a/test/fuzztest/arrayref_fuzzer/arrayref_fuzzer.h b/test/moduletest/arrayunshiftproto/arrayunshiftproto.js similarity index 62% rename from test/fuzztest/arrayref_fuzzer/arrayref_fuzzer.h rename to test/moduletest/arrayunshiftproto/arrayunshiftproto.js index 82e97b79a556e38a71e5fc713ab7c229e8681190..fc9e58ab62b09a5c562bec36db2b94fe2b4bc9ce 100644 --- a/test/fuzztest/arrayref_fuzzer/arrayref_fuzzer.h +++ b/test/moduletest/arrayunshiftproto/arrayunshiftproto.js @@ -1,10 +1,10 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -13,9 +13,13 @@ * limitations under the License. */ -#ifndef ARRAYREF_FUZZER_H -#define ARRAYREF_FUZZER_H -#define FUZZ_PROJECT_NAME "arrayref_fuzzer.h" - -#endif \ No newline at end of file +/* + * @tc.name:array unshift proto + * @tc.desc:test array unshift proto + */ +let arr1 = new Array(500); +arr1.__proto__.unshift(1); +let arr2 = new Array(500); +let arr3 = arr1.concat(arr2); +print(arr3[0], arr3[500]); \ No newline at end of file diff --git a/test/fuzztest/arrayref_fuzzer/corpus/init b/test/moduletest/arrayunshiftproto/expect_output.txt similarity index 83% rename from test/fuzztest/arrayref_fuzzer/corpus/init rename to test/moduletest/arrayunshiftproto/expect_output.txt index 69c5791762c2df3d7e43cb066be9cd8b56f80621..8bbcbbbc7dbe3285db1ea4d8d85d25e1c8d29183 100644 --- a/test/fuzztest/arrayref_fuzzer/corpus/init +++ b/test/moduletest/arrayunshiftproto/expect_output.txt @@ -1,9 +1,9 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. +# Copyright (c) 2024 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, @@ -11,4 +11,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -FUZZ \ No newline at end of file +1 1 \ No newline at end of file diff --git a/test/moduletest/builtins/builtinsregexp.js b/test/moduletest/builtins/builtinsregexp.js index fd6aa85bb945f952ea2d4f8790a2721dd9747cb2..3454d06258cc968df4bd03fa0836f9cf3bf0f3b6 100644 --- a/test/moduletest/builtins/builtinsregexp.js +++ b/test/moduletest/builtins/builtinsregexp.js @@ -71,4 +71,18 @@ var str8 = "Test1234" print(regexp.test(str8)); print(RegExp.$1); +var v1 = "()|()|".repeat(512); +new RegExp(v1).exec(""); +print("regexp.exec succ"); + +const emailRegex = /(\w+)@(\w+)\.(\w+)/; +const testString = "Contact me at support@example.com for assistance."; +const match = emailRegex.exec(testString); +if (match) { + print("match result:", match[0]); + print("match start index:", match.index); +} else { + print("no match"); +} + print("builtins regexp end"); diff --git a/test/moduletest/builtins/expect_output.txt b/test/moduletest/builtins/expect_output.txt index 5e276c524b0fab21ae99a963e346e6730ed675bc..202dff2288c458aedef2f7b918abc522055670cc 100644 --- a/test/moduletest/builtins/expect_output.txt +++ b/test/moduletest/builtins/expect_output.txt @@ -272,6 +272,9 @@ AAA true true 1234 +regexp.exec succ +match result: support@example.com +match start index: 14 builtins regexp end builtins object begin true diff --git a/test/moduletest/container/container_deque.js b/test/moduletest/container/container_deque.js index 389557c9588d3f6e5fef000afb40d47871bc9bc6..3d334087c9d1befaed6ba7a360b32bbc1e8c133e 100644 --- a/test/moduletest/container/container_deque.js +++ b/test/moduletest/container/container_deque.js @@ -162,14 +162,21 @@ if (globalThis["ArkPrivate"] != undefined) { print(error) } let v22; - try { - class C11 extends Deque { + class C11 extends Deque { + } + v22 = new C11() + v22[2295334561] = 0 + print(v22.length) + class C44 extends Deque{ + constructor(a) { + super() + super[a] = 11 + const o10 = { + ...this + } } - v22 = new C11() - v22[2295334561] = 0 - } catch (error) { - print(v22.length) } + new C44(38062) } export let dequeRes = "Test Deque done"; diff --git a/test/moduletest/container/container_queue.js b/test/moduletest/container/container_queue.js index 4c69340872499ac0b04e99b84f8cc4c29ed26a8c..e08aba33b0768d059b140bf9b404ee3ba7023b1d 100644 --- a/test/moduletest/container/container_queue.js +++ b/test/moduletest/container/container_queue.js @@ -162,5 +162,15 @@ if (globalThis["ArkPrivate"] != undefined) { } catch (error) { print(error) } + class C4 extends Queue{ + constructor(a) { + super() + super[a] = 11 + const o10 = { + ...this + } + } + } + new C4(38062) } export let queueRes = "Test Queue done"; diff --git a/test/moduletest/container/container_treemap.js b/test/moduletest/container/container_treemap.js index ac323fb6a98bd655c523634b130cad2c222e5193..d6e2b0ed92499133ab56c8e312381bec13f7210a 100644 --- a/test/moduletest/container/container_treemap.js +++ b/test/moduletest/container/container_treemap.js @@ -197,4 +197,23 @@ if (globalThis["ArkPrivate"] != undefined) { map.set("b", "bv"); map.set("c", "cv"); print("Test TreeMap set After Clear Success") + + let growMap = new fastmap(); + const keyStr = 'KEY_TEST_MAP'; + growMap.set(keyStr,21) + growMap.set(keyStr,68) + growMap.remove(keyStr) + growMap.set(keyStr,23) + growMap.remove(keyStr) + growMap.set(keyStr,86) + growMap.remove(keyStr) + growMap.set(keyStr,37) + growMap.remove(keyStr) + growMap.set(keyStr,33) + growMap.remove(keyStr) + growMap.set(keyStr,34) + growMap.remove(keyStr) + growMap.set(keyStr,64) + growMap.set(keyStr,100) + print(growMap.get(keyStr)) } diff --git a/test/moduletest/container/expect_output.txt b/test/moduletest/container/expect_output.txt index 69b6c13bfe462a26614ea150e7a95438af9c2c0c..2326e6c1bf7f170f339359c3a358e8671e18b6c3 100644 --- a/test/moduletest/container/expect_output.txt +++ b/test/moduletest/container/expect_output.txt @@ -39,6 +39,7 @@ BusinessError: Container is empty BusinessError: Container is empty Test TreeMap success!!! Test TreeMap set After Clear Success +100 Test TreeSet success!!! 226,195,156,20 Test Vector success!!! diff --git a/test/moduletest/dataview/dataview.js b/test/moduletest/dataview/dataview.js index 9a269d4895ee6215ec43fd4f9a003c004cab4112..decb8eafb42ced6aed4d1b7394e4d273e98dee3c 100644 --- a/test/moduletest/dataview/dataview.js +++ b/test/moduletest/dataview/dataview.js @@ -81,4 +81,38 @@ print(second.getInt32(0)); second.setFloat64(0, Infinity); print(second.getInt32(0)); second.setFloat64(0, 27, true); -print(second.getInt32(0)); \ No newline at end of file +print(second.getInt32(0)); + +let ab = new ArrayBuffer(0x100); +try { + let dv1 = new DataView(ab, 0x10, 0xfffffff8); +} catch(e) { + print(e) +} +try { + let dv2 = new DataView(ab, -1, 0xfffffff8); +} catch(e) { + print(e) +} +try { + let dv3 = new DataView(ab, 2**53, 0xfffffff8); +} catch(e) { + print(e) +} +try { + let dv4 = new DataView(ab, 0x10, -1); +} catch(e) { + print(e) +} +try { + let dv5 = new DataView(ab, 0x10, 2**53); +} catch(e) { + print(e) +} + +try { + var dv6 = new DataView(ab, 64, 14); + dv6.setFloat64(0x7fffffff, +254, true); +} catch(e) { + print(e) +} \ No newline at end of file diff --git a/test/moduletest/dataview/expect_output.txt b/test/moduletest/dataview/expect_output.txt index 5d85432006ebbb22fdd4ebd5a344e13505cc20eb..5d395d0ba691ce9df5c6a381f30e8ced7352b5f6 100644 --- a/test/moduletest/dataview/expect_output.txt +++ b/test/moduletest/dataview/expect_output.txt @@ -34,3 +34,9 @@ TypeError: Cannot convert a BigInt value to a number 1076565114 2146435072 0 +RangeError: offset + viewByteLen > bufByteLen +RangeError: integerIndex < 0 or integerIndex > SAFE_NUMBER +RangeError: integerIndex < 0 or integerIndex > SAFE_NUMBER +RangeError: integerIndex < 0 or integerIndex > SAFE_NUMBER +RangeError: integerIndex < 0 or integerIndex > SAFE_NUMBER +RangeError: getIndex +elementSize > viewSize \ No newline at end of file diff --git a/test/moduletest/exp/BUILD.gn b/test/moduletest/exp/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..859c1b73e5be7dfb0c923eacd0c4f4300b97afe7 --- /dev/null +++ b/test/moduletest/exp/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("exp") { + deps = [] +} diff --git a/test/moduletest/exp/exp.js b/test/moduletest/exp/exp.js new file mode 100644 index 0000000000000000000000000000000000000000..715c1f745650f0e1753040d1a08683a48a1d19eb --- /dev/null +++ b/test/moduletest/exp/exp.js @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:exp + * @tc.desc:test exp + * @tc.type: FUNC + * @tc.require: IssueIB212T + */ +print(1**"2"); +print(1**"NaN"); +print(1**"null"); +print(1**"undefined"); +print(1**"Infinity"); + +print(1**2); +print(1**NaN); +print(1**null); +print(1**undefined); +print(1**Infinity); + +print(2**"2"); +print(2**"NaN"); +print(2**"null"); +print(2**"undefined"); +print(2**"Infinity"); + +print(2**2); +print(2**NaN); +print(2**null); +print(2**undefined); +print(2**Infinity); + +print(0**"2"); +print(0**"NaN"); +print(0**"null"); +print(0**"undefined"); +print(0**"Infinity"); + +print(0**2); +print(0**NaN); +print(0**null); +print(0**undefined); +print(0**Infinity); + diff --git a/test/moduletest/exp/expect_output.txt b/test/moduletest/exp/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..496febfa1cb6b9b0382c388063e66e710f0dc2f3 --- /dev/null +++ b/test/moduletest/exp/expect_output.txt @@ -0,0 +1,43 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +1 +NaN +NaN +NaN +NaN +1 +NaN +1 +NaN +NaN +4 +NaN +NaN +NaN +Infinity +4 +NaN +1 +NaN +Infinity +0 +NaN +NaN +NaN +0 +0 +NaN +1 +NaN +0 diff --git a/test/moduletest/ictest/expect_output.txt b/test/moduletest/ictest/expect_output.txt index b7d1dc7da0ae51a79ef79be4c875e8370f45c874..dd2ea95b8d288c49f8d90ab64b2c56ca4b362d0d 100644 --- a/test/moduletest/ictest/expect_output.txt +++ b/test/moduletest/ictest/expect_output.txt @@ -22,3 +22,4 @@ undefined 1 1 4 +v6 diff --git a/test/moduletest/ictest/ictest.js b/test/moduletest/ictest/ictest.js index 286a933d825cef54b127436da0963035fcb3410e..20ede1d726b56dd0236bb935d06263148714f9b4 100644 --- a/test/moduletest/ictest/ictest.js +++ b/test/moduletest/ictest/ictest.js @@ -135,4 +135,16 @@ const v4 = { __proto__: v3 }; v4[3] = v4; v0[1] = v0; v3.splice(0, 0); -print(v3.length); \ No newline at end of file +print(v3.length); + +class C3 { + constructor() { + for (let i = 0; i < 1000; i++) {} + let v6 = new Proxy(this, { + defineProperty: () => {} + }); + v6.h = 4; + print("v6"); + } +} +new C3(); \ No newline at end of file diff --git a/test/moduletest/moduleLazyImport/asyncUseLazyImport.ts b/test/moduletest/moduleLazyImport/asyncUseLazyImport.ts new file mode 100644 index 0000000000000000000000000000000000000000..302aeda3b8ab11214294ef251c46961c82aff3aa --- /dev/null +++ b/test/moduletest/moduleLazyImport/asyncUseLazyImport.ts @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:asyncUseLazyImport + * @tc.desc:test asyncUseLazyImport + * @tc.type: FUNC + * @tc.require: issue#IB2HNC + */ + +// @ts-nocheck +import lazy { TestLazy } from './lazyExport'; +export class Test { + async start() { + this.log(` Test start`) + let a = await this.mapAsync([1, 2], async (t) => { + await this.bindRawData(t) + }) + this.log(` Test end ${new Error().stack}`) + return a + } + private async bindRawData(t: number) { + await this.mapAsync([1, 2], async (k, b) => { + this.onBindRawData(t, k) + }) + await this.mapAsync([4, 5], async (k, b) => { + this.onBindRawData(t, k) + }) + await this.mapAsync([7, 8], async (k, b) => { + this.onBindRawData(t, k) + }) + } + async mapAsync(array: T[], map: (t: T, index: number) => Promise) { + return await Promise.all(array.map(map)) + } + private async onBindRawData(t: number, k: number) { + this.log(` onBindRawData start ${t} ${k}`) + await this.isSelf() + this.log(` onBindRawData end ${t} ${k}`) + } + private async isSelf(): Promise { + return "1" == "1" + } + log(msg: string) { + TestLazy + print(msg) + } +} \ No newline at end of file diff --git a/test/moduletest/moduleLazyImport/expect_output.txt b/test/moduletest/moduleLazyImport/expect_output.txt index 0c3a5d9c9995a84f9a736f68086c6cd1b1c58365..a6a589b5f20cf4f08767427a410aebda1e3d900a 100644 --- a/test/moduletest/moduleLazyImport/expect_output.txt +++ b/test/moduletest/moduleLazyImport/expect_output.txt @@ -30,3 +30,30 @@ this is dynamicLazySequence this is dynamicSubFile this is dynamicLazySequence2 dynamicSubFile + Test start + onBindRawData start 1 1 + onBindRawData start 1 2 + onBindRawData start 2 1 + onBindRawData start 2 2 + onBindRawData end 1 1 + onBindRawData end 1 2 + onBindRawData end 2 1 + onBindRawData end 2 2 + onBindRawData start 1 4 + onBindRawData start 1 5 + onBindRawData start 2 4 + onBindRawData start 2 5 + onBindRawData end 1 4 + onBindRawData end 1 5 + onBindRawData end 2 4 + onBindRawData end 2 5 + onBindRawData start 1 7 + onBindRawData start 1 8 + onBindRawData start 2 7 + onBindRawData start 2 8 + onBindRawData end 1 7 + onBindRawData end 1 8 + onBindRawData end 2 7 + onBindRawData end 2 8 + Test end at start (asyncUseLazyImport.ts:31:1) + diff --git a/test/aottest/pgo_force_ic/pgo_force_ic.ts b/test/moduletest/moduleLazyImport/lazyExport.js similarity index 79% rename from test/aottest/pgo_force_ic/pgo_force_ic.ts rename to test/moduletest/moduleLazyImport/lazyExport.js index d131dce19246dc6f75923a5bf7b9e9ae64a02630..9302db1adb097c5abc82009f5272efd56255601e 100644 --- a/test/aottest/pgo_force_ic/pgo_force_ic.ts +++ b/test/moduletest/moduleLazyImport/lazyExport.js @@ -13,8 +13,12 @@ * limitations under the License. */ -function forceIC() { - print("hello"); -} -forceIC() -print(ArkTools.isAOTCompiled(forceIC)) // pgo:false, aot:false +/* + * @tc.name:asyncUseLazyImport + * @tc.desc:test asyncUseLazyImport + * @tc.type: FUNC + * @tc.require: issue#IB2HNC + */ + +// @ts-nocheck +export class TestLazy {} \ No newline at end of file diff --git a/test/moduletest/moduleLazyImport/moduleLazyImport.js b/test/moduletest/moduleLazyImport/moduleLazyImport.js index fc3bfa872524b220476db8deebee097d5231670c..667e9749ac602b9698243abe989380a3a46f9d86 100644 --- a/test/moduletest/moduleLazyImport/moduleLazyImport.js +++ b/test/moduletest/moduleLazyImport/moduleLazyImport.js @@ -25,6 +25,7 @@ import { aaa } from "./E" import lazy {func1} from './F' import lazy {dynamicLazySequence} from './dynamicLazySequence' import lazy {dynamicLazySequence2} from './dynamicLazySequence2' +import {Test} from './asyncUseLazyImport' print("this is entry"); func1(); @@ -35,4 +36,5 @@ print(h); import("./dynamicLazySequence").then((ns) => { print(ns.dynamicLazySequence); }) -import("./dynamicLazySequence2"); \ No newline at end of file +import("./dynamicLazySequence2"); +new Test().start() \ No newline at end of file diff --git a/test/moduletest/moduleLazyImport/moduleLazyImport.txt b/test/moduletest/moduleLazyImport/moduleLazyImport.txt index ca0c06d82a563df0fe80700b12ae663ca99e39f4..8fc9a7e6be3ae97ce6f50c117adc282bebfdf552 100644 --- a/test/moduletest/moduleLazyImport/moduleLazyImport.txt +++ b/test/moduletest/moduleLazyImport/moduleLazyImport.txt @@ -9,4 +9,6 @@ H.js;H;esm;H.js;xxHxx dynamicLazySequence.js;dynamicLazySequence;esm;dynamicLazySequence.js;xxdynamicLazySequencexx dynamicLazySequence2.js;dynamicLazySequence2;esm;dynamicLazySequence2.js;xxdynamicLazySequence2xx dynamicSubFile.js;dynamicSubFile;esm;dynamicSubFile.js;xxdynamicSubFilexx -moduleLazyImport.js;moduleLazyImport;esm;moduleLazyImport.js;xxmoduleLazyImportxx \ No newline at end of file +moduleLazyImport.js;moduleLazyImport;esm;moduleLazyImport.js;xxmoduleLazyImportxx +asyncUseLazyImport.ts;asyncUseLazyImport;esm;asyncUseLazyImport.ts;xxasyncUseLazyImportxx +lazyExport.js;lazyExport;esm;lazyExport.js;xxlazyExportxx \ No newline at end of file diff --git a/test/moduletest/proxy/expect_output.txt b/test/moduletest/proxy/expect_output.txt index 52a01bf21c82a6e05b1ae64e16d6b471c2875c59..e600bc134c346f8a1e95486e3963f8963ea7921a 100644 --- a/test/moduletest/proxy/expect_output.txt +++ b/test/moduletest/proxy/expect_output.txt @@ -28,3 +28,4 @@ TypeError: function.toString() target is incompatible object test proxy constructor success! false TypeError: ProxyCreate: handler is not Object +test proxy getPrototype success! diff --git a/test/moduletest/proxy/proxy.js b/test/moduletest/proxy/proxy.js index 4e3c16de6bd4544429c755d68ffd684a20f6b46d..9992a3587a67776aae9987c7c7f8f60524640928 100644 --- a/test/moduletest/proxy/proxy.js +++ b/test/moduletest/proxy/proxy.js @@ -138,4 +138,10 @@ print(Object.prototype.isPrototypeOf.call(object, object)); }catch(err) { print(err) } -} \ No newline at end of file +} + +const v7 = new Proxy(Reflect, Reflect); +const v9 = new Proxy(v7, Reflect); +for (const v10 in v9) { +} +print("test proxy getPrototype success!"); \ No newline at end of file diff --git a/test/moduletest/regexp/expect_output.txt b/test/moduletest/regexp/expect_output.txt index 25d57ae82a6f577fd71336ff370636ebedccbf34..d8d1a53970370f2e49d2ac8df2d69ad300ce6d74 100644 --- a/test/moduletest/regexp/expect_output.txt +++ b/test/moduletest/regexp/expect_output.txt @@ -176,3 +176,32 @@ gs gu dg g +\/ ["/"] +\/[a-z]*> ["/style>"] +\/[a-z]*> ["/style>"] +\/[a-z]*> ["/style>"] +\\\/[a-z]*> ["\\/style>"] +\\\/[a-z]*> ["\\/style>"] +\\\/[a-z]*> ["\\/style>"] +\\\/[a-z]*> ["\\/style>"] +SyntaxError +SyntaxError +\[ ["["] +\[ ["["] +SyntaxError +SyntaxError +\\\[ ["\\["] +\\\[ ["\\["] +ab.defgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgz +ab.defgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgz +abCdefgxyzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgz +abxyzdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgz +abxCyzdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgz +abxCyzdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgz +abCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgz +abCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgzabCdefgz +utf83这要替换"! +3这要替换"! +abcdefg3higk"! +true +true diff --git a/test/moduletest/regexp/regexp.js b/test/moduletest/regexp/regexp.js index 57be9cf3e1bd89f71a408d07601741501535e1d6..8309d922b526508e6d0b6c5988134b11971456b4 100644 --- a/test/moduletest/regexp/regexp.js +++ b/test/moduletest/regexp/regexp.js @@ -726,3 +726,169 @@ print(res7.flags); const res8 = /abc/; res8.lastIndex = -1; print(res8.flags); + +{ + let str = "" + let reg = new RegExp("/"); + print(reg.source,JSON.stringify(reg.exec(str))); + + reg = new RegExp("\/[a-z]*>"); + print(reg.source,JSON.stringify(reg.exec(str))); + + reg = new RegExp("\\/[a-z]*>"); + print(reg.source,JSON.stringify(reg.exec(str))); + + reg = new RegExp("\\\/[a-z]*>"); + print(reg.source,JSON.stringify(reg.exec(str))); + + str="