diff --git a/BUILD.gn b/BUILD.gn index 0f8e7fe84d7bd8d9216411a4bd284f2846d65196..e333df1748f6f2539f90a08dbd6d1d66c23345c3 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -232,6 +232,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 239543543a0bf7c584273e21edc2885e306bd130..e3de53701fc1592bbefe16356b30cd422dca3127 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" @@ -268,7 +270,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(); @@ -302,6 +304,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); @@ -2733,4 +2740,13 @@ void Builtins::InitializeJSNativeObject(const JSHandle &env) const env->SetJSNativeObjectClass(thread_, dynclass); } + +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 7a7753ea9633b6ddcde42fc5ab3ad3e546c9c7bc..1ae4d9c22f3cccb68c459a6afe662e74f74703ba 100644 --- a/ecmascript/builtins.h +++ b/ecmascript/builtins.h @@ -209,6 +209,7 @@ private: void SetGetter(const JSHandle &obj, const JSHandle &key, const JSHandle &getter) const; void InitializeJSNativeObject(const JSHandle &env) 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 31bb8274e624a0672003da22504623473a4e518e..118ed3fc9d0c0ad769ea201d05b8de827401adea 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -54,9 +54,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); @@ -91,18 +92,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 afa964b5a12c8f40210ae22c70243ff2951218ef..dba3f2b4350da07d1b0e9a02e81131f30f68733f 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -23,6 +23,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" @@ -72,11 +73,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); @@ -208,6 +209,11 @@ public: } const RuntimeOptions &GetOptions() const override + { + return Runtime::GetOptions(); + } + + static const JSRuntimeOptions &GetJSOptions() { return options_; } @@ -379,7 +385,7 @@ private: NO_COPY_SEMANTIC(EcmaVM); // init EcmaVM construct - RuntimeOptions options_; + static JSRuntimeOptions options_; EcmaStringTable *stringTable_; std::unique_ptr regionFactory_; Chunk chunk_; @@ -423,6 +429,7 @@ private: friend class SnapShotSerialize; friend class ObjectFactory; + 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 4bf334dd88b8f6f6a223b5ce6004fb519431c144..e2a42b907b2406c54dd12bbd05d077364fe0196d 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); @@ -718,6 +719,10 @@ public: debuggerLibraryPath_ = path; } + void SetEnableArkTools(bool value) { + enableArkTools_ = value; + } + private: std::string GetGcType() const { @@ -776,11 +781,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; }; @@ -813,6 +825,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 4ab3e3ad293b811593eb9c4ee31c9cf95affc24a..e0c954508cf9652faea74eee90b0a68689ea0483 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" @@ -94,6 +95,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; @@ -108,7 +110,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 @@ -139,6 +141,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; @@ -163,7 +167,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. @@ -370,6 +374,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 4a5a202f9e68100756d2e562ddf55cec6a6bdd4c..95a2fc49c511f4b00f68d4da5d9888a802f02624 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) @@ -80,7 +81,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"});