OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart 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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 library kernel.ast_to_binary; | 4 library kernel.ast_to_binary; |
5 | 5 |
6 import '../ast.dart'; | 6 import '../ast.dart'; |
7 import '../import_table.dart'; | 7 import '../import_table.dart'; |
8 import 'tag.dart'; | 8 import 'tag.dart'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 import 'dart:typed_data'; | 10 import 'dart:typed_data'; |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 } | 397 } |
398 | 398 |
399 visitRedirectingInitializer(RedirectingInitializer node) { | 399 visitRedirectingInitializer(RedirectingInitializer node) { |
400 writeByte(Tag.RedirectingInitializer); | 400 writeByte(Tag.RedirectingInitializer); |
401 writeReference(node.targetReference); | 401 writeReference(node.targetReference); |
402 writeNode(node.arguments); | 402 writeNode(node.arguments); |
403 } | 403 } |
404 | 404 |
405 visitLocalInitializer(LocalInitializer node) { | 405 visitLocalInitializer(LocalInitializer node) { |
406 writeByte(Tag.LocalInitializer); | 406 writeByte(Tag.LocalInitializer); |
407 writeVariableDeclaration(node.variable); | 407 writeVariableDeclaration(node.variable, false); |
408 } | 408 } |
409 | 409 |
410 visitFunctionNode(FunctionNode node) { | 410 visitFunctionNode(FunctionNode node) { |
411 assert(_variableIndexer != null); | 411 assert(_variableIndexer != null); |
412 _variableIndexer.pushScope(); | 412 _variableIndexer.pushScope(); |
413 var oldLabels = _labelIndexer; | 413 var oldLabels = _labelIndexer; |
414 _labelIndexer = new LabelIndexer(); | 414 _labelIndexer = new LabelIndexer(); |
415 var oldCases = _switchCaseIndexer; | 415 var oldCases = _switchCaseIndexer; |
416 _switchCaseIndexer = new SwitchCaseIndexer(); | 416 _switchCaseIndexer = new SwitchCaseIndexer(); |
417 // Note: FunctionNode has no tag. | 417 // Note: FunctionNode has no tag. |
(...skipping 19 matching lines...) Expand all Loading... |
437 } | 437 } |
438 | 438 |
439 visitVariableGet(VariableGet node) { | 439 visitVariableGet(VariableGet node) { |
440 assert(_variableIndexer != null); | 440 assert(_variableIndexer != null); |
441 int index = _variableIndexer[node.variable]; | 441 int index = _variableIndexer[node.variable]; |
442 assert(index != null); | 442 assert(index != null); |
443 if (index & Tag.SpecializedPayloadMask == index && | 443 if (index & Tag.SpecializedPayloadMask == index && |
444 node.promotedType == null) { | 444 node.promotedType == null) { |
445 writeByte(Tag.SpecializedVariableGet + index); | 445 writeByte(Tag.SpecializedVariableGet + index); |
446 writeOffset(node.fileOffset); | 446 writeOffset(node.fileOffset); |
| 447 writeUInt30(node.variable.binaryOffset); |
447 } else { | 448 } else { |
448 writeByte(Tag.VariableGet); | 449 writeByte(Tag.VariableGet); |
449 writeOffset(node.fileOffset); | 450 writeOffset(node.fileOffset); |
| 451 writeUInt30(node.variable.binaryOffset); |
450 writeUInt30(_variableIndexer[node.variable]); | 452 writeUInt30(_variableIndexer[node.variable]); |
451 writeOptionalNode(node.promotedType); | 453 writeOptionalNode(node.promotedType); |
452 } | 454 } |
453 } | 455 } |
454 | 456 |
455 visitVariableSet(VariableSet node) { | 457 visitVariableSet(VariableSet node) { |
456 assert(_variableIndexer != null); | 458 assert(_variableIndexer != null); |
457 int index = _variableIndexer[node.variable]; | 459 int index = _variableIndexer[node.variable]; |
458 if (index & Tag.SpecializedPayloadMask == index) { | 460 if (index & Tag.SpecializedPayloadMask == index) { |
459 writeByte(Tag.SpecializedVariableSet + index); | 461 writeByte(Tag.SpecializedVariableSet + index); |
460 writeOffset(node.fileOffset); | 462 writeOffset(node.fileOffset); |
| 463 writeUInt30(node.variable.binaryOffset); |
461 writeNode(node.value); | 464 writeNode(node.value); |
462 } else { | 465 } else { |
463 writeByte(Tag.VariableSet); | 466 writeByte(Tag.VariableSet); |
464 writeOffset(node.fileOffset); | 467 writeOffset(node.fileOffset); |
| 468 writeUInt30(node.variable.binaryOffset); |
465 writeUInt30(_variableIndexer[node.variable]); | 469 writeUInt30(_variableIndexer[node.variable]); |
466 writeNode(node.value); | 470 writeNode(node.value); |
467 } | 471 } |
468 } | 472 } |
469 | 473 |
470 visitPropertyGet(PropertyGet node) { | 474 visitPropertyGet(PropertyGet node) { |
471 writeByte(Tag.PropertyGet); | 475 writeByte(Tag.PropertyGet); |
472 writeOffset(node.fileOffset); | 476 writeOffset(node.fileOffset); |
473 writeNode(node.receiver); | 477 writeNode(node.receiver); |
474 writeName(node.name); | 478 writeName(node.name); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 visitConstructorInvocation(ConstructorInvocation node) { | 563 visitConstructorInvocation(ConstructorInvocation node) { |
560 writeByte(node.isConst | 564 writeByte(node.isConst |
561 ? Tag.ConstConstructorInvocation | 565 ? Tag.ConstConstructorInvocation |
562 : Tag.ConstructorInvocation); | 566 : Tag.ConstructorInvocation); |
563 writeOffset(node.fileOffset); | 567 writeOffset(node.fileOffset); |
564 writeReference(node.targetReference); | 568 writeReference(node.targetReference); |
565 writeNode(node.arguments); | 569 writeNode(node.arguments); |
566 } | 570 } |
567 | 571 |
568 visitArguments(Arguments node) { | 572 visitArguments(Arguments node) { |
| 573 writeUInt30(node.positional.length + node.named.length); |
569 writeNodeList(node.types); | 574 writeNodeList(node.types); |
570 writeNodeList(node.positional); | 575 writeNodeList(node.positional); |
571 writeNodeList(node.named); | 576 writeNodeList(node.named); |
572 } | 577 } |
573 | 578 |
574 visitNamedExpression(NamedExpression node) { | 579 visitNamedExpression(NamedExpression node) { |
575 writeStringReference(node.name); | 580 writeStringReference(node.name); |
576 writeNode(node.value); | 581 writeNode(node.value); |
577 } | 582 } |
578 | 583 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 writeNode(node.operand); | 722 writeNode(node.operand); |
718 } | 723 } |
719 | 724 |
720 visitFunctionExpression(FunctionExpression node) { | 725 visitFunctionExpression(FunctionExpression node) { |
721 writeByte(Tag.FunctionExpression); | 726 writeByte(Tag.FunctionExpression); |
722 writeNode(node.function); | 727 writeNode(node.function); |
723 } | 728 } |
724 | 729 |
725 visitLet(Let node) { | 730 visitLet(Let node) { |
726 writeByte(Tag.Let); | 731 writeByte(Tag.Let); |
727 writeVariableDeclaration(node.variable); | 732 writeVariableDeclaration(node.variable, false); |
728 writeNode(node.body); | 733 writeNode(node.body); |
729 --_variableIndexer.stackHeight; | 734 --_variableIndexer.stackHeight; |
730 } | 735 } |
731 | 736 |
732 visitLoadLibrary(LoadLibrary node) { | 737 visitLoadLibrary(LoadLibrary node) { |
733 writeByte(Tag.LoadLibrary); | 738 writeByte(Tag.LoadLibrary); |
734 writeDeferredImportReference(node.import); | 739 writeDeferredImportReference(node.import); |
735 } | 740 } |
736 | 741 |
737 visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) { | 742 visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 writeOptionalNode(node.condition); | 840 writeOptionalNode(node.condition); |
836 writeNodeList(node.updates); | 841 writeNodeList(node.updates); |
837 writeNode(node.body); | 842 writeNode(node.body); |
838 _variableIndexer.popScope(); | 843 _variableIndexer.popScope(); |
839 } | 844 } |
840 | 845 |
841 visitForInStatement(ForInStatement node) { | 846 visitForInStatement(ForInStatement node) { |
842 _variableIndexer.pushScope(); | 847 _variableIndexer.pushScope(); |
843 writeByte(node.isAsync ? Tag.AsyncForInStatement : Tag.ForInStatement); | 848 writeByte(node.isAsync ? Tag.AsyncForInStatement : Tag.ForInStatement); |
844 writeOffset(node.fileOffset); | 849 writeOffset(node.fileOffset); |
845 writeVariableDeclaration(node.variable); | 850 writeVariableDeclaration(node.variable, false); |
846 writeNode(node.iterable); | 851 writeNode(node.iterable); |
847 writeNode(node.body); | 852 writeNode(node.body); |
848 _variableIndexer.popScope(); | 853 _variableIndexer.popScope(); |
849 } | 854 } |
850 | 855 |
851 visitSwitchStatement(SwitchStatement node) { | 856 visitSwitchStatement(SwitchStatement node) { |
852 _switchCaseIndexer.enter(node); | 857 _switchCaseIndexer.enter(node); |
853 writeByte(Tag.SwitchStatement); | 858 writeByte(Tag.SwitchStatement); |
854 writeNode(node.expression); | 859 writeNode(node.expression); |
855 writeNodeList(node.cases); | 860 writeNodeList(node.cases); |
856 _switchCaseIndexer.exit(node); | 861 _switchCaseIndexer.exit(node); |
857 } | 862 } |
858 | 863 |
859 visitSwitchCase(SwitchCase node) { | 864 visitSwitchCase(SwitchCase node) { |
860 // Note: there is no tag on SwitchCase. | 865 // Note: there is no tag on SwitchCase. |
861 writeNodeList(node.expressions); | 866 int length = node.expressions.length; |
862 node.expressionOffsets.forEach(writeOffset); | 867 writeUInt30(length); |
| 868 for (int i = 0; i < length; ++i) { |
| 869 writeOffset(node.expressionOffsets[i]); |
| 870 writeNode(node.expressions[i]); |
| 871 } |
863 writeByte(node.isDefault ? 1 : 0); | 872 writeByte(node.isDefault ? 1 : 0); |
864 writeNode(node.body); | 873 writeNode(node.body); |
865 } | 874 } |
866 | 875 |
867 visitContinueSwitchStatement(ContinueSwitchStatement node) { | 876 visitContinueSwitchStatement(ContinueSwitchStatement node) { |
868 writeByte(Tag.ContinueSwitchStatement); | 877 writeByte(Tag.ContinueSwitchStatement); |
869 writeUInt30(_switchCaseIndexer[node.target]); | 878 writeUInt30(_switchCaseIndexer[node.target]); |
870 } | 879 } |
871 | 880 |
872 visitIfStatement(IfStatement node) { | 881 visitIfStatement(IfStatement node) { |
873 writeByte(Tag.IfStatement); | 882 writeByte(Tag.IfStatement); |
874 writeNode(node.condition); | 883 writeNode(node.condition); |
875 writeNode(node.then); | 884 writeNode(node.then); |
876 writeStatementOrEmpty(node.otherwise); | 885 writeStatementOrEmpty(node.otherwise); |
877 } | 886 } |
878 | 887 |
879 visitReturnStatement(ReturnStatement node) { | 888 visitReturnStatement(ReturnStatement node) { |
880 writeByte(Tag.ReturnStatement); | 889 writeByte(Tag.ReturnStatement); |
881 writeOffset(node.fileOffset); | 890 writeOffset(node.fileOffset); |
882 writeOptionalNode(node.expression); | 891 writeOptionalNode(node.expression); |
883 } | 892 } |
884 | 893 |
885 visitTryCatch(TryCatch node) { | 894 visitTryCatch(TryCatch node) { |
886 writeByte(Tag.TryCatch); | 895 writeByte(Tag.TryCatch); |
887 writeNode(node.body); | 896 writeNode(node.body); |
| 897 if (node.catches.any((Catch c) => c.stackTrace != null)) { |
| 898 // at least one catch needs the stack trace. |
| 899 writeByte(1); |
| 900 } else { |
| 901 // no catch needs the stack trace. |
| 902 writeByte(0); |
| 903 } |
888 writeNodeList(node.catches); | 904 writeNodeList(node.catches); |
889 } | 905 } |
890 | 906 |
891 visitCatch(Catch node) { | 907 visitCatch(Catch node) { |
892 // Note: there is no tag on Catch. | 908 // Note: there is no tag on Catch. |
893 _variableIndexer.pushScope(); | 909 _variableIndexer.pushScope(); |
894 writeNode(node.guard); | 910 writeNode(node.guard); |
895 writeOptionalVariableDeclaration(node.exception); | 911 writeOptionalVariableDeclaration(node.exception); |
896 writeOptionalVariableDeclaration(node.stackTrace); | 912 writeOptionalVariableDeclaration(node.stackTrace); |
897 writeNode(node.body); | 913 writeNode(node.body); |
898 _variableIndexer.popScope(); | 914 _variableIndexer.popScope(); |
899 } | 915 } |
900 | 916 |
901 visitTryFinally(TryFinally node) { | 917 visitTryFinally(TryFinally node) { |
902 writeByte(Tag.TryFinally); | 918 writeByte(Tag.TryFinally); |
903 writeNode(node.body); | 919 writeNode(node.body); |
904 writeNode(node.finalizer); | 920 writeNode(node.finalizer); |
905 } | 921 } |
906 | 922 |
907 visitYieldStatement(YieldStatement node) { | 923 visitYieldStatement(YieldStatement node) { |
908 writeByte(Tag.YieldStatement); | 924 writeByte(Tag.YieldStatement); |
909 writeOffset(node.fileOffset); | 925 writeOffset(node.fileOffset); |
910 writeByte(node.flags); | 926 writeByte(node.flags); |
911 writeNode(node.expression); | 927 writeNode(node.expression); |
912 } | 928 } |
913 | 929 |
914 visitVariableDeclaration(VariableDeclaration node) { | 930 visitVariableDeclaration(VariableDeclaration node) { |
915 writeByte(Tag.VariableDeclaration); | 931 writeVariableDeclaration(node, true); |
916 writeVariableDeclaration(node); | |
917 } | 932 } |
918 | 933 |
919 void writeVariableDeclaration(VariableDeclaration node) { | 934 void writeVariableDeclaration(VariableDeclaration node, |
| 935 [bool hasTag = false]) { |
| 936 node.binaryOffset = _sink.flushedLength + _sink.length; |
| 937 if (hasTag) writeByte(Tag.VariableDeclaration); |
920 writeOffset(node.fileOffset); | 938 writeOffset(node.fileOffset); |
921 writeOffset(node.fileEqualsOffset); | 939 writeOffset(node.fileEqualsOffset); |
922 writeByte(node.flags); | 940 writeByte(node.flags); |
923 writeStringReference(node.name ?? ''); | 941 writeStringReference(node.name ?? ''); |
924 writeNode(node.type); | 942 writeNode(node.type); |
925 writeOptionalNode(node.initializer); | 943 writeOptionalNode(node.initializer); |
926 // Declare the variable after its initializer. It is not in scope in its | 944 // Declare the variable after its initializer. It is not in scope in its |
927 // own initializer. | 945 // own initializer. |
928 _variableIndexer.declare(node); | 946 _variableIndexer.declare(node); |
929 } | 947 } |
930 | 948 |
931 void writeVariableDeclarationList(List<VariableDeclaration> nodes) { | 949 void writeVariableDeclarationList(List<VariableDeclaration> nodes) { |
932 writeList(nodes, writeVariableDeclaration); | 950 writeList(nodes, writeVariableDeclaration); |
933 } | 951 } |
934 | 952 |
935 void writeOptionalVariableDeclaration(VariableDeclaration node) { | 953 void writeOptionalVariableDeclaration(VariableDeclaration node) { |
936 if (node == null) { | 954 if (node == null) { |
937 writeByte(Tag.Nothing); | 955 writeByte(Tag.Nothing); |
938 } else { | 956 } else { |
939 writeByte(Tag.Something); | 957 writeByte(Tag.Something); |
940 writeVariableDeclaration(node); | 958 writeVariableDeclaration(node, false); |
941 } | 959 } |
942 } | 960 } |
943 | 961 |
944 visitFunctionDeclaration(FunctionDeclaration node) { | 962 visitFunctionDeclaration(FunctionDeclaration node) { |
945 writeByte(Tag.FunctionDeclaration); | 963 writeByte(Tag.FunctionDeclaration); |
946 writeOffset(node.fileOffset); | 964 writeOffset(node.fileOffset); |
947 writeVariableDeclaration(node.variable); | 965 writeVariableDeclaration(node.variable, false); |
948 writeNode(node.function); | 966 writeNode(node.function); |
949 } | 967 } |
950 | 968 |
951 visitBottomType(BottomType node) { | 969 visitBottomType(BottomType node) { |
952 writeByte(Tag.BottomType); | 970 writeByte(Tag.BottomType); |
953 } | 971 } |
954 | 972 |
955 visitInvalidType(InvalidType node) { | 973 visitInvalidType(InvalidType node) { |
956 writeByte(Tag.InvalidType); | 974 writeByte(Tag.InvalidType); |
957 } | 975 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 node.typeParameters.isEmpty && | 1009 node.typeParameters.isEmpty && |
992 node.namedParameters.isEmpty) { | 1010 node.namedParameters.isEmpty) { |
993 writeByte(Tag.SimpleFunctionType); | 1011 writeByte(Tag.SimpleFunctionType); |
994 writeNodeList(node.positionalParameters); | 1012 writeNodeList(node.positionalParameters); |
995 writeNode(node.returnType); | 1013 writeNode(node.returnType); |
996 } else { | 1014 } else { |
997 writeByte(Tag.FunctionType); | 1015 writeByte(Tag.FunctionType); |
998 _typeParameterIndexer.enter(node.typeParameters); | 1016 _typeParameterIndexer.enter(node.typeParameters); |
999 writeNodeList(node.typeParameters); | 1017 writeNodeList(node.typeParameters); |
1000 writeUInt30(node.requiredParameterCount); | 1018 writeUInt30(node.requiredParameterCount); |
| 1019 writeUInt30( |
| 1020 node.positionalParameters.length + node.namedParameters.length); |
1001 writeNodeList(node.positionalParameters); | 1021 writeNodeList(node.positionalParameters); |
1002 writeNodeList(node.namedParameters); | 1022 writeNodeList(node.namedParameters); |
1003 writeNode(node.returnType); | 1023 writeNode(node.returnType); |
1004 _typeParameterIndexer.exit(node.typeParameters); | 1024 _typeParameterIndexer.exit(node.typeParameters); |
1005 } | 1025 } |
1006 } | 1026 } |
1007 | 1027 |
1008 visitNamedType(NamedType node) { | 1028 visitNamedType(NamedType node) { |
1009 writeStringReference(node.name); | 1029 writeStringReference(node.name); |
1010 writeNode(node.type); | 1030 writeNode(node.type); |
1011 } | 1031 } |
1012 | 1032 |
1013 visitTypeParameterType(TypeParameterType node) { | 1033 visitTypeParameterType(TypeParameterType node) { |
1014 writeByte(Tag.TypeParameterType); | 1034 writeByte(Tag.TypeParameterType); |
1015 writeUInt30(_typeParameterIndexer[node.parameter]); | 1035 writeUInt30(_typeParameterIndexer[node.parameter]); |
| 1036 writeUInt30(node.parameter.binaryOffset); |
1016 writeOptionalNode(node.bound); | 1037 writeOptionalNode(node.bound); |
1017 } | 1038 } |
1018 | 1039 |
1019 visitVectorType(VectorType node) { | 1040 visitVectorType(VectorType node) { |
1020 writeByte(Tag.VectorType); | 1041 writeByte(Tag.VectorType); |
1021 } | 1042 } |
1022 | 1043 |
1023 visitTypedefType(TypedefType node) { | 1044 visitTypedefType(TypedefType node) { |
1024 writeByte(Tag.TypedefType); | 1045 writeByte(Tag.TypedefType); |
1025 writeReference(node.typedefReference); | 1046 writeReference(node.typedefReference); |
1026 writeNodeList(node.typeArguments); | 1047 writeNodeList(node.typeArguments); |
1027 } | 1048 } |
1028 | 1049 |
1029 visitTypeParameter(TypeParameter node) { | 1050 visitTypeParameter(TypeParameter node) { |
| 1051 node.binaryOffset = _sink.flushedLength + _sink.length; |
1030 writeStringReference(node.name ?? ''); | 1052 writeStringReference(node.name ?? ''); |
1031 writeNode(node.bound); | 1053 writeNode(node.bound); |
1032 } | 1054 } |
1033 | 1055 |
1034 defaultNode(Node node) { | 1056 defaultNode(Node node) { |
1035 throw 'Unsupported node: $node'; | 1057 throw 'Unsupported node: $node'; |
1036 } | 1058 } |
1037 } | 1059 } |
1038 | 1060 |
1039 typedef bool LibraryFilter(Library _); | 1061 typedef bool LibraryFilter(Library _); |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1300 } | 1322 } |
1301 } | 1323 } |
1302 | 1324 |
1303 /// Puts a buffer in front of a [Sink<List<int>>]. | 1325 /// Puts a buffer in front of a [Sink<List<int>>]. |
1304 class BufferedSink { | 1326 class BufferedSink { |
1305 static const int SIZE = 100000; | 1327 static const int SIZE = 100000; |
1306 static const int SMALL = 10000; | 1328 static const int SMALL = 10000; |
1307 final Sink<List<int>> _sink; | 1329 final Sink<List<int>> _sink; |
1308 Uint8List _buffer = new Uint8List(SIZE); | 1330 Uint8List _buffer = new Uint8List(SIZE); |
1309 int length = 0; | 1331 int length = 0; |
| 1332 int flushedLength = 0; |
1310 | 1333 |
1311 BufferedSink(this._sink); | 1334 BufferedSink(this._sink); |
1312 | 1335 |
1313 void addByte(int byte) { | 1336 void addByte(int byte) { |
1314 _buffer[length++] = byte; | 1337 _buffer[length++] = byte; |
1315 if (length == SIZE) { | 1338 if (length == SIZE) { |
1316 _sink.add(_buffer); | 1339 _sink.add(_buffer); |
1317 _buffer = new Uint8List(SIZE); | 1340 _buffer = new Uint8List(SIZE); |
1318 length = 0; | 1341 length = 0; |
| 1342 flushedLength += SIZE; |
1319 } | 1343 } |
1320 } | 1344 } |
1321 | 1345 |
1322 void addBytes(List<int> bytes) { | 1346 void addBytes(List<int> bytes) { |
1323 // Avoid copying a large buffer into the another large buffer. Also, if | 1347 // Avoid copying a large buffer into the another large buffer. Also, if |
1324 // the bytes buffer is too large to fit in our own buffer, just emit both. | 1348 // the bytes buffer is too large to fit in our own buffer, just emit both. |
1325 if (length + bytes.length < SIZE && | 1349 if (length + bytes.length < SIZE && |
1326 (bytes.length < SMALL || length < SMALL)) { | 1350 (bytes.length < SMALL || length < SMALL)) { |
1327 if (length == 0) { | 1351 if (length == 0) { |
1328 _sink.add(bytes); | 1352 _sink.add(bytes); |
| 1353 flushedLength += bytes.length; |
1329 } else { | 1354 } else { |
1330 _buffer.setRange(length, length + bytes.length, bytes); | 1355 _buffer.setRange(length, length + bytes.length, bytes); |
1331 length += bytes.length; | 1356 length += bytes.length; |
1332 } | 1357 } |
1333 } else if (bytes.length < SMALL) { | 1358 } else if (bytes.length < SMALL) { |
1334 // Flush as much as we can in the current buffer. | 1359 // Flush as much as we can in the current buffer. |
1335 _buffer.setRange(length, SIZE, bytes); | 1360 _buffer.setRange(length, SIZE, bytes); |
1336 _sink.add(_buffer); | 1361 _sink.add(_buffer); |
1337 // Copy over the remainder into a new buffer. It is guaranteed to fit | 1362 // Copy over the remainder into a new buffer. It is guaranteed to fit |
1338 // because the input byte array is small. | 1363 // because the input byte array is small. |
1339 int alreadyEmitted = SIZE - length; | 1364 int alreadyEmitted = SIZE - length; |
1340 int remainder = bytes.length - alreadyEmitted; | 1365 int remainder = bytes.length - alreadyEmitted; |
1341 _buffer = new Uint8List(SIZE); | 1366 _buffer = new Uint8List(SIZE); |
1342 _buffer.setRange(0, remainder, bytes, alreadyEmitted); | 1367 _buffer.setRange(0, remainder, bytes, alreadyEmitted); |
1343 length = remainder; | 1368 length = remainder; |
| 1369 flushedLength += SIZE; |
1344 } else { | 1370 } else { |
1345 _sink.add(_buffer.sublist(0, length)); | 1371 _sink.add(_buffer.sublist(0, length)); |
1346 _sink.add(bytes); | 1372 _sink.add(bytes); |
1347 _buffer = new Uint8List(SIZE); | 1373 _buffer = new Uint8List(SIZE); |
| 1374 flushedLength += length; |
| 1375 flushedLength += bytes.length; |
1348 length = 0; | 1376 length = 0; |
1349 } | 1377 } |
1350 } | 1378 } |
1351 | 1379 |
1352 void flush() { | 1380 void flush() { |
1353 _sink.add(_buffer.sublist(0, length)); | 1381 _sink.add(_buffer.sublist(0, length)); |
1354 _buffer = new Uint8List(SIZE); | 1382 _buffer = new Uint8List(SIZE); |
| 1383 flushedLength += length; |
1355 length = 0; | 1384 length = 0; |
1356 } | 1385 } |
1357 | 1386 |
1358 void flushAndDestroy() { | 1387 void flushAndDestroy() { |
1359 _sink.add(_buffer.sublist(0, length)); | 1388 _sink.add(_buffer.sublist(0, length)); |
1360 } | 1389 } |
1361 } | 1390 } |
OLD | NEW |