Skip to content

Commit 3ec7cf9

Browse files
alexmarkovCommit Bot
authored and
Commit Bot
committed
[vm] Record literals
TEST=language/record_literal_test Issue: #49719 Change-Id: I287586c0adb19fe401d76c7a586133a1fe9f1d1d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/257264 Commit-Queue: Alexander Markov <[email protected]> Reviewed-by: Ryan Macnak <[email protected]>
1 parent c94103a commit 3ec7cf9

34 files changed

+1322
-1009
lines changed

runtime/vm/compiler/assembler/assembler_arm.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,13 @@ class Assembler : public AssemblerBase {
834834
void AddRegisters(Register dest, Register src) {
835835
add(dest, dest, Operand(src));
836836
}
837+
void AddScaled(Register dest,
838+
Register src,
839+
ScaleFactor scale,
840+
int32_t value) {
841+
LoadImmediate(dest, value);
842+
add(dest, dest, Operand(src, LSL, scale));
843+
}
837844
void SubImmediate(Register rd,
838845
Register rn,
839846
int32_t value,

runtime/vm/compiler/assembler/assembler_arm64.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,13 @@ class Assembler : public AssemblerBase {
18201820
void AddRegisters(Register dest, Register src) {
18211821
add(dest, dest, Operand(src));
18221822
}
1823+
void AddScaled(Register dest,
1824+
Register src,
1825+
ScaleFactor scale,
1826+
int32_t value) {
1827+
LoadImmediate(dest, value);
1828+
add(dest, dest, Operand(src, LSL, scale));
1829+
}
18231830
void SubImmediateSetFlags(Register dest,
18241831
Register rn,
18251832
int64_t imm,

runtime/vm/compiler/assembler/assembler_ia32.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,12 @@ class Assembler : public AssemblerBase {
728728
void AddRegisters(Register dest, Register src) {
729729
addl(dest, src);
730730
}
731+
void AddScaled(Register dest,
732+
Register src,
733+
ScaleFactor scale,
734+
int32_t value) {
735+
leal(dest, Address(src, scale, value));
736+
}
731737

732738
void SubImmediate(Register reg, const Immediate& imm);
733739
void SubRegisters(Register dest, Register src) {

runtime/vm/compiler/assembler/assembler_riscv.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,13 @@ class Assembler : public MicroAssembler {
943943
void AddRegisters(Register dest, Register src) {
944944
add(dest, dest, src);
945945
}
946+
void AddScaled(Register dest,
947+
Register src,
948+
ScaleFactor scale,
949+
int32_t value) {
950+
slli(dest, src, scale);
951+
addi(dest, dest, value);
952+
}
946953
void SubRegisters(Register dest, Register src) {
947954
sub(dest, dest, src);
948955
}

runtime/vm/compiler/assembler/assembler_x64.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,12 @@ class Assembler : public AssemblerBase {
767767
void AddRegisters(Register dest, Register src) {
768768
addq(dest, src);
769769
}
770+
void AddScaled(Register dest,
771+
Register src,
772+
ScaleFactor scale,
773+
int32_t value) {
774+
leaq(dest, Address(src, scale, value));
775+
}
770776
void AddImmediate(Register dest, Register src, int32_t value);
771777
void AddImmediate(const Address& address, const Immediate& imm);
772778
void SubImmediate(Register reg,

runtime/vm/compiler/backend/constant_propagator.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,10 @@ void ConstantPropagator::VisitAllocateClosure(AllocateClosureInstr* instr) {
938938
SetValue(instr, non_constant_);
939939
}
940940

941+
void ConstantPropagator::VisitAllocateRecord(AllocateRecordInstr* instr) {
942+
SetValue(instr, non_constant_);
943+
}
944+
941945
void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) {
942946
SetValue(instr, non_constant_);
943947
}

runtime/vm/compiler/backend/il.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7401,6 +7401,26 @@ void SuspendInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
74017401
#endif
74027402
}
74037403

7404+
LocationSummary* AllocateRecordInstr::MakeLocationSummary(Zone* zone,
7405+
bool opt) const {
7406+
const intptr_t kNumInputs = 0;
7407+
const intptr_t kNumTemps = 0;
7408+
LocationSummary* locs = new (zone)
7409+
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
7410+
locs->set_out(0, Location::RegisterLocation(AllocateRecordABI::kResultReg));
7411+
return locs;
7412+
}
7413+
7414+
void AllocateRecordInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
7415+
const Code& stub = Code::ZoneHandle(
7416+
compiler->zone(),
7417+
compiler->isolate_group()->object_store()->allocate_record_stub());
7418+
__ LoadImmediate(AllocateRecordABI::kNumFieldsReg, num_fields());
7419+
__ LoadObject(AllocateRecordABI::kFieldNamesReg, field_names());
7420+
compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
7421+
locs(), deopt_id(), env());
7422+
}
7423+
74047424
#undef __
74057425

74067426
} // namespace dart

runtime/vm/compiler/backend/il.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ struct InstrAttrs {
457457
M(CreateArray, _) \
458458
M(AllocateObject, _) \
459459
M(AllocateClosure, _) \
460+
M(AllocateRecord, _) \
460461
M(AllocateTypedData, _) \
461462
M(LoadField, _) \
462463
M(LoadUntagged, kNoGC) \
@@ -6992,6 +6993,46 @@ class AllocateUninitializedContextInstr : public TemplateAllocation<0> {
69926993
DISALLOW_COPY_AND_ASSIGN(AllocateUninitializedContextInstr);
69936994
};
69946995

6996+
// Allocates and null initializes a record object.
6997+
class AllocateRecordInstr : public TemplateAllocation<0> {
6998+
public:
6999+
AllocateRecordInstr(const InstructionSource& source,
7000+
intptr_t num_fields,
7001+
const Array& field_names,
7002+
intptr_t deopt_id)
7003+
: TemplateAllocation(source, deopt_id),
7004+
num_fields_(num_fields),
7005+
field_names_(field_names) {
7006+
ASSERT(field_names.IsNotTemporaryScopedHandle());
7007+
ASSERT(field_names.IsCanonical());
7008+
}
7009+
7010+
DECLARE_INSTRUCTION(AllocateRecord)
7011+
virtual CompileType ComputeType() const;
7012+
7013+
intptr_t num_fields() const { return num_fields_; }
7014+
const Array& field_names() const { return field_names_; }
7015+
7016+
virtual bool HasUnknownSideEffects() const { return false; }
7017+
7018+
virtual bool WillAllocateNewOrRemembered() const {
7019+
return Heap::IsAllocatableInNewSpace(
7020+
compiler::target::Record::InstanceSize(num_fields_));
7021+
}
7022+
7023+
#define FIELD_LIST(F) \
7024+
F(const intptr_t, num_fields_) \
7025+
F(const Array&, field_names_)
7026+
7027+
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(AllocateRecordInstr,
7028+
TemplateAllocation,
7029+
FIELD_LIST)
7030+
#undef FIELD_LIST
7031+
7032+
private:
7033+
DISALLOW_COPY_AND_ASSIGN(AllocateRecordInstr);
7034+
};
7035+
69957036
// This instruction captures the state of the object which had its allocation
69967037
// removed during the AllocationSinking pass.
69977038
// It does not produce any real code only deoptimization information.

runtime/vm/compiler/backend/il_serializer.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2181,6 +2181,9 @@ void Slot::Write(FlowGraphSerializer* s) const {
21812181
case Kind::kArrayElement:
21822182
s->Write<intptr_t>(offset_in_bytes_);
21832183
break;
2184+
case Kind::kRecordField:
2185+
s->Write<intptr_t>(offset_in_bytes_);
2186+
break;
21842187
case Kind::kCapturedVariable:
21852188
s->Write<int8_t>(flags_);
21862189
s->Write<intptr_t>(offset_in_bytes_);
@@ -2224,6 +2227,12 @@ const Slot& Slot::Read(FlowGraphDeserializer* d) {
22242227
offset = d->Read<intptr_t>();
22252228
data = ":array_element";
22262229
break;
2230+
case Kind::kRecordField:
2231+
flags = IsNullableBit::encode(true) |
2232+
IsCompressedBit::encode(Record::ContainsCompressedPointers());
2233+
offset = d->Read<intptr_t>();
2234+
data = ":record_field";
2235+
break;
22272236
case Kind::kCapturedVariable:
22282237
flags = d->Read<int8_t>();
22292238
offset = d->Read<intptr_t>();

runtime/vm/compiler/backend/range_analysis.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2780,6 +2780,7 @@ void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) {
27802780

27812781
case Slot::Kind::kDartField:
27822782
case Slot::Kind::kCapturedVariable:
2783+
case Slot::Kind::kRecordField:
27832784
// Use default value.
27842785
Definition::InferRange(analysis, range);
27852786
break;

runtime/vm/compiler/backend/slot.cc

Lines changed: 11 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -46,61 +46,6 @@ class SlotCache : public ZoneAllocated {
4646
PointerSet<const Slot> fields_;
4747
};
4848

49-
#define NATIVE_SLOT_NAME(C, F) Kind::k##C##_##F
50-
#define NATIVE_TO_STR(C, F) #C "_" #F
51-
52-
const char* Slot::KindToCString(Kind k) {
53-
switch (k) {
54-
#define NATIVE_CASE(C, __, F, ___, ____) \
55-
case NATIVE_SLOT_NAME(C, F): \
56-
return NATIVE_TO_STR(C, F);
57-
NATIVE_SLOTS_LIST(NATIVE_CASE)
58-
#undef NATIVE_CASE
59-
case Kind::kTypeArguments:
60-
return "TypeArguments";
61-
case Kind::kArrayElement:
62-
return "ArrayElement";
63-
case Kind::kCapturedVariable:
64-
return "CapturedVariable";
65-
case Kind::kDartField:
66-
return "DartField";
67-
default:
68-
UNREACHABLE();
69-
return nullptr;
70-
}
71-
}
72-
73-
bool Slot::ParseKind(const char* str, Kind* out) {
74-
ASSERT(str != nullptr && out != nullptr);
75-
#define NATIVE_CASE(C, __, F, ___, ____) \
76-
if (strcmp(str, NATIVE_TO_STR(C, F)) == 0) { \
77-
*out = NATIVE_SLOT_NAME(C, F); \
78-
return true; \
79-
}
80-
NATIVE_SLOTS_LIST(NATIVE_CASE)
81-
#undef NATIVE_CASE
82-
if (strcmp(str, "TypeArguments") == 0) {
83-
*out = Kind::kTypeArguments;
84-
return true;
85-
}
86-
if (strcmp(str, "ArrayElement") == 0) {
87-
*out = Kind::kArrayElement;
88-
return true;
89-
}
90-
if (strcmp(str, "CapturedVariable") == 0) {
91-
*out = Kind::kCapturedVariable;
92-
return true;
93-
}
94-
if (strcmp(str, "DartField") == 0) {
95-
*out = Kind::kDartField;
96-
return true;
97-
}
98-
return false;
99-
}
100-
101-
#undef NATIVE_TO_STR
102-
#undef NATIVE_SLOT_NAME
103-
10449
static classid_t GetUnboxedNativeSlotCid(Representation rep) {
10550
// Currently we only support integer unboxed fields.
10651
if (RepresentationUtils::IsUnboxedInteger(rep)) {
@@ -243,6 +188,7 @@ bool Slot::IsImmutableLengthSlot() const {
243188
case Slot::Kind::kFunctionType_named_parameter_names:
244189
case Slot::Kind::kFunctionType_parameter_types:
245190
case Slot::Kind::kFunctionType_type_parameters:
191+
case Slot::Kind::kRecordField:
246192
case Slot::Kind::kSuspendState_function_data:
247193
case Slot::Kind::kSuspendState_then_callback:
248194
case Slot::Kind::kSuspendState_error_callback:
@@ -345,6 +291,15 @@ const Slot& Slot::GetArrayElementSlot(Thread* thread,
345291
/*static_type=*/nullptr, kTagged);
346292
}
347293

294+
const Slot& Slot::GetRecordFieldSlot(Thread* thread, intptr_t offset_in_bytes) {
295+
return GetCanonicalSlot(
296+
thread, Kind::kRecordField,
297+
IsNullableBit::encode(true) |
298+
IsCompressedBit::encode(Record::ContainsCompressedPointers()),
299+
kDynamicCid, offset_in_bytes, ":record_field",
300+
/*static_type=*/nullptr, kTagged);
301+
}
302+
348303
const Slot& Slot::GetCanonicalSlot(Thread* thread,
349304
Slot::Kind kind,
350305
int8_t flags,
@@ -567,6 +522,7 @@ bool Slot::Equals(const Slot& other) const {
567522
case Kind::kTypeArguments:
568523
case Kind::kTypeArgumentsIndex:
569524
case Kind::kArrayElement:
525+
case Kind::kRecordField:
570526
return true;
571527

572528
case Kind::kCapturedVariable:

runtime/vm/compiler/backend/slot.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ class Slot : public ZoneAllocated {
248248
// Only used during allocation sinking and in MaterializeObjectInstr.
249249
kArrayElement,
250250

251+
// A slot corresponding to a record field at the given offset.
252+
kRecordField,
253+
251254
// A slot within a Context object that contains a value of a captured
252255
// local variable.
253256
kCapturedVariable,
@@ -257,9 +260,6 @@ class Slot : public ZoneAllocated {
257260
};
258261
// clang-format on
259262

260-
static const char* KindToCString(Kind k);
261-
static bool ParseKind(const char* str, Kind* k);
262-
263263
// Returns a slot that represents length field for the given [array_cid].
264264
static const Slot& GetLengthFieldForArrayCid(intptr_t array_cid);
265265

@@ -278,6 +278,12 @@ class Slot : public ZoneAllocated {
278278
static const Slot& GetArrayElementSlot(Thread* thread,
279279
intptr_t offset_in_bytes);
280280

281+
// Returns a slot corresponding to a record field at [offset_in_bytes].
282+
// TODO(dartbug.com/49719): distinguish slots of records with different
283+
// shapes.
284+
static const Slot& GetRecordFieldSlot(Thread* thread,
285+
intptr_t offset_in_bytes);
286+
281287
// Returns a slot that represents the given captured local variable.
282288
static const Slot& GetContextVariableSlotFor(Thread* thread,
283289
const LocalVariable& var);
@@ -301,6 +307,9 @@ class Slot : public ZoneAllocated {
301307
bool IsTypeArguments() const { return kind() == Kind::kTypeArguments; }
302308
bool IsArgumentOfType() const { return kind() == Kind::kTypeArgumentsIndex; }
303309
bool IsArrayElement() const { return kind() == Kind::kArrayElement; }
310+
bool IsRecordField() const {
311+
return kind() == Kind::kRecordField;
312+
}
304313
bool IsImmutableLengthSlot() const;
305314

306315
const char* Name() const;

runtime/vm/compiler/backend/type_propagator.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,6 +1649,10 @@ CompileType AllocateClosureInstr::ComputeType() const {
16491649
return CompileType::FromCid(kClosureCid);
16501650
}
16511651

1652+
CompileType AllocateRecordInstr::ComputeType() const {
1653+
return CompileType::FromCid(kRecordCid);
1654+
}
1655+
16521656
CompileType LoadUntaggedInstr::ComputeType() const {
16531657
return CompileType::Dynamic();
16541658
}

runtime/vm/compiler/frontend/base_flow_graph_builder.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,15 @@ Fragment BaseFlowGraphBuilder::CreateArray() {
933933
return Fragment(array);
934934
}
935935

936+
Fragment BaseFlowGraphBuilder::AllocateRecord(TokenPosition position,
937+
intptr_t num_fields,
938+
const Array& field_names) {
939+
AllocateRecordInstr* allocate = new (Z) AllocateRecordInstr(
940+
InstructionSource(position), num_fields, field_names, GetNextDeoptId());
941+
Push(allocate);
942+
return Fragment(allocate);
943+
}
944+
936945
Fragment BaseFlowGraphBuilder::AllocateTypedData(TokenPosition position,
937946
classid_t class_id) {
938947
Value* num_elements = Pop();

runtime/vm/compiler/frontend/base_flow_graph_builder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ class BaseFlowGraphBuilder {
353353
// Top of the stack should be the closure function.
354354
Fragment AllocateClosure(TokenPosition position = TokenPosition::kNoSource);
355355
Fragment CreateArray();
356+
Fragment AllocateRecord(TokenPosition position,
357+
intptr_t num_fields,
358+
const Array& field_names);
356359
Fragment AllocateTypedData(TokenPosition position, classid_t class_id);
357360
Fragment InstantiateType(const AbstractType& type);
358361
Fragment InstantiateTypeArguments(const TypeArguments& type_arguments);

0 commit comments

Comments
 (0)