// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_EXCEPTIONS_H_
#define RUNTIME_VM_EXCEPTIONS_H_

#include "vm/allocation.h"
#include "vm/token_position.h"

namespace dart {

// Forward declarations.
class AbstractType;
class Array;
class DartFrameIterator;
class Error;
class LanguageError;
class Instance;
class Integer;
class RawInstance;
class RawObject;
class RawScript;
class RawStackTrace;
class String;
class Thread;

class Exceptions : AllStatic {
 public:
  static void Throw(Thread* thread, const Instance& exception);
  static void ReThrow(Thread* thread,
                      const Instance& exception,
                      const Instance& stacktrace);
  static void PropagateError(const Error& error);

  // Propagate an error to the entry frame, skipping over Dart frames.
  static void PropagateToEntry(const Error& error);

  // Helpers to create and throw errors.
  static RawStackTrace* CurrentStackTrace();
  static RawScript* GetCallerScript(DartFrameIterator* iterator);
  static RawInstance* NewInstance(const char* class_name);
  static void CreateAndThrowTypeError(TokenPosition location,
                                      const AbstractType& src_type,
                                      const AbstractType& dst_type,
                                      const String& dst_name,
                                      const String& bound_error_msg);

  enum ExceptionType {
    kNone,
    kRange,
    kRangeMsg,
    kArgument,
    kArgumentValue,
    kIntegerDivisionByZeroException,
    kNoSuchMethod,
    kFormat,
    kUnsupported,
    kStackOverflow,
    kOutOfMemory,
    kNullThrown,
    kIsolateSpawn,
    kAssertion,
    kCast,
    kType,
    kFallThrough,
    kAbstractClassInstantiation,
    kCyclicInitializationError,
    kCompileTimeError,
  };

  static void ThrowByType(ExceptionType type, const Array& arguments);
  // Uses the preallocated out of memory exception to avoid calling
  // into Dart code or allocating any code.
  static void ThrowOOM();
  static void ThrowStackOverflow();
  static void ThrowArgumentError(const Instance& arg);
  static void ThrowRangeError(const char* argument_name,
                              const Integer& argument_value,
                              intptr_t expected_from,
                              intptr_t expected_to);
  static void ThrowRangeErrorMsg(const char* msg);
  static void ThrowCompileTimeError(const LanguageError& error);

  // Returns a RawInstance if the exception is successfully created,
  // otherwise returns a RawError.
  static RawObject* Create(ExceptionType type, const Array& arguments);

  static void JumpToFrame(Thread* thread,
                          uword program_counter,
                          uword stack_pointer,
                          uword frame_pointer,
                          bool clear_deopt_at_target);

 private:
  DISALLOW_COPY_AND_ASSIGN(Exceptions);
};

// The index into the ExceptionHandlers table corresponds to
// the try_index of the handler.
struct ExceptionHandlerInfo {
  uint32_t handler_pc_offset;  // PC offset value of handler.
  int16_t outer_try_index;     // Try block index of enclosing try block.
  int8_t needs_stacktrace;     // True if a stacktrace is needed.
  int8_t has_catch_all;        // Catches all exceptions.
  int8_t is_generated;         // True if this is a generated handler.
};

class CatchEntryState {
 public:
  enum { kCatchEntryStateIsMove = 1, kCatchEntryStateDestShift = 1 };

  CatchEntryState() : data_(NULL), ref_count_(NULL) {}
  explicit CatchEntryState(intptr_t* data)
      : data_(data), ref_count_(new intptr_t(1)) {}

  CatchEntryState(const CatchEntryState& state) { Copy(state); }

  ~CatchEntryState() { Destroy(); }

  CatchEntryState& operator=(const CatchEntryState& state) {
    Destroy();
    Copy(state);
    return *this;
  }

  bool Empty() { return ref_count_ == NULL; }

  intptr_t Pairs() { return data_[0]; }

  intptr_t Src(intptr_t i) { return data_[1 + 2 * i]; }

  intptr_t Dest(intptr_t i) {
    return data_[2 + 2 * i] >> kCatchEntryStateDestShift;
  }

  bool isMove(intptr_t i) { return data_[2 + 2 * i] & kCatchEntryStateIsMove; }

 private:
  void Destroy() {
    if (ref_count_ != NULL) {
      (*ref_count_)--;
      if (*ref_count_ == 0) {
        delete ref_count_;
        delete[] data_;
      }
    }
  }

  void Copy(const CatchEntryState& state) {
    data_ = state.data_;
    ref_count_ = state.ref_count_;
    if (ref_count_ != NULL) {
      (*ref_count_)++;
    }
  }

  // data_ has the following format:
  // 0 - number of pairs in this state
  // 1-2 - 1st encoded src,dest pair
  // 3-4 - 2nd pair
  // ....
  intptr_t* data_;
  intptr_t* ref_count_;
};

}  // namespace dart

#endif  // RUNTIME_VM_EXCEPTIONS_H_
