started representing a block([...]) in a CompiledBlock object. BlockContext represents an activated CompiledBlock context from now on

This commit is contained in:
hyunghwan.chung 2020-10-15 14:50:08 +00:00
parent 821b68a971
commit 7eb10b162a
13 changed files with 207 additions and 241 deletions

View File

@ -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
{
<primitive: #BlockContext_value>
<primitive: #CompiledBlock_value>
self primitiveFailed.
}
method value: a value: b
{
<primitive: #BlockContext_value>
<primitive: #CompiledBlock_value>
self primitiveFailed.
}
method value: a value: b value: c
{
<primitive: #BlockContext_value>
<primitive: #CompiledBlock_value>
self primitiveFailed.
}
method value: a value: b value: c value: d
{
<primitive: #BlockContext_value>
<primitive: #CompiledBlock_value>
self primitiveFailed.
}
method value: a value: b value: c value: d value: e
{
<primitive: #BlockContext_value>
<primitive: #CompiledBlock_value>
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.
}

View File

@ -337,13 +337,12 @@ extend MethodContext
}
//============================================================================
extend BlockContext
extend CompiledBlock
{
method on: anException do: anExceptionBlock
{
| exception_active |
<exception>
/* -------------------------------
thisContext isExceptionContext dump.
(thisContext basicSize) dump.

View File

@ -11,6 +11,6 @@
#include 'Stream.moo'.
/* -------------------------------------------------------------------------- */
#include 'FFI.moo'.
// #include 'FFI.moo'.
#include 'Stdio.moo'.
#include 'Console.moo'.
// #include 'Console.moo'.

View File

@ -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.
}
}

View File

@ -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 ]

View File

@ -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

View File

@ -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;

View File

@ -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");

View File

@ -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);
/* 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");

View File

@ -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' },

View File

@ -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
};

View File

@ -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,7 +882,7 @@ 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;
@ -890,7 +890,7 @@ int moo_genpfmethod (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class, moo_met
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)
if (MOO_UNLIKELY(!mth))
{
MOO_DEBUG2 (moo, "Cannot generate primitive function method [%js] in [%O] - method instantiation failure\n", mthname, _class->name);
goto oops;

View File

@ -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 */