Skip to content

Commit

Permalink
std/jpeg: call slice.bulk_memset
Browse files Browse the repository at this point in the history
  • Loading branch information
nigeltao committed Jun 4, 2023
1 parent 5edfe45 commit 2f18dc6
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 91 deletions.
8 changes: 8 additions & 0 deletions internal/cgen/base/fundamental-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,14 @@ wuffs_base__slice_u8__copy_from_slice(wuffs_base__slice_u8 dst,
return len;
}

static inline wuffs_base__empty_struct //
wuffs_base__bulk_memset(void* ptr, size_t len, uint8_t byte_value) {
if (len) {
memset(ptr, byte_value, len);
}
return wuffs_base__make_empty_struct();
}

// --------

static inline wuffs_base__slice_u8 //
Expand Down
63 changes: 63 additions & 0 deletions internal/cgen/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,69 @@ func (g *gen) writeBuiltinNumType(b *buffer, recv *a.Expr, method t.ID, args []*

func (g *gen) writeBuiltinSlice(b *buffer, recv *a.Expr, method t.ID, args []*a.Node, sideEffectsOnly bool, depth uint32) error {
switch method {
case t.IDBulkMemset:
if arrayOrSlice, lo, hi, ok := recv.IsSlice(); !ok {
return fmt.Errorf("TODO: bulk_memset for general expressions")

} else if hi == nil {
return fmt.Errorf("TODO: bulk_memset for general expressions")

} else if arrayOrSlice.MType().IsBulkNumType() {
b.writes("wuffs_base__bulk_memset(&")
if err := g.writeExpr(b, arrayOrSlice, false, depth); err != nil {
return err
}
if lo == nil {
b.writes("[0], ")
if err := g.writeExpr(b, hi, false, depth); err != nil {
return err
}
} else {
b.writes("[")
if err := g.writeExpr(b, lo, false, depth); err != nil {
return err
}
b.writes("], (")
if err := g.writeExpr(b, hi, false, depth); err != nil {
return err
}
b.writes(" - ")
if err := g.writeExpr(b, lo, false, depth); err != nil {
return err
}
b.writes(")")
}
if bs := arrayOrSlice.MType().Inner().BulkSize(); (bs != nil) && (bs.Cmp(one) != 0) {
b.writes(" * (size_t)")
b.writes(bs.String())
b.writes("u")
}
b.writes(", ")

return g.writeArgs(b, args, depth)

} else if arrayOrSlice.MType().IsContainerOfSpecificNumType(t.IDSlice, t.IDU8) {
b.writes("wuffs_base__bulk_memset(")
if err := g.writeExpr(b, recv, false, depth); err != nil {
return err
}
b.writes(".ptr, ")
if err := g.writeExpr(b, recv, false, depth); err != nil {
return err
}
b.writes(".len")
if bs := arrayOrSlice.MType().Inner().BulkSize(); (bs != nil) && (bs.Cmp(one) != 0) {
b.writes(" * (size_t)")
b.writes(bs.String())
b.writes("u")
}
b.writes(", ")
return g.writeArgs(b, args, depth)

} else {
return fmt.Errorf("TODO: bulk_memset for general expressions")
}

case t.IDCopyFromSlice:
if err := g.writeBuiltinSliceCopyFromSlice8(b, recv, method, args, depth); err != errOptimizationNotApplicable {
return err
Expand Down
31 changes: 31 additions & 0 deletions lang/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,33 @@ func (n *TypeExpr) Pointee() *TypeExpr {
return n
}

func (n *TypeExpr) BulkSize() *big.Int {
if !n.IsBulkNumType() {
return nil
}
ret := big.NewInt(1)
for ; n.id0 == t.IDArray; n = n.rhs.AsTypeExpr() {
ret = ret.Mul(ret, n.ArrayLength().ConstValue())
}
switch n.id2 {
case t.IDU8:
return ret
case t.IDU16:
return ret.Lsh(ret, 1)
case t.IDU32:
return ret.Lsh(ret, 2)
case t.IDU64:
return ret.Lsh(ret, 3)
}
return nil
}

func (n *TypeExpr) IsBulkNumType() bool {
for ; n.id0 == t.IDArray; n = n.rhs.AsTypeExpr() {
}
return n.id0 == 0 && n.id1 == t.IDBase && n.id2.IsNumType()
}

func (n *TypeExpr) IsBool() bool {
return n.id0 == 0 && n.id1 == t.IDBase && n.id2 == t.IDBool
}
Expand Down Expand Up @@ -914,6 +941,10 @@ func (n *TypeExpr) IsReadOnly() bool {
return (n.id0 == t.IDRoarray) || (n.id0 == t.IDRoslice) || (n.id0 == t.IDRotable)
}

func (n *TypeExpr) IsContainerOfSpecificNumType(container t.ID, numType t.ID) bool {
return (n.id0 == container) && n.Inner().IsNumType() && (n.Inner().id2 == numType)
}

func (n *TypeExpr) IsUnsignedInteger() bool {
return n.id0 == 0 && n.id1 == t.IDBase &&
(n.id2 == t.IDU8 || n.id2 == t.IDU16 || n.id2 == t.IDU32 || n.id2 == t.IDU64)
Expand Down
5 changes: 5 additions & 0 deletions lang/builtin/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,11 @@ var SliceFuncs = []string{
"GENERIC T1.prefix(up_to: u64) T1",
"GENERIC T1.uintptr_low_12_bits() u32[..= 4095]",
"GENERIC T1.suffix(up_to: u64) T1",

// The bulk_etc methods are further restricted to those slices whose
// elements are bulk-numeric types: numerics (e.g. base.u32), arrays of
// numerics, arrays of arrays of numerics, etc.
"GENERIC T1.bulk_memset!(byte_value: u8)",
}

var SliceU8Funcs = []string{
Expand Down
12 changes: 10 additions & 2 deletions lang/check/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -730,8 +730,16 @@ func (q *checker) tcheckDot(n *a.Expr, depth uint32) error {
qqid[0] = t.IDBase
qqid[1] = t.IDDagger1
if q.c.isBuiltInSliceFunc(qqid, lTyp) {
n.SetMType(a.NewTypeExpr(t.IDFunc, 0, n.Ident(), lTyp.AsNode(), nil, nil))
return nil
bulky := false
switch qqid[2] {
case t.IDBulkMemset:
bulky = true
}

if !bulky || lTyp.Inner().IsBulkNumType() {
n.SetMType(a.NewTypeExpr(t.IDFunc, 0, n.Ident(), lTyp.AsNode(), nil, nil))
return nil
}
}
return fmt.Errorf("check: no %s method %q", lTyp.Decorator().Str(q.tm), n.Ident().Str(q.tm))

Expand Down
18 changes: 9 additions & 9 deletions lang/token/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -668,14 +668,14 @@ const (
IDIsOK = ID(0x231)
IDIsSuspension = ID(0x232)

IDData = ID(0x240)
IDHeight = ID(0x241)
IDIO = ID(0x242)
IDLimit = ID(0x243)
IDPrefix = ID(0x244)
IDRowU32 = ID(0x245)
IDStride = ID(0x246)
IDSubslice = ID(0x247)
IDBulkMemset = ID(0x240)
IDData = ID(0x241)
IDHeight = ID(0x242)
IDIO = ID(0x243)
IDLimit = ID(0x244)
IDPrefix = ID(0x245)
IDRowU32 = ID(0x246)
IDStride = ID(0x247)
IDSubtable = ID(0x248)
IDSuffix = ID(0x249)
IDUintptrLow12Bits = ID(0x24A)
Expand Down Expand Up @@ -1100,14 +1100,14 @@ var builtInsByID = [nBuiltInIDs]string{
IDIsOK: "is_ok",
IDIsSuspension: "is_suspension",

IDBulkMemset: "bulk_memset",
IDData: "data",
IDHeight: "height",
IDIO: "io",
IDLimit: "limit",
IDPrefix: "prefix",
IDRowU32: "row_u32",
IDStride: "stride",
IDSubslice: "subslice",
IDSubtable: "subtable",
IDSuffix: "suffix",
IDUintptrLow12Bits: "uintptr_low_12_bits",
Expand Down
60 changes: 21 additions & 39 deletions release/c/wuffs-unsupported-snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -12277,6 +12277,14 @@ wuffs_base__slice_u8__copy_from_slice(wuffs_base__slice_u8 dst,
return len;
}

static inline wuffs_base__empty_struct //
wuffs_base__bulk_memset(void* ptr, size_t len, uint8_t byte_value) {
if (len) {
memset(ptr, byte_value, len);
}
return wuffs_base__make_empty_struct();
}

// --------

static inline wuffs_base__slice_u8 //
Expand Down Expand Up @@ -36853,10 +36861,6 @@ wuffs_jpeg__decoder__fill_bitstream(
wuffs_jpeg__decoder* self,
wuffs_base__io_buffer* a_src);

static wuffs_base__empty_struct
wuffs_jpeg__decoder__clear_mcu_blocks(
wuffs_jpeg__decoder* self);

static wuffs_base__empty_struct
wuffs_jpeg__decoder__load_mcu_blocks(
wuffs_jpeg__decoder* self,
Expand Down Expand Up @@ -38937,8 +38941,6 @@ wuffs_jpeg__decoder__do_decode_frame(

uint32_t v_pixfmt = 0;
wuffs_base__status v_status = wuffs_base__make_status(NULL);
uint64_t v_i = 0;
uint64_t v_i_end = 0;
uint8_t v_c = 0;
uint8_t v_marker = 0;

Expand Down Expand Up @@ -38997,15 +38999,15 @@ wuffs_jpeg__decoder__do_decode_frame(
}
goto ok;
}
v_i = self->private_impl.f_components_workbuf_offsets[4];
v_i_end = self->private_impl.f_components_workbuf_offsets[8];
if (v_i_end > ((uint64_t)(a_workbuf.len))) {
if (self->private_impl.f_components_workbuf_offsets[8] > ((uint64_t)(a_workbuf.len))) {
status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length);
goto exit;
}
while (v_i < v_i_end) {
a_workbuf.ptr[v_i] = 0;
v_i += 1;
} else if (self->private_impl.f_components_workbuf_offsets[4] < self->private_impl.f_components_workbuf_offsets[8]) {
wuffs_base__bulk_memset(wuffs_base__slice_u8__subslice_ij(a_workbuf,
self->private_impl.f_components_workbuf_offsets[4],
self->private_impl.f_components_workbuf_offsets[8]).ptr, wuffs_base__slice_u8__subslice_ij(a_workbuf,
self->private_impl.f_components_workbuf_offsets[4],
self->private_impl.f_components_workbuf_offsets[8]).len, 0);
}
label__0__continue:;
while (true) {
Expand Down Expand Up @@ -39516,7 +39518,7 @@ wuffs_jpeg__decoder__decode_sos(
if (self->private_impl.f_sof_marker >= 194) {
wuffs_jpeg__decoder__load_mcu_blocks(self, v_mx, v_my, a_workbuf);
} else {
wuffs_jpeg__decoder__clear_mcu_blocks(self);
wuffs_base__bulk_memset(&self->private_data.f_mcu_blocks[0], self->private_impl.f_mcu_num_blocks * (size_t)128u, 0);
}
while (true) {
v_decode_mcu_result = wuffs_jpeg__decoder__decode_mcu(self);
Expand Down Expand Up @@ -39916,7 +39918,7 @@ wuffs_jpeg__decoder__fill_bitstream(
wuffs_base__io_buffer* a_src) {
uint32_t v_wi = 0;
uint8_t v_c = 0;
uint32_t v_n = 0;
uint32_t v_new_wi = 0;

const uint8_t* iop_a_src = NULL;
const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Expand Down Expand Up @@ -39961,11 +39963,11 @@ wuffs_jpeg__decoder__fill_bitstream(
label__0__break:;
if (((uint64_t)(io2_a_src - iop_a_src)) > 1) {
if ((wuffs_base__peek_u8be__no_bounds_check(iop_a_src) >= 255) && ((wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8) > 0)) {
v_n = (wuffs_base__u32__min(v_wi, 2016) + 32);
while (v_wi < v_n) {
self->private_data.f_bitstream_buffer[v_wi] = 0;
v_wi += 1;
v_new_wi = (wuffs_base__u32__min(v_wi, 2016) + 32);
if (v_wi < v_new_wi) {
wuffs_base__bulk_memset(&self->private_data.f_bitstream_buffer[v_wi], (v_new_wi - v_wi), 0);
}
v_wi = v_new_wi;
}
}
self->private_impl.f_bitstream_wi = v_wi;
Expand All @@ -39976,26 +39978,6 @@ wuffs_jpeg__decoder__fill_bitstream(
return wuffs_base__make_empty_struct();
}

// -------- func jpeg.decoder.clear_mcu_blocks

static wuffs_base__empty_struct
wuffs_jpeg__decoder__clear_mcu_blocks(
wuffs_jpeg__decoder* self) {
uint32_t v_b = 0;
uint32_t v_i = 0;

v_b = 0;
while (v_b < self->private_impl.f_mcu_num_blocks) {
v_i = 0;
while (v_i < 64) {
self->private_data.f_mcu_blocks[v_b][v_i] = 0;
v_i += 1;
}
v_b += 1;
}
return wuffs_base__make_empty_struct();
}

// -------- func jpeg.decoder.load_mcu_blocks

static wuffs_base__empty_struct
Expand Down
Loading

0 comments on commit 2f18dc6

Please sign in to comment.