// 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,
    kLengthIndex,  // Number of context variables for contexts, -1 otherwise.
    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_
