| // 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" |
| |
| namespace dart { |
| |
| // Forward declarations. |
| class Object; |
| class RawObject; |
| class RawObject; |
| 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(RawObject** slot, DeferredSlot* next) |
| : slot_(slot), next_(next) {} |
| virtual ~DeferredSlot() {} |
| |
| RawObject** slot() const { return slot_; } |
| DeferredSlot* next() const { return next_; } |
| |
| virtual void Materialize(DeoptContext* deopt_context) = 0; |
| |
| private: |
| RawObject** const slot_; |
| DeferredSlot* const next_; |
| |
| DISALLOW_COPY_AND_ASSIGN(DeferredSlot); |
| }; |
| |
| class DeferredDouble : public DeferredSlot { |
| public: |
| DeferredDouble(double value, RawObject** 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, RawObject** 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, RawObject** 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, RawObject** 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, RawObject** 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, RawObject** 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, |
| RawObject** 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, RawObject** 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, RawObject** 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<RawObject**>(args)), |
| object_(NULL) {} |
| |
| intptr_t ArgumentCount() const { |
| return kFieldsStartIndex + kFieldEntrySize * field_count_; |
| } |
| |
| RawObject* 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(); |
| |
| RawObject* GetArg(intptr_t index) const { |
| #if !defined(TARGET_ARCH_DBC) |
| return args_[index]; |
| #else |
| return args_[-index]; |
| #endif |
| } |
| |
| RawObject* GetClass() const { return GetArg(kClassIndex); } |
| |
| RawObject* GetLength() const { return GetArg(kLengthIndex); } |
| |
| RawObject* GetFieldOffset(intptr_t index) const { |
| return GetArg(kFieldsStartIndex + kFieldEntrySize * index + kOffsetIndex); |
| } |
| |
| RawObject* 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. |
| RawObject** args_; |
| |
| // Object materialized from this description. |
| const Object* object_; |
| |
| DISALLOW_COPY_AND_ASSIGN(DeferredObject); |
| }; |
| |
| } // namespace dart |
| |
| #endif // RUNTIME_VM_DEFERRED_OBJECTS_H_ |