changed block-local variable access to use XXXX_CTXTEMPVAR instructions.

implemented simple global variable access using XXXX_OBJECT instructions
This commit is contained in:
hyunghwan.chung 2015-06-30 14:47:39 +00:00
parent f33bbfe724
commit 3e0d6630f1
4 changed files with 300 additions and 113 deletions

View File

@ -32,6 +32,7 @@
#define CODE_BUFFER_ALIGN 8 /* 256 */
#define BALIT_BUFFER_ALIGN 8 /* 256 */
#define ARLIT_BUFFER_ALIGN 8 /* 256 */
#define BLK_TMPRCNT_BUFFER_ALIGN 8
/* initial method dictionary size */
#define INSTANCE_METHOD_DICTIONARY_SIZE 256 /* TODO: choose the right size */
@ -67,8 +68,9 @@ typedef enum var_type_t var_type_t;
struct var_info_t
{
var_type_t type;
stix_ssize_t pos;
stix_oop_class_t cls; /* useful if type is VAR_CLASS. note STIX_NULL indicates the self class. TODO: use it for GLOBAL?? */
stix_ssize_t pos; /* not used for VAR_GLOBAL */
stix_oop_class_t cls; /* useful if type is VAR_CLASS. note STIX_NULL indicates the self class. */
stix_oop_association_t gbl; /* used for VAR_GLOBAL only */
};
typedef struct var_info_t var_info_t;
@ -1577,7 +1579,7 @@ write_long:
#else
if (emit_byte_instruction(stix, bc) <= -1 ||
emit_byte_instruction(stix, param_1) <= -1 ||
emit_byte_instruction(stix, param_2) return -1;
emit_byte_instruction(stix, param_2) <= -1) return -1;
#endif
return 0;
}
@ -2268,10 +2270,15 @@ static int get_variable_info (stix_t* stix, const stix_ucs_t* name, const stix_i
return -1;
}
}
/* TODO
else if (find global variable... )
else
{
stix_oop_association_t ass;
ass = stix_lookupsysdic (stix, name);
if (ass)
{
var->type = VAR_GLOBAL;
*/
var->gbl = ass;
}
else
{
/* undeclared identifier */
@ -2279,6 +2286,7 @@ static int get_variable_info (stix_t* stix, const stix_ucs_t* name, const stix_i
return -1;
}
}
}
if (var->pos > MAX_CODE_INDEX)
{
@ -2335,6 +2343,26 @@ static int compile_block_temporaries (stix_t* stix)
return 0;
}
static int store_tmpr_count_for_block (stix_t* stix, stix_size_t tmpr_count)
{
if (stix->c->mth.blk_depth >= stix->c->mth.blk_tmprcnt_capa)
{
stix_size_t* tmp;
stix_size_t new_capa;
new_capa = STIX_ALIGN (stix->c->mth.blk_depth + 1, BLK_TMPRCNT_BUFFER_ALIGN);
tmp = (stix_size_t*)stix_reallocmem (stix, stix->c->mth.blk_tmprcnt, new_capa * STIX_SIZEOF(*tmp));
if (!tmp) return -1;
stix->c->mth.blk_tmprcnt_capa = new_capa;
stix->c->mth.blk_tmprcnt = tmp;
}
/* [NOTE] i don't increment blk_depth here */
stix->c->mth.blk_tmprcnt[stix->c->mth.blk_depth] = tmpr_count;
return 0;
}
static int compile_block_expression (stix_t* stix)
{
stix_size_t jump_inst_pos;
@ -2356,6 +2384,8 @@ static int compile_block_expression (stix_t* stix)
saved_tmprs_len = stix->c->mth.tmprs.len;
saved_tmpr_count = stix->c->mth.tmpr_count;
STIX_ASSERT (stix->c->mth.blk_depth > 0);
STIX_ASSERT (stix->c->mth.blk_tmprcnt[stix->c->mth.blk_depth - 1] == saved_tmpr_count);
if (stix->c->tok.type == STIX_IOTOK_COLON)
{
@ -2415,7 +2445,7 @@ static int compile_block_expression (stix_t* stix)
tmpr_loc = stix->c->tok.loc;
if (compile_block_temporaries(stix) <= -1) return -1;
/* this is a block-local temporary count */
/* this is a block-local temporary count including arguments */
block_tmpr_count = stix->c->mth.tmpr_count - saved_tmpr_count;
if (block_tmpr_count > MAX_CODE_NBLKTMPRS)
{
@ -2423,6 +2453,9 @@ static int compile_block_expression (stix_t* stix)
return -1;
}
/* store the accumulated number of temporaries for the current block */
if (store_tmpr_count_for_block (stix, stix->c->mth.tmpr_count) <= -1) return -1;
printf ("\tpush_context nargs %d ntmprs %d\n", (int)block_arg_count, (int)stix->c->mth.tmpr_count /*block_tmpr_count*/);
printf ("\tpush smint %d\n", (int)block_arg_count);
printf ("\tpush smint %d\n", (int)stix->c->mth.tmpr_count /*block_tmpr_count*/);
@ -2435,21 +2468,15 @@ printf ("\tsend_block_copy\n");
printf ("\tjump\n");
/* insert dummy instructions before replacing them with a jump instruction */
jump_inst_pos = stix->c->mth.code.len;
#if (STIX_BCODE_LONG_PARAM_SIZE == 2)
if (emit_byte_instruction(stix, BCODE_JUMP_FORWARD_X) <= -1 ||
emit_byte_instruction(stix, 0) <= -1 ||
emit_byte_instruction(stix, 0) <= -1) return -1;
#else
if (emit_byte_instruction(stix, BCODE_JUMP_FORWARD_X) <= -1 ||
emit_byte_instruction(stix, 0) <= -1) return -1;
#endif
/* specifying MAX_CODE_JUMP causes emit_single_param_instruction() to
* produce the long jump instruction (BCODE_JUMP_FORWARD_X) */
if (emit_single_param_instruction (stix, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
/* compile statements inside a block */
if (stix->c->tok.type == STIX_IOTOK_RBRACK)
{
/* the block is empty */
if (emit_byte_instruction (stix, BCODE_PUSH_NIL) <= -1) return -1;
GET_TOKEN (stix);
}
else
{
@ -2485,12 +2512,16 @@ printf ("\treturn_from_block\n");
}
/* note that the jump offset is a signed number */
#if (STIX_BCODE_LONG_PARAM_SIZE == 2)
stix->c->mth.code.ptr[jump_inst_pos + 1] = block_code_size >> 8;
stix->c->mth.code.ptr[jump_inst_pos + 2] = ((stix_int16_t)block_code_size & 0xFF);
#else
stix->c->mth.code.ptr[jump_inst_pos + 1] = block_code_size ;
#endif
/* restore the temporary count */
stix->c->mth.tmpr_count = saved_tmpr_count;
stix->c->mth.tmprs.len = saved_tmprs_len;
stix->c->mth.tmpr_count = saved_tmpr_count;
GET_TOKEN (stix);
@ -2761,9 +2792,30 @@ static int compile_expression_primary (stix_t* stix, const stix_ucs_t* ident, co
{
case VAR_ARGUMENT:
case VAR_TEMPORARY:
{
#if defined(STIX_USE_CTXTEMPVAR)
if (stix->c->mth.blk_depth > 0)
{
stix_size_t i;
STIX_ASSERT (var.pos < stix->c->mth.blk_tmprcnt[stix->c->mth.blk_depth]);
for (i = stix->c->mth.blk_depth; i > 0; i--)
{
if (var.pos >= stix->c->mth.blk_tmprcnt[i - 1])
{
printf ("\tpush ctxtempvar %d %d\n", (int)(stix->c->mth.blk_depth - i), (int)(var.pos - stix->c->mth.blk_tmprcnt[i - 1]));
if (emit_double_param_instruction(stix, BCODE_PUSH_CTXTEMPVAR_0, stix->c->mth.blk_depth - i, var.pos - stix->c->mth.blk_tmprcnt[i - 1]) <= -1) return -1;
goto temporary_done;
}
}
}
#endif
if (emit_single_param_instruction(stix, BCODE_PUSH_TEMPVAR_0, var.pos) <= -1) return -1;
printf ("\tpush tempvar %d\n", (int)var.pos);
temporary_done:
break;
}
case VAR_INSTANCE:
case VAR_CLASSINST:
@ -2778,10 +2830,19 @@ printf ("\tpush objvar %d %d\n", (int)var.pos, (int)index);
break;
case VAR_GLOBAL:
/* TODO: .............................. */
printf ("GLOBAL NOT IMPLMENTED.... \n");
stix->errnum = STIX_ENOIMPL;
return -1;
/* [NOTE]
* the association object pointed to by a system dictionary
* is stored into the literal frame. so the system dictionary
* must not migrate the value of the association to a new
* association when it rehashes the entire dictionary.
* If the association entry is deleted from the dictionary,
* the code compiled before the deletion will still access
* the deleted association
*/
if (add_literal(stix, (stix_oop_t)var.gbl, &index) <= -1 ||
emit_single_param_instruction(stix, BCODE_PUSH_OBJECT_0, index) <= -1) return -1;
printf ("\tpush object %d\n", (int)index);
break;
default:
stix->errnum = STIX_EINTERN;
@ -2899,9 +2960,23 @@ printf ("\tpush int literal\n");
/* TODO: dynamic array, non constant array #<> or #{} or what is a better bracket? */
case STIX_IOTOK_LBRACK: /* [ */
{
int n;
/*GET_TOKEN (stix);*/
if (compile_block_expression(stix) <= -1) return -1;
if (store_tmpr_count_for_block (stix, stix->c->mth.tmpr_count) <= -1) return -1;
stix->c->mth.blk_depth++;
/*
* stix->c->mth.tmpr_count[0] contains the number of temporaries for a method.
* stix->c->mth.tmpr_count[1] contains the number of temporaries for the block plus the containing method.
* ...
* stix->c->mth.tmpr_count[n] contains the number of temporaries for the block plus all containing method and block.
*/
n = compile_block_expression(stix);
stix->c->mth.blk_depth--;
if (n <= -1) return -1;
break;
}
case STIX_IOTOK_LPAREN:
GET_TOKEN (stix);
@ -3092,6 +3167,7 @@ static int compile_message_expression (stix_t* stix, int to_super)
if (emit_byte_instruction(stix, BCODE_NOOP) <= -1) return -1;
if (compile_binary_message(stix, to_super) <= -1) return -1;
}
if (stix->c->tok.type == STIX_IOTOK_KEYWORD)
{
STIX_ASSERT (stix->c->mth.code.len > noop_pos);
@ -3117,7 +3193,6 @@ static int compile_message_expression (stix_t* stix, int to_super)
noop_pos = stix->c->mth.code.len;
if (emit_byte_instruction(stix, BCODE_NOOP) <= -1) return -1;
if (compile_keyword_message(stix, to_super) <= -1) return -1;
}
break;
@ -3234,11 +3309,32 @@ printf ("\n");
goto oops;
case VAR_TEMPORARY:
{
#if defined(STIX_USE_CTXTEMPVAR)
if (stix->c->mth.blk_depth > 0)
{
stix_size_t i;
STIX_ASSERT (var.pos < stix->c->mth.blk_tmprcnt[stix->c->mth.blk_depth]);
for (i = stix->c->mth.blk_depth; i > 0; i--)
{
if (var.pos >= stix->c->mth.blk_tmprcnt[i - 1])
{
printf ("\t%s_into_ctxtempvar %d %d\n", (pop? "pop":"store"), (int)(stix->c->mth.blk_depth - i), (int)(var.pos - stix->c->mth.blk_tmprcnt[i - 1]));
if (emit_double_param_instruction(stix, (pop? BCODE_POP_INTO_CTXTEMPVAR_0: BCODE_STORE_INTO_CTXTEMPVAR_0), stix->c->mth.blk_depth - i, var.pos - stix->c->mth.blk_tmprcnt[i - 1]) <= -1) return -1;
goto temporary_done;
}
}
}
#endif
printf ("\t%s_into_tempvar %d\n", (pop? "pop":"store"), (int)var.pos);
if (emit_single_param_instruction (stix, (pop? BCODE_POP_INTO_TEMPVAR_0: BCODE_STORE_INTO_TEMPVAR_0), var.pos) <= -1) goto oops;
temporary_done:
ret = pop;
break;
}
case VAR_INSTANCE:
case VAR_CLASSINST:
@ -3256,9 +3352,11 @@ printf ("\t%s_into_objvar %d %d\n", (pop? "pop":"store"), (int)var.pos, (int)ind
break;
case VAR_GLOBAL:
/* TODO: .............................. */
printf ("\tSTORE_INTO_GLOBL NOT IMPLEMENTED YET\n");
goto oops;
if (add_literal(stix, (stix_oop_t)var.gbl, &index) <= -1 ||
emit_single_param_instruction(stix, (pop? BCODE_POP_INTO_OBJECT_0: BCODE_STORE_INTO_OBJECT_0), index) <= -1) return -1;
printf ("\t%s_into_object %d\n", (pop? "pop":"store"), (int)index);
ret = pop;
break;
default:
stix->errnum = STIX_EINTERN;
@ -3495,8 +3593,9 @@ static int compile_method_definition (stix_t* stix)
stix->c->mth.literal_count = 0;
stix->c->mth.balit_count = 0;
stix->c->mth.arlit_count = 0;
stix->c->mth.code.len = 0;
stix->c->mth.prim_no = -1;
stix->c->mth.blk_depth = 0;
stix->c->mth.code.len = 0;
if (stix->c->tok.type == STIX_IOTOK_LPAREN)
{
@ -4079,6 +4178,7 @@ static void fini_compiler (stix_t* stix)
if (stix->c->mth.literals) stix_freemem (stix, stix->c->mth.literals);
if (stix->c->mth.balit) stix_freemem (stix, stix->c->mth.balit);
if (stix->c->mth.arlit) stix_freemem (stix, stix->c->mth.arlit);
if (stix->c->mth.blk_tmprcnt) stix_freemem (stix, stix->c->mth.blk_tmprcnt);
stix_freemem (stix, stix->c);
stix->c = STIX_NULL;

View File

@ -831,8 +831,6 @@ int stix_execute (stix_t* stix)
{
stix_byte_t bcode;
stix_ooi_t b1, b2, bx;
stix_oop_context_t ctx;
stix_oop_oop_t t1;
stix_oop_t return_value;
stix_size_t inst_counter;
@ -948,6 +946,41 @@ printf ("POP_INTO_INSTVAR %d\n", (int)b1);
case BCODE_POP_INTO_TEMPVAR_5:
case BCODE_POP_INTO_TEMPVAR_6:
case BCODE_POP_INTO_TEMPVAR_7:
{
#if defined(STIX_USE_CTXTEMPVAR)
b1 = bcode & 0x7; /* low 3 bits */
handle_tempvar:
if ((bcode >> 4) & 1)
{
/* push - bit 4 on*/
printf ("PUSH_TEMPVAR %d - ", (int)b1);
ACTIVE_STACK_PUSH (stix, ACTIVE_STACK_GET(stix, b1]));
}
else
{
/* store or pop - bit 5 off */
ACTIVE_STACK_SET(stix, b1, ACTIVE_STACK_GETTOP(stix));
if ((bcode >> 3) & 1)
{
/* pop - bit 3 on */
ACTIVE_STACK_POP (stix);
printf ("POP_INTO_TEMPVAR %d - ", (int)b1);
}
else
{
printf ("STORE_INTO_TEMPVAR %d - ", (int)b1);
}
}
print_object (stix, ctx->slot[bx]);
printf ("\n");
#else
stix_oop_context_t ctx;
b1 = bcode & 0x7; /* low 3 bits */
handle_tempvar:
if (stix->active_context->home != stix->_nil)
@ -1012,7 +1045,9 @@ printf ("STORE_INTO_TEMPVAR %d - ", (int)b1);
print_object (stix, ctx->slot[bx]);
printf ("\n");
#endif
break;
}
/* ------------------------------------------------- */
case BCODE_PUSH_LITERAL_X:
@ -1054,24 +1089,38 @@ printf ("\n");
case BCODE_POP_INTO_OBJECT_1:
case BCODE_POP_INTO_OBJECT_2:
case BCODE_POP_INTO_OBJECT_3:
{
stix_oop_association_t ass;
b1 = bcode & 0x3; /* low 2 bits */
handle_object:
printf ("<<<<<<<<<<<<<< XXXXX_OBJECT NOT IMPLEMENTED YET >>>>>>>>>>>> \n");
stix->errnum = STIX_ENOIMPL;
return -1;
ass = (stix_oop_association_t)stix->active_method->slot[b1];
STIX_ASSERT (STIX_CLASSOF(stix, ass) == stix->_association);
if ((bcode >> 3) & 1)
{
/* store or pop */
ass->value = ACTIVE_STACK_GETTOP(stix);
if ((bcode >> 2) & 1)
{
/* pop */
ACTIVE_STACK_POP (stix);
printf ("POP_INTO_OBJECT %d - ", (int)b1);
}
else
{
printf ("STORE_INTO_OBJECT %d - ", (int)b1);
}
}
else
{
/* push */
ACTIVE_STACK_PUSH (stix, ass->value);
printf ("PUSH_OBJECT %d - ", (int)b1);
}
break;
}
/* -------------------------------------------------------- */
@ -1143,25 +1192,50 @@ return -1;
case BCODE_POP_INTO_CTXTEMPVAR_1:
case BCODE_POP_INTO_CTXTEMPVAR_2:
case BCODE_POP_INTO_CTXTEMPVAR_3:
{
stix_ooi_t i;
stix_oop_context_t ctx;
b1 = bcode & 0x3; /* low 2 bits */
FETCH_BYTE_CODE_TO (stix, b2);
handle_ctxtempvar:
printf ("<<<<<<<<<<<<<< XXXXX_CTXTEMPVAR NOT IMPLEMENTED YET >>>>>>>>>>>> \n");
stix->errnum = STIX_ENOIMPL;
return -1;
ctx = stix->active_context;
STIX_ASSERT ((stix_oop_t)ctx != stix->_nil);
for (i = 0; i < b1; i++)
{
ctx = (stix_oop_context_t)ctx->home;
}
if ((bcode >> 3) & 1)
{
/* store or pop */
ctx->slot[b2] = ACTIVE_STACK_GETTOP(stix);
if ((bcode >> 2) & 1)
{
/* pop */
ACTIVE_STACK_POP (stix);
printf ("POP_INTO_CTXTEMPVAR %d %d - ", (int)b1, (int)b2);
}
else
{
printf ("STORE_INTO_CTXTEMPVAR %d %d - ", (int)b1, (int)b2);
}
}
else
{
/* push */
ACTIVE_STACK_PUSH (stix, ctx->slot[b2]);
printf ("PUSH_CTXTEMPVAR %d %d - ", (int)b1, (int)b2);
}
print_object (stix, ctx->slot[b2]);
printf ("\n");
break;
}
/* -------------------------------------------------------- */
case BCODE_PUSH_OBJVAR_X:
@ -1183,22 +1257,24 @@ return -1;
case BCODE_POP_INTO_OBJVAR_1:
case BCODE_POP_INTO_OBJVAR_2:
case BCODE_POP_INTO_OBJVAR_3:
{
stix_oop_oop_t t;
/* b1 -> variable index to the object indicated by b2.
* b2 -> object index stored in the literal frame. */
b1 = bcode & 0x3; /* low 2 bits */
FETCH_BYTE_CODE_TO (stix, b2);
handle_objvar:
printf ("XXXXXXXXXXXXXXXXXXXXX [%d]\n", (int)b2);
t1 = (stix_oop_oop_t)stix->active_method->slot[b2];
STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(t1) == STIX_OBJ_TYPE_OOP);
STIX_ASSERT (b1 < STIX_OBJ_GET_SIZE(t1));
t = (stix_oop_oop_t)stix->active_method->slot[b2];
STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(t) == STIX_OBJ_TYPE_OOP);
STIX_ASSERT (b1 < STIX_OBJ_GET_SIZE(t));
if ((bcode >> 3) & 1)
{
/* store or pop */
t1->slot[b1] = ACTIVE_STACK_GETTOP(stix);
t->slot[b1] = ACTIVE_STACK_GETTOP(stix);
if ((bcode >> 2) & 1)
{
@ -1215,12 +1291,13 @@ printf ("STORE_INTO_OBJVAR %d %d - ", (int)b1, (int)b2);
{
/* push */
printf ("PUSH_OBJVAR %d %d - ", (int)b1, (int)b2);
ACTIVE_STACK_PUSH (stix, t1->slot[b1]);
ACTIVE_STACK_PUSH (stix, t->slot[b1]);
}
print_object (stix, t1->slot[b1]);
print_object (stix, t->slot[b1]);
printf ("\n");
break;
}
/* -------------------------------------------------------- */
case BCODE_SEND_MESSAGE_X:

View File

@ -30,15 +30,20 @@
#include "stix.h"
/* you can define this to either 1 or 2 */
#define STIX_BCODE_LONG_PARAM_SIZE 2
#define STIX_BCODE_LONG_PARAM_SIZE 1
/* this is useful for debugging. stix_gc() can be called
* while stix has not been fully initialized when this is defined*/
#define STIX_SUPPORT_GC_DURING_IGNITION
/* define this to generate CTXTEMVAR instructions */
#define STIX_USE_CTXTEMPVAR
/* this is for gc debugging */
#define STIX_DEBUG_GC_001
#include <stdio.h> /* TODO: delete these header inclusion lines */
#include <string.h>
#include <assert.h>
@ -452,6 +457,11 @@ struct stix_compiler_t
/* primitive number */
stix_ooi_t prim_no;
/* block depth */
stix_size_t blk_depth;
stix_size_t* blk_tmprcnt;
stix_size_t blk_tmprcnt_capa;
/* byte code */
stix_code_t code;
stix_size_t code_capa;
@ -659,20 +669,20 @@ enum stix_bcode_t
BCODE_JUMP_BY_OFFSET_2 = 0x56,
BCODE_JUMP_BY_OFFSET_3 = 0x57,
BCODE_PUSH_CTXTEMPVAR_0 = 0x58,
BCODE_PUSH_CTXTEMPVAR_1 = 0x59,
BCODE_PUSH_CTXTEMPVAR_2 = 0x5A,
BCODE_PUSH_CTXTEMPVAR_3 = 0x5B,
BCODE_STORE_INTO_CTXTEMPVAR_0 = 0x58, /* 88 */
BCODE_STORE_INTO_CTXTEMPVAR_1 = 0x59, /* 89 */
BCODE_STORE_INTO_CTXTEMPVAR_2 = 0x5A, /* 90 */
BCODE_STORE_INTO_CTXTEMPVAR_3 = 0x5B, /* 91 */
BCODE_STORE_INTO_CTXTEMPVAR_0 = 0x5C,
BCODE_STORE_INTO_CTXTEMPVAR_1 = 0x5D,
BCODE_STORE_INTO_CTXTEMPVAR_2 = 0x5E,
BCODE_STORE_INTO_CTXTEMPVAR_3 = 0x5F,
BCODE_POP_INTO_CTXTEMPVAR_0 = 0x5C, /* 92 */
BCODE_POP_INTO_CTXTEMPVAR_1 = 0x5D, /* 93 */
BCODE_POP_INTO_CTXTEMPVAR_2 = 0x5E, /* 94 */
BCODE_POP_INTO_CTXTEMPVAR_3 = 0x5F, /* 95 */
BCODE_POP_INTO_CTXTEMPVAR_0 = 0x60,
BCODE_POP_INTO_CTXTEMPVAR_1 = 0x61,
BCODE_POP_INTO_CTXTEMPVAR_2 = 0x62,
BCODE_POP_INTO_CTXTEMPVAR_3 = 0x63,
BCODE_PUSH_CTXTEMPVAR_0 = 0x60, /* 96 */
BCODE_PUSH_CTXTEMPVAR_1 = 0x61, /* 97 */
BCODE_PUSH_CTXTEMPVAR_2 = 0x62, /* 98 */
BCODE_PUSH_CTXTEMPVAR_3 = 0x63, /* 99 */
BCODE_PUSH_OBJVAR_0 = 0x64,
BCODE_PUSH_OBJVAR_1 = 0x65,
@ -689,7 +699,6 @@ enum stix_bcode_t
BCODE_POP_INTO_OBJVAR_2 = 0x6E,
BCODE_POP_INTO_OBJVAR_3 = 0x6F,
BCODE_SEND_MESSAGE_0 = 0x70,
BCODE_SEND_MESSAGE_1 = 0x71,
BCODE_SEND_MESSAGE_2 = 0x72,

View File

@ -320,7 +320,8 @@
self value ifFalse: [ ^nil "^self" ].
aBlock value.
##thisContext pc: pc - 3 sp: sp.
thisContext pc: pc + 2 sp: sp.
##thisContext pc: pc + 2 sp: sp.
thisContext pc: pc + 1 sp: sp.
## this +2 or - 3 above is dependent on the byte code instruction size used for 'store'
## +2 to skip STORE_INTO_TEMP(pc) and POP_STACKTOP.
## TODO: make it independent of the byte code size