/*
 * 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_.value() > 0) {
      js_memory_ = OSAllocator::getCurrentBytesAllocated();
    }
  }

  base::Lock lock_;
  base::CVal<base::cval::SizeInBytes, 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
