From f662ff34860f6e66b066c36fd51f687ca8cbbcec Mon Sep 17 00:00:00 2001 From: Ryan Hyun Choi Date: Thu, 2 Sep 2021 16:07:52 +0900 Subject: [PATCH] LWNode_Release_210902_60ce3db Change-Id: Id542c05f38654454540ec38b059c18932f375cbb Signed-off-by: Ryan Choi --- configure.py | 18 +- lib/buffer.js | 12 + lib/internal/assert/calltracker.js | 13 +- lib/internal/bootstrap/node.js | 6 + lib/internal/child_process.js | 52 +- lib/internal/child_process_origin.js | 1082 ----------------- lib/internal/histogram.js | 66 +- lib/internal/histogram_origin.js | 94 -- lib/internal/process/per_thread.js | 39 + lib/internal/source_map/source_map.js | 51 +- lib/internal/source_map/source_map.origin.js | 343 ------ lib/internal/vm/module.js | 20 +- lib/internal/vm/module.origin.js | 465 ------- lib/repl.js | 1 - lib/vm.js | 10 +- lwnode/build-cctest-node.sh | 30 + lwnode/build-cctest.sh | 3 +- lwnode/build.sh | 6 +- lwnode/code/escargotshim/common.gypi | 19 +- .../build/cmake/toolchain_android_arm.cmake | 29 - .../build/cmake/toolchain_darwin_x64.cmake | 30 - .../build/cmake/toolchain_linux_aarch64.cmake | 30 - .../build/cmake/toolchain_linux_arm.cmake | 30 - .../build/cmake/toolchain_linux_i686.cmake | 30 - .../build/cmake/toolchain_linux_x64.cmake | 30 - .../build/cmake/toolchain_linux_x86.cmake | 30 - .../cmake/toolchain_tizen_obs_aarch64.cmake | 30 - .../build/cmake/toolchain_tizen_obs_arm.cmake | 32 - .../cmake/toolchain_tizen_obs_i686.cmake | 32 - .../build/cmake/toolchain_tizen_obs_x64.cmake | 30 - .../build/cmake/toolchain_tizen_obs_x86.cmake | 30 - .../cmake/toolchain_tizen_obs_x86_64.cmake | 30 - .../deps/escargot/build/config.cmake | 28 +- .../deps/escargot/build/escargot.cmake | 34 +- .../deps/escargot/build/target.cmake | 62 + .../escargotshim/deps/escargot/src/Escargot.h | 13 + .../deps/escargot/src/api/EscargotPublic.cpp | 396 +++--- .../deps/escargot/src/api/EscargotPublic.h | 82 +- .../BuiltinArray.cpp} | 16 +- .../BuiltinArrayBuffer.cpp} | 10 +- .../BuiltinAsyncFromSyncIterator.cpp} | 0 .../BuiltinAsyncFunction.cpp} | 10 +- .../BuiltinAsyncGeneratorFunction.cpp} | 6 +- .../BuiltinAsyncIterator.cpp} | 6 +- .../BuiltinAtomics.cpp} | 382 ++++-- .../BuiltinBigInt.cpp} | 23 +- .../BuiltinBoolean.cpp} | 8 +- .../BuiltinDataView.cpp} | 16 +- .../BuiltinDate.cpp} | 14 +- .../BuiltinError.cpp} | 10 +- .../BuiltinFinalizationRegistry.cpp} | 10 +- .../BuiltinFunction.cpp} | 8 +- .../BuiltinGeneratorFunction.cpp} | 10 +- .../BuiltinIntl.cpp} | 30 +- .../BuiltinIterator.cpp} | 10 +- .../BuiltinJSON.cpp} | 18 +- .../BuiltinMap.cpp} | 14 +- .../BuiltinMath.cpp} | 17 +- .../BuiltinNumber.cpp} | 10 +- .../BuiltinObject.cpp} | 12 +- .../BuiltinPromise.cpp} | 0 .../BuiltinProxy.cpp} | 2 +- .../BuiltinReflect.cpp} | 4 +- .../BuiltinRegExp.cpp} | 12 +- .../BuiltinSet.cpp} | 14 +- .../BuiltinSharedArrayBuffer.cpp} | 11 +- .../BuiltinString.cpp} | 20 +- .../BuiltinSymbol.cpp} | 12 +- .../BuiltinTypedArray.cpp} | 36 +- .../BuiltinWeakMap.cpp} | 14 +- .../BuiltinWeakRef.cpp} | 10 +- .../BuiltinWeakSet.cpp} | 14 +- .../src/codecache/CodeCacheReaderWriter.cpp | 4 +- .../src/interpreter/ByteCodeInterpreter.cpp | 6 +- .../escargot/src/{runtime => intl}/Intl.cpp | 4 +- .../escargot/src/{runtime => intl}/Intl.h | 0 .../src/{runtime => intl}/IntlCollator.cpp | 8 +- .../src/{runtime => intl}/IntlCollator.h | 0 .../{runtime => intl}/IntlDateTimeFormat.cpp | 12 +- .../{runtime => intl}/IntlDateTimeFormat.h | 0 .../src/{runtime => intl}/IntlLocale.cpp | 6 +- .../src/{runtime => intl}/IntlLocale.h | 0 .../{runtime => intl}/IntlNumberFormat.cpp | 10 +- .../src/{runtime => intl}/IntlNumberFormat.h | 0 .../src/{runtime => intl}/IntlPluralRules.cpp | 8 +- .../src/{runtime => intl}/IntlPluralRules.h | 0 .../IntlRelativeTimeFormat.cpp | 12 +- .../IntlRelativeTimeFormat.h | 0 .../deps/escargot/src/parser/Script.cpp | 8 +- .../src/parser/esprima_cpp/esprima.cpp | 17 +- .../deps/escargot/src/runtime/ArrayBuffer.cpp | 75 ++ .../deps/escargot/src/runtime/ArrayBuffer.h | 181 +++ .../src/runtime/ArrayBufferObject.cpp | 56 +- .../escargot/src/runtime/ArrayBufferObject.h | 132 +- .../deps/escargot/src/runtime/ArrayObject.h | 7 +- .../escargot/src/runtime/BackingStore.cpp | 54 +- .../deps/escargot/src/runtime/BackingStore.h | 17 +- .../deps/escargot/src/runtime/BigInt.cpp | 46 +- .../deps/escargot/src/runtime/Context.cpp | 3 +- .../escargot/src/runtime/DataViewObject.h | 4 +- .../escargot/src/runtime/FunctionTemplate.cpp | 13 +- .../escargot/src/runtime/FunctionTemplate.h | 4 +- .../deps/escargot/src/runtime/Global.cpp | 73 ++ .../deps/escargot/src/runtime/Global.h | 57 + .../deps/escargot/src/runtime/Object.cpp | 10 + .../deps/escargot/src/runtime/Object.h | 7 + .../escargot/src/runtime/ObjectTemplate.cpp | 9 +- .../deps/escargot/src/runtime/Platform.h | 14 +- .../deps/escargot/src/runtime/PointerValue.h | 23 +- .../escargot/src/runtime/RegExpObject.cpp | 4 +- .../src/runtime/SharedArrayBufferObject.cpp | 48 +- .../src/runtime/SharedArrayBufferObject.h | 45 +- .../deps/escargot/src/runtime/Template.cpp | 21 +- .../deps/escargot/src/runtime/Template.h | 21 +- .../deps/escargot/src/runtime/ThreadLocal.cpp | 133 ++ .../deps/escargot/src/runtime/ThreadLocal.h | 112 ++ .../escargot/src/runtime/TypedArrayObject.cpp | 4 +- .../escargot/src/runtime/TypedArrayObject.h | 2 +- .../deps/escargot/src/runtime/VMInstance.cpp | 94 +- .../deps/escargot/src/runtime/VMInstance.h | 74 +- .../serialization/SerializedBigIntValue.h | 79 ++ .../serialization/SerializedBooleanValue.h | 65 + .../serialization/SerializedNullValue.h | 50 + .../serialization/SerializedNumberValue.h | 64 + .../SerializedSharedArrayBufferObjectValue.h | 77 ++ .../serialization/SerializedStringValue.h | 77 ++ .../serialization/SerializedSymbolValue.h | 98 ++ .../serialization/SerializedUndefinedValue.h | 49 + .../runtime/serialization/SerializedValue.h | 68 ++ .../src/runtime/serialization/Serializer.cpp | 97 ++ .../src/runtime/serialization/Serializer.h | 40 + .../deps/escargot/src/shell/Shell.cpp | 583 ++++++--- .../deps/escargot/src/util/SpinLock.h | 54 + .../src/wasm/GlobalObjectBuiltinWASM.cpp | 11 +- .../deps/escargot/src/wasm/WASMOperations.cpp | 15 +- .../escargot/third_party/wasm/CMakeLists.txt | 18 +- lwnode/code/escargotshim/escargot.gyp | 27 +- lwnode/code/escargotshim/escargotshim.gyp | 36 +- .../escargotshim/include/lwnode-internal.h | 1 - .../code/escargotshim/include/lwnode/lwnode.h | 58 + lwnode/code/escargotshim/include/v8.h | 4 + lwnode/code/escargotshim/lib/stack_frame.js | 96 -- lwnode/code/escargotshim/src/api-data.cc | 189 ++- .../code/escargotshim/src/api-environment.cc | 133 +- lwnode/code/escargotshim/src/api-exception.cc | 89 +- lwnode/code/escargotshim/src/api-scripts.cc | 4 +- .../escargotshim/src/api-serialization.cc | 76 +- lwnode/code/escargotshim/src/api-template.cc | 106 +- lwnode/code/escargotshim/src/api.h | 1 + lwnode/code/escargotshim/src/api/context.cc | 42 +- lwnode/code/escargotshim/src/api/context.h | 10 +- lwnode/code/escargotshim/src/api/engine.cc | 12 +- lwnode/code/escargotshim/src/api/es-helper.cc | 350 +++++- lwnode/code/escargotshim/src/api/es-helper.h | 33 +- .../code/escargotshim/src/api/es-v8-helper.cc | 31 + .../code/escargotshim/src/api/es-v8-helper.h | 2 + .../code/escargotshim/src/api/extra-data.cc | 85 +- lwnode/code/escargotshim/src/api/extra-data.h | 111 +- lwnode/code/escargotshim/src/api/function.cc | 9 +- lwnode/code/escargotshim/src/api/function.h | 2 +- lwnode/code/escargotshim/src/api/handle.cc | 18 +- lwnode/code/escargotshim/src/api/handle.h | 2 +- lwnode/code/escargotshim/src/api/isolate.cc | 137 ++- lwnode/code/escargotshim/src/api/isolate.h | 26 +- lwnode/code/escargotshim/src/api/object.cc | 9 +- .../code/escargotshim/src/api/serializer.cc | 320 +++++ lwnode/code/escargotshim/src/api/serializer.h | 60 + .../code/escargotshim/src/api/stack-trace.cc | 310 +++++ .../code/escargotshim/src/api/stack-trace.h | 42 + lwnode/code/escargotshim/src/api/utils.h | 1 - .../code/escargotshim/src/api/utils/debug.cc | 7 +- .../escargotshim/src/api/utils/gc-container.h | 8 +- lwnode/code/escargotshim/src/api/utils/gc.cc | 50 +- lwnode/code/escargotshim/src/api/utils/gc.h | 9 + .../src/api/utils/{ => logger}/flags.cc | 0 .../src/api/utils/{ => logger}/flags.h | 6 +- .../src/api/utils/{ => logger}/logger.cc | 18 +- .../src/api/utils/{ => logger}/logger.h | 72 +- .../escargotshim/src/api/utils/logger/trace.h | 90 ++ lwnode/code/escargotshim/src/api/utils/misc.h | 84 +- .../code/escargotshim/src/api/utils/smaps.cc | 278 +++++ .../code/escargotshim/src/api/utils/smaps.h | 56 + lwnode/code/escargotshim/src/base.h | 18 +- lwnode/code/escargotshim/src/lwnode.cc | 195 +++ lwnode/code/escargotshim/src/unimplemented.h | 2 +- node.gyp | 11 + packaging/lwnode.spec | 43 +- src/node.h | 6 + src/node_platform.cc | 5 +- src/node_process_methods.cc | 3 + src/node_worker.cc | 21 +- tools/gyp_node.py | 13 +- tools/test.py | 2 +- 193 files changed, 6062 insertions(+), 4377 deletions(-) delete mode 100644 lib/internal/child_process_origin.js delete mode 100644 lib/internal/histogram_origin.js delete mode 100644 lib/internal/source_map/source_map.origin.js delete mode 100644 lib/internal/vm/module.origin.js create mode 100755 lwnode/build-cctest-node.sh delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_android_arm.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_darwin_x64.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_aarch64.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_arm.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_i686.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x64.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x86.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_aarch64.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_arm.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_i686.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x64.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86.cmake delete mode 100644 lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86_64.cmake create mode 100644 lwnode/code/escargotshim/deps/escargot/build/target.cmake rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinArray.cpp => builtins/BuiltinArray.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinArrayBuffer.cpp => builtins/BuiltinArrayBuffer.cpp} (98%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinAsyncFromSyncIterator.cpp => builtins/BuiltinAsyncFromSyncIterator.cpp} (100%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinAsyncFunction.cpp => builtins/BuiltinAsyncFunction.cpp} (94%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinAsyncGeneratorFunction.cpp => builtins/BuiltinAsyncGeneratorFunction.cpp} (98%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinAsyncIterator.cpp => builtins/BuiltinAsyncIterator.cpp} (95%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinAtomics.cpp => builtins/BuiltinAtomics.cpp} (57%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinBigInt.cpp => builtins/BuiltinBigInt.cpp} (96%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinBoolean.cpp => builtins/BuiltinBoolean.cpp} (97%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinDataView.cpp => builtins/BuiltinDataView.cpp} (97%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinDate.cpp => builtins/BuiltinDate.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinError.cpp => builtins/BuiltinError.cpp} (98%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinFinalizationRegistry.cpp => builtins/BuiltinFinalizationRegistry.cpp} (97%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinFunction.cpp => builtins/BuiltinFunction.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinGeneratorFunction.cpp => builtins/BuiltinGeneratorFunction.cpp} (97%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinIntl.cpp => builtins/BuiltinIntl.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinIterator.cpp => builtins/BuiltinIterator.cpp} (91%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinJSON.cpp => builtins/BuiltinJSON.cpp} (98%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinMap.cpp => builtins/BuiltinMap.cpp} (98%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinMath.cpp => builtins/BuiltinMath.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinNumber.cpp => builtins/BuiltinNumber.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinObject.cpp => builtins/BuiltinObject.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinPromise.cpp => builtins/BuiltinPromise.cpp} (100%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinProxy.cpp => builtins/BuiltinProxy.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinReflect.cpp => builtins/BuiltinReflect.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinRegExp.cpp => builtins/BuiltinRegExp.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinSet.cpp => builtins/BuiltinSet.cpp} (98%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinSharedArrayBuffer.cpp => builtins/BuiltinSharedArrayBuffer.cpp} (97%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinString.cpp => builtins/BuiltinString.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinSymbol.cpp => builtins/BuiltinSymbol.cpp} (98%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinTypedArray.cpp => builtins/BuiltinTypedArray.cpp} (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinWeakMap.cpp => builtins/BuiltinWeakMap.cpp} (97%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinWeakRef.cpp => builtins/BuiltinWeakRef.cpp} (96%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime/GlobalObjectBuiltinWeakSet.cpp => builtins/BuiltinWeakSet.cpp} (97%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/Intl.cpp (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/Intl.h (100%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlCollator.cpp (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlCollator.h (100%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlDateTimeFormat.cpp (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlDateTimeFormat.h (100%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlLocale.cpp (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlLocale.h (100%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlNumberFormat.cpp (99%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlNumberFormat.h (100%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlPluralRules.cpp (98%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlPluralRules.h (100%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlRelativeTimeFormat.cpp (98%) rename lwnode/code/escargotshim/deps/escargot/src/{runtime => intl}/IntlRelativeTimeFormat.h (100%) create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.cpp create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/Global.cpp create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/Global.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.cpp create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBigIntValue.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBooleanValue.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNullValue.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNumberValue.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSharedArrayBufferObjectValue.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedStringValue.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSymbolValue.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedUndefinedValue.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedValue.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.cpp create mode 100644 lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.h create mode 100644 lwnode/code/escargotshim/deps/escargot/src/util/SpinLock.h create mode 100644 lwnode/code/escargotshim/include/lwnode/lwnode.h delete mode 100644 lwnode/code/escargotshim/lib/stack_frame.js create mode 100644 lwnode/code/escargotshim/src/api/serializer.cc create mode 100644 lwnode/code/escargotshim/src/api/serializer.h create mode 100644 lwnode/code/escargotshim/src/api/stack-trace.cc create mode 100644 lwnode/code/escargotshim/src/api/stack-trace.h rename lwnode/code/escargotshim/src/api/utils/{ => logger}/flags.cc (100%) rename lwnode/code/escargotshim/src/api/utils/{ => logger}/flags.h (91%) rename lwnode/code/escargotshim/src/api/utils/{ => logger}/logger.cc (83%) rename lwnode/code/escargotshim/src/api/utils/{ => logger}/logger.h (65%) create mode 100644 lwnode/code/escargotshim/src/api/utils/logger/trace.h create mode 100644 lwnode/code/escargotshim/src/api/utils/smaps.cc create mode 100644 lwnode/code/escargotshim/src/api/utils/smaps.h create mode 100644 lwnode/code/escargotshim/src/lwnode.cc diff --git a/configure.py b/configure.py index 4e3e8d5..20a451d 100755 --- a/configure.py +++ b/configure.py @@ -88,9 +88,9 @@ lwnode_optgroup.add_option('--tizen', help='Platform: tizen') lwnode_optgroup.add_option('--profile', - choices=['none', 'tv', 'kiosk'], - default='none', - help='Build profile: none | tv | kiosk') + choices=['common', 'tv', 'kiosk'], + default='common', + help='Build profile: common | tv | kiosk') lwnode_optgroup.add_option('--enable-external-builtin-scripts', action='store_true', @@ -103,6 +103,11 @@ lwnode_optgroup.add_option('--static-escargot', dest='static_escargot', help='link to a static escargot instead of shared linking') +lwnode_optgroup.add_option('--escargot-threading', + action='store_true', + dest='escargot_threading', + help='Enable Escargot threading') + parser.add_option_group(lwnode_optgroup) def get_lwnode_gyp_options(): @@ -129,7 +134,6 @@ def get_lwnode_gyp_options(): if options.tizen: args += ['-Dtarget_os=tizen'] args += ['-Dprofile='+ str(options.profile)] - args += ['-Descargot_host=tizen_obs'] else: args += ['-Dtarget_os=linux'] @@ -138,6 +142,12 @@ def get_lwnode_gyp_options(): else: args += (['-Descargot_lib_type=shared_lib']) + if options.escargot_threading: + args += (['-Descargot_threading=1']) + else: + args += (['-Descargot_threading=0']) + + args += ['-Dnode_core_target_name=lwnode'] args += ['-Dnode_lib_target_name=liblwnode'] diff --git a/lib/buffer.js b/lib/buffer.js index 2c89a24..b8bec1e 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -178,6 +178,18 @@ const bufferWarning = 'Buffer() is deprecated due to security and usability ' + 'Buffer.allocUnsafe(), or Buffer.from() methods instead.'; function showFlaggedDeprecation() { + // @lwnode + // @fixme force depress DeprecationWarning until isInsideNodeModules works + if (bufferWarningAlreadyEmitted || + ++nodeModulesCheckCounter > 10000 || + (!require('internal/options').getOptionValue('--pending-deprecation'))) { + return; + } + + process.emitWarning(bufferWarning, 'DeprecationWarning', 'DEP0005'); + bufferWarningAlreadyEmitted = true; + return; + if (bufferWarningAlreadyEmitted || ++nodeModulesCheckCounter > 10000 || (!require('internal/options').getOptionValue('--pending-deprecation') && diff --git a/lib/internal/assert/calltracker.js b/lib/internal/assert/calltracker.js index 9a6f73c..74f517f 100644 --- a/lib/internal/assert/calltracker.js +++ b/lib/internal/assert/calltracker.js @@ -19,9 +19,7 @@ const noop = () => {}; class CallTracker { - // @lwnode - // #callChecks = new SafeSet() - __callChecks = new SafeSet() + #callChecks = new SafeSet() calls(fn, exact = 1) { if (process._exiting) @@ -42,10 +40,7 @@ class CallTracker { stackTrace: new Error(), name: fn.name || 'calls' }; - // @lwnode - // const callChecks = this.#callChecks; - const callChecks = this.__callChecks; - + const callChecks = this.#callChecks; callChecks.add(context); return function() { @@ -66,9 +61,7 @@ class CallTracker { report() { const errors = []; - // @lwnode - // for (const context of this.#callChecks) { - for (const context of this.__callChecks) { + for (const context of this.#callChecks) { // If functions have not been called exact times if (context.actual !== context.exact) { const message = `Expected the ${context.name} function to be ` + diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index 6d6ca2a..4a9a536 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -87,6 +87,12 @@ const rawMethods = internalBinding('process_methods'); process.kill = wrapped.kill; process.exit = wrapped.exit; + // @lwnode + process.lwnode = wrapped.lwnode; + process._print = wrapped.lwnode._print; + process._ptr = wrapped.lwnode._ptr; + process._stack = wrapped.lwnode._stack; + process.openStdin = function() { process.stdin.resume(); return process.stdin; diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index dc69244..cb035c8 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -504,20 +504,13 @@ ChildProcess.prototype.unref = function() { }; class Control extends EventEmitter { - // @lwnode - // #channel = null; - // #refs = 0; - // #refExplicitlySet = false; - __channel = null; - __refs = 0; - __refExplicitlySet = false; - // end @lwnode + #channel = null; + #refs = 0; + #refExplicitlySet = false; constructor(channel) { super(); - // @lwnode - // this.#channel = channel; - this.__channel = channel; + this.#channel = channel; } // The methods keeping track of the counter are being used to track the @@ -525,49 +518,30 @@ class Control extends EventEmitter { // in progress. Once the user has explicitly requested a certain state, these // methods become no-ops in order to not interfere with the user's intentions. refCounted() { - // @lwnode - // if (++this.#refs === 1 && !this.#refExplicitlySet) { - // this.#channel.ref(); - // } - if (++this.__refs === 1 && !this.__refExplicitlySet) { - this.__channel.ref(); + if (++this.#refs === 1 && !this.#refExplicitlySet) { + this.#channel.ref(); } - // end @lwnode } unrefCounted() { - // @lwnode - // if (--this.#refs === 0 && !this.#refExplicitlySet) { - // this.#channel.unref(); - // this.emit('unref'); - // } - if (--this.__refs === 0 && !this.__refExplicitlySet) { - this.__channel.unref(); + if (--this.#refs === 0 && !this.#refExplicitlySet) { + this.#channel.unref(); this.emit('unref'); } - // end @lwnode } ref() { - // @lwnode - // this.#refExplicitlySet = true; - // this.#channel.ref(); - this.__refExplicitlySet = true; - this.__channel.ref(); + this.#refExplicitlySet = true; + this.#channel.ref(); } unref() { - // @lwnode - // this.#refExplicitlySet = true; - // this.#channel.unref(); - this.__refExplicitlySet = true; - this.__channel.unref(); + this.#refExplicitlySet = true; + this.#channel.unref(); } get fd() { - // @lwnode - // return this.#channel ? this.#channel.fd : undefined; - return this.__channel ? this.__channel.fd : undefined; + return this.#channel ? this.#channel.fd : undefined; } } diff --git a/lib/internal/child_process_origin.js b/lib/internal/child_process_origin.js deleted file mode 100644 index cb035c8..0000000 --- a/lib/internal/child_process_origin.js +++ /dev/null @@ -1,1082 +0,0 @@ -'use strict'; - -const { - ArrayIsArray, - ObjectDefineProperty, - ObjectSetPrototypeOf, - Symbol, - Uint8Array, -} = primordials; - -const { - errnoException, - codes: { - ERR_INVALID_ARG_TYPE, - ERR_INVALID_HANDLE_TYPE, - ERR_INVALID_OPT_VALUE, - ERR_INVALID_SYNC_FORK_INPUT, - ERR_IPC_CHANNEL_CLOSED, - ERR_IPC_DISCONNECTED, - ERR_IPC_ONE_PIPE, - ERR_IPC_SYNC_FORK, - ERR_MISSING_ARGS - } -} = require('internal/errors'); -const { validateString, validateOneOf } = require('internal/validators'); -const EventEmitter = require('events'); -const net = require('net'); -const dgram = require('dgram'); -const inspect = require('internal/util/inspect').inspect; -const assert = require('internal/assert'); - -const { Process } = internalBinding('process_wrap'); -const { - WriteWrap, - kReadBytesOrError, - kArrayBufferOffset, - kLastWriteWasAsync, - streamBaseState -} = internalBinding('stream_wrap'); -const { Pipe, constants: PipeConstants } = internalBinding('pipe_wrap'); -const { TCP } = internalBinding('tcp_wrap'); -const { TTY } = internalBinding('tty_wrap'); -const { UDP } = internalBinding('udp_wrap'); -const SocketList = require('internal/socket_list'); -const { owner_symbol } = require('internal/async_hooks').symbols; -const { convertToValidSignal, deprecate } = require('internal/util'); -const { isArrayBufferView } = require('internal/util/types'); -const spawn_sync = internalBinding('spawn_sync'); -const { kStateSymbol } = require('internal/dgram'); - -const { - UV_EACCES, - UV_EAGAIN, - UV_EINVAL, - UV_EMFILE, - UV_ENFILE, - UV_ENOENT, - UV_ENOSYS, - UV_ESRCH -} = internalBinding('uv'); - -const { SocketListSend, SocketListReceive } = SocketList; - -// Lazy loaded for startup performance and to allow monkey patching of -// internalBinding('http_parser').HTTPParser. -let freeParser; -let HTTPParser; - -const MAX_HANDLE_RETRANSMISSIONS = 3; -const kChannelHandle = Symbol('kChannelHandle'); -const kIsUsedAsStdio = Symbol('kIsUsedAsStdio'); - -// This object contain function to convert TCP objects to native handle objects -// and back again. -const handleConversion = { - 'net.Native': { - simultaneousAccepts: true, - - send(message, handle, options) { - return handle; - }, - - got(message, handle, emit) { - emit(handle); - } - }, - - 'net.Server': { - simultaneousAccepts: true, - - send(message, server, options) { - return server._handle; - }, - - got(message, handle, emit) { - const server = new net.Server(); - server.listen(handle, () => { - emit(server); - }); - } - }, - - 'net.Socket': { - send(message, socket, options) { - if (!socket._handle) - return; - - // If the socket was created by net.Server - if (socket.server) { - // The worker should keep track of the socket - message.key = socket.server._connectionKey; - - const firstTime = !this[kChannelHandle].sockets.send[message.key]; - const socketList = getSocketList('send', this, message.key); - - // The server should no longer expose a .connection property - // and when asked to close it should query the socket status from - // the workers - if (firstTime) socket.server._setupWorker(socketList); - - // Act like socket is detached - if (!options.keepOpen) - socket.server._connections--; - } - - const handle = socket._handle; - - // Remove handle from socket object, it will be closed when the socket - // will be sent - if (!options.keepOpen) { - handle.onread = nop; - socket._handle = null; - socket.setTimeout(0); - - if (freeParser === undefined) - freeParser = require('_http_common').freeParser; - if (HTTPParser === undefined) - HTTPParser = require('_http_common').HTTPParser; - - // In case of an HTTP connection socket, release the associated - // resources - if (socket.parser && socket.parser instanceof HTTPParser) { - freeParser(socket.parser, null, socket); - if (socket._httpMessage) - socket._httpMessage.detachSocket(socket); - } - } - - return handle; - }, - - postSend(message, handle, options, callback, target) { - // Store the handle after successfully sending it, so it can be closed - // when the NODE_HANDLE_ACK is received. If the handle could not be sent, - // just close it. - if (handle && !options.keepOpen) { - if (target) { - // There can only be one _pendingMessage as passing handles are - // processed one at a time: handles are stored in _handleQueue while - // waiting for the NODE_HANDLE_ACK of the current passing handle. - assert(!target._pendingMessage); - target._pendingMessage = - { callback, message, handle, options, retransmissions: 0 }; - } else { - handle.close(); - } - } - }, - - got(message, handle, emit) { - const socket = new net.Socket({ - handle: handle, - readable: true, - writable: true - }); - - // If the socket was created by net.Server we will track the socket - if (message.key) { - - // Add socket to connections list - const socketList = getSocketList('got', this, message.key); - socketList.add({ - socket: socket - }); - } - - emit(socket); - } - }, - - 'dgram.Native': { - simultaneousAccepts: false, - - send(message, handle, options) { - return handle; - }, - - got(message, handle, emit) { - emit(handle); - } - }, - - 'dgram.Socket': { - simultaneousAccepts: false, - - send(message, socket, options) { - message.dgramType = socket.type; - - return socket[kStateSymbol].handle; - }, - - got(message, handle, emit) { - const socket = new dgram.Socket(message.dgramType); - - socket.bind(handle, () => { - emit(socket); - }); - } - } -}; - -function stdioStringToArray(stdio, channel) { - const options = []; - - switch (stdio) { - case 'ignore': - case 'pipe': options.push(stdio, stdio, stdio); break; - case 'inherit': options.push(0, 1, 2); break; - default: - throw new ERR_INVALID_OPT_VALUE('stdio', stdio); - } - - if (channel) options.push(channel); - - return options; -} - -function ChildProcess() { - EventEmitter.call(this); - - this._closesNeeded = 1; - this._closesGot = 0; - this.connected = false; - - this.signalCode = null; - this.exitCode = null; - this.killed = false; - this.spawnfile = null; - - this._handle = new Process(); - this._handle[owner_symbol] = this; - - this._handle.onexit = (exitCode, signalCode) => { - if (signalCode) { - this.signalCode = signalCode; - } else { - this.exitCode = exitCode; - } - - if (this.stdin) { - this.stdin.destroy(); - } - - this._handle.close(); - this._handle = null; - - if (exitCode < 0) { - const syscall = this.spawnfile ? 'spawn ' + this.spawnfile : 'spawn'; - const err = errnoException(exitCode, syscall); - - if (this.spawnfile) - err.path = this.spawnfile; - - err.spawnargs = this.spawnargs.slice(1); - this.emit('error', err); - } else { - this.emit('exit', this.exitCode, this.signalCode); - } - - // If any of the stdio streams have not been touched, - // then pull all the data through so that it can get the - // eof and emit a 'close' event. - // Do it on nextTick so that the user has one last chance - // to consume the output, if for example they only want to - // start reading the data once the process exits. - process.nextTick(flushStdio, this); - - maybeClose(this); - }; -} -ObjectSetPrototypeOf(ChildProcess.prototype, EventEmitter.prototype); -ObjectSetPrototypeOf(ChildProcess, EventEmitter); - - -function flushStdio(subprocess) { - const stdio = subprocess.stdio; - - if (stdio == null) return; - - for (let i = 0; i < stdio.length; i++) { - const stream = stdio[i]; - // TODO(addaleax): This doesn't necessarily account for all the ways in - // which data can be read from a stream, e.g. being consumed on the - // native layer directly as a StreamBase. - if (!stream || !stream.readable || stream[kIsUsedAsStdio]) { - continue; - } - stream.resume(); - } -} - - -function createSocket(pipe, readable) { - return net.Socket({ handle: pipe, readable, writable: !readable }); -} - - -function getHandleWrapType(stream) { - if (stream instanceof Pipe) return 'pipe'; - if (stream instanceof TTY) return 'tty'; - if (stream instanceof TCP) return 'tcp'; - if (stream instanceof UDP) return 'udp'; - - return false; -} - -function closePendingHandle(target) { - target._pendingMessage.handle.close(); - target._pendingMessage = null; -} - - -ChildProcess.prototype.spawn = function(options) { - let i = 0; - - if (options === null || typeof options !== 'object') { - throw new ERR_INVALID_ARG_TYPE('options', 'Object', options); - } - - // If no `stdio` option was given - use default - let stdio = options.stdio || 'pipe'; - - stdio = getValidStdio(stdio, false); - - const ipc = stdio.ipc; - const ipcFd = stdio.ipcFd; - stdio = options.stdio = stdio.stdio; - - - validateOneOf(options.serialization, 'options.serialization', - [undefined, 'json', 'advanced'], true); - const serialization = options.serialization || 'json'; - - if (ipc !== undefined) { - // Let child process know about opened IPC channel - if (options.envPairs === undefined) - options.envPairs = []; - else if (!ArrayIsArray(options.envPairs)) { - throw new ERR_INVALID_ARG_TYPE('options.envPairs', - 'Array', - options.envPairs); - } - - options.envPairs.push(`NODE_CHANNEL_FD=${ipcFd}`); - options.envPairs.push(`NODE_CHANNEL_SERIALIZATION_MODE=${serialization}`); - } - - validateString(options.file, 'options.file'); - this.spawnfile = options.file; - - if (ArrayIsArray(options.args)) - this.spawnargs = options.args; - else if (options.args === undefined) - this.spawnargs = []; - else - throw new ERR_INVALID_ARG_TYPE('options.args', 'Array', options.args); - - const err = this._handle.spawn(options); - - // Run-time errors should emit an error, not throw an exception. - if (err === UV_EACCES || - err === UV_EAGAIN || - err === UV_EMFILE || - err === UV_ENFILE || - err === UV_ENOENT) { - process.nextTick(onErrorNT, this, err); - - // There is no point in continuing when we've hit EMFILE or ENFILE - // because we won't be able to set up the stdio file descriptors. - if (err === UV_EMFILE || err === UV_ENFILE) - return err; - } else if (err) { - // Close all opened fds on error - for (i = 0; i < stdio.length; i++) { - const stream = stdio[i]; - if (stream.type === 'pipe') { - stream.handle.close(); - } - } - - this._handle.close(); - this._handle = null; - throw errnoException(err, 'spawn'); - } - - this.pid = this._handle.pid; - - for (i = 0; i < stdio.length; i++) { - const stream = stdio[i]; - if (stream.type === 'ignore') continue; - - if (stream.ipc) { - this._closesNeeded++; - continue; - } - - // The stream is already cloned and piped, thus stop its readable side, - // otherwise we might attempt to read from the stream when at the same time - // the child process does. - if (stream.type === 'wrap') { - stream.handle.reading = false; - stream.handle.readStop(); - stream._stdio.pause(); - stream._stdio.readableFlowing = false; - stream._stdio._readableState.reading = false; - stream._stdio[kIsUsedAsStdio] = true; - continue; - } - - if (stream.handle) { - // When i === 0 - we're dealing with stdin - // (which is the only one writable pipe). - stream.socket = createSocket(this.pid !== 0 ? - stream.handle : null, i > 0); - - if (i > 0 && this.pid !== 0) { - this._closesNeeded++; - stream.socket.on('close', () => { - maybeClose(this); - }); - } - } - } - - this.stdin = stdio.length >= 1 && stdio[0].socket !== undefined ? - stdio[0].socket : null; - this.stdout = stdio.length >= 2 && stdio[1].socket !== undefined ? - stdio[1].socket : null; - this.stderr = stdio.length >= 3 && stdio[2].socket !== undefined ? - stdio[2].socket : null; - - this.stdio = []; - - for (i = 0; i < stdio.length; i++) - this.stdio.push(stdio[i].socket === undefined ? null : stdio[i].socket); - - // Add .send() method and start listening for IPC data - if (ipc !== undefined) setupChannel(this, ipc, serialization); - - return err; -}; - - -function onErrorNT(self, err) { - self._handle.onexit(err); -} - - -ChildProcess.prototype.kill = function(sig) { - - const signal = sig === 0 ? sig : - convertToValidSignal(sig === undefined ? 'SIGTERM' : sig); - - if (this._handle) { - const err = this._handle.kill(signal); - if (err === 0) { - /* Success. */ - this.killed = true; - return true; - } - if (err === UV_ESRCH) { - /* Already dead. */ - } else if (err === UV_EINVAL || err === UV_ENOSYS) { - /* The underlying platform doesn't support this signal. */ - throw errnoException(err, 'kill'); - } else { - /* Other error, almost certainly EPERM. */ - this.emit('error', errnoException(err, 'kill')); - } - } - - /* Kill didn't succeed. */ - return false; -}; - - -ChildProcess.prototype.ref = function() { - if (this._handle) this._handle.ref(); -}; - - -ChildProcess.prototype.unref = function() { - if (this._handle) this._handle.unref(); -}; - -class Control extends EventEmitter { - #channel = null; - #refs = 0; - #refExplicitlySet = false; - - constructor(channel) { - super(); - this.#channel = channel; - } - - // The methods keeping track of the counter are being used to track the - // listener count on the child process object as well as when writes are - // in progress. Once the user has explicitly requested a certain state, these - // methods become no-ops in order to not interfere with the user's intentions. - refCounted() { - if (++this.#refs === 1 && !this.#refExplicitlySet) { - this.#channel.ref(); - } - } - - unrefCounted() { - if (--this.#refs === 0 && !this.#refExplicitlySet) { - this.#channel.unref(); - this.emit('unref'); - } - } - - ref() { - this.#refExplicitlySet = true; - this.#channel.ref(); - } - - unref() { - this.#refExplicitlySet = true; - this.#channel.unref(); - } - - get fd() { - return this.#channel ? this.#channel.fd : undefined; - } -} - -const channelDeprecationMsg = '_channel is deprecated. ' + - 'Use ChildProcess.channel instead.'; - -let serialization; -function setupChannel(target, channel, serializationMode) { - const control = new Control(channel); - target.channel = control; - target[kChannelHandle] = channel; - - ObjectDefineProperty(target, '_channel', { - get: deprecate(() => { - return target.channel; - }, channelDeprecationMsg, 'DEP0129'), - set: deprecate((val) => { - target.channel = val; - }, channelDeprecationMsg, 'DEP0129'), - configurable: true, - enumerable: false - }); - - target._handleQueue = null; - target._pendingMessage = null; - - if (serialization === undefined) - serialization = require('internal/child_process/serialization'); - const { - initMessageChannel, - parseChannelMessages, - writeChannelMessage - } = serialization[serializationMode]; - - let pendingHandle = null; - initMessageChannel(channel); - channel.pendingHandle = null; - channel.onread = function(arrayBuffer) { - const recvHandle = channel.pendingHandle; - channel.pendingHandle = null; - if (arrayBuffer) { - const nread = streamBaseState[kReadBytesOrError]; - const offset = streamBaseState[kArrayBufferOffset]; - const pool = new Uint8Array(arrayBuffer, offset, nread); - if (recvHandle) - pendingHandle = recvHandle; - - for (const message of parseChannelMessages(channel, pool)) { - // There will be at most one NODE_HANDLE message in every chunk we - // read because SCM_RIGHTS messages don't get coalesced. Make sure - // that we deliver the handle with the right message however. - if (isInternal(message)) { - if (message.cmd === 'NODE_HANDLE') { - handleMessage(message, pendingHandle, true); - pendingHandle = null; - } else { - handleMessage(message, undefined, true); - } - } else { - handleMessage(message, undefined, false); - } - } - } else { - this.buffering = false; - target.disconnect(); - channel.onread = nop; - channel.close(); - target.channel = null; - maybeClose(target); - } - }; - - // Object where socket lists will live - channel.sockets = { got: {}, send: {} }; - - // Handlers will go through this - target.on('internalMessage', function(message, handle) { - // Once acknowledged - continue sending handles. - if (message.cmd === 'NODE_HANDLE_ACK' || - message.cmd === 'NODE_HANDLE_NACK') { - - if (target._pendingMessage) { - if (message.cmd === 'NODE_HANDLE_ACK') { - closePendingHandle(target); - } else if (target._pendingMessage.retransmissions++ === - MAX_HANDLE_RETRANSMISSIONS) { - closePendingHandle(target); - process.emitWarning('Handle did not reach the receiving process ' + - 'correctly', 'SentHandleNotReceivedWarning'); - } - } - - assert(ArrayIsArray(target._handleQueue)); - const queue = target._handleQueue; - target._handleQueue = null; - - if (target._pendingMessage) { - target._send(target._pendingMessage.message, - target._pendingMessage.handle, - target._pendingMessage.options, - target._pendingMessage.callback); - } - - for (let i = 0; i < queue.length; i++) { - const args = queue[i]; - target._send(args.message, args.handle, args.options, args.callback); - } - - // Process a pending disconnect (if any). - if (!target.connected && target.channel && !target._handleQueue) - target._disconnect(); - - return; - } - - if (message.cmd !== 'NODE_HANDLE') return; - - // It is possible that the handle is not received because of some error on - // ancillary data reception such as MSG_CTRUNC. In this case, report the - // sender about it by sending a NODE_HANDLE_NACK message. - if (!handle) - return target._send({ cmd: 'NODE_HANDLE_NACK' }, null, true); - - // Acknowledge handle receival. Don't emit error events (for example if - // the other side has disconnected) because this call to send() is not - // initiated by the user and it shouldn't be fatal to be unable to ACK - // a message. - target._send({ cmd: 'NODE_HANDLE_ACK' }, null, true); - - const obj = handleConversion[message.type]; - - // Update simultaneous accepts on Windows - if (process.platform === 'win32') { - handle.setSimultaneousAccepts(false); - } - - // Convert handle object - obj.got.call(this, message, handle, (handle) => { - handleMessage(message.msg, handle, isInternal(message.msg)); - }); - }); - - target.send = function(message, handle, options, callback) { - if (typeof handle === 'function') { - callback = handle; - handle = undefined; - options = undefined; - } else if (typeof options === 'function') { - callback = options; - options = undefined; - } else if (options !== undefined && - (options === null || typeof options !== 'object')) { - throw new ERR_INVALID_ARG_TYPE('options', 'Object', options); - } - - options = { swallowErrors: false, ...options }; - - if (this.connected) { - return this._send(message, handle, options, callback); - } - const ex = new ERR_IPC_CHANNEL_CLOSED(); - if (typeof callback === 'function') { - process.nextTick(callback, ex); - } else { - process.nextTick(() => this.emit('error', ex)); - } - return false; - }; - - target._send = function(message, handle, options, callback) { - assert(this.connected || this.channel); - - if (message === undefined) - throw new ERR_MISSING_ARGS('message'); - - // Non-serializable messages should not reach the remote - // end point; as any failure in the stringification there - // will result in error message that is weakly consumable. - // So perform a sanity check on message prior to sending. - if (typeof message !== 'string' && - typeof message !== 'object' && - typeof message !== 'number' && - typeof message !== 'boolean') { - throw new ERR_INVALID_ARG_TYPE( - 'message', ['string', 'object', 'number', 'boolean'], message); - } - - // Support legacy function signature - if (typeof options === 'boolean') { - options = { swallowErrors: options }; - } - - let obj; - - // Package messages with a handle object - if (handle) { - // This message will be handled by an internalMessage event handler - message = { - cmd: 'NODE_HANDLE', - type: null, - msg: message - }; - - if (handle instanceof net.Socket) { - message.type = 'net.Socket'; - } else if (handle instanceof net.Server) { - message.type = 'net.Server'; - } else if (handle instanceof TCP || handle instanceof Pipe) { - message.type = 'net.Native'; - } else if (handle instanceof dgram.Socket) { - message.type = 'dgram.Socket'; - } else if (handle instanceof UDP) { - message.type = 'dgram.Native'; - } else { - throw new ERR_INVALID_HANDLE_TYPE(); - } - - // Queue-up message and handle if we haven't received ACK yet. - if (this._handleQueue) { - this._handleQueue.push({ - callback: callback, - handle: handle, - options: options, - message: message.msg, - }); - return this._handleQueue.length === 1; - } - - obj = handleConversion[message.type]; - - // convert TCP object to native handle object - handle = handleConversion[message.type].send.call(target, - message, - handle, - options); - - // If handle was sent twice, or it is impossible to get native handle - // out of it - just send a text without the handle. - if (!handle) - message = message.msg; - - // Update simultaneous accepts on Windows - if (obj.simultaneousAccepts && process.platform === 'win32') { - handle.setSimultaneousAccepts(true); - } - } else if (this._handleQueue && - !(message && (message.cmd === 'NODE_HANDLE_ACK' || - message.cmd === 'NODE_HANDLE_NACK'))) { - // Queue request anyway to avoid out-of-order messages. - this._handleQueue.push({ - callback: callback, - handle: null, - options: options, - message: message, - }); - return this._handleQueue.length === 1; - } - - const req = new WriteWrap(); - - const err = writeChannelMessage(channel, req, message, handle); - const wasAsyncWrite = streamBaseState[kLastWriteWasAsync]; - - if (err === 0) { - if (handle) { - if (!this._handleQueue) - this._handleQueue = []; - if (obj && obj.postSend) - obj.postSend(message, handle, options, callback, target); - } - - if (wasAsyncWrite) { - req.oncomplete = () => { - control.unrefCounted(); - if (typeof callback === 'function') - callback(null); - }; - control.refCounted(); - } else if (typeof callback === 'function') { - process.nextTick(callback, null); - } - } else { - // Cleanup handle on error - if (obj && obj.postSend) - obj.postSend(message, handle, options, callback); - - if (!options.swallowErrors) { - const ex = errnoException(err, 'write'); - if (typeof callback === 'function') { - process.nextTick(callback, ex); - } else { - process.nextTick(() => this.emit('error', ex)); - } - } - } - - /* If the master is > 2 read() calls behind, please stop sending. */ - return channel.writeQueueSize < (65536 * 2); - }; - - // Connected will be set to false immediately when a disconnect() is - // requested, even though the channel might still be alive internally to - // process queued messages. The three states are distinguished as follows: - // - disconnect() never requested: channel is not null and connected - // is true - // - disconnect() requested, messages in the queue: channel is not null - // and connected is false - // - disconnect() requested, channel actually disconnected: channel is - // null and connected is false - target.connected = true; - - target.disconnect = function() { - if (!this.connected) { - this.emit('error', new ERR_IPC_DISCONNECTED()); - return; - } - - // Do not allow any new messages to be written. - this.connected = false; - - // If there are no queued messages, disconnect immediately. Otherwise, - // postpone the disconnect so that it happens internally after the - // queue is flushed. - if (!this._handleQueue) - this._disconnect(); - }; - - target._disconnect = function() { - assert(this.channel); - - // This marks the fact that the channel is actually disconnected. - this.channel = null; - this[kChannelHandle] = null; - - if (this._pendingMessage) - closePendingHandle(this); - - let fired = false; - function finish() { - if (fired) return; - fired = true; - - channel.close(); - target.emit('disconnect'); - } - - // If a message is being read, then wait for it to complete. - if (channel.buffering) { - this.once('message', finish); - this.once('internalMessage', finish); - - return; - } - - process.nextTick(finish); - }; - - function emit(event, message, handle) { - target.emit(event, message, handle); - } - - function handleMessage(message, handle, internal) { - if (!target.channel) - return; - - const eventName = (internal ? 'internalMessage' : 'message'); - - process.nextTick(emit, eventName, message, handle); - } - - channel.readStart(); - return control; -} - -const INTERNAL_PREFIX = 'NODE_'; -function isInternal(message) { - return (message !== null && - typeof message === 'object' && - typeof message.cmd === 'string' && - message.cmd.length > INTERNAL_PREFIX.length && - message.cmd.slice(0, INTERNAL_PREFIX.length) === INTERNAL_PREFIX); -} - -function nop() { } - -function getValidStdio(stdio, sync) { - let ipc; - let ipcFd; - - // Replace shortcut with an array - if (typeof stdio === 'string') { - stdio = stdioStringToArray(stdio); - } else if (!ArrayIsArray(stdio)) { - throw new ERR_INVALID_OPT_VALUE('stdio', stdio); - } - - // At least 3 stdio will be created - // Don't concat() a new Array() because it would be sparse, and - // stdio.reduce() would skip the sparse elements of stdio. - // See https://stackoverflow.com/a/5501711/3561 - while (stdio.length < 3) stdio.push(undefined); - - // Translate stdio into C++-readable form - // (i.e. PipeWraps or fds) - stdio = stdio.reduce((acc, stdio, i) => { - function cleanup() { - for (let i = 0; i < acc.length; i++) { - if ((acc[i].type === 'pipe' || acc[i].type === 'ipc') && acc[i].handle) - acc[i].handle.close(); - } - } - - // Defaults - if (stdio == null) { - stdio = i < 3 ? 'pipe' : 'ignore'; - } - - if (stdio === 'ignore') { - acc.push({ type: 'ignore' }); - } else if (stdio === 'pipe' || (typeof stdio === 'number' && stdio < 0)) { - const a = { - type: 'pipe', - readable: i === 0, - writable: i !== 0 - }; - - if (!sync) - a.handle = new Pipe(PipeConstants.SOCKET); - - acc.push(a); - } else if (stdio === 'ipc') { - if (sync || ipc !== undefined) { - // Cleanup previously created pipes - cleanup(); - if (!sync) - throw new ERR_IPC_ONE_PIPE(); - else - throw new ERR_IPC_SYNC_FORK(); - } - - ipc = new Pipe(PipeConstants.IPC); - ipcFd = i; - - acc.push({ - type: 'pipe', - handle: ipc, - ipc: true - }); - } else if (stdio === 'inherit') { - acc.push({ - type: 'inherit', - fd: i - }); - } else if (typeof stdio === 'number' || typeof stdio.fd === 'number') { - acc.push({ - type: 'fd', - fd: typeof stdio === 'number' ? stdio : stdio.fd - }); - } else if (getHandleWrapType(stdio) || getHandleWrapType(stdio.handle) || - getHandleWrapType(stdio._handle)) { - const handle = getHandleWrapType(stdio) ? - stdio : - getHandleWrapType(stdio.handle) ? stdio.handle : stdio._handle; - - acc.push({ - type: 'wrap', - wrapType: getHandleWrapType(handle), - handle: handle, - _stdio: stdio - }); - } else if (isArrayBufferView(stdio) || typeof stdio === 'string') { - if (!sync) { - cleanup(); - throw new ERR_INVALID_SYNC_FORK_INPUT(inspect(stdio)); - } - } else { - // Cleanup - cleanup(); - throw new ERR_INVALID_OPT_VALUE('stdio', stdio); - } - - return acc; - }, []); - - return { stdio, ipc, ipcFd }; -} - - -function getSocketList(type, worker, key) { - const sockets = worker[kChannelHandle].sockets[type]; - let socketList = sockets[key]; - if (!socketList) { - const Construct = type === 'send' ? SocketListSend : SocketListReceive; - socketList = sockets[key] = new Construct(worker, key); - } - return socketList; -} - - -function maybeClose(subprocess) { - subprocess._closesGot++; - - if (subprocess._closesGot === subprocess._closesNeeded) { - subprocess.emit('close', subprocess.exitCode, subprocess.signalCode); - } -} - -function spawnSync(options) { - const result = spawn_sync.spawn(options); - - if (result.output && options.encoding && options.encoding !== 'buffer') { - for (let i = 0; i < result.output.length; i++) { - if (!result.output[i]) - continue; - result.output[i] = result.output[i].toString(options.encoding); - } - } - - result.stdout = result.output && result.output[1]; - result.stderr = result.output && result.output[2]; - - if (result.error) { - result.error = errnoException(result.error, 'spawnSync ' + options.file); - result.error.path = options.file; - result.error.spawnargs = options.args.slice(1); - } - - return result; -} - -module.exports = { - ChildProcess, - kChannelHandle, - setupChannel, - getValidStdio, - stdioStringToArray, - spawnSync -}; diff --git a/lib/internal/histogram.js b/lib/internal/histogram.js index e0022be..6deb831 100644 --- a/lib/internal/histogram.js +++ b/lib/internal/histogram.js @@ -19,17 +19,11 @@ const kHandle = Symbol('kHandle'); // record various metrics. This Histogram class provides a // generally read-only view of the internal histogram. class Histogram { - // @lwnode - // #handle = undefined; - // #map = new Map(); - __handle = undefined; - __map = new Map(); - // end @lwnode + #handle = undefined; + #map = new Map(); constructor(internal) { - // @lwnode - // this.#handle = internal; - this.__handle = internal; + this.#handle = internal; } [kInspect]() { @@ -45,33 +39,23 @@ class Histogram { } get min() { - // @lwnode - // return this.#handle ? this.#handle.min() : undefined; - return this.__handle ? this.__handle.min() : undefined; + return this.#handle ? this.#handle.min() : undefined; } get max() { - // @lwnode - // return this.#handle ? this.#handle.max() : undefined; - return this.__handle ? this.__handle.max() : undefined; + return this.#handle ? this.#handle.max() : undefined; } get mean() { - // @lwnode - // return this.#handle ? this.#handle.mean() : undefined; - return this.__handle ? this.__handle.mean() : undefined; + return this.#handle ? this.#handle.mean() : undefined; } get exceeds() { - // @lwnode - // return this.#handle ? this.#handle.exceeds() : undefined; - return this.__handle ? this.__handle.exceeds() : undefined; + return this.#handle ? this.#handle.exceeds() : undefined; } get stddev() { - // @lwnode - // return this.#handle ? this.#handle.stddev() : undefined; - return this.__handle ? this.__handle.stddev() : undefined; + return this.#handle ? this.#handle.stddev() : undefined; } percentile(percentile) { @@ -81,42 +65,26 @@ class Histogram { if (percentile <= 0 || percentile > 100) throw new ERR_INVALID_ARG_VALUE.RangeError('percentile', percentile); - // @lwnode - // return this.#handle ? this.#handle.percentile(percentile) : undefined; - return this.__handle ? this.__handle.percentile(percentile) : undefined; + return this.#handle ? this.#handle.percentile(percentile) : undefined; } get percentiles() { - // @lwnode - // this.#map.clear(); - // if (this.#handle) - // this.#handle.percentiles(this.#map); - // return this.#map; - this.__map.clear(); - if (this.__handle) - this.__handle.percentiles(this.__map); - return this.__map; - // end @lwnode + this.#map.clear(); + if (this.#handle) + this.#handle.percentiles(this.#map); + return this.#map; } reset() { - // @lwnode - // if (this.#handle) - // this.#handle.reset(); - if (this.__handle) - this.__handle.reset(); - // end @lwnode + if (this.#handle) + this.#handle.reset(); } [kDestroy]() { - // @lwnode - // this.#handle = undefined; - this.__handle = undefined; + this.#handle = undefined; } - // @lwnode - //get [kHandle]() { return this.#handle; } - get [kHandle]() { return this.__handle; } + get [kHandle]() { return this.#handle; } } module.exports = { diff --git a/lib/internal/histogram_origin.js b/lib/internal/histogram_origin.js deleted file mode 100644 index 6deb831..0000000 --- a/lib/internal/histogram_origin.js +++ /dev/null @@ -1,94 +0,0 @@ -'use strict'; - -const { - customInspectSymbol: kInspect, -} = require('internal/util'); - -const { format } = require('util'); -const { Map, Symbol } = primordials; - -const { - ERR_INVALID_ARG_TYPE, - ERR_INVALID_ARG_VALUE, -} = require('internal/errors').codes; - -const kDestroy = Symbol('kDestroy'); -const kHandle = Symbol('kHandle'); - -// Histograms are created internally by Node.js and used to -// record various metrics. This Histogram class provides a -// generally read-only view of the internal histogram. -class Histogram { - #handle = undefined; - #map = new Map(); - - constructor(internal) { - this.#handle = internal; - } - - [kInspect]() { - const obj = { - min: this.min, - max: this.max, - mean: this.mean, - exceeds: this.exceeds, - stddev: this.stddev, - percentiles: this.percentiles, - }; - return `Histogram ${format(obj)}`; - } - - get min() { - return this.#handle ? this.#handle.min() : undefined; - } - - get max() { - return this.#handle ? this.#handle.max() : undefined; - } - - get mean() { - return this.#handle ? this.#handle.mean() : undefined; - } - - get exceeds() { - return this.#handle ? this.#handle.exceeds() : undefined; - } - - get stddev() { - return this.#handle ? this.#handle.stddev() : undefined; - } - - percentile(percentile) { - if (typeof percentile !== 'number') - throw new ERR_INVALID_ARG_TYPE('percentile', 'number', percentile); - - if (percentile <= 0 || percentile > 100) - throw new ERR_INVALID_ARG_VALUE.RangeError('percentile', percentile); - - return this.#handle ? this.#handle.percentile(percentile) : undefined; - } - - get percentiles() { - this.#map.clear(); - if (this.#handle) - this.#handle.percentiles(this.#map); - return this.#map; - } - - reset() { - if (this.#handle) - this.#handle.reset(); - } - - [kDestroy]() { - this.#handle = undefined; - } - - get [kHandle]() { return this.#handle; } -} - -module.exports = { - Histogram, - kDestroy, - kHandle, -}; diff --git a/lib/internal/process/per_thread.js b/lib/internal/process/per_thread.js index b8f03ff..c4f1e2c 100644 --- a/lib/internal/process/per_thread.js +++ b/lib/internal/process/per_thread.js @@ -225,8 +225,47 @@ function wrapProcessMethods(binding) { }; } + // @lwnode + const lwnode = { + _print: (...args) => { + if (binding.print) { + binding.print.apply(null, args); + } + }, + _ptr: (...args) => { + if (binding.print) { + binding.print.ptr.apply(null, args); + } + }, + _stack: (...args) => { + if (binding.print) { + binding.print.stack.apply(null, args); + } + }, + PssUsage: (...args) => { + if (binding.PssUsage) { + return binding.PssUsage.apply(null, args); + } + }, + PssSwapUsage: (...args) => { + if (binding.PssSwapUsage) { + return binding.PssSwapUsage.apply(null, args); + } + }, + RssUsage: (...args) => { + if (binding.PssUsage) { + return binding.RssUsage.apply(null, args); + } + }, + MemSnapshot: (...args) => { + if (binding.MemSnapshot) { + return binding.MemSnapshot.apply(null, args); + } + }, + }; return { + lwnode, _rawDebug, hrtime, hrtimeBigInt, diff --git a/lib/internal/source_map/source_map.js b/lib/internal/source_map/source_map.js index e04f0a5..7d21e02 100644 --- a/lib/internal/source_map/source_map.js +++ b/lib/internal/source_map/source_map.js @@ -121,11 +121,10 @@ class StringCharIterator { * @param {SourceMapV3} payload */ class SourceMap { - // @lwnode - // #payload; - // #mappings = []; - // #sources = {}; - // #sourceContentByURL = {}; + #payload; + #mappings = []; + #sources = {}; + #sourceContentByURL = {}; /** * @constructor @@ -139,42 +138,36 @@ class SourceMap { for (let i = 0; i < base64Digits.length; ++i) base64Map[base64Digits[i]] = i; } - - this.payload = undefined; - this.mappings = []; - this.sources = {}; - - this.sourceContentByURL = {}; - this.payload = cloneSourceMapV3(payload); - this.parseMappingPayload(); + this.#payload = cloneSourceMapV3(payload); + this.#parseMappingPayload(); } /** * @return {Object} raw source map v3 payload. */ get payload() { - return cloneSourceMapV3(this.payload); + return cloneSourceMapV3(this.#payload); } /** * @param {SourceMapV3} mappingPayload */ - parseMappingPayload() { - if (this.payload.sections) { - this.parseSections(this.payload.sections); + #parseMappingPayload = () => { + if (this.#payload.sections) { + this.#parseSections(this.#payload.sections); } else { - this.parseMap(this.payload, 0, 0); + this.#parseMap(this.#payload, 0, 0); } - this.mappings.sort(compareSourceMapEntry); + this.#mappings.sort(compareSourceMapEntry); } /** * @param {Array.} sections */ - parseSections(sections) { + #parseSections = (sections) => { for (let i = 0; i < sections.length; ++i) { const section = sections[i]; - this.parseMap(section.map, section.offset.line, section.offset.column); + this.#parseMap(section.map, section.offset.line, section.offset.column); } } @@ -185,11 +178,11 @@ class SourceMap { */ findEntry(lineNumber, columnNumber) { let first = 0; - let count = this.mappings.length; + let count = this.#mappings.length; while (count > 1) { const step = count >> 1; const middle = first + step; - const mapping = this.mappings[middle]; + const mapping = this.#mappings[middle]; if (lineNumber < mapping[0] || (lineNumber === mapping[0] && columnNumber < mapping[1])) { count = step; @@ -198,7 +191,7 @@ class SourceMap { count -= step; } } - const entry = this.mappings[first]; + const entry = this.#mappings[first]; if (!first && entry && (lineNumber < entry[0] || (lineNumber === entry[0] && columnNumber < entry[1]))) { return {}; @@ -217,7 +210,7 @@ class SourceMap { /** * @override */ - parseMap(map, lineNumber, columnNumber) { + #parseMap = (map, lineNumber, columnNumber) => { let sourceIndex = 0; let sourceLineNumber = 0; let sourceColumnNumber = 0; @@ -228,10 +221,10 @@ class SourceMap { const url = map.sources[i]; originalToCanonicalURLMap[url] = url; sources.push(url); - this.sources[url] = true; + this.#sources[url] = true; if (map.sourcesContent && map.sourcesContent[i]) - this.sourceContentByURL[url] = map.sourcesContent[i]; + this.#sourceContentByURL[url] = map.sourcesContent[i]; } const stringCharIterator = new StringCharIterator(map.mappings); @@ -252,7 +245,7 @@ class SourceMap { columnNumber += decodeVLQ(stringCharIterator); if (isSeparator(stringCharIterator.peek())) { - this.mappings.push([lineNumber, columnNumber]); + this.#mappings.push([lineNumber, columnNumber]); continue; } @@ -267,7 +260,7 @@ class SourceMap { // Unused index into the names list. decodeVLQ(stringCharIterator); - this.mappings.push([lineNumber, columnNumber, sourceURL, + this.#mappings.push([lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber]); } }; diff --git a/lib/internal/source_map/source_map.origin.js b/lib/internal/source_map/source_map.origin.js deleted file mode 100644 index 7d21e02..0000000 --- a/lib/internal/source_map/source_map.origin.js +++ /dev/null @@ -1,343 +0,0 @@ -// This file is a modified version of: -// https://cs.chromium.org/chromium/src/v8/tools/SourceMap.js?rcl=dd10454c1d -// from the V8 codebase. Logic specific to WebInspector is removed and linting -// is made to match the Node.js style guide. - -// Copyright 2013 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This is a copy from blink dev tools, see: -// http://src.chromium.org/viewvc/blink/trunk/Source/devtools/front_end/SourceMap.js -// revision: 153407 - -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -'use strict'; - -const { - ArrayIsArray -} = primordials; - -const { - ERR_INVALID_ARG_TYPE -} = require('internal/errors').codes; - -let base64Map; - -const VLQ_BASE_SHIFT = 5; -const VLQ_BASE_MASK = (1 << 5) - 1; -const VLQ_CONTINUATION_MASK = 1 << 5; - -class StringCharIterator { - /** - * @constructor - * @param {string} string - */ - constructor(string) { - this._string = string; - this._position = 0; - } - - /** - * @return {string} - */ - next() { - return this._string.charAt(this._position++); - } - - /** - * @return {string} - */ - peek() { - return this._string.charAt(this._position); - } - - /** - * @return {boolean} - */ - hasNext() { - return this._position < this._string.length; - } -} - -/** - * Implements Source Map V3 model. - * See https://github.com/google/closure-compiler/wiki/Source-Maps - * for format description. - * @constructor - * @param {string} sourceMappingURL - * @param {SourceMapV3} payload - */ -class SourceMap { - #payload; - #mappings = []; - #sources = {}; - #sourceContentByURL = {}; - - /** - * @constructor - * @param {SourceMapV3} payload - */ - constructor(payload) { - if (!base64Map) { - const base64Digits = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - base64Map = {}; - for (let i = 0; i < base64Digits.length; ++i) - base64Map[base64Digits[i]] = i; - } - this.#payload = cloneSourceMapV3(payload); - this.#parseMappingPayload(); - } - - /** - * @return {Object} raw source map v3 payload. - */ - get payload() { - return cloneSourceMapV3(this.#payload); - } - - /** - * @param {SourceMapV3} mappingPayload - */ - #parseMappingPayload = () => { - if (this.#payload.sections) { - this.#parseSections(this.#payload.sections); - } else { - this.#parseMap(this.#payload, 0, 0); - } - this.#mappings.sort(compareSourceMapEntry); - } - - /** - * @param {Array.} sections - */ - #parseSections = (sections) => { - for (let i = 0; i < sections.length; ++i) { - const section = sections[i]; - this.#parseMap(section.map, section.offset.line, section.offset.column); - } - } - - /** - * @param {number} lineNumber in compiled resource - * @param {number} columnNumber in compiled resource - * @return {?Array} - */ - findEntry(lineNumber, columnNumber) { - let first = 0; - let count = this.#mappings.length; - while (count > 1) { - const step = count >> 1; - const middle = first + step; - const mapping = this.#mappings[middle]; - if (lineNumber < mapping[0] || - (lineNumber === mapping[0] && columnNumber < mapping[1])) { - count = step; - } else { - first = middle; - count -= step; - } - } - const entry = this.#mappings[first]; - if (!first && entry && (lineNumber < entry[0] || - (lineNumber === entry[0] && columnNumber < entry[1]))) { - return {}; - } else if (!entry) { - return {}; - } - return { - generatedLine: entry[0], - generatedColumn: entry[1], - originalSource: entry[2], - originalLine: entry[3], - originalColumn: entry[4] - }; - } - - /** - * @override - */ - #parseMap = (map, lineNumber, columnNumber) => { - let sourceIndex = 0; - let sourceLineNumber = 0; - let sourceColumnNumber = 0; - - const sources = []; - const originalToCanonicalURLMap = {}; - for (let i = 0; i < map.sources.length; ++i) { - const url = map.sources[i]; - originalToCanonicalURLMap[url] = url; - sources.push(url); - this.#sources[url] = true; - - if (map.sourcesContent && map.sourcesContent[i]) - this.#sourceContentByURL[url] = map.sourcesContent[i]; - } - - const stringCharIterator = new StringCharIterator(map.mappings); - let sourceURL = sources[sourceIndex]; - - while (true) { - if (stringCharIterator.peek() === ',') - stringCharIterator.next(); - else { - while (stringCharIterator.peek() === ';') { - lineNumber += 1; - columnNumber = 0; - stringCharIterator.next(); - } - if (!stringCharIterator.hasNext()) - break; - } - - columnNumber += decodeVLQ(stringCharIterator); - if (isSeparator(stringCharIterator.peek())) { - this.#mappings.push([lineNumber, columnNumber]); - continue; - } - - const sourceIndexDelta = decodeVLQ(stringCharIterator); - if (sourceIndexDelta) { - sourceIndex += sourceIndexDelta; - sourceURL = sources[sourceIndex]; - } - sourceLineNumber += decodeVLQ(stringCharIterator); - sourceColumnNumber += decodeVLQ(stringCharIterator); - if (!isSeparator(stringCharIterator.peek())) - // Unused index into the names list. - decodeVLQ(stringCharIterator); - - this.#mappings.push([lineNumber, columnNumber, sourceURL, - sourceLineNumber, sourceColumnNumber]); - } - }; -} - -/** - * @param {string} char - * @return {boolean} - */ -function isSeparator(char) { - return char === ',' || char === ';'; -} - -/** - * @param {SourceMap.StringCharIterator} stringCharIterator - * @return {number} - */ -function decodeVLQ(stringCharIterator) { - // Read unsigned value. - let result = 0; - let shift = 0; - let digit; - do { - digit = base64Map[stringCharIterator.next()]; - result += (digit & VLQ_BASE_MASK) << shift; - shift += VLQ_BASE_SHIFT; - } while (digit & VLQ_CONTINUATION_MASK); - - // Fix the sign. - const negative = result & 1; - // Use unsigned right shift, so that the 32nd bit is properly shifted to the - // 31st, and the 32nd becomes unset. - result >>>= 1; - if (!negative) { - return result; - } - - // We need to OR here to ensure the 32nd bit (the sign bit in an Int32) is - // always set for negative numbers. If `result` were 1, (meaning `negate` is - // true and all other bits were zeros), `result` would now be 0. But -0 - // doesn't flip the 32nd bit as intended. All other numbers will successfully - // set the 32nd bit without issue, so doing this is a noop for them. - return -result | (1 << 31); -} - -/** - * @param {SourceMapV3} payload - * @return {SourceMapV3} - */ -function cloneSourceMapV3(payload) { - if (typeof payload !== 'object') { - throw new ERR_INVALID_ARG_TYPE('payload', ['Object'], payload); - } - payload = { ...payload }; - for (const key in payload) { - if (payload.hasOwnProperty(key) && ArrayIsArray(payload[key])) { - payload[key] = payload[key].slice(0); - } - } - return payload; -} - -/** - * @param {Array} entry1 source map entry [lineNumber, columnNumber, sourceURL, - * sourceLineNumber, sourceColumnNumber] - * @param {Array} entry2 source map entry. - * @return {number} - */ -function compareSourceMapEntry(entry1, entry2) { - const [lineNumber1, columnNumber1] = entry1; - const [lineNumber2, columnNumber2] = entry2; - if (lineNumber1 !== lineNumber2) { - return lineNumber1 - lineNumber2; - } - return columnNumber1 - columnNumber2; -} - -module.exports = { - SourceMap -}; diff --git a/lib/internal/vm/module.js b/lib/internal/vm/module.js index cda645f..c10433a 100644 --- a/lib/internal/vm/module.js +++ b/lib/internal/vm/module.js @@ -254,8 +254,8 @@ const kDependencySpecifiers = Symbol('kDependencySpecifiers'); const kNoError = Symbol('kNoError'); class SourceTextModule extends Module { - error = kNoError; // @lwnode (module.origin.js) - statusOverride; // @lwnode (module.origin.js) + #error = kNoError; + #statusOverride; constructor(sourceText, options = {}) { validateString(sourceText, 'sourceText'); @@ -310,7 +310,7 @@ class SourceTextModule extends Module { }); this[kLink] = async (linker) => { - this.statusOverride = 'linking'; + this.#statusOverride = 'linking'; const promises = this[kWrap].link(async (identifier) => { const module = await linker(identifier, this); @@ -334,10 +334,10 @@ class SourceTextModule extends Module { await SafePromise.all(promises); } } catch (e) { - this.error = e; + this.#error = e; throw e; } finally { - this.statusOverride = undefined; + this.#statusOverride = undefined; } }; @@ -358,11 +358,11 @@ class SourceTextModule extends Module { if (this[kWrap] === undefined) { throw new ERR_VM_MODULE_NOT_MODULE(); } - if (this.error !== kNoError) { + if (this.#error !== kNoError) { return 'errored'; } - if (this.statusOverride) { - return this.statusOverride; + if (this.#statusOverride) { + return this.#statusOverride; } return super.status; } @@ -371,8 +371,8 @@ class SourceTextModule extends Module { if (this[kWrap] === undefined) { throw new ERR_VM_MODULE_NOT_MODULE(); } - if (this.error !== kNoError) { - return this.error; + if (this.#error !== kNoError) { + return this.#error; } return super.error; } diff --git a/lib/internal/vm/module.origin.js b/lib/internal/vm/module.origin.js deleted file mode 100644 index c10433a..0000000 --- a/lib/internal/vm/module.origin.js +++ /dev/null @@ -1,465 +0,0 @@ -'use strict'; - -const assert = require('internal/assert'); -const { - ArrayIsArray, - ObjectCreate, - ObjectDefineProperty, - ObjectGetPrototypeOf, - ObjectSetPrototypeOf, - SafePromise, - Symbol, - TypeError, - WeakMap, -} = primordials; - -const { isContext } = internalBinding('contextify'); -const { - isModuleNamespaceObject, - isArrayBufferView, -} = require('internal/util/types'); -const { - getConstructorOf, - customInspectSymbol, - emitExperimentalWarning, -} = require('internal/util'); -const { - ERR_INVALID_ARG_TYPE, - ERR_INVALID_ARG_VALUE, - ERR_VM_MODULE_ALREADY_LINKED, - ERR_VM_MODULE_DIFFERENT_CONTEXT, - ERR_VM_MODULE_CANNOT_CREATE_CACHED_DATA, - ERR_VM_MODULE_LINKING_ERRORED, - ERR_VM_MODULE_NOT_MODULE, - ERR_VM_MODULE_STATUS, -} = require('internal/errors').codes; -const { - validateInt32, - validateUint32, - validateString, -} = require('internal/validators'); - -const binding = internalBinding('module_wrap'); -const { - ModuleWrap, - kUninstantiated, - kInstantiating, - kInstantiated, - kEvaluating, - kEvaluated, - kErrored, -} = binding; - -const STATUS_MAP = { - [kUninstantiated]: 'unlinked', - [kInstantiating]: 'linking', - [kInstantiated]: 'linked', - [kEvaluating]: 'evaluating', - [kEvaluated]: 'evaluated', - [kErrored]: 'errored', -}; - -let globalModuleId = 0; -const defaultModuleName = 'vm:module'; -const wrapToModuleMap = new WeakMap(); - -const kWrap = Symbol('kWrap'); -const kContext = Symbol('kContext'); -const kPerContextModuleId = Symbol('kPerContextModuleId'); -const kLink = Symbol('kLink'); - -class Module { - constructor(options) { - emitExperimentalWarning('VM Modules'); - - if (new.target === Module) { - // eslint-disable-next-line no-restricted-syntax - throw new TypeError('Module is not a constructor'); - } - - const { - context, - sourceText, - syntheticExportNames, - syntheticEvaluationSteps, - } = options; - - if (context !== undefined) { - if (typeof context !== 'object' || context === null) { - throw new ERR_INVALID_ARG_TYPE('options.context', 'Object', context); - } - if (!isContext(context)) { - throw new ERR_INVALID_ARG_TYPE('options.context', 'vm.Context', - context); - } - } - - let { identifier } = options; - if (identifier !== undefined) { - validateString(identifier, 'options.identifier'); - } else if (context === undefined) { - identifier = `${defaultModuleName}(${globalModuleId++})`; - } else if (context[kPerContextModuleId] !== undefined) { - const curId = context[kPerContextModuleId]; - identifier = `${defaultModuleName}(${curId})`; - context[kPerContextModuleId] += 1; - } else { - identifier = `${defaultModuleName}(0)`; - ObjectDefineProperty(context, kPerContextModuleId, { - value: 1, - writable: true, - enumerable: false, - configurable: true, - }); - } - - if (sourceText !== undefined) { - this[kWrap] = new ModuleWrap(identifier, context, sourceText, - options.lineOffset, options.columnOffset, - options.cachedData); - - binding.callbackMap.set(this[kWrap], { - initializeImportMeta: options.initializeImportMeta, - importModuleDynamically: options.importModuleDynamically ? - importModuleDynamicallyWrap(options.importModuleDynamically) : - undefined, - }); - } else { - assert(syntheticEvaluationSteps); - this[kWrap] = new ModuleWrap(identifier, context, - syntheticExportNames, - syntheticEvaluationSteps); - } - - wrapToModuleMap.set(this[kWrap], this); - - this[kContext] = context; - } - - get identifier() { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - return this[kWrap].url; - } - - get context() { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - return this[kContext]; - } - - get namespace() { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - if (this[kWrap].getStatus() < kInstantiated) { - throw new ERR_VM_MODULE_STATUS('must not be unlinked or linking'); - } - return this[kWrap].getNamespace(); - } - - get status() { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - return STATUS_MAP[this[kWrap].getStatus()]; - } - - get error() { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - if (this[kWrap].getStatus() !== kErrored) { - throw new ERR_VM_MODULE_STATUS('must be errored'); - } - return this[kWrap].getError(); - } - - async link(linker) { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - if (typeof linker !== 'function') { - throw new ERR_INVALID_ARG_TYPE('linker', 'function', linker); - } - if (this.status === 'linked') { - throw new ERR_VM_MODULE_ALREADY_LINKED(); - } - if (this.status !== 'unlinked') { - throw new ERR_VM_MODULE_STATUS('must be unlinked'); - } - await this[kLink](linker); - this[kWrap].instantiate(); - } - - async evaluate(options = {}) { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - - if (typeof options !== 'object' || options === null) { - throw new ERR_INVALID_ARG_TYPE('options', 'Object', options); - } - - let timeout = options.timeout; - if (timeout === undefined) { - timeout = -1; - } else { - validateUint32(timeout, 'options.timeout', true); - } - const { breakOnSigint = false } = options; - if (typeof breakOnSigint !== 'boolean') { - throw new ERR_INVALID_ARG_TYPE('options.breakOnSigint', 'boolean', - breakOnSigint); - } - const status = this[kWrap].getStatus(); - if (status !== kInstantiated && - status !== kEvaluated && - status !== kErrored) { - throw new ERR_VM_MODULE_STATUS( - 'must be one of linked, evaluated, or errored' - ); - } - await this[kWrap].evaluate(timeout, breakOnSigint); - } - - [customInspectSymbol](depth, options) { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - if (typeof depth === 'number' && depth < 0) - return this; - - const constructor = getConstructorOf(this) || Module; - const o = ObjectCreate({ constructor }); - o.status = this.status; - o.identifier = this.identifier; - o.context = this.context; - - ObjectSetPrototypeOf(o, ObjectGetPrototypeOf(this)); - ObjectDefineProperty(o, Symbol.toStringTag, { - value: constructor.name, - configurable: true - }); - - // Lazy to avoid circular dependency - const { inspect } = require('internal/util/inspect'); - return inspect(o, { ...options, customInspect: false }); - } -} - -const kDependencySpecifiers = Symbol('kDependencySpecifiers'); -const kNoError = Symbol('kNoError'); - -class SourceTextModule extends Module { - #error = kNoError; - #statusOverride; - - constructor(sourceText, options = {}) { - validateString(sourceText, 'sourceText'); - - if (typeof options !== 'object' || options === null) { - throw new ERR_INVALID_ARG_TYPE('options', 'Object', options); - } - - const { - lineOffset = 0, - columnOffset = 0, - initializeImportMeta, - importModuleDynamically, - context, - identifier, - cachedData, - } = options; - - validateInt32(lineOffset, 'options.lineOffset'); - validateInt32(columnOffset, 'options.columnOffset'); - - if (initializeImportMeta !== undefined && - typeof initializeImportMeta !== 'function') { - throw new ERR_INVALID_ARG_TYPE( - 'options.initializeImportMeta', 'function', initializeImportMeta); - } - - if (importModuleDynamically !== undefined && - typeof importModuleDynamically !== 'function') { - throw new ERR_INVALID_ARG_TYPE( - 'options.importModuleDynamically', 'function', - importModuleDynamically); - } - - if (cachedData !== undefined && !isArrayBufferView(cachedData)) { - throw new ERR_INVALID_ARG_TYPE( - 'options.cachedData', - ['Buffer', 'TypedArray', 'DataView'], - cachedData - ); - } - - super({ - sourceText, - context, - identifier, - lineOffset, - columnOffset, - cachedData, - initializeImportMeta, - importModuleDynamically, - }); - - this[kLink] = async (linker) => { - this.#statusOverride = 'linking'; - - const promises = this[kWrap].link(async (identifier) => { - const module = await linker(identifier, this); - if (module[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - if (module.context !== this.context) { - throw new ERR_VM_MODULE_DIFFERENT_CONTEXT(); - } - if (module.status === 'errored') { - throw new ERR_VM_MODULE_LINKING_ERRORED(); - } - if (module.status === 'unlinked') { - await module[kLink](linker); - } - return module[kWrap]; - }); - - try { - if (promises !== undefined) { - await SafePromise.all(promises); - } - } catch (e) { - this.#error = e; - throw e; - } finally { - this.#statusOverride = undefined; - } - }; - - this[kDependencySpecifiers] = undefined; - } - - get dependencySpecifiers() { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - if (this[kDependencySpecifiers] === undefined) { - this[kDependencySpecifiers] = this[kWrap].getStaticDependencySpecifiers(); - } - return this[kDependencySpecifiers]; - } - - get status() { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - if (this.#error !== kNoError) { - return 'errored'; - } - if (this.#statusOverride) { - return this.#statusOverride; - } - return super.status; - } - - get error() { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - if (this.#error !== kNoError) { - return this.#error; - } - return super.error; - } - - createCachedData() { - const { status } = this; - if (status === 'evaluating' || - status === 'evaluated' || - status === 'errored') { - throw new ERR_VM_MODULE_CANNOT_CREATE_CACHED_DATA(); - } - return this[kWrap].createCachedData(); - } -} - -class SyntheticModule extends Module { - constructor(exportNames, evaluateCallback, options = {}) { - if (!ArrayIsArray(exportNames) || - exportNames.some((e) => typeof e !== 'string')) { - throw new ERR_INVALID_ARG_TYPE('exportNames', - 'Array of unique strings', - exportNames); - } else { - exportNames.forEach((name, i) => { - if (exportNames.indexOf(name, i + 1) !== -1) { - throw new ERR_INVALID_ARG_VALUE(`exportNames.${name}`, - name, - 'is duplicated'); - } - }); - } - if (typeof evaluateCallback !== 'function') { - throw new ERR_INVALID_ARG_TYPE('evaluateCallback', 'function', - evaluateCallback); - } - - if (typeof options !== 'object' || options === null) { - throw new ERR_INVALID_ARG_TYPE('options', 'Object', options); - } - - const { context, identifier } = options; - - super({ - syntheticExportNames: exportNames, - syntheticEvaluationSteps: evaluateCallback, - context, - identifier, - }); - - this[kLink] = () => this[kWrap].link(() => { - assert.fail('link callback should not be called'); - }); - } - - setExport(name, value) { - if (this[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - validateString(name, 'name'); - if (this[kWrap].getStatus() < kInstantiated) { - throw new ERR_VM_MODULE_STATUS('must be linked'); - } - this[kWrap].setExport(name, value); - } -} - -function importModuleDynamicallyWrap(importModuleDynamically) { - const importModuleDynamicallyWrapper = async (...args) => { - const m = await importModuleDynamically(...args); - if (isModuleNamespaceObject(m)) { - return m; - } - if (!m || m[kWrap] === undefined) { - throw new ERR_VM_MODULE_NOT_MODULE(); - } - if (m.status === 'errored') { - throw m.error; - } - return m.namespace; - }; - return importModuleDynamicallyWrapper; -} - -module.exports = { - Module, - SourceTextModule, - SyntheticModule, - importModuleDynamicallyWrap, - getModuleFromWrap: (wrap) => wrapToModuleMap.get(wrap), -}; diff --git a/lib/repl.js b/lib/repl.js index f1721cb..3d197ad 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -633,7 +633,6 @@ function REPLServer(prompt, // @lwnode // const lines = errStack.split(/(?<=\n)/); const lines = errStack.split(/^/m); - let matched = false; errStack = ''; diff --git a/lib/vm.js b/lib/vm.js index 45a2edf..ce02c86 100644 --- a/lib/vm.js +++ b/lib/vm.js @@ -139,7 +139,15 @@ class Script extends ContextifyScript { return sigintHandlersWrap(super.runInContext, this, [contextifiedObject, ...args]); } - return super.runInContext(contextifiedObject, ...args); + + // @lwnode: Due to the incorrect Escargot execution, + // we split the code into two. + // @before + // return super.runInContext(contextifiedObject, ...args); + // @after + var r = super.runInContext(contextifiedObject, ...args); + return r; + // @end of lwnode } runInNewContext(contextObject, options) { diff --git a/lwnode/build-cctest-node.sh b/lwnode/build-cctest-node.sh new file mode 100755 index 0000000..1a77e98 --- /dev/null +++ b/lwnode/build-cctest-node.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright (c) 2021-present Samsung Electronics 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. + +CONFIG="--without-npm --without-bundled-v8 \ + --without-inspector --without-node-code-cache --without-node-snapshot \ + --with-intl none --shared-openssl --shared-zlib \ + --dest-os linux --dest-cpu x64 \ + --engine escargot \ + --ninja" + +if [[ $1 =~ ^"-d" ]]; then + ! [[ $1 =~ .*"b" ]] && ./configure $CONFIG --debug --debug-node + ninja -v -C out/Debug cctest |& lwnode/tools/colorize.sh + +else + ./configure $CONFIG + ninja -v -C out/Release cctest |& lwnode/tools/colorize.sh +fi diff --git a/lwnode/build-cctest.sh b/lwnode/build-cctest.sh index a13977e..5ab8701 100755 --- a/lwnode/build-cctest.sh +++ b/lwnode/build-cctest.sh @@ -17,7 +17,8 @@ ROOT_PATH=out/cctest ./tools/gyp/gyp ./lwnode/code/escargotshim/test/cctest.gyp --depth=. -f ninja \ --generator-output=$ROOT_PATH -Dbuild_asan=1 -Dbuild_mode=debug \ - -Descargot_lib_type=static_lib -Denable_experimental=true -Dtarget_arch=x64 + -Descargot_lib_type=static_lib -Dtarget_arch=x64 -Dtarget_os=linux \ + -Denable_experimental=true -Descargot_threading=1 ninja -v -C $ROOT_PATH/out/Debug cctest diff --git a/lwnode/build.sh b/lwnode/build.sh index c4d8dd4..5b6686d 100755 --- a/lwnode/build.sh +++ b/lwnode/build.sh @@ -20,14 +20,14 @@ CONFIG="--without-npm --without-bundled-v8 \ --without-inspector --without-node-code-cache --without-node-snapshot \ --with-intl none --shared-openssl --shared-zlib \ --dest-os linux --dest-cpu x64 \ - --engine escargot \ + --engine escargot --escargot-threading \ --ninja" if [[ $1 =~ ^"-d" ]]; then ! [[ $1 =~ .*"b" ]] && ./configure $CONFIG --debug --debug-node - ninja -v -C out/Debug lwnode |& lwnode/tools/colorize.sh + ninja -v -C out/linux/Debug lwnode |& lwnode/tools/colorize.sh else ./configure $CONFIG - ninja -v -C out/Release lwnode |& lwnode/tools/colorize.sh + ninja -v -C out/linux/Release lwnode |& lwnode/tools/colorize.sh fi diff --git a/lwnode/code/escargotshim/common.gypi b/lwnode/code/escargotshim/common.gypi index b83ea33..5a93981 100755 --- a/lwnode/code/escargotshim/common.gypi +++ b/lwnode/code/escargotshim/common.gypi @@ -10,10 +10,12 @@ 'defines': [ 'LWNODE=1' ], 'cflags!': [ '-Wno-error' ], 'cflags': [ - '-Wall', '-Wextra', '-Werror', '-ggdb', + '-Wall', '-Wextra', '-Werror', '-Wno-unused-variable', '-Wno-unused-function', '-Wno-unused-but-set-variable', + '-fPIC', + '-ggdb', # all builds include debug symbols, which will be stripped before packaging ], 'link_settings': { 'libraries': [ '-ldl', '-lrt' ], @@ -30,20 +32,17 @@ 'conditions': [ ['target_os=="tizen"', { 'target_defaults': { - 'defines': [ - 'HOST_TIZEN', + 'defines': ['HOST_TIZEN'], + 'cflags': [ + '-Os', + '-fPIE', + '-fstack-protector-strong', + '-D_FORTIFY_SOURCE=2', ], 'ldflags': [ - '-mthumb', '-pie', '-Wl,-z,relro,-z,now', ], - 'cflags': [ - '-ggdb', '-Os', - '-fPIC', '-fPIE', - '-fstack-protector-strong', - '-D_FORTIFY_SOURCE=2', - ], }, }], ['build_asan==1', { diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_android_arm.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_android_arm.cmake deleted file mode 100644 index ee682ed..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_android_arm.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_DEFINITIONS -DANDROID=1 -DESCARGOT_32=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG) -SET (ESCARGOT_CXXFLAGS_RELEASE) -SET (ESCARGOT_HOST android) -SET (ESCARGOT_ARCH arm) -SET (ESCARGOT_LDFLAGS -fPIE -pie -march=armv7-a -Wl,--fix-cortex-a8 -llog -Wl,--gc-sections) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_darwin_x64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_darwin_x64.cmake deleted file mode 100644 index c004e44..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_darwin_x64.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_CXXFLAGS -fno-rtti) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT) -SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT) - -SET (ESCARGOT_LDFLAGS -lpthread -Wl,-dead_strip) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_aarch64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_aarch64.cmake deleted file mode 100644 index e225b9e..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_aarch64.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_CXXFLAGS -fno-rtti) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT) -SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_arm.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_arm.cmake deleted file mode 100644 index 25ff1e3..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_arm.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_CXXFLAGS -fno-rtti -march=armv7-a -mthumb) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_32=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG) -SET (ESCARGOT_CXXFLAGS_RELEASE) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_i686.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_i686.cmake deleted file mode 100644 index 2f0543b..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_i686.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_CXXFLAGS -fno-rtti -m32 -mfpmath=sse -msse -msse2) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_32=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG) -SET (ESCARGOT_CXXFLAGS_RELEASE) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections -m32) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x64.cmake deleted file mode 100644 index e225b9e..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x64.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_CXXFLAGS -fno-rtti) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT) -SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x86.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x86.cmake deleted file mode 100644 index bddf67f..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x86.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_CXXFLAGS -fno-rtti -m32 -mfpmath=sse -msse -msse2) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_32=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG) -SET (ESCARGOT_CXXFLAGS_RELEASE) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections -m32) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS -m32) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_aarch64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_aarch64.cmake deleted file mode 100644 index e225b9e..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_aarch64.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_CXXFLAGS -fno-rtti) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT) -SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_arm.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_arm.cmake deleted file mode 100644 index 0f07369..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_arm.cmake +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (GC_CONFIGURE_HOST) - -SET (ESCARGOT_CXXFLAGS) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_TIZEN -DESCARGOT_32=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG -O1) -SET (ESCARGOT_CXXFLAGS_RELEASE -O2) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_i686.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_i686.cmake deleted file mode 100644 index d6e8c89..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_i686.cmake +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (GC_CONFIGURE_HOST) - -SET (ESCARGOT_CXXFLAGS -fno-rtti -m32 -mfpmath=sse -msse -msse2) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_32=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG) -SET (ESCARGOT_CXXFLAGS_RELEASE) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections -m32) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x64.cmake deleted file mode 100644 index e225b9e..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x64.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_CXXFLAGS -fno-rtti) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT) -SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86.cmake deleted file mode 100644 index bddf67f..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_CXXFLAGS -fno-rtti -m32 -mfpmath=sse -msse -msse2) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_32=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG) -SET (ESCARGOT_CXXFLAGS_RELEASE) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections -m32) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS -m32) diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86_64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86_64.cmake deleted file mode 100644 index e225b9e..0000000 --- a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86_64.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2019-present Samsung Electronics Co., Ltd -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -# USA - -SET (ESCARGOT_CXXFLAGS -fno-rtti) - -SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1) - -SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT) -SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT) - -SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections) - -SET (ESCARGOT_LIBRARIES) -SET (ESCARGOT_INCDIRS) - -SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT) diff --git a/lwnode/code/escargotshim/deps/escargot/build/config.cmake b/lwnode/code/escargotshim/deps/escargot/build/config.cmake index cc0d4c8..2030425 100644 --- a/lwnode/code/escargotshim/deps/escargot/build/config.cmake +++ b/lwnode/code/escargotshim/deps/escargot/build/config.cmake @@ -3,12 +3,6 @@ CMAKE_MINIMUM_REQUIRED (VERSION 2.8) ####################################################### # CONFIGURATION ####################################################### -IF (EXISTS "${PROJECT_SOURCE_DIR}/build/cmake/toolchain_${ESCARGOT_HOST}_${ESCARGOT_ARCH}.cmake") - INCLUDE ("${PROJECT_SOURCE_DIR}/build/cmake/toolchain_${ESCARGOT_HOST}_${ESCARGOT_ARCH}.cmake") -ELSE() - MESSAGE (FATAL_ERROR "Error: unsupported target") -ENDIF() - # CONFIGURE ESCARGOT VERSION FIND_PACKAGE(Git) IF (GIT_FOUND) @@ -32,6 +26,10 @@ SET (ESCARGOT_ROOT ${PROJECT_SOURCE_DIR}) SET (ESCARGOT_THIRD_PARTY_ROOT ${ESCARGOT_ROOT}/third_party) SET (GCUTIL_ROOT ${ESCARGOT_THIRD_PARTY_ROOT}/GCutil) +####################################################### +# FLAGS FOR TARGET +####################################################### +INCLUDE (${ESCARGOT_ROOT}/build/target.cmake) ####################################################### # FLAGS FOR COMMON @@ -85,17 +83,11 @@ ELSE() MESSAGE (FATAL_ERROR ${CMAKE_CXX_COMPILER_ID} " is Unsupported Compiler") ENDIF() - - # bdwgc IF (${ESCARGOT_MODE} STREQUAL "debug") SET (ESCARGOT_DEFINITIONS_COMMON ${ESCARGOT_DEFINITIONS_COMMON} -DGC_DEBUG) ENDIF() -####################################################### -# FLAGS FOR $(ESCARGOT_HOST) -####################################################### - IF (${ESCARGOT_OUTPUT} STREQUAL "shared_lib" AND ${ESCARGOT_HOST} STREQUAL "android") SET (ESCARGOT_LDFLAGS ${ESCARGOT_LDFLAGS} -shared) ENDIF() @@ -112,7 +104,6 @@ IF (NOT DEFINED ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN) SET (ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN ON) ENDIF() - IF (${ESCARGOT_HOST} STREQUAL "android") SET (ESCARGOT_LIBICU_SUPPORT OFF) ENDIF() @@ -120,7 +111,8 @@ ENDIF() ####################################################### # FLAGS FOR ADDITIONAL FUNCTION ####################################################### - +SET (ESCARGOT_LIBRARIES) +SET (ESCARGOT_INCDIRS) FIND_PACKAGE (PkgConfig REQUIRED) IF (ESCARGOT_LIBICU_SUPPORT) IF (ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN) @@ -170,23 +162,20 @@ IF (ESCARGOT_THREADING) ENDIF() ####################################################### -# flags for $(MODE) : debug/release +# FLAGS FOR $(MODE) : debug/release ####################################################### # DEBUG FLAGS SET (ESCARGOT_CXXFLAGS_DEBUG -O0 -Wall -Wextra -Werror ${ESCARGOT_CXXFLAGS_DEBUG}) SET (ESCARGOT_DEFINITIONS_DEBUG -D_GLIBCXX_DEBUG -DGC_DEBUG) - # RELEASE FLAGS SET (ESCARGOT_CXXFLAGS_RELEASE -O2 -fno-stack-protector ${ESCARGOT_CXXFLAGS_RELEASE}) SET (ESCARGOT_DEFINITIONS_RELEASE -DNDEBUG) - # SHARED_LIB FLAGS SET (ESCARGOT_CXXFLAGS_SHAREDLIB -fPIC) SET (ESCARGOT_LDFLAGS_SHAREDLIB -ldl) - # STATIC_LIB FLAGS SET (ESCARGOT_CXXFLAGS_STATICLIB -fPIC -DESCARGOT_EXPORT=) SET (ESCARGOT_LDFLAGS_STATICLIB -Wl,--gc-sections) @@ -195,13 +184,11 @@ SET (ESCARGOT_LDFLAGS_STATICLIB -Wl,--gc-sections) SET (ESCARGOT_CXXFLAGS_SHELL -DESCARGOT_EXPORT=) SET (ESCARGOT_LDFLAGS_SHELL -Wl,--gc-sections) - ####################################################### # FLAGS FOR TEST ####################################################### SET (ESCARGOT_DEFINITIONS_TEST -DESCARGOT_ENABLE_TEST) - ####################################################### # FLAGS FOR MEMORY PROFILING ####################################################### @@ -223,7 +210,6 @@ ENDIF() # FLAGS FOR DEBUGGER ####################################################### SET (DEBUGGER_FLAGS) - IF (ESCARGOT_DEBUGGER) SET (DEBUGGER_FLAGS ${DEBUGGER_FLAGS} -DESCARGOT_DEBUGGER) ENDIF() diff --git a/lwnode/code/escargotshim/deps/escargot/build/escargot.cmake b/lwnode/code/escargotshim/deps/escargot/build/escargot.cmake index e19f32e..5359820 100644 --- a/lwnode/code/escargotshim/deps/escargot/build/escargot.cmake +++ b/lwnode/code/escargotshim/deps/escargot/build/escargot.cmake @@ -72,12 +72,12 @@ SET (ESCARGOT_SRC_LIST # GCUTIL IF (${ESCARGOT_OUTPUT} STREQUAL "shared_lib") - SET (ESCARGOT_GCUTIL_CFLAGS ${ESCARGOT_GCUTIL_CFLAGS} ${ESCARGOT_CXXFLAGS_SHAREDLIB}) + SET (ESCARGOT_THIRDPARTY_CFLAGS ${ESCARGOT_THIRDPARTY_CFLAGS} ${ESCARGOT_CXXFLAGS_SHAREDLIB}) ELSEIF (${ESCARGOT_OUTPUT} STREQUAL "static_lib") - SET (ESCARGOT_GCUTIL_CFLAGS ${ESCARGOT_GCUTIL_CFLAGS} ${ESCARGOT_CXXFLAGS_STATICLIB}) + SET (ESCARGOT_THIRDPARTY_CFLAGS ${ESCARGOT_THIRDPARTY_CFLAGS} ${ESCARGOT_CXXFLAGS_STATICLIB}) ENDIF() -SET (GCUTIL_CFLAGS ${ESCARGOT_GCUTIL_CFLAGS}) +SET (GCUTIL_CFLAGS ${ESCARGOT_THIRDPARTY_CFLAGS}) IF (ESCARGOT_SMALL_CONFIG) SET (GCUTIL_CFLAGS ${GCUTIL_CFLAGS} -DSMALL_CONFIG -DMAX_HEAP_SECTS=512) @@ -98,7 +98,7 @@ ADD_LIBRARY (libbf STATIC ${ESCARGOT_THIRD_PARTY_ROOT}/libbf/cutils.c) TARGET_INCLUDE_DIRECTORIES (libbf PUBLIC ${ESCARGOT_THIRD_PARTY_ROOT}/libbf) SET (LIBBF_CFLAGS - ${ESCARGOT_GCUTIL_CFLAGS} # we can share arch flags with gcutil + ${ESCARGOT_THIRDPARTY_CFLAGS} # we can share flags with gcutil ${CFLAGS_FROM_ENV} -w -g3 @@ -135,7 +135,7 @@ SET (ESCARGOT_LIBRARIES ${ESCARGOT_LIBRARIES} runtime-icu-binder-static) # WebAssembly (wabt) IF (ESCARGOT_WASM) SET (WASM_CXX_FLAGS - ${ESCARGOT_GCUTIL_CFLAGS} # we can share arch flags with gcutil + ${ESCARGOT_THIRDPARTY_CFLAGS} # we can share flags with gcutil -g3) SET (WASM_ARCH ${ESCARGOT_ARCH}) @@ -149,31 +149,31 @@ IF (${ESCARGOT_OUTPUT} MATCHES "shell") ADD_EXECUTABLE (${ESCARGOT_TARGET} ${ESCARGOT_SRC_LIST}) TARGET_LINK_LIBRARIES (${ESCARGOT_TARGET} ${ESCARGOT_LIBRARIES} ${ESCARGOT_LDFLAGS} ${LDFLAGS_FROM_ENV}) - TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_INCDIRS}) - TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_DEFINITIONS}) - TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV} ${PROFILER_FLAGS} ${DEBUGGER_FLAGS}) + TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_INCDIRS}) + TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_DEFINITIONS}) + TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV} ${PROFILER_FLAGS} ${DEBUGGER_FLAGS}) ELSEIF (${ESCARGOT_OUTPUT} STREQUAL "shared_lib") ADD_LIBRARY (${ESCARGOT_TARGET} SHARED ${ESCARGOT_SRC_LIST}) TARGET_LINK_LIBRARIES (${ESCARGOT_TARGET} ${ESCARGOT_LIBRARIES} ${ESCARGOT_LDFLAGS} ${LDFLAGS_FROM_ENV}) - TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_INCDIRS}) - TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_DEFINITIONS}) - TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV}) + TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_INCDIRS}) + TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_DEFINITIONS}) + TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV}) ELSEIF (${ESCARGOT_OUTPUT} STREQUAL "static_lib") ADD_LIBRARY (${ESCARGOT_TARGET} STATIC ${ESCARGOT_SRC_LIST}) TARGET_LINK_LIBRARIES (${ESCARGOT_TARGET} ${ESCARGOT_LIBRARIES} ${ESCARGOT_LDFLAGS} ${LDFLAGS_FROM_ENV}) - TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_INCDIRS}) - TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_DEFINITIONS}) - TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV}) + TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_INCDIRS}) + TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_DEFINITIONS}) + TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV}) ELSEIF (${ESCARGOT_OUTPUT} STREQUAL "cctest") ADD_EXECUTABLE (${ESCARGOT_CCTEST_TARGET} ${ESCARGOT_SRC_LIST}) TARGET_LINK_LIBRARIES (${ESCARGOT_CCTEST_TARGET} ${ESCARGOT_LIBRARIES} ${ESCARGOT_LDFLAGS} ${LDFLAGS_FROM_ENV} gtest) - TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_CCTEST_TARGET} PUBLIC ${ESCARGOT_INCDIRS}) - TARGET_COMPILE_DEFINITIONS (${ESCARGOT_CCTEST_TARGET} PUBLIC ${ESCARGOT_DEFINITIONS}) - TARGET_COMPILE_OPTIONS (${ESCARGOT_CCTEST_TARGET} PUBLIC ${ESCARGOT_CXXFLAGS} -I${ESCARGOT_ROOT}/third_party/googletest/googletest/include/ ${CXXFLAGS_FROM_ENV}) + TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_CCTEST_TARGET} PRIVATE ${ESCARGOT_INCDIRS}) + TARGET_COMPILE_DEFINITIONS (${ESCARGOT_CCTEST_TARGET} PRIVATE ${ESCARGOT_DEFINITIONS}) + TARGET_COMPILE_OPTIONS (${ESCARGOT_CCTEST_TARGET} PRIVATE ${ESCARGOT_CXXFLAGS} -I${ESCARGOT_ROOT}/third_party/googletest/googletest/include/ ${CXXFLAGS_FROM_ENV}) ENDIF() diff --git a/lwnode/code/escargotshim/deps/escargot/build/target.cmake b/lwnode/code/escargotshim/deps/escargot/build/target.cmake new file mode 100644 index 0000000..763e1c0 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/build/target.cmake @@ -0,0 +1,62 @@ +# default set of each flag +SET (ESCARGOT_CXXFLAGS -fno-rtti) # build escargot without rtti +SET (ESCARGOT_CXXFLAGS_DEBUG) +SET (ESCARGOT_CXXFLAGS_RELEASE) +SET (ESCARGOT_LDFLAGS) +SET (ESCARGOT_DEFINITIONS) +SET (ESCARGOT_THIRDPARTY_CFLAGS) + +SET (ESCARGOT_BUILD_32BIT OFF) + +IF (${ESCARGOT_HOST} STREQUAL "linux") + # default set of LDFLAGS + SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections) + IF (${ESCARGOT_ARCH} STREQUAL "x64") + ELSEIF ((${ESCARGOT_ARCH} STREQUAL "x86") OR (${ESCARGOT_ARCH} STREQUAL "i686")) + SET (ESCARGOT_BUILD_32BIT ON) + SET (ESCARGOT_CXXFLAGS ${ESCARGOT_CXXFLAGS} -m32 -mfpmath=sse -msse -msse2) + SET (ESCARGOT_LDFLAGS ${ESCARGOT_LDFLAGS} -m32) + SET (ESCARGOT_THIRDPARTY_CFLAGS -m32) + ELSEIF (${ESCARGOT_ARCH} STREQUAL "arm") + SET (ESCARGOT_BUILD_32BIT ON) + SET (ESCARGOT_CXXFLAGS ${ESCARGOT_CXXFLAGS} -march=armv7-a -mthumb) + ELSEIF (${ESCARGOT_ARCH} STREQUAL "aarch64") + ELSE() + MESSAGE (FATAL_ERROR ${ESCARGOT_ARCH} " is unsupported") + ENDIF() +ELSEIF (${ESCARGOT_HOST} STREQUAL "tizen_obs") + # default set of LDFLAGS + SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections) + SET (ESCARGOT_DEFINITIONS -DESCARGOT_TIZEN) + IF (${ESCARGOT_ARCH} STREQUAL "x64") + ELSEIF ((${ESCARGOT_ARCH} STREQUAL "x86") OR (${ESCARGOT_ARCH} STREQUAL "i686")) + SET (ESCARGOT_BUILD_32BIT ON) + SET (ESCARGOT_CXXFLAGS ${ESCARGOT_CXXFLAGS} -m32 -mfpmath=sse -msse -msse2) + SET (ESCARGOT_LDFLAGS ${ESCARGOT_LDFLAGS} -m32) + SET (ESCARGOT_THIRDPARTY_CFLAGS -m32) + ELSEIF (${ESCARGOT_ARCH} STREQUAL "arm") + SET (ESCARGOT_BUILD_32BIT ON) + SET (ESCARGOT_CXXFLAGS_DEBUG -O1) + SET (ESCARGOT_CXXFLAGS_RELEASE -O2) + ELSEIF (${ESCARGOT_ARCH} STREQUAL "aarch64") + ELSE() + MESSAGE (FATAL_ERROR ${ESCARGOT_ARCH} " is unsupported") + ENDIF() +ELSEIF (${ESCARGOT_HOST} STREQUAL "android" AND ${ESCARGOT_ARCH} STREQUAL "arm") + SET (ESCARGOT_BUILD_32BIT ON) + SET (ESCARGOT_LDFLAGS -fPIE -pie -march=armv7-a -Wl,--fix-cortex-a8 -llog -Wl,--gc-sections) + SET (ESCARGOT_DEFINITIONS -DANDROID=1) +ELSEIF (${ESCARGOT_HOST} STREQUAL "darwin" AND ${ESCARGOT_ARCH} STREQUAL "x64") + SET (ESCARGOT_LDFLAGS -lpthread -Wl,-dead_strip) +ELSE() + MESSAGE (FATAL_ERROR ${ESCARGOT_HOST} " with " ${ESCARGOT_ARCH} " is unsupported") +ENDIF() + +IF (ESCARGOT_BUILD_32BIT) + # 32bit build + SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DESCARGOT_32=1) +ELSE() + # 64bit build + SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DESCARGOT_64=1 -DESCARGOT_USE_32BIT_IN_64BIT) + SET (ESCARGOT_THIRDPARTY_CFLAGS ${ESCARGOT_THIRDPARTY_CFLAGS} -DESCARGOT_USE_32BIT_IN_64BIT) +ENDIF() diff --git a/lwnode/code/escargotshim/deps/escargot/src/Escargot.h b/lwnode/code/escargotshim/deps/escargot/src/Escargot.h index e8779e0..d9e3db6 100755 --- a/lwnode/code/escargotshim/deps/escargot/src/Escargot.h +++ b/lwnode/code/escargotshim/deps/escargot/src/Escargot.h @@ -179,6 +179,9 @@ #define NOMINMAX #endif +#if defined(COMPILER_GCC) || defined(COMPILER_CLANG) +#define HAVE_BUILTIN_ATOMIC_FUNCTIONS +#endif #if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) #define CPU_X86_64 @@ -220,10 +223,20 @@ #include #include +#if defined(ENABLE_THREADING) +#include +#include +#include +#endif + extern "C" { #include } +#ifndef ESCARGOT_BUILD_DATE +#define ESCARGOT_BUILD_DATE __DATE__ +#endif + #ifdef ENABLE_ICU #if defined(ENABLE_RUNTIME_ICU_BINDER) typedef unsigned char LChar; diff --git a/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.cpp b/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.cpp index 47e31dd..0e9a964 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.cpp @@ -23,7 +23,10 @@ #include "parser/ast/Node.h" #include "parser/ScriptParser.h" #include "parser/CodeBlock.h" +#include "runtime/Global.h" +#include "runtime/ThreadLocal.h" #include "runtime/Context.h" +#include "runtime/Platform.h" #include "runtime/FunctionObject.h" #include "runtime/Value.h" #include "runtime/VMInstance.h" @@ -44,6 +47,7 @@ #include "runtime/PromiseObject.h" #include "runtime/ProxyObject.h" #include "runtime/BackingStore.h" +#include "runtime/ArrayBuffer.h" #include "runtime/ArrayBufferObject.h" #include "runtime/TypedArrayObject.h" #include "runtime/SetObject.h" @@ -61,6 +65,8 @@ #include "runtime/ExtendedNativeFunctionObject.h" #include "runtime/BigInt.h" #include "runtime/BigIntObject.h" +#include "runtime/SharedArrayBufferObject.h" +#include "runtime/serialization/Serializer.h" #include "interpreter/ByteCode.h" #include "api/internal/ValueAdapter.h" #if defined(ENABLE_WASM) @@ -102,27 +108,190 @@ inline AtomicString toImpl(AtomicStringRef* v) return AtomicString::fromPayload(reinterpret_cast(v)); } +class PlatformBridge : public Platform { +public: + PlatformBridge(PlatformRef* p) + : m_platform(p) + { + } + + virtual ~PlatformBridge() + { + // delete PlatformRef, so we don't care about PlatformRef's lifetime + delete m_platform; + } + + virtual void* onMallocArrayBufferObjectDataBuffer(size_t sizeInByte) override + { + return m_platform->onMallocArrayBufferObjectDataBuffer(sizeInByte); + } + + virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte) override + { + m_platform->onFreeArrayBufferObjectDataBuffer(buffer, sizeInByte); + } + + virtual void* onReallocArrayBufferObjectDataBuffer(void* oldBuffer, size_t oldSizeInByte, size_t newSizeInByte) override + { + return m_platform->onReallocArrayBufferObjectDataBuffer(oldBuffer, oldSizeInByte, newSizeInByte); + } + + virtual void markJSJobEnqueued(Context* relatedContext) override + { + // TODO Job queue should be separately managed for each thread + m_platform->markJSJobEnqueued(toRef(relatedContext)); + } + + virtual LoadModuleResult onLoadModule(Context* relatedContext, Script* whereRequestFrom, String* moduleSrc) override + { + LoadModuleResult result; + auto refResult = m_platform->onLoadModule(toRef(relatedContext), toRef(whereRequestFrom), toRef(moduleSrc)); + + result.script = toImpl(refResult.script.get()); + result.errorMessage = toImpl(refResult.errorMessage); + result.errorCode = refResult.errorCode; + + return result; + } + + virtual void didLoadModule(Context* relatedContext, Optional whereRequestFrom, Script* loadedModule) override + { + if (whereRequestFrom) { + m_platform->didLoadModule(toRef(relatedContext), toRef(whereRequestFrom.value()), toRef(loadedModule)); + } else { + m_platform->didLoadModule(toRef(relatedContext), nullptr, toRef(loadedModule)); + } + } + + virtual void hostImportModuleDynamically(Context* relatedContext, Script* referrer, String* src, PromiseObject* promise) override + { + m_platform->hostImportModuleDynamically(toRef(relatedContext), toRef(referrer), toRef(src), toRef(promise)); + } + + virtual void* allocateThreadLocalCustomData() override + { + return m_platform->allocateThreadLocalCustomData(); + } + + virtual void deallocateThreadLocalCustomData() override + { + m_platform->deallocateThreadLocalCustomData(); + } + +private: + PlatformRef* m_platform; +}; + +void PlatformRef::notifyHostImportModuleDynamicallyResult(ContextRef* relatedContext, ScriptRef* referrer, StringRef* src, PromiseObjectRef* promise, LoadModuleResult loadModuleResult) +{ + auto result = Evaluator::execute(relatedContext, [](ExecutionStateRef* state, LoadModuleResult loadModuleResult, Script::ModuleData::ModulePromiseObject* promise) -> ValueRef* { + if (loadModuleResult.script) { + if (loadModuleResult.script.value()->isExecuted()) { + if (loadModuleResult.script.value()->wasThereErrorOnModuleEvaluation()) { + state->throwException(loadModuleResult.script.value()->moduleEvaluationError()); + } + } + } else { + state->throwException(ErrorObjectRef::create(state, loadModuleResult.errorCode, loadModuleResult.errorMessage)); + } + return ValueRef::createUndefined(); + }, + loadModuleResult, (Script::ModuleData::ModulePromiseObject*)promise); + + Script::ModuleData::ModulePromiseObject* mp = (Script::ModuleData::ModulePromiseObject*)promise; + mp->m_referrer = toImpl(referrer); + if (loadModuleResult.script.hasValue()) { + mp->m_loadedScript = toImpl(loadModuleResult.script.value()); + if (!mp->m_loadedScript->moduleData()->m_didCallLoadedCallback) { + Context* ctx = toImpl(relatedContext); + Global::platform()->didLoadModule(ctx, toImpl(referrer), mp->m_loadedScript); + mp->m_loadedScript->moduleData()->m_didCallLoadedCallback = true; + } + } + + if (result.error) { + mp->m_value = toImpl(result.error.value()); + Evaluator::execute(relatedContext, [](ExecutionStateRef* state, ValueRef* error, PromiseObjectRef* promise) -> ValueRef* { + promise->reject(state, promise); + return ValueRef::createUndefined(); + }, + result.error.value(), promise); + } else { + Evaluator::execute(relatedContext, [](ExecutionStateRef* state, ValueRef* error, PromiseObjectRef* promise) -> ValueRef* { + promise->fulfill(state, promise); + return ValueRef::createUndefined(); + }, + result.error.value(), promise); + } +} + +void* PlatformRef::threadLocalCustomData() +{ + return ThreadLocal::customData(); +} + bool thread_local Globals::g_globalsInited = false; -void Globals::initialize() +void Globals::initialize(PlatformRef* platform) { - // initialize global value or context + // initialize global value or context including thread-local variables // this function should be invoked once at the start of the program + // argument `platform` will be deleted automatically when Globals::finalize called RELEASE_ASSERT(!g_globalsInited); - Heap::initialize(); - VMInstance::initialize(); + Global::initialize(new PlatformBridge(platform)); + ThreadLocal::initialize(); g_globalsInited = true; } void Globals::finalize() { - // finalize global value or context + // finalize global value or context including thread-local variables // this function should be invoked once at the end of the program RELEASE_ASSERT(!!g_globalsInited); - Heap::finalize(); - VMInstance::finalize(); + ThreadLocal::finalize(); + + // Global::finalize should be called at the end of program + // because it holds Platform which could be used in other Object's finalizer + Global::finalize(); g_globalsInited = false; } +void Globals::initializeThread() +{ + // initialize thread-local variables + // this function should be invoked at the start of sub-thread + RELEASE_ASSERT(!g_globalsInited); + ThreadLocal::initialize(); + g_globalsInited = true; +} + +void Globals::finalizeThread() +{ + // finalize thread-local variables + // this function should be invoked once at the end of sub-thread + RELEASE_ASSERT(!!g_globalsInited); + ThreadLocal::finalize(); + g_globalsInited = false; +} + +bool Globals::supportsThreading() +{ +#if defined(ENABLE_THREADING) + return true; +#else + return false; +#endif +} + +const char* Globals::version() +{ + return ESCARGOT_VERSION; +} + +const char* Globals::buildDate() +{ + return ESCARGOT_BUILD_DATE; +} + void* Memory::gcMalloc(size_t siz) { return GC_MALLOC(siz); @@ -517,9 +686,13 @@ OptionalRef RopeStringRef::right() } } -SymbolRef* SymbolRef::create(StringRef* desc) +SymbolRef* SymbolRef::create(OptionalRef desc) { - return toRef(new Symbol(toImpl(desc))); + if (desc) { + return toRef(new Symbol(toImpl(desc.value()))); + } else { + return toRef(new Symbol()); + } } SymbolRef* SymbolRef::fromGlobalSymbolRegistry(VMInstanceRef* vm, StringRef* desc) @@ -527,12 +700,12 @@ SymbolRef* SymbolRef::fromGlobalSymbolRegistry(VMInstanceRef* vm, StringRef* des return toRef(Symbol::fromGlobalSymbolRegistry(toImpl(vm), toImpl(desc))); } -StringRef* SymbolRef::description() +OptionalRef SymbolRef::description() { if (toImpl(this)->description().hasValue()) { return toRef(toImpl(this)->description().value()); } - return toRef(String::emptyString); + return nullptr; } StringRef* SymbolRef::symbolDescriptiveString() @@ -705,105 +878,6 @@ bool BigIntRef::isNegative() return toImpl(this)->isNegative(); } -class PlatformBridge : public Platform { -public: - PlatformBridge(PlatformRef* p) - : m_platform(p) - { - } - - virtual void* onMallocArrayBufferObjectDataBuffer(size_t sizeInByte) override - { - return m_platform->onMallocArrayBufferObjectDataBuffer(sizeInByte); - } - - virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte) override - { - m_platform->onFreeArrayBufferObjectDataBuffer(buffer, sizeInByte); - } - - virtual void* onReallocArrayBufferObjectDataBuffer(void* oldBuffer, size_t oldSizeInByte, size_t newSizeInByte) override - { - return m_platform->onReallocArrayBufferObjectDataBuffer(oldBuffer, oldSizeInByte, newSizeInByte); - } - - virtual void markJSJobEnqueued(Context* relatedContext) override - { - m_platform->markJSJobEnqueued(toRef(relatedContext)); - } - - virtual LoadModuleResult onLoadModule(Context* relatedContext, Script* whereRequestFrom, String* moduleSrc) override - { - LoadModuleResult result; - auto refResult = m_platform->onLoadModule(toRef(relatedContext), toRef(whereRequestFrom), toRef(moduleSrc)); - - result.script = toImpl(refResult.script.get()); - result.errorMessage = toImpl(refResult.errorMessage); - result.errorCode = refResult.errorCode; - - return result; - } - - virtual void didLoadModule(Context* relatedContext, Optional whereRequestFrom, Script* loadedModule) override - { - if (whereRequestFrom) { - m_platform->didLoadModule(toRef(relatedContext), toRef(whereRequestFrom.value()), toRef(loadedModule)); - } else { - m_platform->didLoadModule(toRef(relatedContext), nullptr, toRef(loadedModule)); - } - } - - virtual void hostImportModuleDynamically(Context* relatedContext, Script* referrer, String* src, PromiseObject* promise) override - { - m_platform->hostImportModuleDynamically(toRef(relatedContext), toRef(referrer), toRef(src), toRef(promise)); - } - - PlatformRef* m_platform; -}; - -void PlatformRef::notifyHostImportModuleDynamicallyResult(ContextRef* relatedContext, ScriptRef* referrer, StringRef* src, PromiseObjectRef* promise, LoadModuleResult loadModuleResult) -{ - auto result = Evaluator::execute(relatedContext, [](ExecutionStateRef* state, LoadModuleResult loadModuleResult, Script::ModuleData::ModulePromiseObject* promise) -> ValueRef* { - if (loadModuleResult.script) { - if (loadModuleResult.script.value()->isExecuted()) { - if (loadModuleResult.script.value()->wasThereErrorOnModuleEvaluation()) { - state->throwException(loadModuleResult.script.value()->moduleEvaluationError()); - } - } - } else { - state->throwException(ErrorObjectRef::create(state, loadModuleResult.errorCode, loadModuleResult.errorMessage)); - } - return ValueRef::createUndefined(); - }, - loadModuleResult, (Script::ModuleData::ModulePromiseObject*)promise); - - Script::ModuleData::ModulePromiseObject* mp = (Script::ModuleData::ModulePromiseObject*)promise; - mp->m_referrer = toImpl(referrer); - if (loadModuleResult.script.hasValue()) { - mp->m_loadedScript = toImpl(loadModuleResult.script.value()); - if (!mp->m_loadedScript->moduleData()->m_didCallLoadedCallback) { - Context* ctx = toImpl(relatedContext); - ctx->vmInstance()->platform()->didLoadModule(ctx, toImpl(referrer), mp->m_loadedScript); - mp->m_loadedScript->moduleData()->m_didCallLoadedCallback = true; - } - } - - if (result.error) { - mp->m_value = toImpl(result.error.value()); - Evaluator::execute(relatedContext, [](ExecutionStateRef* state, ValueRef* error, PromiseObjectRef* promise) -> ValueRef* { - promise->reject(state, promise); - return ValueRef::createUndefined(); - }, - result.error.value(), promise); - } else { - Evaluator::execute(relatedContext, [](ExecutionStateRef* state, ValueRef* error, PromiseObjectRef* promise) -> ValueRef* { - promise->fulfill(state, promise); - return ValueRef::createUndefined(); - }, - result.error.value(), promise); - } -} - Evaluator::StackTraceData::StackTraceData() : src(toRef(String::emptyString)) , sourceCode(toRef(String::emptyString)) @@ -931,14 +1005,9 @@ COMPILE_ASSERT((int)VMInstanceRef::PromiseHookType::Resolve == (int)VMInstance:: COMPILE_ASSERT((int)VMInstanceRef::PromiseHookType::Before == (int)VMInstance::PromiseHookType::Before, ""); COMPILE_ASSERT((int)VMInstanceRef::PromiseHookType::After == (int)VMInstance::PromiseHookType::After, ""); -PersistentRefHolder VMInstanceRef::create(PlatformRef* platform, const char* locale, const char* timezone, const char* baseCacheDir) +PersistentRefHolder VMInstanceRef::create(const char* locale, const char* timezone, const char* baseCacheDir) { - return PersistentRefHolder(toRef(new VMInstance(new PlatformBridge(platform), locale, timezone, baseCacheDir))); -} - -PlatformRef* VMInstanceRef::platform() -{ - return ((PlatformBridge*)toImpl(this)->platform())->m_platform; + return PersistentRefHolder(toRef(new VMInstance(locale, timezone, baseCacheDir))); } void VMInstanceRef::setOnVMInstanceDelete(OnVMInstanceDelete cb) @@ -2053,6 +2122,15 @@ bool ContextRef::initDebugger(const char* options) #endif /* ESCARGOT_DEBUGGER */ } +bool ContextRef::isDebuggerRunning() +{ +#ifdef ESCARGOT_DEBUGGER + return !!toImpl(this)->debugger() && toImpl(this)->debugger()->enabled(); +#else /* !ESCARGOT_DEBUGGER */ + return false; +#endif /* ESCARGOT_DEBUGGER */ +} + void ContextRef::printDebugger(StringRef* output) { #ifdef ESCARGOT_DEBUGGER @@ -2767,9 +2845,9 @@ RegExpObjectRef::RegExpObjectOption RegExpObjectRef::option() return (RegExpObjectRef::RegExpObjectOption)toImpl(this)->option(); } -BackingStoreRef* BackingStoreRef::create(VMInstanceRef* instance, size_t byteLength) +BackingStoreRef* BackingStoreRef::create(size_t byteLength) { - return toRef(new BackingStore(toImpl(instance), byteLength)); + return toRef(new BackingStore(byteLength)); } BackingStoreRef* BackingStoreRef::create(void* data, size_t byteLength, BackingStoreRef::BackingStoreRefDeleterCallback callback, void* callbackData) @@ -2792,9 +2870,28 @@ bool BackingStoreRef::isShared() return toImpl(this)->isShared(); } -void BackingStoreRef::reallocate(VMInstanceRef* instance, size_t newByteLength) +void BackingStoreRef::reallocate(size_t newByteLength) +{ + toImpl(this)->reallocate(newByteLength); +} + +OptionalRef ArrayBufferRef::backingStore() { - toImpl(this)->reallocate(toImpl(instance), newByteLength); + if (toImpl(this)->backingStore()) { + return toRef(toImpl(this)->backingStore().value()); + } else { + return nullptr; + } +} + +uint8_t* ArrayBufferRef::rawBuffer() +{ + return (uint8_t*)toImpl(this)->data(); +} + +size_t ArrayBufferRef::byteLength() +{ + return toImpl(this)->byteLength(); } ArrayBufferObjectRef* ArrayBufferObjectRef::create(ExecutionStateRef* state) @@ -2817,41 +2914,33 @@ void ArrayBufferObjectRef::detachArrayBuffer() toImpl(this)->detachArrayBuffer(); } -OptionalRef ArrayBufferObjectRef::backingStore() -{ - if (toImpl(this)->backingStore()) { - return toRef(toImpl(this)->backingStore().value()); - } else { - return nullptr; - } -} - -uint8_t* ArrayBufferObjectRef::rawBuffer() +bool ArrayBufferObjectRef::isDetachedBuffer() { - return (uint8_t*)toImpl(this)->data(); + return toImpl(this)->isDetachedBuffer(); } - -size_t ArrayBufferObjectRef::byteLength() +#if defined(ENABLE_THREADING) +SharedArrayBufferObjectRef* SharedArrayBufferObjectRef::create(ExecutionStateRef* state, size_t byteLength) { - return toImpl(this)->byteLength(); + return toRef(new SharedArrayBufferObject(*toImpl(state), toImpl(state)->context()->globalObject()->sharedArrayBufferPrototype(), byteLength)); } - -bool ArrayBufferObjectRef::isDetachedBuffer() +#else +SharedArrayBufferObjectRef* SharedArrayBufferObjectRef::create(ExecutionStateRef* state, size_t byteLength) { - return toImpl(this)->isDetachedBuffer(); + RELEASE_ASSERT_NOT_REACHED(); } +#endif -ArrayBufferObjectRef* ArrayBufferViewRef::buffer() +ArrayBufferRef* ArrayBufferViewRef::buffer() { return toRef(toImpl(this)->buffer()); } -void ArrayBufferViewRef::setBuffer(ArrayBufferObjectRef* bo, size_t byteOffset, size_t byteLength, size_t arrayLength) +void ArrayBufferViewRef::setBuffer(ArrayBufferRef* bo, size_t byteOffset, size_t byteLength, size_t arrayLength) { toImpl(this)->setBuffer(toImpl(bo), byteOffset, byteLength, arrayLength); } -void ArrayBufferViewRef::setBuffer(ArrayBufferObjectRef* bo, size_t byteOffset, size_t byteLength) +void ArrayBufferViewRef::setBuffer(ArrayBufferRef* bo, size_t byteOffset, size_t byteLength) { toImpl(this)->setBuffer(toImpl(bo), byteOffset, byteLength); } @@ -3340,6 +3429,11 @@ void FunctionTemplateRef::setName(AtomicStringRef* name) toImpl(this)->setName(toImpl(name)); } +void FunctionTemplateRef::setLength(size_t length) +{ + toImpl(this)->setLength(length); +} + void FunctionTemplateRef::updateCallbackFunction(FunctionTemplateRef::NativeFunctionPointer fn) { toImpl(this)->updateCallbackFunction(fn); @@ -3468,6 +3562,26 @@ PlatformRef::LoadModuleResult::LoadModuleResult(ErrorObjectRef::Code errorCode, { } +bool SerializerRef::serializeInto(ValueRef* value, std::ostringstream& output) +{ + return Serializer::serializeInto(toImpl(value), output); +} + +ValueRef* SerializerRef::deserializeFrom(ContextRef* context, std::istringstream& input) +{ + std::unique_ptr value = Serializer::deserializeFrom(input); + + SandBox sb(toImpl(context)); + auto result = sb.run([](ExecutionState& state, void* data) -> Value { + std::unique_ptr* value = (std::unique_ptr*)data; + return value->get()->toValue(state); + }, + &value); + + ASSERT(result.error.isEmpty()); + return toRef(result.result); +} + #if defined(ENABLE_WASM) ValueRef* WASMOperationsRef::copyStableBufferBytes(ExecutionStateRef* state, ValueRef* source) { diff --git a/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.h b/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.h index b0f3c2b..216bbb1 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.h +++ b/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.h @@ -38,12 +38,14 @@ #include #include #include +#include #if !defined(NDEBUG) && defined(__GLIBCXX__) && !defined(_GLIBCXX_DEBUG) #pragma message("You should define `_GLIBCXX_DEBUG` in {debug mode + libstdc++} because Escargot uses it") #endif #define ESCARGOT_POINTERVALUE_CHILD_REF_LIST(F) \ + F(ArrayBuffer) \ F(ArrayBufferObject) \ F(ArrayBufferView) \ F(ArrayObject) \ @@ -65,6 +67,7 @@ F(ProxyObject) \ F(RegExpObject) \ F(SetObject) \ + F(SharedArrayBufferObject) \ F(String) \ F(StringObject) \ F(Symbol) \ @@ -124,10 +127,20 @@ class ESCARGOT_EXPORT Globals { static thread_local bool g_globalsInited; public: - // Escargot has thread-isoloate Globals. - // Users need to call initialize, finalize function for each thread - static void initialize(); + // Escargot has thread-independent Globals. + // Users should call initialize, finalize once in the main program + static void initialize(PlatformRef* platform); static void finalize(); + + // Globals also used for thread initialization + // Users need to call initializeThread, finalizeThread function for each thread + static void initializeThread(); + static void finalizeThread(); + + static bool supportsThreading(); + + static const char* version(); + static const char* buildDate(); }; class ESCARGOT_EXPORT Memory { @@ -603,7 +616,7 @@ class ESCARGOT_EXPORT VMInstanceRef { public: // you can to provide timezone as TZ database name like "US/Pacific". // if you don't provide, we try to detect system timezone. - static PersistentRefHolder create(PlatformRef* platform, const char* locale = nullptr, const char* timezone = nullptr, const char* baseCacheDir = nullptr); + static PersistentRefHolder create(const char* locale = nullptr, const char* timezone = nullptr, const char* baseCacheDir = nullptr); typedef void (*OnVMInstanceDelete)(VMInstanceRef* instance); void setOnVMInstanceDelete(OnVMInstanceDelete cb); @@ -630,8 +643,6 @@ public: // you can call this function if you don't want to use every alive contexts void clearCachesRelatedWithContext(); - PlatformRef* platform(); - SymbolRef* toStringTagSymbol(); SymbolRef* iteratorSymbol(); SymbolRef* unscopablesSymbol(); @@ -667,6 +678,7 @@ public: void throwException(ValueRef* exceptionValue); // if you use this function without Evaluator, your program will crash :( bool initDebugger(const char* options); + bool isDebuggerRunning(); void printDebugger(StringRef* output); StringRef* getClientSource(StringRef** sourceName); @@ -922,9 +934,9 @@ public: class ESCARGOT_EXPORT SymbolRef : public PointerValueRef { public: - static SymbolRef* create(StringRef* desc); + static SymbolRef* create(OptionalRef desc); static SymbolRef* fromGlobalSymbolRegistry(VMInstanceRef* context, StringRef* desc); // this is same with Symbol.for - StringRef* description(); + OptionalRef description(); StringRef* symbolDescriptiveString(); }; @@ -1462,7 +1474,7 @@ class ESCARGOT_EXPORT BackingStoreRef { friend class ArrayBufferObject; public: - static BackingStoreRef* create(VMInstanceRef* instance, size_t byteLength); + static BackingStoreRef* create(size_t byteLength); typedef void (*BackingStoreRefDeleterCallback)(void* data, size_t length, void* deleterData); static BackingStoreRef* create(void* data, size_t byteLength, BackingStoreRefDeleterCallback callback, void* callbackData); @@ -1471,27 +1483,35 @@ public: size_t byteLength(); // Indicates whether the backing store is Shared Data Block (for SharedArrayBuffer) bool isShared(); - void reallocate(VMInstanceRef* instance, size_t newByteLength); + void reallocate(size_t newByteLength); }; -class ESCARGOT_EXPORT ArrayBufferObjectRef : public ObjectRef { +class ESCARGOT_EXPORT ArrayBufferRef : public ObjectRef { +public: + OptionalRef backingStore(); + uint8_t* rawBuffer(); + size_t byteLength(); +}; + +class ESCARGOT_EXPORT ArrayBufferObjectRef : public ArrayBufferRef { public: static ArrayBufferObjectRef* create(ExecutionStateRef* state); void allocateBuffer(ExecutionStateRef* state, size_t bytelength); void attachBuffer(BackingStoreRef* backingStore); void detachArrayBuffer(); - - OptionalRef backingStore(); - uint8_t* rawBuffer(); - size_t byteLength(); bool isDetachedBuffer(); }; +class ESCARGOT_EXPORT SharedArrayBufferObjectRef : public ArrayBufferRef { +public: + static SharedArrayBufferObjectRef* create(ExecutionStateRef* state, size_t bytelength); +}; + class ESCARGOT_EXPORT ArrayBufferViewRef : public ObjectRef { public: - ArrayBufferObjectRef* buffer(); - void setBuffer(ArrayBufferObjectRef* bo, size_t byteOffset, size_t byteLength, size_t arrayLength); - void setBuffer(ArrayBufferObjectRef* bo, size_t byteOffset, size_t byteLength); + ArrayBufferRef* buffer(); + void setBuffer(ArrayBufferRef* bo, size_t byteOffset, size_t byteLength, size_t arrayLength); + void setBuffer(ArrayBufferRef* bo, size_t byteOffset, size_t byteLength); uint8_t* rawBuffer(); size_t byteLength(); size_t byteOffset(); @@ -1741,6 +1761,13 @@ struct ESCARGOT_EXPORT ObjectTemplateNamedPropertyHandlerData { } }; +class ESCARGOT_EXPORT SerializerRef { +public: + // returns the serialization was successful + static bool serializeInto(ValueRef* value, std::ostringstream& output); + static ValueRef* deserializeFrom(ContextRef* context, std::istringstream& input); +}; + class ESCARGOT_EXPORT ObjectTemplateRef : public TemplateRef { public: static ObjectTemplateRef* create(); @@ -1763,7 +1790,10 @@ public: static FunctionTemplateRef* create(AtomicStringRef* name, size_t argumentCount, bool isStrict, bool isConstructor, FunctionTemplateRef::NativeFunctionPointer fn); + // setName and setLength should be called before instantiate void setName(AtomicStringRef* name); + void setLength(size_t length); + void updateCallbackFunction(FunctionTemplateRef::NativeFunctionPointer fn); ObjectTemplateRef* prototypeTemplate(); @@ -1857,6 +1887,22 @@ public: notifyHostImportModuleDynamicallyResult(relatedContext, referrer, src, promise, onLoadModule(relatedContext, referrer, src)); } void notifyHostImportModuleDynamicallyResult(ContextRef* relatedContext, ScriptRef* referrer, StringRef* src, PromiseObjectRef* promise, LoadModuleResult loadModuleResult); + + // ThreadLocal custom data + // PlatformRef should not have any member variables + // Instead, user could allocate thread-local values through following methods + virtual void* allocateThreadLocalCustomData() + { + // do nothing + return nullptr; + } + + virtual void deallocateThreadLocalCustomData() + { + // do nothing + } + + void* threadLocalCustomData(); }; #if defined(ENABLE_WASM) diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArray.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArray.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArray.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArray.cpp index 0a78647..83aec02 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArray.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArray.cpp @@ -18,15 +18,15 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "ArrayObject.h" -#include "IteratorObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/ArrayObject.h" +#include "runtime/IteratorObject.h" +#include "runtime/ToStringRecursionPreventer.h" +#include "runtime/ErrorObject.h" +#include "runtime/NativeFunctionObject.h" #include "interpreter/ByteCodeInterpreter.h" -#include "ToStringRecursionPreventer.h" -#include "ErrorObject.h" -#include "NativeFunctionObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArrayBuffer.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArrayBuffer.cpp similarity index 98% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArrayBuffer.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArrayBuffer.cpp index e9e91e8..8216f25 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArrayBuffer.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArrayBuffer.cpp @@ -18,11 +18,11 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "NativeFunctionObject.h" -#include "ArrayBufferObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/ArrayBufferObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFromSyncIterator.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFromSyncIterator.cpp similarity index 100% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFromSyncIterator.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFromSyncIterator.cpp diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFunction.cpp similarity index 94% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFunction.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFunction.cpp index 895c680..4835ade 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFunction.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFunction.cpp @@ -18,11 +18,11 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "GeneratorObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/GeneratorObject.h" +#include "runtime/NativeFunctionObject.h" #include "runtime/ScriptAsyncFunctionObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncGeneratorFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncGeneratorFunction.cpp similarity index 98% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncGeneratorFunction.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncGeneratorFunction.cpp index e5f46d8..612e71f 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncGeneratorFunction.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncGeneratorFunction.cpp @@ -18,9 +18,9 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" #include "runtime/ScriptAsyncGeneratorFunctionObject.h" #include "runtime/AsyncGeneratorObject.h" #include "runtime/NativeFunctionObject.h" diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncIterator.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncIterator.cpp similarity index 95% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncIterator.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncIterator.cpp index 4f253ac..d58c145 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncIterator.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncIterator.cpp @@ -18,9 +18,9 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" #include "runtime/NativeFunctionObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAtomics.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAtomics.cpp similarity index 57% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAtomics.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAtomics.cpp index 6e85140..7ea0d7c 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAtomics.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAtomics.cpp @@ -20,13 +20,17 @@ #if defined(ENABLE_THREADING) #include "Escargot.h" -#include "Context.h" -#include "VMInstance.h" -#include "NativeFunctionObject.h" -#include "TypedArrayObject.h" -#include "TypedArrayInlines.h" -#include "SharedArrayBufferObject.h" -#include "CheckedArithmetic.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/TypedArrayObject.h" +#include "runtime/TypedArrayInlines.h" +#include "runtime/Global.h" +#include "runtime/BigInt.h" + +#if !defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) && !defined(ENABLE_ATOMICS_GLOBAL_LOCK) +#error "without builtin atomic functions, we need to atomics global lock for implementing atomics builtin" +#endif namespace Escargot { @@ -39,101 +43,9 @@ enum class AtomicBinaryOps : uint8_t { XOR, }; -static Value atomicIntegerOperations(ExecutionState& state, int32_t lnum, int32_t rnum, AtomicBinaryOps op) -{ - int32_t result = 0; - bool passed = true; - - switch (op) { - case AtomicBinaryOps::ADD: - passed = ArithmeticOperations::add(lnum, rnum, result); - break; - case AtomicBinaryOps::AND: - result = lnum & rnum; - break; - case AtomicBinaryOps::EXCH: - result = rnum; - break; - case AtomicBinaryOps::OR: - result = lnum | rnum; - break; - case AtomicBinaryOps::SUB: - passed = ArithmeticOperations::sub(lnum, rnum, result); - break; - case AtomicBinaryOps::XOR: - result = lnum ^ rnum; - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - break; - }; - - if (LIKELY(passed)) { - return Value(result); - } - - ASSERT(op == AtomicBinaryOps::ADD || op == AtomicBinaryOps::SUB); - if (op == AtomicBinaryOps::ADD) { - return Value(Value::EncodeAsDouble, static_cast(lnum) + static_cast(rnum)); - } - return Value(Value::EncodeAsDouble, static_cast(lnum) - static_cast(rnum)); -} - -static Value atomicNumberOperations(ExecutionState& state, double lnum, double rnum, AtomicBinaryOps op) -{ - double result = 0; - - switch (op) { - case AtomicBinaryOps::ADD: - result = lnum + rnum; - break; - case AtomicBinaryOps::AND: - result = Value(lnum).toInt32(state) & Value(rnum).toInt32(state); - break; - case AtomicBinaryOps::EXCH: - result = rnum; - break; - case AtomicBinaryOps::OR: - result = Value(lnum).toInt32(state) | Value(rnum).toInt32(state); - break; - case AtomicBinaryOps::SUB: - result = lnum - rnum; - break; - case AtomicBinaryOps::XOR: - result = Value(lnum).toInt32(state) ^ Value(rnum).toInt32(state); - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - break; - }; - - return Value(result); -} - -static Value atomicBigIntOperations(ExecutionState& state, BigInt* lnum, BigInt* rnum, AtomicBinaryOps op) +static ArrayBuffer* validateIntegerTypedArray(ExecutionState& state, Value typedArray, bool waitable = false) { - switch (op) { - case AtomicBinaryOps::ADD: - return lnum->addition(state, rnum); - case AtomicBinaryOps::AND: - return lnum->bitwiseAnd(state, rnum); - case AtomicBinaryOps::EXCH: - return rnum; - case AtomicBinaryOps::OR: - return lnum->bitwiseOr(state, rnum); - case AtomicBinaryOps::SUB: - return lnum->subtraction(state, rnum); - case AtomicBinaryOps::XOR: - return lnum->bitwiseXor(state, rnum); - default: - RELEASE_ASSERT_NOT_REACHED(); - return Value(); - }; -} - -static ArrayBufferObject* validateIntegerTypedArray(ExecutionState& state, Value typedArray, bool waitable = false) -{ - ArrayBufferObject* buffer = TypedArrayObject::validateTypedArray(state, typedArray); + ArrayBuffer* buffer = TypedArrayObject::validateTypedArray(state, typedArray); TypedArrayObject* TA = typedArray.asObject()->asTypedArrayObject(); if (waitable) { @@ -161,37 +73,117 @@ static size_t validateAtomicAccess(ExecutionState& state, TypedArrayObject* type return (static_cast(accessIndex) * elementSize) + offset; } -static Value getModifySetValueInBuffer(ExecutionState& state, ArrayBufferObject* buffer, size_t indexedPosition, TypedArrayType type, Value v2, AtomicBinaryOps op) +template +static T atomicOperation(volatile uint8_t* rawStart, ArgType value, AtomicBinaryOps op) +{ + T returnValue; +#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) + volatile T* ptr = reinterpret_cast(rawStart); + switch (op) { + case AtomicBinaryOps::ADD: + returnValue = __atomic_fetch_add(ptr, value, __ATOMIC_SEQ_CST); + break; + case AtomicBinaryOps::AND: + returnValue = __atomic_fetch_and(ptr, value, __ATOMIC_SEQ_CST); + break; + case AtomicBinaryOps::EXCH: { + T v = value; + __atomic_exchange(ptr, &v, &returnValue, __ATOMIC_SEQ_CST); + } break; + case AtomicBinaryOps::OR: + returnValue = __atomic_fetch_or(ptr, value, __ATOMIC_SEQ_CST); + break; + case AtomicBinaryOps::SUB: + returnValue = __atomic_fetch_sub(ptr, value, __ATOMIC_SEQ_CST); + break; + default: + ASSERT(op == AtomicBinaryOps::XOR); + returnValue = __atomic_fetch_xor(ptr, value, __ATOMIC_SEQ_CST); + break; + } +#else + { + volatile T* ptr = reinterpret_cast(rawStart); + std::lock_guard guard(Global::atomicsLock()); + returnValue = *ptr; + switch (op) { + case AtomicBinaryOps::ADD: + *ptr = *ptr + value; + break; + case AtomicBinaryOps::AND: + *ptr = *ptr & value; + break; + case AtomicBinaryOps::EXCH: + *ptr = value; + break; + case AtomicBinaryOps::OR: + *ptr = *ptr | value; + break; + case AtomicBinaryOps::SUB: + *ptr = *ptr - value; + break; + default: + ASSERT(op == AtomicBinaryOps::XOR); + *ptr = *ptr ^ value; + break; + } + } +#endif + return returnValue; +} + +static Value getModifySetValueInBuffer(ExecutionState& state, ArrayBuffer* buffer, size_t indexedPosition, TypedArrayType type, Value v2, AtomicBinaryOps op) { size_t elemSize = TypedArrayHelper::elementSize(type); ASSERT(indexedPosition + elemSize <= buffer->byteLength()); - uint8_t* rawStart = const_cast(buffer->data()) + indexedPosition; - Value rawBytesRead = TypedArrayHelper::rawBytesToNumber(state, type, rawStart); - Value v1 = rawBytesRead; - Value val; - if (v1.isInt32() && v2.isInt32()) { - val = atomicIntegerOperations(state, v1.asInt32(), v2.asInt32(), op); - } else if (v1.isNumber() && v2.isNumber()) { - val = atomicNumberOperations(state, v1.asNumber(), v2.asNumber(), op); - } else { - ASSERT(v1.isBigInt() && v2.isBigInt()); - auto lnum = v1.asBigInt(); - auto rnum = v2.asBigInt(); - val = atomicBigIntOperations(state, lnum, rnum, op); + if (v2.isInt32()) { + switch (type) { + case TypedArrayType::Int8: + return Value(atomicOperation(rawStart, v2.asInt32(), op)); + case TypedArrayType::Int16: + return Value(atomicOperation(rawStart, v2.asInt32(), op)); + case TypedArrayType::Int32: + return Value(atomicOperation(rawStart, v2.asInt32(), op)); + case TypedArrayType::Uint8: + return Value(atomicOperation(rawStart, v2.asInt32(), op)); + case TypedArrayType::Uint16: + return Value(atomicOperation(rawStart, v2.asInt32(), op)); + case TypedArrayType::Uint32: + return Value(atomicOperation(rawStart, v2.asInt32(), op)); + default: + ASSERT(TypedArrayType::Uint8Clamped == type); + return Value(atomicOperation(rawStart, v2.asInt32(), op)); + } } - uint8_t* rawBytes = ALLOCA(8, uint8_t, state); - TypedArrayHelper::numberToRawBytes(state, type, val, rawBytes); - memcpy(rawStart, rawBytes, elemSize); - - return rawBytesRead; + switch (type) { + case TypedArrayType::Int8: + return Value(atomicOperation(rawStart, v2.asNumber(), op)); + case TypedArrayType::Int16: + return Value(atomicOperation(rawStart, v2.asNumber(), op)); + case TypedArrayType::Int32: + return Value(atomicOperation(rawStart, v2.asNumber(), op)); + case TypedArrayType::Uint8: + return Value(atomicOperation(rawStart, v2.asNumber(), op)); + case TypedArrayType::Uint16: + return Value(atomicOperation(rawStart, v2.asNumber(), op)); + case TypedArrayType::Uint32: + return Value(atomicOperation(rawStart, v2.asNumber(), op)); + case TypedArrayType::Uint8Clamped: + return Value(atomicOperation(rawStart, v2.asNumber(), op)); + case TypedArrayType::BigInt64: + return new BigInt(atomicOperation(rawStart, v2.asBigInt()->toInt64(), op)); + default: + ASSERT(TypedArrayType::BigUint64 == type); + return new BigInt(atomicOperation(rawStart, v2.asBigInt()->toUint64(), op)); + } } static Value atomicReadModifyWrite(ExecutionState& state, Value typedArray, Value index, Value value, AtomicBinaryOps op) { - ArrayBufferObject* buffer = validateIntegerTypedArray(state, typedArray); + ArrayBuffer* buffer = validateIntegerTypedArray(state, typedArray); TypedArrayObject* TA = typedArray.asObject()->asTypedArrayObject(); size_t indexedPosition = validateAtomicAccess(state, TA, index); TypedArrayType type = TA->typedArrayType(); @@ -216,9 +208,18 @@ static Value builtinAtomicsAnd(ExecutionState& state, Value thisValue, size_t ar return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::AND); } +#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) +template +void atomicCompareExchange(uint8_t* rawStart, uint8_t* expectedBytes, uint8_t* replacementBytes) +{ + __atomic_compare_exchange(reinterpret_cast(rawStart), reinterpret_cast(expectedBytes), + reinterpret_cast(replacementBytes), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); +} +#endif + static Value builtinAtomicsCompareExchange(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) { - ArrayBufferObject* buffer = validateIntegerTypedArray(state, argv[0]); + ArrayBuffer* buffer = validateIntegerTypedArray(state, argv[0]); TypedArrayObject* TA = argv[0].asObject()->asTypedArrayObject(); size_t indexedPosition = validateAtomicAccess(state, TA, argv[1]); TypedArrayType type = TA->typedArrayType(); @@ -237,9 +238,44 @@ static Value builtinAtomicsCompareExchange(ExecutionState& state, Value thisValu ASSERT(indexedPosition + elemSize <= buffer->byteLength()); uint8_t* expectedBytes = ALLOCA(8, uint8_t, state); TypedArrayHelper::numberToRawBytes(state, type, expected, expectedBytes); - - // TODO SharedArrayBuffer case uint8_t* rawStart = const_cast(buffer->data()) + indexedPosition; +#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) + uint8_t* replacementBytes = ALLOCA(8, uint8_t, state); + TypedArrayHelper::numberToRawBytes(state, type, replacement, replacementBytes); + bool ret; + switch (type) { + case TypedArrayType::Int8: + atomicCompareExchange(rawStart, expectedBytes, replacementBytes); + break; + case TypedArrayType::Int16: + atomicCompareExchange(rawStart, expectedBytes, replacementBytes); + break; + case TypedArrayType::Int32: + atomicCompareExchange(rawStart, expectedBytes, replacementBytes); + break; + case TypedArrayType::Uint8: + atomicCompareExchange(rawStart, expectedBytes, replacementBytes); + break; + case TypedArrayType::Uint16: + atomicCompareExchange(rawStart, expectedBytes, replacementBytes); + break; + case TypedArrayType::Uint32: + atomicCompareExchange(rawStart, expectedBytes, replacementBytes); + break; + case TypedArrayType::Uint8Clamped: + atomicCompareExchange(rawStart, expectedBytes, replacementBytes); + break; + case TypedArrayType::BigInt64: + atomicCompareExchange(rawStart, expectedBytes, replacementBytes); + break; + default: + ASSERT(TypedArrayType::BigUint64 == type); + atomicCompareExchange(rawStart, expectedBytes, replacementBytes); + break; + } + return TypedArrayHelper::rawBytesToNumber(state, type, expectedBytes); +#else + std::lock_guard guard(Global::atomicsLock()); Value rawBytesRead = TypedArrayHelper::rawBytesToNumber(state, type, rawStart); bool isByteListEqual = true; @@ -254,8 +290,8 @@ static Value builtinAtomicsCompareExchange(ExecutionState& state, Value thisValu TypedArrayHelper::numberToRawBytes(state, type, replacement, replacementBytes); memcpy(rawStart, replacementBytes, elemSize); } - return rawBytesRead; +#endif } static Value builtinAtomicsExchange(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) @@ -263,14 +299,59 @@ static Value builtinAtomicsExchange(ExecutionState& state, Value thisValue, size return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::EXCH); } +#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) +template +void atomicLoad(uint8_t* rawStart, uint8_t* rawBytes) +{ + __atomic_load(reinterpret_cast(rawStart), reinterpret_cast(rawBytes), __ATOMIC_SEQ_CST); +} +#endif + static Value builtinAtomicsLoad(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) { - ArrayBufferObject* buffer = validateIntegerTypedArray(state, argv[0]); + ArrayBuffer* buffer = validateIntegerTypedArray(state, argv[0]); TypedArrayObject* TA = argv[0].asObject()->asTypedArrayObject(); size_t indexedPosition = validateAtomicAccess(state, TA, argv[1]); TypedArrayType type = TA->typedArrayType(); +#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) + uint8_t* rawStart = TA->buffer()->data() + indexedPosition; + uint8_t* rawBytes = ALLOCA(8, uint8_t, state); + switch (type) { + case TypedArrayType::Int8: + atomicLoad(rawStart, rawBytes); + break; + case TypedArrayType::Int16: + atomicLoad(rawStart, rawBytes); + break; + case TypedArrayType::Int32: + atomicLoad(rawStart, rawBytes); + break; + case TypedArrayType::Uint8: + atomicLoad(rawStart, rawBytes); + break; + case TypedArrayType::Uint16: + atomicLoad(rawStart, rawBytes); + break; + case TypedArrayType::Uint32: + atomicLoad(rawStart, rawBytes); + break; + case TypedArrayType::Uint8Clamped: + atomicLoad(rawStart, rawBytes); + break; + case TypedArrayType::BigInt64: + atomicLoad(rawStart, rawBytes); + break; + default: + ASSERT(TypedArrayType::BigUint64 == type); + atomicLoad(rawStart, rawBytes); + break; + } + return TypedArrayHelper::rawBytesToNumber(state, type, rawBytes); +#else + std::lock_guard guard(Global::atomicsLock()); return buffer->getValueFromBuffer(state, indexedPosition, type); +#endif } static Value builtinAtomicsOr(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) @@ -278,9 +359,17 @@ static Value builtinAtomicsOr(ExecutionState& state, Value thisValue, size_t arg return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::OR); } +#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) +template +void atomicStore(uint8_t* rawStart, uint8_t* rawBytes) +{ + __atomic_store(reinterpret_cast(rawStart), reinterpret_cast(rawBytes), __ATOMIC_SEQ_CST); +} +#endif + static Value builtinAtomicsStore(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) { - ArrayBufferObject* buffer = validateIntegerTypedArray(state, argv[0]); + ArrayBuffer* buffer = validateIntegerTypedArray(state, argv[0]); TypedArrayObject* TA = argv[0].asObject()->asTypedArrayObject(); size_t indexedPosition = validateAtomicAccess(state, TA, argv[1]); TypedArrayType type = TA->typedArrayType(); @@ -293,8 +382,47 @@ static Value builtinAtomicsStore(ExecutionState& state, Value thisValue, size_t v = Value(value.toInteger(state)); } +#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) + uint8_t* rawStart = TA->buffer()->data() + indexedPosition; + uint8_t* rawBytes = ALLOCA(8, uint8_t, state); + TypedArrayHelper::numberToRawBytes(state, type, v, rawBytes); + + switch (type) { + case TypedArrayType::Int8: + atomicStore(rawStart, rawBytes); + break; + case TypedArrayType::Int16: + atomicStore(rawStart, rawBytes); + break; + case TypedArrayType::Int32: + atomicStore(rawStart, rawBytes); + break; + case TypedArrayType::Uint8: + atomicStore(rawStart, rawBytes); + break; + case TypedArrayType::Uint16: + atomicStore(rawStart, rawBytes); + break; + case TypedArrayType::Uint32: + atomicStore(rawStart, rawBytes); + break; + case TypedArrayType::Uint8Clamped: + atomicStore(rawStart, rawBytes); + break; + case TypedArrayType::BigInt64: + atomicStore(rawStart, rawBytes); + break; + default: + ASSERT(TypedArrayType::BigUint64 == type); + atomicStore(rawStart, rawBytes); + break; + } + return v; +#else + std::lock_guard guard(Global::atomicsLock()); buffer->setValueInBuffer(state, indexedPosition, type, v); return v; +#endif } static Value builtinAtomicsSub(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBigInt.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBigInt.cpp similarity index 96% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBigInt.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBigInt.cpp index 413ec19..c0a27e4 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBigInt.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBigInt.cpp @@ -18,14 +18,15 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "BigIntObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/ThreadLocal.h" +#include "runtime/VMInstance.h" +#include "runtime/BigIntObject.h" +#include "runtime/NativeFunctionObject.h" #if defined(ENABLE_ICU) && defined(ENABLE_INTL) -#include "IntlNumberFormat.h" +#include "intl/IntlNumberFormat.h" #endif namespace Escargot { @@ -49,7 +50,7 @@ static Value builtinBigIntConstructor(ExecutionState& state, Value thisValue, si if ((numValue > (double)std::numeric_limits::max()) || (numValue < (double)std::numeric_limits::min())) { // handle overflowed integer number bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_set_float64(&r, numValue); ASSERT(!ret); ASSERT(bf_is_finite(&r)); @@ -75,8 +76,8 @@ static Value builtinBigIntAsUintN(ExecutionState& state, Value thisValue, size_t BigInt* bigint = argv[1].toBigInt(state); // Return a BigInt representing bigint modulo 2bits. bf_t mask, r; - bf_init(VMInstance::bfContext(), &mask); - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &mask); + bf_init(ThreadLocal::bfContext(), &r); bf_set_ui(&mask, 1); bf_mul_2exp(&mask, bits, BF_PREC_INF, BF_RNDZ); bf_add_si(&mask, &mask, -1, BF_PREC_INF, BF_RNDZ); @@ -97,8 +98,8 @@ static Value builtinBigIntAsIntN(ExecutionState& state, Value thisValue, size_t BigInt* bigint = argv[1].toBigInt(state); // Return a BigInt representing bigint modulo 2bits. bf_t mask, r; - bf_init(VMInstance::bfContext(), &mask); - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &mask); + bf_init(ThreadLocal::bfContext(), &r); bf_set_ui(&mask, 1); bf_mul_2exp(&mask, bits, BF_PREC_INF, BF_RNDZ); bf_add_si(&mask, &mask, -1, BF_PREC_INF, BF_RNDZ); diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBoolean.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBoolean.cpp similarity index 97% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBoolean.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBoolean.cpp index 468d941..1a07a2f 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBoolean.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBoolean.cpp @@ -18,10 +18,10 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "BooleanObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/BooleanObject.h" +#include "runtime/NativeFunctionObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDataView.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDataView.cpp similarity index 97% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDataView.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDataView.cpp index 40d5827..5ca74af 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDataView.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDataView.cpp @@ -18,11 +18,11 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "DataViewObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/DataViewObject.h" +#include "runtime/NativeFunctionObject.h" namespace Escargot { @@ -43,11 +43,11 @@ static Value builtinDataViewConstructor(ExecutionState& state, Value thisValue, if (!newTarget.hasValue()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew); } - if (!(argv[0].isObject() && argv[0].asPointerValue()->isArrayBufferObject())) { + if (!(argv[0].isObject() && argv[0].asPointerValue()->isArrayBuffer())) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_ThisNotArrayBufferObject); } - ArrayBufferObject* buffer = argv[0].asObject()->asArrayBufferObject(); + ArrayBuffer* buffer = argv[0].asObject()->asArrayBuffer(); double byteOffset = 0; if (argc >= 2) { Value& val = argv[1]; @@ -127,7 +127,7 @@ FOR_EACH_DATAVIEW_TYPES(DECLARE_DATAVIEW_SETTER); static Value builtinDataViewBufferGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) { if (LIKELY(thisValue.isPointerValue() && thisValue.asPointerValue()->isDataViewObject())) { - ArrayBufferObject* buffer = thisValue.asObject()->asArrayBufferView()->buffer(); + ArrayBuffer* buffer = thisValue.asObject()->asArrayBufferView()->buffer(); if (buffer) { return Value(buffer); } diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDate.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDate.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDate.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDate.cpp index 9c0bf02..6ccfc5f 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDate.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDate.cpp @@ -18,15 +18,15 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "DateObject.h" -#include "ErrorObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/DateObject.h" +#include "runtime/ErrorObject.h" +#include "runtime/NativeFunctionObject.h" #if defined(ENABLE_ICU) && defined(ENABLE_INTL) -#include "IntlDateTimeFormat.h" +#include "intl/IntlDateTimeFormat.h" #endif namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinError.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinError.cpp similarity index 98% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinError.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinError.cpp index bc8f844..e0bd9c6 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinError.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinError.cpp @@ -18,11 +18,11 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "ErrorObject.h" -#include "NativeFunctionObject.h" -#include "ToStringRecursionPreventer.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/ErrorObject.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/ToStringRecursionPreventer.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFinalizationRegistry.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFinalizationRegistry.cpp similarity index 97% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFinalizationRegistry.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFinalizationRegistry.cpp index e58dd32..e2ca14c 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFinalizationRegistry.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFinalizationRegistry.cpp @@ -18,11 +18,11 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "FinalizationRegistryObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/FinalizationRegistryObject.h" +#include "runtime/NativeFunctionObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFunction.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFunction.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFunction.cpp index 0230f62..197cb7f 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFunction.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFunction.cpp @@ -18,10 +18,10 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/NativeFunctionObject.h" #include "runtime/BoundFunctionObject.h" #include "runtime/ScriptFunctionObject.h" #include "runtime/ScriptClassConstructorFunctionObject.h" diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinGeneratorFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinGeneratorFunction.cpp similarity index 97% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinGeneratorFunction.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinGeneratorFunction.cpp index 329d53f..3014125 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinGeneratorFunction.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinGeneratorFunction.cpp @@ -18,11 +18,11 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "GeneratorObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/GeneratorObject.h" +#include "runtime/NativeFunctionObject.h" #include "runtime/ScriptGeneratorFunctionObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIntl.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIntl.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIntl.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIntl.cpp index c7604a1..cfa9c67 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIntl.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIntl.cpp @@ -44,21 +44,21 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "StringObject.h" -#include "ArrayObject.h" -#include "VMInstance.h" -#include "NativeFunctionObject.h" -#include "DateObject.h" -#include "BigInt.h" -#include "Intl.h" -#include "IntlCollator.h" -#include "IntlNumberFormat.h" -#include "IntlDateTimeFormat.h" -#include "IntlPluralRules.h" -#include "IntlLocale.h" -#include "IntlRelativeTimeFormat.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/StringObject.h" +#include "runtime/ArrayObject.h" +#include "runtime/VMInstance.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/DateObject.h" +#include "runtime/BigInt.h" +#include "intl/Intl.h" +#include "intl/IntlCollator.h" +#include "intl/IntlNumberFormat.h" +#include "intl/IntlDateTimeFormat.h" +#include "intl/IntlPluralRules.h" +#include "intl/IntlLocale.h" +#include "intl/IntlRelativeTimeFormat.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIterator.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIterator.cpp similarity index 91% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIterator.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIterator.cpp index 1ea284f..33edc15 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIterator.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIterator.cpp @@ -18,11 +18,11 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "NativeFunctionObject.h" -#include "ToStringRecursionPreventer.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/ToStringRecursionPreventer.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinJSON.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinJSON.cpp similarity index 98% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinJSON.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinJSON.cpp index 7d3bc46..7f179ae 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinJSON.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinJSON.cpp @@ -18,15 +18,15 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "StringObject.h" -#include "ArrayObject.h" -#include "TypedArrayObject.h" -#include "BooleanObject.h" -#include "BigIntObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/StringObject.h" +#include "runtime/ArrayObject.h" +#include "runtime/TypedArrayObject.h" +#include "runtime/BooleanObject.h" +#include "runtime/BigIntObject.h" +#include "runtime/NativeFunctionObject.h" #define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag #define RAPIDJSON_ERROR_CHARTYPE char diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMap.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMap.cpp similarity index 98% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMap.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMap.cpp index 329311b..d509e13 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMap.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMap.cpp @@ -18,13 +18,13 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "MapObject.h" -#include "IteratorObject.h" -#include "NativeFunctionObject.h" -#include "ToStringRecursionPreventer.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/MapObject.h" +#include "runtime/IteratorObject.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/ToStringRecursionPreventer.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMath.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMath.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMath.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMath.cpp index f4b629f..e54ae9f 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMath.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMath.cpp @@ -18,13 +18,14 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "StringObject.h" -#include "NativeFunctionObject.h" - -#include "IEEE754.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/ThreadLocal.h" +#include "runtime/StringObject.h" +#include "runtime/NativeFunctionObject.h" + +#include "runtime/IEEE754.h" #include namespace Escargot { @@ -397,7 +398,7 @@ static Value builtinMathLog2(ExecutionState& state, Value thisValue, size_t argc static Value builtinMathRandom(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) { std::uniform_real_distribution distribution; - return Value(distribution(VMInstance::randEngine())); + return Value(distribution(ThreadLocal::randEngine())); } static Value builtinMathExp(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinNumber.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinNumber.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinNumber.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinNumber.cpp index cd01cba..e74e11a 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinNumber.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinNumber.cpp @@ -18,17 +18,17 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "NumberObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/NumberObject.h" +#include "runtime/NativeFunctionObject.h" // dtoa #include "ieee.h" #include "double-conversion.h" #if defined(ENABLE_ICU) && defined(ENABLE_INTL) -#include "IntlNumberFormat.h" +#include "intl/IntlNumberFormat.h" #endif #define NUMBER_TO_STRING_BUFFER_LENGTH 128 diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinObject.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinObject.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinObject.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinObject.cpp index f9c1de4..f86b8a2 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinObject.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinObject.cpp @@ -18,12 +18,12 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "ArrayObject.h" -#include "NativeFunctionObject.h" -#include "IteratorObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/ArrayObject.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/IteratorObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinPromise.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinPromise.cpp similarity index 100% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinPromise.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinPromise.cpp diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinProxy.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinProxy.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinProxy.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinProxy.cpp index 5d10aee..c3f8ace 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinProxy.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinProxy.cpp @@ -18,7 +18,7 @@ */ #include "Escargot.h" -#include "ProxyObject.h" +#include "runtime/ProxyObject.h" #include "runtime/GlobalObject.h" #include "runtime/Context.h" #include "runtime/ArrayObject.h" diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinReflect.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinReflect.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinReflect.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinReflect.cpp index 67d6328..ee8f6ef 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinReflect.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinReflect.cpp @@ -24,8 +24,8 @@ #include "runtime/ProxyObject.h" #include "runtime/NativeFunctionObject.h" #include "interpreter/ByteCodeInterpreter.h" -#include "ArrayObject.h" -#include "VMInstance.h" +#include "runtime/ArrayObject.h" +#include "runtime/VMInstance.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinRegExp.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinRegExp.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinRegExp.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinRegExp.cpp index 7459b0e..ee14b7b 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinRegExp.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinRegExp.cpp @@ -18,12 +18,12 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "RegExpObject.h" -#include "ArrayObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/RegExpObject.h" +#include "runtime/ArrayObject.h" +#include "runtime/NativeFunctionObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSet.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSet.cpp similarity index 98% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSet.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSet.cpp index 6daab51..31c6823 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSet.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSet.cpp @@ -18,13 +18,13 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "SetObject.h" -#include "IteratorObject.h" -#include "NativeFunctionObject.h" -#include "ToStringRecursionPreventer.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/SetObject.h" +#include "runtime/IteratorObject.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/ToStringRecursionPreventer.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSharedArrayBuffer.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSharedArrayBuffer.cpp similarity index 97% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSharedArrayBuffer.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSharedArrayBuffer.cpp index 1aaba1c..fc4ddb0 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSharedArrayBuffer.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSharedArrayBuffer.cpp @@ -20,12 +20,11 @@ #if defined(ENABLE_THREADING) #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "NativeFunctionObject.h" -#include "ArrayBufferObject.h" -#include "SharedArrayBufferObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/SharedArrayBufferObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinString.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinString.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinString.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinString.cpp index ac6e31d..0f5ebb4 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinString.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinString.cpp @@ -18,17 +18,17 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "StringObject.h" -#include "ErrorObject.h" -#include "RegExpObject.h" -#include "ArrayObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/StringObject.h" +#include "runtime/ErrorObject.h" +#include "runtime/RegExpObject.h" +#include "runtime/ArrayObject.h" +#include "runtime/NativeFunctionObject.h" #if defined(ENABLE_ICU) && defined(ENABLE_INTL) -#include "Intl.h" -#include "IntlCollator.h" +#include "intl/Intl.h" +#include "intl/IntlCollator.h" #endif #include "WTFBridge.h" diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSymbol.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSymbol.cpp similarity index 98% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSymbol.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSymbol.cpp index 1a555d0..5e848f6 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSymbol.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSymbol.cpp @@ -18,12 +18,12 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "SymbolObject.h" -#include "NativeFunctionObject.h" -#include "ToStringRecursionPreventer.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/SymbolObject.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/ToStringRecursionPreventer.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinTypedArray.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinTypedArray.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinTypedArray.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinTypedArray.cpp index ff778c2..4b607e2 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinTypedArray.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinTypedArray.cpp @@ -18,13 +18,13 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "Object.h" -#include "TypedArrayObject.h" -#include "IteratorObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/Object.h" +#include "runtime/TypedArrayObject.h" +#include "runtime/IteratorObject.h" +#include "runtime/NativeFunctionObject.h" namespace Escargot { @@ -234,7 +234,7 @@ static Value builtinTypedArrayLengthGetter(ExecutionState& state, Value thisValu static void initializeTypedArrayFromTypedArray(ExecutionState& state, TypedArrayObject* obj, TypedArrayObject* srcArray) { - ArrayBufferObject* srcData = srcArray->buffer(); + ArrayBuffer* srcData = srcArray->buffer(); srcData->throwTypeErrorIfDetached(state); size_t elementLength = srcArray->arrayLength(); @@ -290,7 +290,7 @@ static void initializeTypedArrayFromTypedArray(ExecutionState& state, TypedArray obj->setBuffer(data, 0, byteLength, elementLength); } -static void initializeTypedArrayFromArrayBuffer(ExecutionState& state, TypedArrayObject* obj, ArrayBufferObject* buffer, const Value& byteOffset, const Value& length) +static void initializeTypedArrayFromArrayBuffer(ExecutionState& state, TypedArrayObject* obj, ArrayBuffer* buffer, const Value& byteOffset, const Value& length) { size_t elementSize = obj->elementSize(); uint64_t offset = byteOffset.toIndex(state); @@ -389,10 +389,10 @@ static Value builtinTypedArrayConstructor(ExecutionState& state, Value thisValue if (argObj->isTypedArrayObject()) { initializeTypedArrayFromTypedArray(state, obj, argObj->asTypedArrayObject()); - } else if (argObj->isArrayBufferObject()) { + } else if (argObj->isArrayBuffer()) { Value byteOffset = (argc > 1) ? argv[1] : Value(); Value length = (argc > 2) ? argv[2] : Value(); - initializeTypedArrayFromArrayBuffer(state, obj, argObj->asArrayBufferObject(), byteOffset, length); + initializeTypedArrayFromArrayBuffer(state, obj, argObj->asArrayBuffer(), byteOffset, length); } else { Value usingIterator = Object::getMethod(state, argObj, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator)); if (!usingIterator.isUndefined()) { @@ -436,7 +436,7 @@ static Value builtinTypedArrayCopyWithin(ExecutionState& state, Value thisValue, // If count > 0, then if (count > 0) { // Let buffer be O.[[ViewedArrayBuffer]]. - ArrayBufferObject* buffer = O->buffer(); + ArrayBuffer* buffer = O->buffer(); // If IsDetachedBuffer(buffer) is true, throw a TypeError exception. buffer->throwTypeErrorIfDetached(state); // Let typedArrayName be the String value of O.[[TypedArrayName]]. @@ -690,7 +690,7 @@ static Value builtinTypedArraySet(ExecutionState& state, Value thisValue, size_t auto typedArrayType = target->typedArrayType(); bool isBigIntArray = typedArrayType == TypedArrayType::BigInt64 || typedArrayType == TypedArrayType::BigUint64; - ArrayBufferObject* targetBuffer = target->buffer(); + ArrayBuffer* targetBuffer = target->buffer(); targetBuffer->throwTypeErrorIfDetached(state); size_t targetLength = target->arrayLength(); size_t targetElementSize = target->elementSize(); @@ -729,7 +729,7 @@ static Value builtinTypedArraySet(ExecutionState& state, Value thisValue, size_t // 22.2.3.23.2%TypedArray%.prototype.set ( typedArray [ , offset ] ) ASSERT(src->isTypedArrayObject()); TypedArrayObject* srcTypedArray = src->asTypedArrayObject(); - ArrayBufferObject* srcBuffer = srcTypedArray->buffer(); + ArrayBuffer* srcBuffer = srcTypedArray->buffer(); srcBuffer->throwTypeErrorIfDetached(state); size_t srcElementSize = srcTypedArray->elementSize(); @@ -834,7 +834,7 @@ static Value builtinTypedArraySort(ExecutionState& state, Value thisValue, size_ // Let O be ToObject(this value). RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, sort); // Let buffer be TypedArrayObject::validateTypedArray(obj). - ArrayBufferObject* buffer = TypedArrayObject::validateTypedArray(state, O); + ArrayBuffer* buffer = TypedArrayObject::validateTypedArray(state, O); // Let len be the value of O’s [[ArrayLength]] internal slot. int64_t len = O->asTypedArrayObject()->arrayLength(); @@ -889,7 +889,7 @@ static Value builtinTypedArraySubArray(ExecutionState& state, Value thisValue, s RESOLVE_THIS_BINDING_TO_TYPEDARRAY(O, TypedArray, subarray); // Let buffer be O.[[ViewedArrayBuffer]]. - ArrayBufferObject* buffer = O->buffer(); + ArrayBuffer* buffer = O->buffer(); // Let srcLength be O.[[ArrayLength]]. double srcLength = O->arrayLength(); // Let relativeBegin be ToInteger(begin). @@ -1450,9 +1450,9 @@ static Value builtinTypedArraySlice(ExecutionState& state, Value thisValue, size } } else if (count > 0) { // Else if count > 0, - ArrayBufferObject* srcBuffer = O->buffer(); + ArrayBuffer* srcBuffer = O->buffer(); srcBuffer->throwTypeErrorIfDetached(state); - ArrayBufferObject* targetBuffer = target->buffer(); + ArrayBuffer* targetBuffer = target->buffer(); size_t elementSize = O->elementSize(); size_t srcByteOffset = O->byteOffset(); diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakMap.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakMap.cpp similarity index 97% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakMap.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakMap.cpp index 56b67d5..e272011 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakMap.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakMap.cpp @@ -18,13 +18,13 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "WeakMapObject.h" -#include "IteratorObject.h" -#include "NativeFunctionObject.h" -#include "ToStringRecursionPreventer.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/WeakMapObject.h" +#include "runtime/IteratorObject.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/ToStringRecursionPreventer.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakRef.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakRef.cpp similarity index 96% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakRef.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakRef.cpp index 6bb73bb..b5c122e 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakRef.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakRef.cpp @@ -18,11 +18,11 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "WeakRefObject.h" -#include "NativeFunctionObject.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/WeakRefObject.h" +#include "runtime/NativeFunctionObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakSet.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakSet.cpp similarity index 97% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakSet.cpp rename to lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakSet.cpp index a60f2f3..a73d967 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakSet.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakSet.cpp @@ -18,13 +18,13 @@ */ #include "Escargot.h" -#include "GlobalObject.h" -#include "Context.h" -#include "VMInstance.h" -#include "WeakSetObject.h" -#include "IteratorObject.h" -#include "NativeFunctionObject.h" -#include "ToStringRecursionPreventer.h" +#include "runtime/GlobalObject.h" +#include "runtime/Context.h" +#include "runtime/VMInstance.h" +#include "runtime/WeakSetObject.h" +#include "runtime/IteratorObject.h" +#include "runtime/NativeFunctionObject.h" +#include "runtime/ToStringRecursionPreventer.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/codecache/CodeCacheReaderWriter.cpp b/lwnode/code/escargotshim/deps/escargot/src/codecache/CodeCacheReaderWriter.cpp index 31e4b6a..1c284c6 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/codecache/CodeCacheReaderWriter.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/codecache/CodeCacheReaderWriter.cpp @@ -27,7 +27,7 @@ #include "parser/CodeBlock.h" #include "interpreter/ByteCode.h" #include "runtime/Context.h" -#include "runtime/VMInstance.h" +#include "runtime/ThreadLocal.h" #include "runtime/ObjectStructurePropertyName.h" namespace Escargot { @@ -867,7 +867,7 @@ ByteCodeBlock* CodeCacheReader::loadByteCodeBlock(Context* context, InterpretedC size = m_buffer.get(); bigIntData.resizeWithUninitializedValues(size); for (size_t i = 0; i < size; i++) { - bigIntData[i] = new BigInt(m_buffer.getBF(VMInstance::bfContext())); + bigIntData[i] = new BigInt(m_buffer.getBF(ThreadLocal::bfContext())); } // ByteCodeBlock::m_code bytecode stream diff --git a/lwnode/code/escargotshim/deps/escargot/src/interpreter/ByteCodeInterpreter.cpp b/lwnode/code/escargotshim/deps/escargot/src/interpreter/ByteCodeInterpreter.cpp index fbb0c18..22952e7 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/interpreter/ByteCodeInterpreter.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/interpreter/ByteCodeInterpreter.cpp @@ -20,6 +20,8 @@ #include "Escargot.h" #include "ByteCode.h" #include "ByteCodeInterpreter.h" +#include "runtime/Global.h" +#include "runtime/Platform.h" #include "runtime/Environment.h" #include "runtime/EnvironmentRecord.h" #include "runtime/FunctionObject.h" @@ -3420,8 +3422,8 @@ NEVER_INLINE void ByteCodeInterpreter::callFunctionComplexCase(ExecutionState& s // Perform ! PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected). innerPromiseCapability.m_promise->asPromiseObject()->then(state, onFulfilled, onRejected); - state.context()->vmInstance()->platform()->hostImportModuleDynamically(byteCodeBlock->m_codeBlock->context(), - referencingScriptOrModule, specifierString, innerPromiseCapability.m_promise->asPromiseObject()); + Global::platform()->hostImportModuleDynamically(byteCodeBlock->m_codeBlock->context(), + referencingScriptOrModule, specifierString, innerPromiseCapability.m_promise->asPromiseObject()); // Return promiseCapability.[[Promise]]. registerFile[code->m_resultIndex] = promiseCapability.m_promise; diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/Intl.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.cpp rename to lwnode/code/escargotshim/deps/escargot/src/intl/Intl.cpp index 533e1e8..c7e236a 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/intl/Intl.cpp @@ -49,9 +49,9 @@ #include "runtime/Value.h" #include "runtime/Object.h" #include "runtime/ArrayObject.h" -#include "runtime/Intl.h" #include "runtime/VMInstance.h" -#include "runtime/IntlLocale.h" +#include "Intl.h" +#include "IntlLocale.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.h b/lwnode/code/escargotshim/deps/escargot/src/intl/Intl.h similarity index 100% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.h rename to lwnode/code/escargotshim/deps/escargot/src/intl/Intl.h diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.cpp rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.cpp index 5557200..2cf2a9a 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.cpp @@ -44,12 +44,12 @@ */ #include "Escargot.h" -#include "Context.h" -#include "ExecutionState.h" -#include "Value.h" +#include "runtime/Context.h" +#include "runtime/ExecutionState.h" +#include "runtime/Value.h" +#include "runtime/VMInstance.h" #include "Intl.h" #include "IntlCollator.h" -#include "VMInstance.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.h similarity index 100% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.h rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.h diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.cpp rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.cpp index b3d7f50..3c0926a 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.cpp @@ -44,14 +44,14 @@ */ #include "Escargot.h" -#include "Context.h" -#include "ExecutionState.h" -#include "VMInstance.h" -#include "Value.h" +#include "runtime/Context.h" +#include "runtime/ExecutionState.h" +#include "runtime/VMInstance.h" +#include "runtime/Value.h" +#include "runtime/DateObject.h" +#include "runtime/ArrayObject.h" #include "Intl.h" #include "IntlDateTimeFormat.h" -#include "DateObject.h" -#include "ArrayObject.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.h similarity index 100% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.h rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.h diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.cpp rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.cpp index ff0efa6..cf24b39 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.cpp @@ -19,9 +19,9 @@ */ #include "Escargot.h" -#include "Context.h" -#include "ExecutionState.h" -#include "Value.h" +#include "runtime/Context.h" +#include "runtime/ExecutionState.h" +#include "runtime/Value.h" #include "Intl.h" #include "IntlLocale.h" diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.h similarity index 100% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.h rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.h diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.cpp similarity index 99% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.cpp rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.cpp index 6e96d0b..21454f7 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.cpp @@ -44,13 +44,13 @@ */ #include "Escargot.h" -#include "Context.h" -#include "ExecutionState.h" -#include "Value.h" +#include "runtime/Context.h" +#include "runtime/ExecutionState.h" +#include "runtime/Value.h" +#include "runtime/ArrayObject.h" +#include "runtime/VMInstance.h" #include "Intl.h" #include "IntlNumberFormat.h" -#include "ArrayObject.h" -#include "VMInstance.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.h similarity index 100% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.h rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.h diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.cpp similarity index 98% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.cpp rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.cpp index 11571b5..5561740 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.cpp @@ -19,12 +19,12 @@ */ #include "Escargot.h" -#include "Context.h" -#include "ExecutionState.h" -#include "Value.h" +#include "runtime/Context.h" +#include "runtime/ExecutionState.h" +#include "runtime/Value.h" +#include "runtime/VMInstance.h" #include "Intl.h" #include "IntlPluralRules.h" -#include "VMInstance.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.h similarity index 100% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.h rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.h diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.cpp similarity index 98% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.cpp rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.cpp index e4336d5..a4619fa 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.cpp @@ -19,14 +19,14 @@ */ #include "Escargot.h" -#include "Context.h" -#include "ExecutionState.h" -#include "Value.h" +#include "runtime/Context.h" +#include "runtime/ExecutionState.h" +#include "runtime/Value.h" +#include "runtime/DateObject.h" +#include "runtime/ArrayObject.h" +#include "runtime/VMInstance.h" #include "Intl.h" #include "IntlRelativeTimeFormat.h" -#include "DateObject.h" -#include "ArrayObject.h" -#include "VMInstance.h" namespace Escargot { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.h similarity index 100% rename from lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.h rename to lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.h diff --git a/lwnode/code/escargotshim/deps/escargot/src/parser/Script.cpp b/lwnode/code/escargotshim/deps/escargot/src/parser/Script.cpp index 776af78..2e13091 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/parser/Script.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/parser/Script.cpp @@ -24,8 +24,10 @@ #include "interpreter/ByteCodeInterpreter.h" #include "parser/ast/Node.h" #include "runtime/Context.h" +#include "runtime/Global.h" #include "runtime/Environment.h" #include "runtime/EnvironmentRecord.h" +#include "runtime/Platform.h" #include "runtime/ErrorObject.h" #include "runtime/ExtendedNativeFunctionObject.h" #include "runtime/SandBox.h" @@ -80,12 +82,12 @@ Context* Script::context() Script* Script::loadModuleFromScript(ExecutionState& state, String* src) { - Platform::LoadModuleResult result = context()->vmInstance()->platform()->onLoadModule(context(), this, src); + Platform::LoadModuleResult result = Global::platform()->onLoadModule(context(), this, src); if (!result.script) { ErrorObject::throwBuiltinError(state, (ErrorObject::Code)result.errorCode, result.errorMessage->toNonGCUTF8StringData().data()); } if (!result.script->moduleData()->m_didCallLoadedCallback) { - context()->vmInstance()->platform()->didLoadModule(context(), this, result.script.value()); + Global::platform()->didLoadModule(context(), this, result.script.value()); result.script->moduleData()->m_didCallLoadedCallback = true; } return result.script.value(); @@ -323,7 +325,7 @@ Value Script::execute(ExecutionState& state, bool isExecuteOnEvalFunction, bool if (isModule()) { if (!moduleData()->m_didCallLoadedCallback) { - context()->vmInstance()->platform()->didLoadModule(context(), nullptr, this); + Global::platform()->didLoadModule(context(), nullptr, this); moduleData()->m_didCallLoadedCallback = true; } diff --git a/lwnode/code/escargotshim/deps/escargot/src/parser/esprima_cpp/esprima.cpp b/lwnode/code/escargotshim/deps/escargot/src/parser/esprima_cpp/esprima.cpp index 22af647..d63fa92 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/parser/esprima_cpp/esprima.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/parser/esprima_cpp/esprima.cpp @@ -418,22 +418,29 @@ public: VectorWithInlineStorage<8, SyntaxNode, std::allocator>& params = paramsResult.params; bool hasParameterOtherThanIdentifier = false; + bool seenDefaultParameter = false; for (size_t i = 0; i < params.size(); i++) { switch (params[i]->type()) { - case Identifier: { - if (!hasParameterOtherThanIdentifier) { + case Identifier: + if (LIKELY(!seenDefaultParameter)) { this->currentScopeContext->m_functionLength++; } break; - } case AssignmentPattern: + seenDefaultParameter = true; + hasParameterOtherThanIdentifier = true; + break; case ArrayPattern: case ObjectPattern: - case RestElement: { + hasParameterOtherThanIdentifier = true; + if (LIKELY(!seenDefaultParameter)) { + this->currentScopeContext->m_functionLength++; + } + break; + case RestElement: hasParameterOtherThanIdentifier = true; break; - } default: { RELEASE_ASSERT_NOT_REACHED(); } diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.cpp new file mode 100644 index 0000000..3176a12 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include "Escargot.h" +#include "runtime/VMInstance.h" +#include "runtime/BackingStore.h" +#include "runtime/ArrayBuffer.h" +#include "runtime/TypedArrayInlines.h" +#include "runtime/ArrayBufferObject.h" +#include "runtime/SharedArrayBufferObject.h" + +namespace Escargot { + +unsigned TypedArrayHelper::elementSizeTable[11] = { 1, 2, 4, 1, 2, 4, 1, 4, 8, 8, 8 }; + +ArrayBuffer::ArrayBuffer(ExecutionState& state, Object* proto) + : Object(state, proto, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER) + , m_mayPointsSharedBackingStore(false) +{ +} + +// $24.1.1.6 +Value ArrayBuffer::getValueFromBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, bool isLittleEndian) +{ + // If isLittleEndian is not present, set isLittleEndian to either true or false. + ASSERT(byteLength()); + size_t elemSize = TypedArrayHelper::elementSize(type); + ASSERT(byteindex + elemSize <= byteLength()); + uint8_t* rawStart = data() + byteindex; + if (LIKELY(isLittleEndian)) { + return TypedArrayHelper::rawBytesToNumber(state, type, rawStart); + } else { + uint8_t* rawBytes = ALLOCA(8, uint8_t, state); + for (size_t i = 0; i < elemSize; i++) { + rawBytes[elemSize - i - 1] = rawStart[i]; + } + return TypedArrayHelper::rawBytesToNumber(state, type, rawBytes); + } +} + +// $24.1.1.8 +void ArrayBuffer::setValueInBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, const Value& val, bool isLittleEndian) +{ + // If isLittleEndian is not present, set isLittleEndian to either true or false. + ASSERT(byteLength()); + size_t elemSize = TypedArrayHelper::elementSize(type); + ASSERT(byteindex + elemSize <= byteLength()); + uint8_t* rawStart = data() + byteindex; + uint8_t* rawBytes = ALLOCA(8, uint8_t, state); + TypedArrayHelper::numberToRawBytes(state, type, val, rawBytes); + if (LIKELY(isLittleEndian)) { + memcpy(rawStart, rawBytes, elemSize); + } else { + for (size_t i = 0; i < elemSize; i++) { + rawStart[i] = rawBytes[elemSize - i - 1]; + } + } +} +} // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.h new file mode 100644 index 0000000..0a7efbd --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotArrayBuffer__ +#define __EscargotArrayBuffer__ + +#include "runtime/Context.h" +#include "runtime/BackingStore.h" + +namespace Escargot { + +enum class TypedArrayType : unsigned { + Int8 = 0, + Int16, + Int32, + Uint8, + Uint16, + Uint32, + Uint8Clamped, + Float32, + Float64, + BigInt64, + BigUint64 +}; + +class ArrayBuffer : public Object { + friend void initializeCustomAllocators(); + +public: + static const uint64_t maxArrayBufferSize = 210000000; + + explicit ArrayBuffer(ExecutionState& state, Object* proto); + + virtual bool isArrayBuffer() const override + { + return true; + } + + Optional backingStore() + { + if (m_backingStore) { + m_mayPointsSharedBackingStore = true; + } + return m_backingStore; + } + + ALWAYS_INLINE uint8_t* data() + { + if (LIKELY(m_backingStore)) { + return reinterpret_cast(m_backingStore->data()); + } + return nullptr; + } + + ALWAYS_INLINE size_t byteLength() + { + if (LIKELY(m_backingStore)) { + return m_backingStore->byteLength(); + } + return 0; + } + + // $24.1.1.6 + Value getValueFromBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, bool isLittleEndian = true); + + // $24.1.1.8 + void setValueInBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, const Value& val, bool isLittleEndian = true); + + ALWAYS_INLINE bool isDetachedBuffer() + { + return (data() == nullptr); + } + + ALWAYS_INLINE void throwTypeErrorIfDetached(ExecutionState& state) + { + if (UNLIKELY(isDetachedBuffer())) { + ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().constructor.string(), ErrorObject::Messages::GlobalObject_DetachedBuffer); + } + } + + void fillData(const uint8_t* newData, size_t length) + { + ASSERT(!isDetachedBuffer()); + memcpy(data(), newData, length); + } + + void* operator new(size_t size) = delete; + void* operator new[](size_t size) = delete; + +protected: + static inline void fillGCDescriptor(GC_word* desc) + { + Object::fillGCDescriptor(desc); + GC_set_bit(desc, GC_WORD_OFFSET(ArrayBuffer, m_backingStore)); + } + + bool m_mayPointsSharedBackingStore; + Optional m_backingStore; +}; + +class ArrayBufferView : public Object { +public: + explicit ArrayBufferView(ExecutionState& state, Object* proto) + : Object(state, proto, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER) + , m_buffer(nullptr) + , m_byteLength(0) + , m_byteOffset(0) + , m_arrayLength(0) + { + } + + ALWAYS_INLINE ArrayBuffer* buffer() { return m_buffer; } + ALWAYS_INLINE size_t byteLength() { return m_byteLength; } + ALWAYS_INLINE size_t byteOffset() { return m_byteOffset; } + ALWAYS_INLINE size_t arrayLength() { return m_arrayLength; } + ALWAYS_INLINE uint8_t* rawBuffer() + { + return m_buffer ? (uint8_t*)(m_buffer->data() + m_byteOffset) : nullptr; + } + + ALWAYS_INLINE void setBuffer(ArrayBuffer* bo, size_t byteOffset, size_t byteLength, size_t arrayLength) + { + m_buffer = bo; + m_byteOffset = byteOffset; + m_byteLength = byteLength; + m_arrayLength = arrayLength; + } + + ALWAYS_INLINE void setBuffer(ArrayBuffer* bo, size_t byteOffset, size_t byteLength) + { + m_buffer = bo; + m_byteOffset = byteOffset; + m_byteLength = byteLength; + } + + virtual bool isArrayBufferView() const override + { + return true; + } + + void* operator new(size_t size) + { + static MAY_THREAD_LOCAL bool typeInited = false; + static MAY_THREAD_LOCAL GC_descr descr; + if (!typeInited) { + GC_word obj_bitmap[GC_BITMAP_SIZE(ArrayBufferView)] = { 0 }; + Object::fillGCDescriptor(obj_bitmap); + GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ArrayBufferView, m_buffer)); + descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(ArrayBufferView)); + typeInited = true; + } + return GC_MALLOC_EXPLICITLY_TYPED(size, descr); + } + void* operator new[](size_t size) = delete; + +private: + ArrayBuffer* m_buffer; + size_t m_byteLength; + size_t m_byteOffset; + size_t m_arrayLength; +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBufferObject.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBufferObject.cpp index fceceef..f0ff07f 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBufferObject.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBufferObject.cpp @@ -25,8 +25,6 @@ namespace Escargot { -unsigned TypedArrayHelper::elementSizeTable[11] = { 1, 2, 4, 1, 2, 4, 1, 4, 8, 8, 8 }; - ArrayBufferObject* ArrayBufferObject::allocateArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength) { // https://www.ecma-international.org/ecma-262/10.0/#sec-allocatearraybuffer @@ -34,7 +32,7 @@ ArrayBufferObject* ArrayBufferObject::allocateArrayBuffer(ExecutionState& state, return constructorRealm->globalObject()->arrayBufferPrototype(); }); - if (byteLength >= ArrayBufferObject::maxArrayBufferSize) { + if (byteLength >= ArrayBuffer::maxArrayBufferSize) { ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().ArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferSize); } @@ -44,7 +42,7 @@ ArrayBufferObject* ArrayBufferObject::allocateArrayBuffer(ExecutionState& state, return obj; } -ArrayBufferObject* ArrayBufferObject::cloneArrayBuffer(ExecutionState& state, ArrayBufferObject* srcBuffer, size_t srcByteOffset, uint64_t srcLength, Object* constructor) +ArrayBufferObject* ArrayBufferObject::cloneArrayBuffer(ExecutionState& state, ArrayBuffer* srcBuffer, size_t srcByteOffset, uint64_t srcLength, Object* constructor) { // https://www.ecma-international.org/ecma-262/10.0/#sec-clonearraybuffer ASSERT(constructor->isConstructor()); @@ -63,8 +61,7 @@ ArrayBufferObject::ArrayBufferObject(ExecutionState& state) } ArrayBufferObject::ArrayBufferObject(ExecutionState& state, Object* proto) - : Object(state, proto, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER) - , m_mayPointsSharedBackingStore(false) + : ArrayBuffer(state, proto) { } @@ -72,7 +69,7 @@ void ArrayBufferObject::allocateBuffer(ExecutionState& state, size_t byteLength) { detachArrayBuffer(); - ASSERT(byteLength < ArrayBufferObject::maxArrayBufferSize); + ASSERT(byteLength < ArrayBuffer::maxArrayBufferSize); const size_t ratio = std::max((size_t)GC_get_free_space_divisor() / 6, (size_t)1); if (byteLength > (GC_get_heap_size() / ratio)) { @@ -85,7 +82,7 @@ void ArrayBufferObject::allocateBuffer(ExecutionState& state, size_t byteLength) GC_invoke_finalizers(); } - m_backingStore = new BackingStore(state.context()->vmInstance(), byteLength); + m_backingStore = new BackingStore(byteLength); } void ArrayBufferObject::attachBuffer(BackingStore* backingStore) @@ -105,7 +102,7 @@ void ArrayBufferObject::detachArrayBuffer() if (m_backingStore && !m_mayPointsSharedBackingStore) { // if backingstore is definitely not shared, we deallocate the backingstore immediately. - m_backingStore.value()->deallocate(); + delete m_backingStore.value(); } m_backingStore.reset(); m_mayPointsSharedBackingStore = false; @@ -118,8 +115,7 @@ void* ArrayBufferObject::operator new(size_t size) static MAY_THREAD_LOCAL GC_descr descr; if (!typeInited) { GC_word obj_bitmap[GC_BITMAP_SIZE(ArrayBufferObject)] = { 0 }; - Object::fillGCDescriptor(obj_bitmap); - GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ArrayBufferObject, m_backingStore)); + ArrayBuffer::fillGCDescriptor(obj_bitmap); descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(ArrayBufferObject)); typeInited = true; } @@ -128,42 +124,4 @@ void* ArrayBufferObject::operator new(size_t size) return CustomAllocator().allocate(1); #endif } - -// $24.1.1.6 -Value ArrayBufferObject::getValueFromBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, bool isLittleEndian) -{ - // If isLittleEndian is not present, set isLittleEndian to either true or false. - ASSERT(byteLength()); - size_t elemSize = TypedArrayHelper::elementSize(type); - ASSERT(byteindex + elemSize <= byteLength()); - uint8_t* rawStart = data() + byteindex; - if (LIKELY(isLittleEndian)) { - return TypedArrayHelper::rawBytesToNumber(state, type, rawStart); - } else { - uint8_t* rawBytes = ALLOCA(8, uint8_t, state); - for (size_t i = 0; i < elemSize; i++) { - rawBytes[elemSize - i - 1] = rawStart[i]; - } - return TypedArrayHelper::rawBytesToNumber(state, type, rawBytes); - } -} - -// $24.1.1.8 -void ArrayBufferObject::setValueInBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, const Value& val, bool isLittleEndian) -{ - // If isLittleEndian is not present, set isLittleEndian to either true or false. - ASSERT(byteLength()); - size_t elemSize = TypedArrayHelper::elementSize(type); - ASSERT(byteindex + elemSize <= byteLength()); - uint8_t* rawStart = data() + byteindex; - uint8_t* rawBytes = ALLOCA(8, uint8_t, state); - TypedArrayHelper::numberToRawBytes(state, type, val, rawBytes); - if (LIKELY(isLittleEndian)) { - memcpy(rawStart, rawBytes, elemSize); - } else { - for (size_t i = 0; i < elemSize; i++) { - rawStart[i] = rawBytes[elemSize - i - 1]; - } - } -} } // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBufferObject.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBufferObject.h index 3f7fb7f..54d1202 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBufferObject.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBufferObject.h @@ -20,26 +20,11 @@ #ifndef __EscargotArrayBufferObject__ #define __EscargotArrayBufferObject__ -#include "runtime/Context.h" -#include "runtime/BackingStore.h" +#include "runtime/ArrayBuffer.h" namespace Escargot { -enum class TypedArrayType : unsigned { - Int8 = 0, - Int16, - Int32, - Uint8, - Uint16, - Uint32, - Uint8Clamped, - Float32, - Float64, - BigInt64, - BigUint64 -}; - -class ArrayBufferObject : public Object { +class ArrayBufferObject : public ArrayBuffer { friend void initializeCustomAllocators(); friend int getValidValueInArrayBufferObject(void* ptr, GC_mark_custom_result* arr); @@ -48,132 +33,21 @@ public: explicit ArrayBufferObject(ExecutionState& state, Object* proto); static ArrayBufferObject* allocateArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength); - static ArrayBufferObject* cloneArrayBuffer(ExecutionState& state, ArrayBufferObject* srcBuffer, size_t srcByteOffset, uint64_t srcLength, Object* constructor); - - static const uint64_t maxArrayBufferSize = 210000000; + static ArrayBufferObject* cloneArrayBuffer(ExecutionState& state, ArrayBuffer* srcBuffer, size_t srcByteOffset, uint64_t srcLength, Object* constructor); void allocateBuffer(ExecutionState& state, size_t bytelength); void attachBuffer(BackingStore* backingStore); void detachArrayBuffer(); - Optional backingStore() - { - if (m_backingStore) { - m_mayPointsSharedBackingStore = true; - } - return m_backingStore; - } virtual bool isArrayBufferObject() const { return true; } - ALWAYS_INLINE uint8_t* data() - { - if (LIKELY(m_backingStore)) { - return reinterpret_cast(m_backingStore->data()); - } - return nullptr; - } - ALWAYS_INLINE size_t byteLength() - { - if (LIKELY(m_backingStore)) { - return m_backingStore->byteLength(); - } - return 0; - } - // $24.1.1.6 - Value getValueFromBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, bool isLittleEndian = true); - // $24.1.1.8 - void setValueInBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, const Value& val, bool isLittleEndian = true); - - ALWAYS_INLINE bool isDetachedBuffer() - { - return (data() == nullptr); - } - - ALWAYS_INLINE void throwTypeErrorIfDetached(ExecutionState& state) - { - if (UNLIKELY(isDetachedBuffer())) { - ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().constructor.string(), ErrorObject::Messages::GlobalObject_DetachedBuffer); - } - } - - void fillData(const uint8_t* newData, size_t length) - { - ASSERT(!isDetachedBuffer()); - memcpy(data(), newData, length); - } - void* operator new(size_t size); void* operator new[](size_t size) = delete; - -protected: - bool m_mayPointsSharedBackingStore; - Optional m_backingStore; }; -class ArrayBufferView : public Object { -public: - explicit ArrayBufferView(ExecutionState& state, Object* proto) - : Object(state, proto, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER) - , m_buffer(nullptr) - , m_byteLength(0) - , m_byteOffset(0) - , m_arrayLength(0) - { - } - - ALWAYS_INLINE ArrayBufferObject* buffer() { return m_buffer; } - ALWAYS_INLINE size_t byteLength() { return m_byteLength; } - ALWAYS_INLINE size_t byteOffset() { return m_byteOffset; } - ALWAYS_INLINE size_t arrayLength() { return m_arrayLength; } - ALWAYS_INLINE uint8_t* rawBuffer() - { - return m_buffer ? (uint8_t*)(m_buffer->data() + m_byteOffset) : nullptr; - } - - ALWAYS_INLINE void setBuffer(ArrayBufferObject* bo, size_t byteOffset, size_t byteLength, size_t arrayLength) - { - m_buffer = bo; - m_byteOffset = byteOffset; - m_byteLength = byteLength; - m_arrayLength = arrayLength; - } - - ALWAYS_INLINE void setBuffer(ArrayBufferObject* bo, size_t byteOffset, size_t byteLength) - { - m_buffer = bo; - m_byteOffset = byteOffset; - m_byteLength = byteLength; - } - - virtual bool isArrayBufferView() const override - { - return true; - } - - void* operator new(size_t size) - { - static MAY_THREAD_LOCAL bool typeInited = false; - static MAY_THREAD_LOCAL GC_descr descr; - if (!typeInited) { - GC_word obj_bitmap[GC_BITMAP_SIZE(ArrayBufferView)] = { 0 }; - Object::fillGCDescriptor(obj_bitmap); - GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ArrayBufferView, m_buffer)); - descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(ArrayBufferView)); - typeInited = true; - } - return GC_MALLOC_EXPLICITLY_TYPED(size, descr); - } - void* operator new[](size_t size) = delete; - -private: - ArrayBufferObject* m_buffer; - size_t m_byteLength; - size_t m_byteOffset; - size_t m_arrayLength; -}; } // namespace Escargot #endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayObject.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayObject.h index d9e5981..bd1c875 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayObject.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayObject.h @@ -33,6 +33,7 @@ class ArrayIteratorObject; class ArrayObject : public Object { friend class VMInstance; + friend class Global; friend class ByteCodeInterpreter; friend class EnumerateObjectWithDestruction; friend class EnumerateObjectWithIteration; @@ -97,7 +98,7 @@ protected: #endif { // dummy default constructor - // only called by VMInstance::initialize to set tag value + // only called by Global::initialize to set tag value } private: @@ -141,7 +142,7 @@ private: }; class ArrayPrototypeObject : public ArrayObject { - friend class VMInstance; + friend class Global; public: explicit ArrayPrototypeObject(ExecutionState& state); @@ -151,7 +152,7 @@ private: : ArrayObject() { // dummy default constructor - // only called by VMInstance::initialize to set tag value + // only called by Global::initialize to set tag value } }; diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/BackingStore.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/BackingStore.cpp index 6b512d1..7adaefa 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/BackingStore.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/BackingStore.cpp @@ -19,7 +19,7 @@ #include "Escargot.h" #include "BackingStore.h" -#include "runtime/VMInstance.h" +#include "runtime/Global.h" #include "runtime/Platform.h" namespace Escargot { @@ -40,18 +40,28 @@ void* BackingStore::operator new(size_t size) static void defaultPlatformBackingStoreDeleter(void* data, size_t length, void* deleterData) { - if (deleterData) { - VMInstance* instance = (VMInstance*)deleterData; - instance->platform()->onFreeArrayBufferObjectDataBuffer(data, length); - } else { - ASSERT(data == nullptr); + if (!!data) { + Global::platform()->onFreeArrayBufferObjectDataBuffer(data, length); } } +BackingStore::~BackingStore() +{ + // Shared Data Block should not be deleted explicitly + ASSERT(!m_isShared); + m_deleter(m_data, m_byteLength, m_deleterData); + GC_REGISTER_FINALIZER_NO_ORDER(this, nullptr, nullptr, nullptr, nullptr); + m_data = nullptr; + m_byteLength = 0; + m_deleter = defaultPlatformBackingStoreDeleter; + m_deleterData = nullptr; + m_isAllocatedByPlatformAllocator = true; +} + BackingStore::BackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback callback, void* callbackData, - bool isShared, bool isAllocatedByPlatformAllocator) + bool isShared) : m_isShared(isShared) - , m_isAllocatedByPlatformAllocator(isAllocatedByPlatformAllocator) + , m_isAllocatedByPlatformAllocator(false) , m_data(data) , m_byteLength(byteLength) , m_deleter(callback) @@ -64,13 +74,14 @@ BackingStore::BackingStore(void* data, size_t byteLength, BackingStoreDeleterCal nullptr, nullptr, nullptr); } -BackingStore::BackingStore(VMInstance* instance, size_t byteLength) - : BackingStore(instance->platform()->onMallocArrayBufferObjectDataBuffer(byteLength), byteLength, - defaultPlatformBackingStoreDeleter, instance, false, true) +BackingStore::BackingStore(size_t byteLength) + : BackingStore(Global::platform()->onMallocArrayBufferObjectDataBuffer(byteLength), byteLength, + defaultPlatformBackingStoreDeleter, nullptr, false) { + m_isAllocatedByPlatformAllocator = true; } -void BackingStore::reallocate(VMInstance* instance, size_t newByteLength) +void BackingStore::reallocate(size_t newByteLength) { // Shared Data Block should not be reallocated ASSERT(!m_isShared); @@ -80,29 +91,16 @@ void BackingStore::reallocate(VMInstance* instance, size_t newByteLength) } if (m_isAllocatedByPlatformAllocator) { - m_data = instance->platform()->onReallocArrayBufferObjectDataBuffer(m_data, m_byteLength, newByteLength); + m_data = Global::platform()->onReallocArrayBufferObjectDataBuffer(m_data, m_byteLength, newByteLength); m_byteLength = newByteLength; } else { m_deleter(m_data, m_byteLength, m_deleterData); - m_data = instance->platform()->onMallocArrayBufferObjectDataBuffer(newByteLength); + m_data = Global::platform()->onMallocArrayBufferObjectDataBuffer(newByteLength); m_deleter = defaultPlatformBackingStoreDeleter; - m_deleterData = instance; + m_deleterData = nullptr; m_byteLength = newByteLength; m_isAllocatedByPlatformAllocator = true; } } -void BackingStore::deallocate() -{ - // Shared Data Block should not be deleted explicitly - ASSERT(!m_isShared); - m_deleter(m_data, m_byteLength, m_deleterData); - GC_REGISTER_FINALIZER_NO_ORDER(this, nullptr, nullptr, nullptr, nullptr); - m_data = nullptr; - m_byteLength = 0; - m_deleter = defaultPlatformBackingStoreDeleter; - m_deleterData = nullptr; - m_isAllocatedByPlatformAllocator = true; -} - } // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/BackingStore.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/BackingStore.h index 272e2a3..fd068fa 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/BackingStore.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/BackingStore.h @@ -22,8 +22,6 @@ namespace Escargot { -class VMInstance; - using BackingStoreDeleterCallback = void (*)(void* data, size_t length, void* deleterData); @@ -31,9 +29,10 @@ class BackingStore : public gc { friend class ArrayBufferObject; public: - BackingStore(VMInstance* instance, size_t byteLength); + BackingStore(size_t byteLength); BackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback callback, - void* callbackData, bool isShared = false, bool isAllocatedByPlatformAllocator = false); + void* callbackData, bool isShared = false); + ~BackingStore(); void* data() const { @@ -50,14 +49,18 @@ public: return m_isShared; } - void reallocate(VMInstance* instance, size_t newByteLength); - void deallocate(); + void* deleterData() const + { + return m_deleterData; + } + + void reallocate(size_t newByteLength); void* operator new(size_t size); void* operator new[](size_t size) = delete; private: - // Indicates whether the backing store was created as Shared Data Block + // Indicates whether the backing store was created for SharedArrayBuffer bool m_isShared; bool m_isAllocatedByPlatformAllocator; void* m_data; diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/BigInt.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/BigInt.cpp index 6a01947..0cf3305 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/BigInt.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/BigInt.cpp @@ -19,7 +19,7 @@ #include "Escargot.h" #include "BigInt.h" -#include "VMInstance.h" +#include "ThreadLocal.h" #include "ErrorObject.h" namespace Escargot { @@ -38,7 +38,7 @@ BigIntData::BigIntData(BigIntData&& src) BigIntData::BigIntData(const double& d) { - bf_init(VMInstance::bfContext(), &m_data); + bf_init(ThreadLocal::bfContext(), &m_data); bf_set_float64(&m_data, d); } @@ -51,7 +51,7 @@ BigIntData::BigIntData(String* src) buffer = (char*)bd.bufferAs8Bit; } else { if (!isAllASCII(bd.bufferAs16Bit, bd.length)) { - bf_init(VMInstance::bfContext(), &m_data); + bf_init(ThreadLocal::bfContext(), &m_data); bf_set_nan(&m_data); return; } @@ -72,7 +72,7 @@ BigIntData::BigIntData(const char* buf, size_t length, int radix) void BigIntData::init(const char* buf, size_t length, int radix) { - bf_init(VMInstance::bfContext(), &m_data); + bf_init(ThreadLocal::bfContext(), &m_data); if (!length) { bf_set_zero(&m_data, 0); return; @@ -155,7 +155,7 @@ void BigInt::initFinalizer() BigInt::BigInt() : m_tag(POINTER_VALUE_BIGINT_TAG_IN_DATA) { - bf_init(VMInstance::bfContext(), &m_bf); + bf_init(ThreadLocal::bfContext(), &m_bf); initFinalizer(); } @@ -266,7 +266,7 @@ String* BigInt::toString(int radix) return String::emptyString; } else { String* ret = String::fromASCII(str, resultLen); - bf_free(VMInstance::bfContext(), str); + bf_free(ThreadLocal::bfContext(), str); return ret; } } @@ -358,7 +358,7 @@ bool BigInt::greaterThanEqual(BigInt* b) BigInt* BigInt::addition(ExecutionState& state, BigInt* b) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_add(&r, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ); if (UNLIKELY(ret)) { bf_delete(&r); @@ -370,7 +370,7 @@ BigInt* BigInt::addition(ExecutionState& state, BigInt* b) BigInt* BigInt::subtraction(ExecutionState& state, BigInt* b) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_sub(&r, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ); if (UNLIKELY(ret)) { bf_delete(&r); @@ -382,7 +382,7 @@ BigInt* BigInt::subtraction(ExecutionState& state, BigInt* b) BigInt* BigInt::multiply(ExecutionState& state, BigInt* b) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_mul(&r, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ); if (UNLIKELY(ret)) { bf_delete(&r); @@ -394,8 +394,8 @@ BigInt* BigInt::multiply(ExecutionState& state, BigInt* b) BigInt* BigInt::division(ExecutionState& state, BigInt* b) { bf_t r, rem; - bf_init(VMInstance::bfContext(), &r); - bf_init(VMInstance::bfContext(), &rem); + bf_init(ThreadLocal::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &rem); int ret = bf_divrem(&r, &rem, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ, BF_RNDZ); bf_delete(&rem); @@ -409,7 +409,7 @@ BigInt* BigInt::division(ExecutionState& state, BigInt* b) BigInt* BigInt::remainder(ExecutionState& state, BigInt* b) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_rem(&r, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ, BF_RNDZ) & BF_ST_INVALID_OP; @@ -423,7 +423,7 @@ BigInt* BigInt::remainder(ExecutionState& state, BigInt* b) BigInt* BigInt::pow(ExecutionState& state, BigInt* b) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_pow(&r, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ); if (UNLIKELY(ret)) { bf_delete(&r); @@ -435,7 +435,7 @@ BigInt* BigInt::pow(ExecutionState& state, BigInt* b) BigInt* BigInt::bitwiseAnd(ExecutionState& state, BigInt* b) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_logic_and(&r, &m_bf, &b->m_bf); if (UNLIKELY(ret)) { bf_delete(&r); @@ -447,7 +447,7 @@ BigInt* BigInt::bitwiseAnd(ExecutionState& state, BigInt* b) BigInt* BigInt::bitwiseOr(ExecutionState& state, BigInt* b) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_logic_or(&r, &m_bf, &b->m_bf); if (UNLIKELY(ret)) { bf_delete(&r); @@ -459,7 +459,7 @@ BigInt* BigInt::bitwiseOr(ExecutionState& state, BigInt* b) BigInt* BigInt::bitwiseXor(ExecutionState& state, BigInt* b) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_logic_xor(&r, &m_bf, &b->m_bf); if (UNLIKELY(ret)) { bf_delete(&r); @@ -471,7 +471,7 @@ BigInt* BigInt::bitwiseXor(ExecutionState& state, BigInt* b) BigInt* BigInt::leftShift(ExecutionState& state, BigInt* src) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); slimb_t v2; #if defined(ESCARGOT_32) @@ -501,7 +501,7 @@ BigInt* BigInt::leftShift(ExecutionState& state, BigInt* src) BigInt* BigInt::rightShift(ExecutionState& state, BigInt* src) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); slimb_t v2; #if defined(ESCARGOT_32) @@ -534,7 +534,7 @@ BigInt* BigInt::rightShift(ExecutionState& state, BigInt* src) BigInt* BigInt::increment(ExecutionState& state) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_add_si(&r, &m_bf, 1, BF_PREC_INF, BF_RNDZ); if (UNLIKELY(ret)) { bf_delete(&r); @@ -546,7 +546,7 @@ BigInt* BigInt::increment(ExecutionState& state) BigInt* BigInt::decrement(ExecutionState& state) { bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_add_si(&r, &m_bf, -1, BF_PREC_INF, BF_RNDZ); if (UNLIKELY(ret)) { bf_delete(&r); @@ -559,7 +559,7 @@ BigInt* BigInt::bitwiseNot(ExecutionState& state) { // The abstract operation BigInt::bitwiseNOT with an argument x of BigInt type returns the one's complement of x; that is, -x - 1. bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_add_si(&r, &m_bf, 1, BF_PREC_INF, BF_RNDZ); bf_neg(&r); @@ -577,7 +577,7 @@ BigInt* BigInt::negativeValue(ExecutionState& state) } bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_set(&r, &m_bf); bf_neg(&r); if (UNLIKELY(ret)) { @@ -596,7 +596,7 @@ BigInt* BigInt::negativeValue() } bf_t r; - bf_init(VMInstance::bfContext(), &r); + bf_init(ThreadLocal::bfContext(), &r); int ret = bf_set(&r, &m_bf); bf_neg(&r); ASSERT(!ret); diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Context.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/Context.cpp index 6b69ff0..efc877a 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/Context.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/Context.cpp @@ -20,6 +20,7 @@ #include "Escargot.h" #include "Context.h" #include "runtime/AtomicString.h" +#include "runtime/ThreadLocal.h" #include "VMInstance.h" #include "GlobalObject.h" #include "StringObject.h" @@ -119,7 +120,7 @@ void Context::setGlobalObjectProxy(Object* newGlobalObjectProxy) ASTAllocator& Context::astAllocator() { - return *VMInstance::astAllocator(); + return *ThreadLocal::astAllocator(); } #ifdef ESCARGOT_DEBUGGER diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/DataViewObject.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/DataViewObject.h index 1d78c53..f989e31 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/DataViewObject.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/DataViewObject.h @@ -53,7 +53,7 @@ public: } bool isLittleEndian = _isLittleEndian.toBoolean(state); - ArrayBufferObject* buffer = this->buffer(); + ArrayBuffer* buffer = this->buffer(); buffer->throwTypeErrorIfDetached(state); size_t viewOffset = byteOffset(); @@ -80,7 +80,7 @@ public: UNUSED_VARIABLE(numericValue); bool isLittleEndian = _isLittleEndian.toBoolean(state); - ArrayBufferObject* buffer = this->buffer(); + ArrayBuffer* buffer = this->buffer(); buffer->throwTypeErrorIfDetached(state); size_t viewOffset = byteOffset(); diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/FunctionTemplate.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/FunctionTemplate.cpp index 9e02cf0..c1d5a6f 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/FunctionTemplate.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/FunctionTemplate.cpp @@ -127,10 +127,16 @@ void FunctionTemplate::updateCallbackFunction(FunctionTemplateRef::NativeFunctio void FunctionTemplate::setName(AtomicString name) { - ASSERT(m_cachedObjectStructure == nullptr); + ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr); m_name = name; } +void FunctionTemplate::setLength(size_t length) +{ + ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr); + m_argumentCount = length; +} + Object* FunctionTemplate::instantiate(Context* ctx) { auto& instantiatedFunctionObjects = ctx->instantiatedFunctionObjects(); @@ -141,7 +147,7 @@ Object* FunctionTemplate::instantiate(Context* ctx) } const size_t functionDefaultPropertyCount = m_isConstructor ? ctx->defaultStructureForFunctionObject()->propertyCount() : ctx->defaultStructureForNotConstructorFunctionObject()->propertyCount(); - if (!m_cachedObjectStructure) { + if (!m_cachedObjectStructure.m_objectStructure) { if (m_isConstructor) { // [prototype, name, length] ASSERT(functionDefaultPropertyCount == 3); @@ -195,7 +201,8 @@ Object* FunctionTemplate::instantiate(Context* ctx) flags |= m_isStrict ? NativeFunctionInfo::Strict : 0; flags |= m_isConstructor ? NativeFunctionInfo::Constructor : 0; - FunctionTemplateNativeFunctionObject* result = new FunctionTemplateNativeFunctionObject(ctx, m_cachedObjectStructure, std::move(objectPropertyValues), NativeFunctionInfo(m_name, m_nativeFunctionData->m_nativeFunction, m_argumentCount, flags)); + FunctionTemplateNativeFunctionObject* result = new FunctionTemplateNativeFunctionObject(ctx, + m_cachedObjectStructure.m_objectStructure, std::move(objectPropertyValues), NativeFunctionInfo(m_name, m_nativeFunctionData->m_nativeFunction, m_argumentCount, flags)); result->setInternalSlotAsPointer(FunctionTemplate::BuiltinFunctionSlot::CallTemplateFunctionDataIndex, m_nativeFunctionData); if (m_isConstructor) { diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/FunctionTemplate.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/FunctionTemplate.h index 501aa5e..81ba50c 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/FunctionTemplate.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/FunctionTemplate.h @@ -55,7 +55,7 @@ public: void inherit(Optional parent) { - ASSERT(!m_cachedObjectStructure); + ASSERT(!m_cachedObjectStructure.m_objectStructure); ASSERT(parent->m_isConstructor); m_parent = parent; } @@ -75,7 +75,9 @@ public: return m_isConstructor; } + // setName and setLength should be called before instantiate void setName(AtomicString name); + void setLength(size_t length); void* operator new(size_t size); void* operator new[](size_t size) = delete; diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Global.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/Global.cpp new file mode 100644 index 0000000..489961a --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/Global.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include "Escargot.h" +#include "runtime/Global.h" +#include "runtime/Platform.h" +#include "runtime/PointerValue.h" +#include "runtime/ArrayObject.h" + +namespace Escargot { + +bool Global::inited; +Platform* Global::g_platform; +#if defined(ENABLE_ATOMICS_GLOBAL_LOCK) +SpinLock Global::g_atomicsLock; +#endif + +void Global::initialize(Platform* platform) +{ + // initialize should be invoked only once in the program + static bool called_once = true; + RELEASE_ASSERT(called_once && !inited); + + ASSERT(!g_platform); + g_platform = platform; + + // initialize PointerValue tag values + // tag values should be initialized once and not changed + PointerValue::g_arrayObjectTag = ArrayObject().getTag(); + PointerValue::g_arrayPrototypeObjectTag = ArrayPrototypeObject().getTag(); + PointerValue::g_objectRareDataTag = ObjectRareData(nullptr).getTag(); + PointerValue::g_doubleInEncodedValueTag = DoubleInEncodedValue(0).getTag(); + + called_once = false; + inited = true; +} + +void Global::finalize() +{ + // finalize should be invoked only once in the program + static bool called_once = true; + RELEASE_ASSERT(called_once && inited); + + delete g_platform; + g_platform = nullptr; + + called_once = false; + inited = false; +} + +Platform* Global::platform() +{ + ASSERT(inited && !!g_platform); + return g_platform; +} + +} // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Global.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/Global.h new file mode 100644 index 0000000..38cdd49 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/Global.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotGlobal__ +#define __EscargotGlobal__ + +#if defined(ENABLE_THREADING) && !defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) +#define ENABLE_ATOMICS_GLOBAL_LOCK +#endif + +#if defined(ENABLE_ATOMICS_GLOBAL_LOCK) +#include "util/SpinLock.h" +#endif + +namespace Escargot { + +class Platform; + +// Global is a global interface used by all threads +class Global { + static bool inited; + static Platform* g_platform; +#if defined(ENABLE_ATOMICS_GLOBAL_LOCK) + static SpinLock g_atomicsLock; +#endif +public: + static void initialize(Platform* platform); + static void finalize(); + + static Platform* platform(); +#if defined(ENABLE_ATOMICS_GLOBAL_LOCK) + static SpinLock& atomicsLock() + { + return g_atomicsLock; + } +#endif +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Object.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/Object.cpp index da6825b..4f81a1a 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/Object.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/Object.cpp @@ -87,6 +87,7 @@ ObjectRareData::ObjectRareData(Object* obj) , m_isArrayObjectLengthWritable(true) , m_isSpreadArrayObject(false) , m_isFinalizerRegistered(false) + , m_isInlineCacheable(true) , m_shouldUpdateEnumerateObject(false) , m_hasNonWritableLastIndexRegExpObject(false) , m_hasExtendedExtraData(false) @@ -1460,6 +1461,11 @@ void Object::deleteOwnProperty(ExecutionState& state, size_t idx) // ASSERT(m_values.size() == m_structure->propertyCount()); } +void Object::markAsNonInlineCachable() +{ + ensureRareData()->m_isInlineCacheable = false; +} + uint64_t Object::length(ExecutionState& state) { // ToLength(Get(obj, "length")) @@ -1641,6 +1647,10 @@ bool Object::defineNativeDataAccessorProperty(ExecutionState& state, const Objec m_structure = m_structure->addProperty(P.toObjectStructurePropertyName(state), ObjectStructurePropertyDescriptor::createDataButHasNativeGetterSetterDescriptor(data)); m_values.pushBack(objectInternalData, m_structure->propertyCount()); + if (UNLIKELY(data->m_actsLikeJSGetterSetter)) { + markAsNonInlineCachable(); + } + return true; } diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Object.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/Object.h index 7a08ccc..f1bcf7c 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/Object.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/Object.h @@ -74,6 +74,7 @@ struct ObjectRareData : public PointerValue { bool m_isArrayObjectLengthWritable : 1; bool m_isSpreadArrayObject : 1; bool m_isFinalizerRegistered : 1; + bool m_isInlineCacheable : 1; bool m_shouldUpdateEnumerateObject : 1; // used only for Array Object when ArrayObject::deleteOwnProperty called bool m_hasNonWritableLastIndexRegExpObject : 1; bool m_hasExtendedExtraData : 1; @@ -767,6 +768,7 @@ class Object : public PointerValue { friend class EnumerateObjectWithDestruction; friend class EnumerateObjectWithIteration; friend struct ObjectRareData; + friend class Template; friend class ObjectTemplate; public: @@ -955,6 +957,9 @@ public: virtual bool isInlineCacheable() { + if (UNLIKELY(hasRareData())) { + return rareData()->m_isInlineCacheable; + } return true; } @@ -1239,6 +1244,8 @@ protected: void setGlobalIntrinsicObject(ExecutionState& state, bool isPrototype = false); void deleteOwnProperty(ExecutionState& state, size_t idx); + + void markAsNonInlineCachable(); }; } // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ObjectTemplate.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/ObjectTemplate.cpp index 60c2b0e..fca2091 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/ObjectTemplate.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/ObjectTemplate.cpp @@ -261,7 +261,7 @@ private: Object* ObjectTemplate::instantiate(Context* ctx) { - if (!m_cachedObjectStructure) { + if (!m_cachedObjectStructure.m_objectStructure) { m_cachedObjectStructure = constructObjectStructure(ctx, nullptr, 0); } ObjectPropertyValueVector objectPropertyValues; @@ -278,9 +278,9 @@ Object* ObjectTemplate::instantiate(Context* ctx) } if (m_namedPropertyHandler) { - result = new ObjectWithNamedPropertyHandler(m_cachedObjectStructure, std::move(objectPropertyValues), proto, m_namedPropertyHandler); + result = new ObjectWithNamedPropertyHandler(m_cachedObjectStructure.m_objectStructure, std::move(objectPropertyValues), proto, m_namedPropertyHandler); } else { - result = new Object(m_cachedObjectStructure, std::move(objectPropertyValues), proto); + result = new Object(m_cachedObjectStructure.m_objectStructure, std::move(objectPropertyValues), proto); } postProcessing(result); @@ -335,6 +335,9 @@ bool ObjectTemplate::installTo(Context* ctx, Object* target) } else if (type == Template::TemplatePropertyData::PropertyType::PropertyNativeAccessorData) { sender->target->defineNativeDataAccessorProperty(state, name, properties[i].second.nativeAccessorData(), Value(Value::FromPayload, (intptr_t)properties[i].second.nativeAccessorPrivateData())); + if (properties[i].second.nativeAccessorData()->m_actsLikeJSGetterSetter) { + sender->target->markAsNonInlineCachable(); + } } else { ASSERT(type == Template::TemplatePropertyData::PropertyType::PropertyAccessorData); Value getter = properties[i].second.accessorData().m_getterTemplate ? properties[i].second.accessorData().m_getterTemplate->instantiate(sender->ctx) : Value(Value::EmptyValue); diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Platform.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/Platform.h index 2bd2d40..5c2888e 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/Platform.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/Platform.h @@ -20,16 +20,14 @@ #ifndef __EscargotPlatform__ #define __EscargotPlatform__ -#include "runtime/SandBox.h" - namespace Escargot { -class ArrayBufferObject; -class PromiseObject; class Context; -class Job; +class Script; +class String; +class PromiseObject; -class Platform : public gc { +class Platform { public: virtual ~Platform() {} // ArrayBuffer @@ -49,6 +47,10 @@ public: virtual LoadModuleResult onLoadModule(Context* relatedContext, Script* whereRequestFrom, String* moduleSrc) = 0; virtual void didLoadModule(Context* relatedContext, Optional whereRequestFrom, Script* loadedModule) = 0; virtual void hostImportModuleDynamically(Context* relatedContext, Script* referrer, String* src, PromiseObject* promise) = 0; + + // ThreadLocal custom data (g_customData) + virtual void* allocateThreadLocalCustomData() = 0; + virtual void deallocateThreadLocalCustomData() = 0; }; } // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/PointerValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/PointerValue.h index 8b1c271..dc0c61f 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/PointerValue.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/PointerValue.h @@ -52,6 +52,7 @@ class GlobalObject; class BoundFunctionObject; class PromiseObject; class ProxyObject; +class ArrayBuffer; class ArrayBufferObject; class ArrayBufferView; class DoubleInEncodedValue; @@ -70,9 +71,7 @@ class AsyncFromSyncIteratorObject; class GlobalObjectProxyObject; class TypedArrayObject; class ModuleNamespaceObject; -#if defined(ENABLE_THREADING) class SharedArrayBufferObject; -#endif #if defined(ENABLE_INTL) class IntlLocaleObject; class IntlPluralRulesObject; @@ -107,7 +106,7 @@ class ExportedFunctionObject; class PointerValue : public gc { friend class Object; friend class Context; - friend class VMInstance; + friend class Global; friend class ByteCodeInterpreter; // tag values for fast type check @@ -291,6 +290,11 @@ public: return false; } + virtual bool isArrayBuffer() const + { + return false; + } + virtual bool isArrayBufferObject() const { return false; @@ -411,12 +415,10 @@ public: return false; } -#if defined(ENABLE_THREADING) virtual bool isSharedArrayBufferObject() const { return false; } -#endif #if defined(ENABLE_INTL) virtual bool isIntlLocaleObject() const @@ -652,6 +654,12 @@ public: return (ProxyObject*)this; } + ArrayBuffer* asArrayBuffer() + { + ASSERT(isArrayBuffer()); + return (ArrayBuffer*)this; + } + ArrayBufferObject* asArrayBufferObject() { ASSERT(isArrayBufferObject()); @@ -760,6 +768,11 @@ public: ASSERT(isSharedArrayBufferObject()); return (SharedArrayBufferObject*)this; } +#else + SharedArrayBufferObject* asSharedArrayBufferObject() + { + RELEASE_ASSERT_NOT_REACHED(); + } #endif #if defined(ENABLE_INTL) diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/RegExpObject.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/RegExpObject.cpp index 1328530..dd61b56 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/RegExpObject.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/RegExpObject.cpp @@ -18,10 +18,10 @@ */ #include "Escargot.h" +#include "ThreadLocal.h" #include "RegExpObject.h" #include "Context.h" #include "ArrayObject.h" -#include "VMInstance.h" #include "WTFBridge.h" #include "Yarr.h" @@ -307,7 +307,7 @@ bool RegExpObject::match(ExecutionState& state, String* str, RegexMatchResult& m if (entry.m_bytecodePattern) { m_bytecodePattern = entry.m_bytecodePattern; } else { - WTF::BumpPointerAllocator* bumpAlloc = VMInstance::bumpPointerAllocator(); + WTF::BumpPointerAllocator* bumpAlloc = ThreadLocal::bumpPointerAllocator(); std::unique_ptr ownedBytecode = JSC::Yarr::byteCompile(*m_yarrPattern, bumpAlloc); m_bytecodePattern = ownedBytecode.release(); entry.m_bytecodePattern = m_bytecodePattern; diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/SharedArrayBufferObject.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/SharedArrayBufferObject.cpp index 1812a76..11f3dfd 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/SharedArrayBufferObject.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/SharedArrayBufferObject.cpp @@ -20,18 +20,32 @@ #if defined(ENABLE_THREADING) #include "Escargot.h" -#include "runtime/VMInstance.h" #include "runtime/Context.h" -#include "runtime/BackingStore.h" -#include "runtime/ArrayBufferObject.h" +#include "runtime/Global.h" +#include "runtime/Platform.h" #include "runtime/SharedArrayBufferObject.h" namespace Escargot { +static void backingStoreDeleter(void* data, size_t length, void* deleterData) +{ + SharedArrayBufferObjectBackingStoreData* internalData = (SharedArrayBufferObjectBackingStoreData*)deleterData; + internalData->deref(); +} + +void SharedArrayBufferObjectBackingStoreData::deref() +{ + auto oldValue = m_refCount.fetch_sub(1); + if (oldValue == 1) { + Global::platform()->onFreeArrayBufferObjectDataBuffer(m_data, m_byteLength); + delete this; + } +} + SharedArrayBufferObject::SharedArrayBufferObject(ExecutionState& state, Object* proto, size_t byteLength) - : ArrayBufferObject(state, proto) + : ArrayBuffer(state, proto) { - ASSERT(byteLength < ArrayBufferObject::maxArrayBufferSize); + ASSERT(byteLength < ArrayBuffer::maxArrayBufferSize); m_mayPointsSharedBackingStore = true; @@ -46,13 +60,18 @@ SharedArrayBufferObject::SharedArrayBufferObject(ExecutionState& state, Object* GC_invoke_finalizers(); } - auto platform = state.context()->vmInstance()->platform(); - void* buffer = platform->onMallocArrayBufferObjectDataBuffer(byteLength); - m_backingStore = new BackingStore(buffer, byteLength, [](void* data, size_t length, void* deleterData) { - Platform* platform = (Platform*)deleterData; - platform->onFreeArrayBufferObjectDataBuffer(data, length); - }, - platform, true); + void* buffer = Global::platform()->onMallocArrayBufferObjectDataBuffer(byteLength); + SharedArrayBufferObjectBackingStoreData* internalData = new SharedArrayBufferObjectBackingStoreData(buffer, byteLength); + + m_backingStore = new BackingStore(buffer, byteLength, backingStoreDeleter, internalData, true); +} + +SharedArrayBufferObject::SharedArrayBufferObject(ExecutionState& state, Object* proto, SharedArrayBufferObjectBackingStoreData* data) + : ArrayBuffer(state, proto) +{ + data->ref(); + m_mayPointsSharedBackingStore = true; + m_backingStore = new BackingStore(data->data(), data->byteLength(), backingStoreDeleter, data, true); } SharedArrayBufferObject* SharedArrayBufferObject::allocateSharedArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength) @@ -62,7 +81,7 @@ SharedArrayBufferObject* SharedArrayBufferObject::allocateSharedArrayBuffer(Exec return constructorRealm->globalObject()->sharedArrayBufferPrototype(); }); - if (byteLength >= ArrayBufferObject::maxArrayBufferSize) { + if (byteLength >= ArrayBuffer::maxArrayBufferSize) { ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().SharedArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferSize); } @@ -77,8 +96,7 @@ void* SharedArrayBufferObject::operator new(size_t size) static MAY_THREAD_LOCAL GC_descr descr; if (!typeInited) { GC_word obj_bitmap[GC_BITMAP_SIZE(SharedArrayBufferObject)] = { 0 }; - Object::fillGCDescriptor(obj_bitmap); - GC_set_bit(obj_bitmap, GC_WORD_OFFSET(SharedArrayBufferObject, m_backingStore)); + ArrayBuffer::fillGCDescriptor(obj_bitmap); descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(SharedArrayBufferObject)); typeInited = true; } diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/SharedArrayBufferObject.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/SharedArrayBufferObject.h index a45f1db..d2f7404 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/SharedArrayBufferObject.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/SharedArrayBufferObject.h @@ -22,23 +22,50 @@ #ifndef __EscargotSharedArrayBufferObject__ #define __EscargotSharedArrayBufferObject__ -namespace Escargot { +#include "runtime/ArrayBuffer.h" -class BackingStore; -class ArrayBufferObject; +namespace Escargot { -class SharedArrayBufferObject : public ArrayBufferObject { +class SharedArrayBufferObjectBackingStoreData { public: - SharedArrayBufferObject(ExecutionState& state, Object* proto, size_t byteLength); + SharedArrayBufferObjectBackingStoreData(void* data, size_t byteLength) + : m_data(data) + , m_byteLength(byteLength) + , m_refCount(1) + { + } - static SharedArrayBufferObject* allocateSharedArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength); + void* data() const + { + return m_data; + } - Optional backingStore() + size_t byteLength() const { - return m_backingStore; + return m_byteLength; } - virtual bool isSharedArrayBufferObject() const + void ref() + { + m_refCount++; + } + + void deref(); + +private: + void* m_data; + size_t m_byteLength; + std::atomic m_refCount; +}; + +class SharedArrayBufferObject : public ArrayBuffer { +public: + SharedArrayBufferObject(ExecutionState& state, Object* proto, size_t byteLength); + SharedArrayBufferObject(ExecutionState& state, Object* proto, SharedArrayBufferObjectBackingStoreData* data); + + static SharedArrayBufferObject* allocateSharedArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength); + + virtual bool isSharedArrayBufferObject() const override { return true; } diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Template.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/Template.cpp index b7766bd..f1d6321 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/Template.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/Template.cpp @@ -44,7 +44,7 @@ bool Template::has(const TemplatePropertyName& name) bool Template::remove(const TemplatePropertyName& name) { - ASSERT(m_cachedObjectStructure == nullptr); + ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr); for (size_t i = 0; i < m_properties.size(); i++) { if (m_properties[i].first == name) { m_properties.erase(i); @@ -56,26 +56,26 @@ bool Template::remove(const TemplatePropertyName& name) void Template::set(const TemplatePropertyName& name, const TemplateData& data, bool isWritable, bool isEnumerable, bool isConfigurable) { - ASSERT(m_cachedObjectStructure == nullptr); + ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr); remove(name); m_properties.pushBack(std::make_pair(name, TemplatePropertyData(data, isWritable, isEnumerable, isConfigurable))); } void Template::setAccessorProperty(const TemplatePropertyName& name, Optional getter, Optional setter, bool isEnumerable, bool isConfigurable) { - ASSERT(m_cachedObjectStructure == nullptr); + ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr); remove(name); m_properties.pushBack(std::make_pair(name, TemplatePropertyData(getter, setter, isEnumerable, isConfigurable))); } void Template::setNativeDataAccessorProperty(const TemplatePropertyName& name, ObjectPropertyNativeGetterSetterData* nativeGetterSetterData, void* privateData) { - ASSERT(m_cachedObjectStructure == nullptr); + ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr); remove(name); m_properties.pushBack(std::make_pair(name, TemplatePropertyData(nativeGetterSetterData, privateData))); } -ObjectStructure* Template::constructObjectStructure(Context* ctx, ObjectStructureItem* baseItems, size_t baseItemCount) +Template::CachedObjectStructure Template::constructObjectStructure(Context* ctx, ObjectStructureItem* baseItems, size_t baseItemCount) { size_t propertyCount = m_properties.size() + baseItemCount; ObjectStructureItemTightVector structureItemVector; @@ -87,6 +87,7 @@ ObjectStructure* Template::constructObjectStructure(Context* ctx, ObjectStructur bool hasIndexStringAsPropertyName = false; bool hasNonAtomicPropertyName = false; + bool isInlineNonCacheable = false; for (size_t i = baseItemCount; i < propertyCount; i++) { auto propertyIndex = i - baseItemCount; auto propertyName = m_properties[propertyIndex].first.toObjectStructurePropertyName(ctx); @@ -102,6 +103,7 @@ ObjectStructure* Template::constructObjectStructure(Context* ctx, ObjectStructur desc = ObjectStructurePropertyDescriptor::createDataDescriptor(m_properties[propertyIndex].second.presentAttributes()); } else if (type == Template::TemplatePropertyData::PropertyType::PropertyNativeAccessorData) { desc = ObjectStructurePropertyDescriptor::createDataButHasNativeGetterSetterDescriptor(m_properties[propertyIndex].second.nativeAccessorData()); + isInlineNonCacheable = isInlineNonCacheable | m_properties[propertyIndex].second.nativeAccessorData()->m_actsLikeJSGetterSetter; } else { ASSERT(type == Template::TemplatePropertyData::PropertyType::PropertyAccessorData); desc = ObjectStructurePropertyDescriptor::createAccessorDescriptor(m_properties[propertyIndex].second.presentAttributes()); @@ -116,7 +118,10 @@ ObjectStructure* Template::constructObjectStructure(Context* ctx, ObjectStructur newObjectStructure = new ObjectStructureWithTransition(std::move(structureItemVector), hasIndexStringAsPropertyName, hasNonAtomicPropertyName); } - return newObjectStructure; + CachedObjectStructure s; + s.m_objectStructure = newObjectStructure; + s.m_inlineCacheable = !isInlineNonCacheable; + return s; } void Template::constructObjectPropertyValues(Context* ctx, ObjectPropertyValue* baseItems, size_t baseItemCount, ObjectPropertyValueVector& objectPropertyValues) @@ -151,5 +156,9 @@ void Template::postProcessing(Object* instantiatedObject) if (m_instanceExtraData) { instantiatedObject->setExtraData(m_instanceExtraData); } + + if (!m_cachedObjectStructure.m_inlineCacheable) { + instantiatedObject->markAsNonInlineCachable(); + } } } // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Template.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/Template.h index bdfd3c0..7761bb8 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/Template.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/Template.h @@ -158,7 +158,7 @@ public: virtual Object* instantiate(Context* ctx) = 0; bool didInstantiate() const { - return m_cachedObjectStructure; + return m_cachedObjectStructure.m_objectStructure; } virtual bool isObjectTemplate() const @@ -173,17 +173,26 @@ public: Optional cachedObjectStructure() { - return m_cachedObjectStructure; + return m_cachedObjectStructure.m_objectStructure; } protected: - ObjectStructure* constructObjectStructure(Context* ctx, ObjectStructureItem* baseItems, size_t baseItemCount); + struct CachedObjectStructure { + ObjectStructure* m_objectStructure; + bool m_inlineCacheable; + + CachedObjectStructure() + : m_objectStructure(nullptr) + , m_inlineCacheable(false) + { + } + }; + CachedObjectStructure constructObjectStructure(Context* ctx, ObjectStructureItem* baseItems, size_t baseItemCount); void constructObjectPropertyValues(Context* ctx, ObjectPropertyValue* baseItems, size_t baseItemCount, ObjectPropertyValueVector& objectPropertyValues); void postProcessing(Object* instantiatedObject); Template() : m_instanceExtraData(nullptr) - , m_cachedObjectStructure(nullptr) { } virtual ~Template() @@ -194,7 +203,7 @@ protected: { GC_set_bit(desc, GC_WORD_OFFSET(Template, m_properties)); GC_set_bit(desc, GC_WORD_OFFSET(Template, m_instanceExtraData)); - GC_set_bit(desc, GC_WORD_OFFSET(Template, m_cachedObjectStructure)); + GC_set_bit(desc, GC_WORD_OFFSET(Template, m_cachedObjectStructure.m_objectStructure)); } class TemplatePropertyData { @@ -332,7 +341,7 @@ protected: Vector, GCUtil::gc_malloc_allocator>> m_properties; void* m_instanceExtraData; - ObjectStructure* m_cachedObjectStructure; + CachedObjectStructure m_cachedObjectStructure; }; } // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.cpp new file mode 100644 index 0000000..07e3547 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include "Escargot.h" +#include "runtime/ThreadLocal.h" +#include "heap/Heap.h" +#include "runtime/Global.h" +#include "runtime/Platform.h" +#include "parser/ASTAllocator.h" +#include "BumpPointerAllocator.h" +#if defined(ENABLE_WASM) +#include "wasm.h" +#endif + +namespace Escargot { + +MAY_THREAD_LOCAL bool ThreadLocal::inited; + +MAY_THREAD_LOCAL std::mt19937* ThreadLocal::g_randEngine; +MAY_THREAD_LOCAL bf_context_t ThreadLocal::g_bfContext; +#if defined(ENABLE_WASM) +MAY_THREAD_LOCAL WASMContext ThreadLocal::g_wasmContext; +#endif +MAY_THREAD_LOCAL ASTAllocator* ThreadLocal::g_astAllocator; +MAY_THREAD_LOCAL WTF::BumpPointerAllocator* ThreadLocal::g_bumpPointerAllocator; +MAY_THREAD_LOCAL void* ThreadLocal::g_customData; + +void ThreadLocal::initialize() +{ + // initialize should be invoked only once in each thread + static MAY_THREAD_LOCAL bool called_once = true; + RELEASE_ASSERT(called_once && !inited); + + // Heap is initialized for each thread + Heap::initialize(); + + // g_randEngine + g_randEngine = new std::mt19937((unsigned int)time(NULL)); + + // g_bfContext + bf_context_init(&g_bfContext, [](void* opaque, void* ptr, size_t size) -> void* { + return realloc(ptr, size); + }, + nullptr); + +#if defined(ENABLE_WASM) + // g_wasmContext + g_wasmContext.engine = wasm_engine_new(); + g_wasmContext.store = wasm_store_new(g_wasmContext.engine); + g_wasmContext.lastGCCheckTime = 0; +#endif + + // g_astAllocator + g_astAllocator = new ASTAllocator(); + + // g_bumpPointerAllocator + g_bumpPointerAllocator = new WTF::BumpPointerAllocator(); + + // g_customData + g_customData = Global::platform()->allocateThreadLocalCustomData(); + + called_once = false; + inited = true; +} + +void ThreadLocal::finalize() +{ + // finalize should be invoked only once in each thread + static MAY_THREAD_LOCAL bool called_once = true; + RELEASE_ASSERT(called_once && inited); + + // g_customData + Global::platform()->deallocateThreadLocalCustomData(); + g_customData = nullptr; + + // full gc(Heap::finalize) should be invoked after g_customData deallocation + // because g_customData might contain GC-object + Heap::finalize(); + + // g_randEngine does not need finalization + delete g_randEngine; + g_randEngine = nullptr; + + // g_bfContext + bf_context_end(&g_bfContext); + +#if defined(ENABLE_WASM) + // g_wasmContext + wasm_store_delete(g_wasmContext.store); + wasm_engine_delete(g_wasmContext.engine); + g_wasmContext.store = nullptr; + g_wasmContext.engine = nullptr; + g_wasmContext.lastGCCheckTime = 0; +#endif + + // g_astAllocator + delete g_astAllocator; + g_astAllocator = nullptr; + + // g_bumpPointerAllocator + delete g_bumpPointerAllocator; + g_bumpPointerAllocator = nullptr; + + called_once = false; + inited = false; +} + +#if defined(ENABLE_WASM) +void ThreadLocal::wasmGC(uint64_t lastCheckTime) +{ + ASSERT(inited && !!g_wasmContext.store); + wasm_store_gc(g_wasmContext.store); + g_wasmContext.lastGCCheckTime = lastCheckTime; +} +#endif + +} // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.h new file mode 100644 index 0000000..b313453 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotThreadLocalRecord__ +#define __EscargotThreadLocalRecord__ + +namespace WTF { +class BumpPointerAllocator; +} + +#if defined(ENABLE_WASM) +struct wasm_engine_t; +struct wasm_store_t; +struct WASMContext { + wasm_engine_t* engine; + wasm_store_t* store; + uint64_t lastGCCheckTime; +}; +#endif + +namespace Escargot { + +class ASTAllocator; + +// ThreadLocal has thread-local values +// ThreadLocal should be created for each thread +// ThreadLocal is a non-GC global object which means that users who want to customize it should manage memory by themselves +class ThreadLocal { + static MAY_THREAD_LOCAL bool inited; + + // Global data per thread + static MAY_THREAD_LOCAL std::mt19937* g_randEngine; + static MAY_THREAD_LOCAL bf_context_t g_bfContext; +#if defined(ENABLE_WASM) + static MAY_THREAD_LOCAL WASMContext g_wasmContext; +#endif + static MAY_THREAD_LOCAL ASTAllocator* g_astAllocator; + static MAY_THREAD_LOCAL WTF::BumpPointerAllocator* g_bumpPointerAllocator; + // custom data allocated by user through Platform::allocateThreadLocalCustomData + static MAY_THREAD_LOCAL void* g_customData; + +public: + static void initialize(); + static void finalize(); + + // Global data getter + static std::mt19937& randEngine() + { + ASSERT(inited && !!g_randEngine); + return *g_randEngine; + } + + static bf_context_t* bfContext() + { + ASSERT(inited && !!g_bfContext.realloc_func); + return &g_bfContext; + } + +#if defined(ENABLE_WASM) + static void wasmGC(uint64_t lastCheckTime); + + static wasm_store_t* wasmStore() + { + ASSERT(inited && !!g_wasmContext.store); + return g_wasmContext.store; + } + + static uint64_t wasmLastGCCheckTime() + { + ASSERT(inited && !!g_wasmContext.store); + return g_wasmContext.lastGCCheckTime; + } +#endif + + static ASTAllocator* astAllocator() + { + ASSERT(inited && !!g_astAllocator); + return g_astAllocator; + } + + static WTF::BumpPointerAllocator* bumpPointerAllocator() + { + ASSERT(inited && !!g_bumpPointerAllocator); + return g_bumpPointerAllocator; + } + + static void* customData() + { + ASSERT(inited && !!g_customData); + return g_customData; + } +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/TypedArrayObject.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/TypedArrayObject.cpp index b3726bd..12195f8 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/TypedArrayObject.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/TypedArrayObject.cpp @@ -146,7 +146,7 @@ void TypedArrayObject::sort(ExecutionState& state, int64_t length, const std::fu } } -ArrayBufferObject* TypedArrayObject::validateTypedArray(ExecutionState& state, const Value& O) +ArrayBuffer* TypedArrayObject::validateTypedArray(ExecutionState& state, const Value& O) { if (!O.isObject()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotObject); @@ -158,7 +158,7 @@ ArrayBufferObject* TypedArrayObject::validateTypedArray(ExecutionState& state, c } auto wrapper = thisObject->asTypedArrayObject(); - ArrayBufferObject* buffer = wrapper->buffer(); + ArrayBuffer* buffer = wrapper->buffer(); buffer->throwTypeErrorIfDetached(state); return buffer; } diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/TypedArrayObject.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/TypedArrayObject.h index 008036a..47dfa1f 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/TypedArrayObject.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/TypedArrayObject.h @@ -81,7 +81,7 @@ public: virtual void enumeration(ExecutionState& state, bool (*callback)(ExecutionState& state, Object* self, const ObjectPropertyName&, const ObjectStructurePropertyDescriptor& desc, void* data), void* data, bool shouldSkipSymbolKey) override; virtual void sort(ExecutionState& state, int64_t length, const std::function& comp) override; - static ArrayBufferObject* validateTypedArray(ExecutionState& state, const Value& O); + static ArrayBuffer* validateTypedArray(ExecutionState& state, const Value& O); protected: explicit TypedArrayObject(ExecutionState& state, Object* proto) diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.cpp index 6fb6d03..70492b5 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.cpp @@ -19,7 +19,9 @@ #include "Escargot.h" #include "VMInstance.h" -#include "BumpPointerAllocator.h" +#include "runtime/Global.h" +#include "runtime/ThreadLocal.h" +#include "runtime/Platform.h" #include "runtime/ArrayObject.h" #include "runtime/ArrayBufferObject.h" #include "runtime/StringObject.h" @@ -27,97 +29,22 @@ #include "runtime/JobQueue.h" #include "runtime/CompressibleString.h" #include "runtime/ReloadableString.h" -#include "runtime/Intl.h" +#include "intl/Intl.h" #include "interpreter/ByteCode.h" -#include "parser/ASTAllocator.h" #if defined(ENABLE_CODE_CACHE) #include "codecache/CodeCache.h" #endif -#if defined(ENABLE_WASM) -#include "wasm.h" -#endif #include namespace Escargot { -///////////////////////////////////////////////// -// VMInstance Global Data -///////////////////////////////////////////////// -MAY_THREAD_LOCAL std::mt19937* VMInstance::g_randEngine; -MAY_THREAD_LOCAL bf_context_t VMInstance::g_bfContext; #if defined(ENABLE_WASM) #ifndef ESCARGOT_WASM_GC_CHECK_INTERVAL #define ESCARGOT_WASM_GC_CHECK_INTERVAL 5000 #endif -MAY_THREAD_LOCAL WASMContext VMInstance::g_wasmContext; -#endif -MAY_THREAD_LOCAL ASTAllocator* VMInstance::g_astAllocator; -MAY_THREAD_LOCAL WTF::BumpPointerAllocator* VMInstance::g_bumpPointerAllocator; - -void VMInstance::initialize() -{ - // g_randEngine - g_randEngine = new std::mt19937((unsigned int)time(NULL)); - - // g_bfContext - bf_context_init(&g_bfContext, [](void* opaque, void* ptr, size_t size) -> void* { - return realloc(ptr, size); - }, - nullptr); - -#if defined(ENABLE_WASM) - // g_wasmContext - g_wasmContext.engine = wasm_engine_new(); - g_wasmContext.store = wasm_store_new(g_wasmContext.engine); - g_wasmContext.lastGCCheckTime = 0; #endif - // g_astAllocator - g_astAllocator = new ASTAllocator(); - - // g_bumpPointerAllocator - g_bumpPointerAllocator = new WTF::BumpPointerAllocator(); - - // initialize PointerValue tag values - // tag values should be initialized once and not changed - PointerValue::g_arrayObjectTag = ArrayObject().getTag(); - PointerValue::g_arrayPrototypeObjectTag = ArrayPrototypeObject().getTag(); - PointerValue::g_objectRareDataTag = ObjectRareData(nullptr).getTag(); - PointerValue::g_doubleInEncodedValueTag = DoubleInEncodedValue(0).getTag(); -} - -void VMInstance::finalize() -{ - // this function should be invoked after full gc (Heap::finalize) - // because some registered gc-finalizers could use these global values - - // g_randEngine does not need finalization - delete g_randEngine; - g_randEngine = nullptr; - - // g_bfContext - bf_context_end(&g_bfContext); - -#if defined(ENABLE_WASM) - // g_wasmContext - wasm_store_delete(g_wasmContext.store); - wasm_engine_delete(g_wasmContext.engine); - g_wasmContext.store = nullptr; - g_wasmContext.engine = nullptr; - g_wasmContext.lastGCCheckTime = 0; -#endif - - // g_astAllocator - delete g_astAllocator; - g_astAllocator = nullptr; - - // g_bumpPointerAllocator - delete g_bumpPointerAllocator; - g_bumpPointerAllocator = nullptr; -} -///////////////////////////////////////////////// - Value VMInstance::functionPrototypeNativeGetter(ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) { ASSERT(self->isFunctionObject()); @@ -245,9 +172,8 @@ void VMInstance::gcEventCallback(GC_EventType t, void* data) } #endif #if defined(ENABLE_WASM) - if (currentTick - g_wasmContext.lastGCCheckTime > ESCARGOT_WASM_GC_CHECK_INTERVAL) { - wasm_store_gc(g_wasmContext.store); - g_wasmContext.lastGCCheckTime = currentTick; + if (currentTick - ThreadLocal::wasmLastGCCheckTime() > ESCARGOT_WASM_GC_CHECK_INTERVAL) { + ThreadLocal::wasmGC(currentTick); } #endif #endif @@ -314,7 +240,6 @@ void* VMInstance::operator new(size_t size) GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_regexpCache)); GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_regexpOptionStringCache)); GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_cachedUTC)); - GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_platform)); GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_jobQueue)); #if defined(ENABLE_INTL) GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_intlAvailableLocales)); @@ -368,7 +293,7 @@ VMInstance::~VMInstance() #endif } -VMInstance::VMInstance(Platform* platform, const char* locale, const char* timezone, const char* baseCacheDir) +VMInstance::VMInstance(const char* locale, const char* timezone, const char* baseCacheDir) : m_staticStrings(&m_atomicStringMap) , m_currentSandBox(nullptr) , m_isFinalized(false) @@ -387,7 +312,6 @@ VMInstance::VMInstance(Platform* platform, const char* locale, const char* timez , m_promiseHook(nullptr) , m_promiseHookPublic(nullptr) , m_cachedUTC(nullptr) - , m_platform(platform) { GC_REGISTER_FINALIZER_NO_ORDER(this, [](void* obj, void*) { VMInstance* self = (VMInstance*)obj; @@ -580,7 +504,7 @@ void VMInstance::clearCachesRelatedWithContext() // this lock should be released immediately (destructor may be called later) m_codeCache->clear(); #endif - bf_clear_cache(&g_bfContext); + bf_clear_cache(ThreadLocal::bfContext()); } void VMInstance::enterIdleMode() @@ -645,7 +569,7 @@ void VMInstance::somePrototypeObjectDefineIndexedProperty(ExecutionState& state) void VMInstance::enqueueJob(Job* job) { m_jobQueue->enqueueJob(job); - m_platform->markJSJobEnqueued(job->relatedContext()); + Global::platform()->markJSJobEnqueued(job->relatedContext()); } bool VMInstance::hasPendingJob() diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.h index cfd6d6b..daf386f 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.h @@ -20,33 +20,17 @@ #ifndef __EscargotVMInstance__ #define __EscargotVMInstance__ -#include "runtime/Platform.h" +#include "runtime/SandBox.h" #include "runtime/AtomicString.h" #include "runtime/StaticStrings.h" #include "runtime/ToStringRecursionPreventer.h" -#if defined(ENABLE_WASM) -struct wasm_engine_t; -struct wasm_store_t; -struct WASMContext { - wasm_engine_t* engine; - wasm_store_t* store; - uint64_t lastGCCheckTime; -}; -#endif - -namespace WTF { -class BumpPointerAllocator; -} - namespace Escargot { -class SandBox; class Context; class CodeBlock; class JobQueue; class Job; -class ASTAllocator; class Symbol; class String; #if defined(ENABLE_COMPRESSIBLE_STRING) @@ -93,53 +77,7 @@ class VMInstance : public gc { friend class ScriptParser; friend class SandBox; - ///////////////////////////////// - // Global Data - // global values which should be initialized once and shared during the runtime - static MAY_THREAD_LOCAL std::mt19937* g_randEngine; - static MAY_THREAD_LOCAL bf_context_t g_bfContext; -#if defined(ENABLE_WASM) - static MAY_THREAD_LOCAL WASMContext g_wasmContext; -#endif - - static MAY_THREAD_LOCAL ASTAllocator* g_astAllocator; - static MAY_THREAD_LOCAL WTF::BumpPointerAllocator* g_bumpPointerAllocator; - ///////////////////////////////// - public: - ///////////////////////////////// - // Global Data Static Function - static void initialize(); - static void finalize(); - static std::mt19937& randEngine() - { - ASSERT(!!g_randEngine); - return *g_randEngine; - } - static bf_context_t* bfContext() - { - ASSERT(!!g_bfContext.realloc_func); - return &g_bfContext; - } -#if defined(ENABLE_WASM) - static wasm_store_t* wasmStore() - { - ASSERT(!!g_wasmContext.store); - return g_wasmContext.store; - } -#endif - static ASTAllocator* astAllocator() - { - ASSERT(!!g_astAllocator); - return g_astAllocator; - } - static WTF::BumpPointerAllocator* bumpPointerAllocator() - { - ASSERT(!!g_bumpPointerAllocator); - return g_bumpPointerAllocator; - } - ///////////////////////////////// - enum PromiseHookType { Init, Resolve, @@ -149,7 +87,7 @@ public: typedef void (*PromiseHook)(ExecutionState& state, PromiseHookType type, PromiseObject* promise, const Value& parent, void* hook); - VMInstance(Platform* platform, const char* locale = nullptr, const char* timezone = nullptr, const char* baseCacheDir = nullptr); + VMInstance(const char* locale = nullptr, const char* timezone = nullptr, const char* baseCacheDir = nullptr); ~VMInstance(); void* operator new(size_t size); @@ -259,11 +197,6 @@ public: } #endif - Platform* platform() - { - return m_platform; - } - SandBox* currentSandBox() { return m_currentSandBox; @@ -279,7 +212,6 @@ public: return m_regexpOptionStringCache; } - void setOnDestroyCallback(void (*onVMInstanceDestroy)(VMInstance* instance, void* data), void* data) { m_onVMInstanceDestroy = onVMInstanceDestroy; @@ -399,8 +331,6 @@ private: #endif DateObject* m_cachedUTC; - Platform* m_platform; - // promise job queue JobQueue* m_jobQueue; diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBigIntValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBigIntValue.h new file mode 100644 index 0000000..7e5c78a --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBigIntValue.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotSerializedBigIntValue__ +#define __EscargotSerializedBigIntValue__ + +#include "runtime/serialization/SerializedValue.h" +#include "runtime/BigInt.h" + +namespace Escargot { + +class SerializedBigIntValue : public SerializedValue { + friend class Serializer; + +public: + virtual Type type() override + { + return SerializedValue::BigInt; + } + + virtual Value toValue(ExecutionState& state) override + { + BigIntData d(m_value.data(), m_value.size()); + return Value(new ::Escargot::BigInt(std::move(d))); + } + +protected: + virtual void serializeValueData(std::ostringstream& outputStream) override + { + size_t s = m_value.size(); + outputStream << s; + outputStream << std::endl; + for (size_t i = 0; i < s; i++) { + outputStream << m_value[i]; + } + } + + static std::unique_ptr deserializeFrom(std::istringstream& inputStream) + { + size_t s; + inputStream >> s; + std::string str; + str.reserve(s); + + for (size_t i = 0; i < s; i++) { + char ch; + inputStream >> ch; + str.push_back(ch); + } + + return std::unique_ptr(new SerializedBigIntValue(std::move(str))); + } + + SerializedBigIntValue(std::string&& value) + : m_value(value) + { + } + std::string m_value; +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBooleanValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBooleanValue.h new file mode 100644 index 0000000..8778e36 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBooleanValue.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotSerializedBooleanValue__ +#define __EscargotSerializedBooleanValue__ + +#include "runtime/serialization/SerializedValue.h" + +namespace Escargot { + +class SerializedBooleanValue : public SerializedValue { + friend class Serializer; + +public: + virtual Type type() override + { + return SerializedValue::Boolean; + } + + virtual Value toValue(ExecutionState& state) override + { + return Value(m_value); + } + +protected: + virtual void serializeValueData(std::ostringstream& outputStream) override + { + outputStream << m_value; + outputStream << std::endl; + } + + static std::unique_ptr deserializeFrom(std::istringstream& inputStream) + { + bool v; + inputStream >> v; + return std::unique_ptr(new SerializedBooleanValue(v)); + } + + SerializedBooleanValue(bool value) + : m_value(value) + { + } + + bool m_value; +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNullValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNullValue.h new file mode 100644 index 0000000..327e0c6 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNullValue.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotSerializedNullValue__ +#define __EscargotSerializedNullValue__ + +#include "runtime/serialization/SerializedValue.h" + +namespace Escargot { + +class SerializedNullValue : public SerializedValue { + friend class Serializer; + +public: + virtual Type type() override + { + return SerializedValue::Null; + } + + virtual Value toValue(ExecutionState& state) override + { + return Value(Value::Null); + } + +protected: + static std::unique_ptr deserializeFrom(std::istringstream& inputStream) + { + return std::unique_ptr(new SerializedNullValue()); + } +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNumberValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNumberValue.h new file mode 100644 index 0000000..c70e174 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNumberValue.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotSerializedNumberValue__ +#define __EscargotSerializedNumberValue__ + +#include "runtime/serialization/SerializedValue.h" + +namespace Escargot { + +class SerializedNumberValue : public SerializedValue { + friend class Serializer; + +public: + virtual Type type() override + { + return SerializedValue::Number; + } + + virtual Value toValue(ExecutionState& state) override + { + return Value(m_value); + } + +protected: + virtual void serializeValueData(std::ostringstream& outputStream) override + { + outputStream << m_value; + outputStream << std::endl; + } + + static std::unique_ptr deserializeFrom(std::istringstream& inputStream) + { + double v; + inputStream >> v; + return std::unique_ptr(new SerializedNumberValue(v)); + } + + SerializedNumberValue(double value) + : m_value(value) + { + } + double m_value; +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSharedArrayBufferObjectValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSharedArrayBufferObjectValue.h new file mode 100644 index 0000000..786fb94 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSharedArrayBufferObjectValue.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#if defined(ENABLE_THREADING) + +#ifndef __EscargotSerializedSharedArrayBufferObjectValue__ +#define __EscargotSerializedSharedArrayBufferObjectValue__ + +#include "runtime/serialization/SerializedValue.h" +#include "runtime/SharedArrayBufferObject.h" + +namespace Escargot { + +class SerializedSharedArrayBufferObjectValue : public SerializedValue { + friend class Serializer; + +public: + virtual Type type() override + { + return SerializedValue::SharedArrayBufferObject; + } + + virtual Value toValue(ExecutionState& state) override + { + return Value(new ::Escargot::SharedArrayBufferObject(state, state.context()->globalObject()->sharedArrayBufferPrototype(), m_bufferData)); + } + +protected: + virtual void serializeValueData(std::ostringstream& outputStream) override + { + size_t ptr = reinterpret_cast(m_bufferData); + outputStream << ptr; + outputStream << std::endl; + } + + static std::unique_ptr deserializeFrom(std::istringstream& inputStream) + { + size_t ptr; + inputStream >> ptr; + SharedArrayBufferObjectBackingStoreData* data = reinterpret_cast(ptr); + return std::unique_ptr(new SerializedSharedArrayBufferObjectValue(data)); + } + + SerializedSharedArrayBufferObjectValue(SharedArrayBufferObjectBackingStoreData* bufferData) + : m_bufferData(bufferData) + { + m_bufferData->ref(); + } + + ~SerializedSharedArrayBufferObjectValue() + { + m_bufferData->deref(); + } + + SharedArrayBufferObjectBackingStoreData* m_bufferData; +}; + +} // namespace Escargot + +#endif +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedStringValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedStringValue.h new file mode 100644 index 0000000..6dda479 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedStringValue.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotSerializedStringValue__ +#define __EscargotSerializedStringValue__ + +#include "runtime/serialization/SerializedValue.h" + +namespace Escargot { + +class SerializedStringValue : public SerializedValue { + friend class Serializer; + +public: + virtual Type type() override + { + return SerializedValue::String; + } + + virtual Value toValue(ExecutionState& state) override + { + return Value(String::fromUTF8(m_value.data(), m_value.size())); + } + +protected: + virtual void serializeValueData(std::ostringstream& outputStream) override + { + size_t s = m_value.size(); + outputStream << s; + outputStream << std::endl; + for (size_t i = 0; i < s; i++) { + outputStream << m_value[i]; + } + } + + static std::unique_ptr deserializeFrom(std::istringstream& inputStream) + { + size_t s; + inputStream >> s; + std::string str; + str.reserve(s); + + for (size_t i = 0; i < s; i++) { + char ch; + inputStream >> ch; + str.push_back(ch); + } + + return std::unique_ptr(new SerializedStringValue(std::move(str))); + } + + SerializedStringValue(std::string&& value) + : m_value(value) + { + } + std::string m_value; +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSymbolValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSymbolValue.h new file mode 100644 index 0000000..f9d1b6e --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSymbolValue.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotSerializedSymbolValue__ +#define __EscargotSerializedSymbolValue__ + +#include "runtime/serialization/SerializedValue.h" + +namespace Escargot { + +class SerializedSymbolValue : public SerializedValue { + friend class Serializer; + +public: + virtual Type type() override + { + return SerializedValue::Symbol; + } + + virtual Value toValue(ExecutionState& state) override + { + if (m_value) { + return Value(new ::Escargot::Symbol( + String::fromUTF8(m_value.value().data(), m_value.value().size()))); + } + return Value(new ::Escargot::Symbol()); + } + +protected: + virtual void serializeValueData(std::ostringstream& outputStream) override + { + if (m_value) { + outputStream << true; + outputStream << std::endl; + size_t s = m_value.value().size(); + outputStream << s; + outputStream << std::endl; + for (size_t i = 0; i < s; i++) { + outputStream << (m_value.value())[i]; + } + } else { + outputStream << false; + outputStream << std::endl; + } + } + + static std::unique_ptr deserializeFrom(std::istringstream& inputStream) + { + bool hasValue; + inputStream >> hasValue; + if (hasValue) { + size_t s; + inputStream >> s; + std::string str; + str.reserve(s); + + for (size_t i = 0; i < s; i++) { + char ch; + inputStream >> ch; + str.push_back(ch); + } + + return std::unique_ptr(new SerializedSymbolValue(std::move(str))); + } + return std::unique_ptr(new SerializedSymbolValue()); + } + + SerializedSymbolValue(std::string&& value) + : m_value(value) + { + } + + SerializedSymbolValue() + { + } + + Optional m_value; +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedUndefinedValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedUndefinedValue.h new file mode 100644 index 0000000..35f39a3 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedUndefinedValue.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotSerializedUndefinedValue__ +#define __EscargotSerializedUndefinedValue__ + +#include "runtime/serialization/SerializedValue.h" + +namespace Escargot { + +class SerializedUndefinedValue : public SerializedValue { + friend class Serializer; + +public: + virtual Type type() override + { + return SerializedValue::Undefined; + } + virtual Value toValue(ExecutionState& state) override + { + return Value(); + } + +protected: + static std::unique_ptr deserializeFrom(std::istringstream& inputStream) + { + return std::unique_ptr(new SerializedUndefinedValue()); + } +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedValue.h new file mode 100644 index 0000000..c83d5a7 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedValue.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotSerializedValue__ +#define __EscargotSerializedValue__ + +#include "runtime/Value.h" + +namespace Escargot { + +class SerializedValue { + friend class Serializer; + +public: +#define FOR_EACH_SERIALIZABLE_TYPE(F) \ + F(Undefined) \ + F(Null) \ + F(Boolean) \ + F(Number) \ + F(String) \ + F(Symbol) \ + F(BigInt) + + enum Type { +#define DECLARE_SERIALIZABLE_TYPE(name) name, + FOR_EACH_SERIALIZABLE_TYPE(DECLARE_SERIALIZABLE_TYPE) +#undef DECLARE_SERIALIZABLE_TYPE +#if defined(ENABLE_THREADING) + SharedArrayBufferObject +#endif + }; + virtual ~SerializedValue() {} + virtual Type type() = 0; + virtual Value toValue(ExecutionState& state) = 0; + + void serializeInto(std::ostringstream& outputStream) + { + serializeValueType(outputStream); + serializeValueData(outputStream); + } + +protected: + virtual void serializeValueData(std::ostringstream& outputStream) {} + void serializeValueType(std::ostringstream& outputStream) + { + outputStream << static_cast(type()); + } +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.cpp new file mode 100644 index 0000000..7759776 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include "Escargot.h" +#include "Serializer.h" + +#include "runtime/serialization/SerializedBigIntValue.h" +#include "runtime/serialization/SerializedBooleanValue.h" +#include "runtime/serialization/SerializedNullValue.h" +#include "runtime/serialization/SerializedNumberValue.h" +#include "runtime/serialization/SerializedSharedArrayBufferObjectValue.h" +#include "runtime/serialization/SerializedStringValue.h" +#include "runtime/serialization/SerializedSymbolValue.h" +#include "runtime/serialization/SerializedUndefinedValue.h" + +namespace Escargot { + +std::unique_ptr Serializer::serialize(const Value& value) +{ + if (value.isUndefined()) { + return std::unique_ptr(new SerializedUndefinedValue()); + } else if (value.isNull()) { + return std::unique_ptr(new SerializedNullValue()); + } else if (value.isBoolean()) { + return std::unique_ptr(new SerializedBooleanValue(value.asBoolean())); + } else if (value.isNumber()) { + return std::unique_ptr(new SerializedNumberValue(value.asNumber())); + } else if (value.isString()) { + return std::unique_ptr(new SerializedStringValue(value.asString()->toNonGCUTF8StringData())); + } else if (value.isBigInt()) { + return std::unique_ptr(new SerializedBigIntValue(value.asBigInt()->toString()->toNonGCUTF8StringData())); + } else if (value.isSymbol()) { + if (value.asSymbol()->description()) { + return std::unique_ptr(new SerializedSymbolValue(value.asSymbol()->description()->toNonGCUTF8StringData())); + } else { + return std::unique_ptr(new SerializedSymbolValue()); + } + } else if (value.isObject()) { +#if defined(ENABLE_THREADING) + if (value.asObject()->isSharedArrayBufferObject()) { + return std::unique_ptr(new SerializedSharedArrayBufferObjectValue( + static_cast(value.asObject()->asSharedArrayBufferObject()->backingStore()->deleterData()))); + } +#endif + } + + return nullptr; +} + +bool Serializer::serializeInto(const Value& value, std::ostringstream& output) +{ + auto sv = serialize(value); + if (sv) { + sv->serializeInto(output); + return true; + } + return false; +} + +std::unique_ptr Serializer::deserializeFrom(std::istringstream& input) +{ + unsigned char type; + input >> type; + switch (type) { +#define DECLARE_SERIALIZABLE_TYPE(name) \ + case SerializedValue::Type::name: \ + return Serialized##name##Value::deserializeFrom(input); + FOR_EACH_SERIALIZABLE_TYPE(DECLARE_SERIALIZABLE_TYPE) +#undef DECLARE_SERIALIZABLE_TYPE +#if defined(ENABLE_THREADING) + case SerializedValue::Type::SharedArrayBufferObject: + return SerializedSharedArrayBufferObjectValue::deserializeFrom(input); +#endif + default: + RELEASE_ASSERT_NOT_REACHED(); + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +} // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.h new file mode 100644 index 0000000..f482f33 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __EscargotSerializer__ +#define __EscargotSerializer__ + +#include "runtime/Value.h" +#include "runtime/serialization/SerializedValue.h" + +namespace Escargot { + +class Serializer { +public: + // this function can return nullptr if serialize failed + static std::unique_ptr serialize(const Value& value); + // returns the serialization was successful + static bool serializeInto(const Value& value, std::ostringstream& output); + + static std::unique_ptr deserializeFrom(std::istringstream& input); +}; + +} // namespace Escargot + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/shell/Shell.cpp b/lwnode/code/escargotshim/deps/escargot/src/shell/Shell.cpp index a283fe7..f30fef0 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/shell/Shell.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/shell/Shell.cpp @@ -19,6 +19,13 @@ #include #include +#include +#include +#include + +#include +#include +#include #include "api/EscargotPublic.h" #include "malloc.h" @@ -259,7 +266,12 @@ static ValueRef* builtinGc(ExecutionStateRef* state, ValueRef* thisValue, size_t return ValueRef::createUndefined(); } +PersistentRefHolder createEscargotContext(VMInstanceRef* instance, bool isMainThread = true); + #if defined(ESCARGOT_ENABLE_TEST) + +static bool evalScript(ContextRef* context, StringRef* source, StringRef* srcName, bool shouldPrintScriptResult, bool isModule); + static ValueRef* builtinUneval(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) { if (argc) { @@ -299,11 +311,9 @@ static ValueRef* builtinCreateNewGlobalObject(ExecutionStateRef* state, ValueRef return ContextRef::create(state->context()->vmInstance())->globalObject(); } -PersistentRefHolder createEscargotContext(VMInstanceRef* instance); - static ValueRef* builtin262CreateRealm(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) { - auto newContext = createEscargotContext(state->context()->vmInstance()); + auto newContext = createEscargotContext(state->context()->vmInstance(), false); return newContext->globalObject()->get(state, StringRef::createFromASCII("$262")); } @@ -327,182 +337,218 @@ static ValueRef* builtin262IsHTMLDDA(ExecutionStateRef* state, ValueRef* thisVal { return ValueRef::createNull(); } -#endif +struct WorkerThreadData { + std::string message; + bool running; + volatile bool ended; -PersistentRefHolder createEscargotContext(VMInstanceRef* instance) + WorkerThreadData() + : running(true) + , ended(false) + { + } +}; +std::mutex workerMutex; +std::vector> workerThreads; +std::vector messagesFromWorkers; + +static ValueRef* builtin262AgentStart(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) { - PersistentRefHolder context = ContextRef::create(instance); + std::string script = argv[0]->toString(state)->toStdUTF8String(); - Evaluator::execute(context, [](ExecutionStateRef* state) -> ValueRef* { - ContextRef* context = state->context(); + std::thread worker([](std::string script) { + Globals::initializeThread(); - GlobalObjectProxyObjectRef* proxy = GlobalObjectProxyObjectRef::create(state, state->context()->globalObject(), [](ExecutionStateRef* state, GlobalObjectProxyObjectRef* proxy, GlobalObjectRef* targetGlobalObject, GlobalObjectProxyObjectRef::AccessOperationType operationType, OptionalRef nonIndexedStringPropertyNameIfExists) { - // TODO check security - }); - context->setGlobalObjectProxy(proxy); + Memory::setGCFrequency(24); + PersistentRefHolder instance = VMInstanceRef::create(); + PersistentRefHolder context = createEscargotContext(instance.get(), false); - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "print"), builtinPrint, 1, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("print"), buildFunctionObjectRef, true, true, true); - } + evalScript(context.get(), StringRef::createFromUTF8(script.data(), script.size()), + StringRef::createFromASCII("from main thread"), false, false); - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "load"), builtinLoad, 1, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("load"), buildFunctionObjectRef, true, true, true); - } + while (true) { + { + bool running = false; + std::lock_guard guard(workerMutex); + for (size_t i = 0; i < workerThreads.size(); i++) { + if (workerThreads[i].first.get_id() == std::this_thread::get_id()) { + running = workerThreads[i].second.running; + break; + } + } + if (!running) { + break; + } + } - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "read"), builtinRead, 1, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("read"), buildFunctionObjectRef, true, true, true); - } + // readmessage if exists + std::string message; + { + std::lock_guard guard(workerMutex); + for (size_t i = 0; i < workerThreads.size(); i++) { + if (workerThreads[i].first.get_id() == std::this_thread::get_id()) { + message = std::move(workerThreads[i].second.message); + break; + } + } + } - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "run"), builtinRun, 1, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("run"), buildFunctionObjectRef, true, true, true); - } + if (message.length()) { + std::istringstream istream(message); + ValueRef* val1 = SerializerRef::deserializeFrom(context.get(), istream); + ValueRef* val2 = SerializerRef::deserializeFrom(context.get(), istream); + + ValueRef* callback = (ValueRef*)context.get()->globalObject()->extraData(); + if (callback) { + Evaluator::execute(context.get(), [](ExecutionStateRef* state, ValueRef* callback, ValueRef* v1, ValueRef* v2) -> ValueRef* { + ValueRef* argv[2] = { v1, v2 }; + return callback->call(state, ValueRef::createUndefined(), 2, argv); + }, + callback, val1, val2); + } + } - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "gc"), builtinGc, 0, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("gc"), buildFunctionObjectRef, true, true, true); + usleep(10 * 1000); } -#if defined(ESCARGOT_ENABLE_TEST) - // There is no specific standard for the [@@toStringTag] property of global object. - // But "global" string is added here to pass legacy TCs - context->globalObject()->defineDataProperty(state, context->vmInstance()->toStringTagSymbol(), ObjectRef::DataPropertyDescriptor(AtomicStringRef::create(context, "global")->string(), (ObjectRef::PresentAttribute)(ObjectRef::NonWritablePresent | ObjectRef::NonEnumerablePresent | ObjectRef::ConfigurablePresent))); + context.release(); + instance.release(); - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "uneval"), builtinUneval, 1, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("uneval"), buildFunctionObjectRef, true, true, true); - } + Globals::finalizeThread(); - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "drainJobQueue"), builtinDrainJobQueue, 0, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("drainJobQueue"), buildFunctionObjectRef, true, true, true); + std::lock_guard guard(workerMutex); + for (size_t i = 0; i < workerThreads.size(); i++) { + if (workerThreads[i].first.get_id() == std::this_thread::get_id()) { + workerThreads[i].second.ended = true; + } } + }, + script); - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "addPromiseReactions"), builtinAddPromiseReactions, 3, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("addPromiseReactions"), buildFunctionObjectRef, true, true, true); - } + { + std::lock_guard guard(workerMutex); + workerThreads.push_back(std::make_pair(std::move(worker), WorkerThreadData())); + } - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "createNewGlobalObject"), builtinCreateNewGlobalObject, 0, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("createNewGlobalObject"), buildFunctionObjectRef, true, true, true); - } + return ValueRef::createUndefined(); +} - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "newGlobal"), builtinCreateNewGlobalObject, 0, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("newGlobal"), buildFunctionObjectRef, true, true, true); +static ValueRef* builtin262AgentBroadcast(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) +{ + std::ostringstream ostream; + if (argc > 0) { + SerializerRef::serializeInto(argv[0], ostream); + } else { + SerializerRef::serializeInto(ValueRef::createUndefined(), ostream); + } + if (argc > 1) { + SerializerRef::serializeInto(argv[1], ostream); + } else { + SerializerRef::serializeInto(ValueRef::createUndefined(), ostream); + } + + + std::string message(ostream.str()); + { + std::lock_guard guard(workerMutex); + for (size_t i = 0; i < workerThreads.size(); i++) { + workerThreads[i].second.message = message; } + } - // https://github.com/tc39/test262/blob/master/INTERPRETING.md + while (true) { + bool thereIsNoMessage = true; { - ObjectRef* dollor262Object = ObjectRef::create(state); - - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "gc"), builtinGc, 0, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - dollor262Object->defineDataProperty(state, StringRef::createFromASCII("gc"), buildFunctionObjectRef, true, true, true); + std::lock_guard guard(workerMutex); + for (size_t i = 0; i < workerThreads.size(); i++) { + if (workerThreads[i].second.message.size()) { + thereIsNoMessage = false; + break; + } } + } - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "createRealm"), builtin262CreateRealm, 0, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - dollor262Object->defineDataProperty(state, StringRef::createFromASCII("createRealm"), buildFunctionObjectRef, true, true, true); - } + if (thereIsNoMessage) { + break; + } - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "detachArrayBuffer"), builtin262DetachArrayBuffer, 1, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - dollor262Object->defineDataProperty(state, StringRef::createFromASCII("detachArrayBuffer"), buildFunctionObjectRef, true, true, true); - } + usleep(10 * 1000); // sleep 10ms + } - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "evalScript"), builtin262EvalScript, 1, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - dollor262Object->defineDataProperty(state, StringRef::createFromASCII("evalScript"), buildFunctionObjectRef, true, true, true); - } - { - dollor262Object->defineDataProperty(state, StringRef::createFromASCII("global"), context->globalObjectProxy(), true, true, true); - } + return ValueRef::createUndefined(); +} - { - FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "IsHTMLDDA"), builtin262IsHTMLDDA, 0, true, false); - FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); - buildFunctionObjectRef->setIsHTMLDDA(); - dollor262Object->defineDataProperty(state, StringRef::createFromASCII("IsHTMLDDA"), buildFunctionObjectRef, true, true, true); - } +static ValueRef* builtin262AgentReport(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) +{ + std::string message; + if (argc > 0) { + message = argv[0]->toString(state)->toStdUTF8String(); + } + std::lock_guard guard(workerMutex); + messagesFromWorkers.push_back(message); + return ValueRef::createUndefined(); +} - context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("$262"), dollor262Object, true, false, true); +static ValueRef* builtin262AgentLeaving(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) +{ + std::lock_guard guard(workerMutex); + for (size_t i = 0; i < workerThreads.size(); i++) { + if (workerThreads[i].first.get_id() == std::this_thread::get_id()) { + workerThreads[i].second.running = false; + break; } -#endif - return ValueRef::createUndefined(); - }); + } + return ValueRef::createUndefined(); +} - return context; +static ValueRef* builtin262AgentReceiveBroadcast(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) +{ + state->context()->globalObject()->setExtraData(argv[0]); + return ValueRef::createUndefined(); } -class ShellPlatform : public PlatformRef { -public: - virtual void markJSJobEnqueued(ContextRef* relatedContext) override - { - // ignore. we always check pending job after eval script +static ValueRef* builtin262AgentGetReport(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) +{ + std::lock_guard guard(workerMutex); + if (messagesFromWorkers.size()) { + std::string message = messagesFromWorkers.front(); + messagesFromWorkers.erase(messagesFromWorkers.begin()); + return StringRef::createFromUTF8(message.data(), message.size()); + } else { + return ValueRef::createNull(); } +} - static std::string dirnameOf(const std::string& fname) - { - size_t pos = fname.find_last_of("/"); - if (std::string::npos == pos) { - pos = fname.find_last_of("\\/"); - } - return (std::string::npos == pos) - ? "" - : fname.substr(0, pos); - } +static ValueRef* builtin262AgentMonotonicNow(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return ValueRef::create((uint64_t)tv.tv_sec * 1000UL + tv.tv_usec / 1000UL); +} - static std::string absolutePath(const std::string& referrerPath, const std::string& src) - { - std::string utf8MayRelativePath = dirnameOf(referrerPath) + "/" + src; - auto absPath = realpath(utf8MayRelativePath.data(), nullptr); - if (!absPath) { - return std::string(); - } - std::string utf8AbsolutePath = absPath; - free(absPath); +static ValueRef* builtin262AgentSleep(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) +{ + double m = argv[0]->toNumber(state); + usleep(m * 1000.0); + return ValueRef::createUndefined(); +} - return utf8AbsolutePath; - } +#endif - static std::string absolutePath(const std::string& src) +class ShellPlatform : public PlatformRef { +public: + virtual void markJSJobEnqueued(ContextRef* relatedContext) override { - auto absPath = realpath(src.data(), nullptr); - if (!absPath) { - return std::string(); - } - std::string utf8AbsolutePath = absPath; - free(absPath); - - return utf8AbsolutePath; + // ignore. we always check pending job after eval script } - std::vector>> loadedModules; virtual LoadModuleResult onLoadModule(ContextRef* relatedContext, ScriptRef* whereRequestFrom, StringRef* moduleSrc) override { std::string referrerPath = whereRequestFrom->src()->toStdUTF8String(); + auto& loadedModules = *reinterpret_cast>>*>(threadLocalCustomData()); for (size_t i = 0; i < loadedModules.size(); i++) { if (std::get<2>(loadedModules[i]) == whereRequestFrom) { @@ -545,6 +591,7 @@ public: } else { path = absolutePath(loadedModule->src()->toStdUTF8String()); } + auto& loadedModules = *reinterpret_cast>>*>(threadLocalCustomData()); loadedModules.push_back(std::make_tuple(path, relatedContext, PersistentRefHolder(loadedModule))); } @@ -553,6 +600,53 @@ public: LoadModuleResult loadedModuleResult = onLoadModule(relatedContext, referrer, src); notifyHostImportModuleDynamicallyResult(relatedContext, referrer, src, promise, loadedModuleResult); } + + virtual void* allocateThreadLocalCustomData() override + { + return new std::vector>>(); + } + + virtual void deallocateThreadLocalCustomData() override + { + delete reinterpret_cast>>*>(threadLocalCustomData()); + } + +private: + std::string dirnameOf(const std::string& fname) + { + size_t pos = fname.find_last_of("/"); + if (std::string::npos == pos) { + pos = fname.find_last_of("\\/"); + } + return (std::string::npos == pos) + ? "" + : fname.substr(0, pos); + } + + std::string absolutePath(const std::string& referrerPath, const std::string& src) + { + std::string utf8MayRelativePath = dirnameOf(referrerPath) + "/" + src; + auto absPath = realpath(utf8MayRelativePath.data(), nullptr); + if (!absPath) { + return std::string(); + } + std::string utf8AbsolutePath = absPath; + free(absPath); + + return utf8AbsolutePath; + } + + std::string absolutePath(const std::string& src) + { + auto absPath = realpath(src.data(), nullptr); + if (!absPath) { + return std::string(); + } + std::string utf8AbsolutePath = absPath; + free(absPath); + + return utf8AbsolutePath; + } }; static bool evalScript(ContextRef* context, StringRef* source, StringRef* srcName, bool shouldPrintScriptResult, bool isModule) @@ -622,6 +716,189 @@ static bool evalScript(ContextRef* context, StringRef* source, StringRef* srcNam return result; } + +PersistentRefHolder createEscargotContext(VMInstanceRef* instance, bool isMainThread) +{ + PersistentRefHolder context = ContextRef::create(instance); + + Evaluator::execute(context, [](ExecutionStateRef* state, bool isMainThread) -> ValueRef* { + ContextRef* context = state->context(); + + GlobalObjectProxyObjectRef* proxy = GlobalObjectProxyObjectRef::create(state, state->context()->globalObject(), [](ExecutionStateRef* state, GlobalObjectProxyObjectRef* proxy, GlobalObjectRef* targetGlobalObject, GlobalObjectProxyObjectRef::AccessOperationType operationType, OptionalRef nonIndexedStringPropertyNameIfExists) { + // TODO check security + }); + context->setGlobalObjectProxy(proxy); + + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "print"), builtinPrint, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("print"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "load"), builtinLoad, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("load"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "read"), builtinRead, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("read"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "run"), builtinRun, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("run"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "gc"), builtinGc, 0, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("gc"), buildFunctionObjectRef, true, true, true); + } + +#if defined(ESCARGOT_ENABLE_TEST) + // There is no specific standard for the [@@toStringTag] property of global object. + // But "global" string is added here to pass legacy TCs + context->globalObject()->defineDataProperty(state, context->vmInstance()->toStringTagSymbol(), ObjectRef::DataPropertyDescriptor(AtomicStringRef::create(context, "global")->string(), (ObjectRef::PresentAttribute)(ObjectRef::NonWritablePresent | ObjectRef::NonEnumerablePresent | ObjectRef::ConfigurablePresent))); + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "uneval"), builtinUneval, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("uneval"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "drainJobQueue"), builtinDrainJobQueue, 0, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("drainJobQueue"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "addPromiseReactions"), builtinAddPromiseReactions, 3, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("addPromiseReactions"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "createNewGlobalObject"), builtinCreateNewGlobalObject, 0, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("createNewGlobalObject"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "newGlobal"), builtinCreateNewGlobalObject, 0, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("newGlobal"), buildFunctionObjectRef, true, true, true); + } + + // https://github.com/tc39/test262/blob/master/INTERPRETING.md + { + ObjectRef* dollor262Object = ObjectRef::create(state); + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "gc"), builtinGc, 0, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + dollor262Object->defineDataProperty(state, StringRef::createFromASCII("gc"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "createRealm"), builtin262CreateRealm, 0, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + dollor262Object->defineDataProperty(state, StringRef::createFromASCII("createRealm"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "detachArrayBuffer"), builtin262DetachArrayBuffer, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + dollor262Object->defineDataProperty(state, StringRef::createFromASCII("detachArrayBuffer"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "evalScript"), builtin262EvalScript, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + dollor262Object->defineDataProperty(state, StringRef::createFromASCII("evalScript"), buildFunctionObjectRef, true, true, true); + } + + { + dollor262Object->defineDataProperty(state, StringRef::createFromASCII("global"), context->globalObjectProxy(), true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "IsHTMLDDA"), builtin262IsHTMLDDA, 0, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + buildFunctionObjectRef->setIsHTMLDDA(); + dollor262Object->defineDataProperty(state, StringRef::createFromASCII("IsHTMLDDA"), buildFunctionObjectRef, true, true, true); + } + + if (Globals::supportsThreading()) { + ObjectRef* agentObject = ObjectRef::create(state); + if (isMainThread) { + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "start"), builtin262AgentStart, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + agentObject->defineDataProperty(state, StringRef::createFromASCII("start"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "broadcast"), builtin262AgentBroadcast, 2, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + agentObject->defineDataProperty(state, StringRef::createFromASCII("broadcast"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "getReport"), builtin262AgentGetReport, 0, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + agentObject->defineDataProperty(state, StringRef::createFromASCII("getReport"), buildFunctionObjectRef, true, true, true); + } + } else { + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "leaving"), builtin262AgentLeaving, 0, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + agentObject->defineDataProperty(state, StringRef::createFromASCII("leaving"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "receiveBroadcast"), builtin262AgentReceiveBroadcast, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + agentObject->defineDataProperty(state, StringRef::createFromASCII("receiveBroadcast"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "report"), builtin262AgentReport, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + agentObject->defineDataProperty(state, StringRef::createFromASCII("report"), buildFunctionObjectRef, true, true, true); + } + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "monotonicNow"), builtin262AgentMonotonicNow, 0, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + agentObject->defineDataProperty(state, StringRef::createFromASCII("monotonicNow"), buildFunctionObjectRef, true, true, true); + } + + { + FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "sleep"), builtin262AgentSleep, 1, true, false); + FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo); + agentObject->defineDataProperty(state, StringRef::createFromASCII("sleep"), buildFunctionObjectRef, true, true, true); + } + + dollor262Object->defineDataProperty(state, StringRef::createFromASCII("agent"), agentObject, true, false, true); + } + + context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("$262"), dollor262Object, true, false, true); + } +#endif + return ValueRef::createUndefined(); + }, + isMainThread); + + return context; +} + int main(int argc, char* argv[]) { #ifndef NDEBUG @@ -636,15 +913,11 @@ int main(int argc, char* argv[]) mallopt(M_MMAP_MAX, 1024 * 1024); #endif - Globals::initialize(); + Globals::initialize(new ShellPlatform()); Memory::setGCFrequency(24); - ShellPlatform* platform = new ShellPlatform(); - PersistentRefHolder instance = VMInstanceRef::create(platform); - instance->setOnVMInstanceDelete([](VMInstanceRef* instance) { - delete instance->platform(); - }); + PersistentRefHolder instance = VMInstanceRef::create(); PersistentRefHolder context = createEscargotContext(instance.get()); if (getenv("GC_FREE_SPACE_DIVISOR") && strlen(getenv("GC_FREE_SPACE_DIVISOR"))) { @@ -733,6 +1006,10 @@ int main(int argc, char* argv[]) } } + if (runShell && !context->isDebuggerRunning()) { + printf("escargot version:%s, %s%s\n", Globals::version(), Globals::buildDate(), Globals::supportsThreading() ? "(supports threading)" : ""); + } + while (runShell) { static char buf[2048]; printf("escargot> "); @@ -744,6 +1021,30 @@ int main(int argc, char* argv[]) evalScript(context, str, StringRef::createFromASCII("from shell input"), true, false); } +#if defined(ESCARGOT_ENABLE_TEST) + while (true) { + bool everyThreadIsEnded = true; + { + std::lock_guard guard(workerMutex); + for (auto& i : workerThreads) { + if (!i.second.ended) { + everyThreadIsEnded = false; + break; + } + } + } + if (everyThreadIsEnded) { + break; + } + + usleep(10 * 1000); + } + + for (auto& i : workerThreads) { + i.first.join(); + } +#endif + context.release(); instance.release(); diff --git a/lwnode/code/escargotshim/deps/escargot/src/util/SpinLock.h b/lwnode/code/escargotshim/deps/escargot/src/util/SpinLock.h new file mode 100644 index 0000000..d96ef74 --- /dev/null +++ b/lwnode/code/escargotshim/deps/escargot/src/util/SpinLock.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#if defined(ENABLE_THREADING) + +#ifndef __EscargotSpinLock__ +#define __EscargotSpinLock__ + +#include + +namespace Escargot { + +class SpinLock { + std::atomic_flag m_locked; + +public: + SpinLock() + : m_locked(0) + { + } + + void lock() + { + while (m_locked.test_and_set(std::memory_order_acquire)) { + } + } + + void unlock() + { + m_locked.clear(std::memory_order_release); + } +}; + +} // namespace Escargot + +#endif + +#endif diff --git a/lwnode/code/escargotshim/deps/escargot/src/wasm/GlobalObjectBuiltinWASM.cpp b/lwnode/code/escargotshim/deps/escargot/src/wasm/GlobalObjectBuiltinWASM.cpp index 946a8e2..ca87e12 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/wasm/GlobalObjectBuiltinWASM.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/wasm/GlobalObjectBuiltinWASM.cpp @@ -23,6 +23,7 @@ #include "wasm.h" #include "runtime/GlobalObject.h" #include "runtime/Context.h" +#include "runtime/ThreadLocal.h" #include "runtime/VMInstance.h" #include "runtime/NativeFunctionObject.h" #include "runtime/ExtendedNativeFunctionObject.h" @@ -124,7 +125,7 @@ static Value builtinWASMValidate(ExecutionState& state, Value thisValue, size_t wasm_byte_vec_new_uninitialized(&binary, byteLength); memcpy(binary.data, srcBuffer->data(), byteLength); - bool result = wasm_module_validate(VMInstance::wasmStore(), &binary); + bool result = wasm_module_validate(ThreadLocal::wasmStore(), &binary); wasm_byte_vec_delete(&binary); return Value(result); @@ -346,7 +347,7 @@ static Value builtinWASMInstanceConstructor(ExecutionState& state, Value thisVal // Instantiate the core of a WebAssembly module module with imports, and let instance be the result. own wasm_trap_t* trap = nullptr; - own wasm_instance_t* instance = wasm_instance_new(VMInstance::wasmStore(), module, imports.data, &trap); + own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, imports.data, &trap); wasm_extern_vec_delete(&imports); if (!instance) { @@ -428,7 +429,7 @@ static Value builtinWASMMemoryConstructor(ExecutionState& state, Value thisValue own wasm_memorytype_t* memtype = wasm_memorytype_new(&limits); // Let (store, memaddr) be mem_alloc(store, memtype). If allocation fails, throw a RangeError exception. - own wasm_memory_t* memaddr = wasm_memory_new(VMInstance::wasmStore(), memtype); + own wasm_memory_t* memaddr = wasm_memory_new(ThreadLocal::wasmStore(), memtype); wasm_memorytype_delete(memtype); wasm_ref_t* memref = wasm_memory_as_ref(memaddr); @@ -621,7 +622,7 @@ static Value builtinWASMTableConstructor(ExecutionState& state, Value thisValue, own wasm_tabletype_t* tabletype = wasm_tabletype_new(wasm_valtype_new(WASM_FUNCREF), &limits); // Let (store, tableaddr) be table_alloc(store, type). - own wasm_table_t* tableaddr = wasm_table_new(VMInstance::wasmStore(), tabletype, nullptr); + own wasm_table_t* tableaddr = wasm_table_new(ThreadLocal::wasmStore(), tabletype, nullptr); wasm_tabletype_delete(tabletype); wasm_ref_t* tableref = wasm_table_as_ref(tableaddr); @@ -841,7 +842,7 @@ static Value builtinWASMGlobalConstructor(ExecutionState& state, Value thisValue own wasm_globaltype_t* globaltype = wasm_globaltype_new(wasm_valtype_new(valuetype), mut); // Let (store, globaladdr) be global_alloc(store, globaltype, value). - own wasm_global_t* globaladdr = wasm_global_new(VMInstance::wasmStore(), globaltype, &value); + own wasm_global_t* globaladdr = wasm_global_new(ThreadLocal::wasmStore(), globaltype, &value); wasm_globaltype_delete(globaltype); wasm_ref_t* globalref = wasm_global_as_ref(globaladdr); diff --git a/lwnode/code/escargotshim/deps/escargot/src/wasm/WASMOperations.cpp b/lwnode/code/escargotshim/deps/escargot/src/wasm/WASMOperations.cpp index b076781..90b00c5 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/wasm/WASMOperations.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/wasm/WASMOperations.cpp @@ -21,6 +21,7 @@ #include "Escargot.h" #include "wasm.h" +#include "runtime/ThreadLocal.h" #include "runtime/VMInstance.h" #include "runtime/Job.h" #include "runtime/ArrayBufferObject.h" @@ -121,7 +122,7 @@ static own wasm_func_t* wasmCreateHostFunction(ExecutionState& state, Object* fu own wasm_functype_t* functypeCopy = wasm_functype_copy(functype); WASMHostFunctionEnvironment* env = new WASMHostFunctionEnvironment(func, functypeCopy); - own wasm_func_t* funcaddr = wasm_func_new_with_env(VMInstance::wasmStore(), functypeCopy, callbackHostFunction, env, nullptr); + own wasm_func_t* funcaddr = wasm_func_new_with_env(ThreadLocal::wasmStore(), functypeCopy, callbackHostFunction, env, nullptr); state.context()->wasmEnvCache()->push_back(env); @@ -146,7 +147,7 @@ static Value wasmInstantiateModule(ExecutionState& state, Value thisValue, size_ // Instantiate the core of a WebAssembly module module with imports, and let instance be the result. own wasm_trap_t* trap = nullptr; - own wasm_instance_t* instance = wasm_instance_new(VMInstance::wasmStore(), module, imports.data, &trap); + own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, imports.data, &trap); wasm_extern_vec_delete(&imports); if (!instance) { @@ -187,7 +188,7 @@ Value WASMOperations::copyStableBufferBytes(ExecutionState& state, Value source) copyBuffer = ArrayBufferObject::cloneArrayBuffer(state, srcBuffer, 0, srcBuffer->byteLength(), state.context()->globalObject()->arrayBuffer()); } else if (srcObject->isTypedArrayObject()) { TypedArrayObject* srcArray = srcObject->asTypedArrayObject(); - ArrayBufferObject* srcBuffer = srcArray->buffer(); + ArrayBuffer* srcBuffer = srcArray->buffer(); copyBuffer = ArrayBufferObject::cloneArrayBuffer(state, srcBuffer, srcArray->byteOffset(), srcArray->arrayLength() * srcArray->elementSize(), state.context()->globalObject()->arrayBuffer()); } } @@ -212,7 +213,7 @@ Value WASMOperations::compileModule(ExecutionState& state, Value thisValue, size wasm_byte_vec_new_uninitialized(&binary, byteLength); memcpy(binary.data, srcBuffer->data(), byteLength); - own wasm_module_t* module = wasm_module_new(VMInstance::wasmStore(), &binary); + own wasm_module_t* module = wasm_module_new(ThreadLocal::wasmStore(), &binary); wasm_byte_vec_delete(&binary); if (!module) { @@ -440,7 +441,7 @@ void WASMOperations::readImportsOfModule(ExecutionState& state, wasm_module_t* m // Let (store, globaladdr) be global_alloc(store, const valtype, value). // FIXME globaltype own wasm_globaltype_t* globaltype = wasm_globaltype_new(wasm_valtype_new(wasm_valtype_kind(valtype)), WASM_CONST); - globaladdr = wasm_global_new(VMInstance::wasmStore(), globaltype, &value); + globaladdr = wasm_global_new(ThreadLocal::wasmStore(), globaltype, &value); wasm_globaltype_delete(globaltype); } else if (v.isObject() && v.asObject()->isWASMGlobalObject()) { @@ -526,7 +527,7 @@ Value WASMOperations::instantiateCoreModule(ExecutionState& state, Value thisVal // Instantiate the core of a WebAssembly module module with imports, and let instance be the result. own wasm_trap_t* trap = nullptr; - own wasm_instance_t* instance = wasm_instance_new(VMInstance::wasmStore(), module, imports.data, &trap); + own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, imports.data, &trap); wasm_extern_vec_delete(&imports); if (!instance) { @@ -561,7 +562,7 @@ Object* WASMOperations::instantiatePromiseOfModuleWithImportObject(ExecutionStat void WASMOperations::collectHeap() { // collect (GC) WASM Objects allocated inside WASM heap - wasm_store_gc(VMInstance::wasmStore()); + wasm_store_gc(ThreadLocal::wasmStore()); } } // namespace Escargot diff --git a/lwnode/code/escargotshim/deps/escargot/third_party/wasm/CMakeLists.txt b/lwnode/code/escargotshim/deps/escargot/third_party/wasm/CMakeLists.txt index 89fb35d..9e49187 100644 --- a/lwnode/code/escargotshim/deps/escargot/third_party/wasm/CMakeLists.txt +++ b/lwnode/code/escargotshim/deps/escargot/third_party/wasm/CMakeLists.txt @@ -36,7 +36,14 @@ check_symbol_exists(strcasecmp "strings.h" HAVE_STRCASECMP) include(CheckTypeSize) check_type_size(ssize_t SSIZE_T) -check_type_size(size_t SIZEOF_SIZE_T) +#check_type_size(size_t SIZEOF_SIZE_T) + +# Escargot specific option (for the case of compilation to 32bit from 64bit) +if (ESCARGOT_BUILD_32BIT) + set(SIZEOF_SIZE_T 4) +else () + set(SIZEOF_SIZE_T 8) +endif () set(WABT_ROOT ${PROJECT_SOURCE_DIR}/wabt) configure_file(${WABT_ROOT}/src/config.h.in ${PROJECT_SOURCE_DIR}/config.h) @@ -141,10 +148,13 @@ set(WABT_SRC # disable -Wpointer-arith: this is a GCC extension, and doesn't work in MSVC. set(WASM_CXX_FLAGS_INTERNAL - -Wall -Wextra -Wno-unused-parameter -Wpointer-arith - -Wuninitialized -std=c++11 -Wold-style-cast -fno-exceptions -fPIC -fdata-sections -ffunction-sections + -Wall -Wextra -Werror -Wno-unused-parameter -Wpointer-arith + -Wuninitialized -fno-exceptions -fPIC -fdata-sections -ffunction-sections ) +# set c++ flags +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wold-style-cast") + # Need to define __STDC_*_MACROS because C99 specifies that C++ shouldn't # define format (e.g. PRIu64) or limit (e.g. UINT32_MAX) macros without the # definition, and some libcs (e.g. glibc2.17 and earlier) follow that. @@ -166,7 +176,7 @@ add_compile_options(${WASM_CXX_FLAGS}) set(WASM_CFLAGS_FROM_ENV $ENV{CFLAGS}) separate_arguments(WASM_CFLAGS_FROM_ENV) -add_compile_options(${WASM_CXX_FLAGS_FROM_ENV}) +add_compile_options(${WASM_CFLAGS_FROM_ENV}) # build wabt lib add_library(wabt STATIC ${WABT_SRC}) diff --git a/lwnode/code/escargotshim/escargot.gyp b/lwnode/code/escargotshim/escargot.gyp index 6942a2b..55114f5 100755 --- a/lwnode/code/escargotshim/escargot.gyp +++ b/lwnode/code/escargotshim/escargot.gyp @@ -1,11 +1,13 @@ { 'includes': ['common.gypi'], 'variables': { + 'target_arch%': '<(target_arch)', + 'target_os%': '<(target_os)', + 'build_host%': '<(build_host)', + 'build_asan%': '<(build_asan)', 'escargot_dir%': 'deps/escargot', "escargot_lib_type%": 'shared_lib', # static_lib | shared_lib - 'build_asan%': '<(build_asan)', - 'target_arch%': '<(target_arch)', -# 'escargot_arch%': 'x64', + 'escargot_threading%': '<(escargot_threading)', 'conditions': [ ['escargot_lib_type=="shared_lib"', { 'lib_ext': '.so' @@ -18,12 +20,21 @@ ['target_arch=="x32"', { 'target_arch': 'i686' }], + ['target_os=="tizen"', { + # tizen build host is fixed to gbs + 'build_host': 'tizen_obs' + }], ], }, 'targets': [{ 'target_name': 'escargot', 'type': 'none', 'variables': { + 'configs': ' -#include "../src/unimplemented.h" namespace v8 { class Isolate; diff --git a/lwnode/code/escargotshim/include/lwnode/lwnode.h b/lwnode/code/escargotshim/include/lwnode/lwnode.h new file mode 100644 index 0000000..d196252 --- /dev/null +++ b/lwnode/code/escargotshim/include/lwnode/lwnode.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021-present Samsung Electronics 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. + */ + +#pragma once + +#include +#include + +namespace LWNode { + +void InitializeProcessMethods(v8::Local target, + v8::Local context); + +bool dumpSelfMemorySnapshot(); + +class Utils { + public: + // should return string buffer + typedef void* (*LoadCallback)(void* callbackData); + // should free memoryPtr + typedef void (*UnloadCallback)(void* memoryPtr, void* callbackData); + + struct ReloadableSourceData { + void* preloadedData{nullptr}; + + const char* path() { return path_; } + size_t preloadedDataLength() { return preloadedDataLength_; } + static ReloadableSourceData* create(std::string sourcePath, + void* preloadedData, + size_t preloadedDataLength); + + private: + char* path_{nullptr}; + size_t preloadedDataLength_{0}; + ReloadableSourceData() = default; + }; + + static v8::MaybeLocal NewReloadableStringFromOneByte( + v8::Isolate* isolate, + ReloadableSourceData* data, + LoadCallback loadCallback, + UnloadCallback unloadCallback); +}; + +} // namespace LWNode diff --git a/lwnode/code/escargotshim/include/v8.h b/lwnode/code/escargotshim/include/v8.h index b60ebe7..271fafd 100644 --- a/lwnode/code/escargotshim/include/v8.h +++ b/lwnode/code/escargotshim/include/v8.h @@ -12155,6 +12155,8 @@ MaybeLocal Isolate::GetDataFromSnapshotOnce(size_t index) { int64_t Isolate::AdjustAmountOfExternalAllocatedMemory( int64_t change_in_bytes) { +// @lwnode +#if 0 typedef internal::Internals I; int64_t* external_memory = reinterpret_cast( reinterpret_cast(this) + I::kExternalMemoryOffset); @@ -12182,6 +12184,8 @@ int64_t Isolate::AdjustAmountOfExternalAllocatedMemory( ReportExternalAllocationLimitReached(); } return *external_memory; +#endif + return 0; } Local Context::GetEmbedderData(int index) { diff --git a/lwnode/code/escargotshim/lib/stack_frame.js b/lwnode/code/escargotshim/lib/stack_frame.js deleted file mode 100644 index d899cc8..0000000 --- a/lwnode/code/escargotshim/lib/stack_frame.js +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2021-present Samsung Electronics 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 () { - // Simulate V8 JavaScript stack trace API - function StackFrame(func, funcName, fileName, lineNumber, columnNumber) { - this.column = columnNumber | 0; - this.lineNumber = lineNumber | 0; - this.scriptName = fileName | 'Unknown'; - this.functionName = funcName | 'Unknown'; - this.function = func | function () { }; - } - - StackFrame.prototype.getFunction = function () { - // TODO: Fix if .stack is called from different callsite - // from where Error() or Error.captureStackTrace was called - return this.function; - }; - - StackFrame.prototype.getTypeName = function () { - //TODO : Fix this - return this.functionName; - }; - - StackFrame.prototype.getMethodName = function () { - return this.functionName; - }; - - StackFrame.prototype.getFunctionName = function () { - return this.functionName; - }; - - StackFrame.prototype.getFileName = function () { - return this.scriptName; - }; - - StackFrame.prototype.getLineNumber = function () { - return this.lineNumber; - }; - - StackFrame.prototype.getColumnNumber = function () { - return this.column; - }; - - StackFrame.prototype.isEval = function () { - // TODO - return false; - }; - - StackFrame.prototype.isToplevel = function () { - // TODO - return false; - }; - - StackFrame.prototype.isNative = function () { - // TODO - return false; - }; - - StackFrame.prototype.isConstructor = function () { - // TODO - return false; - }; - - StackFrame.prototype.toString = function () { - return (this.functionName || 'Anonymous function') + ' (' + - this.scriptName + ':' + this.lineNumber + ':' + this.column + ')'; - }; - - function captureStackTrace(err, func) { - // TODO: implement error stack - err.stack = []; - err.stack.push( - new StackFrame(func, undefined, undefined, undefined, undefined)); - err.stack.push( - new StackFrame(func, undefined, undefined, undefined, undefined)); - err.stack.push( - new StackFrame(func, undefined, undefined, undefined, undefined)); - } - - Error.captureStackTrace = captureStackTrace; - -})(); diff --git a/lwnode/code/escargotshim/src/api-data.cc b/lwnode/code/escargotshim/src/api-data.cc index 2fab46c..e3f9d89 100644 --- a/lwnode/code/escargotshim/src/api-data.cc +++ b/lwnode/code/escargotshim/src/api-data.cc @@ -18,6 +18,8 @@ #include "api/utils.h" #include "base.h" +#include + using namespace Escargot; using namespace EscargotShim; @@ -106,7 +108,7 @@ bool Value::IsDataView() const { } bool Value::IsSharedArrayBuffer() const { - LWNODE_RETURN_FALSE; + return CVAL(this)->value()->isSharedArrayBufferObject(); } bool Value::IsObject() const { @@ -513,7 +515,8 @@ std::unique_ptr v8::BackingStore::Reallocate( v8::Isolate* isolate, std::unique_ptr backing_store, size_t byte_length) { - LWNODE_UNIMPLEMENT; + auto self = reinterpret_cast(backing_store.get()); + self->reallocate(byte_length); return backing_store; } @@ -532,7 +535,7 @@ std::shared_ptr v8::ArrayBuffer::GetBackingStore() { if (esSelf->backingStore().hasValue()) { esBackingStore = esSelf->backingStore().value(); } else { - esBackingStore = BackingStoreRef::create(lwIsolate->vmInstance(), 0); + esBackingStore = BackingStoreRef::create(0); } return std::shared_ptr( @@ -1035,10 +1038,6 @@ Maybe v8::Object::DefineOwnProperty(v8::Local context, v8::PropertyAttribute attributes) { API_ENTER_WITH_CONTEXT(context, Nothing()); - if (attributes == None) { - return Set(context, key, value); - } - auto r = ObjectRefHelper::defineDataProperty( CVAL(*context)->context()->get(), CVAL(this)->value()->asObject(), @@ -1114,40 +1113,14 @@ Maybe v8::Object::GetPropertyAttributes( auto esSelf = CVAL(this)->value()->asObject(); auto esKey = CVAL(*key)->value(); - PropertyAttribute attr; - EvalResult r = Evaluator::execute( - esContext, - [](ExecutionStateRef* esState, - ObjectRef* esSelf, - ValueRef* esKey, - PropertyAttribute* attr) -> ValueRef* { - auto val = esSelf->getOwnPropertyDescriptor(esState, esKey); - bool isWritable = - val->asObject() - ->get(esState, StringRef::createFromASCII("writable")) - ->asBoolean(); - bool isEnumerable = - val->asObject() - ->get(esState, StringRef::createFromASCII("enumerable")) - ->asBoolean(); - bool isConfigurable = - val->asObject() - ->get(esState, StringRef::createFromASCII("configurable")) - ->asBoolean(); - - *attr = *attr | !isWritable ? PropertyAttribute::ReadOnly - : PropertyAttribute::None; - *attr = *attr | !isEnumerable ? PropertyAttribute::DontEnum - : PropertyAttribute::None; - *attr = *attr | !isConfigurable ? PropertyAttribute::DontDelete - : PropertyAttribute::None; - return val; - }, - esSelf, - esKey, - &attr); + auto r = ObjectRefHelper::getPropertyAttributes(esContext, esSelf, esKey); API_HANDLE_EXCEPTION(r, lwIsolate, Nothing()); + if (r.result->isUndefined()) { + return Just(PropertyAttribute::None); + } + + PropertyAttribute attr = static_cast(r.result->asUInt32()); return Just(attr); } @@ -1465,7 +1438,7 @@ Maybe Object::SetAccessor(Local context, Local dataLocalValue; if (!data.ToLocal(&dataLocalValue)) { dataLocalValue = - Utils::NewLocal(lwIsolate->toV8(), lwIsolate->undefined()); + Utils::NewLocal(lwIsolate->toV8(), lwIsolate->undefined_value()); } return ObjectUtils::SetAccessor( @@ -1555,12 +1528,39 @@ v8::Object::GetRealNamedPropertyAttributesInPrototypeChain( MaybeLocal v8::Object::GetRealNamedProperty(Local context, Local key) { - LWNODE_RETURN_LOCAL(Value); + API_ENTER_WITH_CONTEXT(context, MaybeLocal()); + + auto r = ObjectRefHelper::getOwnProperty(VAL(*context)->context()->get(), + VAL(this)->value()->asObject(), + VAL(*key)->value()); + + API_HANDLE_EXCEPTION(r, lwIsolate, MaybeLocal()); + + if (r.result->isUndefined()) { + return MaybeLocal(); + } + + return Utils::NewLocal(lwIsolate->toV8(), r.result); } Maybe v8::Object::GetRealNamedPropertyAttributes( - Local context, - Local key){LWNODE_RETURN_MAYBE(PropertyAttribute)} + Local context, Local key) { + API_ENTER_WITH_CONTEXT(context, Nothing()); + + auto r = + ObjectRefHelper::getPropertyAttributes(VAL(*context)->context()->get(), + CVAL(this)->value()->asObject(), + CVAL(*key)->value(), + true); + API_HANDLE_EXCEPTION(r, lwIsolate, Nothing()); + + if (r.result->isUndefined()) { + return Just(PropertyAttribute::None); + } + + auto attr = static_cast(r.result->asUInt32()); + return Just(V8Helper::toPropertyAttribute(attr)); +} Local v8::Object::Clone() { auto lwIsolate = IsolateWrap::GetCurrent(); @@ -1602,10 +1602,27 @@ Local v8::Object::Clone() { Local v8::Object::CreationContext() { auto lwIsolate = IsolateWrap::GetCurrent(); - LWNODE_DCHECK_MSG(lwIsolate->getNumberOfContexts() == 1, - "%zu", - lwIsolate->getNumberOfContexts()); - return v8::Utils::NewLocal(lwIsolate->toV8(), lwIsolate->GetCurrentContext()); + auto esSelf = CVAL(this)->value()->asObject(); + + auto esVal = esSelf->creationContext(); + if (!esVal.hasValue()) { + return Local(); + } + + auto globalObjectData = + ObjectRefHelper::getExtraData(esVal.get()->globalObject()) + ->asGlobalObjectData(); + + LWNODE_CHECK(globalObjectData->internalFieldCount() == + GlobalObjectData::kInternalFieldCount); + + auto lwCreationContext = reinterpret_cast( + globalObjectData->internalField(GlobalObjectData::kContextWrapSlot)); + + return v8::Local::New( + lwIsolate->toV8(), + reinterpret_cast( + EscargotShim::ValueWrap::createContext(lwCreationContext))); } int v8::Object::GetIdentityHash() { @@ -1613,11 +1630,17 @@ int v8::Object::GetIdentityHash() { } bool v8::Object::IsCallable() { - LWNODE_RETURN_FALSE; + auto esSelf = CVAL(this)->value()->asObject(); + return esSelf->isCallable(); } bool v8::Object::IsConstructor() { - LWNODE_RETURN_FALSE; + auto esSelf = CVAL(this)->value()->asObject(); + if (esSelf->isFunctionObject()) { + return esSelf->asFunctionObject()->isConstructor(); + } + + return false; } bool v8::Object::IsApiWrapper() { @@ -1647,7 +1670,18 @@ MaybeLocal Function::New(Local context, int length, ConstructorBehavior behavior, SideEffectType side_effect_type) { - LWNODE_RETURN_LOCAL(Function); + API_ENTER_WITH_CONTEXT(context, MaybeLocal()); + + Local functionTemplate = + FunctionTemplate::New(lwIsolate->toV8(), + callback, + data, + Local(), + length, + behavior, + side_effect_type); + + return functionTemplate->GetFunction(context); } MaybeLocal Function::NewInstance(Local context, @@ -1752,7 +1786,9 @@ MaybeLocal Function::Call(Local context, return Utils::NewLocal(lwIsolate->toV8(), r.result); } -void Function::SetName(v8::Local name) {} +void Function::SetName(v8::Local name) { + LWNODE_ONCE(LWNODE_UNIMPLEMENT); +} Local Function::GetName() const { LWNODE_RETURN_LOCAL(Value); @@ -1813,7 +1849,7 @@ bool String::ContainsOnlyOneByte() const { int String::Utf8Length(Isolate* isolate) const { auto esString = CVAL(this)->value()->asString(); - if (esString->has8BitContent()) { + if (StringRefHelper::isAsciiString(esString)) { return esString->length(); } else { return esString->toStdUTF8String().length(); @@ -1885,7 +1921,8 @@ int String::WriteUtf8(Isolate* v8_isolate, auto esString = CVAL(this)->value()->asString(); auto bufferData = esString->stringBufferAccessData(); - if (bufferData.has8BitContent) { + + if (StringRefHelper::isAsciiString(esString)) { byteLength = bufferData.length; int maxBytes = std::min(bufferCapacity, byteLength); memcpy(buffer, bufferData.buffer, maxBytes); @@ -2079,13 +2116,13 @@ void String::ExternalStringResourceBase::operator delete(void* ptr) { Local Symbol::Description() const { auto lwIsolate = IsolateWrap::GetCurrent(); auto esDescription = CVAL(this)->value()->asSymbol()->description(); - return Utils::NewLocal(lwIsolate->toV8(), esDescription); + return Utils::NewLocal(lwIsolate->toV8(), esDescription.get()); } Local Private::Name() const { auto lwIsolate = IsolateWrap::GetCurrent(); auto esDescription = CVAL(this)->value()->asSymbol()->description(); - return Utils::NewLocal(lwIsolate->toV8(), esDescription); + return Utils::NewLocal(lwIsolate->toV8(), esDescription.get()); } template @@ -2149,30 +2186,66 @@ int v8::Object::InternalFieldCount() { CVAL(this)->value()->asObject()); } +static std::string toExtraDataString(const void* target, + int index, + const void* field) { + std::ostringstream oss; + ObjectData* data = + ObjectRefHelper::getExtraData(CVAL(target)->value()->asObject()); + + oss << CVAL(target)->getHandleInfoString(); + oss << " fields (" << data << ")"; + oss << " [" << index << "]"; + + if (field && CVAL(field)->isValid()) { + oss << " " << CVAL(field)->getHandleInfoString(); + } else { + oss << " " << field; + } + return oss.str(); +} + Local v8::Object::SlowGetInternalField(int index) { auto lwValue = ObjectRefHelper::getInternalField(CVAL(this)->value()->asObject(), index); + + LWNODE_CALL_TRACE_ID( + OBJDATA, "%s", toExtraDataString(this, index, lwValue).c_str()); + return Utils::ToLocal(lwValue); } void v8::Object::SetInternalField(int index, v8::Local value) { + LWNODE_CALL_TRACE_ID( + OBJDATA, "%s", toExtraDataString(this, index, *value).c_str()); + ObjectRefHelper::setInternalField( CVAL(this)->value()->asObject(), index, VAL(*value)); } void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) { - return ObjectRefHelper::getInternalPointer(CVAL(this)->value()->asObject(), - index); + void* field = ObjectRefHelper::getInternalPointer( + CVAL(this)->value()->asObject(), index); + + LWNODE_CALL_TRACE_ID( + OBJDATA, "%s", toExtraDataString(this, index, field).c_str()); + + return field; } void v8::Object::SetAlignedPointerInInternalField(int index, void* value) { + LWNODE_CALL_TRACE_ID( + OBJDATA, "%s", toExtraDataString(this, index, value).c_str()); + ObjectRefHelper::setInternalPointer( CVAL(this)->value()->asObject(), index, value); } void v8::Object::SetAlignedPointerInInternalFields(int argc, int indices[], - void* values[]) {} + void* values[]) { + LWNODE_RETURN_VOID; +} // static void* ExternalValue(i::Object obj) { // // Obscure semantics for undefined, but somehow checked in our unit diff --git a/lwnode/code/escargotshim/src/api-environment.cc b/lwnode/code/escargotshim/src/api-environment.cc index 3b3cfd2..3a6e4e1 100644 --- a/lwnode/code/escargotshim/src/api-environment.cc +++ b/lwnode/code/escargotshim/src/api-environment.cc @@ -29,17 +29,12 @@ namespace v8 { void v8::V8::InitializePlatform(Platform* platform) { /* NOTHING TO DO */ - LWNODE_CALL_TRACE_GC_START(); internal::V8::InitializePlatform(platform); - LWNODE_CALL_TRACE_GC_END(); } void v8::V8::ShutdownPlatform() { - LWNODE_CALL_TRACE_GC_START(); - MemoryUtil::gc(); EscargotShim::Platform::Dispose(); internal::V8::ShutdownPlatform(); - LWNODE_CALL_TRACE_GC_END(); } bool v8::V8::Initialize(const int build_config) { @@ -309,8 +304,8 @@ Local v8::External::New(Isolate* isolate, void* value) { auto esObject = ObjectRefHelper::create(esContext); auto data = new ExternalObjectData(); - data->setInternalFieldCount(1); - data->setInternalField(0, value); + data->setInternalFieldCount(ExternalObjectData::kInternalFieldCount); + data->setInternalField(ExternalObjectData::kValueSlot, value); ObjectRefHelper::setExtraData(esObject, data); @@ -1448,7 +1443,9 @@ v8::ArrayBuffer::Contents v8::ArrayBuffer::GetContents(bool externalize) { return ArrayBuffer::Contents(); } -void v8::ArrayBuffer::Detach() {} +void v8::ArrayBuffer::Detach() { + CVAL(this)->value()->asArrayBufferObject()->detachArrayBuffer(); +} size_t v8::ArrayBuffer::ByteLength() const { return CVAL(this)->value()->asArrayBufferObject()->byteLength(); @@ -1504,8 +1501,7 @@ std::unique_ptr v8::ArrayBuffer::NewBackingStore( Isolate* isolate, size_t byte_length) { auto lwIsolate = IsolateWrap::GetCurrent(); - BackingStoreRef* esBackingStore = - BackingStoreRef::create(lwIsolate->vmInstance(), byte_length); + BackingStoreRef* esBackingStore = BackingStoreRef::create(byte_length); lwIsolate->addBackingStore(esBackingStore); return std::unique_ptr( @@ -1520,40 +1516,31 @@ std::unique_ptr v8::ArrayBuffer::NewBackingStore( auto lwIsolate = IsolateWrap::GetCurrent(); auto lwContext = lwIsolate->GetCurrentContext(); - BackingStoreRef* esBackingStore = nullptr; - EvalResult r = Evaluator::execute( - lwContext->get(), - [](ExecutionStateRef* esState, - BackingStoreRef** backingStore, - void* data, - size_t byteLength, - v8::BackingStore::DeleterCallback deleter, - void* deleterData) -> ValueRef* { - struct Params { - v8::BackingStore::DeleterCallback deleter; - void* deleterData; - }; - - Params* callbackData = new Params(); - callbackData->deleter = deleter; - callbackData->deleterData = deleterData; - auto callback = [](void* data, size_t length, void* callbackData) { - Params* p = (Params*)callbackData; - p->deleter(data, length, p->deleterData); - delete p; - }; - - *backingStore = - BackingStoreRef::create(data, byteLength, callback, callbackData); + struct Params { + BackingStore::DeleterCallback deleter{nullptr}; + void* deleter_data{nullptr}; + }; + + Params* callbackData = new Params(); + callbackData->deleter = deleter; + callbackData->deleter_data = deleter_data; + + auto callback = [](void* data, size_t length, void* callbackData) { + Params* params = reinterpret_cast(callbackData); + if (data) { + /* + @note + + According to src/node_buffer.cc mention, V8 simply ignores the + BackingStore deleter callback if data == nullptr. + */ + params->deleter(data, length, params->deleter_data); + } + delete params; + }; - return ValueRef::createNull(); - }, - &esBackingStore, - data, - byte_length, - deleter, - deleter_data); - LWNODE_CHECK(esBackingStore); + BackingStoreRef* esBackingStore = + BackingStoreRef::create(data, byte_length, callback, callbackData); lwIsolate->addBackingStore(esBackingStore); @@ -1569,7 +1556,6 @@ Local v8::ArrayBufferView::Buffer() { size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) { LWNODE_CALL_TRACE(); - LWNODE_CHECK_NOT_NULL(dest); auto esArrayBufferView = CVAL(this)->value()->asArrayBufferView(); @@ -1577,6 +1563,8 @@ size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) { return 0; } + LWNODE_CHECK_NOT_NULL(dest); + size_t byteLengthToCopy = std::min(byte_length, esArrayBufferView->byteLength()); @@ -1586,7 +1574,7 @@ size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) { } bool v8::ArrayBufferView::HasBuffer() const { - ArrayBufferObjectRef* esArrayBufferObject = + ArrayBufferRef* esArrayBufferObject = CVAL(this)->value()->asArrayBufferView()->buffer(); return esArrayBufferObject != nullptr; } @@ -1684,12 +1672,24 @@ v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::GetContents( } size_t v8::SharedArrayBuffer::ByteLength() const { - LWNODE_RETURN_0; + auto esSelf = CVAL(this)->value()->asSharedArrayBufferObject(); + return esSelf->byteLength(); } Local v8::SharedArrayBuffer::New(Isolate* isolate, size_t byte_length) { - LWNODE_RETURN_LOCAL(SharedArrayBuffer); + API_ENTER_NO_EXCEPTION(isolate); + auto lwContext = lwIsolate->GetCurrentContext(); + + auto r = Evaluator::execute( + lwContext->get(), + [](ExecutionStateRef* state, size_t byteLength) -> ValueRef* { + return SharedArrayBufferObjectRef::create(state, byteLength); + }, + byte_length); + LWNODE_CHECK(r.isSuccessful()); + + return Utils::NewLocal(isolate, r.result); } Local v8::SharedArrayBuffer::New( @@ -1697,6 +1697,7 @@ Local v8::SharedArrayBuffer::New( void* data, size_t byte_length, ArrayBufferCreationMode mode) { + // Deprecate soon LWNODE_RETURN_LOCAL(SharedArrayBuffer); } @@ -1714,7 +1715,13 @@ Local v8::SharedArrayBuffer::New( std::unique_ptr v8::SharedArrayBuffer::NewBackingStore( Isolate* isolate, size_t byte_length) { - LWNODE_RETURN_NULLPTR; + auto lwIsolate = IsolateWrap::GetCurrent(); + + BackingStoreRef* esBackingStore = BackingStoreRef::create(byte_length); + lwIsolate->addBackingStore(esBackingStore); + + return std::unique_ptr( + reinterpret_cast(esBackingStore)); } std::unique_ptr v8::SharedArrayBuffer::NewBackingStore( @@ -1722,7 +1729,32 @@ std::unique_ptr v8::SharedArrayBuffer::NewBackingStore( size_t byte_length, v8::BackingStore::DeleterCallback deleter, void* deleter_data) { - LWNODE_RETURN_NULLPTR; + auto lwIsolate = IsolateWrap::GetCurrent(); + + struct Params { + BackingStore::DeleterCallback deleter{nullptr}; + void* deleterData{nullptr}; + }; + + Params* callbackData = new Params(); + callbackData->deleter = deleter; + callbackData->deleterData = deleter_data; + + auto callback = [](void* data, size_t length, void* callbackData) { + Params* params = reinterpret_cast(callbackData); + if (data) { + params->deleter(data, length, params->deleterData); + } + delete params; + }; + + auto esBackingStore = + BackingStoreRef::create(data, byte_length, callback, callbackData); + + lwIsolate->addBackingStore(esBackingStore); + + return std::unique_ptr( + reinterpret_cast(esBackingStore)); } Local v8::Symbol::New(Isolate* isolate, Local name) { @@ -1911,7 +1943,8 @@ v8::Local Isolate::GetIncumbentContext() { v8::Local Isolate::ThrowException(v8::Local value) { LWNODE_CALL_TRACE_ID(TRYCATCH); auto lwIsolate = IsolateWrap::GetCurrent(); - auto esValue = CVAL(*value)->value(); + auto esValue = value.IsEmpty() ? lwIsolate->undefined_value()->value() + : CVAL(*value)->value(); lwIsolate->ScheduleThrow(esValue); return Utils::NewLocal(lwIsolate->toV8(), esValue); diff --git a/lwnode/code/escargotshim/src/api-exception.cc b/lwnode/code/escargotshim/src/api-exception.cc index 46d8551..f9b7a94 100644 --- a/lwnode/code/escargotshim/src/api-exception.cc +++ b/lwnode/code/escargotshim/src/api-exception.cc @@ -113,7 +113,8 @@ v8::Local v8::TryCatch::ReThrow() { return v8::Local(); } rethrow_ = true; - return v8::Utils::ToLocal(IsolateWrap::fromV8(isolate_)->undefined()); + return v8::Utils::ToLocal( + IsolateWrap::fromV8(isolate_)->undefined_value()); } v8::Local v8::TryCatch::Exception() const { @@ -169,6 +170,19 @@ void v8::TryCatch::SetCaptureMessage(bool value) { // --- M e s s a g e --- +static bool hasStackTraceData(ValueRef* exception) { + if (!exception->isObject()) { + return false; + } + + auto stackTrace = ExceptionObjectData::stackTrace(exception->asObject()); + auto empty = stackTrace->empty(); + if (empty) { + LWNODE_LOG_WARN("No StackTrace found"); + } + return !empty; +} + Local Message::Get() const { LWNODE_RETURN_LOCAL(String); } @@ -207,15 +221,16 @@ ScriptOrigin Message::GetScriptOrigin() const { v8::Local Message::GetScriptResourceName() const { auto lwIsolate = IsolateWrap::GetCurrent(); - auto stackTrace = - ExceptionObjectData::stackTrace(lwIsolate->pending_exception()); - if (stackTrace->empty()) { - LWNODE_LOG_WARN("No StackTrace found"); + + if (!hasStackTraceData(lwIsolate->pending_exception())) { return Utils::NewLocal(lwIsolate->toV8(), StringRef::emptyString()); } + auto stackTrace = ExceptionObjectData::stackTrace( + lwIsolate->pending_exception()->asObject()); + auto top = stackTrace->front(); - return Utils::NewLocal(lwIsolate->toV8(), top->src); + return Utils::NewLocal(lwIsolate->toV8(), top->src()); } v8::Local Message::GetStackTrace() const { @@ -224,44 +239,44 @@ v8::Local Message::GetStackTrace() const { Maybe Message::GetLineNumber(Local context) const { auto lwIsolate = CVAL(*context)->context()->GetIsolate(); - auto stackTrace = - ExceptionObjectData::stackTrace(lwIsolate->pending_exception()); - if (stackTrace->empty()) { - LWNODE_LOG_WARN("No StackTrace found"); + if (!hasStackTraceData(lwIsolate->pending_exception())) { return Just(0); } + auto stackTrace = ExceptionObjectData::stackTrace( + lwIsolate->pending_exception()->asObject()); + auto top = stackTrace->front(); - return Just(top->loc.line); + return Just(top->loc().line); } int Message::GetStartPosition() const { auto lwIsolate = IsolateWrap::GetCurrent(); - auto stackTrace = - ExceptionObjectData::stackTrace(lwIsolate->pending_exception()); - if (stackTrace->empty()) { - LWNODE_LOG_WARN("No StackTrace found"); + if (!hasStackTraceData(lwIsolate->pending_exception())) { return 0; } + auto stackTrace = ExceptionObjectData::stackTrace( + lwIsolate->pending_exception()->asObject()); + auto top = stackTrace->front(); - return top->loc.index; + return top->loc().index; } int Message::GetEndPosition() const { auto lwIsolate = IsolateWrap::GetCurrent(); - auto stackTrace = - ExceptionObjectData::stackTrace(lwIsolate->pending_exception()); - if (stackTrace->empty()) { - LWNODE_LOG_WARN("No StackTrace found"); + if (!hasStackTraceData(lwIsolate->pending_exception())) { return 0; } + auto stackTrace = ExceptionObjectData::stackTrace( + lwIsolate->pending_exception()->asObject()); + auto top = stackTrace->front(); - return top->loc.index + 1; + return top->loc().index + 1; } int Message::ErrorLevel() const { @@ -285,16 +300,16 @@ int Message::GetWasmFunctionIndex() const { Maybe Message::GetStartColumn(Local context) const { auto lwIsolate = CVAL(*context)->context()->GetIsolate(); - auto stackTrace = - ExceptionObjectData::stackTrace(lwIsolate->pending_exception()); - if (stackTrace->empty()) { - LWNODE_LOG_WARN("No StackTrace found"); + if (!hasStackTraceData(lwIsolate->pending_exception())) { return Nothing(); } + auto stackTrace = ExceptionObjectData::stackTrace( + lwIsolate->pending_exception()->asObject()); + auto top = stackTrace->front(); - return Just(top->loc.column - 1); + return Just(top->loc().column - 1); } int Message::GetEndColumn() const { @@ -303,16 +318,16 @@ int Message::GetEndColumn() const { Maybe Message::GetEndColumn(Local context) const { auto lwIsolate = CVAL(*context)->context()->GetIsolate(); - auto stackTrace = - ExceptionObjectData::stackTrace(lwIsolate->pending_exception()); - if (stackTrace->empty()) { - LWNODE_LOG_WARN("No StackTrace found"); + if (!hasStackTraceData(lwIsolate->pending_exception())) { return Nothing(); } + auto stackTrace = ExceptionObjectData::stackTrace( + lwIsolate->pending_exception()->asObject()); + auto top = stackTrace->front(); - int endCol = top->loc.column; + int endCol = top->loc().column; return Just(endCol); } @@ -327,20 +342,20 @@ bool Message::IsOpaque() const { MaybeLocal Message::GetSourceLine(Local context) const { auto lwIsolate = CVAL(*context)->context()->GetIsolate(); - auto stackTrace = - ExceptionObjectData::stackTrace(lwIsolate->pending_exception()); - if (stackTrace->empty()) { - LWNODE_LOG_WARN("No StackTrace found"); + if (!hasStackTraceData(lwIsolate->pending_exception())) { return Utils::NewLocal(lwIsolate->toV8(), StringRef::emptyString()); } + auto stackTrace = ExceptionObjectData::stackTrace( + lwIsolate->pending_exception()->asObject()); + auto top = stackTrace->front(); - std::string code = top->sourceCode->toStdUTF8String(); + std::string code = top->sourceCode()->toStdUTF8String(); std::stringstream ss(code); std::string line; for (size_t i = 1; std::getline(ss, line); i++) { - if (i == top->loc.line) { + if (i == top->loc().line) { break; } } diff --git a/lwnode/code/escargotshim/src/api-scripts.cc b/lwnode/code/escargotshim/src/api-scripts.cc index eddef51..97c07ef 100644 --- a/lwnode/code/escargotshim/src/api-scripts.cc +++ b/lwnode/code/escargotshim/src/api-scripts.cc @@ -198,7 +198,7 @@ Maybe Module::InstantiateModule(Local context, MaybeLocal Module::Evaluate(Local context) { LWNODE_ONCE(LWNODE_UNIMPLEMENT_WORKAROUND); API_ENTER_WITH_CONTEXT(context, MaybeLocal()); - return v8::Utils::ToLocal(lwIsolate->undefined()); + return v8::Utils::ToLocal(lwIsolate->undefined_value()); } Local Module::CreateSyntheticModule( @@ -443,7 +443,7 @@ uint32_t ScriptCompiler::CachedDataVersionTag() { #ifndef NDEBUG static size_t s_track_data_size; #define TRACK_MSG_FMT \ - "total size of new CachedData: " COLOR_GREEN "%zuB" COLOR_RESET + "total size of new CachedData: " CLR_GREEN "%zuB" CLR_RESET #endif ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache( diff --git a/lwnode/code/escargotshim/src/api-serialization.cc b/lwnode/code/escargotshim/src/api-serialization.cc index 4d2d224..9d3d5ce 100644 --- a/lwnode/code/escargotshim/src/api-serialization.cc +++ b/lwnode/code/escargotshim/src/api-serialization.cc @@ -41,57 +41,69 @@ Maybe ValueSerializer::Delegate::GetWasmModuleTransferId( void* ValueSerializer::Delegate::ReallocateBufferMemory(void* old_buffer, size_t size, size_t* actual_size) { - LWNODE_RETURN_NULLPTR; + *actual_size = size; + return realloc(old_buffer, size); } void ValueSerializer::Delegate::FreeBufferMemory(void* buffer) { - LWNODE_UNIMPLEMENT; + return free(buffer); } -// struct ValueSerializer::PrivateData { -// LWNODE_UNIMPLEMENT; -// }; +struct ValueSerializer::PrivateData { + explicit PrivateData(Isolate* i, ValueSerializer::Delegate* delegate) + : isolate(i), serializer(i, delegate) {} + Isolate* isolate; + EscargotShim::ValueSerializer serializer; +}; ValueSerializer::ValueSerializer(Isolate* isolate) : ValueSerializer(isolate, nullptr) { LWNODE_UNIMPLEMENT; } -ValueSerializer::ValueSerializer(Isolate* isolate, Delegate* delegate) { - LWNODE_UNIMPLEMENT; -} -// : private_( -// new PrivateData(reinterpret_cast(isolate), -// delegate)) {} +ValueSerializer::ValueSerializer(Isolate* isolate, Delegate* delegate) + : private_(new PrivateData(isolate, delegate)) {} ValueSerializer::~ValueSerializer() { - LWNODE_UNIMPLEMENT; + delete private_; } void ValueSerializer::WriteHeader() { - LWNODE_UNIMPLEMENT; + private_->serializer.WriteHeader(); } void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) {} Maybe ValueSerializer::WriteValue(Local context, - Local value){ - LWNODE_RETURN_MAYBE(bool)} + Local value) { + bool result = private_->serializer.WriteValue(CVAL(*value)->value()); + return Just(result); +} std::pair ValueSerializer::Release() { return std::make_pair(nullptr, 0); } void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, - Local array_buffer) {} + Local array_buffer) { + LWNODE_RETURN_VOID; +} -void ValueSerializer::WriteUint32(uint32_t value) {} +void ValueSerializer::WriteUint32(uint32_t value) { + LWNODE_RETURN_VOID; +} -void ValueSerializer::WriteUint64(uint64_t value) {} +void ValueSerializer::WriteUint64(uint64_t value) { + LWNODE_RETURN_VOID; +} -void ValueSerializer::WriteDouble(double value) {} +void ValueSerializer::WriteDouble(double value) { + LWNODE_RETURN_VOID; +} -void ValueSerializer::WriteRawBytes(const void* source, size_t length) {} +void ValueSerializer::WriteRawBytes(const void* source, size_t length) { + LWNODE_RETURN_VOID; +} MaybeLocal ValueDeserializer::Delegate::ReadHostObject( Isolate* v8_isolate){LWNODE_RETURN_LOCAL(Object)} @@ -109,21 +121,29 @@ struct ValueDeserializer::PrivateData {}; ValueDeserializer::ValueDeserializer(Isolate* isolate, const uint8_t* data, size_t size) - : ValueDeserializer(isolate, data, size, nullptr) {} + : ValueDeserializer(isolate, data, size, nullptr) { + LWNODE_RETURN_VOID; +} ValueDeserializer::ValueDeserializer(Isolate* isolate, const uint8_t* data, size_t size, - Delegate* delegate) {} + Delegate* delegate) { + LWNODE_RETURN_VOID; +} -ValueDeserializer::~ValueDeserializer() {} +ValueDeserializer::~ValueDeserializer() { + LWNODE_RETURN_VOID; +} Maybe ValueDeserializer::ReadHeader(Local context) { LWNODE_RETURN_MAYBE(bool) } void ValueDeserializer::SetSupportsLegacyWireFormat( - bool supports_legacy_wire_format) {} + bool supports_legacy_wire_format) { + LWNODE_RETURN_VOID; +} uint32_t ValueDeserializer::GetWireFormatVersion() const { LWNODE_RETURN_0; @@ -134,10 +154,14 @@ MaybeLocal ValueDeserializer::ReadValue(Local context) { } void ValueDeserializer::TransferArrayBuffer(uint32_t transfer_id, - Local array_buffer) {} + Local array_buffer) { + LWNODE_RETURN_VOID; +} void ValueDeserializer::TransferSharedArrayBuffer( - uint32_t transfer_id, Local shared_array_buffer) {} + uint32_t transfer_id, Local shared_array_buffer) { + LWNODE_RETURN_VOID; +} bool ValueDeserializer::ReadUint32(uint32_t* value) { LWNODE_RETURN_FALSE; diff --git a/lwnode/code/escargotshim/src/api-template.cc b/lwnode/code/escargotshim/src/api-template.cc index 8f6801b..5408749 100644 --- a/lwnode/code/escargotshim/src/api-template.cc +++ b/lwnode/code/escargotshim/src/api-template.cc @@ -60,7 +60,9 @@ void Template::Set(v8::Local name, void Template::SetPrivate(v8::Local name, v8::Local value, - v8::PropertyAttribute attribute) {} + v8::PropertyAttribute attribute) { + LWNODE_RETURN_VOID; +} void Template::SetAccessorProperty(v8::Local name, v8::Local getter, @@ -114,15 +116,30 @@ static ValueRef* FunctionTemplateNativeFunction( LWNODE_DCHECK_NOT_NULL(callee->extraData()); auto fnData = FunctionData::toFunctionData(callee->extraData()); + LWNODE_CALL_TRACE_ID(TEMPLATE, + "es: %p newTarget: %s", + thisValue, + strBool(newTarget.hasValue())); + + auto lwIsolate = IsolateWrap::GetCurrent(); if (!fnData->checkSignature(state, thisValue)) { - IsolateWrap::GetCurrent()->ScheduleThrow(TypeErrorObjectRef::create( + lwIsolate->ScheduleThrow(TypeErrorObjectRef::create( state, StringRef::createFromASCII("Illegal invocation"))); + lwIsolate->Throw(state); LWNODE_DLOG_ERROR("Signature mismatch!"); return ValueRef::createUndefined(); } + auto thisObject = thisValue->asObject(); + if (newTarget.hasValue() && ObjectRefHelper::hasExtraData(thisObject)) { + auto objectData = ObjectRefHelper::getExtraData(thisObject)->clone(); + objectData->setInstanceTemplate(fnData->instanceTemplate()); + ObjectRefHelper::setExtraData(thisObject, objectData, true); + } + Local result; if (fnData->callback()) { + LWNODE_CALL_TRACE_ID(TEMPLATE, "> Call JS callback"); FunctionCallbackInfoWrap info(fnData->isolate(), thisValue, thisValue, @@ -131,16 +148,20 @@ static ValueRef* FunctionTemplateNativeFunction( argc, argv); fnData->callback()(info); + if (lwIsolate->has_scheduled_exception()) { + lwIsolate->Throw(state); + } result = info.GetReturnValue().Get(); - // TODO: error check from 'state' } if (newTarget.hasValue()) { return thisValue; } + if (!result.IsEmpty()) { return VAL(*result)->value(); } + return ValueRef::createUndefined(); } @@ -160,7 +181,7 @@ Local FunctionTemplate::New(Isolate* isolate, LWNODE_ONCE(LWNODE_DLOG_WARN("@ignored/SideEffectType::kHasSideEffect")); } - API_ENTER_NO_EXCEPTION(isolate); + API_ENTER_NO_EXCEPTION(isolate, TEMPLATE); bool isConstructor = false; if (behavior == ConstructorBehavior::kAllow) { isConstructor = true; @@ -173,9 +194,10 @@ Local FunctionTemplate::New(Isolate* isolate, isConstructor, // isConstruction FunctionTemplateNativeFunction); // fn - FunctionTemplateRefHelper::setInstanceExtraData( - esFunctionTemplate, - new FunctionData(isolate, *callback, *data, *signature)); + auto functionData = new FunctionData(isolate, *callback, *data, *signature); + functionData->setInstanceTemplate(esFunctionTemplate); + FunctionTemplateRefHelper::setInstanceExtraData(esFunctionTemplate, + functionData); return Utils::NewLocal(isolate, esFunctionTemplate); } @@ -225,7 +247,8 @@ Local FunctionTemplate::InstanceTemplate() { } void FunctionTemplate::SetLength(int length) { - LWNODE_RETURN_VOID; + FunctionTemplateRef* self = CVAL(this)->ftpl(); + self->setLength(length); } void FunctionTemplate::SetClassName(Local name) { @@ -261,7 +284,7 @@ void FunctionTemplate::RemovePrototype() { } MaybeLocal FunctionTemplate::GetFunction(Local context) { - API_ENTER_WITH_CONTEXT(context, MaybeLocal()); + API_ENTER_WITH_CONTEXT(context, MaybeLocal(), TEMPLATE); auto esContext = lwIsolate->GetCurrentContext()->get(); auto esFunctionTemplate = CVAL(this)->ftpl(); @@ -280,27 +303,34 @@ bool FunctionTemplate::HasInstance(v8::Local value) { if (!esValue->isObject()) { return false; } - auto esTemplateObject = CVAL(this)->ftpl()->instantiate(esContext); + auto esObject = esValue->asObject(); - auto r = Evaluator::execute( - esContext, - [](ExecutionStateRef* esState, - ValueRef* esValue, - ObjectRef* esTemplateObject) -> ValueRef* { - return ValueRef::create(esValue->instanceOf(esState, esTemplateObject)); - }, - esValue, - esTemplateObject); - LWNODE_CHECK(r.isSuccessful()); + if (!ObjectRefHelper::hasExtraData(esObject)) { + return false; + } + + auto esSelf = CVAL(this)->ftpl(); + auto tpl = ObjectRefHelper::getExtraData(esObject)->instanceTemplate(); + if (esSelf == tpl) { + return true; + } + + auto parent = tpl->parent(); + while (parent.hasValue()) { + if (esSelf == parent.value()) { + return true; + } + parent = parent->parent(); + } - return r.result->asBoolean(); + return false; } // --- O b j e c t T e m p l a t e --- Local ObjectTemplate::New( Isolate* isolate, v8::Local constructor) { - API_ENTER_NO_EXCEPTION(isolate); + API_ENTER_NO_EXCEPTION(isolate, TEMPLATE); return Utils::NewLocal(isolate, ObjectTemplateRef::create()); } @@ -353,6 +383,7 @@ void ObjectTemplate::SetAccessor(v8::Local name, v8::Local signature, SideEffectType getter_side_effect_type, SideEffectType setter_side_effect_type) { + // @note AccessControl is not considered. ObjectTemplateUtils::SetAccessor(CVAL(this)->otpl(), IsolateWrap::GetCurrent(), name, @@ -371,6 +402,7 @@ void ObjectTemplate::SetAccessor(v8::Local name, v8::Local signature, SideEffectType getter_side_effect_type, SideEffectType setter_side_effect_type) { + // @note AccessControl is not considered. ObjectTemplateUtils::SetAccessor(CVAL(this)->otpl(), IsolateWrap::GetCurrent(), name, @@ -487,6 +519,20 @@ void ObjectTemplate::SetHandler( handlerConfiguration->m_namedPropertyHandler.query(v8PropertyName, info); Local ret = info.GetReturnValue().Get(); if (info.hasReturnValue()) { + bool hasNone = (handlerConfiguration->m_namedPropertyHandler.flags == + PropertyHandlerFlags::kNone); + bool hasNoSideEffect = + (static_cast( + handlerConfiguration->m_namedPropertyHandler.flags) & + static_cast(PropertyHandlerFlags::kHasNoSideEffect)); + + if (hasNone) { + return TemplatePropertyAttribute::TemplatePropertyAttributeExist; + } else if (hasNoSideEffect) { + return TemplatePropertyAttribute::TemplatePropertyAttributeEnumerable; + } else { + LWNODE_UNIMPLEMENT; + } return TemplatePropertyAttribute::TemplatePropertyAttributeExist; } @@ -686,14 +732,20 @@ bool ObjectTemplate::IsImmutableProto() { LWNODE_RETURN_FALSE; } -void ObjectTemplate::SetImmutableProto() {} +void ObjectTemplate::SetImmutableProto() { + LWNODE_RETURN_VOID; +} MaybeLocal ObjectTemplate::NewInstance(Local context) { - API_ENTER_WITH_CONTEXT(context, MaybeLocal()); - auto esContext = lwIsolate->GetCurrentContext()->get(); + API_ENTER_WITH_CONTEXT(context, MaybeLocal(), TEMPLATE); + auto esContext = VAL(*context)->context()->get(); auto esObjectTemplate = CVAL(this)->otpl(); - return Utils::NewLocal(lwIsolate->toV8(), - esObjectTemplate->instantiate(esContext)); + auto newObject = esObjectTemplate->instantiate(esContext); + if (ObjectRefHelper::getExtraData(newObject)) { + auto objectData = ObjectRefHelper::getExtraData(newObject); + ObjectRefHelper::setExtraData(newObject, objectData->clone(), true); + } + return Utils::NewLocal(lwIsolate->toV8(), newObject); } } // namespace v8 diff --git a/lwnode/code/escargotshim/src/api.h b/lwnode/code/escargotshim/src/api.h index 17fbd04..6bca167 100644 --- a/lwnode/code/escargotshim/src/api.h +++ b/lwnode/code/escargotshim/src/api.h @@ -38,6 +38,7 @@ #include "api/isolate.h" #include "api/module.h" #include "api/object.h" +#include "api/serializer.h" #include "api/utils/string.h" namespace i = v8::internal; diff --git a/lwnode/code/escargotshim/src/api/context.cc b/lwnode/code/escargotshim/src/api/context.cc index 85db923..da85006 100644 --- a/lwnode/code/escargotshim/src/api/context.cc +++ b/lwnode/code/escargotshim/src/api/context.cc @@ -17,8 +17,9 @@ #include "context.h" #include "base.h" #include "es-helper.h" -#include "escargot_natives.h" +#include "extra-data.h" #include "isolate.h" +#include "stack-trace.h" using namespace Escargot; @@ -51,24 +52,51 @@ static bool createGlobals(ContextRef* context) { #if defined(HOST_TIZEN) // @todo setup device APIs #endif - evalJavaScript(context, - "stack_frame", - reinterpret_cast(stack_frame_raw), - sizeof(stack_frame_raw)); + // Create captureStackTrace and stackTraceLimit + EvalResult r = + Evaluator::execute(context, [](ExecutionStateRef* state) -> ValueRef* { + auto errorObject = state->context() + ->globalObject() + ->get(state, StringRef::createFromASCII("Error")) + ->asObject(); + + errorObject->set(state, + StringRef::createFromASCII("captureStackTrace"), + StackTrace::createCaptureStackTrace(state)); + errorObject->set( + state, + StringRef::createFromASCII("stackTraceLimit"), + ValueRef::create( + 20)); // TODO: get number from '--stack-trace-limit' options + return ValueRef::createUndefined(); + }); + LWNODE_CHECK(r.isSuccessful()); return true; } +// ContextWrap + ContextWrap::ContextWrap(IsolateWrap* isolate) { isolate_ = isolate; + context_ = ContextRef::create(isolate->vmInstance()); + callSite_ = new CallSite(context_); + + auto globalObjectData = new GlobalObjectData(); + globalObjectData->setInternalFieldCount( + GlobalObjectData::kInternalFieldCount); + globalObjectData->setInternalField(GlobalObjectData::kContextWrapSlot, this); + ObjectRefHelper::setExtraData(context_->globalObject(), globalObjectData); createGlobals(context_); + + val_ = context_; + type_ = Type::Context; } ContextWrap* ContextWrap::New(IsolateWrap* isolate) { LWNODE_CHECK_NOT_NULL(isolate); - auto context = new ContextWrap(isolate); - return context; + return new ContextWrap(isolate); } void ContextWrap::Enter() { diff --git a/lwnode/code/escargotshim/src/api/context.h b/lwnode/code/escargotshim/src/api/context.h index a9b4be0..81ce211 100644 --- a/lwnode/code/escargotshim/src/api/context.h +++ b/lwnode/code/escargotshim/src/api/context.h @@ -17,16 +17,16 @@ #pragma once #include -#include "utils/gc.h" +#include "api/handle.h" namespace EscargotShim { class IsolateWrap; -class ValueWrap; +class CallSite; typedef GCUnorderedMap EmbedderDataMap; -class ContextWrap : public gc { +class ContextWrap : public ValueWrap { public: static ContextWrap* New(IsolateWrap* isolate); @@ -49,6 +49,8 @@ class ContextWrap : public gc { Escargot::ValueRef* GetSecurityToken(); void UseDefaultSecurityToken(); + CallSite* callSite() { return callSite_; } + private: EmbedderDataMap* embedder_data_{nullptr}; @@ -60,6 +62,8 @@ class ContextWrap : public gc { Escargot::ContextRef* context_ = nullptr; Escargot::ObjectRef* bindingObject_ = nullptr; Escargot::ValueRef* security_token_ = nullptr; + + CallSite* callSite_ = nullptr; }; } // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/engine.cc b/lwnode/code/escargotshim/src/api/engine.cc index 5122b4b..7861697 100644 --- a/lwnode/code/escargotshim/src/api/engine.cc +++ b/lwnode/code/escargotshim/src/api/engine.cc @@ -18,7 +18,6 @@ #include #include #include "handle.h" -#include "utils/logger.h" #include "utils/misc.h" #include "utils/string.h" @@ -37,8 +36,7 @@ Platform* Platform::GetInstance() { void Platform::Dispose() { LWNODE_CALL_TRACE_GC_START(); - delete s_platform; - s_platform = nullptr; + // s_platform is freed in Escargot::PlatformBridge LWNODE_CALL_TRACE_GC_END(); } @@ -251,7 +249,7 @@ void GCHeap::printStatus(bool forcePrint) { return; } - LWNODE_DLOG_INFO(COLOR_GREEN "----- GCHEAP -----" COLOR_RESET); + LWNODE_DLOG_INFO(CLR_GREEN "----- GCHEAP -----" CLR_RESET); LWNODE_DLOG_INFO("[STAT]"); LWNODE_DLOG_INFO(" freed: %zu", stat_.freed); LWNODE_DLOG_INFO(" strong: %zu", persistents_.size()); @@ -265,7 +263,7 @@ void GCHeap::printStatus(bool forcePrint) { << std::setw(3) << iter.second.weak << ") "; }); - LWNODE_DLOG_INFO(COLOR_GREEN "------------------" COLOR_RESET); + LWNODE_DLOG_INFO(CLR_GREEN "------------------" CLR_RESET); LWNODE_DLOG_INFO("[PHANTOM]"); printAddress(weakPhantoms_, [](std::stringstream& stream, const HeapSegment& iter) { @@ -275,7 +273,7 @@ void GCHeap::printStatus(bool forcePrint) { << std::setw(3) << iter.second.weak << ") "; }); - LWNODE_DLOG_INFO(COLOR_GREEN "------------------" COLOR_RESET); + LWNODE_DLOG_INFO(CLR_GREEN "------------------" CLR_RESET); } void GCHeap::postUpdate(void* address) { @@ -349,7 +347,7 @@ void Engine::initialize() { mallopt(M_MMAP_MAX, 1024 * 1024); #endif - Globals::initialize(); + Globals::initialize(Platform::GetInstance()); Memory::setGCFrequency(GC_FREE_SPACE_DIVISOR); gcHeap_.reset(GCHeap::create()); diff --git a/lwnode/code/escargotshim/src/api/es-helper.cc b/lwnode/code/escargotshim/src/api/es-helper.cc index e418413..bf98eb1 100755 --- a/lwnode/code/escargotshim/src/api/es-helper.cc +++ b/lwnode/code/escargotshim/src/api/es-helper.cc @@ -27,6 +27,8 @@ using namespace Escargot; namespace EscargotShim { +// --- ObjectRefHelper --- + ObjectRef* ObjectRefHelper::create(ContextRef* context) { EvalResult r = Evaluator::execute(context, [](ExecutionStateRef* state) -> ValueRef* { @@ -63,6 +65,82 @@ EvalResult ObjectRefHelper::setProperty(ContextRef* context, value); } +ValueRef* ObjectRefHelper::getOwnPropertyAttributes(ExecutionStateRef* state, + ObjectRef* object, + ValueRef* key) { + auto val = object->getOwnPropertyDescriptor(state, key); + if (val->isUndefined()) { + return ValueRef::createUndefined(); + } + + int attr = ObjectRef::PresentAttribute::NotPresent; + + bool isWritable = val->asObject() + ->get(state, StringRef::createFromASCII("writable")) + ->asBoolean(); + bool isEnumerable = val->asObject() + ->get(state, StringRef::createFromASCII("enumerable")) + ->asBoolean(); + bool isConfigurable = + val->asObject() + ->get(state, StringRef::createFromASCII("configurable")) + ->asBoolean(); + + if (isWritable) { + attr = attr | ObjectRef::PresentAttribute::WritablePresent; + } else { + attr = attr | ObjectRef::PresentAttribute::NonWritablePresent; + } + + if (isEnumerable) { + attr = attr | ObjectRef::PresentAttribute::EnumerablePresent; + } else { + attr = attr | ObjectRef::PresentAttribute::NonEnumerablePresent; + } + + if (isConfigurable) { + attr = attr | ObjectRef::PresentAttribute::ConfigurablePresent; + } else { + attr = attr | ObjectRef::PresentAttribute::NonConfigurablePresent; + } + + return ValueRef::create(attr); +} + +EvalResult ObjectRefHelper::getPropertyAttributes(ContextRef* context, + ObjectRef* object, + ValueRef* key, + bool skipPrototype) { + LWNODE_DCHECK_NOT_NULL(object); + LWNODE_DCHECK_NOT_NULL(key); + + EvalResult r = Evaluator::execute( + context, + [](ExecutionStateRef* state, + ObjectRef* object, + ValueRef* key, + bool skipPrototype) -> ValueRef* { + LWNODE_DCHECK_NOT_NULL(object); + LWNODE_DCHECK_NOT_NULL(key); + + ValueRef* attr = ValueRef::createUndefined(); + for (ObjectRef* o = object; o; + o = o->getPrototypeObject(state).value()) { + attr = getOwnPropertyAttributes(state, o, key); + if (skipPrototype || !attr->isUndefined()) { + break; + } + } + + return attr; + }, + object, + key, + skipPrototype); + + return r; +} + EvalResult ObjectRefHelper::getProperty(ContextRef* context, ObjectRef* object, ValueRef* key) { @@ -78,6 +156,20 @@ EvalResult ObjectRefHelper::getProperty(ContextRef* context, key); } +EvalResult ObjectRefHelper::getOwnProperty(ContextRef* context, + ObjectRef* object, + ValueRef* key) { + LWNODE_DCHECK_NOT_NULL(object); + LWNODE_DCHECK_NOT_NULL(key); + + return Evaluator::execute( + context, + [](ExecutionStateRef* esState, ObjectRef* object, ValueRef* key) + -> ValueRef* { return object->getOwnProperty(esState, key); }, + object, + key); +} + EvalResult ObjectRefHelper::hasProperty(ContextRef* context, ObjectRef* object, ValueRef* key) { @@ -308,19 +400,14 @@ bool ObjectRefHelper::hasExtraData(ObjectRef* object) { return false; } -void ObjectRefHelper::setExtraData( - ObjectRef* object, - ObjectData* data, - Memory::GCAllocatedMemoryFinalizer callback) { - if (object->extraData()) { +void ObjectRefHelper::setExtraData(ObjectRef* object, + ObjectData* data, + bool isForceReplace) { + if (isForceReplace == false && object->extraData()) { LWNODE_DLOG_WARN("extra data already exists. it will be removed."); } object->setExtraData(data); - - if (callback) { - MemoryUtil::gcRegisterFinalizer(object, callback); - } } ObjectData* ObjectRefHelper::getExtraData(ObjectRef* object) { @@ -391,6 +478,37 @@ static std::string getCodeLine(const std::string& codeString, int errorLine) { return result; } +std::string EvalResultHelper::getCallStackString( + const GCManagedVector& traceData, + size_t maxStackSize) { + std::ostringstream oss; + const std::string separator = " "; + size_t maxPrintStackSize = std::min((int)maxStackSize, (int)traceData.size()); + + oss << "Call Stack:" << std::endl; + for (size_t i = 0; i < maxPrintStackSize; ++i) { + const auto& iter = traceData[i]; + const auto& resourceName = iter.src->toStdUTF8String(); + const auto& codeString = iter.sourceCode->toStdUTF8String(); + const int errorLine = iter.loc.line; + const int errorColumn = iter.loc.column; + + auto sourceOnStack = getCodeLine(codeString, errorLine); + + // Trim left spaces + auto pos = sourceOnStack.find_first_not_of(' '); + auto errorCodeLine = + sourceOnStack.substr(pos != std::string::npos ? pos : 0); + + oss << separator << i << ": " << (errorCodeLine == "" ? "?" : errorCodeLine) + << " "; + oss << "(" << (resourceName == "" ? "?" : resourceName) << ":" << errorLine + << ":" << errorColumn << ")" << std::endl; + } + + return oss.str(); +} + std::string EvalResultHelper::getErrorString( ContextRef* context, const Evaluator::EvaluatorResult& result) { const auto& traceData = result.stackTraceData; @@ -434,28 +552,7 @@ std::string EvalResultHelper::getErrorString( } } - size_t maxPrintStackSize = std::min(5, (int)traceData.size()); - - oss << "Call Stack:" << std::endl; - for (size_t i = 0; i < maxPrintStackSize; ++i) { - const auto& iter = traceData[i]; - const auto& resourceName = iter.src->toStdUTF8String(); - const auto& codeString = iter.sourceCode->toStdUTF8String(); - const int errorLine = iter.loc.line; - const int errorColumn = iter.loc.column; - - auto sourceOnStack = getCodeLine(codeString, errorLine); - - // Trim left spaces - auto pos = sourceOnStack.find_first_not_of(' '); - auto errorCodeLine = - sourceOnStack.substr(pos != std::string::npos ? pos : 0); - - oss << separator << i << ": " - << (errorCodeLine == "" ? "?" : errorCodeLine) << " "; - oss << "(" << (resourceName == "" ? "?" : resourceName) << ":" - << errorLine << ":" << errorColumn << ")" << std::endl; - } + oss << getCallStackString(traceData); } return oss.str(); @@ -475,60 +572,148 @@ Evaluator::EvaluatorResult EvalResultHelper::compileRun(ContextRef* context, context, compileResult.parseErrorCode, compileResult.parseErrorMessage); LWNODE_LOG_ERROR( - "%s", result.resultOrErrorToString(context)->toStdUTF8String().c_str()); + "Compile: %s", + result.resultOrErrorToString(context)->toStdUTF8String().c_str()); return result; } - return Evaluator::execute( + auto r = Evaluator::execute( context, [](ExecutionStateRef* state, ScriptRef* script) -> ValueRef* { return script->execute(state); }, compileResult.script.get()); + + if (r.isSuccessful() == false) { + LWNODE_DLOG_RAW("Execute:\n %s (%s:%d)\n%s", + TRACE_ARGS2, + EvalResultHelper::getErrorString(context, r).c_str()); + } + return r; } -void EvalResultHelper::attachBuiltinPrint(ContextRef* context) { +void EvalResultHelper::attachBuiltinPrint(ContextRef* context, + ObjectRef* target) { static auto builtinPrint = [](ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall) -> ValueRef* { if (argc > 0) { - if (argv[0]->isSymbol()) { - puts(argv[0] - ->asSymbol() - ->symbolDescriptiveString() - ->toStdUTF8String() - .c_str()); - } else { - puts(argv[0]->toString(state)->toStdUTF8String().c_str()); + std::stringstream ss; + + for (size_t i = 0; i < argc; ++i) { + if (argv[i]->isSymbol()) { + ss << argv[i] + ->asSymbol() + ->symbolDescriptiveString() + ->toStdUTF8String(); + } else { + ss << argv[i] + ->toStringWithoutException(state->context()) + ->toStdUTF8String(); + } + ss << " "; } - } else { - puts("undefined"); + + LWNODE_DLOG_RAW("%s", ss.str().c_str()); } return ValueRef::createUndefined(); }; - Evaluator::execute(context, [](ExecutionStateRef* state) -> ValueRef* { - ContextRef* context = state->context(); + static auto builtinPrintAddress = [](ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isConstructCall) -> ValueRef* { + if (argc > 0) { + std::stringstream ss; + + for (size_t i = 0; i < argc; ++i) { + if (argv[i]->isString()) { + ss << argv[i] + ->toStringWithoutException(state->context()) + ->toStdUTF8String(); + } else { + ss << CLR_DIM << "(" << argv[i] << ")" << CLR_RESET; + } + ss << " "; + } + + LWNODE_DLOG_RAW("%s", ss.str().c_str()); + } + return ValueRef::createUndefined(); + }; - FunctionObjectRef::NativeFunctionInfo info( - AtomicStringRef::create(context, "print"), - builtinPrint, - 1, - true, - false); + static auto builtinPrintCallStack = [](ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isConstructCall) -> ValueRef* { + size_t maxStackSize = 5; - context->globalObject()->defineDataProperty( - state, - StringRef::createFromASCII("print"), - FunctionObjectRef::create(state, info), - true, - true, - true); + if (argc == 1 && argv[0]->isUInt32()) { + maxStackSize = argv[0]->toUint32(state); + } + + LWNODE_DLOG_RAW( + "%s", + getCallStackString(state->computeStackTraceData(), maxStackSize) + .c_str()); return ValueRef::createUndefined(); - }); + }; + + Evaluator::execute( + context, + [](ExecutionStateRef* state, ObjectRef* target) -> ValueRef* { + auto esPrint = + FunctionObjectRef::create(state, + FunctionObjectRef::NativeFunctionInfo( + AtomicStringRef::emptyAtomicString(), + builtinPrint, + 1, + true, + false)); + + esPrint->defineDataProperty( + state, + StringRef::createFromASCII("ptr"), + FunctionObjectRef::create(state, + FunctionObjectRef::NativeFunctionInfo( + AtomicStringRef::emptyAtomicString(), + builtinPrintAddress, + 1, + true, + false)), + true, + true, + true); + + esPrint->defineDataProperty( + state, + StringRef::createFromASCII("stack"), + FunctionObjectRef::create(state, + FunctionObjectRef::NativeFunctionInfo( + AtomicStringRef::emptyAtomicString(), + builtinPrintCallStack, + 1, + true, + false)), + true, + true, + true); + + target->defineDataProperty(state, + StringRef::createFromASCII("print"), + esPrint, + true, + true, + true); + + return ValueRef::createUndefined(); + }, + target); } ObjectData* ObjectRefHelper::createExtraDataIfNotExist(ObjectRef* object) { @@ -560,6 +745,7 @@ void ObjectRefHelper::setInternalField(ObjectRef* object, InternalField* lwValue) { auto data = getExtraData(object); LWNODE_CHECK_NOT_NULL(data); + data->setInternalField(idx, lwValue); } @@ -567,7 +753,12 @@ InternalField* ObjectRefHelper::getInternalField(ObjectRef* object, int idx) { auto data = getExtraData(object); LWNODE_CHECK_NOT_NULL(data); - return reinterpret_cast(data->internalField(idx)); + auto field = reinterpret_cast(data->internalField(idx)); + if (!field) { + return IsolateWrap::GetCurrent()->undefined_value(); + } + + return field; } void ObjectRefHelper::setInternalPointer(ObjectRef* object, @@ -580,12 +771,16 @@ void ObjectRefHelper::setInternalPointer(ObjectRef* object, } void* ObjectRefHelper::getInternalPointer(ObjectRef* object, int idx) { - auto data = getExtraData(object); - LWNODE_CHECK_NOT_NULL(data); + auto extraData = getExtraData(object); + LWNODE_CHECK_NOT_NULL(extraData); + + auto data = extraData->internalField(idx); - return data->internalField(idx); + return data; } +// --- ObjectTemplateRefHelper --- + void ObjectTemplateRefHelper::setInstanceExtraData(ObjectTemplateRef* otpl, ObjectData* data) { LWNODE_CHECK_NOT_NULL(data); @@ -627,8 +822,11 @@ int ObjectTemplateRefHelper::getInternalFieldCount(ObjectTemplateRef* otpl) { return data->internalFieldCount(); } +// --- FunctionTemplateRefHelper --- + void FunctionTemplateRefHelper::setInstanceExtraData(FunctionTemplateRef* ftpl, FunctionData* data) { + LWNODE_CALL_TRACE_ID(OBJDATA, "es: %p data: %p", ftpl, data); LWNODE_CHECK_NOT_NULL(data); LWNODE_CHECK_NULL(ftpl->instanceExtraData()); @@ -638,9 +836,12 @@ void FunctionTemplateRefHelper::setInstanceExtraData(FunctionTemplateRef* ftpl, FunctionData* FunctionTemplateRefHelper::getInstanceExtraData( FunctionTemplateRef* ftpl) { auto data = ftpl->instanceExtraData(); + LWNODE_CALL_TRACE_ID(OBJDATA, "es: %p data: %p", ftpl, data); return reinterpret_cast(data); } +// --- ExceptionHelper --- + ValueWrap* ExceptionHelper::wrapException(ValueRef* exception) { return ValueWrap::createValue(exception); } @@ -666,4 +867,25 @@ ErrorObjectRef* ExceptionHelper::createErrorObject(ContextRef* context, return r.result->asErrorObject(); } +// --- StringRefHelper --- + +bool StringRefHelper::isAsciiString(StringRef* str) { + auto bufferData = str->stringBufferAccessData(); + + if (!bufferData.has8BitContent) { + return false; + } + + bool isAscii = true; + for (size_t i = 0; i < bufferData.length; i++) { + char16_t c = bufferData.charAt(i); + if (c > 127) { // including all 7 bit code + isAscii = false; + break; + } + } + + return isAscii; +} + } // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/es-helper.h b/lwnode/code/escargotshim/src/api/es-helper.h index 26b4765..e3bddf3 100755 --- a/lwnode/code/escargotshim/src/api/es-helper.h +++ b/lwnode/code/escargotshim/src/api/es-helper.h @@ -51,6 +51,15 @@ class ObjectRefHelper { ValueRef* key, ValueRef* value); + static EvalResult getOwnProperty(ContextRef* context, + ObjectRef* object, + ValueRef* key); + + static EvalResult getPropertyAttributes(ContextRef* context, + ObjectRef* object, + ValueRef* key, + bool skipPrototype = false); + static EvalResult hasProperty(ContextRef* context, ObjectRef* object, ValueRef* key); @@ -90,13 +99,11 @@ class ObjectRefHelper { ValueRef* propertyName, const ObjectRef::AccessorPropertyDescriptor& descriptor); - static void setExtraData( - ObjectRef* object, - ObjectData* data, - Memory::GCAllocatedMemoryFinalizer callback = nullptr); + static void setExtraData(ObjectRef* object, + ObjectData* data, + bool isForceReplace = false); static bool hasExtraData(ObjectRef* object); static ObjectData* getExtraData(ObjectRef* object); - static ObjectData* createExtraDataIfNotExist(ObjectRef* object); static void setInternalFieldCount(ObjectRef* object, int size); static int getInternalFieldCount(ObjectRef* object); @@ -112,15 +119,22 @@ class ObjectRefHelper { static StringRef* getConstructorName(ContextRef* context, ObjectRef* object); private: + static ObjectData* createExtraDataIfNotExist(ObjectRef* object); + + static ValueRef* getOwnPropertyAttributes(ExecutionStateRef* state, + ObjectRef* object, + ValueRef* key); }; class ObjectTemplateRefHelper { public: static void setInstanceExtraData(ObjectTemplateRef* otpl, ObjectData* data); static ObjectData* getInstanceExtraData(ObjectTemplateRef* otpl); - static ObjectData* createInstanceExtraDataIfNotExist(ObjectTemplateRef* otpl); static void setInternalFieldCount(ObjectTemplateRef* otpl, int size); static int getInternalFieldCount(ObjectTemplateRef* otpl); + + private: + static ObjectData* createInstanceExtraDataIfNotExist(ObjectTemplateRef* otpl); }; class FunctionTemplateRefHelper { @@ -197,12 +211,15 @@ class ArrayBufferHelper { class EvalResultHelper { public: - static void attachBuiltinPrint(ContextRef* context); + static void attachBuiltinPrint(ContextRef* context, ObjectRef* target); static Evaluator::EvaluatorResult compileRun(ContextRef* context, const char* source, bool isModule = false); static std::string getErrorString( ContextRef* context, const Evaluator::EvaluatorResult& eval_result); + static std::string getCallStackString( + const GCManagedVector& traceData, + size_t maxStackSize = 5); }; class ExceptionHelper { @@ -220,6 +237,8 @@ class StringRefHelper { static bool equalsWithASCIIString(StringRef* esString, const char (&str)[N]) { return esString->equalsWithASCIIString(str, N - 1); } + + static bool isAsciiString(StringRef* str); }; } // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/es-v8-helper.cc b/lwnode/code/escargotshim/src/api/es-v8-helper.cc index d581650..474b3bb 100644 --- a/lwnode/code/escargotshim/src/api/es-v8-helper.cc +++ b/lwnode/code/escargotshim/src/api/es-v8-helper.cc @@ -26,19 +26,50 @@ ObjectRef::PresentAttribute V8Helper::toPresentAttribute( if (attributes & v8::ReadOnly) { presentAttributes = static_cast( presentAttributes | ObjectRef::PresentAttribute::NonWritablePresent); + } else { + presentAttributes = static_cast( + presentAttributes | ObjectRef::PresentAttribute::WritablePresent); } if (attributes & v8::DontEnum) { presentAttributes = static_cast( presentAttributes | ObjectRef::PresentAttribute::NonEnumerablePresent); + } else { + presentAttributes = static_cast( + presentAttributes | ObjectRef::PresentAttribute::EnumerablePresent); } if (attributes & v8::DontDelete) { presentAttributes = static_cast( presentAttributes | ObjectRef::PresentAttribute::NonConfigurablePresent); + } else { + presentAttributes = static_cast( + presentAttributes | ObjectRef::PresentAttribute::ConfigurablePresent); } return presentAttributes; } + +v8::PropertyAttribute V8Helper::toPropertyAttribute( + ObjectRef::PresentAttribute attributes) { + int propertyAttributes = v8::PropertyAttribute::None; + + if (attributes & ObjectRef::PresentAttribute::NonWritablePresent) { + propertyAttributes = + propertyAttributes | ObjectRef::PresentAttribute::NonWritablePresent; + } + + if (attributes & ObjectRef::PresentAttribute::NonEnumerablePresent) { + propertyAttributes = + propertyAttributes | ObjectRef::PresentAttribute::NonEnumerablePresent; + } + + if (attributes & ObjectRef::PresentAttribute::NonConfigurablePresent) { + propertyAttributes = propertyAttributes | + ObjectRef::PresentAttribute::NonConfigurablePresent; + } + + return static_cast(propertyAttributes); +} } // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/es-v8-helper.h b/lwnode/code/escargotshim/src/api/es-v8-helper.h index 6c430c2..4d09bcb 100644 --- a/lwnode/code/escargotshim/src/api/es-v8-helper.h +++ b/lwnode/code/escargotshim/src/api/es-v8-helper.h @@ -27,6 +27,8 @@ class V8Helper { public: static ObjectRef::PresentAttribute toPresentAttribute( v8::PropertyAttribute attributes); + static v8::PropertyAttribute toPropertyAttribute( + ObjectRef::PresentAttribute attributes); }; } // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/extra-data.cc b/lwnode/code/escargotshim/src/api/extra-data.cc index f1547e5..d9bd271 100644 --- a/lwnode/code/escargotshim/src/api/extra-data.cc +++ b/lwnode/code/escargotshim/src/api/extra-data.cc @@ -30,6 +30,22 @@ static inline bool checkOutofBounds(ObjectData* data, int idx) { return idx >= data->internalFieldCount() || idx < 0; } +static std::string toObjectDataString(const ObjectData* data, + int index, + const void* field) { + std::ostringstream oss; + + oss << " fields (" << data << ")"; + oss << " [" << index << "]"; + + if (field && CVAL(field)->isValid()) { + oss << " " << CVAL(field)->getHandleInfoString(); + } else { + oss << " " << field; + } + return oss.str(); +} + int ObjectData::internalFieldCount() { if (m_internalFields == nullptr) { return 0; @@ -38,14 +54,17 @@ int ObjectData::internalFieldCount() { } void ObjectData::setInternalFieldCount(int size) { + LWNODE_CALL_TRACE_ID(OBJDATA, "%d", size); + // TODO: throw internal error if (size <= 0) { LWNODE_DLOG_ERROR("InternalField: The size is negative"); return; } + m_internalFields = new GCContainer(size); for (int i = 0; i < size; i++) { - m_internalFields->set(i, IsolateWrap::GetCurrent()->undefined()); + setInternalField(i, nullptr); } } @@ -56,6 +75,10 @@ void ObjectData::setInternalField(int idx, void* lwValue) { LWNODE_DLOG_ERROR("InternalField: Internal field out of bounds"); return; } + + LWNODE_CALL_TRACE_ID( + OBJDATA, "%s", toObjectDataString(this, idx, lwValue).c_str()); + m_internalFields->set(idx, lwValue); } @@ -66,7 +89,40 @@ void* ObjectData::internalField(int idx) { LWNODE_DLOG_ERROR("InternalField: Internal field out of bounds"); return nullptr; } - return m_internalFields->get(idx); + + void* field = m_internalFields->get(idx); + if (field) { + LWNODE_CALL_TRACE_ID( + OBJDATA, "%s", toObjectDataString(this, idx, field).c_str()); + } + + return field; +} + +ObjectData* ObjectData::clone() { + auto newData = new ObjectData(); + + LWNODE_CALL_TRACE_ID(OBJDATA, "%p clone: %p", this, newData); + + // copy internalField + auto count = internalFieldCount(); + if (count > 0) { + newData->setInternalFieldCount(count); + } + for (int i = 0; i < count; i++) { + LWNODE_DCHECK(internalField(i) == nullptr); + newData->setInternalField(i, internalField(i)); + } + + return newData; +} + +void ObjectData::setInstanceTemplate(Escargot::FunctionTemplateRef* tpl) { + instanceTemplate_ = tpl; +} + +Escargot::FunctionTemplateRef* ObjectData::instanceTemplate() { + return instanceTemplate_; } bool FunctionData::checkSignature(Escargot::ExecutionStateRef* state, @@ -89,7 +145,30 @@ bool FunctionData::checkSignature(Escargot::ExecutionStateRef* state, return r.result->asBoolean(); } -GCVector* ExceptionObjectData::stackTrace( +static bool isValidStackFrame(const Evaluator::StackTraceData& traceData) { + const int errorLine = traceData.loc.line; + const int errorColumn = traceData.loc.column; + // simple filter for { [native function] } :-1:-1) + return (errorLine > 0 && errorColumn > 0); +} + +ExceptionObjectData::ExceptionObjectData( + GCManagedVector& stackTraceData, + bool isThisExceptionUndefined) + : isThisExceptionUndefined_(isThisExceptionUndefined) { + constexpr const char* kNativeFunction = "[native function]"; + + for (size_t i = 0; i < stackTraceData.size(); i++) { + const auto& traceData = stackTraceData[i]; + if (isValidStackFrame(traceData) == false) { + LWNODE_DLOG_INFO("filtered: stack frame #%zu", i); + continue; + } + stackTraces_.push_back(new StackTraceData(traceData)); + } +} + +GCVector* ExceptionObjectData::stackTrace( ObjectRef* exceptionObject) { auto exceptionObjectData = static_cast( ObjectRefHelper::getExtraData(exceptionObject)); diff --git a/lwnode/code/escargotshim/src/api/extra-data.h b/lwnode/code/escargotshim/src/api/extra-data.h index 2c73db9..e93482a 100644 --- a/lwnode/code/escargotshim/src/api/extra-data.h +++ b/lwnode/code/escargotshim/src/api/extra-data.h @@ -23,6 +23,9 @@ namespace EscargotShim { class ExternalObjectData; +class GlobalObjectData; +class ExceptionObjectData; +class StackTraceData; class ValueWrap; class BackingStoreWrap; @@ -35,9 +38,28 @@ class ObjectData : public gc { return reinterpret_cast(this); } + GlobalObjectData* asGlobalObjectData() { + LWNODE_CHECK(isGlobalObjectData()); + return reinterpret_cast(this); + } + + ExceptionObjectData* asExceptionObjectData() { + LWNODE_CHECK(isExceptionObjectData()); + return reinterpret_cast(this); + } + + StackTraceData* asStackTraceData() { + LWNODE_CHECK(isStackTraceData()); + return reinterpret_cast(this); + } + virtual bool isFunctionData() const { return false; } virtual bool isExternalObjectData() const { return false; } virtual bool isExceptionObjectData() const { return false; } + virtual bool isStackTraceData() const { return false; } + virtual bool isGlobalObjectData() const { return false; } + + ObjectData* clone(); // InternalFields int internalFieldCount(); @@ -45,8 +67,13 @@ class ObjectData : public gc { void setInternalField(int idx, void* lwValue); void* internalField(int idx); + // Template + void setInstanceTemplate(Escargot::FunctionTemplateRef* tpl); + Escargot::FunctionTemplateRef* instanceTemplate(); + private: GCContainer* m_internalFields{nullptr}; + Escargot::FunctionTemplateRef* instanceTemplate_{nullptr}; }; class FunctionData : public ObjectData { @@ -87,37 +114,63 @@ class FunctionData : public ObjectData { class ExternalObjectData : public ObjectData { public: + enum InternalFields { + kValueSlot, + kInternalFieldCount, + }; bool isExternalObjectData() const override { return true; } }; -class ExceptionObjectData : public ObjectData { +// TODO: check to make sure StackTraceData inherit ObjectData. +class StackTraceData : public ObjectData { public: - struct StackTraceData : public gc { - public: - StackTraceData(Escargot::Evaluator::StackTraceData& data) - : src(data.src), - sourceCode(data.sourceCode), - loc(data.loc), - functionName(data.functionName), - isConstructor(data.isConstructor), - isAssociatedWithJavaScriptCode(data.isAssociatedWithJavaScriptCode), - isEval(data.isEval) {} - - StringRef* src{nullptr}; - StringRef* sourceCode{nullptr}; - Escargot::Evaluator::LOC loc{0, 0, 0}; - StringRef* functionName{nullptr}; - bool isFunction{false}; - bool isConstructor{false}; - bool isAssociatedWithJavaScriptCode{false}; - bool isEval{false}; - }; + StackTraceData(const Escargot::Evaluator::StackTraceData& data) + : src_(data.src), + sourceCode_(data.sourceCode), + loc_(data.loc), + functionName_(data.functionName), + isConstructor_(data.isConstructor), + isAssociatedWithJavaScriptCode_(data.isAssociatedWithJavaScriptCode), + isEval_(data.isEval) {} + + bool isStackTraceData() const override { return true; } + + StringRef* src() const { return src_; } + StringRef* sourceCode() const { return sourceCode_; } + Escargot::Evaluator::LOC loc() const { return loc_; } + StringRef* functionName() const { return functionName_; } + bool isFunction() const { return isFunction_; } + bool isConstructor() const { return isConstructor_; } + bool isAssociatedWithJavaScriptCode() const { + return isAssociatedWithJavaScriptCode_; + } + bool isEval() const { return isEval_; } + private: + StringRef* src_{nullptr}; + StringRef* sourceCode_{nullptr}; + Escargot::Evaluator::LOC loc_{0, 0, 0}; + StringRef* functionName_{nullptr}; + bool isFunction_{false}; + bool isConstructor_{false}; + bool isAssociatedWithJavaScriptCode_{false}; + bool isEval_{false}; +}; + +class ExceptionObjectData : public ObjectData { + public: public: ExceptionObjectData( - GCManagedVector& stackTraceData) { - for (size_t i = 0; i < stackTraceData.size(); i++) { - stackTraces_.push_back(new StackTraceData(stackTraceData[i])); + GCManagedVector& stackTraceData, + bool isThisExceptionUndefined = false); + + ExceptionObjectData(GCVector* stackTrace, + bool isThisExceptionUndefined = false) + : isThisExceptionUndefined_(isThisExceptionUndefined) { + { + for (const auto& iter : *stackTrace) { + stackTraces_.push_back(iter); + } } } @@ -128,6 +181,16 @@ class ExceptionObjectData : public ObjectData { private: GCVector stackTraces_; + bool isThisExceptionUndefined_{false}; +}; + +class GlobalObjectData : public ObjectData { + public: + enum InternalFields { + kContextWrapSlot, + kInternalFieldCount, + }; + bool isGlobalObjectData() const override { return true; } }; } // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/function.cc b/lwnode/code/escargotshim/src/api/function.cc index b459f5b..739ed23 100644 --- a/lwnode/code/escargotshim/src/api/function.cc +++ b/lwnode/code/escargotshim/src/api/function.cc @@ -45,7 +45,7 @@ FunctionCallbackInfoWrap::FunctionCallbackInfoWrap( m_implicitArgs[T::kDataIndex] = data; m_implicitArgs[T::kNewTargetIndex] = newTarget.hasValue() ? ValueWrap::createValue(newTarget.get()) - : lwIsolate->undefined(); + : lwIsolate->undefined_value(); } HandleWrap** FunctionCallbackInfoWrap::toWrapperArgs(ValueRef* thisValue, @@ -68,8 +68,9 @@ HandleWrap** FunctionCallbackInfoWrap::toWrapperArgs(ValueRef* thisValue, string1 // the beginning of the arguments array */ - m_args = reinterpret_cast( - Escargot::Memory::gcMalloc(sizeof(HandleWrap*) * (argc + 1))); + m_args = + reinterpret_cast(Escargot::Memory::gcMallocUncollectable( + sizeof(HandleWrap*) * (argc + 1))); #ifdef V8_REVERSE_JSARGS #error "Not implement V8_REVERSE_JSARGS" @@ -109,7 +110,7 @@ PropertyCallbackInfoWrap::PropertyCallbackInfoWrap(v8::Isolate* isolate, reinterpret_cast(m_implicitArgs)) { auto lwIsolate = IsolateWrap::fromV8(isolate); // m_implicitArgs[F::kShouldThrowOnErrorIndex]; // TODO - m_implicitArgs[F::kHolderIndex] = lwIsolate->hole(); + m_implicitArgs[F::kHolderIndex] = ValueWrap::createValue(holder); m_implicitArgs[F::kIsolateIndex] = reinterpret_cast(isolate); // m_implicitArgs[F::kReturnValueDefaultValueIndex]; // TODO m_implicitArgs[F::kReturnValueIndex] = lwIsolate->defaultReturnValue(); diff --git a/lwnode/code/escargotshim/src/api/function.h b/lwnode/code/escargotshim/src/api/function.h index 4b06dd4..9687029 100644 --- a/lwnode/code/escargotshim/src/api/function.h +++ b/lwnode/code/escargotshim/src/api/function.h @@ -40,7 +40,7 @@ class FunctionCallbackInfoWrap : public v8::FunctionCallbackInfo { HandleWrap** toWrapperArgs(ValueRef* thisValue, int argc, ValueRef** argv); private: - HandleWrap** m_args{nullptr}; + HandleWrap** m_args; HandleWrap* m_implicitArgs[T::kArgsLength]; }; diff --git a/lwnode/code/escargotshim/src/api/handle.cc b/lwnode/code/escargotshim/src/api/handle.cc index 93709e9..3580aca 100644 --- a/lwnode/code/escargotshim/src/api/handle.cc +++ b/lwnode/code/escargotshim/src/api/handle.cc @@ -41,7 +41,7 @@ uint8_t HandleWrap::location() const { } bool HandleWrap::isValid() const { - return (type_ > Type::NotPresent && type_ < Type::EndOfType); + return (type_ >= Type::JsValue && type_ < Type::EndOfType); } bool HandleWrap::isStrongOrWeak() const { @@ -73,11 +73,13 @@ HandleWrap* HandleWrap::as(void* address) { return p; } -std::string HandleWrap::getHandleInfoString() { +std::string HandleWrap::getHandleInfoString() const { std::stringstream ss; - ss << "(addr: " << this << " es: " << val_ - << " loc: " << std::to_string(location_) - << " type: " << std::to_string(type_) << ")"; + ss << "(addr: " << this << " es: " << val_; + if (location_ != Location::Local) { + ss << " loc: " << std::to_string(location_); + } + ss << " type: " << std::to_string(type_) << ")"; return ss.str(); } @@ -117,12 +119,14 @@ ValueRef* ValueWrap::value() const { } ValueWrap* ValueWrap::createContext(ContextWrap* lwContext) { - return new ValueWrap(lwContext, Type::Context); + LWNODE_CHECK(lwContext->type_ == Type::Context); + LWNODE_CHECK_NOT_NULL(lwContext->val_); + return lwContext; }; ContextWrap* ValueWrap::context() const { LWNODE_CHECK(type_ == Type::Context); - return reinterpret_cast(val_); + return reinterpret_cast(const_cast(this)); } ValueWrap* ValueWrap::createScript(ScriptRef* esScript) { diff --git a/lwnode/code/escargotshim/src/api/handle.h b/lwnode/code/escargotshim/src/api/handle.h index 533c954..060d352 100644 --- a/lwnode/code/escargotshim/src/api/handle.h +++ b/lwnode/code/escargotshim/src/api/handle.h @@ -59,7 +59,7 @@ class HandleWrap : public gc { bool isStrongOrWeak() const; uint8_t location() const; HandleWrap* clone(Location location = Local); - std::string getHandleInfoString(); + std::string getHandleInfoString() const; static HandleWrap* as(void* address); protected: diff --git a/lwnode/code/escargotshim/src/api/isolate.cc b/lwnode/code/escargotshim/src/api/isolate.cc index 8ed4e4d..f7f30d1 100755 --- a/lwnode/code/escargotshim/src/api/isolate.cc +++ b/lwnode/code/escargotshim/src/api/isolate.cc @@ -26,6 +26,8 @@ namespace v8 { namespace internal { +using namespace EscargotShim; + // 'exception_' is of type ValueWrap*. Ref: api-exception.cc void Isolate::SetTerminationOnExternalTryCatch() { LWNODE_CALL_TRACE_ID(TRYCATCH, "try_catch_handler_: %p", try_catch_handler_); @@ -54,6 +56,8 @@ void Isolate::ScheduleThrow(Escargot::ValueRef* value) { // using v8:tryCatch, etc. In this case, we should not do any exception // handling. + set_scheduled_exception(value); + // Note: No stack data exist GCManagedVector stackTraceData; SetPendingExceptionAndMessage(value, stackTraceData); @@ -90,17 +94,21 @@ bool Isolate::has_scheduled_exception() { return !isHole(scheduled_exception_); } +void Isolate::set_scheduled_exception(Escargot::ValueRef* exception_obj) { + scheduled_exception_ = exception_obj; +} + void Isolate::clear_scheduled_exception() { LWNODE_CALL_TRACE_ID(TRYCATCH); scheduled_exception_ = hole()->value(); } -Escargot::ObjectRef* Isolate::pending_exception() { +Escargot::ValueRef* Isolate::pending_exception() { LWNODE_CHECK(has_pending_exception()); return pending_exception_; } -void Isolate::set_pending_exception(Escargot::ObjectRef* exception_obj) { +void Isolate::set_pending_exception(Escargot::ValueRef* exception_obj) { LWNODE_CALL_TRACE_ID(TRYCATCH); LWNODE_CHECK_NOT_NULL(exception_obj); pending_exception_ = exception_obj; @@ -168,10 +176,12 @@ void Isolate::ReportPendingMessages() { if (should_report_exception) { v8::HandleScope scope(EscargotShim::IsolateWrap::toV8(this)); - v8::Local message; v8::Local exception = v8::Utils::NewLocal( EscargotShim::IsolateWrap::toV8(this), pending_exception_); + v8::Local message = v8::Exception::CreateMessage( + EscargotShim::IsolateWrap::toV8(this), exception); + if (message_callback_ != nullptr) { message_callback_(message, exception); } @@ -214,6 +224,19 @@ IsolateWrap::IsolateWrap() { Memory::gcRegisterFinalizer(this, [](void* self) { reinterpret_cast(self)->~IsolateWrap(); }); + + MemoryUtil::gcSetWarningListener([](WarnEventType type) { + switch (type) { + case OUT_OF_MEMORY: + case FAILED_TO_EXPAND_HEAP: + if (s_currentIsolate) { + s_currentIsolate->onFatalError(nullptr, "Out of memory"); + } + break; + default: + break; + } + }); } IsolateWrap::~IsolateWrap() { @@ -249,6 +272,7 @@ void IsolateWrap::set_array_buffer_allocator_shared( } void IsolateWrap::InitializeGlobalSlots() { + LWNODE_CALL_TRACE_ID(ISOWRAP); globalSlot_[internal::Internals::kUndefinedValueRootIndex] = EscargotShim::ValueWrap::createValue(ValueRef::createUndefined()); globalSlot_[internal::Internals::kTheHoleValueRootIndex] = @@ -294,7 +318,7 @@ void IsolateWrap::Initialize(const v8::Isolate::CreateParams& params) { auto platform = Platform::GetInstance(); platform->setAllocator(array_buffer_allocator()); - vmInstance_ = VMInstanceRef::create(platform); + vmInstance_ = VMInstanceRef::create(); vmInstance_->setOnVMInstanceDelete([](VMInstanceRef* instance) { // Do Nothing LWNODE_CALL_TRACE_GC_START(); @@ -305,6 +329,51 @@ void IsolateWrap::Initialize(const v8::Isolate::CreateParams& params) { InitializeGlobalSlots(); scheduled_exception_ = hole()->value(); + + // Register lwnode internal promise hook to create the internal field. + LWNODE_ONCE(LWNODE_DLOG_INFO("v8::Promise::kEmbedderFieldCount: %d", + v8::Promise::kEmbedderFieldCount)); + if (v8::Promise::kEmbedderFieldCount > 0) { + auto fn = [](ExecutionStateRef* state, + VMInstanceRef::PromiseHookType type, + PromiseObjectRef* promise, + ValueRef* parent) { + // 1. create internal field on Init + if (type == VMInstanceRef::PromiseHookType::Init) { + LWNODE_DCHECK(v8::Promise::kEmbedderFieldCount > 0); + if (ObjectRefHelper::getInternalFieldCount(promise) == 0) { + ObjectRefHelper::setInternalFieldCount(promise, + Promise::kEmbedderFieldCount); + /* + @note + In Node.js, promise internal field count is supposed to be set to 1. + + reference: + - configure.py: v8_promise_internal_field_count = 1 + - tools/v8_gypfiles/features.gypi: V8_PROMISE_INTERNAL_FIELD_COUNT + - deps/v8/src/heap/factory.cc: Factory::NewJSPromise() + + v8 sets Smi::zero() to promise's internal fields, which are: + - Number from getInternalField + - nullptr from GetAlignedPointerFromInternalField + + In lwnode, the returned value will be: + - Undefined from getInternalField + - nullptr from GetAlignedPointerFromInternalField + + The difference from getInternalField seems not that meaningful in + Node.js. + */ + } + } + + // 2. run PromiseHook + IsolateWrap::GetCurrent()->RunPromiseHook( + (v8::PromiseHookType)type, promise, parent); + }; + + vmInstance_->registerPromiseHook(fn); + } } void IsolateWrap::Enter() { @@ -349,7 +418,7 @@ void IsolateWrap::popHandleScope(v8Scope_t* handleScope) { } void IsolateWrap::addHandleToCurrentScope(HandleWrap* value) { - LWNODE_CALL_TRACE("%p", value); + LWNODE_CALL_TRACE_ID(ISOWRAP, "%p", value); LWNODE_CHECK(handleScopes_.size() >= 1); handleScopes_.back()->add(value); } @@ -373,22 +442,6 @@ bool IsolateWrap::isCurrentScopeSealed() { } void IsolateWrap::pushContext(ContextWrap* context) { - LWNODE_CALL_TRACE_ID(ISOWRAP, - "%p (%zu -> %zu)", - context, - contextScopes_.size(), - contextScopes_.size() + 1); - - if (contextScopes_.size() && (contextScopes_.back() != context)) { - LWNODE_DLOG_WARN(R"(multiple contexts exist: -contextScopes_.back() != context means that we need to support multiple -contexts. In Node.js at this time, one main Context associated with the -Environment instance is used for most Node.js features (except writing -MessagePort objects.) So, on purpose, we don't store Object's creation -context which is related to Object::CreationContext(). -@note: we may ignore this warning if cctest not related runs.)"); - } - contextScopes_.push_back(context); } @@ -513,24 +566,36 @@ void IsolateWrap::SetPendingExceptionAndMessage( GCManagedVector& stackTraceData) { LWNODE_CALL_TRACE_ID(TRYCATCH); - auto exceptionObject = - ObjectRefHelper::toObject(GetCurrentContext()->get(), exception); - ObjectRefHelper::setExtraData(exceptionObject, - new ExceptionObjectData(stackTraceData)); + if (exception->isObject()) { + ObjectRefHelper::setExtraData(exception->asObject(), + new ExceptionObjectData(stackTraceData)); + } - set_pending_exception(exceptionObject); + set_pending_exception(exception); // @note // pending_message_obj: v8::Message isn't created. Instead v8::Message // uses `stackTraceData.stackTraces()` directly to make a result requested. set_pending_message_obj(nullptr); } +void IsolateWrap::Throw(Escargot::ExecutionStateRef* state) { + LWNODE_CALL_TRACE_ID(TRYCATCH); + LWNODE_DCHECK(has_scheduled_exception()); + + auto exception = scheduled_exception(); + clear_scheduled_exception(); + if (hasExternalTryCatch()) { + return; + } + state->throwException(exception); +} + ValueWrap** IsolateWrap::getGlobal(const int index) { LWNODE_CHECK(index < internal::Internals::kRootIndexSize); return &globalSlot_[index]; } -ValueWrap* IsolateWrap::undefined() { +ValueWrap* IsolateWrap::undefined_value() { return globalSlot_[internal::Internals::kUndefinedValueRootIndex]; } @@ -581,10 +646,24 @@ void IsolateWrap::onFatalError(const char* location, const char* message) { } void IsolateWrap::SetPromiseHook(v8::PromiseHook callback) { - auto lwIsolate = GetCurrent(); - promise_hook_ = callback; + if (v8::Promise::kEmbedderFieldCount > 0) { + // @todo LWNODE_CHECK(isPromiseHookRegistered()); + return; + } + + // @note + // the following won't be used in Node.js since + // v8::Promise::kEmbedderFieldCount will be set to 1. + LWNODE_DCHECK(false); + + auto lwIsolate = GetCurrent(); + if (promise_hook_ == nullptr) { + lwIsolate->vmInstance()->unregisterPromiseHook(); + return; + } + auto fn = [](ExecutionStateRef* state, VMInstanceRef::PromiseHookType type, PromiseObjectRef* promise, diff --git a/lwnode/code/escargotshim/src/api/isolate.h b/lwnode/code/escargotshim/src/api/isolate.h index 7157846..930bf0b 100755 --- a/lwnode/code/escargotshim/src/api/isolate.h +++ b/lwnode/code/escargotshim/src/api/isolate.h @@ -39,9 +39,10 @@ class Isolate : public gc { Escargot::ValueRef* scheduled_exception(); bool has_scheduled_exception(); + void set_scheduled_exception(Escargot::ValueRef* exception_obj); void clear_scheduled_exception(); - Escargot::ObjectRef* pending_exception(); + Escargot::ValueRef* pending_exception(); bool has_pending_exception(); Escargot::ValueRef* pending_message_obj(); @@ -72,6 +73,14 @@ class Isolate : public gc { prepare_stack_trace_callback_ = callback; } + bool HasPrepareStackTraceCallback() const { + return prepare_stack_trace_callback_ != nullptr; + } + + v8::PrepareStackTraceCallback PrepareStackTraceCallback() const { + return prepare_stack_trace_callback_; + } + void SetAbortOnUncaughtExceptionCallback( v8::Isolate::AbortOnUncaughtExceptionCallback callback) { abort_on_uncaught_exception_callback_ = callback; @@ -83,9 +92,7 @@ class Isolate : public gc { } protected: - Escargot::ValueRef* scheduled_exception_{nullptr}; - - void set_pending_exception(Escargot::ObjectRef* exception_obj); + void set_pending_exception(Escargot::ValueRef* exception_obj); void set_pending_message_obj(Escargot::ValueRef* message_obj); void clear_pending_exception(); void clear_pending_message_obj(); @@ -93,6 +100,11 @@ class Isolate : public gc { v8::TryCatch* getExternalTryCatchOnTop(); bool hasExternalTryCatch(); + // @important memory layout (IsolateData, kEmbedderDataOffset, + // kExternalMemoryOffset, kExternalMemoryLlimitOffset and so on) aren't + // considered. + + Escargot::ValueRef* scheduled_exception_{nullptr}; v8::PromiseRejectCallback promise_reject_callback_{nullptr}; v8::PromiseHook promise_hook_{nullptr}; v8::MessageCallback message_callback_{nullptr}; @@ -103,7 +115,7 @@ class Isolate : public gc { private: v8::TryCatch* try_catch_handler_{nullptr}; - Escargot::ObjectRef* pending_exception_{nullptr}; + Escargot::ValueRef* pending_exception_{nullptr}; Escargot::ValueRef* pending_message_obj_{nullptr}; }; } // namespace internal @@ -183,7 +195,7 @@ class IsolateWrap final : public v8::internal::Isolate { VMInstanceRef* vmInstance() { return vmInstance_; } ValueWrap** getGlobal(const int idex); - ValueWrap* undefined(); + ValueWrap* undefined_value(); ValueWrap* hole() override; ValueWrap* null(); ValueWrap* trueValue(); @@ -212,6 +224,8 @@ class IsolateWrap final : public v8::internal::Isolate { void onFatalError(const char* location, const char* message); + void Throw(Escargot::ExecutionStateRef* state); + void lock_gc_release() { release_lock_.reset(this); } void unlock_gc_release() { release_lock_.release(); } diff --git a/lwnode/code/escargotshim/src/api/object.cc b/lwnode/code/escargotshim/src/api/object.cc index 40b2035..914a8d5 100644 --- a/lwnode/code/escargotshim/src/api/object.cc +++ b/lwnode/code/escargotshim/src/api/object.cc @@ -39,7 +39,10 @@ static ValueRef* accessorPropertyGetter( wrapper->m_isolate, self, receiver, VAL(wrapper->m_data)); auto v8Getter = wrapper->m_getter; - LWNODE_CHECK_NOT_NULL(v8Getter); + if (!v8Getter) { + return ValueRef::createUndefined(); + } + LWNODE_CALL_TRACE( "name: %s", VAL(wrapper->m_name)->value()->asString()->toStdUTF8String().c_str()) @@ -92,9 +95,7 @@ NativeDataAccessorPropertyDataWrap::NativeDataAccessorPropertyDataWrap( m_name(*name), m_getter(getter), m_setter(setter), - m_data(*data) { - LWNODE_CHECK_NOT_NULL(getter); -} + m_data(*data) {} Maybe ObjectUtils::SetAccessor(ObjectRef* esObject, IsolateWrap* lwIsolate, diff --git a/lwnode/code/escargotshim/src/api/serializer.cc b/lwnode/code/escargotshim/src/api/serializer.cc new file mode 100644 index 0000000..a7c365c --- /dev/null +++ b/lwnode/code/escargotshim/src/api/serializer.cc @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2021-present Samsung Electronics 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 "serializer.h" +#include "context.h" +#include "es-helper.h" +#include "isolate.h" + +using namespace Escargot; +using namespace v8; + +namespace EscargotShim { + +// base on v8/src/objects/value-serializer.cc + +static const uint32_t kLatestVersion = 13; + +enum class SerializationTag : uint8_t { + // version:uint32_t (if at beginning of data, sets version > 0) + kVersion = 0xFF, + // ignore + kPadding = '\0', + // refTableSize:uint32_t (previously used for sanity checks; safe to ignore) + kVerifyObjectCount = '?', + // Oddballs (no data). + kTheHole = '-', + kUndefined = '_', + kNull = '0', + kTrue = 'T', + kFalse = 'F', + // Number represented as 32-bit integer, ZigZag-encoded + // (like sint32 in protobuf) + kInt32 = 'I', + // Number represented as 32-bit unsigned integer, varint-encoded + // (like uint32 in protobuf) + kUint32 = 'U', + // Number represented as a 64-bit double. + // Host byte order is used (N.B. this makes the format non-portable). + kDouble = 'N', + // BigInt. Bitfield:uint32_t, then raw digits storage. + kBigInt = 'Z', + // byteLength:uint32_t, then raw data + kUtf8String = 'S', + kOneByteString = '"', + kTwoByteString = 'c', + // Reference to a serialized object. objectID:uint32_t + kObjectReference = '^', + // Beginning of a JS object. + kBeginJSObject = 'o', + // End of a JS object. numProperties:uint32_t + kEndJSObject = '{', + // Beginning of a sparse JS array. length:uint32_t + // Elements and properties are written as key/value pairs, like objects. + kBeginSparseJSArray = 'a', + // End of a sparse JS array. numProperties:uint32_t length:uint32_t + kEndSparseJSArray = '@', + // Beginning of a dense JS array. length:uint32_t + // |length| elements, followed by properties as key/value pairs + kBeginDenseJSArray = 'A', + // End of a dense JS array. numProperties:uint32_t length:uint32_t + kEndDenseJSArray = '$', + // Date. millisSinceEpoch:double + kDate = 'D', + // Boolean object. No data. + kTrueObject = 'y', + kFalseObject = 'x', + // Number object. value:double + kNumberObject = 'n', + // BigInt object. Bitfield:uint32_t, then raw digits storage. + kBigIntObject = 'z', + // String object, UTF-8 encoding. byteLength:uint32_t, then raw data. + kStringObject = 's', + // Regular expression, UTF-8 encoding. byteLength:uint32_t, raw data, + // flags:uint32_t. + kRegExp = 'R', + // Beginning of a JS map. + kBeginJSMap = ';', + // End of a JS map. length:uint32_t. + kEndJSMap = ':', + // Beginning of a JS set. + kBeginJSSet = '\'', + // End of a JS set. length:uint32_t. + kEndJSSet = ',', + // Array buffer. byteLength:uint32_t, then raw data. + kArrayBuffer = 'B', + // Array buffer (transferred). transferID:uint32_t + kArrayBufferTransfer = 't', + // View into an array buffer. + // subtag:ArrayBufferViewTag, byteOffset:uint32_t, byteLength:uint32_t + // For typed arrays, byteOffset and byteLength must be divisible by the size + // of the element. + // Note: kArrayBufferView is special, and should have an ArrayBuffer (or an + // ObjectReference to one) serialized just before it. This is a quirk arising + // from the previous stack-based implementation. + kArrayBufferView = 'V', + // Shared array buffer. transferID:uint32_t + kSharedArrayBuffer = 'u', + // A wasm module object transfer. next value is its index. + kWasmModuleTransfer = 'w', + // The delegate is responsible for processing all following data. + // This "escapes" to whatever wire format the delegate chooses. + kHostObject = '\\', + // A transferred WebAssembly.Memory object. maximumPages:int32_t, then by + // SharedArrayBuffer tag and its data. + kWasmMemoryTransfer = 'm', + // A list of (subtag: ErrorTag, [subtag dependent data]). See ErrorTag for + // details. + kError = 'r', + + // The following tags are reserved because they were in use in Chromium before + // the kHostObject tag was introduced in format version 13, at + // v8 refs/heads/master@{#43466} + // chromium/src refs/heads/master@{#453568} + // + // They must not be reused without a version check to prevent old values from + // starting to deserialize incorrectly. For simplicity, it's recommended to + // avoid them altogether. + // + // This is the set of tags that existed in SerializationTag.h at that time and + // still exist at the time of this writing (i.e., excluding those that were + // removed on the Chromium side because there should be no real user data + // containing them). + // + // It might be possible to also free up other tags which were never persisted + // (e.g. because they were used only for transfer) in the future. + kLegacyReservedMessagePort = 'M', + kLegacyReservedBlob = 'b', + kLegacyReservedBlobIndex = 'i', + kLegacyReservedFile = 'f', + kLegacyReservedFileIndex = 'e', + kLegacyReservedDOMFileSystem = 'd', + kLegacyReservedFileList = 'l', + kLegacyReservedFileListIndex = 'L', + kLegacyReservedImageData = '#', + kLegacyReservedImageBitmap = 'g', + kLegacyReservedImageBitmapTransfer = 'G', + kLegacyReservedOffscreenCanvas = 'H', + kLegacyReservedCryptoKey = 'K', + kLegacyReservedRTCCertificate = 'k', +}; + +ValueSerializer::ValueSerializer(v8::Isolate* isolate, + v8::ValueSerializer::Delegate* delegate) + : lwIsolate_(IsolateWrap::fromV8(isolate)), delegate_(delegate) {} + +void ValueSerializer::WriteHeader() { + WriteTag(SerializationTag::kVersion); + WriteVarint(kLatestVersion); +} + +bool ValueSerializer::WriteJSObject(ObjectRef* object) { + if (LWNODE_UNLIKELY(out_of_memory_)) { + return ThrowIfOutOfMemory(); + } + if (ObjectRefHelper::getInternalFieldCount(object) > 0) { + // TODO: WriteHostObject + LWNODE_UNIMPLEMENT; + return false; + } + + auto esContext = lwIsolate_->GetCurrentContext()->get(); + uint32_t propertiesWritten = 0; + WriteTag(SerializationTag::kBeginJSObject); + Escargot::ValueVectorRef* keys = nullptr; + EvalResult r = Evaluator::execute( + lwIsolate_->GetCurrentContext()->get(), + [](ExecutionStateRef* state, + ObjectRef* object, + Escargot::ValueVectorRef** keys) -> ValueRef* { + *keys = object->ownPropertyKeys(state); + return ValueRef::createUndefined(); + }, + object, + &keys); + LWNODE_CHECK(r.isSuccessful()); + + for (size_t i = 0; i < keys->size(); i++) { + auto propValueResult = + ObjectRefHelper::getProperty(esContext, object, keys->at(i)); + LWNODE_CHECK(propValueResult.isSuccessful()); + bool success = + WriteValue(keys->at(i)) && WriteValue(propValueResult.result); + if (!success) { + return false; + } + propertiesWritten++; + WriteTag(SerializationTag::kEndJSObject); + WriteVarint(propertiesWritten); + } + return ThrowIfOutOfMemory(); +} + +bool ValueSerializer::WriteValue(ValueRef* value) { + if (value->isUndefined()) { + LWNODE_UNIMPLEMENT; + } else if (value->isNull()) { + LWNODE_UNIMPLEMENT; + } else if (value->isBoolean()) { + LWNODE_UNIMPLEMENT; + } else if (value->isNumber()) { + LWNODE_UNIMPLEMENT; + } else if (value->isBigInt()) { + LWNODE_UNIMPLEMENT; + } else if (value->isArrayBufferObject()) { + LWNODE_UNIMPLEMENT; + } else if (value->isDataViewObject()) { + LWNODE_UNIMPLEMENT; + } else if (value->isString()) { + LWNODE_UNIMPLEMENT; + } else if (value->isTypedArrayObject()) { + LWNODE_UNIMPLEMENT; + } else if (value->isArrayObject()) { + LWNODE_UNIMPLEMENT; + } else if (value->isSymbol()) { + LWNODE_UNIMPLEMENT; + } else if (value->isFunctionObject()) { + LWNODE_UNIMPLEMENT; + } else if (value->isObject()) { + return WriteJSObject(value->asObject()); + } else { + LWNODE_UNIMPLEMENT; + } + return false; +} + +// base on v8 +void ValueSerializer::WriteTag(SerializationTag tag) { + uint8_t raw_tag = static_cast(tag); + WriteRawBytes(&raw_tag, sizeof(raw_tag)); +} + +// base on v8 +template +void ValueSerializer::WriteVarint(T value) { + // Writes an unsigned integer as a base-128 varint. + // The number is written, 7 bits at a time, from the least significant to the + // most significant 7 bits. Each byte, except the last, has the MSB set. + // See also https://developers.google.com/protocol-buffers/docs/encoding + static_assert(std::is_integral::value && std::is_unsigned::value, + "Only unsigned integer types can be written as varints."); + uint8_t stack_buffer[sizeof(T) * 8 / 7 + 1]; + uint8_t* next_byte = &stack_buffer[0]; + do { + *next_byte = (value & 0x7F) | 0x80; + next_byte++; + value >>= 7; + } while (value); + *(next_byte - 1) &= 0x7F; + WriteRawBytes(stack_buffer, next_byte - stack_buffer); +} + +// base on v8 +void ValueSerializer::WriteRawBytes(const void* source, size_t length) { + uint8_t* dest; + if (ReserveRawBytes(length).To(&dest) && length > 0) { + memcpy(dest, source, length); + } +} + +// base on v8 +Maybe ValueSerializer::ReserveRawBytes(size_t bytes) { + size_t old_size = buffer_size_; + size_t new_size = old_size + bytes; + if (LWNODE_UNLIKELY(new_size > buffer_capacity_)) { + bool ok; + if (!ExpandBuffer(new_size).To(&ok)) { + return Nothing(); + } + } + buffer_size_ = new_size; + return Just(&buffer_[old_size]); +} + +// base on v8 +Maybe ValueSerializer::ExpandBuffer(size_t required_capacity) { + LWNODE_CHECK(required_capacity > buffer_capacity_); + size_t requested_capacity = + std::max(required_capacity, buffer_capacity_ * 2) + 64; + size_t provided_capacity = 0; + void* new_buffer = nullptr; + if (delegate_) { + new_buffer = delegate_->ReallocateBufferMemory( + buffer_, requested_capacity, &provided_capacity); + } else { + new_buffer = realloc(buffer_, requested_capacity); + provided_capacity = requested_capacity; + } + if (new_buffer) { + LWNODE_CHECK(provided_capacity >= requested_capacity); + buffer_ = reinterpret_cast(new_buffer); + buffer_capacity_ = provided_capacity; + return Just(true); + } else { + out_of_memory_ = true; + return Nothing(); + } +} + +bool ValueSerializer::ThrowIfOutOfMemory() { + if (out_of_memory_) { + // TODO: thrwo internal error + return false; + } + return true; +} + +} // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/serializer.h b/lwnode/code/escargotshim/src/api/serializer.h new file mode 100644 index 0000000..9018cc3 --- /dev/null +++ b/lwnode/code/escargotshim/src/api/serializer.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021-present Samsung Electronics 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. + */ + +#pragma once + +#include +#include + +using namespace Escargot; + +namespace EscargotShim { + +enum class SerializationTag : uint8_t; + +class IsolateWrap; + +class ValueSerializer { + public: + ValueSerializer(v8::Isolate* isolate, + v8::ValueSerializer::Delegate* delegate); + void WriteHeader(); + bool WriteValue(ValueRef* value); + + private: + void WriteTag(SerializationTag tag); + template + void WriteVarint(T value); + void WriteUint32(uint32_t value); + void WriteUint64(uint64_t value); + void WriteRawBytes(const void* source, size_t length); + void WriteDouble(double value); + bool WriteJSObject(ObjectRef* object); + + v8::Maybe ReserveRawBytes(size_t bytes); + v8::Maybe ExpandBuffer(size_t required_capacity); + + bool ThrowIfOutOfMemory(); + + IsolateWrap* lwIsolate_ = nullptr; + v8::ValueSerializer::Delegate* delegate_ = nullptr; + uint8_t* buffer_ = nullptr; + size_t buffer_size_ = 0; + size_t buffer_capacity_ = 0; + bool out_of_memory_ = false; +}; + +} // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/stack-trace.cc b/lwnode/code/escargotshim/src/api/stack-trace.cc new file mode 100644 index 0000000..d48642f --- /dev/null +++ b/lwnode/code/escargotshim/src/api/stack-trace.cc @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2021-present Samsung Electronics 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 "stack-trace.h" +#include "api.h" +#include "base.h" +#include "context.h" +#include "isolate.h" + +using namespace Escargot; +using namespace v8; + +namespace EscargotShim { + +class NativeDataAccessorPropertyDataForStackTrace + : public ObjectRef::NativeDataAccessorPropertyData { + public: + NativeDataAccessorPropertyDataForStackTrace( + bool isWritable, + bool isEnumerable, + bool isConfigurable, + ObjectRef::NativeDataAccessorPropertyGetter getter, + ObjectRef::NativeDataAccessorPropertySetter setter, + ValueVectorRef* stackTraceVector) + : NativeDataAccessorPropertyData( + isWritable, isEnumerable, isConfigurable, getter, setter), + stackTraceVector_(stackTraceVector) {} + + ValueVectorRef* stackTraceVector() { return stackTraceVector_; } + + void* operator new(size_t size) { return GC_MALLOC(size); } + + private: + ValueVectorRef* stackTraceVector_; +}; + +static size_t getStackTraceLimit(ExecutionStateRef* state) { + auto errorObject = state->context()->globalObject()->get( + state, StringRef::createFromASCII("Error")); + LWNODE_CHECK(errorObject->isObject()); + + auto stackTraceLimitValue = errorObject->asObject()->get( + state, StringRef::createFromASCII("stackTraceLimit")); + LWNODE_CHECK(stackTraceLimitValue->isNumber()); + + return stackTraceLimitValue->asNumber(); +} + +static ValueRef* StackTraceGetter( + ExecutionStateRef* state, + ObjectRef* self, + ValueRef* receiver, + ObjectRef::NativeDataAccessorPropertyData* data) { + auto lwIsolate = IsolateWrap::GetCurrent(); + auto lwContext = lwIsolate->GetCurrentContext(); + auto accessorData = + reinterpret_cast(data); + + if (lwIsolate->HasPrepareStackTraceCallback()) { + auto sites = + ArrayObjectRef::create(state, accessorData->stackTraceVector()); + v8::MaybeLocal callbackResult = + lwIsolate->PrepareStackTraceCallback()( + v8::Utils::NewLocal(lwIsolate->toV8(), lwContext), + v8::Utils::NewLocal(lwIsolate->toV8(), self), + v8::Utils::NewLocal(lwIsolate->toV8(), sites)); + + if (!callbackResult.IsEmpty()) { + Local callbackResultLocal; + if (callbackResult.ToLocal(&callbackResultLocal)) { + return CVAL(*callbackResultLocal)->value(); + } + } + } + + return ValueRef::createUndefined(); +} + +static bool StackTraceSetter(ExecutionStateRef* state, + ObjectRef* self, + ValueRef* receiver, + ObjectRef::NativeDataAccessorPropertyData* data, + ValueRef* setterInputData) { + LWNODE_RETURN_FALSE; +} + +static ValueRef* captureStackTraceCallback(ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isConstructCall) { + if (argc < 1 || !argv[0]->isObject()) { + return ValueRef::createUndefined(); + } + + auto exceptionObject = argv[0]->asObject(); + auto callSite = IsolateWrap::GetCurrent()->GetCurrentContext()->callSite(); + auto stackTrace = state->computeStackTraceData(); + auto stackTraceVector = ValueVectorRef::create(); + + std::string filterFunctionName; + if (argc > 1 && argv[1]->isFunctionObject()) { + auto name = argv[1]->asFunctionObject()->get( + state, StringRef::createFromASCII("name")); + if (name->isString()) { + filterFunctionName = name->asString()->toStdUTF8String(); + } + } + + // TODO: handle `constructorOpt` option : + // compare the address of constructorOpt function not name. + int stacktraceStartIdx = 1; + size_t stackTraceLimit = getStackTraceLimit(state) + stacktraceStartIdx; + + for (size_t i = stacktraceStartIdx; + i < stackTraceLimit && i < stackTrace.size(); + i++) { + if (!filterFunctionName.empty() && + filterFunctionName == stackTrace[i].functionName->toStdUTF8String()) { + break; + } + + stackTraceVector->pushBack( + callSite->instantiate(state->context(), stackTrace[i])); + } + + exceptionObject->defineNativeDataAccessorProperty( + state, + StringRef::createFromUTF8("stack"), + new NativeDataAccessorPropertyDataForStackTrace(false, + false, + false, + StackTraceGetter, + StackTraceSetter, + stackTraceVector)); + + return ValueRef::createUndefined(); +} + +ValueRef* StackTrace::createCaptureStackTrace( + Escargot::ExecutionStateRef* state) { + FunctionObjectRef::NativeFunctionInfo info( + AtomicStringRef::create(state->context(), "captureStackTrace"), + captureStackTraceCallback, + 1, + true, + false); + + return FunctionObjectRef::create(state, info); +} + +static void setCallSitePrototype( + ContextRef* context, + ObjectTemplateRef* otpl, + const char* name, + Escargot::FunctionObjectRef::NativeFunctionPointer fn) { + auto length = strlen(name); + + EvalResult r = Evaluator::execute( + context, + [](ExecutionStateRef* state, + const char* name, + size_t length, + Escargot::FunctionObjectRef::NativeFunctionPointer fn) -> ValueRef* { + return FunctionObjectRef::create( + state, + FunctionObjectRef::NativeFunctionInfo( + AtomicStringRef::create(state->context(), name, length), + fn, + 0, + true, + false)); + }, + name, + length, + fn); + LWNODE_CHECK(r.isSuccessful()); + + otpl->set( + StringRef::createFromASCII(name, length), r.result, false, false, true); +} + +static void injectSitePrototype(ContextRef* context, ObjectTemplateRef* otpl) { + setCallSitePrototype( + context, + otpl, + "getFunctionName", + [](ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isNewExpression) -> ValueRef* { + auto data = ObjectRefHelper::getExtraData(thisValue->asObject()) + ->asStackTraceData(); + return data->functionName(); + }); + + setCallSitePrototype( + context, + otpl, + "getFileName", + [](ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isNewExpression) -> ValueRef* { + auto data = ObjectRefHelper::getExtraData(thisValue->asObject()) + ->asStackTraceData(); + return data->src(); + }); + + setCallSitePrototype( + context, + otpl, + "getLineNumber", + [](ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isNewExpression) -> ValueRef* { + auto data = ObjectRefHelper::getExtraData(thisValue->asObject()) + ->asStackTraceData(); + return ValueRef::create(data->loc().line); + }); + + setCallSitePrototype( + context, + otpl, + "getColumnNumber", + [](ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isNewExpression) -> ValueRef* { + auto data = ObjectRefHelper::getExtraData(thisValue->asObject()) + ->asStackTraceData(); + return ValueRef::create(data->loc().column); + }); + + setCallSitePrototype( + context, + otpl, + "isEval", + [](ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isNewExpression) -> ValueRef* { + auto data = ObjectRefHelper::getExtraData(thisValue->asObject()) + ->asStackTraceData(); + return ValueRef::create(data->isEval()); + }); + + setCallSitePrototype( + context, + otpl, + "toString", + [](ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isNewExpression) -> ValueRef* { + auto data = ObjectRefHelper::getExtraData(thisValue->asObject()) + ->asStackTraceData(); + std::ostringstream stream; + stream << data->functionName()->toStdUTF8String() << " (" + << data->src()->toStdUTF8String() << ":" << data->loc().line + << ":" << data->loc().column << ")"; + auto string = stream.str(); + return StringRef::createFromASCII(string.data(), string.length()); + }); +} + +CallSite::CallSite(ContextRef* context) { + template_ = FunctionTemplateRef::create( + AtomicStringRef::create(context, "CallSite"), + 0, + true, + true, + [](ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + OptionalRef newTarget) -> ValueRef* { + return ValueRef::createUndefined(); + }); + injectSitePrototype(context, template_->prototypeTemplate()); +} + +ValueRef* CallSite::instantiate(ContextRef* context, + const Evaluator::StackTraceData& data) { + auto callSite = template_->instanceTemplate()->instantiate(context); + ObjectRefHelper::setExtraData(callSite, new StackTraceData(data)); + return callSite; +}; + +} // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/stack-trace.h b/lwnode/code/escargotshim/src/api/stack-trace.h new file mode 100644 index 0000000..4853f08 --- /dev/null +++ b/lwnode/code/escargotshim/src/api/stack-trace.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-present Samsung Electronics 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. + */ + +#pragma once + +#include +#include + +using namespace Escargot; + +namespace EscargotShim { + +class StackTrace { + public: + static ValueRef* createCaptureStackTrace(ExecutionStateRef* state); +}; + +class CallSite : public gc { + public: + CallSite(Escargot::ContextRef* context); + + ValueRef* instantiate(ContextRef* context, + const Evaluator::StackTraceData& data); + + private: + FunctionTemplateRef* template_; +}; + +} // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/utils.h b/lwnode/code/escargotshim/src/api/utils.h index 51f7f49..fd24174 100644 --- a/lwnode/code/escargotshim/src/api/utils.h +++ b/lwnode/code/escargotshim/src/api/utils.h @@ -20,6 +20,5 @@ #include "utils/compiler.h" #include "utils/conversions-inl.h" #include "utils/gc.h" -#include "utils/logger.h" #include "utils/misc.h" #include "utils/string.h" diff --git a/lwnode/code/escargotshim/src/api/utils/debug.cc b/lwnode/code/escargotshim/src/api/utils/debug.cc index 6e80239..0d4f480 100644 --- a/lwnode/code/escargotshim/src/api/utils/debug.cc +++ b/lwnode/code/escargotshim/src/api/utils/debug.cc @@ -19,7 +19,7 @@ #include #endif #include "debug.h" -#include "logger.h" +#include "misc.h" namespace EscargotShim { @@ -43,6 +43,11 @@ static const char* getCurrentProcessName() { #endif void DebugUtils::printStackTrace() { +#if defined(NDEBUG) + if (EscargotShim::Flags::isInternalLogEnabled() == false) { + return; + } +#endif #if defined(LWNODE_PLATFORM_LINUX) void* frames[kStackTraceFrameSize]; static const char* processName = getCurrentProcessName(); diff --git a/lwnode/code/escargotshim/src/api/utils/gc-container.h b/lwnode/code/escargotshim/src/api/utils/gc-container.h index ba42490..a18dbb2 100644 --- a/lwnode/code/escargotshim/src/api/utils/gc-container.h +++ b/lwnode/code/escargotshim/src/api/utils/gc-container.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include "gc.h" @@ -27,7 +28,7 @@ class GCContainer : public gc { public: GCContainer() {} - explicit GCContainer(const size_t size, ...) { + explicit GCContainer(const size_t size, const size_t argc = 0, ...) { if (size) { buffer_ = (T*)Escargot::Memory::gcMalloc(sizeof(T) * size); size_ = size; @@ -35,9 +36,10 @@ class GCContainer : public gc { new (&buffer_[i]) T(); } + assert(argc <= size); std::va_list args; - va_start(args, size); - for (size_t i = 0; i < size; ++i) { + va_start(args, argc); + for (size_t i = 0; i < argc; ++i) { buffer_[i] = va_arg(args, T); } va_end(args); diff --git a/lwnode/code/escargotshim/src/api/utils/gc.cc b/lwnode/code/escargotshim/src/api/utils/gc.cc index 56b0f2c..b63025d 100644 --- a/lwnode/code/escargotshim/src/api/utils/gc.cc +++ b/lwnode/code/escargotshim/src/api/utils/gc.cc @@ -15,25 +15,22 @@ */ #include "gc.h" + #include -#include -#include "flags.h" -#include "logger.h" +#include "misc.h" using namespace Escargot; #define LOG_HANDLER(msg, ...) \ do { \ if (EscargotShim::Flags::isTraceGCEnabled()) { \ - LWNODE_LOG_RAW(COLOR_DIM msg COLOR_RESET, ##__VA_ARGS__); \ + LWNODE_LOG_RAW(CLR_DIM msg CLR_RESET, ##__VA_ARGS__); \ } \ } while (0) #define LOG_HANDLER_RAW(msg, ...) \ do { \ - if (EscargotShim::Flags::isTraceGCEnabled()) { \ - printf(msg, ##__VA_ARGS__); \ - } \ + printf(msg, ##__VA_ARGS__); \ } while (0) // --- GCTracer --- @@ -100,11 +97,11 @@ void GCTracer::printState() { for (const auto& it : registeredAddress_) { if (it.deallocated) { - LOG_HANDLER(COLOR_MAGENTA "deallocated: %s (%p)", + LOG_HANDLER(CLR_MAGENTA "deallocated: %s (%p)", it.description.c_str(), TO_GCPTR(it.ptr)); } else { - LOG_HANDLER(COLOR_YELLOW "backtrace of %s (%p):\n", + LOG_HANDLER(CLR_YELLOW "backtrace of %s (%p):\n", it.description.c_str(), TO_GCPTR(it.ptr)); @@ -159,14 +156,35 @@ void MemoryUtil::gcStartStatsTrace() { prettyBytes(heap, sizeof(heap), nheap, g_filter); LOG_HANDLER("use %s, heap %s", use, heap); }); +} -#ifdef ENABLE_GC_WARN - GC_set_warn_proc([](char* msg, GC_word arg) { - char formatted[1024]; - snprintf(formatted, sizeof(formatted) - 1, msg, arg); - LOG_HANDLER("[WARN] %s\n", formatted); - }); +static thread_local MemoryUtil::OnGCWarnEventListener g_gcWarnEventListener; + +void MemoryUtil::gcSetWarningListener(OnGCWarnEventListener callback) { + if (g_gcWarnEventListener == nullptr) { + g_gcWarnEventListener = callback; + + GC_set_warn_proc([](char* format, GC_word arg) { + /* + GC Warning: ...May lead to memory leak and poor performance + GC Warning: ...Failed to expand heap + GC Warning: Out of Memory! ... Returning NULL! + */ + std::string message = format; + +#if !defined(NDEBUG) + LOG_HANDLER_RAW(format, arg); #endif + + if (message.find("poor performance") != std::string::npos) { + g_gcWarnEventListener(POOR_PERFORMANCE); + } else if (message.find("Failed to expand heap") != std::string::npos) { + g_gcWarnEventListener(FAILED_TO_EXPAND_HEAP); + } else if (message.find("Out of Memory") != std::string::npos) { + g_gcWarnEventListener(OUT_OF_MEMORY); + } + }); + } } void MemoryUtil::printGCStats() { @@ -188,6 +206,7 @@ void MemoryUtil::printBacktrace(void* gcPtr) { } void MemoryUtil::printEveryReachableGCObjects() { +#if !defined(ESCARGOT_THREADING) LOG_HANDLER("print reachable pointers -->\n"); GC_gcollect(); GC_disable(); @@ -226,6 +245,7 @@ void MemoryUtil::printEveryReachableGCObjects() { LOG_HANDLER("<-- end of print reachable pointers %fKB (count: %zu)\n", temp.totalRemainSize / 1024.f, temp.totalCount); +#endif } void MemoryUtil::gcFull() { diff --git a/lwnode/code/escargotshim/src/api/utils/gc.h b/lwnode/code/escargotshim/src/api/utils/gc.h index 2e39091..8f9d0e9 100644 --- a/lwnode/code/escargotshim/src/api/utils/gc.h +++ b/lwnode/code/escargotshim/src/api/utils/gc.h @@ -159,8 +159,17 @@ class GCTracer { std::vector
registeredAddress_; }; +enum WarnEventType { + POOR_PERFORMANCE, + FAILED_TO_EXPAND_HEAP, + OUT_OF_MEMORY, +}; + class ESCARGOT_EXPORT MemoryUtil { public: + typedef void (*OnGCWarnEventListener)(WarnEventType type); + + static void gcSetWarningListener(OnGCWarnEventListener callback); static void gcStartStatsTrace(); static void gcEndStatsTrace(); static void gcFull(); diff --git a/lwnode/code/escargotshim/src/api/utils/flags.cc b/lwnode/code/escargotshim/src/api/utils/logger/flags.cc similarity index 100% rename from lwnode/code/escargotshim/src/api/utils/flags.cc rename to lwnode/code/escargotshim/src/api/utils/logger/flags.cc diff --git a/lwnode/code/escargotshim/src/api/utils/flags.h b/lwnode/code/escargotshim/src/api/utils/logger/flags.h similarity index 91% rename from lwnode/code/escargotshim/src/api/utils/flags.h rename to lwnode/code/escargotshim/src/api/utils/logger/flags.h index 2035e0b..e6b613f 100644 --- a/lwnode/code/escargotshim/src/api/utils/flags.h +++ b/lwnode/code/escargotshim/src/api/utils/logger/flags.h @@ -19,7 +19,11 @@ #include #include #include -#include "compiler.h" + +#if !defined(LWNODE_EXPORT) +#define LWNODE_EXPORT __attribute__((visibility("default"))) +#define LWNODE_LOCAL __attribute__((visibility("hidden"))) +#endif namespace EscargotShim { diff --git a/lwnode/code/escargotshim/src/api/utils/logger.cc b/lwnode/code/escargotshim/src/api/utils/logger/logger.cc similarity index 83% rename from lwnode/code/escargotshim/src/api/utils/logger.cc rename to lwnode/code/escargotshim/src/api/utils/logger/logger.cc index 5d6e854..88ee28c 100644 --- a/lwnode/code/escargotshim/src/api/utils/logger.cc +++ b/lwnode/code/escargotshim/src/api/utils/logger/logger.cc @@ -15,6 +15,7 @@ */ #include "logger.h" +#include #include #include #include @@ -42,27 +43,36 @@ thread_local int s_indentCount = 0; thread_local int s_deltaCount = 0; thread_local std::set s_counterIds; +#define FORCE_ENABLE_INDENT_ID "NODE" + +static bool isIndentIdEnabled(std::string id) { + if (id == FORCE_ENABLE_INDENT_ID) { + return true; + } + return EscargotShim::Flags::isTraceCallEnabled(id); +} + void IndentCounter::indent(std::string id) { - if (EscargotShim::Flags::isTraceCallEnabled(id) == false) return; + if (isIndentIdEnabled(id) == false) return; s_deltaCount++; } void IndentCounter::unIndent(std::string id) { - if (EscargotShim::Flags::isTraceCallEnabled(id) == false) return; + if (isIndentIdEnabled(id) == false) return; s_deltaCount--; } IndentCounter::IndentCounter(std::string id) { id_ = id; - if (EscargotShim::Flags::isTraceCallEnabled(id) == false) return; + if (isIndentIdEnabled(id) == false) return; s_indentCount++; s_counterIds.insert(id); } IndentCounter::~IndentCounter() { - if (EscargotShim::Flags::isTraceCallEnabled(id_) == false) return; + if (isIndentIdEnabled(id_) == false) return; s_indentCount--; s_counterIds.erase(id_); diff --git a/lwnode/code/escargotshim/src/api/utils/logger.h b/lwnode/code/escargotshim/src/api/utils/logger/logger.h similarity index 65% rename from lwnode/code/escargotshim/src/api/utils/logger.h rename to lwnode/code/escargotshim/src/api/utils/logger/logger.h index ab2aaec..5ba6d71 100644 --- a/lwnode/code/escargotshim/src/api/utils/logger.h +++ b/lwnode/code/escargotshim/src/api/utils/logger/logger.h @@ -16,31 +16,30 @@ #pragma once -#include #include #include #include "flags.h" -#define COLOR_RESET "\033[0m" -#define COLOR_DIM "\033[0;2m" -#define COLOR_RED "\033[0;31m" -#define COLOR_GREEN "\033[0;32m" -#define COLOR_GREY "\033[0;37m" -#define COLOR_BLACK "\033[0;30m" -#define COLOR_YELLOW "\033[0;33m" -#define COLOR_BLUE "\033[0;34m" -#define COLOR_MAGENTA "\033[0;35m" -#define COLOR_CYAN "\033[0;36m" -#define COLOR_DARKGREY "\033[01;30m" -#define COLOR_BRED "\033[01;31m" -#define COLOR_BYELLOW "\033[01;33m" -#define COLOR_BBLUE "\033[01;34m" -#define COLOR_BMAGENTA "\033[01;35m" -#define COLOR_BCYAN "\033[01;36m" -#define COLOR_BGREEN "\033[01;32m" -#define COLOR_WHITE "\033[01;37m" -#define COLOR_REDBG "\033[0;41m" +#define CLR_RESET "\033[0m" +#define CLR_DIM "\033[0;2m" +#define CLR_RED "\033[0;31m" +#define CLR_GREEN "\033[0;32m" +#define CLR_GREY "\033[0;37m" +#define CLR_BLACK "\033[0;30m" +#define CLR_YELLOW "\033[0;33m" +#define CLR_BLUE "\033[0;34m" +#define CLR_MAGENTA "\033[0;35m" +#define CLR_CYAN "\033[0;36m" +#define CLR_DARKGREY "\033[01;30m" +#define CLR_BRED "\033[01;31m" +#define CLR_BYELLOW "\033[01;33m" +#define CLR_BBLUE "\033[01;34m" +#define CLR_BMAGENTA "\033[01;35m" +#define CLR_BCYAN "\033[01;36m" +#define CLR_BGREEN "\033[01;32m" +#define CLR_WHITE "\033[01;37m" +#define CLR_REDBG "\033[0;41m" std::string getPrettyFunctionName(const std::string fullname); std::string createCodeLocation(const char* functionName, @@ -69,40 +68,41 @@ class IndentCounter { #define TRACE_ARGS2 \ getPrettyFunctionName(__PRETTY_FUNCTION__).c_str(), __FILENAME__, __LINE__ -#if !defined(NDEBUG) #define LWNODE_LOG_RAW(fmt, ...) \ do { \ fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ } while (0); + +#if !defined(NDEBUG) +#define LWNODE_LOG_INTERNAL(fmt, ...) LWNODE_LOG_RAW(fmt, ##__VA_ARGS__); #else -#define LWNODE_LOG_RAW(fmt, ...) \ - do { \ - if (EscargotShim::Flags::isInternalLogEnabled() == true) { \ - fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ - } \ - } while (0); +#define LWNODE_LOG_INTERNAL(fmt, ...) \ + if (EscargotShim::Flags::isInternalLogEnabled()) { \ + LWNODE_LOG_RAW(fmt, ##__VA_ARGS__); \ + } #endif #define LWNODE_LOG_INFO(fmt, ...) \ - LWNODE_LOG_RAW("INFO " fmt COLOR_RESET, ##__VA_ARGS__); + LWNODE_LOG_INTERNAL("INFO " fmt CLR_RESET, ##__VA_ARGS__); #define LWNODE_LOG_WARN(fmt, ...) \ - LWNODE_LOG_RAW(COLOR_YELLOW "WARN " fmt COLOR_RESET, ##__VA_ARGS__); + LWNODE_LOG_INTERNAL(CLR_YELLOW "WARN " fmt CLR_RESET, ##__VA_ARGS__); #define LWNODE_LOG_ERROR(fmt, ...) \ - LWNODE_LOG_RAW(COLOR_BRED "ERROR " fmt COLOR_RESET, ##__VA_ARGS__); + LWNODE_LOG_INTERNAL(CLR_BRED "ERROR " fmt CLR_RESET, ##__VA_ARGS__); #define LWNODE_UNIMPLEMENT \ - LWNODE_LOG_RAW(COLOR_RED "UNIMPLEMENTED " TRACE_FMT COLOR_RESET, TRACE_ARGS2); + LWNODE_LOG_INTERNAL(CLR_RED "UNIMPLEMENTED " TRACE_FMT CLR_RESET, \ + TRACE_ARGS2); #define LWNODE_UNIMPLEMENT_IGNORED \ - LWNODE_LOG_RAW(COLOR_DIM "UNIMPLEMENTED (IGNORED) " TRACE_FMT COLOR_RESET, \ - TRACE_ARGS2); + LWNODE_LOG_INTERNAL(CLR_DIM "UNIMPLEMENTED (IGNORED) " TRACE_FMT CLR_RESET, \ + TRACE_ARGS2); #define LWNODE_UNIMPLEMENT_WORKAROUND \ - LWNODE_LOG_RAW(COLOR_DIM \ - "UNIMPLEMENTED (USE WORKAROUND) " TRACE_FMT COLOR_RESET, \ - TRACE_ARGS2); + LWNODE_LOG_INTERNAL(CLR_DIM \ + "UNIMPLEMENTED (USE WORKAROUND) " TRACE_FMT CLR_RESET, \ + TRACE_ARGS2); // conditional loggers diff --git a/lwnode/code/escargotshim/src/api/utils/logger/trace.h b/lwnode/code/escargotshim/src/api/utils/logger/trace.h new file mode 100644 index 0000000..aec155d --- /dev/null +++ b/lwnode/code/escargotshim/src/api/utils/logger/trace.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021-present Samsung Electronics 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. + */ + +#pragma once + +#include "flags.h" +#include "logger.h" + +#if !defined(NDEBUG) + +#define FIRST_ARG(N, ...) N +#define LEFT_ARGS(N, ...) , ##__VA_ARGS__ +#define TRACE_TAG_FMT CLR_DIM "TRACE (%-10s)" +#define TRACE_TAG_ARG(id) std::string(id).substr(0, 10).c_str() +#define COUNTER_FMT "%s" +#define COUNTER_ARG(id) IndentCounter::getString(id).c_str() + +#define LWNODE_CALL_TRACE_ID_LOG(id, ...) \ + if (EscargotShim::Flags::isTraceCallEnabled(#id)) { \ + LWNODE_DLOG_RAW(TRACE_TAG_FMT " " COUNTER_FMT TRACE_FMT \ + " " CLR_RESET FIRST_ARG(__VA_ARGS__) \ + CLR_RESET, \ + TRACE_TAG_ARG(#id), \ + COUNTER_ARG(#id), \ + TRACE_ARGS2 LEFT_ARGS(__VA_ARGS__)); \ + } + +#define LWNODE_CALL_TRACE_ID(id, ...) \ + IndentCounter __counter(#id); \ + LWNODE_CALL_TRACE_ID_LOG(id, __VA_ARGS__) + +#define LWNODE_CALL_TRACE_ID_INDENT(id) IndentCounter::indent(#id); +#define LWNODE_CALL_TRACE_ID_UNINDENT(id) IndentCounter::unIndent(#id); + +#define LWNODE_CALL_TRACE(msg, ...) \ + LWNODE_CALL_TRACE_ID(COMMON, msg, ##__VA_ARGS__); +#define LWNODE_CALL_TRACE_LOG(msg, ...) \ + LWNODE_CALL_TRACE_ID_LOG(COMMON, msg, ##__VA_ARGS__); +#define LWNODE_CALL_TRACE_INDENT() LWNODE_CALL_TRACE_ID_INDENT(COMMON); +#define LWNODE_CALL_TRACE_UNINDENT() LWNODE_CALL_TRACE_ID_UNINDENT(COMMON); + +#define LWNODE_CALL_TRACE_GC_START(msg, ...) \ + if (EscargotShim::Flags::isTraceCallEnabled("gc")) { \ + LWNODE_DLOG_INFO("GC: %s (%s:%d): " msg, TRACE_ARGS, ##__VA_ARGS__); \ + } + +#define LWNODE_CALL_TRACE_GC_END(msg, ...) \ + if (EscargotShim::Flags::isTraceCallEnabled("gc")) { \ + LWNODE_DLOG_INFO("GC: /%s (%s:%d): " msg, TRACE_ARGS, ##__VA_ARGS__); \ + } + +#else +#define LWNODE_CALL_TRACE_ID(...) +#define LWNODE_CALL_TRACE_ID_LOG(...) +#define LWNODE_CALL_TRACE_ID_INDENT(...) +#define LWNODE_CALL_TRACE_ID_UNINDENT(...) + +#define LWNODE_CALL_TRACE(...) +#define LWNODE_CALL_TRACE_LOG(...) +#define LWNODE_CALL_TRACE_INDENT() +#define LWNODE_CALL_TRACE_UNINDENT() +#define LWNODE_CALL_TRACE_GC_START(...) +#define LWNODE_CALL_TRACE_GC_END(...) +#endif + +#if !defined(NDEBUG) +#define LWNODE_ONCE(operation) \ + do { \ + static bool once##__LINE__ = false; \ + if (!once##__LINE__) { \ + operation; \ + once##__LINE__ = true; \ + } \ + } while (0) +#else +#define LWNODE_ONCE(operation) +#endif diff --git a/lwnode/code/escargotshim/src/api/utils/misc.h b/lwnode/code/escargotshim/src/api/utils/misc.h index 8b570f4..5205bca 100644 --- a/lwnode/code/escargotshim/src/api/utils/misc.h +++ b/lwnode/code/escargotshim/src/api/utils/misc.h @@ -18,8 +18,7 @@ #include #include "debug.h" -#include "flags.h" -#include "logger.h" +#include "logger/trace.h" /* UNLIKELY */ #ifndef LWNODE_UNLIKELY @@ -41,10 +40,11 @@ /* CHECK */ // Use CHECK when abort should occurs if the condition fails -#define CHECK_FMT COLOR_REDBG "CHECK FAILED" COLOR_RESET " " +#define CHECK_FMT CLR_REDBG "CHECK FAILED" CLR_RESET " " #define _LWNODE_CHECK_FAILED_HANDLER(msg, ...) \ - LWNODE_LOG_RAW(CHECK_FMT msg "\n\t " TRACE_FMT, ##__VA_ARGS__, TRACE_ARGS); \ + LWNODE_LOG_INTERNAL( \ + CHECK_FMT msg "\n\t " TRACE_FMT, ##__VA_ARGS__, TRACE_ARGS); \ EscargotShim::DebugUtils::printStackTrace(); \ std::abort(); @@ -74,79 +74,3 @@ #define LWNODE_DCHECK_NOT_NULL(x) #define LWNODE_DCHECK_MSG(condition, msg, ...) #endif - -#if !defined(NDEBUG) - -#define FIRST_ARG(N, ...) N -#define LEFT_ARGS(N, ...) , ##__VA_ARGS__ -#define TRACE_TAG_FMT COLOR_DIM "TRACE (%-10s)" -#define TRACE_TAG_ARG(id) std::string(id).substr(0, 10).c_str() -#define COUNTER_FMT "%s" -#define COUNTER_ARG(id) IndentCounter::getString(id).c_str() - -#define LWNODE_CALL_TRACE_ID(id, ...) \ - IndentCounter __counter(#id); \ - if (EscargotShim::Flags::isTraceCallEnabled(#id)) { \ - LWNODE_DLOG_RAW(TRACE_TAG_FMT " " COUNTER_FMT TRACE_FMT \ - " " COLOR_RESET FIRST_ARG(__VA_ARGS__) \ - COLOR_RESET, \ - TRACE_TAG_ARG(#id), \ - COUNTER_ARG(#id), \ - TRACE_ARGS2 LEFT_ARGS(__VA_ARGS__)); \ - } - -#define LWNODE_CALL_TRACE_ID_LOG(id, ...) \ - if (EscargotShim::Flags::isTraceCallEnabled(#id)) { \ - LWNODE_DLOG_RAW(TRACE_TAG_FMT \ - " " COUNTER_FMT COLOR_RESET FIRST_ARG(__VA_ARGS__) \ - COLOR_RESET, \ - TRACE_TAG_ARG(#id), \ - COUNTER_ARG(#id) LEFT_ARGS(__VA_ARGS__)); \ - } - -#define LWNODE_CALL_TRACE_ID_INDENT(id) IndentCounter::indent(#id); -#define LWNODE_CALL_TRACE_ID_UNINDENT(id) IndentCounter::unIndent(#id); - -#define LWNODE_CALL_TRACE(msg, ...) \ - LWNODE_CALL_TRACE_ID(COMMON, msg, ##__VA_ARGS__); -#define LWNODE_CALL_TRACE_LOG(msg, ...) \ - LWNODE_CALL_TRACE_ID_LOG(COMMON, msg, ##__VA_ARGS__); -#define LWNODE_CALL_TRACE_INDENT() LWNODE_CALL_TRACE_ID_INDENT(COMMON); -#define LWNODE_CALL_TRACE_UNINDENT() LWNODE_CALL_TRACE_ID_UNINDENT(COMMON); - -#define LWNODE_CALL_TRACE_GC_START(msg, ...) \ - if (EscargotShim::Flags::isTraceCallEnabled("gc")) { \ - LWNODE_DLOG_INFO("GC: %s (%s:%d): " msg, TRACE_ARGS, ##__VA_ARGS__); \ - } - -#define LWNODE_CALL_TRACE_GC_END(msg, ...) \ - if (EscargotShim::Flags::isTraceCallEnabled("gc")) { \ - LWNODE_DLOG_INFO("GC: /%s (%s:%d): " msg, TRACE_ARGS, ##__VA_ARGS__); \ - } - -#else -#define LWNODE_CALL_TRACE_ID(...) -#define LWNODE_CALL_TRACE_ID_LOG(...) -#define LWNODE_CALL_TRACE_ID_INDENT(...) -#define LWNODE_CALL_TRACE_ID_UNINDENT(...) - -#define LWNODE_CALL_TRACE(...) -#define LWNODE_CALL_TRACE_LOG(...) -#define LWNODE_CALL_TRACE_INDENT() -#define LWNODE_CALL_TRACE_UNINDENT() -#define LWNODE_CALL_TRACE_GC_START(...) -#define LWNODE_CALL_TRACE_GC_END(...) -#endif - -#if !defined(NDEBUG) -#define LWNODE_ONCE(operation) \ - do { \ - static bool once##__LINE__ = false; \ - if (!once##__LINE__) { \ - operation; \ - once##__LINE__ = true; \ - } \ - } while (0) -#else -#define LWNODE_ONCE(operation) -#endif diff --git a/lwnode/code/escargotshim/src/api/utils/smaps.cc b/lwnode/code/escargotshim/src/api/utils/smaps.cc new file mode 100644 index 0000000..406273e --- /dev/null +++ b/lwnode/code/escargotshim/src/api/utils/smaps.cc @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2021-present Samsung Electronics 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. + * + * @author lwnode-contributors + */ + +#include "smaps.h" +#include +#include +#include +#include +#include +#include +#include + +// utils + +bool existsFile(const std::string& path) { + std::ifstream fs(path); + return fs.good(); +} + +std::string getCurrentTimeString(std::string format) { + std::stringstream ss; + auto time = std::time(nullptr); + ss << std::put_time(std::localtime(&time), format.c_str()); + return ss.str(); +} + +static std::vector tokenize(const std::string& str) { + std::vector result; + std::string token; + std::stringstream ss(str); + + while (ss >> token) { + result.push_back(token); + } + return result; +} + +static std::vector tokenize(const std::string& str, + const char delimiter) { + std::vector result; + std::string token; + std::stringstream ss(str); + + while (std::getline(ss, token, delimiter)) { + result.push_back(token); + } + return result; +} + +static inline bool startsWith(const std::string& string, + const std::string& prefix) { + return (string.rfind(prefix, 0) == 0); +} + +static std::string trimString(std::string& str, + const std::string& delimiters = " \t\n\v\f\r") { + str.erase(str.find_last_not_of(delimiters) + 1); + str.erase(0, str.find_first_not_of(delimiters)); + return str; +} + +// parseSmaps + +static std::string getMemoryRegionString(std::string pathname) { + std::string type = "ANONYMOUS"; + if (pathname[0] != '/') { + if (startsWith(pathname, "[stack") || startsWith(pathname, "[tstack")) { + type = "STACK"; + } else if (startsWith(pathname, "[heap") || pathname.empty()) { + type = "HEAP/MMAP"; + } else if (startsWith(pathname, "[vdso")) { + type = "VDSO"; + } + } else if (existsFile(pathname)) { + type = "LIBRARY"; + } + return type; +} + +std::vector parseSmaps(std::istream& input) { + std::vector result; + std::string line; + + SmapContents map; + bool isHeaderFound = false; + + while (std::getline(input, line, '\n')) { + if (line.find("-") != std::string::npos) { + isHeaderFound = true; + if (map.empty() == false) { + result.push_back(map); + map.clear(); + } + /* + The format is: + + address perms offset dev inode pathname + + 08048000-08049000 r-xp 00000000 03:00 8312 /opt/test + 08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test + 0804a000-0806b000 rw-p 00000000 00:00 0 [heap] + a7cb1000-a7cb2000 ---p 00000000 00:00 0 + */ + auto tokens = tokenize(line); + auto address = tokenize(tokens[0], '-'); + + map[kStartingAddr] = address[0]; + map[kEndingAddr] = address[1]; + map[kPermissions] = tokens[1].substr(tokens[1].size() - 1) + + tokens[1].substr(0, tokens[1].size() - 1); + + map[kOffset] = tokens[2]; + map[kDev] = tokens[3]; + map[kInode] = tokens[4]; + + std::string pathname = (tokens.size() == 6) ? tokens[5] : ""; + map[kPathname] = pathname; + map[kRegion] = getMemoryRegionString(pathname); + } else { + if (isHeaderFound == false) { + continue; + } + /* + The format is: + + Size: 1084 kB + KernelPageSize: 4 kB + MMUPageSize: 4 kB + Rss: 892 kB + Pss: 374 kB + Shared_Clean: 892 kB + Shared_Dirty: 0 kB + Private_Clean: 0 kB + Private_Dirty: 0 kB + Referenced: 892 kB + Anonymous: 0 kB + LazyFree: 0 kB + AnonHugePages: 0 kB + ShmemPmdMapped: 0 kB + Shared_Hugetlb: 0 kB + Private_Hugetlb: 0 kB + Swap: 0 kB + SwapPss: 0 kB + KernelPageSize: 4 kB + MMUPageSize: 4 kB + Locked: 0 kB + THPeligible: 0 + */ + auto tokens = tokenize(line, ':'); + if (tokens.size() == 2) { + std::string count = trimString(tokens[1]); + if (count.rfind(" kB") != std::string::npos) { + count = count.substr(0, count.size() - 3); // 3: " kB" + } + map[trimString(tokens[0])] = count; + } + } + } + + return result; +} + +std::vector parseSmaps(std::string pid) { + auto smapsPath = "/proc/" + pid + "/smaps"; + if (existsFile(smapsPath)) { + std::ifstream input("/proc/" + pid + "/smaps"); + return parseSmaps(input); + } + return std::vector(); +} + +size_t calculateTotal(std::vector& smaps, const char* key) { + size_t total = 0; + for (auto& smap : smaps) { + total += std::stoull(smap[key]); + } + return total; +} + +size_t calculateTotalPssSwap(std::vector& smaps) { + size_t total = 0; + for (auto& smap : smaps) { + total += (std::stoull(smap["Pss"]) + std::stoull(smap["Swap"])); + } + return total; +} + +size_t calculateTotalRss(std::vector& smaps) { + size_t total = 0; + for (auto& smap : smaps) { + total += std::stoull(smap["Rss"]); + } + return total; +} + +std::string getMemorySnapshotString(std::vector& smaps, + SnapshotStringOption option) { + std::stringstream output; + + if (option & kShowFullInfo) { + output << "perms,start-addr,end-addr,vm_name,offset,dev,inode,vm_size,rss," + "pss,swap,total_pss"; + if (option & kShowRegion) { + output << ",region"; + } + output << std::endl; + } else { + output + << "perms,start-addr,end-addr,vm_name,vm_size,rss,pss,swap,total_pss"; + if (option & kShowRegion) { + output << ",region"; + } + output << std::endl; + } + + const int kApiSystemPointerSize = sizeof(void*); + const int kAlignSize = kApiSystemPointerSize * 2 - 4; + + for (auto& smap : smaps) { + auto totalPass = std::stoull(smap["Pss"]) + std::stoull((smap["Swap"])); + output << smap[kPermissions] << "," + << "0x" << std::setfill('0') << std::setw(kAlignSize) + << smap[kStartingAddr] << "," + << "0x" << std::setfill('0') << std::setw(kAlignSize) + << smap[kEndingAddr] << ","; + + auto pathname = smap[kPathname]; + if (option & kUseShortPath) { + std::size_t found = pathname.rfind('/'); + if (found != std::string::npos) { + pathname = pathname.substr(found + 1); + } + } + output << pathname; + + if (option & kShowFullInfo) { + output << "," << smap[kOffset] << "," << smap[kDev] << "," + << smap[kInode]; + } + output << "," << smap["Size"] << "," << smap["Rss"] << "," << smap["Pss"] + << "," << smap["Swap"] << "," << totalPass; + if (option & kShowRegion) { + output << "," << smap[kRegion]; + } + output << std::endl; + } + + return output.str(); +} + +bool dumpMemorySnapshot(std::string outputPath, + std::vector& smaps) { + std::ofstream output(outputPath); + + if (!output) { + return false; + } + + SnapshotStringOption option = + static_cast(kUseShortPath | kShowRegion); + output << getMemorySnapshotString(smaps, option); + return true; +} diff --git a/lwnode/code/escargotshim/src/api/utils/smaps.h b/lwnode/code/escargotshim/src/api/utils/smaps.h new file mode 100644 index 0000000..a035e4d --- /dev/null +++ b/lwnode/code/escargotshim/src/api/utils/smaps.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021-present Samsung Electronics 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. + * + * @author lwnode-contributors + */ + +#pragma once + +#include +#include +#include + +typedef std::unordered_map SmapContents; + +constexpr const char* kStartingAddr = "StartingAddr"; +constexpr const char* kEndingAddr = "EndingAddr"; +constexpr const char* kPermissions = "Permissions"; +constexpr const char* kOffset = "Offset"; +constexpr const char* kDev = "Dev"; +constexpr const char* kInode = "Inode"; +constexpr const char* kPathname = "Pathname"; +constexpr const char* kRegion = "Region"; +constexpr const char* kPss = "Pss"; +constexpr const char* kSwap = "Swap"; + +std::vector parseSmaps(std::string pid); +size_t calculateTotal(std::vector& smaps, const char* key); +size_t calculateTotalPssSwap(std::vector& smaps); +size_t calculateTotalRss(std::vector& smaps); +bool dumpMemorySnapshot(std::string outputPath, + std::vector& smaps); + +enum SnapshotStringOption { + kShowDefault = 0, + kShowFullInfo = 1, + kUseShortPath = 1 << 1, + kShowRegion = 1 << 2, +}; + +std::string getMemorySnapshotString(std::vector& smaps, + SnapshotStringOption option = kShowDefault); + +bool existsFile(const std::string& path); +std::string getCurrentTimeString(std::string format = "%y%m%d-%H%M%S"); diff --git a/lwnode/code/escargotshim/src/base.h b/lwnode/code/escargotshim/src/base.h index ff5f0cc..846daf4 100644 --- a/lwnode/code/escargotshim/src/base.h +++ b/lwnode/code/escargotshim/src/base.h @@ -18,6 +18,10 @@ #include "unimplemented.h" +namespace EscargotShim { +class ValueWrap; +} + #define VAL(that) reinterpret_cast(that) #define CVAL(that) reinterpret_cast(that) @@ -40,17 +44,19 @@ #define __DLOG_EVAL_EXCEPTION(eval_result) #endif -#define API_ENTER(isolate, bailout_value) \ - LWNODE_CALL_TRACE(); \ +#define __CALL_TRACE_ID(id, ...) LWNODE_CALL_TRACE_ID(id) + +#define API_ENTER(isolate, bailout_value, ...) \ + __CALL_TRACE_ID(__VA_ARGS__ __VA_OPT__(, ) COMMON); \ IsolateWrap* lwIsolate = IsolateWrap::fromV8(isolate); \ __TERMINATION_CHECK(lwIsolate, bailout_value) -#define API_ENTER_NO_EXCEPTION(isolate) \ - LWNODE_CALL_TRACE(); \ +#define API_ENTER_NO_EXCEPTION(isolate, ...) \ + __CALL_TRACE_ID(__VA_ARGS__ __VA_OPT__(, ) COMMON); \ IsolateWrap* lwIsolate = IsolateWrap::fromV8(isolate); -#define API_ENTER_WITH_CONTEXT(local_context, bailout_value) \ - LWNODE_CALL_TRACE(); \ +#define API_ENTER_WITH_CONTEXT(local_context, bailout_value, ...) \ + __CALL_TRACE_ID(__VA_ARGS__ __VA_OPT__(, ) COMMON); \ IsolateWrap* lwIsolate = local_context.IsEmpty() \ ? IsolateWrap::GetCurrent() \ : VAL(*local_context)->context()->GetIsolate(); \ diff --git a/lwnode/code/escargotshim/src/lwnode.cc b/lwnode/code/escargotshim/src/lwnode.cc new file mode 100644 index 0000000..3c69a6d --- /dev/null +++ b/lwnode/code/escargotshim/src/lwnode.cc @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2021-present Samsung Electronics 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 "lwnode/lwnode.h" +#include +#include +#include +#include "api.h" +#include "api/isolate.h" +#include "api/utils/misc.h" +#include "api/utils/smaps.h" +#include "base.h" + +using namespace v8; +using namespace EscargotShim; +using namespace std::literals; + +namespace LWNode { + +static void SetMethod(ContextRef* context, + ObjectRef* target, + std::string name, + NativeFunctionPointer nativeFunction) { + Evaluator::execute( + context, + [](ExecutionStateRef* state, + ObjectRef* target, + StringRef* name, + NativeFunctionPointer nativeFunction) -> ValueRef* { + target->defineDataProperty( + state, + name, + FunctionObjectRef::create(state, + FunctionObjectRef::NativeFunctionInfo( + AtomicStringRef::emptyAtomicString(), + nativeFunction, + 0, + true, + false)), + true, + true, + true); + + return ValueRef::createUndefined(); + }, + target, + StringRef::createFromASCII(name.c_str(), name.length()), + nativeFunction); +} + +constexpr auto kSmapCacheDuration = 600ms; + +static std::vector& getSelfSmaps() { + static std::vector s_cachedSmaps = parseSmaps("self"); + static auto s_lastUpdatedTime = std::chrono::steady_clock::now(); + + if (std::chrono::duration_cast( + std::chrono::steady_clock::now() - s_lastUpdatedTime) < + kSmapCacheDuration) { + return s_cachedSmaps; + } + + s_cachedSmaps = parseSmaps("self"); + s_lastUpdatedTime = std::chrono::steady_clock::now(); + return s_cachedSmaps; +} + +static std::string createDumpFilePath() { + std::string appName; + std::ifstream("/proc/self/comm") >> appName; + std::string outputPath = + "/tmp/smaps-" + appName + "-" + getCurrentTimeString() + ".csv"; + return outputPath; +} + +bool dumpSelfMemorySnapshot() { + auto& smaps = getSelfSmaps(); + return dumpMemorySnapshot(createDumpFilePath(), smaps); +} + +static ValueRef* PssUsage(ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isConstructCall) { + auto& smaps = getSelfSmaps(); + size_t total = calculateTotal(smaps, kPss); + return ValueRef::create(total); +}; + +static ValueRef* PssSwapUsage(ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isConstructCall) { + auto& smaps = getSelfSmaps(); + size_t total = calculateTotalPssSwap(smaps); + return ValueRef::create(total); +}; + +static ValueRef* RssUsage(ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isConstructCall) { + auto& smaps = getSelfSmaps(); + size_t total = calculateTotalRss(smaps); + return ValueRef::create(total); +}; + +static ValueRef* MemSnapshot(ExecutionStateRef* state, + ValueRef* thisValue, + size_t argc, + ValueRef** argv, + bool isConstructCall) { +#ifdef PRODUCTION + return ValueRef::create(false); +#endif + auto outputPath = createDumpFilePath(); + auto& smaps = getSelfSmaps(); + if (dumpMemorySnapshot(outputPath, smaps)) { + return StringRef::createFromASCII(outputPath.c_str(), outputPath.length()); + } + return ValueRef::createUndefined(); +}; + +void InitializeProcessMethods(Local target, Local context) { + auto esContext = CVAL(*context)->context()->get(); + auto esTarget = CVAL(*target)->value()->asObject(); + +#if !defined(NDEBUG) + EvalResultHelper::attachBuiltinPrint(esContext, esTarget); +#endif + + SetMethod(esContext, esTarget, "PssUsage", PssUsage); + SetMethod(esContext, esTarget, "RssUsage", RssUsage); + SetMethod(esContext, esTarget, "PssSwapUsage", PssSwapUsage); + SetMethod(esContext, esTarget, "MemSnapshot", MemSnapshot); +} + +Utils::ReloadableSourceData* Utils::ReloadableSourceData::create( + std::string sourcePath, void* preloadedData, size_t preloadedDataLength) { + auto data = new (Memory::gcMalloc(sizeof(ReloadableSourceData))) + ReloadableSourceData(); + + data->path_ = (char*)Escargot::Memory::gcMalloc(sourcePath.size() + 1); + std::copy(sourcePath.begin(), sourcePath.end(), data->path_); + data->path_[sourcePath.size()] = '\0'; + + data->preloadedData = preloadedData; + data->preloadedDataLength_ = preloadedDataLength; + + return data; +} + +MaybeLocal Utils::NewReloadableStringFromOneByte( + Isolate* isolate, + ReloadableSourceData* data, + LoadCallback loadCallback, + UnloadCallback unloadCallback) { + MaybeLocal result; + + if (data->preloadedDataLength() == 0) { + result = String::Empty(isolate); + } else if (data->preloadedDataLength() > v8::String::kMaxLength) { + result = MaybeLocal(); + } else { + Escargot::StringRef* reloadableString = + Escargot::StringRef::createReloadableString( + IsolateWrap::fromV8(isolate)->vmInstance(), + true, + data->preloadedDataLength(), + data, // data should be gc-managed. + loadCallback, + unloadCallback); + result = v8::Utils::NewLocal(isolate, reloadableString); + } + + return result; +} + +} // namespace LWNode diff --git a/lwnode/code/escargotshim/src/unimplemented.h b/lwnode/code/escargotshim/src/unimplemented.h index b507311..9737dc4 100644 --- a/lwnode/code/escargotshim/src/unimplemented.h +++ b/lwnode/code/escargotshim/src/unimplemented.h @@ -16,7 +16,7 @@ #pragma once -#include "api/utils/logger.h" +#include "api/utils/misc.h" #define LWNODE_RETURN_VOID \ LWNODE_UNIMPLEMENT; \ diff --git a/node.gyp b/node.gyp index 4808717..0de1fb4 100644 --- a/node.gyp +++ b/node.gyp @@ -1206,9 +1206,20 @@ }], ], }, # fuzz_env + { 'target_name': 'cctest', 'type': 'executable', + 'conditions': [ + ['lwnode=="true"', { + 'includes': [ 'lwnode/test/node/cctest.gypi' ], + }], + ] + }, # cctest + + { + 'target_name': 'cctest8', + 'type': 'executable', 'dependencies': [ '<(node_lib_target_name)', diff --git a/packaging/lwnode.spec b/packaging/lwnode.spec index de9a46a..9f29476 100644 --- a/packaging/lwnode.spec +++ b/packaging/lwnode.spec @@ -55,10 +55,8 @@ Requires: %{name} = %{version} Development files for Lightweight node.js. # Initialize the variables -%{!?target: %define target lwnode} -%{!?target_lib: %define target_lib liblwnode} %{!?node_engine: %define node_engine escargot} -%{!?build_profile: %define build_profile none} +%{!?lib_type: %define lib_type shared} %description @@ -102,15 +100,30 @@ CXXFLAGS+="-fsanitize=address -fsanitize-recover=address -U_FORTIFY_SOURCE -fno- LDFLAGS+="-fsanitize=address" %endif +%if "%{node_engine}" == "escargot" +%define target lwnode +%define target_lib liblwnode +%define target_src out/tizen/Release +%define extra_config --without-bundled-v8 --engine escargot --escargot-threading +%else +%define target node +%define target_src out/v8/Release +%endif + +%if "%{lib_type}" == "shared" +%define lib_type_config --shared +%endif + echo "Building:" %{target} -./configure --without-npm --without-bundled-v8 \ +./configure --tizen --without-npm \ --without-inspector --without-node-code-cache --without-node-snapshot \ --with-intl none --shared-openssl --shared-zlib --dest-os linux --dest-cpu '%{tizen_arch}' \ - --engine escargot --ninja --shared - -ninja -C out/Release %{target_lib} -ninja -C out/Release %{target} + --ninja %{?extra_config} %{?lib_type_config} +%if "%{node_engine}" == "escargot" && "%{lib_type}" == "shared" +ninja -C %{target_src} %{target_lib} +%endif +ninja -C %{target_src} %{target} ############################################## @@ -122,15 +135,19 @@ rm -rf %{buildroot} mkdir -p %{buildroot}%{_bindir} mkdir -p %{buildroot}%{_libdir} -rm -f ./out/Release/lib/*.tmp ./out/Release/lib/*.TOC -cp ./out/Release/lib/liblwnode.so* %{buildroot}%{_libdir} -cp ./out/Release/gen/escargot/libescargot.so %{buildroot}%{_libdir} +rm -f %{target_src}/lib/*.tmp %{target_src}/lib/*.TOC +%if "%{node_engine}" == "escargot" && "%{lib_type}" == "shared" +cp %{target_src}/lib/liblwnode.so* %{buildroot}%{_libdir} +cp %{target_src}/gen/escargot/libescargot.so %{buildroot}%{_libdir} +%endif # for devel files -cp ./out/Release/%{target} %{buildroot}%{_bindir} +strip -v -g %{target_src}/%{target} +cp %{target_src}/%{target} %{buildroot}%{_bindir} %clean rm ./*.list +rm ./*.manifest %post /sbin/ldconfig @@ -146,8 +163,10 @@ rm ./*.list %files %manifest packaging/%{name}.manifest %defattr(-,root,root,-) +%if "%{node_engine}" == "escargot" && "%{lib_type}" == "shared" %{_libdir}/libescargot.so %{_libdir}/liblwnode.so* +%endif %license LICENSE.Apache-2.0 LICENSE.BOEHM-GC LICENSE.BSD-3-Clause LICENSE.MIT LICENSE.NodeJS %files devel diff --git a/src/node.h b/src/node.h index 38e0ef5..4f72c77 100644 --- a/src/node.h +++ b/src/node.h @@ -64,6 +64,12 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif + +#ifdef LWNODE +#include "lwnode.h" +#include "trace.h" +#endif + #include "v8.h" // NOLINT(build/include_order) #if (__GNUC__ >= 8) && !defined(__clang__) #pragma GCC diagnostic pop diff --git a/src/node_platform.cc b/src/node_platform.cc index 797ba3d..9f97bf1 100644 --- a/src/node_platform.cc +++ b/src/node_platform.cc @@ -430,7 +430,9 @@ void NodePlatform::AddIsolateFinishedCallback(Isolate* isolate, void NodePlatform::Shutdown() { if (has_shut_down_) return; has_shut_down_ = true; - worker_thread_task_runner_->Shutdown(); + if (worker_thread_task_runner_) { // @lwnode + worker_thread_task_runner_->Shutdown(); + } { Mutex::ScopedLock lock(per_isolate_mutex_); @@ -477,6 +479,7 @@ void PerIsolatePlatformData::RunForegroundTask(uv_timer_t* handle) { void NodePlatform::DrainTasks(Isolate* isolate) { std::shared_ptr per_isolate = ForNodeIsolate(isolate); if (!per_isolate) return; + if (!worker_thread_task_runner_) return; // @lwnode do { // Worker tasks aren't associated with an Isolate. diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc index 8c8a209..de6561c 100644 --- a/src/node_process_methods.cc +++ b/src/node_process_methods.cc @@ -463,6 +463,9 @@ static void InitializeProcessMethods(Local target, env->SetMethod(target, "reallyExit", ReallyExit); env->SetMethodNoSideEffect(target, "uptime", Uptime); env->SetMethod(target, "patchProcessObject", PatchProcessObject); +#ifdef LWNODE + LWNode::InitializeProcessMethods(target, context); +#endif } } // namespace node diff --git a/src/node_worker.cc b/src/node_worker.cc index 2e018c4..8584b45 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -24,11 +24,14 @@ using v8::FunctionTemplate; using v8::HandleScope; using v8::Integer; using v8::Isolate; +using v8::Just; using v8::Local; using v8::Locker; +using v8::Maybe; using v8::MaybeLocal; using v8::Null; using v8::Number; +using v8::Nothing; using v8::Object; using v8::ResourceConstraints; using v8::SealHandleScope; @@ -364,6 +367,7 @@ void Worker::Run() { } { + /* int exit_code; bool stopped = is_stopped(); if (!stopped) @@ -371,9 +375,22 @@ void Worker::Run() { Mutex::ScopedLock lock(mutex_); if (exit_code_ == 0 && !stopped) exit_code_ = exit_code; + */ + // @lwnode remove warning: ‘exit_code’ may be used uninitialized + Maybe exit_code = Nothing(); + bool stopped = is_stopped(); + if (!stopped) { + exit_code = Just(EmitExit(env_.get())); + } + Mutex::ScopedLock lock(mutex_); + if (exit_code_ == 0 && !stopped && exit_code.IsJust()) { + exit_code_ = exit_code.FromJust(); + } - Debug(this, "Exiting thread for worker %llu with exit code %d", - thread_id_.id, exit_code_); + Debug(this, + "Exiting thread for worker %llu with exit code %d", + thread_id_.id, + exit_code_); } } diff --git a/tools/gyp_node.py b/tools/gyp_node.py index 332a729..9b0ced3 100755 --- a/tools/gyp_node.py +++ b/tools/gyp_node.py @@ -35,8 +35,17 @@ def run_gyp(args): args.append('--depth=' + node_root) # @lwnode - if '-Dnode_core_target_name=lwnode' not in args: - global output_dir + global output_dir + if '-Dnode_core_target_name=lwnode' in args: + if '-Dtarget_os=tizen' in args: + output_dir = os.path.join(output_dir, 'tizen') + args.extend(['--generator-output', output_dir]) + args.extend(['-Goutput_dir=' + output_dir]) + else: + output_dir = os.path.join(output_dir, 'linux') + args.extend(['--generator-output', output_dir]) + args.extend(['-Goutput_dir=' + output_dir]) + else: output_dir = os.path.join(output_dir, 'v8') args.extend(['--generator-output', output_dir]) args.extend(['-Goutput_dir=' + output_dir]) diff --git a/tools/test.py b/tools/test.py index 4d97a5b..c55b0a9 100755 --- a/tools/test.py +++ b/tools/test.py @@ -908,7 +908,7 @@ class Context(object): if self.vm is not None: return self.vm if arch == 'none': - name = 'out/Debug/lwnode' if mode == 'debug' else 'out/Release/lwnode' + name = 'out/linux/Debug/lwnode' if mode == 'debug' else 'out/linux/Release/lwnode' else: name = 'out/%s.%s/lwnode' % (arch, mode) -- 2.34.1