// Copyright (c) 2013, 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_DEFERRED_OBJECTS_H_
#define RUNTIME_VM_DEFERRED_OBJECTS_H_

#include "platform/globals.h"
#include "vm/tagged_pointer.h"

namespace dart {

// Forward declarations.
class Object;
class DeoptContext;

// Used by the deoptimization infrastructure to defer allocation of
// unboxed objects until frame is fully rewritten and GC is safe.
// Describes a stack slot that should be populated with a reference to
// the materialized object.
class DeferredSlot {
 public:
  DeferredSlot(ObjectPtr* slot, DeferredSlot* next)
      : slot_(slot), next_(next) {}
  virtual ~DeferredSlot() {}

  ObjectPtr* slot() const { return slot_; }
  DeferredSlot* next() const { return next_; }

  virtual void Materialize(DeoptContext* deopt_context) = 0;

 private:
  ObjectPtr* const slot_;
  DeferredSlot* const next_;

  DISALLOW_COPY_AND_ASSIGN(DeferredSlot);
};

class DeferredDouble : public DeferredSlot {
 public:
  DeferredDouble(double value, ObjectPtr* slot, DeferredSlot* next)
      : DeferredSlot(slot, next), value_(value) {}

  virtual void Materialize(DeoptContext* deopt_context);

  double value() const { return value_; }

 private:
  const double value_;

  DISALLOW_COPY_AND_ASSIGN(DeferredDouble);
};

class DeferredMint : public DeferredSlot {
 public:
  DeferredMint(int64_t value, ObjectPtr* slot, DeferredSlot* next)
      : DeferredSlot(slot, next), value_(value) {}

  virtual void Materialize(DeoptContext* deopt_context);

  int64_t value() const { return value_; }

 private:
  const int64_t value_;

  DISALLOW_COPY_AND_ASSIGN(DeferredMint);
};

class DeferredFloat32x4 : public DeferredSlot {
 public:
  DeferredFloat32x4(simd128_value_t value, ObjectPtr* slot, DeferredSlot* next)
      : DeferredSlot(slot, next), value_(value) {}

  virtual void Materialize(DeoptContext* deopt_context);

  simd128_value_t value() const { return value_; }

 private:
  const simd128_value_t value_;

  DISALLOW_COPY_AND_ASSIGN(DeferredFloat32x4);
};

class DeferredFloat64x2 : public DeferredSlot {
 public:
  DeferredFloat64x2(simd128_value_t value, ObjectPtr* slot, DeferredSlot* next)
      : DeferredSlot(slot, next), value_(value) {}

  virtual void Materialize(DeoptContext* deopt_context);

  simd128_value_t value() const { return value_; }

 private:
  const simd128_value_t value_;

  DISALLOW_COPY_AND_ASSIGN(DeferredFloat64x2);
};

class DeferredInt32x4 : public DeferredSlot {
 public:
  DeferredInt32x4(simd128_value_t value, ObjectPtr* slot, DeferredSlot* next)
      : DeferredSlot(slot, next), value_(value) {}

  virtual void Materialize(DeoptContext* deopt_context);

  simd128_value_t value() const { return value_; }

 private:
  const simd128_value_t value_;

  DISALLOW_COPY_AND_ASSIGN(DeferredInt32x4);
};

// Describes a slot that contains a reference to an object that had its
// allocation removed by AllocationSinking pass.
// Object itself is described and materialized by DeferredObject.
class DeferredObjectRef : public DeferredSlot {
 public:
  DeferredObjectRef(intptr_t index, ObjectPtr* slot, DeferredSlot* next)
      : DeferredSlot(slot, next), index_(index) {}

  virtual void Materialize(DeoptContext* deopt_context);

  intptr_t index() const { return index_; }

 private:
  const intptr_t index_;

  DISALLOW_COPY_AND_ASSIGN(DeferredObjectRef);
};

class DeferredRetAddr : public DeferredSlot {
 public:
  DeferredRetAddr(intptr_t index,
                  intptr_t deopt_id,
                  ObjectPtr* slot,
                  DeferredSlot* next)
      : DeferredSlot(slot, next), index_(index), deopt_id_(deopt_id) {}

  virtual void Materialize(DeoptContext* deopt_context);

  intptr_t index() const { return index_; }

 private:
  const intptr_t index_;
  const intptr_t deopt_id_;

  DISALLOW_COPY_AND_ASSIGN(DeferredRetAddr);
};

class DeferredPcMarker : public DeferredSlot {
 public:
  DeferredPcMarker(intptr_t index, ObjectPtr* slot, DeferredSlot* next)
      : DeferredSlot(slot, next), index_(index) {}

  virtual void Materialize(DeoptContext* deopt_context);

  intptr_t index() const { return index_; }

 private:
  const intptr_t index_;

  DISALLOW_COPY_AND_ASSIGN(DeferredPcMarker);
};

class DeferredPp : public DeferredSlot {
 public:
  DeferredPp(intptr_t index, ObjectPtr* slot, DeferredSlot* next)
      : DeferredSlot(slot, next), index_(index) {}

  virtual void Materialize(DeoptContext* deopt_context);

  intptr_t index() const { return index_; }

 private:
  const intptr_t index_;

  DISALLOW_COPY_AND_ASSIGN(DeferredPp);
};

// Describes an object which allocation was removed by AllocationSinking pass.
// Arguments for materialization are stored as a part of expression stack
// for the bottommost deoptimized frame so that GC could discover them.
// They will be removed from the stack at the very end of deoptimization.
class DeferredObject {
 public:
  DeferredObject(intptr_t field_count, intptr_t* args)
      : field_count_(field_count),
        args_(reinterpret_cast<ObjectPtr*>(args)),
        object_(NULL) {}

  intptr_t ArgumentCount() const {
    return kFieldsStartIndex + kFieldEntrySize * field_count_;
  }

  ObjectPtr object();

  // Fill object with actual field values.
  void Fill();

 private:
  enum {
    kClassIndex = 0,

    // Number of context variables for contexts,
    // number of elements for arrays and typed data objects,
    // -1 otherwise.
    kLengthIndex,

    kFieldsStartIndex
  };

  enum {
    kOffsetIndex = 0,
    kValueIndex,
    kFieldEntrySize,
  };

  // Allocate the object but keep its fields null-initialized. Actual field
  // values will be filled later by the Fill method. This separation between
  // allocation and filling is needed because dematerialized objects form
  // a graph which can contain cycles.
  void Create();

  ObjectPtr GetArg(intptr_t index) const { return args_[index]; }

  ObjectPtr GetClass() const { return GetArg(kClassIndex); }

  ObjectPtr GetLength() const { return GetArg(kLengthIndex); }

  ObjectPtr GetFieldOffset(intptr_t index) const {
    return GetArg(kFieldsStartIndex + kFieldEntrySize * index + kOffsetIndex);
  }

  ObjectPtr GetValue(intptr_t index) const {
    return GetArg(kFieldsStartIndex + kFieldEntrySize * index + kValueIndex);
  }

  // Amount of fields that have to be initialized.
  const intptr_t field_count_;

  // Pointer to the first materialization argument on the stack.
  // The first argument is Class of the instance to materialize followed by
  // Field, value pairs.
  ObjectPtr* args_;

  // Object materialized from this description.
  const Object* object_;

  DISALLOW_COPY_AND_ASSIGN(DeferredObject);
};

}  // namespace dart

#endif  // RUNTIME_VM_DEFERRED_OBJECTS_H_
