/*
 * Copyright 2016 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/mozjs/opaque_root_tracker.h"

#include <utility>
#include <vector>

#include "cobalt/script/mozjs/weak_heap_object.h"

namespace cobalt {
namespace script {
namespace mozjs {
namespace {
// Implementation of OpaqueRootTracker::OpaqueRootState.
// On creation, this class will register reachability between objects and their
// roots in |ReferencedObjectMap|. On destruction, the reachability
// relationship will be removed.
class OpaqueRootStateImpl : public OpaqueRootTracker::OpaqueRootState {
 public:
  OpaqueRootStateImpl(JSContext* context,
                      ReferencedObjectMap* referenced_object_map)
      : context_(context), referenced_object_map_(referenced_object_map) {}

  void TrackReachability(WrapperPrivate* from, WrapperPrivate* to) {
    intptr_t from_key = ReferencedObjectMap::GetKeyForWrappable(
        from->wrappable<Wrappable>().get());
    JS::RootedObject to_object(context_, to->js_object_proxy());
    referenced_objects_.push_back(
        std::make_pair(from_key, WeakHeapObject(context_, to_object)));
    referenced_object_map_->AddReferencedObject(from_key, to_object);
  }

  ~OpaqueRootStateImpl() {
    for (ReferencedObjectPairVector::iterator it = referenced_objects_.begin();
         it != referenced_objects_.end(); ++it) {
      if (it->second.Get()) {
        JS::RootedObject reachable_object(context_, it->second.Get());
        referenced_object_map_->RemoveReferencedObject(it->first,
                                                       reachable_object);
      }
    }
  }

 private:
  typedef std::vector<std::pair<intptr_t, WeakHeapObject> >
      ReferencedObjectPairVector;

  JSContext* context_;
  ReferencedObjectMap* referenced_object_map_;
  ReferencedObjectPairVector referenced_objects_;
};
}  // namespace

OpaqueRootTracker::OpaqueRootTracker(JSContext* context,
                                     ReferencedObjectMap* referenced_object_map,
                                     WrapperFactory* wrapper_factory)
    : context_(context),
      referenced_object_map_(referenced_object_map),
      wrapper_factory_(wrapper_factory) {}

void OpaqueRootTracker::AddObjectWithOpaqueRoot(
    WrapperPrivate* wrapper_private) {
  all_objects_.insert(wrapper_private);
}

void OpaqueRootTracker::RemoveObjectWithOpaqueRoot(
    WrapperPrivate* wrapper_private) {
  all_objects_.erase(wrapper_private);
}

scoped_ptr<OpaqueRootTracker::OpaqueRootState>
OpaqueRootTracker::GetCurrentOpaqueRootState() {
  scoped_ptr<OpaqueRootStateImpl> state(
      new OpaqueRootStateImpl(context_, referenced_object_map_));
  // Get the current opaque root for all objects that are being tracked.
  for (WrapperPrivateSet::iterator it = all_objects_.begin();
       it != all_objects_.end(); ++it) {
    WrapperPrivate* reachable_object_wrapper_private = *it;
    Wrappable* opaque_root = reachable_object_wrapper_private->GetOpaqueRoot();
    if (opaque_root) {
      WrapperPrivate* opaque_root_private = WrapperPrivate::GetFromWrappable(
          opaque_root, context_, wrapper_factory_);
      // Always mark the root as reachable from the non-root object.
      state->TrackReachability(reachable_object_wrapper_private,
                               opaque_root_private);

      // Only mark the non-root object as reachable if we need to keep the
      // wrapper alive for some reason. In general it's okay for a wrapper to
      // get GC'd because the Cobalt object will still be kept alive, and a new
      // JS object can be created if needed again.
      if (reachable_object_wrapper_private
              ->ShouldKeepWrapperAliveIfReachable()) {
        state->TrackReachability(opaque_root_private,
                                 reachable_object_wrapper_private);
      }
    }
  }
  return state.PassAs<OpaqueRootState>();
}

}  // namespace mozjs
}  // namespace script
}  // namespace cobalt
