// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef V8_API_H_
#define V8_API_H_

#include "apiutils.h"
#include "factory.h"

#include "../include/v8-testing.h"

namespace v8 {

// Constants used in the implementation of the API.  The most natural thing
// would usually be to place these with the classes that use them, but
// we want to keep them out of v8.h because it is an externally
// visible file.
class Consts {
 public:
  enum TemplateType {
    FUNCTION_TEMPLATE = 0,
    OBJECT_TEMPLATE = 1
  };
};


// Utilities for working with neander-objects, primitive
// env-independent JSObjects used by the api.
class NeanderObject {
 public:
  explicit NeanderObject(int size);
  explicit inline NeanderObject(v8::internal::Handle<v8::internal::Object> obj);
  explicit inline NeanderObject(v8::internal::Object* obj);
  inline v8::internal::Object* get(int index);
  inline void set(int index, v8::internal::Object* value);
  inline v8::internal::Handle<v8::internal::JSObject> value() { return value_; }
  int size();
 private:
  v8::internal::Handle<v8::internal::JSObject> value_;
};


// Utilities for working with neander-arrays, a simple extensible
// array abstraction built on neander-objects.
class NeanderArray {
 public:
  NeanderArray();
  explicit inline NeanderArray(v8::internal::Handle<v8::internal::Object> obj);
  inline v8::internal::Handle<v8::internal::JSObject> value() {
    return obj_.value();
  }

  void add(v8::internal::Handle<v8::internal::Object> value);

  int length();

  v8::internal::Object* get(int index);
  // Change the value at an index to undefined value. If the index is
  // out of bounds, the request is ignored. Returns the old value.
  void set(int index, v8::internal::Object* value);
 private:
  NeanderObject obj_;
};


NeanderObject::NeanderObject(v8::internal::Handle<v8::internal::Object> obj)
    : value_(v8::internal::Handle<v8::internal::JSObject>::cast(obj)) { }


NeanderObject::NeanderObject(v8::internal::Object* obj)
    : value_(v8::internal::Handle<v8::internal::JSObject>(
        v8::internal::JSObject::cast(obj))) { }


NeanderArray::NeanderArray(v8::internal::Handle<v8::internal::Object> obj)
    : obj_(obj) { }


v8::internal::Object* NeanderObject::get(int offset) {
  ASSERT(value()->HasFastElements());
  return v8::internal::FixedArray::cast(value()->elements())->get(offset);
}


void NeanderObject::set(int offset, v8::internal::Object* value) {
  ASSERT(value_->HasFastElements());
  v8::internal::FixedArray::cast(value_->elements())->set(offset, value);
}


template <typename T> static inline T ToCData(v8::internal::Object* obj) {
  STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
  return reinterpret_cast<T>(
      reinterpret_cast<intptr_t>(v8::internal::Proxy::cast(obj)->proxy()));
}


template <typename T>
static inline v8::internal::Handle<v8::internal::Object> FromCData(T obj) {
  STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
  return FACTORY->NewProxy(
      reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj)));
}


class ApiFunction {
 public:
  explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
  v8::internal::Address address() { return addr_; }
 private:
  v8::internal::Address addr_;
};


enum ExtensionTraversalState {
  UNVISITED, VISITED, INSTALLED
};


class RegisteredExtension {
 public:
  explicit RegisteredExtension(Extension* extension);
  static void Register(RegisteredExtension* that);
  Extension* extension() { return extension_; }
  RegisteredExtension* next() { return next_; }
  RegisteredExtension* next_auto() { return next_auto_; }
  ExtensionTraversalState state() { return state_; }
  void set_state(ExtensionTraversalState value) { state_ = value; }
  static RegisteredExtension* first_extension() { return first_extension_; }
 private:
  Extension* extension_;
  RegisteredExtension* next_;
  RegisteredExtension* next_auto_;
  ExtensionTraversalState state_;
  static RegisteredExtension* first_extension_;
};


class Utils {
 public:
  static bool ReportApiFailure(const char* location, const char* message);

  static Local<FunctionTemplate> ToFunctionTemplate(NeanderObject obj);
  static Local<ObjectTemplate> ToObjectTemplate(NeanderObject obj);

  static inline Local<Context> ToLocal(
      v8::internal::Handle<v8::internal::Context> obj);
  static inline Local<Value> ToLocal(
      v8::internal::Handle<v8::internal::Object> obj);
  static inline Local<Function> ToLocal(
      v8::internal::Handle<v8::internal::JSFunction> obj);
  static inline Local<String> ToLocal(
      v8::internal::Handle<v8::internal::String> obj);
  static inline Local<RegExp> ToLocal(
      v8::internal::Handle<v8::internal::JSRegExp> obj);
  static inline Local<Object> ToLocal(
      v8::internal::Handle<v8::internal::JSObject> obj);
  static inline Local<Array> ToLocal(
      v8::internal::Handle<v8::internal::JSArray> obj);
  static inline Local<External> ToLocal(
      v8::internal::Handle<v8::internal::Proxy> obj);
  static inline Local<Message> MessageToLocal(
      v8::internal::Handle<v8::internal::Object> obj);
  static inline Local<StackTrace> StackTraceToLocal(
      v8::internal::Handle<v8::internal::JSArray> obj);
  static inline Local<StackFrame> StackFrameToLocal(
      v8::internal::Handle<v8::internal::JSObject> obj);
  static inline Local<Number> NumberToLocal(
      v8::internal::Handle<v8::internal::Object> obj);
  static inline Local<Integer> IntegerToLocal(
      v8::internal::Handle<v8::internal::Object> obj);
  static inline Local<Uint32> Uint32ToLocal(
      v8::internal::Handle<v8::internal::Object> obj);
  static inline Local<FunctionTemplate> ToLocal(
      v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
  static inline Local<ObjectTemplate> ToLocal(
      v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj);
  static inline Local<Signature> ToLocal(
      v8::internal::Handle<v8::internal::SignatureInfo> obj);
  static inline Local<TypeSwitch> ToLocal(
      v8::internal::Handle<v8::internal::TypeSwitchInfo> obj);

  static inline v8::internal::Handle<v8::internal::TemplateInfo>
      OpenHandle(const Template* that);
  static inline v8::internal::Handle<v8::internal::FunctionTemplateInfo>
      OpenHandle(const FunctionTemplate* that);
  static inline v8::internal::Handle<v8::internal::ObjectTemplateInfo>
      OpenHandle(const ObjectTemplate* that);
  static inline v8::internal::Handle<v8::internal::Object>
      OpenHandle(const Data* data);
  static inline v8::internal::Handle<v8::internal::JSRegExp>
      OpenHandle(const RegExp* data);
  static inline v8::internal::Handle<v8::internal::JSObject>
      OpenHandle(const v8::Object* data);
  static inline v8::internal::Handle<v8::internal::JSArray>
      OpenHandle(const v8::Array* data);
  static inline v8::internal::Handle<v8::internal::String>
      OpenHandle(const String* data);
  static inline v8::internal::Handle<v8::internal::Object>
      OpenHandle(const Script* data);
  static inline v8::internal::Handle<v8::internal::JSFunction>
      OpenHandle(const Function* data);
  static inline v8::internal::Handle<v8::internal::JSObject>
      OpenHandle(const Message* message);
  static inline v8::internal::Handle<v8::internal::JSArray>
      OpenHandle(const StackTrace* stack_trace);
  static inline v8::internal::Handle<v8::internal::JSObject>
      OpenHandle(const StackFrame* stack_frame);
  static inline v8::internal::Handle<v8::internal::Context>
      OpenHandle(const v8::Context* context);
  static inline v8::internal::Handle<v8::internal::SignatureInfo>
      OpenHandle(const v8::Signature* sig);
  static inline v8::internal::Handle<v8::internal::TypeSwitchInfo>
      OpenHandle(const v8::TypeSwitch* that);
  static inline v8::internal::Handle<v8::internal::Proxy>
      OpenHandle(const v8::External* that);
};


template <class T>
static inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
  return reinterpret_cast<T*>(obj.location());
}


template <class T>
v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom(
    v8::HandleScope* scope) {
  v8::internal::Handle<T> handle;
  if (!is_null()) {
    handle = *this;
  }
  return Utils::OpenHandle(*scope->Close(Utils::ToLocal(handle)));
}


// Implementations of ToLocal

#define MAKE_TO_LOCAL(Name, From, To)                                       \
  Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
    ASSERT(obj.is_null() || !obj->IsTheHole());                             \
    return Local<To>(reinterpret_cast<To*>(obj.location()));                \
  }

MAKE_TO_LOCAL(ToLocal, Context, Context)
MAKE_TO_LOCAL(ToLocal, Object, Value)
MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
MAKE_TO_LOCAL(ToLocal, String, String)
MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
MAKE_TO_LOCAL(ToLocal, JSObject, Object)
MAKE_TO_LOCAL(ToLocal, JSArray, Array)
MAKE_TO_LOCAL(ToLocal, Proxy, External)
MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature)
MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch)
MAKE_TO_LOCAL(MessageToLocal, Object, Message)
MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace)
MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
MAKE_TO_LOCAL(NumberToLocal, Object, Number)
MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)

#undef MAKE_TO_LOCAL


// Implementations of OpenHandle

#define MAKE_OPEN_HANDLE(From, To) \
  v8::internal::Handle<v8::internal::To> Utils::OpenHandle(\
    const v8::From* that) { \
    return v8::internal::Handle<v8::internal::To>( \
        reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
  }

MAKE_OPEN_HANDLE(Template, TemplateInfo)
MAKE_OPEN_HANDLE(FunctionTemplate, FunctionTemplateInfo)
MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo)
MAKE_OPEN_HANDLE(Signature, SignatureInfo)
MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo)
MAKE_OPEN_HANDLE(Data, Object)
MAKE_OPEN_HANDLE(RegExp, JSRegExp)
MAKE_OPEN_HANDLE(Object, JSObject)
MAKE_OPEN_HANDLE(Array, JSArray)
MAKE_OPEN_HANDLE(String, String)
MAKE_OPEN_HANDLE(Script, Object)
MAKE_OPEN_HANDLE(Function, JSFunction)
MAKE_OPEN_HANDLE(Message, JSObject)
MAKE_OPEN_HANDLE(Context, Context)
MAKE_OPEN_HANDLE(External, Proxy)
MAKE_OPEN_HANDLE(StackTrace, JSArray)
MAKE_OPEN_HANDLE(StackFrame, JSObject)

#undef MAKE_OPEN_HANDLE


namespace internal {

// Tracks string usage to help make better decisions when
// externalizing strings.
//
// Implementation note: internally this class only tracks fresh
// strings and keeps a single use counter for them.
class StringTracker {
 public:
  // Records that the given string's characters were copied to some
  // external buffer. If this happens often we should honor
  // externalization requests for the string.
  void RecordWrite(Handle<String> string) {
    Address address = reinterpret_cast<Address>(*string);
    Address top = isolate_->heap()->NewSpaceTop();
    if (IsFreshString(address, top)) {
      IncrementUseCount(top);
    }
  }

  // Estimates freshness and use frequency of the given string based
  // on how close it is to the new space top and the recorded usage
  // history.
  inline bool IsFreshUnusedString(Handle<String> string) {
    Address address = reinterpret_cast<Address>(*string);
    Address top = isolate_->heap()->NewSpaceTop();
    return IsFreshString(address, top) && IsUseCountLow(top);
  }

 private:
  StringTracker() : use_count_(0), last_top_(NULL), isolate_(NULL) { }

  static inline bool IsFreshString(Address string, Address top) {
    return top - kFreshnessLimit <= string && string <= top;
  }

  inline bool IsUseCountLow(Address top) {
    if (last_top_ != top) return true;
    return use_count_ < kUseLimit;
  }

  inline void IncrementUseCount(Address top) {
    if (last_top_ != top) {
      use_count_ = 0;
      last_top_ = top;
    }
    ++use_count_;
  }

  // Single use counter shared by all fresh strings.
  int use_count_;

  // Last new space top when the use count above was valid.
  Address last_top_;

  Isolate* isolate_;

  // How close to the new space top a fresh string has to be.
  static const int kFreshnessLimit = 1024;

  // The number of uses required to consider a string useful.
  static const int kUseLimit = 32;

  friend class Isolate;

  DISALLOW_COPY_AND_ASSIGN(StringTracker);
};


// This class is here in order to be able to declare it a friend of
// HandleScope.  Moving these methods to be members of HandleScope would be
// neat in some ways, but it would expose internal implementation details in
// our public header file, which is undesirable.
//
// An isolate has a single instance of this class to hold the current thread's
// data. In multithreaded V8 programs this data is copied in and out of storage
// so that the currently executing thread always has its own copy of this
// data.
ISOLATED_CLASS HandleScopeImplementer {
 public:

  HandleScopeImplementer()
      : blocks_(0),
        entered_contexts_(0),
        saved_contexts_(0),
        spare_(NULL),
        call_depth_(0) { }

  // Threading support for handle data.
  static int ArchiveSpacePerThread();
  char* RestoreThread(char* from);
  char* ArchiveThread(char* to);
  void FreeThreadResources();

  // Garbage collection support.
  void Iterate(v8::internal::ObjectVisitor* v);
  static char* Iterate(v8::internal::ObjectVisitor* v, char* data);


  inline internal::Object** GetSpareOrNewBlock();
  inline void DeleteExtensions(internal::Object** prev_limit);

  inline void IncrementCallDepth() {call_depth_++;}
  inline void DecrementCallDepth() {call_depth_--;}
  inline bool CallDepthIsZero() { return call_depth_ == 0; }

  inline void EnterContext(Handle<Object> context);
  inline bool LeaveLastContext();

  // Returns the last entered context or an empty handle if no
  // contexts have been entered.
  inline Handle<Object> LastEnteredContext();

  inline void SaveContext(Context* context);
  inline Context* RestoreContext();
  inline bool HasSavedContexts();

  inline List<internal::Object**>* blocks() { return &blocks_; }

 private:
  void ResetAfterArchive() {
    blocks_.Initialize(0);
    entered_contexts_.Initialize(0);
    saved_contexts_.Initialize(0);
    spare_ = NULL;
    call_depth_ = 0;
  }

  void Free() {
    ASSERT(blocks_.length() == 0);
    ASSERT(entered_contexts_.length() == 0);
    ASSERT(saved_contexts_.length() == 0);
    blocks_.Free();
    entered_contexts_.Free();
    saved_contexts_.Free();
    if (spare_ != NULL) {
      DeleteArray(spare_);
      spare_ = NULL;
    }
    ASSERT(call_depth_ == 0);
  }

  List<internal::Object**> blocks_;
  // Used as a stack to keep track of entered contexts.
  List<Handle<Object> > entered_contexts_;
  // Used as a stack to keep track of saved contexts.
  List<Context*> saved_contexts_;
  Object** spare_;
  int call_depth_;
  // This is only used for threading support.
  v8::ImplementationUtilities::HandleScopeData handle_scope_data_;

  void IterateThis(ObjectVisitor* v);
  char* RestoreThreadHelper(char* from);
  char* ArchiveThreadHelper(char* to);

  DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer);
};


static const int kHandleBlockSize = v8::internal::KB - 2;  // fit in one page


void HandleScopeImplementer::SaveContext(Context* context) {
  saved_contexts_.Add(context);
}


Context* HandleScopeImplementer::RestoreContext() {
  return saved_contexts_.RemoveLast();
}


bool HandleScopeImplementer::HasSavedContexts() {
  return !saved_contexts_.is_empty();
}


void HandleScopeImplementer::EnterContext(Handle<Object> context) {
  entered_contexts_.Add(context);
}


bool HandleScopeImplementer::LeaveLastContext() {
  if (entered_contexts_.is_empty()) return false;
  entered_contexts_.RemoveLast();
  return true;
}


Handle<Object> HandleScopeImplementer::LastEnteredContext() {
  if (entered_contexts_.is_empty()) return Handle<Object>::null();
  return entered_contexts_.last();
}


// If there's a spare block, use it for growing the current scope.
internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() {
  internal::Object** block = (spare_ != NULL) ?
      spare_ :
      NewArray<internal::Object*>(kHandleBlockSize);
  spare_ = NULL;
  return block;
}


void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
  while (!blocks_.is_empty()) {
    internal::Object** block_start = blocks_.last();
    internal::Object** block_limit = block_start + kHandleBlockSize;
#ifdef DEBUG
    // NoHandleAllocation may make the prev_limit to point inside the block.
    if (block_start <= prev_limit && prev_limit <= block_limit) break;
#else
    if (prev_limit == block_limit) break;
#endif

    blocks_.RemoveLast();
#ifdef DEBUG
    v8::ImplementationUtilities::ZapHandleRange(block_start, block_limit);
#endif
    if (spare_ != NULL) {
      DeleteArray(spare_);
    }
    spare_ = block_start;
  }
  ASSERT((blocks_.is_empty() && prev_limit == NULL) ||
         (!blocks_.is_empty() && prev_limit != NULL));
}


class Testing {
 public:
  static v8::Testing::StressType stress_type() { return stress_type_; }
  static void set_stress_type(v8::Testing::StressType stress_type) {
    stress_type_ = stress_type;
  }

 private:
  static v8::Testing::StressType stress_type_;
};

} }  // namespace v8::internal

#endif  // V8_API_H_
