From: Ryan Hyun Choi Date: Mon, 26 Jul 2021 04:07:18 +0000 (+0900) Subject: LWNode_Release_210726_a33b69e X-Git-Tag: accepted/tizen/unified/20210726.135432^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5cfc323b14e70905c7b735ea6012dd566758133a;p=platform%2Fframework%2Fweb%2Flwnode.git LWNode_Release_210726_a33b69e Change-Id: I11fe7a29e3b5ec37e6aadf9faa4126f773f46292 Signed-off-by: Ryan Choi --- diff --git a/common.gypi b/common.gypi index 4745bb5..2ef53fd 100644 --- a/common.gypi +++ b/common.gypi @@ -173,7 +173,7 @@ }], ], }, - 'cflags': [ '-O3' ], + 'cflags': [ '-Os' ], 'conditions': [ ['OS=="linux"', { 'conditions': [ diff --git a/configure.py b/configure.py index 61ddbf1..4e3e8d5 100755 --- a/configure.py +++ b/configure.py @@ -1974,7 +1974,10 @@ if options.compile_commands_json: # pass the leftover positional arguments to GYP gyp_args += args # @lwnode -gyp_args += get_lwnode_gyp_options() +if options.without_bundled_v8: + gyp_args += get_lwnode_gyp_options() +else: + gyp_args += ['-Dlwnode='+ 'false'] # @end of lwnode if warn.warned and not options.verbose: diff --git a/lwnode/code/escargotshim/common.gypi b/lwnode/code/escargotshim/common.gypi index 6b78b9f..b83ea33 100755 --- a/lwnode/code/escargotshim/common.gypi +++ b/lwnode/code/escargotshim/common.gypi @@ -7,10 +7,10 @@ 'build_asan%': '0', }, 'target_defaults': { - 'defines': [], + 'defines': [ 'LWNODE=1' ], 'cflags!': [ '-Wno-error' ], 'cflags': [ - '-Wall', '-Wextra', '-Werror', + '-Wall', '-Wextra', '-Werror', '-ggdb', '-Wno-unused-variable', '-Wno-unused-function', '-Wno-unused-but-set-variable', @@ -20,11 +20,11 @@ }, 'configurations': { 'Debug': { - 'cflags': [ '-g', '-O0', '-Werror' ], + 'cflags': [ '-O0' ], }, 'Release': { 'defines': ['NDEBUG'], - 'cflags': [ '-Wfatal-errors' ], + 'cflags': [ '-Wfatal-errors', '-Os' ], }, }, 'conditions': [ @@ -39,7 +39,7 @@ '-Wl,-z,relro,-z,now', ], 'cflags': [ - '-g', '-O0', + '-ggdb', '-Os', '-fPIC', '-fPIE', '-fstack-protector-strong', '-D_FORTIFY_SOURCE=2', diff --git a/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.cpp b/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.cpp index 01e6a9d..47e31dd 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.cpp @@ -926,6 +926,11 @@ Evaluator::EvaluatorResult Evaluator::executeFunction(ContextRef* ctx, ValueRef* return toEvaluatorResultRef(result); } +COMPILE_ASSERT((int)VMInstanceRef::PromiseHookType::Init == (int)VMInstance::PromiseHookType::Init, ""); +COMPILE_ASSERT((int)VMInstanceRef::PromiseHookType::Resolve == (int)VMInstance::PromiseHookType::Resolve, ""); +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) { return PersistentRefHolder(toRef(new VMInstance(new PlatformBridge(platform), locale, timezone, baseCacheDir))); @@ -2944,7 +2949,11 @@ Uint8ClampedArrayObjectRef* Uint8ClampedArrayObjectRef::create(ExecutionStateRef PromiseObjectRef* PromiseObjectRef::create(ExecutionStateRef* state) { - return toRef(new PromiseObject(*toImpl(state))); + auto promise = new PromiseObject(*toImpl(state)); + if (UNLIKELY(toImpl(state)->context()->vmInstance()->isPromiseHookRegistered())) { + toImpl(state)->context()->vmInstance()->triggerPromiseHook(*toImpl(state), VMInstance::PromiseHookType::Init, promise); + } + return toRef(promise); } COMPILE_ASSERT((int)PromiseObjectRef::PromiseState::Pending == (int)PromiseObject::PromiseState::Pending, ""); @@ -2978,11 +2987,17 @@ ObjectRef* PromiseObjectRef::then(ExecutionStateRef* state, ValueRef* onFulfille void PromiseObjectRef::fulfill(ExecutionStateRef* state, ValueRef* value) { + if (UNLIKELY(toImpl(state)->context()->vmInstance()->isPromiseHookRegistered())) { + toImpl(state)->context()->vmInstance()->triggerPromiseHook(*toImpl(state), VMInstance::PromiseHookType::Resolve, toImpl(this)); + } toImpl(this)->fulfill(*toImpl(state), toImpl(value)); } void PromiseObjectRef::reject(ExecutionStateRef* state, ValueRef* reason) { + if (UNLIKELY(toImpl(state)->context()->vmInstance()->isPromiseHookRegistered())) { + toImpl(state)->context()->vmInstance()->triggerPromiseHook(*toImpl(state), VMInstance::PromiseHookType::Resolve, toImpl(this)); + } toImpl(this)->reject(*toImpl(state), toImpl(reason)); } diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/PromiseObject.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/PromiseObject.cpp index dca3a69..273366c 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/PromiseObject.cpp +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/PromiseObject.cpp @@ -279,7 +279,7 @@ static Value promiseResolveFunctions(ExecutionState& state, Value thisValue, siz PromiseObject* promise = promiseValue.asObject()->asPromiseObject(); if (UNLIKELY(state.context()->vmInstance()->isPromiseHookRegistered())) { - state.context()->vmInstance()->triggerPromiseHook(state, VMInstance::PromiseHookType::Resolve, promise, Value()); + state.context()->vmInstance()->triggerPromiseHook(state, VMInstance::PromiseHookType::Resolve, promise); } // Let alreadyResolved be F.[[AlreadyResolved]]. @@ -336,7 +336,7 @@ static Value promiseRejectFunctions(ExecutionState& state, Value thisValue, size PromiseObject* promise = promiseValue.asObject()->asPromiseObject(); if (UNLIKELY(state.context()->vmInstance()->isPromiseHookRegistered())) { - state.context()->vmInstance()->triggerPromiseHook(state, VMInstance::PromiseHookType::Resolve, promise, Value()); + state.context()->vmInstance()->triggerPromiseHook(state, VMInstance::PromiseHookType::Resolve, promise); } // Let alreadyResolved be F.[[AlreadyResolved]]. diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.h index b1a9e69..cfd6d6b 100644 --- a/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.h +++ b/lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.h @@ -305,7 +305,7 @@ public: m_promiseHookPublic = nullptr; } - void triggerPromiseHook(ExecutionState& state, PromiseHookType type, PromiseObject* promise, const Value& parent) + void triggerPromiseHook(ExecutionState& state, PromiseHookType type, PromiseObject* promise, const Value& parent = Value()) { ASSERT(!!m_promiseHook); if (m_promiseHookPublic) { diff --git a/lwnode/code/escargotshim/include/v8-profiler.h b/lwnode/code/escargotshim/include/v8-profiler.h index c3b25e8..5a52315 100644 --- a/lwnode/code/escargotshim/include/v8-profiler.h +++ b/lwnode/code/escargotshim/include/v8-profiler.h @@ -1050,7 +1050,7 @@ class V8_EXPORT CodeEventHandler { CodeEventHandler(); CodeEventHandler(const CodeEventHandler&); CodeEventHandler& operator=(const CodeEventHandler&); - void* internal_listener_; + void* internal_listener_ = nullptr; }; } // namespace v8 diff --git a/lwnode/code/escargotshim/include/v8.h b/lwnode/code/escargotshim/include/v8.h index e10ba15..c137dab 100644 --- a/lwnode/code/escargotshim/include/v8.h +++ b/lwnode/code/escargotshim/include/v8.h @@ -1211,9 +1211,9 @@ class V8_EXPORT HandleScope { void operator delete(void*, size_t); void operator delete[](void*, size_t); - internal::Isolate* isolate_; - internal::Address* prev_next_; - internal::Address* prev_limit_; + internal::Isolate* isolate_ = nullptr; + internal::Address* prev_next_ = nullptr; + internal::Address* prev_limit_ = nullptr; // Local::New uses CreateHandle with an Isolate* parameter. template friend class Local; @@ -1262,7 +1262,7 @@ class V8_EXPORT EscapableHandleScope : public HandleScope { void operator delete[](void*, size_t); internal::Address* Escape(internal::Address* escape_value); - internal::Address* escape_slot_; + internal::Address* escape_slot_ = nullptr; }; /** @@ -1286,9 +1286,9 @@ class V8_EXPORT SealHandleScope { void operator delete(void*, size_t); void operator delete[](void*, size_t); - internal::Isolate* const isolate_; - internal::Address* prev_limit_; - int prev_sealed_level_; + internal::Isolate* const isolate_ = nullptr; + internal::Address* prev_limit_ = nullptr; + int prev_sealed_level_ = 0; }; @@ -2384,7 +2384,7 @@ class V8_EXPORT ValueSerializer { private: struct PrivateData; - PrivateData* private_; + PrivateData* private_ = nullptr; }; /** @@ -2481,7 +2481,7 @@ class V8_EXPORT ValueDeserializer { private: struct PrivateData; - PrivateData* private_; + PrivateData* private_ = nullptr; }; @@ -7038,7 +7038,7 @@ class V8_EXPORT Extension { // NOLINT private: const char* name_; size_t source_length_; // expected to initialize before source_ - String::ExternalOneByteStringResource* source_; + String::ExternalOneByteStringResource* source_ = nullptr; int dep_count_; const char** deps_; bool auto_enable_; @@ -7699,8 +7699,8 @@ class V8_EXPORT HeapStatistics { bool does_zap_garbage_; size_t number_of_native_contexts_; size_t number_of_detached_contexts_; - size_t total_global_handles_size_; - size_t used_global_handles_size_; + size_t total_global_handles_size_ = 0; + size_t used_global_handles_size_ = 0; friend class V8; friend class Isolate; @@ -8347,7 +8347,7 @@ class V8_EXPORT Isolate { private: OnFailure on_failure_; - void* internal_; + void* internal_ = nullptr; }; @@ -8366,9 +8366,9 @@ class V8_EXPORT Isolate { const AllowJavascriptExecutionScope&) = delete; private: - void* internal_throws_; - void* internal_assert_; - void* internal_dump_; + void* internal_throws_ = nullptr; + void* internal_assert_ = nullptr; + void* internal_dump_ = nullptr; }; /** @@ -8388,9 +8388,9 @@ class V8_EXPORT Isolate { const SuppressMicrotaskExecutionScope&) = delete; private: - internal::Isolate* const isolate_; - internal::MicrotaskQueue* const microtask_queue_; - internal::Address previous_stack_height_; + internal::Isolate* const isolate_ = nullptr; + internal::MicrotaskQueue* const microtask_queue_ = nullptr; + internal::Address previous_stack_height_ = 0; friend class internal::ThreadLocalTop; }; @@ -8409,7 +8409,7 @@ class V8_EXPORT Isolate { SafeForTerminationScope& operator=(const SafeForTerminationScope&) = delete; private: - internal::Isolate* isolate_; + internal::Isolate* isolate_ = nullptr; bool prev_value_; }; @@ -9986,7 +9986,7 @@ class V8_EXPORT SnapshotCreator { size_t AddData(Local context, internal::Address object); size_t AddData(internal::Address object); - void* data_; + void* data_ = nullptr; }; /** @@ -10260,7 +10260,7 @@ class V8_EXPORT TryCatch { TryCatch* next_; void* exception_; void* message_obj_; - void* js_stack_comparable_address_; + void* js_stack_comparable_address_ = nullptr; bool is_verbose_ : 1; bool can_continue_ : 1; bool capture_message_ : 1; diff --git a/lwnode/code/escargotshim/src/api-data.cc b/lwnode/code/escargotshim/src/api-data.cc index 3632f8a..2fab46c 100644 --- a/lwnode/code/escargotshim/src/api-data.cc +++ b/lwnode/code/escargotshim/src/api-data.cc @@ -1686,6 +1686,11 @@ MaybeLocal Function::NewInstanceWithSideEffectType( LWNODE_RETURN_LOCAL(Object); } +static inline std::string toStdStringWithoutException(ContextRef* context, + ValueRef* esValue) { + return esValue->toStringWithoutException(context)->toStdUTF8String(); +} + MaybeLocal Function::Call(Local context, v8::Local recv, int argc, @@ -1693,7 +1698,7 @@ MaybeLocal Function::Call(Local context, API_ENTER_WITH_CONTEXT(context, MaybeLocal()); LWNODE_CHECK(CVAL(this)->value()->isCallable()); - auto lwContext = VAL(*context)->context(); + auto esContext = VAL(*context)->context()->get(); GCVector arguments; for (int i = 0; i < argc; i++) { @@ -1701,7 +1706,7 @@ MaybeLocal Function::Call(Local context, } auto r = Evaluator::execute( - lwContext->get(), + esContext, [](ExecutionStateRef* state, ValueRef* self, ValueRef* receiver, @@ -1714,7 +1719,35 @@ MaybeLocal Function::Call(Local context, arguments.size(), arguments.data()); - API_HANDLE_EXCEPTION(r, lwIsolate, MaybeLocal()); + if (!r.isSuccessful()) { + LWNODE_DLOG_ERROR("Evaluate"); + LWNODE_DLOG_RAW("Internal:\n this: %p (es: %p)\n recv: %p (es: %p)", + this, + CVAL(this)->value(), + *recv, + CVAL(*recv)->value()); + + LWNODE_DLOG_RAW(" arguments (%d):", argc); + for (int i = 0; i < argc; i++) { + auto esValue = VAL(*argv[i])->value(); + LWNODE_DLOG_RAW(" [%d] %p (es: %p) %s", + i, + *argv[i], + esValue, + toStdStringWithoutException(esContext, esValue).c_str()); + } + + LWNODE_DLOG_RAW("Execute:\n %s (%s:%d)\nResource:\n %s\n%s", + TRACE_ARGS2, + "N/A", + EvalResultHelper::getErrorString( + lwIsolate->GetCurrentContext()->get(), r) + .c_str()); + + lwIsolate->SetPendingExceptionAndMessage(r.error.get(), r.stackTraceData); + lwIsolate->ReportPendingMessages(); + return MaybeLocal(); + } return Utils::NewLocal(lwIsolate->toV8(), r.result); } diff --git a/lwnode/code/escargotshim/src/api-environment.cc b/lwnode/code/escargotshim/src/api-environment.cc index 5fb71d4..5754db2 100644 --- a/lwnode/code/escargotshim/src/api-environment.cc +++ b/lwnode/code/escargotshim/src/api-environment.cc @@ -320,6 +320,7 @@ Local v8::External::New(Isolate* isolate, void* value) { void* External::Value() const { auto esObject = CVAL(this)->value()->asObject(); + LWNODE_CHECK(ObjectRefHelper::getExtraData(esObject)); auto externalObjectData = ObjectRefHelper::getExtraData(esObject)->asExternalObjectData(); @@ -1141,12 +1142,6 @@ MaybeLocal Promise::Resolver::New(Local context) { [](ExecutionStateRef* state, EscargotShim::IsolateWrap* lwIsolate) -> ValueRef* { auto promise = PromiseObjectRef::create(state); - - // NOTE: Update RunPromiseHook to be called from Escargot after Escargot - // supports this feature - lwIsolate->RunPromiseHook( - PromiseHookType::kInit, promise, ValueRef::createUndefined()); - return promise; }, lwIsolate); @@ -1176,10 +1171,6 @@ Maybe Promise::Resolver::Resolve(Local context, PromiseObjectRef* promise, ValueRef* esValue, EscargotShim::IsolateWrap* lwIsolate) -> ValueRef* { - // NOTE: Update RunPromiseHook to be called from Escargot after Escargot - // supports this feature - lwIsolate->RunPromiseHook(PromiseHookType::kResolve, promise, esValue); - promise->fulfill(state, esValue); return ValueRef::createUndefined(); }, @@ -1207,10 +1198,6 @@ Maybe Promise::Resolver::Reject(Local context, PromiseObjectRef* promise, ValueRef* esValue, EscargotShim::IsolateWrap* lwIsolate) -> ValueRef* { - // NOTE: Update RunPromiseHook to be called from Escargot after Escargot - // supports this feature - lwIsolate->RunPromiseHook(PromiseHookType::kResolve, promise, esValue); - promise->reject(state, esValue); return ValueRef::createUndefined(); }, @@ -1772,7 +1759,12 @@ Local v8::Symbol::For(Isolate* isolate, Local name) { } Local v8::Symbol::ForApi(Isolate* isolate, Local name) { - LWNODE_RETURN_LOCAL(Symbol); + API_ENTER_NO_EXCEPTION(isolate); + + SymbolRef* esSymbol = + lwIsolate->getApiSymbol(VAL(*name)->value()->asString()); + + return Utils::NewLocal(isolate, esSymbol); } #define WELL_KNOWN_SYMBOLS(V) \ @@ -1814,7 +1806,7 @@ Local v8::Private::New(Isolate* isolate, Local name) { // @todo For now, we ignore the private attribute and use a normal Symbol // instead. - SymbolRef* esSymbol = lwIsolate->getPrivateSymbol(esName); + SymbolRef* esSymbol = lwIsolate->createApiPrivateSymbol(esName); return Utils::NewLocal(isolate, esSymbol); } @@ -1823,7 +1815,7 @@ Local v8::Private::ForApi(Isolate* isolate, Local name) { API_ENTER_NO_EXCEPTION(isolate); SymbolRef* esSymbol = - lwIsolate->getPrivateSymbol(VAL(*name)->value()->asString()); + lwIsolate->getApiPrivateSymbol(VAL(*name)->value()->asString()); return Utils::NewLocal(isolate, esSymbol); } @@ -1896,10 +1888,6 @@ bool Isolate::InContext() { } void Isolate::ClearKeptObjects() { -#if !defined(GC_HEAP_TRACE_ONLY) - MemoryUtil::gc(); - MemoryUtil::gcInvokeFinalizers(); -#endif LWNODE_RETURN_VOID; } @@ -1997,7 +1985,7 @@ void Isolate::RequestInterrupt(InterruptCallback callback, void* data) { } void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) { - LWNODE_RETURN_VOID; + IsolateWrap::GetCurrent()->CollectGarbage(); } Isolate* Isolate::GetCurrent() { @@ -2017,6 +2005,7 @@ void Isolate::Initialize(Isolate* isolate, } Isolate* Isolate::New(const Isolate::CreateParams& params) { + LWNODE_CALL_TRACE(); Isolate* isolate = Allocate(); Initialize(isolate, params); return isolate; @@ -2035,10 +2024,12 @@ void Isolate::DiscardThreadSpecificMetadata() { } void Isolate::Enter() { + LWNODE_CALL_TRACE(); IsolateWrap::fromV8(this)->Enter(); } void Isolate::Exit() { + LWNODE_CALL_TRACE(); IsolateWrap::fromV8(this)->Exit(); } @@ -2490,9 +2481,7 @@ void MicrotasksScope::PerformCheckpoint(Isolate* v8_isolate) { auto lwIsolate = IsolateWrap::fromV8(v8_isolate); auto vmInstance = lwIsolate->vmInstance(); - if (vmInstance->hasPendingJob() == false) { - return; - } + GCHeap::ProcessingHoldScope scope; while (vmInstance->hasPendingJob()) { auto r = vmInstance->executePendingJob(); diff --git a/lwnode/code/escargotshim/src/api-handles.cc b/lwnode/code/escargotshim/src/api-handles.cc index 19a1260..1d42960 100644 --- a/lwnode/code/escargotshim/src/api-handles.cc +++ b/lwnode/code/escargotshim/src/api-handles.cc @@ -38,7 +38,7 @@ void HandleScope::Initialize(Isolate* isolate) { HandleScope::~HandleScope() { LWNODE_CALL_TRACE_UNINDENT(); - LWNODE_CALL_TRACE(); + LWNODE_CALL_TRACE("%p", this); IsolateWrap::fromV8(isolate_)->popHandleScope(this); } @@ -79,7 +79,23 @@ i::Address* HandleScope::CreateHandle(i::Isolate* isolate, i::Address value) { LWNODE_CHECK(handle->isValid()); - lwIsolate->addHandleToCurrentScope(handle); + switch (handle->location()) { + case HandleWrap::Location::Local: + lwIsolate->addHandleToCurrentScope(handle); + return reinterpret_cast(handle); + + case HandleWrap::Location::Strong: + case HandleWrap::Location::Weak: { + auto cloned = handle->clone(HandleWrap::Location::Local); + lwIsolate->addHandleToCurrentScope(cloned); + return reinterpret_cast(cloned); + } + + default: + break; + } + + LWNODE_CHECK_NOT_REACH_HERE(); return reinterpret_cast(value); } @@ -146,10 +162,12 @@ void SealHandleScope::operator delete[](void*, size_t) { } void Context::Enter() { + LWNODE_CALL_TRACE("%s", VAL(this)->getHandleInfoString().c_str()); VAL(this)->context()->Enter(); } void Context::Exit() { + LWNODE_CALL_TRACE(); VAL(this)->context()->Exit(); } diff --git a/lwnode/code/escargotshim/src/api-template.cc b/lwnode/code/escargotshim/src/api-template.cc index 416c3ae..8f6801b 100644 --- a/lwnode/code/escargotshim/src/api-template.cc +++ b/lwnode/code/escargotshim/src/api-template.cc @@ -117,6 +117,8 @@ static ValueRef* FunctionTemplateNativeFunction( if (!fnData->checkSignature(state, thisValue)) { IsolateWrap::GetCurrent()->ScheduleThrow(TypeErrorObjectRef::create( state, StringRef::createFromASCII("Illegal invocation"))); + LWNODE_DLOG_ERROR("Signature mismatch!"); + return ValueRef::createUndefined(); } Local result; diff --git a/lwnode/code/escargotshim/src/api.cc b/lwnode/code/escargotshim/src/api.cc index a98a54c..f554f69 100644 --- a/lwnode/code/escargotshim/src/api.cc +++ b/lwnode/code/escargotshim/src/api.cc @@ -281,8 +281,13 @@ void ResourceConstraints::set_max_semi_space_size_in_kb(size_t limit_in_kb) { i::Address* V8::GlobalizeReference(i::Isolate* isolate, i::Address* obj) { LWNODE_CALL_TRACE(); LWNODE_CHECK(isolate); +#if defined(GC_HEAP_TRACE_ONLY) + auto persistent = PersistentWrap::GlobalizeReference( + reinterpret_cast(isolate), obj); + return reinterpret_cast(persistent); +#endif + IsolateWrap::fromV8(isolate)->globalHandles()->Create(VAL(obj)); - Engine::current()->gcHeap()->GlobalizeReference(obj, isolate); return obj; } @@ -317,28 +322,38 @@ void V8::MakeWeak(i::Address* location, WeakCallbackType type) { LWNODE_CALL_TRACE(); - Engine::current()->gcHeap()->MakeWeak( - location, parameter, weak_callback, type); +#if defined(GC_HEAP_TRACE_ONLY) + PersistentWrap::MakeWeak(location, parameter, weak_callback); + return; +#endif #if defined(LWNODE_ENABLE_EXPERIMENTAL) if (type != WeakCallbackType::kParameter) { LWNODE_RETURN_VOID; // TODO } - GlobalHandles::MakeWeak(VAL(location), parameter, weak_callback); -#else - LWNODE_RETURN_VOID; #endif } void V8::MakeWeak(i::Address** location_addr) { +#if defined(LWNODE_ENABLE_EXPERIMENTAL) + GlobalHandles::MakeWeak( + VAL(*location_addr), reinterpret_cast(location_addr), nullptr); +#endif LWNODE_RETURN_VOID; } void* V8::ClearWeak(i::Address* location) { LWNODE_CALL_TRACE(); - Engine::current()->gcHeap()->ClearWeak(location); +#if defined(GC_HEAP_TRACE_ONLY) + return PersistentWrap::ClearWeak(location); +#endif + +#if defined(LWNODE_ENABLE_EXPERIMENTAL) + return GlobalHandles::ClearWeakness(VAL(location)); +#else LWNODE_RETURN_NULLPTR; +#endif } void V8::AnnotateStrongRetainer(i::Address* location, const char* label) { @@ -347,8 +362,12 @@ void V8::AnnotateStrongRetainer(i::Address* location, const char* label) { void V8::DisposeGlobal(i::Address* location) { LWNODE_CALL_TRACE(); +#if defined(GC_HEAP_TRACE_ONLY) + PersistentWrap::DisposeGlobal(location); + return; +#endif + GlobalHandles::Destroy(VAL(location)); - Engine::current()->gcHeap()->DisposeGlobal(location); } void V8::DisposeTracedGlobal(internal::Address* location) { diff --git a/lwnode/code/escargotshim/src/api/context.cc b/lwnode/code/escargotshim/src/api/context.cc index 448d76b..85db923 100644 --- a/lwnode/code/escargotshim/src/api/context.cc +++ b/lwnode/code/escargotshim/src/api/context.cc @@ -31,7 +31,8 @@ static void evalJavaScript(ContextRef* context, ScriptParserRef::InitializeScriptResult scriptResult = context->scriptParser()->initializeScript( StringRef::createExternalFromASCII(buffer, bufferSize), - StringRef::createFromASCII(name, sizeof(name))); + StringRef::createFromASCII(name, + strnlen(name, v8::String::kMaxLength))); LWNODE_CHECK_MSG(scriptResult.isSuccessful(), "Cannot parser %s: %s", name, diff --git a/lwnode/code/escargotshim/src/api/engine.cc b/lwnode/code/escargotshim/src/api/engine.cc index 558a0b0..5122b4b 100644 --- a/lwnode/code/escargotshim/src/api/engine.cc +++ b/lwnode/code/escargotshim/src/api/engine.cc @@ -17,6 +17,7 @@ #include "engine.h" #include #include +#include "handle.h" #include "utils/logger.h" #include "utils/misc.h" #include "utils/string.h" @@ -81,142 +82,106 @@ void Platform::hostImportModuleDynamically(ContextRef* relatedContext, } // --- G C H e a p --- -#if !defined(GC_HEAP_TRACE_ONLY) + #define GC_WRAP_PERSISTENT_POINTER(p) (GC_heap_pointer)(p) -#define GC_UNWRAP_POINTER(p) ((void*)p) -#else -#define GC_WRAP_PERSISTENT_POINTER(p) GC_HIDE_POINTER(p) -#define GC_UNWRAP_POINTER(p) ((void*)GC_HIDE_POINTER(p)) -#endif +#define GC_UNWRAP_PERSISTENT_POINTER(p) ((void*)p) +#define GC_WRAP_WEAK_POINTER(p) (GC_heap_pointer)(p) +#define GC_UNWRAP_WEAK_POINTER(p) ((void*)p) /* - @note gc heap tracing lifetime - - a) The types of heap tracing are strong, weak and phantom weak. - b) Every persitent is created as strong type at the registration. - Following flow is considered: - - i) strong <-> weak <-> phantom weak -> (finalizer) -> nullptr - ii) strong -> nullptr - iii) phantom weak -> strong - - If weak counter is 1, then the pointer will be phantom weak which is - collectable for GC. + state diagram: + FREE -> STRONG <-> WEAK -> (Post GC Processing) -> { STRONG, WEAK, FREE } */ -void GCHeap::GlobalizeReference(void* address, void* data) { - LWNODE_CALL_TRACE("address %p, data %p", address, data); +void GCHeap::acquire(void* address, Kind kind, void* data) { + LWNODE_CALL_TRACE_ID( + GCHEAP, + "%s kind %u data %p", + PersistentWrap::as(address)->getPersistentInfoString().c_str(), + kind, + data); + auto iter = persistents_.find(GC_WRAP_PERSISTENT_POINTER(address)); if (iter != persistents_.end()) { - iter->second.strong++; - iter->second.weak--; - iter->second.weak = std::max(iter->second.weak, 0); - // no-progress handling weak phantoms + if (kind == STRONG) iter->second.strong++; + if (kind == WEAK) iter->second.weak++; } else { - auto iter = weakPhantoms_.find(GC_HIDE_POINTER(address)); + auto iter = weakPhantoms_.find(GC_WRAP_WEAK_POINTER(address)); if (iter != weakPhantoms_.end()) { - // move phantom weak to strong AddressInfo info = iter->second; LWNODE_CHECK(info.strong == 0); - LWNODE_CHECK(info.weak == 1); - info.strong++; - info.weak--; + LWNODE_CHECK(info.weak != 0); + + if (kind == STRONG) iter->second.strong++; + if (kind == WEAK) iter->second.weak++; persistents_.emplace(GC_WRAP_PERSISTENT_POINTER(address), info); weakPhantoms_.erase(iter); - // no-progress handling weak phantoms } else { persistents_.emplace(GC_WRAP_PERSISTENT_POINTER(address), AddressInfo(1, 0, data)); } } - notifyUpdate(address); + postUpdate(address); } -void GCHeap::DisposeGlobal(void* address) { - LWNODE_CALL_TRACE("address %p", address); +void GCHeap::release(void* address, Kind kind) { + LWNODE_CALL_TRACE_ID( + GCHEAP, + "%s kind %u", + PersistentWrap::as(address)->getPersistentInfoString().c_str(), + kind); + auto iter = persistents_.find(GC_WRAP_PERSISTENT_POINTER(address)); if (iter != persistents_.end()) { - iter->second.strong--; + if (kind == STRONG) iter->second.strong--; + if (kind == WEAK) iter->second.weak--; + iter->second.strong = std::max(iter->second.strong, 0); + iter->second.weak = std::max(iter->second.weak, 0); // progress handling weak phantoms if (iter->second.strong == 0) { - if (iter->second.weak == 0) { - persistents_.erase(iter); - } else if (iter->second.weak <= 1) { - weakPhantoms_.emplace(GC_HIDE_POINTER(address), iter->second); - persistents_.erase(iter); + if (iter->second.weak > 0) { + weakPhantoms_.emplace(GC_WRAP_WEAK_POINTER(address), iter->second); } - } - } - notifyUpdate(address); -} - -void GCHeap::MakeWeak(void* address) { - LWNODE_CALL_TRACE("address %p", address); - auto iter = persistents_.find(GC_WRAP_PERSISTENT_POINTER(address)); - if (iter != persistents_.end()) { - iter->second.strong--; - iter->second.strong = std::max(iter->second.strong, 0); - iter->second.weak++; - - // progress handling weak phantoms - if (iter->second.strong == 0 && iter->second.weak <= 1) { - weakPhantoms_.emplace(GC_HIDE_POINTER(address), iter->second); persistents_.erase(iter); } - } else { - auto iter = weakPhantoms_.find(GC_HIDE_POINTER(address)); - if (iter != weakPhantoms_.end()) { - // move phantom weak to weak - AddressInfo info = iter->second; - - LWNODE_CHECK(info.strong == 0); - LWNODE_CHECK(info.weak == 1); - info.weak++; - - persistents_.emplace(GC_WRAP_PERSISTENT_POINTER(address), info); - weakPhantoms_.erase(iter); - } else { - LWNODE_CHECK(false); // assumes this doesn't happen. let's see. - } } - - notifyUpdate(address); + postUpdate(address); } -void GCHeap::ClearWeak(void* address) { - LWNODE_CALL_TRACE("address %p", address); - // 1. handle persistents_ and weakPhantoms_ - auto iter = persistents_.find(GC_WRAP_PERSISTENT_POINTER(address)); - if (iter != persistents_.end()) { - // guard: ClearWeak can be called even if no weak reference exist. - if (iter->second.weak > 0) { - iter->second.weak--; - } - - // progress handling weak phantoms - if (iter->second.strong <= 0 && iter->second.weak <= 1) { - weakPhantoms_.emplace(GC_HIDE_POINTER(address), iter->second); - persistents_.erase(iter); - } +void GCHeap::postGarbageCollectionProcessing() { + if (isOnPostGarbageCollectionProcessing_ || + ProcessingHoldScope::isSkipProcessing()) { + return; } - // 2. ensure clearing finalizer bound to this address - MemoryUtil::gcRegisterFinalizer(address, nullptr, nullptr); + LWNODE_CALL_TRACE_ID( + GCHEAP, "last: %zu, current: %zu", stat_.weak, weakPhantoms_.size()); + if (stat_.weak == weakPhantoms_.size()) { + return; + } + isOnPostGarbageCollectionProcessing_ = true; - notifyUpdate(address); -} + // 1. move weaks to process post task. + GCVector weaks; + weaks.reserve(weakPhantoms_.size()); + for (const HeapSegment& it : weakPhantoms_) { + weaks.push_back(it); + } + weakPhantoms_.clear(); -void GCHeap::disposePhantomWeak(void* address) { - LWNODE_CALL_TRACE("address %p", address); - auto iter = weakPhantoms_.find(GC_HIDE_POINTER(address)); - if (iter != weakPhantoms_.end()) { - weakPhantoms_.erase(iter); + // 2. invoke finalizers + for (const auto& iter : weaks) { + PersistentWrap* persistent = + PersistentWrap::as(GC_UNWRAP_PERSISTENT_POINTER(iter.first)); + persistent->invokeFinalizer(); } - notifyUpdate(address); + + stat_.weak = weakPhantoms_.size(); + isOnPostGarbageCollectionProcessing_ = false; } bool GCHeap::isTraced(void* address) { @@ -225,28 +190,29 @@ bool GCHeap::isTraced(void* address) { return true; } - if (weakPhantoms_.find(GC_HIDE_POINTER(address)) != weakPhantoms_.end()) { + if (weakPhantoms_.find(GC_WRAP_WEAK_POINTER(address)) != + weakPhantoms_.end()) { return true; } + return false; } -void* GCHeap::getPersistentData(void* address) { - auto iter = persistents_.find(GC_WRAP_PERSISTENT_POINTER(address)); - if (iter != persistents_.end()) { - return iter->second.data; - } - - auto iterWeak = weakPhantoms_.find(GC_HIDE_POINTER(address)); - if (iterWeak != weakPhantoms_.end()) { - return iterWeak->second.data; +void GCHeap::disposePhantomWeak(void* address) { + LWNODE_CALL_TRACE_ID( + GCHEAP, + "%s", + PersistentWrap::as(address)->getPersistentInfoString().c_str()); + stat_.freed++; + auto iter = weakPhantoms_.find(GC_WRAP_WEAK_POINTER(address)); + if (iter != weakPhantoms_.end()) { + weakPhantoms_.erase(iter); } - return nullptr; + postUpdate(address); } -typedef void (*formatterFunction)( - std::stringstream& stream, - const std::pair& iter); +typedef void (*formatterFunction)(std::stringstream& stream, + const GCHeap::HeapSegment& iter); static void printAddress( const GCUnorderedMap& map, @@ -270,94 +236,74 @@ static void printAddress( } } -void GCHeap::printStatus() { - if (isStatusPrinted) { +void GCHeap::printStatus(bool forcePrint) { + if (Flags::isTraceCallEnabled("GCHEAP") == false) { return; } - isStatusPrinted = true; - if (persistents_.size() == 0 && weakPhantoms_.size() == 0) { + if (!forcePrint && isStatePrinted_) { + return; + } + + isStatePrinted_ = true; + + if (!forcePrint || (persistents_.size() == 0 && weakPhantoms_.size() == 0)) { return; } - LWNODE_LOG_INFO(COLOR_GREEN "----- GCHEAP -----" COLOR_RESET); - LWNODE_LOG_INFO("[HOLD]"); - printAddress( - persistents_, - [](std::stringstream& stream, - const std::pair& iter) { - stream << std::setw(15) << std::right << GC_UNWRAP_POINTER(iter.first) - << " (" - << "S" << std::setw(3) << iter.second.strong << " W" - << std::setw(3) << iter.second.weak << ") "; - }); - - LWNODE_LOG_INFO(COLOR_GREEN "------------------" COLOR_RESET); - LWNODE_LOG_INFO("[PHANTOM]"); - printAddress( - weakPhantoms_, - [](std::stringstream& stream, - const std::pair& iter) { - stream << std::setw(15) << std::right << GC_REVEAL_POINTER(iter.first) - << " (" - << "S" << std::setw(3) << iter.second.strong << " W" - << std::setw(3) << iter.second.weak << ") "; - }); - - LWNODE_LOG_INFO(COLOR_GREEN "------------------" COLOR_RESET); + LWNODE_DLOG_INFO(COLOR_GREEN "----- GCHEAP -----" COLOR_RESET); + LWNODE_DLOG_INFO("[STAT]"); + LWNODE_DLOG_INFO(" freed: %zu", stat_.freed); + LWNODE_DLOG_INFO(" strong: %zu", persistents_.size()); + LWNODE_DLOG_INFO(" weak: %zu", weakPhantoms_.size()); + LWNODE_DLOG_INFO("[HOLD]"); + printAddress(persistents_, + [](std::stringstream& stream, const HeapSegment& iter) { + stream << std::setw(15) << std::right + << GC_UNWRAP_PERSISTENT_POINTER(iter.first) << " (" + << "S" << std::setw(3) << iter.second.strong << " W" + << std::setw(3) << iter.second.weak << ") "; + }); + + LWNODE_DLOG_INFO(COLOR_GREEN "------------------" COLOR_RESET); + LWNODE_DLOG_INFO("[PHANTOM]"); + printAddress(weakPhantoms_, + [](std::stringstream& stream, const HeapSegment& iter) { + stream << std::setw(15) << std::right + << GC_UNWRAP_WEAK_POINTER(iter.first) << " (" + << "S" << std::setw(3) << iter.second.strong << " W" + << std::setw(3) << iter.second.weak << ") "; + }); + + LWNODE_DLOG_INFO(COLOR_GREEN "------------------" COLOR_RESET); } -void GCHeap::notifyUpdate(void* address) { - isStatusPrinted = false; +void GCHeap::postUpdate(void* address) { + isStatePrinted_ = false; } -void GCHeap::MakeWeak(void* location, - void* parameter, - v8::WeakCallbackInfo::Callback weak_callback, - v8::WeakCallbackType type) { - LWNODE_CALL_TRACE("address %p", location); +void GCHeap::processGCEvent() { + auto gcHeap = Engine::current()->gcHeap(); + gcHeap->printStatus(); + gcHeap->postGarbageCollectionProcessing(); +} - if (type != v8::WeakCallbackType::kParameter) { - LWNODE_CHECK(false); - } +std::vector + GCHeap::ProcessingHoldScope::s_processingHoldScopes_; -#if !defined(GC_HEAP_TRACE_ONLY) - // 1. register the given finalizer - struct Params { - v8::Isolate* isolate; - void* parameter; - v8::WeakCallbackInfo::Callback weak_callback; - }; - - Params* params = new Params(); - - LWNODE_CHECK(isTraced(location)); - - v8::Isolate* v8Isolate = - reinterpret_cast(getPersistentData(location)); - - LWNODE_CHECK_NOT_NULL(v8Isolate); - - params->isolate = v8Isolate; - params->parameter = parameter; - params->weak_callback = weak_callback; - - MemoryUtil::gcRegisterFinalizer( - location, - [](void* address, void* data) { - Engine::current()->gcHeap()->disposePhantomWeak(address); - Params* params = (Params*)data; - void* embedderFields[v8::kEmbedderFieldsInWeakCallback] = {}; - v8::WeakCallbackInfo info( - params->isolate, params->parameter, embedderFields, nullptr); - params->weak_callback(info); - delete params; - }, - params); -#endif +GCHeap::ProcessingHoldScope::ProcessingHoldScope() { + s_processingHoldScopes_.push_back(this); +} - // 2. make this location as weak type - MakeWeak(location); +GCHeap::ProcessingHoldScope::~ProcessingHoldScope() { + s_processingHoldScopes_.pop_back(); +} + +bool GCHeap::ProcessingHoldScope::isSkipProcessing() { + if (s_processingHoldScopes_.empty()) { + return false; + } + return true; } // --- E n g i n e --- @@ -365,11 +311,13 @@ void GCHeap::MakeWeak(void* location, static Engine* s_engine; std::unordered_set Engine::s_externalStrings; +static Engine::State s_state = Engine::Freed; bool Engine::Initialize() { if (s_engine == nullptr) { s_engine = new Engine(); s_engine->initialize(); + s_state = Running; } return true; } @@ -381,7 +329,7 @@ bool Engine::Dispose() { delete s_engine; s_engine = nullptr; } - + s_state = Freed; LWNODE_CALL_TRACE_GC_END(); return true; } @@ -403,23 +351,23 @@ void Engine::initialize() { Globals::initialize(); Memory::setGCFrequency(GC_FREE_SPACE_DIVISOR); - gcHeap_.reset(new GCHeap()); + gcHeap_.reset(GCHeap::create()); - if (Flags::isTraceCallEnabled("HEAP")) { - Memory::setGCEventListener([]() { - // this is invoked at GC_EVENT_RECLAIM_END phase - Engine::current()->gcHeap()->printStatus(); - }); - } +#if defined(GC_HEAP_TRACE_ONLY) + // this is invoked at GC_EVENT_RECLAIM_END phase + Memory::setGCEventListener(GCHeap::processGCEvent); +#endif auto flags = Flags::get(); if (Flags::isTraceGCEnabled()) { - MemoryUtil::gcStartStatsTrace(); + LWNODE_DLOG_WARN("temporary blocked for postGarbageCollectionProcessing"); + // MemoryUtil::gcStartStatsTrace(); } } void Engine::dispose() { LWNODE_CALL_TRACE_GC_START(); + s_state = OnDestroy; Memory::setGCEventListener(nullptr); @@ -437,6 +385,10 @@ Engine* Engine::current() { return s_engine; } +Engine::State Engine::getState() { + return s_state; +} + void Engine::registerExternalString( v8::String::ExternalStringResourceBase* v8Str) { s_externalStrings.emplace(v8Str); diff --git a/lwnode/code/escargotshim/src/api/engine.h b/lwnode/code/escargotshim/src/api/engine.h index e4c8981..b5f3102 100644 --- a/lwnode/code/escargotshim/src/api/engine.h +++ b/lwnode/code/escargotshim/src/api/engine.h @@ -62,24 +62,14 @@ class Platform : public PlatformRef { v8::ArrayBuffer::Allocator* allocator_ = nullptr; }; -#define GC_HEAP_TRACE_ONLY - class GCHeap : public gc { public: - void GlobalizeReference(void* address, void* data); - void DisposeGlobal(void* address); - void MakeWeak(void* address); - void MakeWeak(void* location, - void* parameter, - v8::WeakCallbackInfo::Callback weak_callback, - v8::WeakCallbackType type); - void ClearWeak(void* address); - void disposePhantomWeak(void* address); - bool isTraced(void* address); - void* getPersistentData(void* address); - void printStatus(); + enum Kind { + FREE = 0, + STRONG, + WEAK, + }; - typedef GC_word GC_heap_pointer; struct AddressInfo { AddressInfo(int strong_, int weak_, void* data_ = nullptr) { strong = strong_; @@ -90,13 +80,44 @@ class GCHeap : public gc { int weak = 0; void* data = nullptr; }; + typedef GC_word GC_heap_pointer; + typedef std::pair HeapSegment; + + void acquire(void* address, Kind kind, void* data); + void release(void* address, Kind kind); + void disposePhantomWeak(void* address); + bool isTraced(void* address); + void printStatus(bool forcePrint = false); + + class ProcessingHoldScope { + public: + ProcessingHoldScope(); + ~ProcessingHoldScope(); + + static bool isSkipProcessing(); + + private: + static std::vector s_processingHoldScopes_; + }; + + void postGarbageCollectionProcessing(); + static void processGCEvent(); + + static GCHeap* create() { return new GCHeap(); } private: - void notifyUpdate(void* address); + void postUpdate(void* address); GCUnorderedMap persistents_; GCUnorderedMap weakPhantoms_; - bool isStatusPrinted = false; + bool isStatePrinted_ = false; + bool isOnPostGarbageCollectionProcessing_ = false; + struct Stat { + size_t freed = 0; + size_t weak = 0; + }; + + Stat stat_; }; class Engine { @@ -112,6 +133,14 @@ class Engine { GCHeap* gcHeap() { return gcHeap_.get(); } + enum State { + Freed, + Running, + OnDestroy, + }; + + static State getState(); + private: Engine() = default; void initialize(); diff --git a/lwnode/code/escargotshim/src/api/global-handles.cc b/lwnode/code/escargotshim/src/api/global-handles.cc index 28a500a..fd3ff9f 100644 --- a/lwnode/code/escargotshim/src/api/global-handles.cc +++ b/lwnode/code/escargotshim/src/api/global-handles.cc @@ -48,6 +48,23 @@ class GlobalWeakHandler { return nodeBlock; } + size_t clearWeakValue() { + auto weakValuesSize = weakValues_.size(); + if (weakValuesSize == 0) { + return 0; + } + LWNODE_CALL_TRACE_ID( + GLOBALHANDLES, "Clear weak values: %ld", weakValuesSize); + for (auto& iter : weakValues_) { + iter.second->releaseValue(); + } + return weakValuesSize; + } + + bool isWeak(ValueWrap* lwValue) { + return weakValues_.find(lwValue) != weakValues_.end(); + } + void dispose() { weakValues_.clear(); } private: @@ -59,55 +76,41 @@ GlobalWeakHandler g_globalWeakHandler; GlobalHandles::Node::Node(void* parameter, v8::WeakCallbackInfo::Callback callback) - : parameter_(parameter), callback_(callback) { - LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "New Node(%p)", this); -} + : parameter_(parameter), callback_(callback) {} -GlobalHandles::Node::~Node() { - LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "Free Node(%p)", this); -} +GlobalHandles::Node::~Node() {} -GlobalHandles::NodeBlock::NodeBlock(v8::Isolate* isolate, uint32_t count) - : isolate_(isolate), usedNodes_(count) { - LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "New NodeBlock(%p)", this); +GlobalHandles::NodeBlock::NodeBlock(v8::Isolate* isolate, + ValueWrap* value, + uint32_t count) + : isolate_(isolate), value_(value), usedNodes_(count) { + holder_.reset(value_); } GlobalHandles::NodeBlock::~NodeBlock() { - LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "Free NodeBlock(%p)", this); - auto curNode = firstNode_; - while (curNode) { - auto nextNode = curNode->nextNode(); - delete curNode; - curNode = nextNode; - } + delete firstNode_; + holder_.release(); } -bool GlobalHandles::NodeBlock::increaseUsage() { - return usedNodes_++ == 0; -} - -bool GlobalHandles::NodeBlock::decreaseUsage() { - LWNODE_DCHECK(usedNodes_ > 0); - return --usedNodes_ == 0; -} - -GlobalHandles::Node* GlobalHandles::NodeBlock::pushNode(ValueWrap* lwValue, - Node* node) { +GlobalHandles::Node* GlobalHandles::NodeBlock::pushNode(Node* node) { if (firstNode_ == nullptr) { firstNode_ = node; - registerWeakCallback(lwValue); } else { // TODO - LWNODE_DLOG_WARN("The weak callback is registered several times.") + LWNODE_DLOG_WARN("The weak callback is registered several times."); + if (node) { + delete node; + return nullptr; + } } return node; } -void GlobalHandles::NodeBlock::registerWeakCallback(ValueWrap* lwValue) { - MemoryUtil::gcRegisterFinalizer(lwValue, [](void* self) { +void GlobalHandles::NodeBlock::registerWeakCallback() { + MemoryUtil::gcRegisterFinalizer(value_, [](void* self) { LWNODE_CALL_TRACE_GC_START(); - LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "Call weak callback"); + LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "Call weak callback: %p", self); auto block = g_globalWeakHandler.popBlock(VAL(self)); if (!block) { @@ -123,19 +126,19 @@ void GlobalHandles::NodeBlock::registerWeakCallback(ValueWrap* lwValue) { v8::WeakCallbackInfo info( block->isolate(), curNode->parameter(), embedderFields, nullptr); LWNODE_CHECK_NOT_NULL(block->isolate()); - LWNODE_CALL_TRACE_ID( - GLOBALHANDLES, "Call v8 callback: parm(%p)", curNode->parameter()); curNode->callback()(info); } - - if (curNode->nextNode()) { - LWNODE_UNIMPLEMENT; // TODO - } + // TODO: The weak callback is registered several times.(create nextNode) } LWNODE_CALL_TRACE_GC_END(); }); } +void GlobalHandles::NodeBlock::releaseValue() { + registerWeakCallback(); + holder_.release(); +} + GlobalHandles::GlobalHandles(v8::Isolate* isolate) : isolate_(isolate) { g_globalHandlesVector.push_back(this); } @@ -162,7 +165,9 @@ void GlobalHandles::Create(ValueWrap* lwValue) { } else { ++iter->second; // TODO: - LWNODE_DLOG_WARN("Persistent value was created multiple times.") + LWNODE_CALL_TRACE_ID(GLOBALHANDLES, + "Persistent value was created multiple times: %p", + lwValue); } } @@ -172,7 +177,7 @@ void GlobalHandles::Destroy(ValueWrap* lwValue) { return; } } - LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "Cannot destroy: %p", lwValue) + LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "Cannot destroy: %p", lwValue); } bool GlobalHandles::destroy(ValueWrap* lwValue) { @@ -188,6 +193,15 @@ bool GlobalHandles::destroy(ValueWrap* lwValue) { return false; } +size_t GlobalHandles::PostGarbageCollectionProcessing( + /*const v8::GCCallbackFlags gc_callback_flags*/) { +#if defined(LWNODE_ENABLE_EXPERIMENTAL) + return g_globalWeakHandler.clearWeakValue(); +#else + return 0; +#endif +} + void GlobalHandles::MakeWeak(ValueWrap* lwValue, void* parameter, v8::WeakCallbackInfo::Callback callback) { @@ -196,7 +210,7 @@ void GlobalHandles::MakeWeak(ValueWrap* lwValue, return; } } - LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "Cannot make weak value: %p", lwValue) + LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "Cannot make weak value: %p", lwValue); } bool GlobalHandles::makeWeak(ValueWrap* lwValue, @@ -207,13 +221,39 @@ bool GlobalHandles::makeWeak(ValueWrap* lwValue, return false; } - auto block = - std::make_unique(isolate_, iter->second); - block->pushNode(lwValue, new Node(parameter, callback)); + if (g_globalWeakHandler.isWeak(lwValue)) { + return false; + } + + auto block = std::make_unique( + isolate_, lwValue, iter->second); + block->pushNode(new Node(parameter, callback)); g_globalWeakHandler.pushBlock(lwValue, std::move(block)); + LWNODE_CALL_TRACE_ID( + GLOBALHANDLES, "MakeWeak: %p(%ld)", lwValue, iter->second); persistentValues_.erase(iter); - LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "MakeWeak: %p", lwValue) + return true; +} + +void* GlobalHandles::ClearWeakness(ValueWrap* lwValue) { + for (auto globalHandles : g_globalHandlesVector) { + if (globalHandles->clearWeak(lwValue)) { + return lwValue; + } + } + LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "Cannot clear weak value: %p", lwValue); + return nullptr; +} + +bool GlobalHandles::clearWeak(ValueWrap* lwValue) { + auto block = g_globalWeakHandler.popBlock(lwValue); + if (!block) { + return false; + } + LWNODE_CHECK(persistentValues_.find(lwValue) == persistentValues_.end()); + persistentValues_.emplace(lwValue, block->usedNodes()); + LWNODE_CALL_TRACE_ID(GLOBALHANDLES, "ClearWeak: %p", lwValue); return true; } diff --git a/lwnode/code/escargotshim/src/api/global-handles.h b/lwnode/code/escargotshim/src/api/global-handles.h index de0a132..82eb645 100644 --- a/lwnode/code/escargotshim/src/api/global-handles.h +++ b/lwnode/code/escargotshim/src/api/global-handles.h @@ -31,6 +31,10 @@ class GlobalHandles final : public gc { static void MakeWeak(ValueWrap* lwValue, void* parameter, v8::WeakCallbackInfo::Callback callback); + static void* ClearWeakness(ValueWrap* lwValue); + + size_t PostGarbageCollectionProcessing( + /*const v8::GCCallbackFlags gc_callback_flags*/); bool destroy(ValueWrap* lwValue); @@ -38,6 +42,8 @@ class GlobalHandles final : public gc { void* parameter, v8::WeakCallbackInfo::Callback callback); + bool clearWeak(ValueWrap* lwValue); + size_t handles_count(); void Dispose(); @@ -49,43 +55,41 @@ class GlobalHandles final : public gc { Node(const Node&) = delete; - Node* nextNode() { return nextNode_; } void* parameter() { return parameter_; } v8::WeakCallbackInfo::Callback callback() { return callback_; } private: - Node* nextNode_{nullptr}; void* parameter_{nullptr}; v8::WeakCallbackInfo::Callback callback_; }; class NodeBlock { public: - NodeBlock(v8::Isolate* isolate, uint32_t count); + NodeBlock(v8::Isolate* isolate, ValueWrap* value, uint32_t count); ~NodeBlock(); NodeBlock(const NodeBlock&) = delete; - bool increaseUsage(); - - bool decreaseUsage(); - - uint32_t usage() { return usedNodes_; } + uint32_t usedNodes() { return usedNodes_; } Node* firstNode() { return firstNode_; } void setFirstNode(Node* node) { firstNode_ = node; } - Node* pushNode(ValueWrap* lwValue, Node* node); + Node* pushNode(Node* node); + + void registerWeakCallback(); - void registerWeakCallback(ValueWrap* lwValue); + void releaseValue(); v8::Isolate* isolate() { return isolate_; } private: v8::Isolate* isolate_{nullptr}; + ValueWrap* value_{nullptr}; uint32_t usedNodes_{0}; Node* firstNode_{nullptr}; + Escargot::PersistentRefHolder holder_; }; private: diff --git a/lwnode/code/escargotshim/src/api/handle.cc b/lwnode/code/escargotshim/src/api/handle.cc index c731b5c..93709e9 100644 --- a/lwnode/code/escargotshim/src/api/handle.cc +++ b/lwnode/code/escargotshim/src/api/handle.cc @@ -15,8 +15,10 @@ */ #include "handle.h" +#include #include "api.h" #include "context.h" +#include "engine.h" #include "isolate.h" #include "utils/misc.h" @@ -30,8 +32,53 @@ uint8_t HandleWrap::type() const { return type_; } +uint8_t HandleWrap::valueType() const { + return valueType_; +} + +uint8_t HandleWrap::location() const { + return location_; +} + bool HandleWrap::isValid() const { - return (type_ < HandleWrap::Type::NotPresent); + return (type_ > Type::NotPresent && type_ < Type::EndOfType); +} + +bool HandleWrap::isStrongOrWeak() const { + return (location_ == Strong || location_ == Weak || location_ == NearDeath); +} + +void HandleWrap::copy(HandleWrap* that, Location location) { + val_ = that->val_; + type_ = that->type_; + valueType_ = that->valueType_; + location_ = location; +} + +HandleWrap* HandleWrap::clone(Location location) { + auto handle = new HandleWrap(); + handle->val_ = val_; + handle->type_ = type_; + handle->valueType_ = valueType_; + handle->location_ = location; + + LWNODE_CALL_TRACE_ID( + HANDLE, "%p is cloned from %s", handle, getHandleInfoString().c_str()); + return handle; +} + +HandleWrap* HandleWrap::as(void* address) { + auto p = reinterpret_cast(address); + LWNODE_CHECK(p->isValid()); + return p; +} + +std::string HandleWrap::getHandleInfoString() { + std::stringstream ss; + ss << "(addr: " << this << " es: " << val_ + << " loc: " << std::to_string(location_) + << " type: " << std::to_string(type_) << ")"; + return ss.str(); } // --- ValueWrap --- @@ -41,8 +88,9 @@ ValueWrap::ValueWrap(void* ptr, HandleWrap::ValueType valueType) { LWNODE_CHECK_NOT_NULL(ptr); type_ = type; - holder_ = ptr; + val_ = ptr; valueType_ = valueType; + LWNODE_CALL_TRACE_ID(HANDLE, "%s", getHandleInfoString().c_str()); } bool ValueWrap::isExternalString() const { @@ -55,47 +103,41 @@ ExternalStringWrap* ValueWrap::asExternalString() const { } ValueWrap* ValueWrap::createValue(Escargot::ValueRef* esValue) { - auto value = new ValueWrap(esValue, Type::JsValue); - LWNODE_CALL_TRACE_ID(VALUEWRAP, "es:%p | %p", esValue, value); - return value; + return new ValueWrap(esValue, Type::JsValue); } ValueRef* ValueWrap::value() const { LWNODE_CHECK_MSG(type() == Type::JsValue, - "type should be %d but %d. (this: %p, holder_: %p)", + "type should be %d but %d. (this: %p, val_: %p)", Type::JsValue, type(), this, - holder_); - return reinterpret_cast(holder_); + val_); + return reinterpret_cast(val_); } ValueWrap* ValueWrap::createContext(ContextWrap* lwContext) { - auto value = new ValueWrap(lwContext, Type::Context); - LWNODE_CALL_TRACE_ID(VALUEWRAP, "es:%p | %p", lwContext, value); - return value; + return new ValueWrap(lwContext, Type::Context); }; ContextWrap* ValueWrap::context() const { - LWNODE_CHECK(type() == Type::Context); - return reinterpret_cast(holder_); + LWNODE_CHECK(type_ == Type::Context); + return reinterpret_cast(val_); } ValueWrap* ValueWrap::createScript(ScriptRef* esScript) { - auto value = new ValueWrap(esScript, Type::Script); - LWNODE_CALL_TRACE_ID(VALUEWRAP, "es:%p | %p", esScript, value); - return value; + return new ValueWrap(esScript, Type::Script); }; ScriptRef* ValueWrap::script() const { - LWNODE_CHECK(type() == Type::Script); - return reinterpret_cast(holder_); + LWNODE_CHECK(type_ == Type::Script); + return reinterpret_cast(val_); } Escargot::TemplateRef* ValueWrap::tpl() const { - LWNODE_CHECK(type() == Type::ObjectTemplate || - type() == Type::FunctionTemplate); - return reinterpret_cast(holder_); + LWNODE_CHECK(type_ == Type::ObjectTemplate || + type_ == Type::FunctionTemplate); + return reinterpret_cast(val_); } ValueWrap* ValueWrap::createFunctionTemplate( @@ -104,8 +146,8 @@ ValueWrap* ValueWrap::createFunctionTemplate( } Escargot::FunctionTemplateRef* ValueWrap::ftpl() const { - LWNODE_CHECK(type() == Type::FunctionTemplate); - return reinterpret_cast(holder_); + LWNODE_CHECK(type_ == Type::FunctionTemplate); + return reinterpret_cast(val_); } ValueWrap* ValueWrap::createObjectTemplate( @@ -114,8 +156,8 @@ ValueWrap* ValueWrap::createObjectTemplate( } Escargot::ObjectTemplateRef* ValueWrap::otpl() const { - LWNODE_CHECK(type() == Type::ObjectTemplate); - return reinterpret_cast(holder_); + LWNODE_CHECK(type_ == Type::ObjectTemplate); + return reinterpret_cast(val_); } ValueWrap* ValueWrap::createModule(ModuleWrap* esModule) { @@ -123,8 +165,208 @@ ValueWrap* ValueWrap::createModule(ModuleWrap* esModule) { } ModuleWrap* ValueWrap::module() const { - LWNODE_CHECK(type() == Type::Module); - return reinterpret_cast(holder_); + LWNODE_CHECK(type_ == Type::Module); + return reinterpret_cast(val_); +} + +// --- PersistentWrap --- + +inline static GCHeap* GCHeap() { + return Engine::current()->gcHeap(); +} + +inline static void acquireStrong(void* address, void* data = nullptr) { + GCHeap()->acquire(address, GCHeap::STRONG, data); +} + +inline static void releaseStrong(void* address) { + GCHeap()->release(address, GCHeap::STRONG); +} + +inline static void acquireWeak(void* address, void* data = nullptr) { + GCHeap()->acquire(address, GCHeap::WEAK, data); +} + +inline static void releaseWeak(void* address) { + GCHeap()->release(address, GCHeap::WEAK); +} + +inline static void makeStrongToWeak(void* address) { + acquireWeak(address); + releaseStrong(address); +} +/* + 1. val_ : HandleWrap MUST be compatible with in V8 other apis. + + ex1) + v8::Persistent global1; + global1.Reset(isolate, v8_str("str")); + Local local1 = Local::New(isolate, global1); + CHECK(global1 == local1); + + ex2) + v8::Context* operator->() { + return *reinterpret_cast(&context_); + } + v8::Context* operator*() { return operator->(); } + v8::Persistent context_; + + 2. member values of this instance MUST be hidden to GC. +*/ + +PersistentWrap::PersistentWrap(ValueWrap* lwValue) { + // copy the given value information and set it as Strong + copy(lwValue, Location::Strong); + + holder_ = lwValue; + + LWNODE_CALL_TRACE_ID(GCHEAP, + "%s trace: (%p)", + getPersistentInfoString().c_str(), + getTracingAddress()); + + acquireStrong(this, nullptr); + LWNODE_DCHECK(GCHeap()->isTraced(this)); +} + +void* PersistentWrap::getTracingAddress() { + return this; +} + +void* PersistentWrap::GlobalizeReference(v8::Isolate* isolate, void* address) { + LWNODE_CALL_TRACE_ID(GCHEAP); + ValueWrap* lwValue = reinterpret_cast(address); + LWNODE_CHECK(lwValue->isValid()); + + PersistentWrap* persistent = new PersistentWrap(lwValue); + + persistent->v8Isolate_ = isolate; + + GCHeap()->printStatus(true); + + return persistent; +} + +void PersistentWrap::DisposeGlobal(void* address) { + PersistentWrap* persistent = reinterpret_cast(address); + LWNODE_CALL_TRACE_ID( + GCHEAP, "%s", persistent->getPersistentInfoString().c_str()); + + LWNODE_DCHECK(persistent->location_ != Local); + + persistent->dispose(); + + GCHeap()->printStatus(true); +} + +void PersistentWrap::dispose() { + LWNODE_CALL_TRACE_ID(GCHEAP, + "%s isFinalizerCalled: %s", + getPersistentInfoString().c_str(), + strBool(isFinalizerCalled)); + if (isFinalizerCalled) { + return; + } + + if (location_ == Location::Strong) { + releaseStrong(getTracingAddress()); + } else if (location_ == Location::Weak) { + releaseWeak(getTracingAddress()); + } else { + LWNODE_CHECK_NOT_REACH_HERE(); + } +} + +void PersistentWrap::MakeWeak( + void* address, + void* parameter, + v8::WeakCallbackInfo::Callback weak_callback) { + LWNODE_CALL_TRACE_ID(GCHEAP); + PersistentWrap* persitent = reinterpret_cast(address); + LWNODE_CHECK(persitent->location() != Location::Local); + persitent->makeWeak(parameter, weak_callback); + + GCHeap()->printStatus(true); +} + +void PersistentWrap::makeWeak( + void* parameter, v8::WeakCallbackInfo::Callback weak_callback) { + if (location_ == Location::Strong) { + // Strong -> Weak + makeStrongToWeak(getTracingAddress()); + location_ = Location::Weak; + parameter_ = parameter; + weak_callback_ = weak_callback; + + } else if (location_ == Location::Weak) { + LWNODE_CHECK(weak_callback_ == weak_callback); + LWNODE_CHECK(parameter_ == parameter); + + } else { + LWNODE_CHECK_NOT_REACH_HERE(); + } + + LWNODE_CHECK(GCHeap()->isTraced(this)); +} + +void PersistentWrap::invokeFinalizer() { + if (Engine::getState() == Engine::Running) { + GCHeap()->disposePhantomWeak(this); + } + + v8::HandleScope handleScope(v8Isolate_); + void* embedderFields[v8::kEmbedderFieldsInWeakCallback] = {}; + v8::WeakCallbackInfo data( + v8Isolate_, parameter_, embedderFields, nullptr); + + weak_callback_(data); + + isFinalizerCalled = true; +} + +void* PersistentWrap::ClearWeak(void* address) { + LWNODE_CALL_TRACE_ID(GCHEAP); + PersistentWrap* persitent = reinterpret_cast(address); + LWNODE_CHECK(persitent->location() != Location::Local); + void* p = persitent->clearWeak(); + GCHeap()->printStatus(true); + return p; +} + +void* PersistentWrap::clearWeak() { + if (location_ == Location::Strong) { + // Nothing to do + LWNODE_CHECK_NULL(weak_callback_); + LWNODE_CHECK_NULL(parameter_); + + } else if (location_ == Location::Weak) { + // Weak -> Strong + acquireStrong(getTracingAddress(), nullptr); + releaseWeak(getTracingAddress()); + location_ = Location::Strong; + + } else { + LWNODE_CHECK_NOT_REACH_HERE(); + } + + void* p = parameter_; + parameter_ = nullptr; + weak_callback_ = nullptr; + return p; +} + +PersistentWrap* PersistentWrap::as(void* address) { + auto p = reinterpret_cast(address); + LWNODE_CHECK(p->isStrongOrWeak()); + LWNODE_CHECK(p->isValid()); + return p; +} + +std::string PersistentWrap::getPersistentInfoString() { + std::stringstream ss; + ss << getHandleInfoString() << " holder: " << holder_; + + return ss.str(); } } // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/handle.h b/lwnode/code/escargotshim/src/api/handle.h index a6c7846..533c954 100644 --- a/lwnode/code/escargotshim/src/api/handle.h +++ b/lwnode/code/escargotshim/src/api/handle.h @@ -26,18 +26,26 @@ class ContextWrap; class IsolateWrap; class ModuleWrap; class ExternalStringWrap; +class GCHeap; class HandleWrap : public gc { public: enum Type : uint8_t { + NotPresent = 0, JsValue = 101, Context, ObjectTemplate, FunctionTemplate, Script, Module, - // NotPresent should be at last - NotPresent, + EndOfType, + }; + + enum Location : uint8_t { + Local = 0, + Strong, + Weak, + NearDeath, }; enum ValueType : uint8_t { @@ -46,13 +54,22 @@ class HandleWrap : public gc { }; uint8_t type() const; + uint8_t valueType() const; bool isValid() const; + bool isStrongOrWeak() const; + uint8_t location() const; + HandleWrap* clone(Location location = Local); + std::string getHandleInfoString(); + static HandleWrap* as(void* address); protected: HandleWrap() = default; - void* holder_ = nullptr; + void copy(HandleWrap* that, Location location); + + void* val_ = nullptr; uint8_t type_ = Type::NotPresent; uint8_t valueType_ = ValueType::None; // TODO: remove this variable + uint8_t location_ = Location::Local; }; class ValueWrap : public HandleWrap { @@ -97,6 +114,37 @@ class ValueWrap : public HandleWrap { ValueWrap(void* ptr, HandleWrap::Type type, HandleWrap::ValueType valueType = HandleWrap::ValueType::None); + ValueWrap() = default; +}; + +class PersistentWrap : public ValueWrap { + public: + static void* GlobalizeReference(v8::Isolate* isolate, void* address); + static void DisposeGlobal(void* address); + static void MakeWeak(void* address, + void* parameter, + v8::WeakCallbackInfo::Callback weak_callback); + static void* ClearWeak(void* address); + + static PersistentWrap* as(void* address); + std::string getPersistentInfoString(); + void invokeFinalizer(); + + private: + PersistentWrap(ValueWrap* ptr); + + void dispose(); + void makeWeak(void* parameter, + v8::WeakCallbackInfo::Callback weak_callback); + void* clearWeak(); + void* getTracingAddress(); + + ValueWrap* holder_{nullptr}; + v8::Isolate* v8Isolate_{nullptr}; + v8::WeakCallbackInfo::Callback weak_callback_{nullptr}; + void* parameter_{nullptr}; + bool isFinalizerCalled{false}; + friend class GCHeap; }; } // namespace EscargotShim diff --git a/lwnode/code/escargotshim/src/api/handlescope.cc b/lwnode/code/escargotshim/src/api/handlescope.cc index 1f702dc..80985d7 100644 --- a/lwnode/code/escargotshim/src/api/handlescope.cc +++ b/lwnode/code/escargotshim/src/api/handlescope.cc @@ -37,7 +37,11 @@ HandleScopeWrap::HandleScopeWrap(v8::EscapableHandleScope* scope, : type_(type), v8scope_(reinterpret_cast(scope)) {} void HandleScopeWrap::add(HandleWrap* value) { - LWNODE_CALL_TRACE_ID(HDLSCOPE, "%p -> %p | %p", value, v8scope_, this); + LWNODE_CALL_TRACE_ID(HDLSCOPE, + "%s --> %p (lw: %p)", + value->getHandleInfoString().c_str(), + v8scope_, + this); handles_.push_back(value); } diff --git a/lwnode/code/escargotshim/src/api/isolate.cc b/lwnode/code/escargotshim/src/api/isolate.cc index 3cb180e..8ed4e4d 100755 --- a/lwnode/code/escargotshim/src/api/isolate.cc +++ b/lwnode/code/escargotshim/src/api/isolate.cc @@ -230,6 +230,7 @@ IsolateWrap* IsolateWrap::New() { } void IsolateWrap::Dispose() { + LWNODE_CALL_TRACE_ID(ISOWRAP); LWNODE_CALL_TRACE_GC_START(); // NOTE: check unlock_gc_release(); is needed (and where) // unlock_gc_release(); @@ -348,6 +349,7 @@ void IsolateWrap::popHandleScope(v8Scope_t* handleScope) { } void IsolateWrap::addHandleToCurrentScope(HandleWrap* value) { + LWNODE_CALL_TRACE("%p", value); LWNODE_CHECK(handleScopes_.size() >= 1); handleScopes_.back()->add(value); } @@ -371,7 +373,11 @@ bool IsolateWrap::isCurrentScopeSealed() { } void IsolateWrap::pushContext(ContextWrap* context) { - LWNODE_CALL_TRACE_ID(ISOWRAP, "%p", 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: @@ -396,7 +402,11 @@ size_t IsolateWrap::getNumberOfContexts() { void IsolateWrap::popContext(ContextWrap* context) { LWNODE_CHECK(contextScopes_.back() == context); - LWNODE_CALL_TRACE_ID(ISOWRAP, "%p", context); + LWNODE_CALL_TRACE_ID(ISOWRAP, + "%p (%zu -> %zu)", + context, + contextScopes_.size(), + contextScopes_.size() - 1); contextScopes_.pop_back(); } @@ -422,30 +432,82 @@ void IsolateWrap::removeBackingStore(BackingStoreRef* value) { backingStores_.erase(value); } -SymbolRef* IsolateWrap::getPrivateSymbol(StringRef* esString) { - // @check replace this container if this function is called a lot. +SymbolRef* IsolateWrap::createApiSymbol(StringRef* name) { + // FIXME: Use a set + auto newSymbol = SymbolRef::create(name); + bool found = false; + for (size_t i = 0; i < apiSymbols_.size(); i++) { + if (apiSymbols_[i]->description()->equals(name)) { + apiSymbols_[i] = newSymbol; + found = true; + break; + } + } + + if (!found) { + apiSymbols_.push_back(newSymbol); + LWNODE_DLOG_INFO("malc: api symbol: %s", name->toStdUTF8String().c_str()); + } + + return newSymbol; +} + +SymbolRef* IsolateWrap::getApiSymbol(StringRef* name) { + // FIXME: Use a set LWNODE_CALL_TRACE_ID(ISOWRAP); - for (size_t i = 0; i < privateSymbols_.size(); i++) { - if (privateSymbols_[i]->description()->equals(esString)) { - return privateSymbols_[i]; + for (size_t i = 0; i < apiSymbols_.size(); i++) { + if (apiSymbols_[i]->description()->equals(name)) { + return apiSymbols_[i]; } } - auto newSymbol = SymbolRef::create(esString); - privateSymbols_.push_back(newSymbol); + return createApiSymbol(name); +} - LWNODE_DLOG_INFO("malc: private symbol: %s", - esString->toStdUTF8String().c_str()); +SymbolRef* IsolateWrap::createApiPrivateSymbol(StringRef* name) { + // FIXME: Use a set + auto newSymbol = SymbolRef::create(name); + bool found = false; + for (size_t i = 0; i < apiPrivateSymbols_.size(); i++) { + if (apiPrivateSymbols_[i]->description()->equals(name)) { + apiPrivateSymbols_[i] = newSymbol; + found = true; + break; + } + } + + if (!found) { + apiPrivateSymbols_.push_back(newSymbol); + LWNODE_DLOG_INFO("malc: private symbol: %s", + name->toStdUTF8String().c_str()); + } return newSymbol; } +SymbolRef* IsolateWrap::getApiPrivateSymbol(StringRef* name) { + // FIXME: Use a set + LWNODE_CALL_TRACE_ID(ISOWRAP); + + for (size_t i = 0; i < apiPrivateSymbols_.size(); i++) { + if (apiPrivateSymbols_[i]->description()->equals(name)) { + return apiPrivateSymbols_[i]; + } + } + + return createApiPrivateSymbol(name); +} + void IsolateWrap::ClearPendingExceptionAndMessage() { clear_pending_exception(); clear_pending_message_obj(); } +void IsolateWrap::CollectGarbage() { + globalHandles_->PostGarbageCollectionProcessing(); +} + void IsolateWrap::SetPendingExceptionAndMessage( ValueRef* exception, GCManagedVector& stackTraceData) { diff --git a/lwnode/code/escargotshim/src/api/isolate.h b/lwnode/code/escargotshim/src/api/isolate.h index f8b8679..7157846 100755 --- a/lwnode/code/escargotshim/src/api/isolate.h +++ b/lwnode/code/escargotshim/src/api/isolate.h @@ -194,10 +194,16 @@ class IsolateWrap final : public v8::internal::Isolate { bool isHole(const ValueWrap* wrap) override; bool isHole(const Escargot::ValueRef* ref) override; - SymbolRef* getPrivateSymbol(StringRef* esString); + SymbolRef* createApiSymbol(StringRef* name); + SymbolRef* getApiSymbol(StringRef* name); + + SymbolRef* createApiPrivateSymbol(StringRef* name); + SymbolRef* getApiPrivateSymbol(StringRef* name); GlobalHandles* globalHandles() { return globalHandles_; } + void CollectGarbage(); + void SetPendingExceptionAndMessage( ValueRef* exception, GCManagedVector& stackTraceData) @@ -224,7 +230,8 @@ class IsolateWrap final : public v8::internal::Isolate { GCVector contextScopes_; PersistentRefHolder privateValuesSymbol_; - GCVector privateSymbols_; + GCVector apiSymbols_; + GCVector apiPrivateSymbols_; // Isolate Scope static THREAD_LOCAL IsolateWrap* s_currentIsolate; diff --git a/lwnode/code/escargotshim/src/api/utils/gc.cc b/lwnode/code/escargotshim/src/api/utils/gc.cc index e14d474..56b0f2c 100644 --- a/lwnode/code/escargotshim/src/api/utils/gc.cc +++ b/lwnode/code/escargotshim/src/api/utils/gc.cc @@ -282,7 +282,7 @@ void MemoryUtil::prettyBytes(char* buf, }; uint s = 0; double c = bytes; - while (c >= 1024 && s < 7) { + while (c >= 1024 && s < 7 - 1) { c /= 1024; s++; } diff --git a/lwnode/code/escargotshim/src/api/utils/logger.h b/lwnode/code/escargotshim/src/api/utils/logger.h index 41c2912..ab2aaec 100644 --- a/lwnode/code/escargotshim/src/api/utils/logger.h +++ b/lwnode/code/escargotshim/src/api/utils/logger.h @@ -83,7 +83,8 @@ class IndentCounter { } while (0); #endif -#define LWNODE_LOG_INFO(fmt, ...) LWNODE_LOG_RAW("INFO " fmt, ##__VA_ARGS__); +#define LWNODE_LOG_INFO(fmt, ...) \ + LWNODE_LOG_RAW("INFO " fmt COLOR_RESET, ##__VA_ARGS__); #define LWNODE_LOG_WARN(fmt, ...) \ LWNODE_LOG_RAW(COLOR_YELLOW "WARN " fmt COLOR_RESET, ##__VA_ARGS__); diff --git a/lwnode/code/escargotshim/src/libplatform/tracing/trace-buffer.h b/lwnode/code/escargotshim/src/libplatform/tracing/trace-buffer.h index 3b4a47e..b951c11 100644 --- a/lwnode/code/escargotshim/src/libplatform/tracing/trace-buffer.h +++ b/lwnode/code/escargotshim/src/libplatform/tracing/trace-buffer.h @@ -56,7 +56,7 @@ class TraceBufferRingBuffer : public TraceBuffer { size_t max_chunks_; std::unique_ptr trace_writer_; std::vector> chunks_; - size_t chunk_index_; + size_t chunk_index_ = 0; bool is_empty_ = true; uint32_t current_chunk_seq_ = 1; }; diff --git a/tools/gyp_node.py b/tools/gyp_node.py index 8c7493f..332a729 100755 --- a/tools/gyp_node.py +++ b/tools/gyp_node.py @@ -34,6 +34,14 @@ def run_gyp(args): args.append('--depth=' + node_root) +# @lwnode + if '-Dnode_core_target_name=lwnode' not in args: + global output_dir + output_dir = os.path.join(output_dir, 'v8') + args.extend(['--generator-output', output_dir]) + args.extend(['-Goutput_dir=' + output_dir]) +# @end of lwnode + # There's a bug with windows which doesn't allow this feature. if sys.platform != 'win32' and 'ninja' not in args: # Tell gyp to write the Makefiles into output_dir