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