// Copyright 2017 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_OBJECTS_FRAME_ARRAY_H_
#define V8_OBJECTS_FRAME_ARRAY_H_

#include "src/objects.h"
#include "src/wasm/wasm-objects.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

template <typename T>
class Handle;

#define FRAME_ARRAY_FIELD_LIST(V)     \
  V(WasmInstance, WasmInstanceObject) \
  V(WasmFunctionIndex, Smi)           \
  V(IsWasmInterpreterFrame, Smi)      \
  V(Receiver, Object)                 \
  V(Function, JSFunction)             \
  V(Code, AbstractCode)               \
  V(Offset, Smi)                      \
  V(Flags, Smi)

// Container object for data collected during simple stack trace captures.
class FrameArray : public FixedArray {
 public:
#define DECL_FRAME_ARRAY_ACCESSORS(name, type) \
  inline type* name(int frame_ix) const;       \
  inline void Set##name(int frame_ix, type* value);
  FRAME_ARRAY_FIELD_LIST(DECL_FRAME_ARRAY_ACCESSORS)
#undef DECL_FRAME_ARRAY_ACCESSORS

  inline bool IsWasmFrame(int frame_ix) const;
  inline bool IsWasmInterpretedFrame(int frame_ix) const;
  inline bool IsAsmJsWasmFrame(int frame_ix) const;
  inline int FrameCount() const;

  void ShrinkToFit();

  // Flags.
  enum Flag {
    kIsWasmFrame = 1 << 0,
    kIsWasmInterpretedFrame = 1 << 1,
    kIsAsmJsWasmFrame = 1 << 2,
    kIsStrict = 1 << 3,
    kIsConstructor = 1 << 4,
    kAsmJsAtNumberConversion = 1 << 5
  };

  static Handle<FrameArray> AppendJSFrame(Handle<FrameArray> in,
                                          Handle<Object> receiver,
                                          Handle<JSFunction> function,
                                          Handle<AbstractCode> code, int offset,
                                          int flags);
  static Handle<FrameArray> AppendWasmFrame(
      Handle<FrameArray> in, Handle<WasmInstanceObject> wasm_instance,
      int wasm_function_index, WasmCodeWrapper code, int offset, int flags);

  DECL_CAST(FrameArray)

 private:
  // The underlying fixed array embodies a captured stack trace. Frame i
  // occupies indices
  //
  // kFirstIndex + 1 + [i * kElementsPerFrame, (i + 1) * kElementsPerFrame[,
  //
  // with internal offsets as below:

  static const int kWasmInstanceOffset = 0;
  static const int kWasmFunctionIndexOffset = 1;
  static const int kIsWasmInterpreterFrameOffset = 2;

  static const int kReceiverOffset = 0;
  static const int kFunctionOffset = 1;

  static const int kCodeOffset = 2;
  static const int kOffsetOffset = 3;

  static const int kFlagsOffset = 4;

  static const int kElementsPerFrame = 5;

  // Array layout indices.

  static const int kFrameCountIndex = 0;
  static const int kFirstIndex = 1;

  static int LengthFor(int frame_count) {
    return kFirstIndex + frame_count * kElementsPerFrame;
  }

  static Handle<FrameArray> EnsureSpace(Handle<FrameArray> array, int length);

  friend class Factory;
  DISALLOW_IMPLICIT_CONSTRUCTORS(FrameArray);
};

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_FRAME_ARRAY_H_
