Added spec:commit task to commit changes to spec/ruby sources.
[rbx.git] / shotgun / lib / methctx.c
blobc912e57aac23b2254e93c3feebf184f2b790fda7
1 #include "shotgun/lib/shotgun.h"
2 #include "shotgun/lib/cpu.h"
3 #include "shotgun/lib/methctx.h"
4 #include "shotgun/lib/tuple.h"
5 #include "shotgun/lib/bytearray.h"
7 OBJECT methctx_dup(STATE, OBJECT self) {
8 OBJECT ctx;
9 struct fast_context *cur, *old;
11 methctx_reference(state, self);
13 ctx = NEW_OBJECT(object_class(state, self), FASTCTX_FIELDS);
15 ctx->StoresBytes = TRUE;
16 if(self->obj_type == MContextType) {
17 ctx->CTXFast = TRUE;
19 ctx->obj_type = self->obj_type;
21 assert(ctx->obj_type == MContextType || ctx->obj_type == BContextType);
23 old = FASTCTX(self);
24 cur = FASTCTX(ctx);
26 if(!NIL_P(old->sender)) methctx_reference(state, old->sender);
27 SET_STRUCT_FIELD(ctx, cur->sender, old->sender);
28 SET_STRUCT_FIELD(ctx, cur->block, old->block);
29 SET_STRUCT_FIELD(ctx, cur->method, old->method);
30 SET_STRUCT_FIELD(ctx, cur->literals, old->literals);
31 SET_STRUCT_FIELD(ctx, cur->locals, old->locals);
32 cur->argcount = old->argcount;
33 SET_STRUCT_FIELD(ctx, cur->name, old->name);
34 SET_STRUCT_FIELD(ctx, cur->method_module, old->method_module);
35 cur->opaque_data = old->opaque_data;
36 SET_STRUCT_FIELD(ctx, cur->self, old->self);
37 SET_STRUCT_FIELD(ctx, cur->custom_iseq, old->custom_iseq);
38 cur->data = old->data;
39 cur->type = old->type;
40 cur->ip = old->ip;
41 cur->sp = old->sp;
42 cur->fp = old->fp;
44 ctx->ForeverYoung = TRUE;
46 return ctx;
49 OBJECT methctx_dup_chain(STATE, OBJECT ctx, OBJECT *also) {
50 OBJECT sender, top;
51 top = methctx_dup(state, ctx);
52 ctx = top;
54 for(;;) {
55 sender = FASTCTX(ctx)->sender;
56 if(NIL_P(sender)) break;
58 methctx_reference(state, sender);
60 FASTCTX(ctx)->sender = methctx_dup(state, sender);
61 /* Update another ref if one is passed in
62 (used to also update home_context) */
63 if(also && *also == sender) {
64 *also = FASTCTX(ctx)->sender;
66 ctx = sender;
69 return top;
72 OBJECT blokenv_s_under_context2(STATE, OBJECT cmethod, OBJECT ctx, OBJECT ctx_block) {
73 OBJECT obj;
74 int num_lcls = N2I(cmethod_get_local_count(cmethod));
76 obj = blokenv_allocate(state);
77 blokenv_set_home(obj, ctx);
78 blokenv_set_initial_ip(obj, I2N(0));
79 // We have no real last since the block gets it's own method.
80 // Just set this very large so that comparison for bounds
81 // checks are always true.
82 blokenv_set_last_ip(obj, I2N(1 << 25));
83 blokenv_set_post_send(obj, I2N(0));
84 blokenv_set_home_block(obj, ctx_block);
85 blokenv_set_method(obj, cmethod);
86 blokenv_set_local_count(obj, I2N(num_lcls));
87 return obj;
90 void blokenv_call(STATE, cpu c, OBJECT self, int num_args) {
91 OBJECT t1, t2, t3;
92 int j;
94 c->blockargs = num_args;
96 t3 = tuple_new(state, num_args);
97 for(j = 0; j < num_args; j++) {
98 t1 = stack_pop();
99 tuple_put(state, t3, j, t1);
101 stack_push(t3);
103 cpu_flush_sp(c);
104 t2 = cpu_create_block_context(state, c, self, c->sp);
105 cpu_activate_context(state, c, t2, blokenv_get_home(self), 1);
109 void methctx_reference(STATE, OBJECT ctx) {
110 struct fast_context *fc;
112 /* Don't do it again. */
113 if(!stack_context_p(ctx)) return;
115 /* Has to be done first because this uses informated we're about
116 to overwrite. */
117 object_memory_context_referenced(state->om, ctx);
119 CLEAR_FLAGS(ctx);
120 ctx->gc_zone = YoungObjectZone;
121 switch(FASTCTX(ctx)->type) {
122 case FASTCTX_NORMAL:
123 SET_CLASS(ctx, BASIC_CLASS(fastctx));
124 ctx->obj_type = MContextType;
125 ctx->CTXFast = TRUE;
126 break;
127 case FASTCTX_BLOCK:
128 SET_CLASS(ctx, BASIC_CLASS(blokctx));
129 ctx->obj_type = BContextType;
130 break;
131 case FASTCTX_NMC:
132 SET_CLASS(ctx, BASIC_CLASS(nmc));
133 ctx->obj_type = MContextType;
134 break;
136 SET_NUM_FIELDS(ctx, FASTCTX_FIELDS);
137 ctx->StoresBytes = TRUE;
138 ctx->ForeverYoung = TRUE;
140 fc = FASTCTX(ctx);
142 /* Fixup the locals tuple. */
143 if(!NIL_P(fc->locals) && fc->locals->gc_zone == 0) {
144 fc->locals->gc_zone = YoungObjectZone;