From 7eb10b162af0301120de6be8ed4454d9a4ed2de0 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Thu, 15 Oct 2020 14:50:08 +0000 Subject: [PATCH] started representing a block([...]) in a CompiledBlock object. BlockContext represents an activated CompiledBlock context from now on --- moo/kernel/Context.moo | 154 +++++++++++++++-------------- moo/kernel/Except.moo | 3 +- moo/kernel/Moo.moo | 4 +- moo/kernel/test-001.moo | 4 + moo/kernel/test-003.moo | 18 ++-- moo/lib/bct-lab.h | 2 +- moo/lib/comp.c | 7 -- moo/lib/decode.c | 4 - moo/lib/exec.c | 212 +++++++++++++++------------------------- moo/lib/gc.c | 8 ++ moo/lib/moo-prv.h | 6 +- moo/lib/moo.c | 8 +- moo/lib/moo.h | 18 +++- 13 files changed, 207 insertions(+), 241 deletions(-) diff --git a/moo/kernel/Context.moo b/moo/kernel/Context.moo index 84d43ab..6932fcc 100644 --- a/moo/kernel/Context.moo +++ b/moo/kernel/Context.moo @@ -111,6 +111,80 @@ class(#pointer,#final,#limited) BlockContext(Context) ^self.home vargAt: index } + method pc + { + ^self.ip + } + + method pc: anInteger + { + self.ip := anInteger. + } + + method sp + { + ^self.sp + } + + method sp: anInteger + { + self.sp := anInteger. + } + + method restart + { + ip := self.source pc. + } +} + + +class(#pointer) CompiledMethod(Object) +{ + var owner, + name, + preamble, + preamble_data_1, + preamble_data_2, + ntmprs, + nargs, + dbi_file_offset, + dbi_method_offset. + + method preamble + { + ^self.preamble + } + + method preambleCode + { + /* TODO: make this a primtive for performance */ + ^(self.preamble bitShift: -4) bitAnd: 16r1F. + } + + method owner + { + ^self.owner + } + + method name + { + ^self.name + } + + method(#primitive) sourceText. + method(#primitive) sourceFile. + method(#primitive) sourceLine. + method(#primitive) ipSourceLine: ip. +} + +class CompiledBlock(Object) +{ + var ip, ntmprs, nargs, home. + + // create a new process in the suspended state + method(#variadic,#primitive) newProcess(). + method(#variadic,#primitive) newSystemProcess(). // this method is for internal use only. never call this. + // TODO: how can i pass variadic arguments to newProcess // method(#variadic) fork() -> how to pass them to newProcess??? method fork @@ -119,40 +193,35 @@ class(#pointer,#final,#limited) BlockContext(Context) ^self newProcess resume. } - // create a new process in the suspended state - method(#variadic,#primitive) newProcess(). - method(#variadic,#primitive) newSystemProcess(). // this method is for internal use only. never call this. - // evaluate the block method(#variadic,#primitive) value(). method value: a { - + self primitiveFailed. } method value: a value: b { - + self primitiveFailed. } method value: a value: b value: c { - + self primitiveFailed. } method value: a value: b value: c value: d { - + self primitiveFailed. } method value: a value: b value: c value: d value: e { - + self primitiveFailed. } - method ifTrue: aBlock { //^(self value) ifTrue: aBlock. @@ -285,69 +354,4 @@ class(#pointer,#final,#limited) BlockContext(Context) * -------------------------------------------------- */ while ((self value) == false) { }. } - - method pc - { - ^self.ip - } - - method pc: anInteger - { - self.ip := anInteger. - } - - method sp - { - ^self.sp - } - - method sp: anInteger - { - self.sp := anInteger. - } - - method restart - { - ip := self.source pc. - } -} - - -class(#pointer) CompiledMethod(Object) -{ - var owner, - name, - preamble, - preamble_data_1, - preamble_data_2, - ntmprs, - nargs, - dbi_file_offset, - dbi_method_offset. - - method preamble - { - ^self.preamble - } - - method preambleCode - { - /* TODO: make this a primtive for performance */ - ^(self.preamble bitShift: -4) bitAnd: 16r1F. - } - - method owner - { - ^self.owner - } - - method name - { - ^self.name - } - - method(#primitive) sourceText. - method(#primitive) sourceFile. - method(#primitive) sourceLine. - method(#primitive) ipSourceLine: ip. } diff --git a/moo/kernel/Except.moo b/moo/kernel/Except.moo index 6fb448a..71d0907 100644 --- a/moo/kernel/Except.moo +++ b/moo/kernel/Except.moo @@ -337,13 +337,12 @@ extend MethodContext } //============================================================================ -extend BlockContext +extend CompiledBlock { method on: anException do: anExceptionBlock { | exception_active | - /* ------------------------------- thisContext isExceptionContext dump. (thisContext basicSize) dump. diff --git a/moo/kernel/Moo.moo b/moo/kernel/Moo.moo index 60bd6f3..e087801 100644 --- a/moo/kernel/Moo.moo +++ b/moo/kernel/Moo.moo @@ -11,6 +11,6 @@ #include 'Stream.moo'. /* -------------------------------------------------------------------------- */ -#include 'FFI.moo'. +// #include 'FFI.moo'. #include 'Stdio.moo'. -#include 'Console.moo'. +// #include 'Console.moo'. diff --git a/moo/kernel/test-001.moo b/moo/kernel/test-001.moo index 65057c0..cfbbb99 100644 --- a/moo/kernel/test-001.moo +++ b/moo/kernel/test-001.moo @@ -427,5 +427,9 @@ extend MyObject tb := tc at: idx. System log(System.Log.INFO, idx asString, (if (tb value) { " PASS" } else { " FAIL" }), "\n"). ]. + + + [ 10 dump. [20 dump] value; value; ] value; value. + } } diff --git a/moo/kernel/test-003.moo b/moo/kernel/test-003.moo index 6cbbb14..10c5bf8 100644 --- a/moo/kernel/test-003.moo +++ b/moo/kernel/test-003.moo @@ -172,26 +172,30 @@ start: // 10-14 [(10 isKindOf: Integer) == true], [(10 isKindOf: 20) == false], - [([] isKindOf: BlockContext) == true], - [([] isKindOf: MethodContext) == false], - [([] isKindOf: Context) == true], + [([] isKindOf: CompiledBlock) == true], + [([] isKindOf: CompiledMethod) == false], + [([] isKindOf: BlockContext) == false], + + // 15-19 + [([] isKindOf: MethodContext) == false], + [([] isKindOf: Context) == false], [("string" isKindOf: String) == true], [(#symbol isKindOf: String) == true], [("string" isKindOf: Symbol) == false], - [(#symbol isKindOf: Symbol) == true], - [ [] value == nil ], // 20-24 + [(#symbol isKindOf: Symbol) == true], + [ [] value == nil ], [ self test_local_return_001 ], [ self test_if_001 ], [ self test_while_001 ], [ (if (1 > 2) { } else { }) == nil. ], - [ (if (1 < 2) { } else { }) == nil. ], - [ (if (1 > 2) { } else { goto A01. A01: nil }) == nil ], // 25-29 + [ (if (1 < 2) { } else { }) == nil. ], + [ (if (1 > 2) { } else { goto A01. A01: nil }) == nil ], [ (if (1 > 2) { } else { 9876. goto A02. A02: 9876. }) == 9876 ], [ [ | a3 | a3:= 20. if (a3 == 21) { a3 := 4321. goto L03 } else { a3 := 1234. goto L03 }. a3 := 8888. L03: a3 ] value == 1234 ], [ [ | a4 | a4:= 21. if (a4 == 21) { a4 := 4321. goto L04 } else { a4 := 1234. goto L04 }. a4 := 8888. L04: a4 ] value == 4321 ] diff --git a/moo/lib/bct-lab.h b/moo/lib/bct-lab.h index efc45bc..d1bdc12 100644 --- a/moo/lib/bct-lab.h +++ b/moo/lib/bct-lab.h @@ -254,5 +254,5 @@ /* 251 */ &&case_BCODE_RETURN_FROM_BLOCK, /* 252 */ &&case_BCODE_LOCAL_RETURN, /* 253 */ &&case_BCODE_MAKE_BLOCK, - /* 254 */ &&case_BCODE_SEND_BLOCK_COPY, + /* 254 */ &&case_DEFAULT, /* 255 */ &&case_BCODE_NOOP diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 4111f36..6531cf0 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -5110,14 +5110,7 @@ static int compile_block_expression (moo_t* moo) * updating the temporaries count for the current block. */ if (store_tmpr_count_for_block(moo, md->tmpr_count) <= -1) return -1; -#if defined(MOO_USE_MAKE_BLOCK) if (emit_double_param_instruction(moo, BCODE_MAKE_BLOCK, block_arg_count, md->tmpr_count/*block_tmpr_count*/, &block_loc) <= -1) return -1; -#else - if (emit_byte_instruction(moo, BCODE_PUSH_CONTEXT, &block_loc) <= -1 || - emit_push_smooi_literal(moo, block_arg_count, &block_loc) <= -1 || - emit_push_smooi_literal(moo, md->tmpr_count/*block_tmpr_count*/, &block_loc) <= -1 || - emit_byte_instruction(moo, BCODE_SEND_BLOCK_COPY, &block_loc) <= -1) return -1; -#endif /* insert dummy instructions before replacing them with a jump instruction */ jump_inst_pos = md->code.len; diff --git a/moo/lib/decode.c b/moo/lib/decode.c index 1673220..ed1dd38 100644 --- a/moo/lib/decode.c +++ b/moo/lib/decode.c @@ -585,10 +585,6 @@ int moo_decode (moo_t* moo, moo_oop_method_t mth, const moo_oocs_t* classfqn) MOO_ASSERT (moo, b2 >= b1); break; - case BCODE_SEND_BLOCK_COPY: - LOG_INST_0 (moo, "send_block_copy"); - break; - case BCODE_NOOP: /* do nothing */ LOG_INST_0 (moo, "noop"); diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 4f55a52..910f903 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -2531,7 +2531,7 @@ static moo_pfrc_t pf_method_get_source_text (moo_t* moo, moo_mod_t* mod, moo_ooi /* ------------------------------------------------------------------ */ -static moo_pfrc_t __block_value (moo_t* moo, moo_oop_context_t rcv_blkctx, moo_ooi_t nargs, moo_ooi_t num_first_arg_elems, moo_oop_context_t* pblkctx) +static moo_pfrc_t __block_value (moo_t* moo, moo_oop_block_t rcv_block, moo_ooi_t nargs, moo_ooi_t num_first_arg_elems, moo_oop_context_t* pblkctx) { /* prepare a new block context for activation. * the receiver must be a block context which becomes the base @@ -2555,54 +2555,48 @@ static moo_pfrc_t __block_value (moo_t* moo, moo_oop_context_t rcv_blkctx, moo_o */ /* the receiver must be a block context */ - MOO_ASSERT (moo, MOO_CLASSOF(moo, rcv_blkctx) == moo->_block_context); - if (rcv_blkctx->receiver_or_base != moo->_nil) + MOO_ASSERT (moo, MOO_CLASSOF(moo, rcv_block) == moo->_block); +#if 0 + if (rcv_block->receiver_or_base != moo->_nil) { /* the 'source' field is not nil. * this block context has already been activated once. * you can't send 'value' again to reactivate it. * For example, [thisContext value] value. */ - MOO_ASSERT (moo, MOO_OBJ_GET_SIZE(rcv_blkctx) > MOO_CONTEXT_NAMED_INSTVARS); - moo_seterrbfmt (moo, MOO_EPERM, "re-valuing of a block context - %O", rcv_blkctx); + MOO_ASSERT (moo, MOO_OBJ_GET_SIZE(rcv_block) > MOO_CONTEXT_NAMED_INSTVARS); + moo_seterrbfmt (moo, MOO_EPERM, "re-valuing of a block context - %O", rcv_block); return MOO_PF_FAILURE; } - MOO_ASSERT (moo, MOO_OBJ_GET_SIZE(rcv_blkctx) == MOO_CONTEXT_NAMED_INSTVARS); +#endif + MOO_ASSERT (moo, MOO_OBJ_GET_SIZE(rcv_block) == MOO_BLOCK_NAMED_INSTVARS); - if (MOO_OOP_TO_SMOOI(rcv_blkctx->method_or_nargs) != actual_arg_count /* nargs */) + if (MOO_OOP_TO_SMOOI(rcv_block->nargs) != actual_arg_count /* nargs */) { moo_seterrbfmt (moo, MOO_ENUMARGS, "wrong number of arguments to a block context %O - %zd expected, %zd given", - rcv_blkctx, MOO_OOP_TO_SMOOI(rcv_blkctx->method_or_nargs), actual_arg_count); + rcv_block, MOO_OOP_TO_SMOOI(rcv_block->nargs), actual_arg_count); return MOO_PF_FAILURE; } /* the number of temporaries stored in the block context * accumulates the number of temporaries starting from the origin. * simple calculation is needed to find the number of local temporaries */ - local_ntmprs = MOO_OOP_TO_SMOOI(rcv_blkctx->ntmprs) - - MOO_OOP_TO_SMOOI(((moo_oop_context_t)rcv_blkctx->home)->ntmprs); + local_ntmprs = MOO_OOP_TO_SMOOI(rcv_block->ntmprs) - + MOO_OOP_TO_SMOOI(((moo_oop_context_t)rcv_block->home)->ntmprs); MOO_ASSERT (moo, local_ntmprs >= actual_arg_count); - /* create a new block context to clone rcv_blkctx */ - moo_pushvolat (moo, (moo_oop_t*)&rcv_blkctx); - blkctx = (moo_oop_context_t) moo_instantiate(moo, moo->_block_context, MOO_NULL, local_ntmprs); + /* create a new block context based on the receiver block(rcv_block) */ + moo_pushvolat (moo, (moo_oop_t*)&rcv_block); + blkctx = (moo_oop_context_t)moo_instantiate(moo, moo->_block_context, MOO_NULL, local_ntmprs); moo_popvolat (moo); - if (!blkctx) return MOO_PF_FAILURE; + if (MOO_UNLIKELY(!blkctx)) return MOO_PF_FAILURE; -#if 0 - /* shallow-copy the named part including home, origin, etc. */ - for (i = 0; i < MOO_CONTEXT_NAMED_INSTVARS; i++) - { - MOO_STORE_OOP (moo, MOO_OBJ_GET_OOP_PTR(blkctx, i), MOO_OBJ_GET_OOP_VAL(rcv_blkctx, i)); - } -#else - blkctx->ip = rcv_blkctx->ip; /* no MOO_STORE_OOP() as it's a small integer */ - blkctx->ntmprs = rcv_blkctx->ntmprs; /* no MOO_STORE_OOP() as it's a small integer */ - MOO_STORE_OOP (moo, &blkctx->method_or_nargs, rcv_blkctx->method_or_nargs); - MOO_STORE_OOP (moo, &blkctx->receiver_or_base, (moo_oop_t)rcv_blkctx); - MOO_STORE_OOP (moo, &blkctx->home, rcv_blkctx->home); - MOO_STORE_OOP (moo, (moo_oop_t*)&blkctx->origin, (moo_oop_t)rcv_blkctx->origin); -#endif + blkctx->ip = rcv_block->ip; /* no MOO_STORE_OOP() as it's a small integer */ + blkctx->ntmprs = rcv_block->ntmprs; /* no MOO_STORE_OOP() as it's a small integer */ + MOO_STORE_OOP (moo, &blkctx->method_or_nargs, rcv_block->nargs); + MOO_STORE_OOP (moo, &blkctx->receiver_or_base, (moo_oop_t)rcv_block); + MOO_STORE_OOP (moo, &blkctx->home, (moo_oop_t)rcv_block->home); + MOO_STORE_OOP (moo, (moo_oop_t*)&blkctx->origin, (moo_oop_t)rcv_block->home->origin); /* TODO: check the stack size of a block context to see if it's large enough to hold arguments */ if (num_first_arg_elems > 0) @@ -2641,15 +2635,16 @@ static moo_pfrc_t __block_value (moo_t* moo, moo_oop_context_t rcv_blkctx, moo_o static moo_pfrc_t pf_block_value (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) { moo_pfrc_t x; - moo_oop_context_t rcv_blkctx, blkctx; + moo_oop_block_t rcv_block; + moo_oop_context_t blkctx; - rcv_blkctx = (moo_oop_context_t)MOO_STACK_GETRCV(moo, nargs); - MOO_PF_CHECK_RCV (moo, MOO_CLASSOF(moo,rcv_blkctx) == moo->_block_context); + rcv_block = (moo_oop_block_t)MOO_STACK_GETRCV(moo, nargs); + MOO_PF_CHECK_RCV (moo, MOO_CLASSOF(moo,rcv_block) == moo->_block); - x = __block_value(moo, rcv_blkctx, nargs, 0, &blkctx); + x = __block_value(moo, rcv_block, nargs, 0, &blkctx); if (x <= MOO_PF_FAILURE) return x; /* hard failure and soft failure */ - SWITCH_ACTIVE_CONTEXT (moo, (moo_oop_context_t)blkctx); + SWITCH_ACTIVE_CONTEXT (moo, blkctx); return MOO_PF_SUCCESS; } @@ -2662,7 +2657,8 @@ static MOO_INLINE moo_pfrc_t __block_new_process (moo_t* moo, moo_mod_t* mod, mo */ int x; - moo_oop_context_t rcv_blkctx, blkctx; + moo_oop_block_t rcv_block; + moo_oop_context_t blkctx; moo_oop_process_t proc; #if 0 moo_ooi_t num_first_arg_elems = 0; @@ -2686,15 +2682,15 @@ static MOO_INLINE moo_pfrc_t __block_new_process (moo_t* moo, moo_mod_t* mod, mo } #endif - rcv_blkctx = (moo_oop_context_t)MOO_STACK_GETRCV(moo, nargs); - MOO_PF_CHECK_RCV (moo, MOO_CLASSOF(moo,rcv_blkctx) == moo->_block_context); + rcv_block = (moo_oop_block_t)MOO_STACK_GETRCV(moo, nargs); + MOO_PF_CHECK_RCV (moo, MOO_CLASSOF(moo,rcv_block) == moo->_block); /* this primitive creates a new process with a block as if the block * is sent the value message */ #if 0 - x = __block_value(moo, rcv_blkctx, nargs, num_first_arg_elems, &blkctx); + x = __block_value(moo, rcv_block, nargs, num_first_arg_elems, &blkctx); #else - x = __block_value(moo, rcv_blkctx, nargs, 0, &blkctx); + x = __block_value(moo, rcv_block, nargs, 0, &blkctx); #endif if (x <= 0) return x; /* both hard failure and soft failure */ @@ -2705,7 +2701,7 @@ static MOO_INLINE moo_pfrc_t __block_new_process (moo_t* moo, moo_mod_t* mod, mo blkctx->sender = (moo_oop_context_t)moo->_nil; proc = make_process(moo, blkctx, proc_flags); - if (!proc) return MOO_PF_FAILURE; /* hard failure */ /* TOOD: can't this be treated as a soft failure? throw an exception instead?? */ + if (MOO_UNLIKELY(!proc)) return MOO_PF_FAILURE; /* hard failure */ /* TOOD: can't this be treated as a soft failure? throw an exception instead?? */ /* __block_value() has popped all arguments and the receiver. * PUSH the return value instead of changing the stack top */ @@ -4320,10 +4316,6 @@ static pf_t pftab[] = { "Apex_~=", { moo_pf_not_equal, 1, 1 } }, { "Apex_~~", { moo_pf_not_identical, 1, 1 } }, - { "BlockContext_newProcess", { pf_block_new_process, 0, MA } }, - { "BlockContext_newSystemProcess", { pf_block_new_system_process, 0, MA } }, - { "BlockContext_value", { pf_block_value, 0, MA } }, - { "Character_<", { pf_character_lt, 1, 1 } }, { "Character_<=", { pf_character_le, 1, 1 } }, { "Character_>", { pf_character_gt, 1, 1 } }, @@ -4331,6 +4323,9 @@ static pf_t pftab[] = { "Character_asError", { pf_character_as_error, 0, 0 } }, { "Character_asInteger", { pf_character_as_smooi, 0, 0 } }, + { "CompiledBlock_newProcess", { pf_block_new_process, 0, MA } }, + { "CompiledBlock_newSystemProcess", { pf_block_new_system_process, 0, MA } }, + { "CompiledBlock_value", { pf_block_value, 0, MA } }, { "CompiledMethod_ipSourceLine:", { pf_method_get_ip_source_line, 1, 1 } }, { "CompiledMethod_sourceFile", { pf_method_get_source_file, 0, 0 } }, { "CompiledMethod_sourceLine", { pf_method_get_source_line, 0, 0 } }, @@ -5416,6 +5411,7 @@ static MOO_INLINE void do_return_from_block (moo_t* moo) static MOO_INLINE int make_block (moo_t* moo) { +#if 0 moo_oop_context_t blkctx; moo_oob_t b1, b2; @@ -5461,6 +5457,46 @@ static MOO_INLINE int make_block (moo_t* moo) /* push the new block context to the stack of the active context */ MOO_STACK_PUSH (moo, (moo_oop_t)blkctx); return 0; +#else + moo_oop_block_t block; + moo_oob_t b1, b2; + + /* b1 - number of block arguments + * b2 - number of block temporaries */ + FETCH_PARAM_CODE_TO (moo, b1); + FETCH_PARAM_CODE_TO (moo, b2); + + LOG_INST2 (moo, "make_block %zu %zu", b1, b2); + + MOO_ASSERT (moo, b1 >= 0); + MOO_ASSERT (moo, b2 >= b1); + + /* the block context object created here is used as a base + * object for block context activation. pf_block_value() + * clones a block context and activates the cloned context. + * this base block context is created with no stack for + * this reason */ + block = (moo_oop_block_t)moo_instantiate(moo, moo->_block, MOO_NULL, 0); + if (MOO_UNLIKELY(!block)) return -1; + + /* the long forward jump instruction has the format of + * 11000100 KKKKKKKK or 11000100 KKKKKKKK KKKKKKKK + * depending on MOO_BCODE_LONG_PARAM_SIZE. change 'ip' to point to + * the instruction after the jump. */ + block->ip = MOO_SMOOI_TO_OOP(moo->ip + MOO_BCODE_LONG_PARAM_SIZE + 1); + /* the number of arguments for a block context is local to the block */ + block->nargs = MOO_SMOOI_TO_OOP(b1); + /* the number of temporaries here is an accumulated count including + * the number of temporaries of a home context */ + block->ntmprs = MOO_SMOOI_TO_OOP(b2); + + /* set the home context where it's defined */ + MOO_STORE_OOP (moo, (moo_oop_t*)&block->home, (moo_oop_t)moo->active_context); + + /* push the new block context to the stack of the active context */ + MOO_STACK_PUSH (moo, (moo_oop_t)block); + return 0; +#endif } static int __execute (moo_t* moo) @@ -6059,7 +6095,7 @@ static int __execute (moo_t* moo) /* -------------------------------------------------------- */ - ON_INST(BCODE_PUSH_RECEIVER) + ON_INST(BCODE_PUSH_RECEIVER) /* push self or super */ LOG_INST0 (moo, "push_receiver"); MOO_STACK_PUSH (moo, moo->active_context->origin->receiver_or_base); NEXT_INST(); @@ -6333,94 +6369,6 @@ static int __execute (moo_t* moo) if (make_block(moo) <= -1) return -1; NEXT_INST(); - ON_INST(BCODE_SEND_BLOCK_COPY) - { - moo_ooi_t nargs, ntmprs; - moo_oop_context_t rctx; - moo_oop_context_t blkctx; - - LOG_INST0 (moo, "send_block_copy"); - - /* it emulates thisContext blockCopy: nargs ofTmprCount: ntmprs */ - MOO_ASSERT (moo, moo->sp >= 2); - - MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(MOO_STACK_GETTOP(moo))); - ntmprs = MOO_OOP_TO_SMOOI(MOO_STACK_GETTOP(moo)); - MOO_STACK_POP (moo); - - MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(MOO_STACK_GETTOP(moo))); - nargs = MOO_OOP_TO_SMOOI(MOO_STACK_GETTOP(moo)); - MOO_STACK_POP (moo); - - MOO_ASSERT (moo, nargs >= 0); - MOO_ASSERT (moo, ntmprs >= nargs); - - /* the block context object created here is used - * as a base object for block context activation. - * pf_block_value() clones a block - * context and activates the cloned context. - * this base block context is created with no - * stack for this reason. */ - blkctx = (moo_oop_context_t)moo_instantiate(moo, moo->_block_context, MOO_NULL, 0); - if (!blkctx) return -1; - - /* get the receiver to the block copy message after block context instantiation - * not to get affected by potential GC */ - rctx = (moo_oop_context_t)MOO_STACK_GETTOP(moo); - MOO_ASSERT (moo, rctx == moo->active_context); - - /* [NOTE] - * blkctx->sender is left to nil. it is set to the - * active context before it gets activated. see - * pf_block_value(). - * - * blkctx->home is set here to the active context. - * it's redundant to have them pushed to the stack - * though it is to emulate the message sending of - * blockCopy:withNtmprs:. BCODE_MAKE_BLOCK has been - * added to replace BCODE_SEND_BLOCK_COPY and pusing - * arguments to the stack. - * - * blkctx->origin is set here by copying the origin - * of the active context. - */ - - /* the extended jump instruction has the format of - * 0000XXXX KKKKKKKK or 0000XXXX KKKKKKKK KKKKKKKK - * depending on MOO_BCODE_LONG_PARAM_SIZE. change 'ip' to point to - * the instruction after the jump. */ - blkctx->ip = MOO_SMOOI_TO_OOP(moo->ip + MOO_BCODE_LONG_PARAM_SIZE + 1); - blkctx->sp = MOO_SMOOI_TO_OOP(-1); - /* the number of arguments for a block context is local to the block */ - blkctx->method_or_nargs = MOO_SMOOI_TO_OOP(nargs); - /* the number of temporaries here is an accumulated count including - * the number of temporaries of a home context */ - blkctx->ntmprs = MOO_SMOOI_TO_OOP(ntmprs); - - MOO_STORE_OOP (moo, &blkctx->home, (moo_oop_t)rctx); - blkctx->receiver_or_base = moo->_nil; - - /* [NOTE] - * the origin of a method context is set to itself - * when it's created. so it's safe to simply copy - * the origin field this way. - * - * if the context that receives the blockCopy message - * is a method context, the following conditions are all true. - * rctx->home == moo->_nil - * MOO_CLASSOF(moo, rctx) == moo->_method_context - * rctx == (moo_oop_t)moo->active_context - * rctx == rctx->origin - * - * if it is a block context, the following condition is true. - * MOO_CLASSOF(moo, rctx) == moo->_block_context - */ - MOO_STORE_OOP (moo, (moo_oop_t*)&blkctx->origin, (moo_oop_t)rctx->origin); - - MOO_STACK_SETTOP (moo, (moo_oop_t)blkctx); - NEXT_INST(); - } - ON_INST(BCODE_NOOP) /* do nothing */ LOG_INST0 (moo, "noop"); diff --git a/moo/lib/gc.c b/moo/lib/gc.c index 8970165..6f051c3 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -254,6 +254,14 @@ static kernel_class_info_t kernel_classes[] = MOO_OBJ_TYPE_OOP, MOO_OFFSETOF(moo_t, _methsig) }, + { 13, + { 'C','o','m','p','i','l','e','d','B','l','o','c','k' }, + 0, + 0, + MOO_BLOCK_NAMED_INSTVARS, + 0, + MOO_OBJ_TYPE_OOP, + MOO_OFFSETOF(moo_t, _block) }, { 13, { 'M','e','t','h','o','d','C','o','n','t','e','x','t' }, diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 7c41d91..4ed34c3 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -42,10 +42,6 @@ /* define this to generate XXXX_CTXTEMVAR instructions */ #define MOO_USE_CTXTEMPVAR -/* define this to use the MAKE_BLOCK instruction instead of - * PUSH_CONTEXT, PUSH_INTLIT, PUSH_INTLIT, SEND_BLOCK_COPY */ -#define MOO_USE_MAKE_BLOCK - /* define this to enable karatsuba multiplication in bigint */ #define MOO_ENABLE_KARATSUBA #define MOO_KARATSUBA_CUTOFF 32 @@ -1021,7 +1017,7 @@ enum moo_bcode_t BCODE_RETURN_FROM_BLOCK = 0xFB, /* return the stack top from a block */ BCODE_LOCAL_RETURN = 0xFC, BCODE_MAKE_BLOCK = 0xFD, - BCODE_SEND_BLOCK_COPY = 0xFE, + /* UNUSED 0xFE */ BCODE_NOOP = 0xFF }; diff --git a/moo/lib/moo.c b/moo/lib/moo.c index 1d846b4..4bd8a2a 100644 --- a/moo/lib/moo.c +++ b/moo/lib/moo.c @@ -868,7 +868,7 @@ int moo_genpfmethod (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class, moo_met } mnsym = (moo_oop_char_t)moo_makesymbol(moo, mthname, i); - if (!mnsym) goto oops; + if (MOO_UNLIKELY(!mnsym)) goto oops; moo_pushvolat (moo, (moo_oop_t*)&mnsym); tmp_count++; /* compose a full primitive function identifier to VM's string buffer. @@ -882,15 +882,15 @@ int moo_genpfmethod (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class, moo_met } pfidsym = (moo_oop_char_t)moo_makesymbol(moo, moo->sbuf[MOO_SBUF_ID_TMP].ptr, moo->sbuf[MOO_SBUF_ID_TMP].len); - if (!pfidsym) + if (MOO_UNLIKELY(!pfidsym)) { MOO_DEBUG2 (moo, "Cannot generate primitive function method [%js] in [%O] - symbol instantiation failure\n", mthname, _class->name); goto oops; } moo_pushvolat (moo, (moo_oop_t*)&pfidsym); tmp_count++; - mth = (moo_oop_method_t)moo_instantiatewithtrailer (moo, moo->_method, 1, MOO_NULL, 0); - if (!mth) + mth = (moo_oop_method_t)moo_instantiatewithtrailer(moo, moo->_method, 1, MOO_NULL, 0); + if (MOO_UNLIKELY(!mth)) { MOO_DEBUG2 (moo, "Cannot generate primitive function method [%js] in [%O] - method instantiation failure\n", mthname, _class->name); goto oops; diff --git a/moo/lib/moo.h b/moo/lib/moo.h index c728d7f..5779ec0 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -695,6 +695,8 @@ struct moo_method_t #define MOO_METHOD_PREAMBLE_FLAG_DUAL (1 << 2) #define MOO_METHOD_PREAMBLE_FLAG_LENIENT (1 << 3) /* lenient primitive method - no exception upon failure. return an error instead */ + + /* [NOTE] if you change the number of instance variables for moo_context_t, * you need to change the defintion of BlockContext and MethodContext. * plus, you need to update various exception handling code in MethodContext */ @@ -741,7 +743,7 @@ struct moo_context_t * for a block context, it points to the active context at the * moment the block context was created. that is, it points to * a method context where the base block has been defined. - * an activated block context copies this field from the source. */ + * an activated block context copies this field from the base block context. */ moo_oop_t home; /* it points to the method context created of the method defining the code @@ -753,7 +755,7 @@ struct moo_context_t * * when a method context is created, it is set to itself. no change is * made when the method context is activated. when a base block context is - * created (when MAKE_BLOCK or BLOCK_COPY is executed), it is set to the + * created (when MAKE_BLOCK is executed), it is set to the * origin of the active context. when the base block context is shallow-copied * for activation (when it is sent 'value'), it is set to the origin of * the base block context. */ @@ -763,6 +765,17 @@ struct moo_context_t moo_oop_t stack[1]; /* context stack that stores arguments and temporaries */ }; +#define MOO_BLOCK_NAMED_INSTVARS 4 +typedef struct moo_block_t moo_block_t; +typedef struct moo_block_t* moo_oop_block_t; +struct moo_block_t +{ + MOO_OBJ_HEADER; + moo_oop_t ip; /* smooi. instruction pointer where the byte code begins in home->origin */ + moo_oop_t ntmprs; + moo_oop_t nargs; + moo_oop_context_t home; /* home context */ +}; #define MOO_PROCESS_NAMED_INSTVARS 13 typedef struct moo_process_t moo_process_t; @@ -1609,6 +1622,7 @@ struct moo_t moo_oop_class_t _method_dictionary; /* MethodDictionary */ moo_oop_class_t _method; /* CompiledMethod */ moo_oop_class_t _methsig; /* MethodSignature */ + moo_oop_class_t _block; /* CompiledBlock */ moo_oop_class_t _method_context; /* MethodContext */ moo_oop_class_t _block_context; /* BlockContext */