// 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-45/opaque_root_tracker.h"

#include <utility>
#include <vector>

#include "cobalt/script/mozjs-45/weak_heap_object.h"
#include "third_party/mozjs-45/js/src/jsapi.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());
    JSObject* to_proxy = to->js_object_proxy();
    DCHECK(to_proxy);
    JS::RootedValue to_value(context_, JS::ObjectValue(*to_proxy));
    referenced_objects_.push_back(
        std::make_pair(from_key, WeakHeapObject(context_, to_value)));
    referenced_object_map_->AddReferencedObject(from_key, to_value);
  }

  ~OpaqueRootStateImpl() {
    JSAutoRequest auto_request(context_);
    for (ReferencedObjectPairVector::iterator it = referenced_objects_.begin();
         it != referenced_objects_.end(); ++it) {
      WeakHeapObject &value = it->second;
      if (value.IsGcThing() && !value.WasCollected()) {
        JS::RootedValue reachable_value(context_, it->second.GetValue());
        referenced_object_map_->RemoveReferencedObject(it->first,
                                                       reachable_value);
      }
    }
  }

 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* wrapper_private = *it;
    TrackReachabilityToOpaqueRoot(state.get(), wrapper_private);
    TrackReachableWrappables(state.get(), wrapper_private);
  }
  return state.PassAs<OpaqueRootState>();
}

void OpaqueRootTracker::TrackReachabilityToOpaqueRoot(
    OpaqueRootState* state, WrapperPrivate* wrapper_private) {
  OpaqueRootStateImpl* state_impl =
      base::polymorphic_downcast<OpaqueRootStateImpl*>(state);
  // If this wrappable has an opaque root, track reachability between this
  // wrappable and its root.
  Wrappable* opaque_root = 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_impl->TrackReachability(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 (wrapper_private->ShouldKeepWrapperAliveIfReachable()) {
      state_impl->TrackReachability(opaque_root_private, wrapper_private);
    }
  }
}

void OpaqueRootTracker::TrackReachableWrappables(
    OpaqueRootState* state, WrapperPrivate* wrapper_private) {
  OpaqueRootStateImpl* state_impl =
      base::polymorphic_downcast<OpaqueRootStateImpl*>(state);
  // Track any wrappables that are explicitly marked as reachable from
  // this wrappable.
  typedef std::vector<Wrappable*> WrappableVector;
  WrappableVector reachable_objects;
  wrapper_private->GetReachableWrappables(&reachable_objects);
  for (size_t i = 0; i < reachable_objects.size(); ++i) {
    WrapperPrivate* reachable_object_private = WrapperPrivate::GetFromWrappable(
        reachable_objects[i], context_, wrapper_factory_);
    state_impl->TrackReachability(wrapper_private, reachable_object_private);
  }
}

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