@@ -14,6 +14,8 @@ package org.scalajs.linker.backend.webassembly
14
14
15
15
import scala .annotation .tailrec
16
16
17
+ import java .nio .{ByteBuffer , ByteOrder }
18
+
17
19
import org .scalajs .ir .{Position , UTF8String }
18
20
import org .scalajs .linker .backend .javascript .SourceMapWriter
19
21
@@ -84,7 +86,7 @@ private sealed class BinaryWriter(module: Module, emitDebugInfo: Boolean) {
84
86
protected def emitEndFuncPosition (): Unit = ()
85
87
protected def emitSourceMapSection (): Unit = ()
86
88
87
- def write (): Array [ Byte ] = {
89
+ def write (): ByteBuffer = {
88
90
// magic header: null char + "asm"
89
91
buf.byte(0 )
90
92
buf.byte('a' )
@@ -499,42 +501,43 @@ object BinaryWriter {
499
501
private final val SectionDataCount = 0x0C
500
502
private final val SectionTag = 0x0D
501
503
502
- def write (module : Module , emitDebugInfo : Boolean ): Array [ Byte ] =
504
+ def write (module : Module , emitDebugInfo : Boolean ): ByteBuffer =
503
505
new BinaryWriter (module, emitDebugInfo).write()
504
506
505
507
def writeWithSourceMap (module : Module , emitDebugInfo : Boolean ,
506
- sourceMapWriter : SourceMapWriter , sourceMapURI : String ): Array [ Byte ] = {
508
+ sourceMapWriter : SourceMapWriter , sourceMapURI : String ): ByteBuffer = {
507
509
new WithSourceMap (module, emitDebugInfo, sourceMapWriter, sourceMapURI).write()
508
510
}
509
511
510
512
private [BinaryWriter ] final class Buffer {
511
- private var buf : Array [Byte ] = new Array [Byte ](1024 * 1024 )
512
- private var size : Int = 0
513
-
514
- private def ensureCapacity (capacity : Int ): Unit = {
515
- if (buf.length < capacity) {
516
- val newCapacity = Integer .highestOneBit(capacity) << 1
517
- buf = java.util.Arrays .copyOf(buf, newCapacity)
513
+ private var buf : ByteBuffer =
514
+ ByteBuffer .allocate(1024 * 1024 ).order(ByteOrder .LITTLE_ENDIAN )
515
+
516
+ private def ensureRemaining (requiredRemaining : Int ): Unit = {
517
+ if (buf.remaining() < requiredRemaining) {
518
+ buf.flip()
519
+ val newCapacity = Integer .highestOneBit(buf.capacity() + requiredRemaining) << 1
520
+ val newBuf = ByteBuffer .allocate(newCapacity).order(ByteOrder .LITTLE_ENDIAN )
521
+ newBuf.put(buf)
522
+ buf = newBuf
518
523
}
519
524
}
520
525
521
- def currentGlobalOffset : Int = size
526
+ def currentGlobalOffset : Int = buf.position()
522
527
523
- def result (): Array [Byte ] =
524
- java.util.Arrays .copyOf(buf, size)
528
+ def result (): ByteBuffer = {
529
+ buf.flip()
530
+ buf
531
+ }
525
532
526
533
def byte (b : Byte ): Unit = {
527
- val newSize = size + 1
528
- ensureCapacity(newSize)
529
- buf(size) = b
530
- size = newSize
534
+ ensureRemaining(1 )
535
+ buf.put(b)
531
536
}
532
537
533
538
def rawByteArray (array : Array [Byte ]): Unit = {
534
- val newSize = size + array.length
535
- ensureCapacity(newSize)
536
- System .arraycopy(array, 0 , buf, size, array.length)
537
- size = newSize
539
+ ensureRemaining(array.length)
540
+ buf.put(array)
538
541
}
539
542
540
543
def boolean (b : Boolean ): Unit =
@@ -555,23 +558,13 @@ object BinaryWriter {
555
558
def i64 (value : Long ): Unit = s64(value)
556
559
557
560
def f32 (value : Float ): Unit = {
558
- val bits = java.lang.Float .floatToIntBits(value)
559
- byte(bits.toByte)
560
- byte((bits >>> 8 ).toByte)
561
- byte((bits >>> 16 ).toByte)
562
- byte((bits >>> 24 ).toByte)
561
+ ensureRemaining(4 )
562
+ buf.putFloat(value)
563
563
}
564
564
565
565
def f64 (value : Double ): Unit = {
566
- val bits = java.lang.Double .doubleToLongBits(value)
567
- byte(bits.toByte)
568
- byte((bits >>> 8 ).toByte)
569
- byte((bits >>> 16 ).toByte)
570
- byte((bits >>> 24 ).toByte)
571
- byte((bits >>> 32 ).toByte)
572
- byte((bits >>> 40 ).toByte)
573
- byte((bits >>> 48 ).toByte)
574
- byte((bits >>> 56 ).toByte)
566
+ ensureRemaining(8 )
567
+ buf.putDouble(value)
575
568
}
576
569
577
570
def vec [A ](elems : Iterable [A ])(op : A => Unit ): Unit = {
@@ -589,25 +582,21 @@ object BinaryWriter {
589
582
def name (utf8 : UTF8String ): Unit = {
590
583
val len = utf8.length
591
584
u32(len)
592
- ensureCapacity(size + len)
593
- var i = 0
594
- while (i != len) {
595
- byte(utf8(i))
596
- i += 1
597
- }
585
+ ensureRemaining(len)
586
+ utf8.writeTo(buf)
598
587
}
599
588
600
589
def byteLengthSubSection (subSectionContent : => Unit ): Unit = {
601
590
// Reserve 4 bytes at the current offset to store the byteLength later
602
- val byteLengthOffset = size
603
- val startOffset = byteLengthOffset + 4
604
- ensureCapacity( startOffset)
605
- size = startOffset // do not write the 4 bytes for now
591
+ val byteLengthOffset = buf.position()
592
+ ensureRemaining( 4 )
593
+ val startOffset = buf.position() + 4
594
+ buf.position( startOffset) // do not write the 4 bytes for now
606
595
607
596
subSectionContent
608
597
609
598
// Compute byteLength
610
- val endOffset = size
599
+ val endOffset = buf.position()
611
600
val byteLength = endOffset - startOffset
612
601
613
602
/* Because we limited ourselves to 4 bytes, we cannot represent a size
@@ -623,10 +612,10 @@ object BinaryWriter {
623
612
* when we write the code section, which is important to efficiently
624
613
* generate source maps.
625
614
*/
626
- buf(byteLengthOffset) = ((byteLength & 0x7F ) | 0x80 ).toByte
627
- buf(byteLengthOffset + 1 ) = (((byteLength >>> 7 ) & 0x7F ) | 0x80 ).toByte
628
- buf(byteLengthOffset + 2 ) = (((byteLength >>> 14 ) & 0x7F ) | 0x80 ).toByte
629
- buf(byteLengthOffset + 3 ) = ((byteLength >>> 21 ) & 0x7F ).toByte
615
+ buf.put (byteLengthOffset, ((byteLength & 0x7F ) | 0x80 ).toByte)
616
+ buf.put (byteLengthOffset + 1 , (((byteLength >>> 7 ) & 0x7F ) | 0x80 ).toByte)
617
+ buf.put (byteLengthOffset + 2 , (((byteLength >>> 14 ) & 0x7F ) | 0x80 ).toByte)
618
+ buf.put (byteLengthOffset + 3 , ((byteLength >>> 21 ) & 0x7F ).toByte)
630
619
}
631
620
632
621
@ tailrec
0 commit comments