| // 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_(nullptr) {} | |
| intptr_t ArgumentCount() const { | |
| return kFieldsStartIndex + kFieldEntrySize * field_count_; | |
| } | |
| ObjectPtr object(); | |
| // Fill object with actual field values. | |
| void Fill(); | |
| private: | |
| enum { | |
| kClassIndex = 0, | |
| // For closure: encoded length and flags. | |
| // For contexts: number of context variables. | |
| // For arrays and typed data objects: number of elements. | |
| // For records: shape. | |
| // -1 otherwise. | |
| kLengthOrShapeIndex, | |
| 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 GetLengthOrShape() const { return GetArg(kLengthOrShapeIndex); } | |
| 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_ |