| /* |
| * Copyright 2014 Google Inc. All Rights Reserved. |
| * |
| * 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 "cobalt/script/javascriptcore/jsc_engine.h" |
| |
| #include "base/logging.h" |
| #include "base/memory/singleton.h" |
| #include "base/message_loop.h" |
| #include "base/synchronization/lock.h" |
| #include "base/time.h" |
| #include "cobalt/base/c_val.h" |
| #include "cobalt/base/poller.h" |
| #include "cobalt/script/javascriptcore/jsc_global_environment.h" |
| #include "cobalt/script/javascriptcore/jsc_global_object.h" |
| #include "third_party/WebKit/Source/JavaScriptCore/runtime/InitializeThreading.h" |
| #include "third_party/WebKit/Source/WTF/wtf/OSAllocator.h" |
| |
| namespace cobalt { |
| namespace script { |
| namespace javascriptcore { |
| |
| namespace { |
| |
| #if defined(__LB_SHELL__FOR_RELEASE__) |
| const int kPollerPeriodMs = 2000; |
| #else // #if defined(__LB_SHELL__FOR_RELEASE__) |
| const int kPollerPeriodMs = 20; |
| #endif // #if defined(__LB_SHELL__FOR_RELEASE__) |
| |
| class JSCEngineStats { |
| public: |
| JSCEngineStats(); |
| |
| static JSCEngineStats* GetInstance() { |
| return Singleton<JSCEngineStats, |
| StaticMemorySingletonTraits<JSCEngineStats> >::get(); |
| } |
| |
| void JSCEngineCreated() { |
| base::AutoLock auto_lock(lock_); |
| ++js_engine_count_; |
| } |
| |
| void JSCEngineDestroyed() { |
| base::AutoLock auto_lock(lock_); |
| --js_engine_count_; |
| } |
| |
| private: |
| friend struct StaticMemorySingletonTraits<JSCEngineStats>; |
| |
| void Update() { |
| base::AutoLock auto_lock(lock_); |
| if (js_engine_count_ > 0) { |
| js_memory_ = OSAllocator::getCurrentBytesAllocated(); |
| } |
| } |
| |
| base::Lock lock_; |
| base::CVal<size_t, base::CValPublic> js_memory_; |
| base::CVal<size_t> js_engine_count_; |
| scoped_ptr<base::PollerWithThread> poller_; |
| }; |
| |
| JSCEngineStats::JSCEngineStats() |
| : js_memory_("Memory.JS", 0, |
| "Total memory occupied by the JSC page allocator."), |
| js_engine_count_("Count.JS.Engine", 0, |
| "Total JavaScript engine registered.") { |
| poller_.reset(new base::PollerWithThread( |
| base::Bind(&JSCEngineStats::Update, base::Unretained(this)), |
| base::TimeDelta::FromMilliseconds(kPollerPeriodMs))); |
| } |
| |
| } // namespace |
| |
| JSCEngine::JSCEngine() { |
| global_data_ = JSC::JSGlobalData::create(JSC::LargeHeap); |
| JSCEngineStats::GetInstance()->JSCEngineCreated(); |
| } |
| |
| JSCEngine::~JSCEngine() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| JSCEngineStats::GetInstance()->JSCEngineDestroyed(); |
| script_object_registry_.ClearEntries(); |
| } |
| |
| scoped_refptr<GlobalEnvironment> JSCEngine::CreateGlobalEnvironment() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| return new JSCGlobalEnvironment(this); |
| } |
| |
| void JSCEngine::CollectGarbage() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| JSC::JSLockHolder lock(global_data_.get()); |
| DCHECK(global_data_->heap.isSafeToCollect()); |
| global_data_->heap.collectAllGarbage(); |
| } |
| |
| void JSCEngine::ReportExtraMemoryCost(size_t bytes) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| JSC::JSLockHolder lock(global_data_.get()); |
| global_data_->heap.reportExtraMemoryCost(bytes); |
| } |
| |
| } // namespace javascriptcore |
| |
| scoped_ptr<JavaScriptEngine> JavaScriptEngine::CreateEngine() { |
| // Documentation in InitializeThreading.h states this function should be |
| // called from the main thread. However, calling it here from the thread each |
| // engine is created on appears to show no difference in practice. |
| JSC::initializeThreading(); |
| |
| // There must be at most one JSGlobalData instance created per thread. |
| scoped_ptr<javascriptcore::JSCEngine> engine(new javascriptcore::JSCEngine()); |
| |
| // Global data should be of Default type - one per thread. |
| DCHECK(!engine->global_data()->usingAPI()); |
| |
| return engine.PassAs<JavaScriptEngine>(); |
| } |
| |
| } // namespace script |
| } // namespace cobalt |