| OLD | NEW |
| 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 | 4 |
| 5 library service.struct; | 5 library service.struct; |
| 6 | 6 |
| 7 import "dart:ffi"; | 7 import "dart:ffi"; |
| 8 | 8 |
| 9 const int HEADER_SIZE = 56; | 9 const int HEADER_SIZE = 56; |
| 10 | 10 |
| 11 Reader getRoot(Reader reader, Foreign request) { | 11 Reader getRoot(Reader reader, ForeignMemory request) { |
| 12 int segments = request.getInt32(HEADER_SIZE - 8); | 12 int segments = request.getInt32(HEADER_SIZE - 8); |
| 13 if (segments == 0) { | 13 if (segments == 0) { |
| 14 MessageReader messageReader = new MessageReader(); | 14 MessageReader messageReader = new MessageReader(); |
| 15 Segment segment = new Segment(messageReader, request); | 15 Segment segment = new Segment(messageReader, request); |
| 16 messageReader.segments.add(segment); | 16 messageReader.segments.add(segment); |
| 17 reader._segment = segment; | 17 reader._segment = segment; |
| 18 reader._offset = HEADER_SIZE; | 18 reader._offset = HEADER_SIZE; |
| 19 return reader; | 19 return reader; |
| 20 } else { | 20 } else { |
| 21 return getSegmentedRoot(reader, request, segments); | 21 return getSegmentedRoot(reader, request, segments); |
| 22 } | 22 } |
| 23 } | 23 } |
| 24 | 24 |
| 25 Reader getSegmentedRoot(Reader reader, Foreign request, int segments) { | 25 Reader getSegmentedRoot(Reader reader, ForeignMemory request, int segments) { |
| 26 MessageReader messageReader = new MessageReader(); | 26 MessageReader messageReader = new MessageReader(); |
| 27 int offset = HEADER_SIZE + 8; | 27 int offset = HEADER_SIZE + 8; |
| 28 for (int i = 0; i < segments; i++) { | 28 for (int i = 0; i < segments; i++) { |
| 29 int address = (Foreign.bitsPerMachineWord == 32) | 29 int address = (Foreign.bitsPerMachineWord == 32) |
| 30 ? request.getUint32(offset) | 30 ? request.getUint32(offset) |
| 31 : request.getUint64(offset); | 31 : request.getUint64(offset); |
| 32 int size = request.getInt32(offset + 8); | 32 int size = request.getInt32(offset + 8); |
| 33 Foreign memory = new Foreign.fromAddress(address, size); | 33 ForeignMemory memory = new ForeignMemory.fromAddress(address, size); |
| 34 Segment segment = new Segment(messageReader, memory); | 34 Segment segment = new Segment(messageReader, memory); |
| 35 messageReader.segments.add(segment); | 35 messageReader.segments.add(segment); |
| 36 offset += 16; | 36 offset += 16; |
| 37 } | 37 } |
| 38 reader._segment = messageReader.segments.first; | 38 reader._segment = messageReader.segments.first; |
| 39 reader._offset = HEADER_SIZE; | 39 reader._offset = HEADER_SIZE; |
| 40 return reader; | 40 return reader; |
| 41 } | 41 } |
| 42 | 42 |
| 43 int getResultMessage(Builder builder) { | 43 int getResultMessage(Builder builder) { |
| 44 BuilderSegment segment = builder._segment; | 44 BuilderSegment segment = builder._segment; |
| 45 if (segment._next == null) { | 45 if (segment._next == null) { |
| 46 // Mark result as being non-segmented. | 46 // Mark result as being non-segmented. |
| 47 Foreign memory = segment.memory; | 47 ForeignMemory memory = segment.memory; |
| 48 memory.setInt32(0, 0); | 48 memory.setInt32(0, 0); |
| 49 memory.setInt32(4, memory.length); | 49 memory.setInt32(4, memory.length); |
| 50 return memory.value; | 50 return memory.address; |
| 51 } | 51 } |
| 52 | 52 |
| 53 // The result is a segmented message. Build a memory block that | 53 // The result is a segmented message. Build a memory block that |
| 54 // contains the addresses and sizes of all of them. | 54 // contains the addresses and sizes of all of them. |
| 55 int segments = segment._builder._segments; | 55 int segments = segment._builder._segments; |
| 56 int size = 8 + (segments * 16); | 56 int size = 8 + (segments * 16); |
| 57 Foreign buffer = new Foreign.allocated(size); | 57 ForeignMemory buffer = new ForeignMemory.allocated(size); |
| 58 // Mark the result as being segmented. | 58 // Mark the result as being segmented. |
| 59 buffer.setInt32(0, segments); | 59 buffer.setInt32(0, segments); |
| 60 int offset = 8; | 60 int offset = 8; |
| 61 do { | 61 do { |
| 62 buffer.setInt64(offset, segment.memory.value); | 62 buffer.setInt64(offset, segment.memory.address); |
| 63 buffer.setInt32(offset + 8, segment._used); | 63 buffer.setInt32(offset + 8, segment._used); |
| 64 segment = segment._next; | 64 segment = segment._next; |
| 65 offset += 16; | 65 offset += 16; |
| 66 } while (segment != null); | 66 } while (segment != null); |
| 67 return buffer.value; | 67 return buffer.address; |
| 68 } | 68 } |
| 69 | 69 |
| 70 class MessageReader { | 70 class MessageReader { |
| 71 final List<Segment> segments = []; | 71 final List<Segment> segments = []; |
| 72 MessageReader(); | 72 MessageReader(); |
| 73 | 73 |
| 74 Segment getSegment(int id) => segments[id]; | 74 Segment getSegment(int id) => segments[id]; |
| 75 } | 75 } |
| 76 | 76 |
| 77 class Segment { | 77 class Segment { |
| 78 final MessageReader reader; | 78 final MessageReader reader; |
| 79 final Foreign memory; | 79 final ForeignMemory memory; |
| 80 Segment(this.reader, this.memory); | 80 Segment(this.reader, this.memory); |
| 81 } | 81 } |
| 82 | 82 |
| 83 class Reader { | 83 class Reader { |
| 84 Segment _segment; | 84 Segment _segment; |
| 85 int _offset; | 85 int _offset; |
| 86 | 86 |
| 87 Segment get segment => _segment; | 87 Segment get segment => _segment; |
| 88 void set segment(Segment value) { | 88 void set segment(Segment value) { |
| 89 _segment = value; | 89 _segment = value; |
| 90 } | 90 } |
| 91 | 91 |
| 92 int get offset => _offset; | 92 int get offset => _offset; |
| 93 void set offset(int value) { | 93 void set offset(int value) { |
| 94 _offset = value; | 94 _offset = value; |
| 95 } | 95 } |
| 96 | 96 |
| 97 readStruct(Reader reader, int offset) { | 97 readStruct(Reader reader, int offset) { |
| 98 Segment segment = _segment; | 98 Segment segment = _segment; |
| 99 offset += _offset; | 99 offset += _offset; |
| 100 while (true) { | 100 while (true) { |
| 101 Foreign memory = segment.memory; | 101 ForeignMemory memory = segment.memory; |
| 102 int lo = memory.getInt32(offset + 0); | 102 int lo = memory.getInt32(offset + 0); |
| 103 int hi = memory.getInt32(offset + 4); | 103 int hi = memory.getInt32(offset + 4); |
| 104 int tag = lo & 3; | 104 int tag = lo & 3; |
| 105 if (tag == 0) { | 105 if (tag == 0) { |
| 106 throw new UnimplementedError("Cannot read uninitialized structs"); | 106 throw new UnimplementedError("Cannot read uninitialized structs"); |
| 107 } else if (tag == 1) { | 107 } else if (tag == 1) { |
| 108 reader._segment = segment; | 108 reader._segment = segment; |
| 109 reader._offset = lo >> 2; | 109 reader._offset = lo >> 2; |
| 110 return reader; | 110 return reader; |
| 111 } else { | 111 } else { |
| 112 segment = segment.reader.getSegment(hi); | 112 segment = segment.reader.getSegment(hi); |
| 113 offset = lo >> 2; | 113 offset = lo >> 2; |
| 114 } | 114 } |
| 115 } | 115 } |
| 116 } | 116 } |
| 117 | 117 |
| 118 readList(ListReader reader, int offset) { | 118 readList(ListReader reader, int offset) { |
| 119 Segment segment = _segment; | 119 Segment segment = _segment; |
| 120 offset += _offset; | 120 offset += _offset; |
| 121 while (true) { | 121 while (true) { |
| 122 Foreign memory = segment.memory; | 122 ForeignMemory memory = segment.memory; |
| 123 int lo = memory.getInt32(offset + 0); | 123 int lo = memory.getInt32(offset + 0); |
| 124 int hi = memory.getInt32(offset + 4); | 124 int hi = memory.getInt32(offset + 4); |
| 125 int tag = lo & 3; | 125 int tag = lo & 3; |
| 126 if (tag == 0) { | 126 if (tag == 0) { |
| 127 // If the list hasn't been initialized, then | 127 // If the list hasn't been initialized, then |
| 128 // we return an empty list. | 128 // we return an empty list. |
| 129 reader._length = 0; | 129 reader._length = 0; |
| 130 return reader; | 130 return reader; |
| 131 } else if (tag == 2) { | 131 } else if (tag == 2) { |
| 132 reader._segment = segment; | 132 reader._segment = segment; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 Iterable getRange(int start, int end) { throw new UnsupportedError("ListBuilde
r::getRange"); } | 205 Iterable getRange(int start, int end) { throw new UnsupportedError("ListBuilde
r::getRange"); } |
| 206 void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { th
row new UnsupportedError("ListBuilder::setRange"); } | 206 void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { th
row new UnsupportedError("ListBuilder::setRange"); } |
| 207 void removeRange(int start, int end) { throw new UnsupportedError("ListBuilder
::removeRange"); } | 207 void removeRange(int start, int end) { throw new UnsupportedError("ListBuilder
::removeRange"); } |
| 208 void fillRange(int start, int end, [fillValue]) { throw new UnsupportedError("
ListBuilder::fillRange"); } | 208 void fillRange(int start, int end, [fillValue]) { throw new UnsupportedError("
ListBuilder::fillRange"); } |
| 209 void replaceRange(int start, int end, Iterable replacement) { throw new Unsupp
ortedError("ListBuilder::replaceRange"); } | 209 void replaceRange(int start, int end, Iterable replacement) { throw new Unsupp
ortedError("ListBuilder::replaceRange"); } |
| 210 Map asMap() { throw new UnsupportedError("ListBuilder::asMap"); } | 210 Map asMap() { throw new UnsupportedError("ListBuilder::asMap"); } |
| 211 } | 211 } |
| 212 | 212 |
| 213 class BuilderSegment { | 213 class BuilderSegment { |
| 214 final MessageBuilder _builder; | 214 final MessageBuilder _builder; |
| 215 final Foreign memory; | 215 final ForeignMemory memory; |
| 216 int _id; | 216 int _id; |
| 217 int _used = 0; | 217 int _used = 0; |
| 218 BuilderSegment _next; | 218 BuilderSegment _next; |
| 219 | 219 |
| 220 BuilderSegment(this._builder, this._id, int space) | 220 BuilderSegment(this._builder, this._id, int space) |
| 221 : memory = new Foreign.allocated(space); | 221 : memory = new ForeignMemory.allocated(space); |
| 222 | 222 |
| 223 bool HasSpaceForBytes(int bytes) => _used + bytes <= memory.length; | 223 bool HasSpaceForBytes(int bytes) => _used + bytes <= memory.length; |
| 224 | 224 |
| 225 int Allocate(int bytes) { | 225 int Allocate(int bytes) { |
| 226 if (!HasSpaceForBytes(bytes)) return -1; | 226 if (!HasSpaceForBytes(bytes)) return -1; |
| 227 var result = _used; | 227 var result = _used; |
| 228 _used += bytes; | 228 _used += bytes; |
| 229 return result; | 229 return result; |
| 230 } | 230 } |
| 231 } | 231 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 int get offset => _offset; | 269 int get offset => _offset; |
| 270 void set offset(int value) { | 270 void set offset(int value) { |
| 271 _offset = value; | 271 _offset = value; |
| 272 } | 272 } |
| 273 | 273 |
| 274 Builder NewStruct(Builder builder, int offset, int size) { | 274 Builder NewStruct(Builder builder, int offset, int size) { |
| 275 offset += _offset; | 275 offset += _offset; |
| 276 BuilderSegment segment = _segment; | 276 BuilderSegment segment = _segment; |
| 277 while (true) { | 277 while (true) { |
| 278 int result = segment.Allocate(size); | 278 int result = segment.Allocate(size); |
| 279 Foreign memory = segment.memory; | 279 ForeignMemory memory = segment.memory; |
| 280 if (result >= 0) { | 280 if (result >= 0) { |
| 281 memory.setInt32(offset + 0, (result << 2) | 1); | 281 memory.setInt32(offset + 0, (result << 2) | 1); |
| 282 memory.setInt32(offset + 4, 0); | 282 memory.setInt32(offset + 4, 0); |
| 283 builder._segment = segment; | 283 builder._segment = segment; |
| 284 builder._offset = result; | 284 builder._offset = result; |
| 285 return builder; | 285 return builder; |
| 286 } | 286 } |
| 287 | 287 |
| 288 BuilderSegment other = segment._builder.FindSegmentForBytes(size + 8); | 288 BuilderSegment other = segment._builder.FindSegmentForBytes(size + 8); |
| 289 int target = other.Allocate(8); | 289 int target = other.Allocate(8); |
| 290 memory.setInt32(offset + 0, (target << 2) | 3); | 290 memory.setInt32(offset + 0, (target << 2) | 3); |
| 291 memory.setInt32(offset + 4, other._id); | 291 memory.setInt32(offset + 4, other._id); |
| 292 | 292 |
| 293 segment = other; | 293 segment = other; |
| 294 offset = target; | 294 offset = target; |
| 295 } | 295 } |
| 296 } | 296 } |
| 297 | 297 |
| 298 ListBuilder NewList(ListBuilder list, | 298 ListBuilder NewList(ListBuilder list, |
| 299 int offset, | 299 int offset, |
| 300 int length, | 300 int length, |
| 301 int size) { | 301 int size) { |
| 302 list._length = length; | 302 list._length = length; |
| 303 offset += _offset; | 303 offset += _offset; |
| 304 size *= length; | 304 size *= length; |
| 305 BuilderSegment segment = _segment; | 305 BuilderSegment segment = _segment; |
| 306 while (true) { | 306 while (true) { |
| 307 int result = segment.Allocate(size); | 307 int result = segment.Allocate(size); |
| 308 Foreign memory = segment.memory; | 308 ForeignMemory memory = segment.memory; |
| 309 if (result >= 0) { | 309 if (result >= 0) { |
| 310 memory.setInt32(offset + 0, (result << 2) | 1); | 310 memory.setInt32(offset + 0, (result << 2) | 1); |
| 311 memory.setInt32(offset + 4, length); | 311 memory.setInt32(offset + 4, length); |
| 312 list._segment = segment; | 312 list._segment = segment; |
| 313 list._offset = result; | 313 list._offset = result; |
| 314 return list; | 314 return list; |
| 315 } | 315 } |
| 316 | 316 |
| 317 BuilderSegment other = segment._builder.FindSegmentForBytes(size + 8); | 317 BuilderSegment other = segment._builder.FindSegmentForBytes(size + 8); |
| 318 int target = other.Allocate(8); | 318 int target = other.Allocate(8); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 void removeWhere(Function test) { throw new UnsupportedError("ListBuilder::rem
oveWhere"); } | 388 void removeWhere(Function test) { throw new UnsupportedError("ListBuilder::rem
oveWhere"); } |
| 389 void retainWhere(Function test) { throw new UnsupportedError("ListBuilder::ret
ainWhere"); } | 389 void retainWhere(Function test) { throw new UnsupportedError("ListBuilder::ret
ainWhere"); } |
| 390 List sublist(int start, [int end]) { throw new UnsupportedError("ListBuilder::
sublist"); } | 390 List sublist(int start, [int end]) { throw new UnsupportedError("ListBuilder::
sublist"); } |
| 391 Iterable getRange(int start, int end) { throw new UnsupportedError("ListBuilde
r::getRange"); } | 391 Iterable getRange(int start, int end) { throw new UnsupportedError("ListBuilde
r::getRange"); } |
| 392 void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { th
row new UnsupportedError("ListBuilder::setRange"); } | 392 void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { th
row new UnsupportedError("ListBuilder::setRange"); } |
| 393 void removeRange(int start, int end) { throw new UnsupportedError("ListBuilder
::removeRange"); } | 393 void removeRange(int start, int end) { throw new UnsupportedError("ListBuilder
::removeRange"); } |
| 394 void fillRange(int start, int end, [fillValue]) { throw new UnsupportedError("
ListBuilder::fillRange"); } | 394 void fillRange(int start, int end, [fillValue]) { throw new UnsupportedError("
ListBuilder::fillRange"); } |
| 395 void replaceRange(int start, int end, Iterable replacement) { throw new Unsupp
ortedError("ListBuilder::replaceRange"); } | 395 void replaceRange(int start, int end, Iterable replacement) { throw new Unsupp
ortedError("ListBuilder::replaceRange"); } |
| 396 Map asMap() { throw new UnsupportedError("ListBuilder::asMap"); } | 396 Map asMap() { throw new UnsupportedError("ListBuilder::asMap"); } |
| 397 } | 397 } |
| OLD | NEW |