| // 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_ |