Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(707)

Unified Diff: runtime/vm/intrinsifier.cc

Issue 2235433002: VM: Add more array intrinsics. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: addressed comments Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/flow_graph_inliner.cc ('k') | runtime/vm/method_recognizer.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/intrinsifier.cc
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 15a0fa9275c5e0ae839856f01ee82d33846147c6..93478fc3d866fe8569d7397034f129e31ff5d4ed 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -384,35 +384,8 @@ static void PrepareIndexedOp(BlockBuilder* builder,
Thread::kNoDeoptId));
}
-
-bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* index = builder.AddParameter(1);
- Definition* array = builder.AddParameter(2);
-
- PrepareIndexedOp(&builder, array, index, Array::length_offset());
-
- Definition* result = builder.AddDefinition(
- new LoadIndexedInstr(new Value(array),
- new Value(index),
- Instance::ElementSizeFor(kArrayCid), // index scale
- kArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- builder.AddIntrinsicReturn(new Value(result));
- return true;
-}
-
-
-bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) {
- return Build_ObjectArrayGetIndexed(flow_graph);
-}
-
-
-bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) {
+static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph,
+ intptr_t array_cid) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
TargetEntryInstr* normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
@@ -420,46 +393,70 @@ bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) {
Definition* index = builder.AddParameter(1);
Definition* array = builder.AddParameter(2);
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
- Definition* result = builder.AddDefinition(
- new LoadIndexedInstr(new Value(array),
- new Value(index),
- 1, // index scale
- kTypedDataUint8ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- builder.AddIntrinsicReturn(new Value(result));
- return true;
-}
-
-
-bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* index = builder.AddParameter(1);
- Definition* array = builder.AddParameter(2);
+ intptr_t length_offset = Array::length_offset();
+ if (RawObject::IsTypedDataClassId(array_cid)) {
+ length_offset = TypedData::length_offset();
+ } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ length_offset = ExternalTypedData::length_offset();
+ }
- PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
+ PrepareIndexedOp(&builder, array, index, length_offset);
- Definition* elements = builder.AddDefinition(
+ if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ array = builder.AddDefinition(
new LoadUntaggedInstr(new Value(array),
ExternalTypedData::data_offset()));
+ }
+
Definition* result = builder.AddDefinition(
- new LoadIndexedInstr(new Value(elements),
+ new LoadIndexedInstr(new Value(array),
new Value(index),
- 1, // index scale
- kExternalTypedDataUint8ArrayCid,
+ Instance::ElementSizeFor(array_cid), // index scale
+ array_cid,
Thread::kNoDeoptId,
builder.TokenPos()));
+ // Box and/or convert result if necessary.
+ switch (array_cid) {
+ case kTypedDataInt32ArrayCid:
+ case kExternalTypedDataInt32ArrayCid:
+ result = builder.AddDefinition(
+ BoxInstr::Create(kUnboxedInt32, new Value(result)));
+ break;
+ case kTypedDataUint32ArrayCid:
+ case kExternalTypedDataUint32ArrayCid:
+ result = builder.AddDefinition(
+ BoxInstr::Create(kUnboxedUint32, new Value(result)));
+ break;
+ case kTypedDataFloat32ArrayCid:
+ result = builder.AddDefinition(
+ new FloatToDoubleInstr(new Value(result), Thread::kNoDeoptId));
+ // Fall through.
+ case kTypedDataFloat64ArrayCid:
+ result = builder.AddDefinition(
+ BoxInstr::Create(kUnboxedDouble, new Value(result)));
+ break;
+ case kArrayCid:
+ case kImmutableArrayCid:
+ case kTypedDataInt8ArrayCid:
+ case kTypedDataUint8ArrayCid:
+ case kExternalTypedDataUint8ArrayCid:
+ case kTypedDataUint8ClampedArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid:
+ // Nothing to do.
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
builder.AddIntrinsicReturn(new Value(result));
return true;
}
-bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) {
+static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph,
+ intptr_t array_cid) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
TargetEntryInstr* normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
@@ -468,54 +465,82 @@ bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) {
Definition* index = builder.AddParameter(2);
Definition* array = builder.AddParameter(3);
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
- builder.AddInstruction(
- new CheckSmiInstr(new Value(value),
- Thread::kNoDeoptId,
- builder.TokenPos()));
-
- builder.AddInstruction(
- new StoreIndexedInstr(new Value(array),
- new Value(index),
- new Value(value),
- kNoStoreBarrier,
- 1, // index scale
- kTypedDataUint8ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- // Return null.
- Definition* null_def = builder.AddNullDefinition();
- builder.AddIntrinsicReturn(new Value(null_def));
- return true;
-}
-
-
-bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* value = builder.AddParameter(1);
- Definition* index = builder.AddParameter(2);
- Definition* array = builder.AddParameter(3);
+ intptr_t length_offset = Array::length_offset();
+ if (RawObject::IsTypedDataClassId(array_cid)) {
+ length_offset = TypedData::length_offset();
+ } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ length_offset = ExternalTypedData::length_offset();
+ }
- PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
+ PrepareIndexedOp(&builder, array, index, length_offset);
+
+ // Value check/conversion.
+ switch (array_cid) {
+ case kTypedDataInt8ArrayCid:
+ case kTypedDataUint8ArrayCid:
+ case kExternalTypedDataUint8ArrayCid:
+ case kTypedDataUint8ClampedArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid:
+ builder.AddInstruction(new CheckSmiInstr(new Value(value),
+ Thread::kNoDeoptId,
+ builder.TokenPos()));
+ break;
+ case kTypedDataInt32ArrayCid:
+ case kExternalTypedDataInt32ArrayCid:
+ // Use same truncating unbox-instruction for int32 and uint32.
+ // Fall-through.
+ case kTypedDataUint32ArrayCid:
+ case kExternalTypedDataUint32ArrayCid:
+ // Supports smi and mint, slow-case for bigints.
+ value = builder.AddUnboxInstr(kUnboxedUint32,
+ new Value(value),
+ /* is_checked = */ false);
+ break;
+ case kTypedDataFloat32ArrayCid:
+ case kTypedDataFloat64ArrayCid: {
+ const ICData& value_check = ICData::ZoneHandle(ICData::New(
+ flow_graph->function(),
+ Symbols::Empty(), // Dummy function name.
+ Object::empty_array(), // Dummy args. descr.
+ Thread::kNoDeoptId,
+ 1,
+ false));
+ value_check.AddReceiverCheck(kDoubleCid, flow_graph->function());
+ builder.AddInstruction(
+ new CheckClassInstr(new Value(value),
+ Thread::kNoDeoptId,
+ value_check,
+ builder.TokenPos()));
+ value = builder.AddUnboxInstr(kUnboxedDouble,
+ new Value(value),
+ /* is_checked = */ true);
+ if (array_cid == kTypedDataFloat32ArrayCid) {
+ value = builder.AddDefinition(
+ new DoubleToFloatInstr(new Value(value), Thread::kNoDeoptId));
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
- builder.AddInstruction(
- new CheckSmiInstr(new Value(value),
- Thread::kNoDeoptId,
- builder.TokenPos()));
- Definition* elements = builder.AddDefinition(
+ if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ array = builder.AddDefinition(
new LoadUntaggedInstr(new Value(array),
ExternalTypedData::data_offset()));
+ }
+ // No store barrier.
+ ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) ||
+ RawObject::IsTypedDataClassId(array_cid));
builder.AddInstruction(
- new StoreIndexedInstr(new Value(elements),
+ new StoreIndexedInstr(new Value(array),
new Value(index),
new Value(value),
kNoStoreBarrier,
- 1, // index scale
- kExternalTypedDataUint8ArrayCid,
+ Instance::ElementSizeFor(array_cid), // index scale
+ array_cid,
Thread::kNoDeoptId,
builder.TokenPos()));
// Return null.
@@ -525,137 +550,78 @@ bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) {
}
-bool Intrinsifier::Build_Uint32ArraySetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* value = builder.AddParameter(1);
- Definition* index = builder.AddParameter(2);
- Definition* array = builder.AddParameter(3);
-
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
- Definition* unboxed_value =
- builder.AddUnboxInstr(kUnboxedUint32,
- new Value(value),
- /* is_checked = */ true);
-
- builder.AddInstruction(
- new StoreIndexedInstr(new Value(array),
- new Value(index),
- new Value(unboxed_value),
- kNoStoreBarrier,
- 4, // index scale
- kTypedDataUint32ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- // Return null.
- Definition* null_def = builder.AddNullDefinition();
- builder.AddIntrinsicReturn(new Value(null_def));
- return true;
+#define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \
+bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \
+ return IntrinsifyArrayGetIndexed( \
+ flow_graph, \
+ MethodRecognizer::MethodKindToReceiverCid( \
+ MethodRecognizer::k##enum_name##GetIndexed)); \
}
-bool Intrinsifier::Build_Uint32ArrayGetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* index = builder.AddParameter(1);
- Definition* array = builder.AddParameter(2);
-
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
- Definition* unboxed_value = builder.AddDefinition(
- new LoadIndexedInstr(new Value(array),
- new Value(index),
- 4, // index scale
- kTypedDataUint32ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- Definition* result = builder.AddDefinition(
- BoxInstr::Create(kUnboxedUint32, new Value(unboxed_value)));
- builder.AddIntrinsicReturn(new Value(result));
- return true;
+#define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \
+bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \
+ return IntrinsifyArraySetIndexed( \
+ flow_graph, \
+ MethodRecognizer::MethodKindToReceiverCid( \
+ MethodRecognizer::k##enum_name##SetIndexed)); \
}
+DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray) // Setter in intrinsifier_<arch>.cc.
+DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray)
-bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) {
- if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
- return false;
- }
+#define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \
+DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \
+DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* value = builder.AddParameter(1);
- Definition* index = builder.AddParameter(2);
- Definition* array = builder.AddParameter(3);
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array)
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
+#undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS
+#undef DEFINE_ARRAY_GETTER_INTRINSIC
+#undef DEFINE_ARRAY_SETTER_INTRINSIC
- const ICData& value_check = ICData::ZoneHandle(ICData::New(
- flow_graph->function(),
- String::Handle(flow_graph->function().name()),
- Object::empty_array(), // Dummy args. descr.
- Thread::kNoDeoptId,
- 1,
- false));
- value_check.AddReceiverCheck(kDoubleCid, flow_graph->function());
- builder.AddInstruction(
- new CheckClassInstr(new Value(value),
- Thread::kNoDeoptId,
- value_check,
- builder.TokenPos()));
- Definition* double_value =
- builder.AddUnboxInstr(kUnboxedDouble,
- new Value(value),
- /* is_checked = */ true);
- builder.AddInstruction(
- new StoreIndexedInstr(new Value(array),
- new Value(index),
- new Value(double_value),
- kNoStoreBarrier,
- 8, // index scale
- kTypedDataFloat64ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- // Return null.
- Definition* null_def = builder.AddNullDefinition();
- builder.AddIntrinsicReturn(new Value(null_def));
- return true;
+#define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \
+bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \
+ if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \
+ return false; \
+ } \
+ return IntrinsifyArrayGetIndexed( \
+ flow_graph, \
+ MethodRecognizer::MethodKindToReceiverCid( \
+ MethodRecognizer::k##enum_name##GetIndexed)); \
}
-bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) {
- if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
- return false;
- }
-
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
+#define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \
+bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \
+ if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \
+ return false; \
+ } \
+ return IntrinsifyArraySetIndexed( \
+ flow_graph, \
+ MethodRecognizer::MethodKindToReceiverCid( \
+ MethodRecognizer::k##enum_name##SetIndexed)); \
+}
- Definition* index = builder.AddParameter(1);
- Definition* array = builder.AddParameter(2);
+#define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \
+DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \
+DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
+DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array)
+DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array)
- Definition* unboxed_value = builder.AddDefinition(
- new LoadIndexedInstr(new Value(array),
- new Value(index),
- 8, // index scale
- kTypedDataFloat64ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- Definition* result = builder.AddDefinition(
- BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value)));
- builder.AddIntrinsicReturn(new Value(result));
- return true;
-}
+#undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS
+#undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC
+#undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC
static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) {
« no previous file with comments | « runtime/vm/flow_graph_inliner.cc ('k') | runtime/vm/method_recognizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698