diff --git a/BUILD.gn b/BUILD.gn index 4e7eeb93a477984799c979f7f6d05177d10b02a6..9ca42947db115ca984ea5f1f21623862b26c665e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -245,6 +245,7 @@ ecma_source = [ "ecmascript/base/typed_array_helper.cpp", "ecmascript/base/utf_helper.cpp", "ecmascript/builtins.cpp", + "ecmascript/builtins/builtins_ark_tools.cpp", "ecmascript/builtins/builtins_array.cpp", "ecmascript/builtins/builtins_arraybuffer.cpp", "ecmascript/builtins/builtins_async_function.cpp", diff --git a/ecmascript/builtins.cpp b/ecmascript/builtins.cpp index a74fe84e892ea46e237c5447519d0d60085ff9e8..5c32ec6195d83d9e303792d1c529faf181538f42 100644 --- a/ecmascript/builtins.cpp +++ b/ecmascript/builtins.cpp @@ -17,6 +17,7 @@ #include "ecmascript/base/error_type.h" #include "ecmascript/base/number_helper.h" +#include "ecmascript/builtins/builtins_ark_tools.h" #include "ecmascript/builtins/builtins_array.h" #include "ecmascript/builtins/builtins_arraybuffer.h" #include "ecmascript/builtins/builtins_async_function.h" @@ -74,6 +75,7 @@ #include "ecmascript/js_promise.h" #include "ecmascript/js_regexp.h" #include "ecmascript/js_relative_time_format.h" +#include "ecmascript/js_runtime_options.h" #include "ecmascript/js_set.h" #include "ecmascript/js_set_iterator.h" #include "ecmascript/js_string_iterator.h" @@ -267,7 +269,7 @@ void Builtins::Initialize(const JSHandle &env, JSThread *thread) InitializePromise(env, objFuncDynclass); InitializePromiseJob(env); - RuntimeOptions options = vm_->GetOptions(); + JSRuntimeOptions options = vm_->GetJSOptions(); std::string icuPath = options.GetIcuDataPath(); if (icuPath == "default") { SetHwIcuDirectory(); @@ -301,6 +303,11 @@ void Builtins::InitializeGlobalObject(const JSHandle &env, const JSHa SetFunction(env, globalObject, "stopRuntimeStat", Global::StopRuntimeStat, 0); #endif + JSRuntimeOptions options = vm_->GetJSOptions(); + if (options.IsEnableArkTools()) { + SetConstant(globalObject, "ArkTools", InitializeArkTools(env).GetTaggedValue()); + } + // Global object function SetFunction(env, globalObject, "eval", Global::NotSupportEval, FunctionLength::ONE); SetFunction(env, globalObject, "isFinite", Global::IsFinite, FunctionLength::ONE); @@ -2723,4 +2730,13 @@ void Builtins::InitializePluralRules(const JSHandle &env) // 15.4.5 Intl.PluralRules.prototype.resolvedOptions () SetFunction(env, prPrototype, "resolvedOptions", PluralRules::ResolvedOptions, FunctionLength::ZERO); } + +JSHandle Builtins::InitializeArkTools(const JSHandle &env) const +{ + [[maybe_unused]] EcmaHandleScope scope(thread_); + + JSHandle tools = factory_->NewEmptyJSObject(); + SetFunction(env, tools, "print", builtins::BuiltinsArkTools::ObjectDump, FunctionLength::ZERO); + return tools; +} } // namespace panda::ecmascript diff --git a/ecmascript/builtins.h b/ecmascript/builtins.h index dcf28552c7915b4cc9c700d29ec011c94cf163f6..63fa4b4fe76e12058165a70e6df98b086b781213 100644 --- a/ecmascript/builtins.h +++ b/ecmascript/builtins.h @@ -208,6 +208,7 @@ private: const JSHandle &getter, const JSHandle &setter) const; void SetGetter(const JSHandle &obj, const JSHandle &key, const JSHandle &getter) const; + JSHandle InitializeArkTools(const JSHandle &env) const; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_BUILTINS_H diff --git a/ecmascript/builtins/builtins_ark_tools.cpp b/ecmascript/builtins/builtins_ark_tools.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2b063f546b4a066b0a47eb1ce04749ad703a6f8 --- /dev/null +++ b/ecmascript/builtins/builtins_ark_tools.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecmascript/builtins/builtins_ark_tools.h" +#include "ecmascript/base/string_helper.h" + +namespace panda::ecmascript::builtins { +using StringHelper = base::StringHelper; + +JSTaggedValue BuiltinsArkTools::ObjectDump(EcmaRuntimeCallInfo *msg) +{ + ASSERT(msg); + JSThread *thread = msg->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + JSHandle str = JSTaggedValue::ToString(thread, GetCallArg(msg, 0)); + // The default log level of ace_engine and js_runtime is error + LOG(ERROR, RUNTIME) << ": " << base::StringHelper::ToStdString(*str); + + uint32_t numArgs = msg->GetArgsNumber(); + for (uint32_t i = 1; i < numArgs; i++) { + JSHandle obj = GetCallArg(msg, i); + std::ostringstream oss; + obj->Dump(thread, oss); + + // The default log level of ace_engine and js_runtime is error + LOG(ERROR, RUNTIME) << ": " << oss.str(); + } + + return JSTaggedValue::Undefined(); +} +} // namespace panda::ecmascript::builtins diff --git a/ecmascript/builtins/builtins_ark_tools.h b/ecmascript/builtins/builtins_ark_tools.h new file mode 100644 index 0000000000000000000000000000000000000000..f5256bb6d9a4230d10eb2a2732d3dea5345ebbb8 --- /dev/null +++ b/ecmascript/builtins/builtins_ark_tools.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_BUILTINS_BUILTINS_ARK_TOOLS_H +#define ECMASCRIPT_BUILTINS_BUILTINS_ARK_TOOLS_H + +#include "ecmascript/base/builtins_base.h" +#include "ecmascript/js_thread.h" + +namespace panda::ecmascript::builtins { +class BuiltinsArkTools : public base::BuiltinsBase { +public: + // Make sure the ECMASCRIPT_OBJECT_DUMP in config.h has been opened before use it + // Use through arkTools.print(msg, [obj1, obj2, ... objn]) in js + static JSTaggedValue ObjectDump(EcmaRuntimeCallInfo *msg); +}; +} // namespace panda::ecmascript::builtins + +#endif // ECMASCRIPT_BUILTINS_BUILTINS_ARK_TOOLS_H diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 569edd1cbf8010aec545f6518ea4665dec81a347..9348f3733c9b140efec98df6365f49f7366a5540 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -56,9 +56,10 @@ namespace panda::ecmascript { // NOLINTNEXTLINE(fuchsia-statically-constructed-objects) static const std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0"; +JSRuntimeOptions EcmaVM::options_; // NOLINT(fuchsia-statically-constructed-objects) /* static */ -EcmaVM *EcmaVM::Create(const RuntimeOptions &options) +EcmaVM *EcmaVM::Create(const JSRuntimeOptions &options) { auto runtime = Runtime::GetCurrent(); auto vm = runtime->GetInternalAllocator()->New(options); @@ -93,18 +94,18 @@ Expected EcmaVM::Create(Runtime *runtime) } // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -EcmaVM::EcmaVM() : EcmaVM(Runtime::GetOptions()) +EcmaVM::EcmaVM() : EcmaVM(EcmaVM::GetJSOptions()) { isTestMode_ = true; } -EcmaVM::EcmaVM(RuntimeOptions options) - : options_(std::move(options)), - stringTable_(new EcmaStringTable(this)), +EcmaVM::EcmaVM(JSRuntimeOptions options) + : stringTable_(new EcmaStringTable(this)), regionFactory_(std::make_unique()), chunk_(regionFactory_.get()), nativeMethods_(&chunk_) { + options_ = std::move(options); icEnable_ = options_.IsIcEnable(); rendezvous_ = chunk_.New(); snapshotSerializeEnable_ = options_.IsSnapshotSerializeEnabled(); diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index cde72c508d4355e630ca62a8bfa79150dda4265c..63a93b7b0235e2c71f8c672eded610997febecfb 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -24,6 +24,7 @@ #include "ecmascript/js_handle.h" #include "ecmascript/js_method.h" #include "ecmascript/js_native_pointer.h" +#include "ecmascript/js_runtime_options.h" #include "ecmascript/mem/c_containers.h" #include "ecmascript/mem/c_string.h" #include "ecmascript/mem/chunk_containers.h" @@ -75,11 +76,11 @@ public: return reinterpret_cast(object); } - static EcmaVM *Create(const RuntimeOptions &options); + static EcmaVM *Create(const JSRuntimeOptions &options); static bool Destroy(PandaVM *vm); - explicit EcmaVM(RuntimeOptions options); + explicit EcmaVM(JSRuntimeOptions options); static Expected Create([[maybe_unused]] Runtime *runtime); @@ -211,6 +212,11 @@ public: } const RuntimeOptions &GetOptions() const override + { + return Runtime::GetOptions(); + } + + static const JSRuntimeOptions &GetJSOptions() { return options_; } @@ -393,7 +399,7 @@ private: NO_COPY_SEMANTIC(EcmaVM); // init EcmaVM construct - RuntimeOptions options_; + static JSRuntimeOptions options_; EcmaStringTable *stringTable_; std::unique_ptr regionFactory_; Chunk chunk_; @@ -439,6 +445,7 @@ private: friend class SnapShotSerialize; friend class ObjectFactory; friend class ValueSerializer; + friend class panda::JSNApi; }; } // namespace ecmascript } // namespace panda diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h new file mode 100644 index 0000000000000000000000000000000000000000..5c13618871462a2eea0da3499435b1dc926eabc5 --- /dev/null +++ b/ecmascript/js_runtime_options.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_JS_RUNTIME_OPTIONS_H_ +#define ECMASCRIPT_JS_RUNTIME_OPTIONS_H_ + +#include "runtime/include/runtime_options.h" +#include "utils/logger.h" + +// namespace panda { +namespace panda::ecmascript { +class JSRuntimeOptions : public RuntimeOptions { +public: + explicit JSRuntimeOptions(const std::string &exe_path = "") : RuntimeOptions(exe_path) {} + ~JSRuntimeOptions() = default; + DEFAULT_COPY_SEMANTIC(JSRuntimeOptions); + DEFAULT_MOVE_SEMANTIC(JSRuntimeOptions); + + void AddOptions(PandArgParser *parser) + { + RuntimeOptions::AddOptions(parser); + parser->Add(&enable_ark_tools_); + } + + bool IsEnableArkTools() const + { + return enable_ark_tools_.GetValue(); + } + + void SetEnableArkTools(bool value) + { + enable_ark_tools_.SetValue(value); + } + + bool WasSetEnableArkTools() const + { + return enable_ark_tools_.WasSet(); + } + +private: + PandArg enable_ark_tools_{"enable-ark-tools", false, R"(Enable ark tools to debug. Default: false)"}; +}; +} // namespace panda::ecmascript + +#endif // ECMASCRIPT_JS_RUNTIME_OPTIONS_H_ diff --git a/ecmascript/js_vm/main.cpp b/ecmascript/js_vm/main.cpp index a3bad4b9ed4861c2b6459d07abec7cc6640c0780..9d766034077f9adc2431c71760ef128c12e5ffcd 100644 --- a/ecmascript/js_vm/main.cpp +++ b/ecmascript/js_vm/main.cpp @@ -23,6 +23,7 @@ #include "ecmascript/ecma_language_context.h" #include "ecmascript/ecma_string.h" #include "ecmascript/ecma_vm.h" +#include "ecmascript/js_runtime_options.h" #include "ecmascript/napi/include/jsnapi.h" #include "include/runtime.h" #include "libpandabase/os/native_stack.h" @@ -59,7 +60,7 @@ int Main(const int argc, const char **argv) BlockSignals(); Span sp(argv, argc); - RuntimeOptions runtimeOptions(sp[0]); + JSRuntimeOptions runtimeOptions(sp[0]); panda::PandArg help("help", false, "Print this message and exit"); panda::PandArg options("options", false, "Print compiler and runtime options"); @@ -106,6 +107,7 @@ int Main(const int argc, const char **argv) runtimeOptions.SetShouldInitializeIntrinsics(false); runtimeOptions.SetBootClassSpaces({"ecmascript"}); runtimeOptions.SetRuntimeType("ecmascript"); + JSNApi::SetOptions(runtimeOptions); static EcmaLanguageContext lcEcma; bool ret = Runtime::Create(runtimeOptions, {&lcEcma}); if (!ret) { diff --git a/ecmascript/napi/include/jsnapi.h b/ecmascript/napi/include/jsnapi.h index aff0c0facf5b0b620c60fd8bd0b95d7382a81a95..a3a4885cf4636242e3d6750773582c454e5cf167 100644 --- a/ecmascript/napi/include/jsnapi.h +++ b/ecmascript/napi/include/jsnapi.h @@ -44,6 +44,7 @@ class JSNApiTests; namespace ecmascript { class EcmaVM; +class JSRuntimeOptions; } // namespace ecmascript using Deleter = void (*)(void *buffer, void *data); @@ -726,6 +727,10 @@ public: debuggerLibraryPath_ = path; } + void SetEnableArkTools(bool value) { + enableArkTools_ = value; + } + private: std::string GetGcType() const { @@ -784,11 +789,18 @@ private: return debuggerLibraryPath_; } + bool GetEnableArkTools() const + { + return enableArkTools_; + } + + GC_TYPE gcType_ = GC_TYPE::EPSILON; LOG_LEVEL logLevel_ = LOG_LEVEL::DEBUG; uint32_t gcPoolSize_ = DEFAULT_GC_POOL_SIZE; LOG_PRINT logBufPrint_{nullptr}; std::string debuggerLibraryPath_{}; + bool enableArkTools_{false}; friend JSNApi; }; @@ -821,6 +833,7 @@ public: static void* SerializeValue(const EcmaVM *vm, Local data, Local transfer); static Local DeserializeValue(const EcmaVM *vm, void* recoder); static void DeleteSerializationData(void *data); + static void SetOptions(const ecmascript::JSRuntimeOptions &options); private: static bool CreateRuntime(const RuntimeOption &option); diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index 865091e49160774db5e2a4a1de019208328b3af9..edad0b42654c23113b71a0bdd9b4149176eec08f 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -39,6 +39,7 @@ #include "ecmascript/js_primitive_ref.h" #include "ecmascript/js_promise.h" #include "ecmascript/js_regexp.h" +#include "ecmascript/js_runtime_options.h" #include "ecmascript/js_serializer.h" #include "ecmascript/js_set.h" #include "ecmascript/js_tagged_number.h" @@ -93,6 +94,7 @@ using ecmascript::base::JsonParser; using ecmascript::base::JsonStringifier; using ecmascript::base::StringHelper; using ecmascript::base::TypedArrayHelper; +using ecmascript::JSRuntimeOptions; template using JSHandle = ecmascript::JSHandle; @@ -107,7 +109,7 @@ constexpr std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0"; // ------------------------------------ Panda ----------------------------------------------- bool JSNApi::CreateRuntime(const RuntimeOption &option) { - RuntimeOptions runtimeOptions; + JSRuntimeOptions runtimeOptions; runtimeOptions.SetRuntimeType("ecmascript"); // GC @@ -138,6 +140,8 @@ bool JSNApi::CreateRuntime(const RuntimeOption &option) // Debugger runtimeOptions.SetDebuggerLibraryPath(option.GetDebuggerLibraryPath()); + runtimeOptions.SetEnableArkTools(option.GetEnableArkTools()); + SetOptions(runtimeOptions); static EcmaLanguageContext lcEcma; if (!Runtime::Create(runtimeOptions, {&lcEcma})) { std::cerr << "Error: cannot create runtime" << std::endl; @@ -162,7 +166,7 @@ EcmaVM *JSNApi::CreateJSVM(const RuntimeOption &option) runtime = Runtime::GetCurrent(); return EcmaVM::Cast(runtime->GetPandaVM()); } - RuntimeOptions runtimeOptions; + JSRuntimeOptions runtimeOptions; // GC runtimeOptions.SetGcTriggerType("no-gc-for-start-up"); // A non-production gc strategy. Prohibit stw-gc 10 times. @@ -381,6 +385,11 @@ Local JSNApi::GetExportObject(EcmaVM *vm, const std::string &file, co JSHandle exportObj = moduleManager->GetModuleItem(vm->GetJSThread(), moduleObj, itemString); return JSNApiHelper::ToLocal(exportObj); } + +void JSNApi::SetOptions(const ecmascript::JSRuntimeOptions &options) +{ + ecmascript::EcmaVM::options_ = options; +} // ----------------------------------- HandleScope ------------------------------------- LocalScope::LocalScope(const EcmaVM *vm) : thread_(vm->GetJSThread()) { diff --git a/ecmascript/snapshot/tests/snapshot_test.cpp b/ecmascript/snapshot/tests/snapshot_test.cpp index 3131e0baac3e18970a95c7d8d0cdf9754a90d3dc..f28064c11435af7207046300ab8b7e6e14f6b49c 100644 --- a/ecmascript/snapshot/tests/snapshot_test.cpp +++ b/ecmascript/snapshot/tests/snapshot_test.cpp @@ -40,7 +40,7 @@ public: void SetUp() override { - RuntimeOptions options; + JSRuntimeOptions options; options.SetShouldLoadBootPandaFiles(false); options.SetShouldInitializeIntrinsics(false); options.SetBootIntrinsicSpaces({"ecmascript"}); diff --git a/ecmascript/tests/gc_test.cpp b/ecmascript/tests/gc_test.cpp index bece8eee7f97c335f28b1cf6f6f3c113141c20a8..3ba0b6fc4af667d145202ccedae0b7625c2001ee 100644 --- a/ecmascript/tests/gc_test.cpp +++ b/ecmascript/tests/gc_test.cpp @@ -38,7 +38,7 @@ public: void SetUp() override { - RuntimeOptions options; + JSRuntimeOptions options; options.SetShouldLoadBootPandaFiles(false); options.SetShouldInitializeIntrinsics(false); options.SetBootClassSpaces({"ecmascript"}); diff --git a/ecmascript/tests/js_serializer_test.cpp b/ecmascript/tests/js_serializer_test.cpp index e40c6341dc852fd8d3710bf3d694eb73ba790f20..5a0d702ef6cfaf2f45c53fdd0cc5fc793096da97 100644 --- a/ecmascript/tests/js_serializer_test.cpp +++ b/ecmascript/tests/js_serializer_test.cpp @@ -41,7 +41,7 @@ public: JSDeserializerTest() : ecmaVm(nullptr), scope(nullptr), thread(nullptr) {} void Init() { - RuntimeOptions options; + JSRuntimeOptions options; options.SetShouldLoadBootPandaFiles(false); options.SetShouldInitializeIntrinsics(false); options.SetBootIntrinsicSpaces({"ecmascript"}); diff --git a/ecmascript/tests/test_helper.h b/ecmascript/tests/test_helper.h index fd21b7023445e0457934d4a587e0e5e192e1eb61..f65d77ef9a146d960cd20373e6ba00583783391f 100644 --- a/ecmascript/tests/test_helper.h +++ b/ecmascript/tests/test_helper.h @@ -33,6 +33,7 @@ using panda::ecmascript::JSTaggedType; using panda::ecmascript::JSTaggedValue; using panda::ecmascript::JSThread; using panda::ecmascript::NUM_MANDATORY_JSFUNC_ARGS; +using ecmascript::JSRuntimeOptions; // Add for hmf tests platform, define to TEST_F or TEST_P when running gtest in gitlab #define HWTEST_F_L0(testsuit, testcase) HWTEST_F(testsuit, testcase, testing::ext::TestSize.Level0) @@ -81,7 +82,7 @@ public: // If you want to call once create, you can refer to BuiltinsMathTest for detail. static void CreateEcmaVMWithScope(PandaVM *&instance, JSThread *&thread, EcmaHandleScope *&scope) { - RuntimeOptions options; + JSRuntimeOptions options; options.SetShouldLoadBootPandaFiles(false); options.SetShouldInitializeIntrinsics(false); options.SetBootClassSpaces({"ecmascript"});