dart-sdk/runtime/vm/deferred_objects.h
Alexander Markov 3675fd25f4 [vm] Packed representation of record shape
The representation of record shape in record instances and record
types is changed from a pair

  int num_fields
  Array field_names

to a single integer - packed bitfield

  int num_fields(16)
  int field_names_index(kSmiBits-16)

where field names index is an index in the array available from
ObjectStore.

With the new representation of record shapes:
1) Size of record instances is reduced.
2) Number of comparisons for a shape test reduced from 2 to 1
(shape test is used during type checks).
3) A few operations removed from Record.hashCode.
4) Type testing stubs (TTS) are now supported for record types with
named fields. Previously it was not possible to check shape of records
with named fields in TTS as TTS cannot access object pool and cannot
load field names array).

TEST=existing

Issue: https://github.com/dart-lang/sdk/issues/49719

Change-Id: I7cdcbb53938aba5d561cd24dc99530395dbbea7e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/276201
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
2022-12-20 20:11:48 +00:00

257 lines
6.8 KiB
C++

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