// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_ALLOCATION_SITE_SCOPES_H_
#define V8_ALLOCATION_SITE_SCOPES_H_

#include "src/handles.h"
#include "src/objects.h"
#include "src/objects/map.h"

namespace v8 {
namespace internal {

// AllocationSiteContext is the base class for walking and copying a nested
// boilerplate with AllocationSite and AllocationMemento support.
class AllocationSiteContext {
 public:
  explicit AllocationSiteContext(Isolate* isolate) {
    isolate_ = isolate;
  }

  Handle<AllocationSite> top() { return top_; }
  Handle<AllocationSite> current() { return current_; }

  bool ShouldCreateMemento(Handle<JSObject> object) { return false; }

  Isolate* isolate() { return isolate_; }

 protected:
  void update_current_site(AllocationSite* site) {
    *(current_.location()) = site;
  }

  void InitializeTraversal(Handle<AllocationSite> site) {
    top_ = site;
    // {current_} is updated in place to not create unnecessary Handles, hence
    // we initially need a separate handle.
    current_ = Handle<AllocationSite>::New(*top_, isolate());
  }

 private:
  Isolate* isolate_;
  Handle<AllocationSite> top_;
  Handle<AllocationSite> current_;
};


// AllocationSiteUsageContext aids in the creation of AllocationMementos placed
// behind some/all components of a copied object literal.
class AllocationSiteUsageContext : public AllocationSiteContext {
 public:
  AllocationSiteUsageContext(Isolate* isolate, Handle<AllocationSite> site,
                             bool activated)
      : AllocationSiteContext(isolate),
        top_site_(site),
        activated_(activated) { }

  inline Handle<AllocationSite> EnterNewScope() {
    if (top().is_null()) {
      InitializeTraversal(top_site_);
    } else {
      // Advance current site
      Object* nested_site = current()->nested_site();
      // Something is wrong if we advance to the end of the list here.
      update_current_site(AllocationSite::cast(nested_site));
    }
    return Handle<AllocationSite>(*current(), isolate());
  }

  inline void ExitScope(Handle<AllocationSite> scope_site,
                        Handle<JSObject> object) {
    // This assert ensures that we are pointing at the right sub-object in a
    // recursive walk of a nested literal.
    DCHECK(object.is_null() || *object == scope_site->boilerplate());
  }

  bool ShouldCreateMemento(Handle<JSObject> object) {
    if (activated_ &&
        AllocationSite::CanTrack(object->map()->instance_type())) {
      if (FLAG_allocation_site_pretenuring ||
          AllocationSite::ShouldTrack(object->GetElementsKind())) {
        if (FLAG_trace_creation_allocation_sites) {
          PrintF("*** Creating Memento for %s %p\n",
                 object->IsJSArray() ? "JSArray" : "JSObject",
                 static_cast<void*>(*object));
        }
        return true;
      }
    }
    return false;
  }

  static const bool kCopying = true;

 private:
  Handle<AllocationSite> top_site_;
  bool activated_;
};


}  // namespace internal
}  // namespace v8

#endif  // V8_ALLOCATION_SITE_SCOPES_H_
