[vm] Fix serialization of SIMD vectors. Broken by bbefc0574887c1e00e00d07d7cb8a2b5acd249d6. TEST=ci Bug: https://github.com/dart-lang/sdk/issues/46793 Change-Id: I8e5869caee2d705cecaf974cca3ee3f0c542ad3c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208840 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Siva Annamalai <asiva@google.com>
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h index 7da4532..c0c642f 100644 --- a/runtime/vm/datastream.h +++ b/runtime/vm/datastream.h
@@ -85,7 +85,7 @@ }; // Reads 'len' bytes from the stream. - void ReadBytes(uint8_t* addr, intptr_t len) { + void ReadBytes(void* addr, intptr_t len) { ASSERT((end_ - current_) >= len); if (len != 0) { memmove(addr, current_, len);
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc index 37bb767..3eca655 100644 --- a/runtime/vm/message_snapshot.cc +++ b/runtime/vm/message_snapshot.cc
@@ -145,7 +145,7 @@ void WriteWordWith32BitWrites(uword value) { stream_.WriteWordWith32BitWrites(value); } - void WriteBytes(const uint8_t* addr, intptr_t len) { + void WriteBytes(const void* addr, intptr_t len) { stream_.WriteBytes(addr, len); } void WriteAscii(const String& str) { @@ -344,7 +344,7 @@ } intptr_t ReadUnsigned() { return stream_.ReadUnsigned(); } uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); } - void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); } + void ReadBytes(void* addr, intptr_t len) { stream_.ReadBytes(addr, len); } const char* ReadAscii() { intptr_t len = ReadUnsigned(); const char* result = reinterpret_cast<const char*>(CurrentBufferAddress()); @@ -1572,8 +1572,7 @@ d->AssignRef(data.ptr()); const intptr_t length_in_bytes = length * element_size; NoSafepointScope no_safepoint; - uint8_t* cdata = reinterpret_cast<uint8_t*>(data.untag()->data()); - d->ReadBytes(cdata, length_in_bytes); + d->ReadBytes(data.untag()->data(), length_in_bytes); } } @@ -2066,6 +2065,60 @@ } }; +class Simd128MessageSerializationCluster : public MessageSerializationCluster { + public: + explicit Simd128MessageSerializationCluster(intptr_t cid) + : MessageSerializationCluster("Simd128", + MessagePhase::kBeforeTypes, + cid) {} + ~Simd128MessageSerializationCluster() {} + + void Trace(MessageSerializer* s, Object* object) { objects_.Add(object); } + + void WriteNodes(MessageSerializer* s) { + intptr_t count = objects_.length(); + s->WriteUnsigned(count); + for (intptr_t i = 0; i < count; i++) { + Object* vector = objects_[i]; + s->AssignRef(vector); + ASSERT_EQUAL(Int32x4::value_offset(), Float32x4::value_offset()); + ASSERT_EQUAL(Int32x4::value_offset(), Float64x2::value_offset()); + s->WriteBytes(&(static_cast<Int32x4Ptr>(vector->ptr())->untag()->value_), + sizeof(simd128_value_t)); + } + } + + private: + GrowableArray<Object*> objects_; +}; + +class Simd128MessageDeserializationCluster + : public MessageDeserializationCluster { + public: + explicit Simd128MessageDeserializationCluster(intptr_t cid) + : MessageDeserializationCluster("Simd128"), cid_(cid) {} + ~Simd128MessageDeserializationCluster() {} + + void ReadNodes(MessageDeserializer* d) { + intptr_t count = d->ReadUnsigned(); + for (intptr_t i = 0; i < count; i++) { + ASSERT_EQUAL(Int32x4::InstanceSize(), Float32x4::InstanceSize()); + ASSERT_EQUAL(Int32x4::InstanceSize(), Float64x2::InstanceSize()); + ObjectPtr vector = + Object::Allocate(cid_, Int32x4::InstanceSize(), Heap::kNew, + Int32x4::ContainsCompressedPointers()); + d->AssignRef(vector); + ASSERT_EQUAL(Int32x4::value_offset(), Float32x4::value_offset()); + ASSERT_EQUAL(Int32x4::value_offset(), Float64x2::value_offset()); + d->ReadBytes(&(static_cast<Int32x4Ptr>(vector)->untag()->value_), + sizeof(simd128_value_t)); + } + } + + private: + const intptr_t cid_; +}; + class RegExpMessageSerializationCluster : public MessageSerializationCluster { public: RegExpMessageSerializationCluster() @@ -3233,6 +3286,10 @@ return new (Z) OneByteStringMessageSerializationCluster(Z, is_canonical); case kTwoByteStringCid: return new (Z) TwoByteStringMessageSerializationCluster(Z, is_canonical); + case kInt32x4Cid: + case kFloat32x4Cid: + case kFloat64x2Cid: + return new (Z) Simd128MessageSerializationCluster(cid); default: break; } @@ -3321,6 +3378,11 @@ return new (Z) OneByteStringMessageDeserializationCluster(is_canonical); case kTwoByteStringCid: return new (Z) TwoByteStringMessageDeserializationCluster(is_canonical); + case kInt32x4Cid: + case kFloat32x4Cid: + case kFloat64x2Cid: + ASSERT(!is_canonical); + return new (Z) Simd128MessageDeserializationCluster(cid); default: break; }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h index eb0d9e3..ce45815 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h
@@ -859,6 +859,7 @@ friend void UntaggedObject::Validate(IsolateGroup* isolate_group) const; friend class Closure; friend class InstanceDeserializationCluster; + friend class Simd128MessageDeserializationCluster; friend class OneByteString; friend class TwoByteString; friend class ExternalOneByteString;
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 3d442b2..885d79d 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h
@@ -3024,6 +3024,8 @@ ALIGN8 int32_t value_[4]; + friend class Simd128MessageSerializationCluster; + friend class Simd128MessageDeserializationCluster; public: int32_t x() const { return value_[0]; }
diff --git a/tests/lib/isolate/simd_vectors_message_test.dart b/tests/lib/isolate/simd_vectors_message_test.dart new file mode 100644 index 0000000..324d4ef --- /dev/null +++ b/tests/lib/isolate/simd_vectors_message_test.dart
@@ -0,0 +1,48 @@ +// Copyright (c) 2021, 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. + +// See https://github.com/dart-lang/sdk/issues/46793 + +import "dart:async"; +import "dart:isolate"; +import "dart:typed_data"; + +import "package:async_helper/async_helper.dart"; +import "package:expect/expect.dart"; + +main() { + asyncStart(); + var port; + port = new RawReceivePort((message) { + print("Receive $message"); + + var int32x4 = message[0] as Int32x4; + Expect.equals(-1, int32x4.x); + Expect.equals(0, int32x4.y); + Expect.equals(1, int32x4.z); + Expect.equals(2, int32x4.w); + + var float32x4 = message[1] as Float32x4; + Expect.equals(-2.5, float32x4.x); + Expect.equals(0.0, float32x4.y); + Expect.equals(1.25, float32x4.z); + Expect.equals(2.125, float32x4.w); + + var float64x2 = message[2] as Float64x2; + Expect.equals(16.5, float64x2.x); + Expect.equals(-32.25, float64x2.y); + + port.close(); + asyncEnd(); + }); + + + var list = [ + new Int32x4(-1, 0, 1, 2), + new Float32x4(-2.5, 0.0, 1.25, 2.125), + new Float64x2(16.5, -32.25), + ]; + print("Send $list"); + port.sendPort.send(list); +}
diff --git a/tests/lib_2/isolate/simd_vectors_message_test.dart b/tests/lib_2/isolate/simd_vectors_message_test.dart new file mode 100644 index 0000000..fedd5a0 --- /dev/null +++ b/tests/lib_2/isolate/simd_vectors_message_test.dart
@@ -0,0 +1,50 @@ +// Copyright (c) 2021, 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. + +// See https://github.com/dart-lang/sdk/issues/46793 + +// @dart = 2.9 + +import "dart:async"; +import "dart:isolate"; +import "dart:typed_data"; + +import "package:async_helper/async_helper.dart"; +import "package:expect/expect.dart"; + +main() { + asyncStart(); + var port; + port = new RawReceivePort((message) { + print("Receive $message"); + + var int32x4 = message[0] as Int32x4; + Expect.equals(-1, int32x4.x); + Expect.equals(0, int32x4.y); + Expect.equals(1, int32x4.z); + Expect.equals(2, int32x4.w); + + var float32x4 = message[1] as Float32x4; + Expect.equals(-2.5, float32x4.x); + Expect.equals(0.0, float32x4.y); + Expect.equals(1.25, float32x4.z); + Expect.equals(2.125, float32x4.w); + + var float64x2 = message[2] as Float64x2; + Expect.equals(16.5, float64x2.x); + Expect.equals(-32.25, float64x2.y); + + port.close(); + asyncEnd(); + }); + + + var list = [ + new Int32x4(-1, 0, 1, 2), + new Float32x4(-2.5, 0.0, 1.25, 2.125), + new Float64x2(16.5, -32.25), + ]; + print("Send $list"); + port.sendPort.send(list); +}