Subversion Repositories Kolibri OS

Rev

Rev 9715 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8.  
  9. ; Small heap based on malloc/free/realloc written by Doug Lea
  10. ; Version 2.8.3 Thu Sep 22 11:16:15 2005  Doug Lea  (dl at gee)
  11. ; Source ftp://gee.cs.oswego.edu/pub/misc/malloc.c
  12. ; License http://creativecommons.org/licenses/publicdomain.
  13.  
  14.  
  15. ; eax= size
  16.  
  17. ; temp
  18. ;  esi= nb
  19. ;  ebx= idx
  20. ;
  21. align 4
  22. malloc:
  23.         push    ebx esi
  24.  
  25. ; nb = ((size+7)&~7)+8;
  26.  
  27.         mov     esi, eax   ;size
  28.         add     esi, 7
  29.         and     esi, -8
  30.         add     esi, 8
  31.  
  32.         mov     ecx, mst.mutex
  33.         call    mutex_lock
  34.  
  35.         cmp     esi, 256
  36.         jae     .large
  37.  
  38.         mov     ecx, esi
  39.         shr     ecx, 3
  40.         or      eax, -1
  41.         shl     eax, cl
  42.         and     eax, [mst.smallmap]
  43.         jz      .small
  44.  
  45.         push    ebp
  46.         push    edi
  47.  
  48.         bsf     eax, eax
  49.         mov     ebx, eax
  50.  
  51. ; psize= idx<<3;
  52. ; B = &ms.smallbins[idx];
  53. ; p = B->fd;
  54. ; F = p->fd;
  55. ; rsize= psize-nb;
  56.  
  57.         lea     ebp, [eax*8]              ;ebp= psize
  58.         shl     eax, 4
  59.         lea     edi, [mst.smallbins+eax]  ;edi= B
  60.         mov     edx, [edi+8]              ;edx= p
  61.         mov     eax, [edx+8]              ;eax= F
  62.         mov     ecx, ebp
  63.         sub     ecx, esi                  ;ecx= rsize
  64.  
  65. ; if (B == F)
  66.         cmp     edi, eax
  67.         jne     @F
  68.  
  69.         btr     [mst.smallmap], ebx
  70. @@:
  71.  
  72. ; B->fd = F;
  73. ; F->bk = B;
  74. ; if(rsize<16)
  75.  
  76.         cmp     ecx, 16
  77.         mov     [edi+8], eax
  78.         mov     [eax+12], edi
  79.         jae     .split
  80.  
  81. ; p->head = psize|PINUSE_BIT|CINUSE_BIT;
  82. ; (p + psize)->head |= PINUSE_BIT;
  83.  
  84.         lea     eax, [edx+8]
  85.         or      dword [edx+ebp+4], 1
  86.  
  87.         or      ebp, 3
  88.         mov     [edx+4], ebp
  89.  
  90.         pop     edi
  91.         pop     ebp
  92. .done:
  93.         mov     esi, eax
  94.         mov     ecx, mst.mutex
  95.         call    mutex_unlock
  96.         mov     eax, esi
  97.         pop     esi ebx
  98.         ret
  99.  
  100. .split:
  101.         lea     ebx, [edx+8]              ;ebx=mem
  102.  
  103. ; r = chunk_plus_offset(p, nb);
  104. ; p->head = nb|PINUSE_BIT|CINUSE_BIT;
  105. ; r->head = rsize|PINUSE_BIT;
  106.  
  107.         lea     eax, [edx+esi]            ;eax= r
  108.         or      esi, 3
  109.         mov     [edx+4], esi
  110.  
  111.         mov     edx, ecx
  112.         or      edx, 1
  113.         mov     [eax+4], edx
  114.  
  115. ; (r + rsize)->prev_foot = rsize;
  116.  
  117.         mov     [eax+ecx], ecx
  118.  
  119. ; I  = rsize>>3;
  120.  
  121.         shr     ecx, 3
  122.  
  123. ;      ms.smallmap |=  1<< I;
  124.         bts     [mst.smallmap], ecx
  125.  
  126. ; B = &ms.smallbins[I];
  127.  
  128.         shl     ecx, 4
  129.         pop     edi
  130.         pop     ebp
  131.         add     ecx, mst.smallbins        ;ecx= B
  132.  
  133.         mov     edx, [ecx+8]              ; F = B->fd;
  134.         mov     [ecx+8], eax              ; B->fd = r;
  135.         mov     [edx+12], eax             ; F->bk = r;
  136.         mov     [eax+8], edx              ; r->fd = F;
  137.         mov     [eax+12], ecx             ; r->bk = B;
  138.  
  139.         mov     eax, ebx
  140.         jmp     .done
  141.  
  142. .small:
  143.  
  144. ; if (ms.treemap != 0 && (mem = malloc_small(nb)) != 0)
  145. ;;;;;;;;;;; start a change <lrz>
  146.         mov     eax, [mst.treemap]
  147.         test    eax, eax
  148. ;;;;;;;;;;; end the change <lrz>
  149. ;           cmp [mst.treemap], 0
  150.         jz      .from_top
  151.         mov     eax, esi
  152.         call    malloc_small
  153.         test    eax, eax
  154.         jz      .from_top
  155.         jmp     .done
  156.  
  157. .large:
  158.  
  159. ; if (ms.treemap != 0 && (mem = malloc_large(nb)) != 0)
  160.  
  161.         cmp     [mst.treemap], 0
  162.         je      .from_top
  163.  
  164.         call    malloc_large  ;esi= nb
  165.         test    eax, eax
  166.         jne     .done
  167. .from_top:
  168.  
  169. ; if (nb < ms.topsize)
  170.  
  171.         mov     eax, [mst.topsize]
  172.         cmp     esi, eax
  173.         jae     .fail
  174.  
  175. ; rsize = ms.topsize -= nb;
  176. ; p = ms.top;
  177.  
  178.         mov     ecx, [mst.top]
  179.         sub     eax, esi
  180.         mov     [mst.topsize], eax
  181.  
  182. ; r = ms.top = chunk_plus_offset(p, nb);
  183. ; r->head = rsize | PINUSE_BIT;
  184. ; p->head = nb |PINUSE_BIT|CINUSE_BIT;
  185.  
  186.         lea     edx, [ecx+esi]
  187.         or      eax, 1
  188.         mov     [mst.top], edx
  189.         or      esi, 3
  190.         mov     [edx+4], eax
  191.         mov     [ecx+4], esi
  192.         lea     eax, [ecx+8]
  193.         jmp     .done
  194.  
  195. .fail:
  196.         xor     eax, eax
  197.         jmp     .done
  198.  
  199. ; param
  200. ;  eax= mem
  201. align 4
  202. free:
  203.         test    eax, eax
  204.         jz      .exit
  205.  
  206.         push    ebx edi
  207.         mov     edi, eax
  208.         add     edi, -8
  209.  
  210. ; if(p->head & CINUSE_BIT)
  211.  
  212.         test    byte [edi+4], 2
  213.         je      .fail
  214.  
  215.         mov     ecx, mst.mutex
  216.         call    mutex_lock
  217.  
  218. ; psize = p->head & (~3);
  219.  
  220.         mov     eax, [edi+4]
  221.         push    esi
  222.         mov     esi, eax
  223.         and     esi, -4
  224.  
  225. ; next = chunk_plus_offset(p, psize);
  226. ; if(!(p->head & PINUSE_BIT))
  227.  
  228.         test    al, 1
  229.         lea     ebx, [esi+edi]
  230.         jne     .next
  231.  
  232. ; prevsize = p->prev_foot;
  233. ; prev=p - prevsize;
  234. ; psize += prevsize;
  235. ; p = prev;
  236.  
  237.         mov     ecx, [edi] ;ecx= prevsize
  238.         add     esi, ecx             ;esi= psize
  239.         sub     edi, ecx             ;edi= p
  240.  
  241. ; if (prevsize < 256)
  242.  
  243.         cmp     ecx, 256
  244.         jae     .unlink_large
  245.  
  246.         mov     eax, [edi+8]         ;F = p->fd;
  247.         mov     edx, [edi+12]        ;B = p->bk;
  248.  
  249. ; if (F == B)
  250. ; ms.smallmap &=  ~(1<< I);
  251.         shr     ecx, 3
  252.         cmp     eax, edx
  253.         jne     @F
  254.         btr     [mst.smallmap], ecx
  255. @@:
  256.         mov     [eax+12], edx          ;F->bk = B;
  257.         mov     [edx+8], eax           ;B->fd = F
  258.         jmp     .next
  259. .unlink_large:
  260.         mov     edx, edi
  261.         call    unlink_large_chunk
  262. .next:
  263.  
  264. ; if(next->head & PINUSE_BIT)
  265.  
  266.         mov     eax, [ebx+4]
  267.         test    al, 1
  268.         jz      .fail2
  269.  
  270. ; if (! (next->head & CINUSE_BIT))
  271.  
  272.         test    al, 2
  273.         jnz     .fix_next
  274.  
  275. ; if (next == ms.top)
  276.  
  277.         cmp     ebx, [mst.top]
  278.         jne     @F
  279.  
  280. ; tsize = ms.topsize += psize;
  281.  
  282.         mov     eax, [mst.topsize]
  283.         add     eax, esi
  284.         mov     [mst.topsize], eax
  285.  
  286. ; ms.top = p;
  287. ; p->head = tsize | PINUSE_BIT;
  288.  
  289.         or      eax, 1
  290.         mov     [mst.top], edi
  291.         mov     [edi+4], eax
  292. .fail2:
  293.         mov     esi, eax
  294.         mov     ecx, mst.mutex
  295.         call    mutex_unlock
  296.         mov     eax, esi
  297.         pop     esi
  298. .fail:
  299.         pop     edi ebx
  300. .exit:
  301.         ret
  302.  
  303. @@:
  304.  
  305. ; nsize = next->head & ~INUSE_BITS;
  306.  
  307.         and     eax, -4
  308.         add     esi, eax               ;psize += nsize;
  309.  
  310. ; if (nsize < 256)
  311.  
  312.         cmp     eax, 256
  313.         jae     .unl_large
  314.  
  315.         mov     edx, [ebx+8]           ;F = next->fd
  316.         mov     ebx, [ebx+12]          ;B = next->bk
  317.  
  318. ; if (F == B)
  319.  
  320.         cmp     edx, ebx
  321.         jne     @F
  322.         mov     ecx, eax
  323.         shr     ecx, 3
  324.         btr     [mst.smallmap], ecx
  325. @@:
  326.         mov     [edx+12], ebx          ;F->bk = B
  327.  
  328. ; p->head = psize|PINUSE_BIT;
  329.  
  330.         mov     ecx, esi
  331.         mov     [ebx+8], edx
  332.         or      ecx, 1
  333.         mov     [edi+4], ecx
  334.  
  335. ; (p+psize)->prev_foot = psize;
  336.  
  337.         mov     [esi+edi], esi
  338.  
  339. ; insert_chunk(p,psize);
  340.  
  341.         mov     eax, esi
  342.         mov     ecx, edi
  343.         call    insert_chunk
  344.         jmp     .fail2
  345. .unl_large:
  346.  
  347. ; unlink_large_chunk((tchunkptr)next);
  348.  
  349.         mov     edx, ebx
  350.         call    unlink_large_chunk
  351. ; p->head = psize|PINUSE_BIT;
  352.  
  353.         mov     ecx, esi
  354.         or      ecx, 1
  355.         mov     [edi+4], ecx
  356.  
  357. ; (p+psize)->prev_foot = psize;
  358.  
  359.         mov     [esi+edi], esi
  360.  
  361. ; insert_chunk(p,psize);
  362.  
  363.         mov     eax, esi
  364.         mov     ecx, edi
  365.         call    insert_chunk
  366.         jmp     .fail2
  367. .fix_next:
  368.  
  369. ; (p+psize)->prev_foot = psize;
  370. ; next->head &= ~PINUSE_BIT;
  371. ; p->head = psize|PINUSE_BIT;
  372.  
  373.         and     eax, -2
  374.         mov     edx, esi
  375.         mov     [ebx+4], eax
  376.         or      edx, 1
  377.         mov     [edi+4], edx
  378.  
  379. ; (p+psize)->prev_foot = psize;
  380.  
  381.         mov     [esi+edi], esi
  382. ; insert_chunk(p,psize);
  383.  
  384.         mov     eax, esi
  385.         mov     ecx, edi
  386.         call    insert_chunk
  387.         jmp     .fail2
  388.  
  389. ; param
  390. ;  ecx = chunk
  391. ;  eax = size
  392.  
  393. insert_chunk:
  394.  
  395.         cmp     eax, 256
  396.         push    esi
  397.         mov     esi, ecx
  398.         jae     .large
  399.  
  400. ; I  = S>>3;
  401. ; ms.smallmap |=  1<< I;
  402.  
  403.         shr     eax, 3
  404.         bts     [mst.smallmap], eax
  405.  
  406. ; B = &ms.smallbins[I];
  407.  
  408.         shl     eax, 4
  409.         add     eax, mst.smallbins
  410.         mov     edx, [eax+8]           ;F = B->fd
  411.         mov     [eax+8], esi           ;B->fd = P
  412.         mov     [edx+12], esi          ;F->bk = P
  413.         mov     [esi+8], edx           ;P->fd = F
  414.         mov     [esi+12], eax          ;P->bk = B
  415.         pop     esi
  416.         ret
  417. .large:
  418.         mov     ebx, eax
  419.         call    insert_large_chunk
  420.         pop     esi
  421.         ret
  422.  
  423.  
  424. ; param
  425. ;  esi= chunk
  426. ;  ebx= size
  427.  
  428. insert_large_chunk:
  429.  
  430. ; I = compute_tree_index(S);
  431.  
  432.         mov     edx, ebx
  433.         shr     edx, 8
  434.         bsr     eax, edx
  435.         lea     ecx, [eax+7]
  436.         mov     edx, ebx
  437.         shr     edx, cl
  438.         and     edx, 1
  439.         lea     ecx, [edx+eax*2]
  440.  
  441. ; X->index = I;
  442.         mov     dword [esi+28], ecx
  443.  
  444. ; X->child[0] = X->child[1] = 0;
  445.         and     dword [esi+20], 0
  446.         and     dword [esi+16], 0
  447.  
  448. ; H = &ms.treebins[I];
  449.  
  450.         mov     eax, ecx
  451.         lea     edx, [mst.treebins+eax*4]
  452.  
  453. ; if (!(ms.treemap & 1<<I))
  454.         bt      [mst.treemap], ecx
  455.         jc      .tree
  456.  
  457. ; ms.treemap |= 1<<I;
  458.         bts     [mst.treemap], ecx
  459. ; *H = X;
  460.         mov     dword [edx], esi
  461.         jmp     .done
  462. .tree:
  463.  
  464. ; T = *H;
  465.         mov     edx, [edx]
  466.  
  467. ; K = S << leftshift_for_tree_index(I);
  468.         mov     eax, ecx
  469.         shr     eax, 1
  470.         sub     ecx, 31
  471.         mov     edi, 37
  472.         sub     edi, eax
  473.         neg     ecx
  474.         sbb     ecx, ecx
  475.         and     ecx, edi
  476.         mov     eax, ebx
  477.         shl     eax, cl    ;eax= K
  478.  
  479.         jmp     .loop
  480. .not_eq_size:
  481.  
  482. ; C = &(T->child[(K >> 31) & 1]);
  483.         mov     ecx, eax
  484.         shr     ecx, 31
  485.         lea     ecx, [edx+ecx*4+16]
  486.  
  487. ; K <<= 1;
  488. ; if (*C != 0)
  489.         mov     edi, [ecx]
  490.         add     eax, eax
  491.         test    edi, edi
  492.         jz      .insert_child
  493.  
  494. ; T = *C;
  495.         mov     edx, edi
  496. .loop:
  497.  
  498. ; for (;;)
  499. ; if ((T->head & ~INUSE_BITS) != S)
  500.  
  501.         mov     ecx, [edx+4]
  502.         and     ecx, not 3
  503.         cmp     ecx, ebx
  504.         jne     .not_eq_size
  505.  
  506. ; F = T->fd;
  507.         mov     eax, [edx+8]
  508.  
  509. ; T->fd = F->bk = X;
  510.         mov     [eax+12], esi
  511.         mov     [edx+8], esi
  512.  
  513. ; X->fd = F;
  514. ; X->bk = T;
  515. ; X->parent = 0;
  516.  
  517.         and     dword [esi+24], 0
  518.         mov     [esi+8], eax
  519.         mov     [esi+12], edx
  520.         ret
  521. .insert_child:
  522.  
  523. ; *C = X;
  524.         mov     [ecx], esi
  525. .done:
  526.  
  527. ; X->parent = T;
  528.         mov     [esi+24], edx
  529.  
  530. ; X->fd = X->bk = X;
  531.         mov     [esi+12], esi
  532.         mov     [esi+8], esi
  533.         ret
  534.  
  535.  
  536. ; param
  537. ;  edx= chunk
  538.  
  539. unlink_large_chunk:
  540.  
  541.         mov     eax, [edx+12]
  542.         cmp     eax, edx
  543.         push    edi
  544.         mov     edi, [edx+24]
  545.         je      @F
  546.  
  547.         mov     ecx, [edx+8]          ;F = X->fd
  548.         mov     [ecx+12], eax         ;F->bk = R;
  549.         mov     [eax+8], ecx          ;R->fd = F
  550.         jmp     .parent
  551. @@:
  552.         mov     eax, [edx+20]
  553.         test    eax, eax
  554.         push    esi
  555.         lea     esi, [edx+20]
  556.         jne     .loop
  557.  
  558.         mov     eax, [edx+16]
  559.         test    eax, eax
  560.         lea     esi, [edx+16]
  561.         je      .l2
  562. .loop:
  563.         cmp     dword [eax+20], 0
  564.         lea     ecx, [eax+20]
  565.         jne     @F
  566.  
  567.         cmp     dword [eax+16], 0
  568.         lea     ecx, [eax+16]
  569.         je      .l1
  570. @@:
  571.         mov     eax, [ecx]
  572.         mov     esi, ecx
  573.         jmp     .loop
  574. .l1:
  575.         mov     dword [esi], 0
  576. .l2:
  577.         pop     esi
  578. .parent:
  579.         test    edi, edi
  580.         je      .done
  581.  
  582.         mov     ecx, [edx+28]
  583.         cmp     edx, [mst.treebins + ecx*4]
  584.         lea     ecx, [mst.treebins + ecx*4]
  585.         jne     .l3
  586.  
  587.         test    eax, eax
  588.         mov     [ecx], eax
  589.         jne     .l5
  590.  
  591.         mov     ecx, [edx+28]
  592.         btr     [mst.treemap], ecx
  593.         pop     edi
  594.         ret
  595.  
  596. .l3:
  597.         cmp     [edi+16], edx
  598.         jne     @F
  599.  
  600.         mov     [edi+16], eax
  601.         jmp     .l4
  602.  
  603. @@:
  604.         mov     [edi+20], eax
  605.  
  606. .l4:
  607.         test    eax, eax
  608.         je      .done
  609.  
  610. .l5:
  611.         mov     [eax+24], edi
  612.         mov     ecx, [edx+16]
  613.         test    ecx, ecx
  614.         je      .l6
  615.  
  616.         mov     [eax+16], ecx
  617.         mov     [ecx+24], eax
  618.  
  619. .l6:
  620.         mov     edx, [edx+20]
  621.         test    edx, edx
  622.         je      .done
  623.  
  624.         mov     [eax+20], edx
  625.         mov     [edx+24], eax
  626.  
  627. .done:
  628.         pop     edi
  629.         ret
  630.  
  631. ; param
  632. ;  esi= nb
  633.  
  634. malloc_small:
  635.         push    ebp
  636.         mov     ebp, esi
  637.  
  638.         push    edi
  639.  
  640.         bsf     eax, [mst.treemap]
  641.         mov     ecx, [mst.treebins + eax*4]
  642.  
  643. ; rsize = (t->head & ~INUSE_BITS) - nb;
  644.  
  645.         mov     edi, [ecx+4]
  646.         and     edi, -4
  647.         sub     edi, esi
  648.  
  649. .loop:
  650.         mov     ebx, ecx
  651.  
  652. .loop_1:
  653.  
  654. ; while ((t = leftmost_child(t)) != 0)
  655.  
  656.         mov     eax, [ecx+16]
  657.         test    eax, eax
  658.         jz      @F
  659.         mov     ecx, eax
  660.         jmp     .l1
  661.  
  662. @@:
  663.         mov     ecx, [ecx+20]
  664.  
  665. .l1:
  666.         test    ecx, ecx
  667.         jz      .unlink
  668.  
  669. ; trem = (t->head & ~INUSE_BITS) - nb;
  670.  
  671.         mov     eax, [ecx+4]
  672.         and     eax, -4
  673.         sub     eax, ebp
  674.  
  675. ; if (trem < rsize)
  676.  
  677.         cmp     eax, edi
  678.         jae     .loop_1
  679.  
  680. ; rsize = trem;
  681.  
  682.         mov     edi, eax
  683.         jmp     .loop
  684. .unlink:
  685.  
  686.  
  687. ; r = chunk_plus_offset((mchunkptr)v, nb);
  688. ; unlink_large_chunk(v);
  689.  
  690.         mov     edx, ebx
  691.         lea     esi, [ebx + ebp]
  692.         call    unlink_large_chunk
  693.  
  694. ; if (rsize < 16)
  695.  
  696.         cmp     edi, 16
  697.         jae     .split
  698.  
  699. ; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT;
  700.  
  701.         lea     ecx, [edi + ebp]
  702.  
  703. ; (v+rsize + nb)->head |= PINUSE_BIT;
  704.  
  705.         add     edi, ebx
  706.         lea     eax, [edi + ebp + 4]
  707.         pop     edi
  708.         or      ecx, 3
  709.         mov     [ebx + 4], ecx
  710.         or      dword [eax], 1
  711.         pop     ebp
  712.  
  713.         lea     eax, [ebx + 8]
  714.         ret
  715.  
  716. .split:
  717.  
  718. ; v->head = nb|PINUSE_BIT|CINUSE_BIT;
  719. ; r->head = rsize|PINUSE_BIT;
  720. ; (r+rsize)->prev_foot = rsize;
  721.  
  722.         or      ebp, 3
  723.         mov     edx, edi
  724.         or      edx, 1
  725.  
  726.         cmp     edi, 256
  727.         mov     [ebx+4], ebp
  728.         mov     [esi+4], edx
  729.         mov     [esi+edi], edi
  730.         jae     .large
  731.  
  732.         shr     edi, 3
  733.         bts     [mst.smallmap], edi
  734.  
  735.         mov     eax, edi
  736.         shl     eax, 4
  737.         add     eax, mst.smallbins
  738.  
  739.         mov     edx, [eax+8]
  740.         mov     [eax+8], esi
  741.         mov     [edx+12], esi
  742.         pop     edi
  743.         mov     [esi+12], eax
  744.         mov     [esi+8], edx
  745.         pop     ebp
  746.         lea     eax, [ebx+8]
  747.         ret
  748.  
  749. .large:
  750.         lea     eax, [ebx+8]
  751.         push    eax
  752.         mov     ebx, edi
  753.         call    insert_large_chunk
  754.         pop     eax
  755.         pop     edi
  756.         pop     ebp
  757.         ret
  758.  
  759.  
  760. ; param
  761. ;  esi= nb
  762.  
  763. malloc_large:
  764. .idx equ esp+4
  765. .rst equ esp
  766.  
  767.         push    ebp
  768.         push    esi
  769.         push    edi
  770.         sub     esp, 8
  771. ; v = 0;
  772. ; rsize = -nb;
  773.  
  774.         mov     edi, esi
  775.         mov     ebx, esi
  776.         xor     ebp, ebp
  777.         neg     edi
  778.  
  779. ; idx = compute_tree_index(nb);
  780.  
  781.         mov     edx, esi
  782.         shr     edx, 8
  783.         bsr     eax, edx
  784.         lea     ecx, [eax+7]
  785.         shr     esi, cl
  786.         and     esi, 1
  787.         lea     ecx, [esi + eax*2]
  788.         mov     [.idx], ecx
  789.  
  790. ; if ((t = ms.treebins[idx]) != 0)
  791.  
  792.         mov     eax, [mst.treebins + ecx*4]
  793.         test    eax, eax
  794.         jz      .l3
  795.  
  796. ; sizebits = nb << leftshift_for_tree_index(idx);
  797.  
  798.         cmp     ecx, 31
  799.         jne     @F
  800.         xor     ecx, ecx
  801.         jmp     .l1
  802.  
  803. @@:
  804.         mov     edx, ecx
  805.         shr     edx, 1
  806.         mov     ecx, 37
  807.         sub     ecx, edx
  808.  
  809. .l1:
  810.         mov     edx, ebx
  811.         shl     edx, cl
  812.  
  813. ; rst = 0;
  814.         mov     [.rst], ebp
  815.  
  816. .loop:
  817.  
  818. ; trem = (t->head & ~INUSE_BITS) - nb;
  819.  
  820.         mov     ecx, [eax+4]
  821.         and     ecx, -4
  822.         sub     ecx, ebx
  823.  
  824. ; if (trem < rsize)
  825.  
  826.         cmp     ecx, edi
  827.         jae     @F
  828. ; v = t;
  829. ; if ((rsize = trem) == 0)
  830.  
  831.         test    ecx, ecx
  832.         mov     ebp, eax
  833.         mov     edi, ecx
  834.         je      .l2
  835.  
  836. @@:
  837.  
  838. ; rt = t->child[1];
  839.  
  840.         mov     ecx, [eax+20]
  841.  
  842. ; t = t->child[(sizebits >> 31) & 1];
  843.  
  844.         mov     esi, edx
  845.         shr     esi, 31
  846.  
  847. ; if (rt != 0 && rt != t)
  848.  
  849.         test    ecx, ecx
  850.         mov     eax, [eax + esi*4+16]
  851.         jz      @F
  852.         cmp     ecx, eax
  853.         jz      @F
  854.  
  855. ; rst = rt;
  856.         mov     [.rst], ecx
  857.  
  858. @@:
  859. ; if (t == 0)
  860.  
  861.         test    eax, eax
  862.         jz      @F
  863.  
  864. ; sizebits <<= 1;
  865.  
  866.         add     edx, edx
  867.         jmp     .loop
  868.  
  869. @@:
  870. ; t = rst;
  871.         mov     eax, [.rst]
  872.  
  873. .l2:
  874. ; if (t == 0 && v == 0)
  875.  
  876.         test    eax, eax
  877.         jne     .l4
  878.         test    ebp, ebp
  879.         jne     .l7
  880.         mov     ecx, [.idx]
  881.  
  882. .l3:
  883.  
  884. ; leftbits = (-1<<idx) & ms.treemap;
  885. ; if (leftbits != 0)
  886.  
  887.         or      edx, -1
  888.         shl     edx, cl
  889.         and     edx, [mst.treemap]
  890.         jz      @F
  891.  
  892.         bsf     eax, edx
  893. ; t = ms.treebins[i];
  894.         mov     eax, [mst.treebins + eax*4]
  895.  
  896. @@:
  897.  
  898. ; while (t != 0)
  899.         test    eax, eax
  900.         jz      .l5
  901.  
  902. .l4:
  903.  
  904. ; trem = (t->head & ~INUSE_BITS) - nb;
  905.  
  906.         mov     ecx, [eax+4]
  907.         and     ecx, -4
  908.         sub     ecx, ebx
  909.  
  910. ; if (trem < rsize)
  911.  
  912.         cmp     ecx, edi
  913.         jae     @F
  914. ; rsize = trem;
  915.  
  916.         mov     edi, ecx
  917. ; v = t;
  918.         mov     ebp, eax
  919.  
  920. @@:
  921.  
  922. ; t = leftmost_child(t);
  923.  
  924.         mov     ecx, [eax+16]
  925.         test    ecx, ecx
  926.         je      @F
  927.         mov     eax, ecx
  928.         jmp     .l6
  929.  
  930. @@:
  931.         mov     eax, [eax+20]
  932.  
  933. .l6:
  934.  
  935. ; while (t != 0)
  936.  
  937.         test    eax, eax
  938.         jne     .l4
  939.  
  940. .l5:
  941.  
  942. ; if (v != 0)
  943.  
  944.         test    ebp, ebp
  945.         jz      .done
  946.  
  947. .l7:
  948.  
  949. ; r = chunk_plus_offset((mchunkptr)v, nb);
  950. ; unlink_large_chunk(v);
  951.  
  952.         mov     edx, ebp
  953.         lea     esi, [ebx + ebp]
  954.         call    unlink_large_chunk
  955.  
  956. ; if (rsize < 16)
  957.  
  958.         cmp     edi, 16
  959.         jae     .large
  960.  
  961. ; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT;
  962.  
  963.         lea     ecx, [edi + ebx]
  964.  
  965. ; (v+rsize + nb)->head |= PINUSE_BIT;
  966.  
  967.         add     edi, ebp
  968.         lea     eax, [edi + ebx + 4]
  969.         or      ecx, 3
  970.         mov     [ebp+4], ecx
  971.         or      dword [eax], 1
  972.         lea     eax, [ebp+8]
  973.         add     esp, 8
  974.         pop     edi
  975.         pop     esi
  976.         pop     ebp
  977.         ret
  978.  
  979. .large:
  980.  
  981. ; v->head = nb|PINUSE_BIT|CINUSE_BIT;
  982. ; r->head = rsize|PINUSE_BIT;
  983.  
  984.         mov     edx, edi
  985.         or      ebx, 3
  986.         mov     [ebp+4], ebx
  987.         or      edx, 1
  988.         mov     [esi+4], edx
  989.  
  990. ; (r+rsize)->prev_foot = rsize;
  991. ; insert_large_chunk((tchunkptr)r, rsize);
  992.  
  993.         mov     [esi+edi], edi
  994.         mov     eax, edi
  995.         mov     ecx, esi
  996.         call    insert_chunk
  997.  
  998.         lea     eax, [ebp+8]
  999.         add     esp, 8
  1000.         pop     edi
  1001.         pop     esi
  1002.         pop     ebp
  1003.         ret
  1004.  
  1005. .done:
  1006.         add     esp, 8
  1007.         pop     edi
  1008.         pop     esi
  1009.         pop     ebp
  1010.         xor     eax, eax
  1011.         ret
  1012.  
  1013. init_malloc:
  1014.  
  1015.         stdcall kernel_alloc, 0x40000
  1016.  
  1017.         mov     [mst.top], eax
  1018.         mov     [mst.topsize], 128*1024
  1019.         mov     dword [eax+4], (128*1024) or 1
  1020.         mov     eax, mst.smallbins
  1021.  
  1022. @@:
  1023.         mov     [eax+8], eax
  1024.         mov     [eax+12], eax
  1025.         add     eax, 16
  1026.         cmp     eax, mst.smallbins + 512
  1027.         jb      @B
  1028.  
  1029.         mov     ecx, mst.mutex
  1030.         call    mutex_init
  1031.  
  1032.         ret
  1033.  
  1034.