Skip to content

Sweep not work correctly on ESP8266 #23

Description

@elct9620

Thanks for this tiny GC implementation that I can use as an example in my book about implementing a mruby virtual machine.

For the demo of my example, I run it on my macOS and ESP8266 chip.
But the tgc_sweep never runs because the gc->nfrees always be 0 in ESP8266.

The patch has removed this line to force it run sweep event nothing to be free.

tgc/tgc.c

Line 249 in 3520705

if (gc->frees == NULL) { return; }

Does anyone have any idea about the root cause to let the GC never work?

Activity

  1. orangeduck commented on Feb 8, 2022

    @orangeduck
    Owner

    If the number of frees was zero it means it probably didn't mark anything during the marking phase. Perhaps for some reason it is not finding any pointers on the stack? This is hard to debug without knowing more of the code.

  2. elct9620 commented on Feb 8, 2022

    @elct9620
    Author

    Thanks for your reply.

    Currently, it marks correctly in my macOS but does not work when I upload it to the ESP8266 chip.

    I am not sure the setjmp does have any relation to this issue.

    The implementation which I used. The tgc_stop isn't free any memory after the program stopped.

    // Enum
    enum mrb_type {
      MRB_TYPE_OBJECT,
    }
    
    // Structures
    typedef struct mrb_state {
      // ...
      tgc_t gc;
    } mrb_state;
    
    typedef struct mb_value {
      union {
        int i;
        void* p;
      } value;
      mrb_type type;
    } mrb_value;
    
    typedef struct RObject {
      // ...
      kh_iv iv;
    } RObject;
    // Functions
    
    mrb_state* mrb_open() {
      mrb_value mrb;
      // ...
    
      void* stack;
      tgc_start(&mrb->gc, &stack);
      return mrb;
    }
    
    void mrb_close(mrb_state* mrb) {
      // ...
      tgc_stop(&mrb->gc);
      free(mrb);
    }
    
    void mrb_new_object(mrb_state* mrb) {
      mrb_value value;
      RObject* object = (RObject*)tgc_alloc_opt(&mrb->gc, sizeof(RObject), 0, mrb_free_object);
      kh_init(iv, object->iv);
      // ...
      value.type = MRB_TYPE_OBJECT;
      value.value.p = (void*)object;
    
      return value;
    }
    // Usage
    
    int main(int argc, char** argv) {
      mrb_state* mrb = mrb_open();
      // Inside VM - Begin
      mrb_value regs[3];
      while(true) {
          // ...
          case(OP_SEND) {
            regs[0] = mrb_new_object(mrb);
            continue;
          }
          // ...
      }
      // Inside VM - End
      mrb_close(mrb);
    }
  3. orangeduck commented on Feb 9, 2022

    @orangeduck
    Owner

    To me it looks like maybe you need to call tgc_start(&mrb->gc, &stack); and tgc_stop(&mrb->gc); in the main function otherwise it might not be starting marking the stack from deep enough.

  4. elct9620 commented on Feb 9, 2022

    @elct9620
    Author

    I have tried to call tgc_start(&mrb->gc, &stack) and tgc_stop(&mrb->gc) in the main function but not work, too.

    Does any way to change the stack deep threshold to make it start marking early? The ESP8266 design may be different from the PC cause the stack is not deep enough.

  5. orangeduck commented on Feb 9, 2022

    @orangeduck
    Owner
  6. elct9620 commented on Feb 9, 2022

    @elct9620
    Author

    Thanks, I will try it and report the result.

  7. neslib commented on Dec 2, 2025

    @neslib

    I think this can happen because the return value of realloc is undefined when the size is 0. If the compiler returns NULL in that case, then the function will exit and ant TGC_MARK flags will not get reset and so these pointers never get released.

    By removing the NULL check as suggested, the rest of the code will still get executed and the TGC_MARK flags get reset as needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions