removed unused code of putting compiled method code into a separate array.

started implementing interface method support
This commit is contained in:
hyunghwan.chung 2019-10-04 18:32:38 +00:00
parent eb3461b588
commit 7b8b7d70fd
6 changed files with 112 additions and 126 deletions

View File

@ -321,7 +321,6 @@ class(#pointer) CompiledMethod(Object)
preamble_data_2, preamble_data_2,
ntmprs, ntmprs,
nargs, nargs,
//code, <-- only if moo is built with MOO_USE_METHOD_TRAILER disabled.
dbi_file_offset, dbi_file_offset,
dbi_method_offset. dbi_method_offset.

View File

@ -7451,70 +7451,30 @@ static int compile_method_statements (moo_t* moo)
return emit_byte_instruction(moo, BCODE_RETURN_RECEIVER, TOKEN_LOC(moo)); return emit_byte_instruction(moo, BCODE_RETURN_RECEIVER, TOKEN_LOC(moo));
} }
static int add_compiled_method_to_class (moo_t* moo) static moo_ooi_t compute_preamble (moo_t* moo, moo_method_data_t* md)
{ {
moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit;
moo_oop_char_t name; /* selector */
moo_oop_method_t mth; /* method */
#if defined(MOO_USE_METHOD_TRAILER)
/* nothing extra */
#else
moo_oop_byte_t code;
#endif
moo_oow_t tmp_count = 0;
moo_oow_t i;
moo_ooi_t preamble_code, preamble_index, preamble_flags; moo_ooi_t preamble_code, preamble_index, preamble_flags;
MOO_ASSERT (moo, moo->c->cunit->cunit_type == MOO_CUNIT_CLASS);
name = (moo_oop_char_t)moo_makesymbol(moo, cc->mth.name.ptr, cc->mth.name.len);
if (!name) goto oops;
moo_pushvolat (moo, (moo_oop_t*)&name); tmp_count++;
/* The variadic data part passed to moo_instantiate() is not GC-safe.
* let's delay initialization of variadic data a bit. */
#if defined(MOO_USE_METHOD_TRAILER)
mth = (moo_oop_method_t)moo_instantiatewithtrailer(moo, moo->_method, cc->mth.literals.count, cc->mth.code.ptr, cc->mth.code.len);
#else
mth = (moo_oop_method_t)moo_instantiate(moo, moo->_method, MOO_NULL, cc->mth.literals.count);
#endif
if (!mth) goto oops;
for (i = 0; i < cc->mth.literals.count; i++)
{
/* let's do the variadic data initialization here */
MOO_STORE_OOP (moo, &mth->literal_frame[i], cc->mth.literals.ptr[i]);
}
moo_pushvolat (moo, (moo_oop_t*)&mth); tmp_count++;
#if defined(MOO_USE_METHOD_TRAILER)
/* do nothing */
#else
code = (moo_oop_byte_t)moo_instantiate(moo, moo->_byte_array, cc->mth.code.ptr, cc->mth.code.len);
if (!code) goto oops;
moo_pushvolat (moo, (moo_oop_t*)&code); tmp_count++;
#endif
preamble_code = MOO_METHOD_PREAMBLE_NONE; preamble_code = MOO_METHOD_PREAMBLE_NONE;
preamble_index = 0; preamble_index = 0;
preamble_flags = 0; preamble_flags = 0;
if (cc->mth.pftype <= 0) if (md->pftype <= 0)
{ {
/* no primitive is set - perform some mutation for simplicity and efficiency */ /* no primitive is set - perform some mutation for simplicity and efficiency */
if (cc->mth.code.len <= 0) if (md->code.len <= 0)
{ {
preamble_code = MOO_METHOD_PREAMBLE_RETURN_RECEIVER; preamble_code = MOO_METHOD_PREAMBLE_RETURN_RECEIVER;
} }
else else
{ {
if (cc->mth.code.ptr[0] == BCODE_RETURN_RECEIVER) if (md->code.ptr[0] == BCODE_RETURN_RECEIVER)
{ {
preamble_code = MOO_METHOD_PREAMBLE_RETURN_RECEIVER; preamble_code = MOO_METHOD_PREAMBLE_RETURN_RECEIVER;
} }
else if (cc->mth.code.len > 1 && cc->mth.code.ptr[1] == BCODE_RETURN_STACKTOP) else if (md->code.len > 1 && md->code.ptr[1] == BCODE_RETURN_STACKTOP)
{ {
switch (cc->mth.code.ptr[0]) switch (md->code.ptr[0])
{ {
case BCODE_PUSH_RECEIVER: case BCODE_PUSH_RECEIVER:
preamble_code = MOO_METHOD_PREAMBLE_RETURN_RECEIVER; preamble_code = MOO_METHOD_PREAMBLE_RETURN_RECEIVER;
@ -7573,15 +7533,15 @@ static int add_compiled_method_to_class (moo_t* moo)
case BCODE_PUSH_INSTVAR_6: case BCODE_PUSH_INSTVAR_6:
case BCODE_PUSH_INSTVAR_7: case BCODE_PUSH_INSTVAR_7:
preamble_code = MOO_METHOD_PREAMBLE_RETURN_INSTVAR; preamble_code = MOO_METHOD_PREAMBLE_RETURN_INSTVAR;
preamble_index = cc->mth.code.ptr[0] & 0x7; /* low 3 bits */ preamble_index = md->code.ptr[0] & 0x7; /* low 3 bits */
break; break;
} }
} }
else if (cc->mth.code.len > MOO_BCODE_LONG_PARAM_SIZE + 1 && else if (md->code.len > MOO_BCODE_LONG_PARAM_SIZE + 1 &&
cc->mth.code.ptr[MOO_BCODE_LONG_PARAM_SIZE + 1] == BCODE_RETURN_STACKTOP) md->code.ptr[MOO_BCODE_LONG_PARAM_SIZE + 1] == BCODE_RETURN_STACKTOP)
{ {
int i; int i;
switch (cc->mth.code.ptr[0]) switch (md->code.ptr[0])
{ {
case BCODE_PUSH_INSTVAR_X: case BCODE_PUSH_INSTVAR_X:
preamble_code = MOO_METHOD_PREAMBLE_RETURN_INSTVAR; preamble_code = MOO_METHOD_PREAMBLE_RETURN_INSTVAR;
@ -7599,7 +7559,7 @@ static int add_compiled_method_to_class (moo_t* moo)
preamble_index = 0; preamble_index = 0;
for (i = 1; i <= MOO_BCODE_LONG_PARAM_SIZE; i++) for (i = 1; i <= MOO_BCODE_LONG_PARAM_SIZE; i++)
{ {
preamble_index = (preamble_index << 8) | cc->mth.code.ptr[i]; preamble_index = (preamble_index << 8) | md->code.ptr[i];
} }
if (!MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(preamble_index)) if (!MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(preamble_index))
@ -7612,48 +7572,73 @@ static int add_compiled_method_to_class (moo_t* moo)
} }
} }
} }
else if (cc->mth.pftype == PFTYPE_NUMBERED) else if (md->pftype == PFTYPE_NUMBERED)
{ {
preamble_code = MOO_METHOD_PREAMBLE_PRIMITIVE; preamble_code = MOO_METHOD_PREAMBLE_PRIMITIVE;
preamble_index = cc->mth.pfnum; preamble_index = md->pfnum;
} }
else if (cc->mth.pftype == PFTYPE_NAMED) else if (md->pftype == PFTYPE_NAMED)
{ {
preamble_code = MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE; preamble_code = MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE;
preamble_index = cc->mth.pfnum; /* index to literal frame */ preamble_index = md->pfnum; /* index to literal frame */
} }
else if (cc->mth.pftype == PFTYPE_EXCEPTION) else if (md->pftype == PFTYPE_EXCEPTION)
{ {
preamble_code = MOO_METHOD_PREAMBLE_EXCEPTION; preamble_code = MOO_METHOD_PREAMBLE_EXCEPTION;
preamble_index = 0; preamble_index = 0;
} }
else else
{ {
MOO_ASSERT (moo, cc->mth.pftype == PFTYPE_ENSURE); MOO_ASSERT (moo, md->pftype == PFTYPE_ENSURE);
preamble_code = MOO_METHOD_PREAMBLE_ENSURE; preamble_code = MOO_METHOD_PREAMBLE_ENSURE;
preamble_index = 0; preamble_index = 0;
} }
preamble_flags |= cc->mth.variadic; /* MOO_METHOD_PREAMBLE_FLAG_VARIADIC or MOO_METHOD_PREAMBLE_FLAG_LIBERAL */ preamble_flags |= md->variadic; /* MOO_METHOD_PREAMBLE_FLAG_VARIADIC or MOO_METHOD_PREAMBLE_FLAG_LIBERAL */
if (cc->mth.type == MOO_METHOD_DUAL) preamble_flags |= MOO_METHOD_PREAMBLE_FLAG_DUAL; if (md->type == MOO_METHOD_DUAL) preamble_flags |= MOO_METHOD_PREAMBLE_FLAG_DUAL;
if (cc->mth.lenient) preamble_flags |= MOO_METHOD_PREAMBLE_FLAG_LENIENT; if (md->lenient) preamble_flags |= MOO_METHOD_PREAMBLE_FLAG_LENIENT;
MOO_ASSERT (moo, MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(preamble_index)); MOO_ASSERT (moo, MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(preamble_index));
return MOO_METHOD_MAKE_PREAMBLE(preamble_code, preamble_index, preamble_flags);
}
static int add_compiled_method_to_class (moo_t* moo)
{
moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit;
moo_oop_char_t name; /* selector */
moo_oop_method_t mth; /* method */
moo_oow_t tmp_count = 0;
moo_oow_t i;
moo_ooi_t preamble;
MOO_ASSERT (moo, moo->c->cunit->cunit_type == MOO_CUNIT_CLASS);
name = (moo_oop_char_t)moo_makesymbol(moo, cc->mth.name.ptr, cc->mth.name.len);
if (!name) goto oops;
moo_pushvolat (moo, (moo_oop_t*)&name); tmp_count++;
/* The variadic data part passed to moo_instantiate() is not GC-safe.
* let's delay initialization of variadic data a bit. */
mth = (moo_oop_method_t)moo_instantiatewithtrailer(moo, moo->_method, cc->mth.literals.count, cc->mth.code.ptr, cc->mth.code.len);
if (!mth) goto oops;
for (i = 0; i < cc->mth.literals.count; i++)
{
/* let's do the variadic data initialization here */
MOO_STORE_OOP (moo, &mth->literal_frame[i], cc->mth.literals.ptr[i]);
}
moo_pushvolat (moo, (moo_oop_t*)&mth); tmp_count++;
preamble = compute_preamble(moo, &cc->mth);
MOO_STORE_OOP (moo, (moo_oop_t*)&mth->owner, (moo_oop_t)cc->self_oop); MOO_STORE_OOP (moo, (moo_oop_t*)&mth->owner, (moo_oop_t)cc->self_oop);
MOO_STORE_OOP (moo, (moo_oop_t*)&mth->name, (moo_oop_t)name); MOO_STORE_OOP (moo, (moo_oop_t*)&mth->name, (moo_oop_t)name);
mth->preamble = MOO_SMOOI_TO_OOP(MOO_METHOD_MAKE_PREAMBLE(preamble_code, preamble_index, preamble_flags)); mth->preamble = MOO_SMOOI_TO_OOP(preamble);
mth->preamble_data[0] = MOO_SMPTR_TO_OOP(0); mth->preamble_data[0] = MOO_SMPTR_TO_OOP(0);
mth->preamble_data[1] = MOO_SMPTR_TO_OOP(0); mth->preamble_data[1] = MOO_SMPTR_TO_OOP(0);
mth->tmpr_count = MOO_SMOOI_TO_OOP(cc->mth.tmpr_count); mth->tmpr_count = MOO_SMOOI_TO_OOP(cc->mth.tmpr_count);
mth->tmpr_nargs = MOO_SMOOI_TO_OOP(cc->mth.tmpr_nargs); mth->tmpr_nargs = MOO_SMOOI_TO_OOP(cc->mth.tmpr_nargs);
#if defined(MOO_USE_METHOD_TRAILER)
/* do nothing */
#else
MOO_STORE_OOP (moo, (moo_oop_t*)&mth->code, (moo_oop_t)code);
#endif
if (moo->dbgi) if (moo->dbgi)
{ {
moo_oow_t file_offset; moo_oow_t file_offset;
@ -7718,6 +7703,12 @@ oops:
return -1; return -1;
} }
static int add_compiled_method_to_interface (moo_t* moo)
{
/* TODO: */
return -1;
}
static void clear_pooldic_import_data (moo_t* moo, moo_pooldic_import_data_t* pdimp) static void clear_pooldic_import_data (moo_t* moo, moo_pooldic_import_data_t* pdimp)
{ {
if (pdimp->dcl.ptr) moo_freemem (moo, pdimp->dcl.ptr); if (pdimp->dcl.ptr) moo_freemem (moo, pdimp->dcl.ptr);
@ -9546,7 +9537,7 @@ oops:
static int __compile_method_signature (moo_t* moo) static int __compile_method_signature (moo_t* moo)
{ {
/*moo_cunit_interface_t* ifce = (moo_cunit_interface_t*)moo->c->cunit;*/ moo_cunit_interface_t* ifce = (moo_cunit_interface_t*)moo->c->cunit;
MOO_ASSERT (moo, moo->c->cunit->cunit_type == MOO_CUNIT_INTERFACE); MOO_ASSERT (moo, moo->c->cunit->cunit_type == MOO_CUNIT_INTERFACE);
@ -9558,18 +9549,43 @@ static int __compile_method_signature (moo_t* moo)
if (compile_method_name(moo) <= -1) return -1; if (compile_method_name(moo) <= -1) return -1;
if (TOKEN_TYPE(moo) != MOO_IOTOK_PERIOD) if (TOKEN_TYPE(moo) == MOO_IOTOK_LBRACE)
{ {
/* . expected */ /* you can inlcude method body optionally */
moo_setsynerr (moo, MOO_SYNERR_PERIOD, TOKEN_LOC(moo), TOKEN_NAME(moo)); GET_TOKEN (moo);
if (compile_method_temporaries(moo) <= -1 ||
compile_method_pragma(moo) <= -1 || /* TODO: disallow pragmas... */
compile_method_statements(moo) <= -1) return -1;
if (TOKEN_TYPE(moo) != MOO_IOTOK_RBRACE)
{
/* } expected */
moo_setsynerr (moo, MOO_SYNERR_RBRACE, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1; return -1;
} }
if (add_method_signature(moo) <= -1) return -1; /* end of method has been reached */
if (resolve_goto_labels(moo) <= -1) return -1;
GET_TOKEN (moo); GET_TOKEN (moo);
/* add a compiled method to the method dictionary */
if (add_compiled_method_to_interface(moo) <= -1) return -1;
return 0; return 0;
} }
else if (TOKEN_TYPE(moo) == MOO_IOTOK_PERIOD)
{
if (add_method_signature(moo) <= -1) return -1;
GET_TOKEN (moo);
return 0;
}
/* . or { expected */
moo_setsynerrbfmt (moo, MOO_SYNERR_PERIOD, TOKEN_LOC(moo), TOKEN_NAME(moo), "period or left brace expected");
return -1;
}
static int compile_method_signature (moo_t* moo) static int compile_method_signature (moo_t* moo)
{ {
@ -10029,7 +10045,7 @@ static int __compile_pooldic_definition (moo_t* moo)
if (TOKEN_TYPE(moo) != MOO_IOTOK_COMMA) if (TOKEN_TYPE(moo) != MOO_IOTOK_COMMA)
{ {
moo_setsynerrbfmt (moo, MOO_SYNERR_COMMA, TOKEN_LOC(moo), TOKEN_NAME(moo), "comma expected"); moo_setsynerrbfmt (moo, MOO_SYNERR_COMMA, TOKEN_LOC(moo), TOKEN_NAME(moo), ", expected to separate pooldic items");
goto oops; goto oops;
} }
@ -10039,7 +10055,7 @@ static int __compile_pooldic_definition (moo_t* moo)
* to be followed by a comma. what is better? */ * to be followed by a comma. what is better? */
if (TOKEN_TYPE(moo) != MOO_IOTOK_IDENT) if (TOKEN_TYPE(moo) != MOO_IOTOK_IDENT)
{ {
moo_setsynerrbfmt (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo), "identifier expected after comma"); moo_setsynerrbfmt (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo), "identifier expected after ,");
goto oops; goto oops;
} }
} }

View File

@ -4815,12 +4815,8 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
moo->processor->active->perrmsg = moo->_nil; moo->processor->active->perrmsg = moo->_nil;
} }
#if defined(MOO_USE_METHOD_TRAILER)
MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_TRAILER(method)); MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_TRAILER(method));
if (MOO_METHOD_GET_CODE_SIZE(method) == 0) /* this trailer size field is not a small integer */ if (MOO_METHOD_GET_CODE_SIZE(method) == 0) /* this trailer size field is not a small integer */
#else
if (method->code == moo->_nil)
#endif
{ {
/* no byte code to execute - invoke 'self primitiveFailed' */ /* no byte code to execute - invoke 'self primitiveFailed' */
moo_oow_t i; moo_oow_t i;

View File

@ -486,16 +486,14 @@ static int ignite_1 (moo_t* moo)
MOO_OBJ_SET_CLASS (moo->_nil, (moo_oop_t)moo->_undefined_object); MOO_OBJ_SET_CLASS (moo->_nil, (moo_oop_t)moo->_undefined_object);
#if defined(MOO_USE_METHOD_TRAILER) /* an instance of a method class stores byte codes in the trailer space.
/* an instance of a method class stores byte codes in the trailer space * unlike other classes with trailer size set, the size of the trailer
* when compiled with MOO_USE_METHOD_TRAILER. unlike other classes with * space is not really determined by the traailer size set in the class.
* trailer size set, the size of the trailer space is not really determined * the compiler determines the actual size of the trailer space depending
* by the traailer size set in the class. the compiler determines the * on the byte codes generated. i should set the following fields to avoid
* actual size of the trailer space depending on the byte codes generated. * confusion at the GC phase. */
* i should set the following fields to avoid confusion at the GC phase. */
moo->_method->trsize = MOO_SMOOI_TO_OOP(0); moo->_method->trsize = MOO_SMOOI_TO_OOP(0);
moo->_method->trgc = MOO_SMPTR_TO_OOP(0); moo->_method->trgc = MOO_SMPTR_TO_OOP(0);
#endif
return 0; return 0;
} }

View File

@ -862,11 +862,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++; moo_pushvolat (moo, (moo_oop_t*)&pfidsym); tmp_count++;
#if defined(MOO_USE_METHOD_TRAILER)
mth = (moo_oop_method_t)moo_instantiatewithtrailer (moo, moo->_method, 1, MOO_NULL, 0); mth = (moo_oop_method_t)moo_instantiatewithtrailer (moo, moo->_method, 1, MOO_NULL, 0);
#else
mth = (moo_oop_method_t)moo_instantiate(moo, moo->_method, MOO_NULL, 1);
#endif
if (!mth) if (!mth)
{ {
MOO_DEBUG2 (moo, "Cannot generate primitive function method [%js] in [%O] - method instantiation failure\n", mthname, _class->name); MOO_DEBUG2 (moo, "Cannot generate primitive function method [%js] in [%O] - method instantiation failure\n", mthname, _class->name);

View File

@ -34,12 +34,6 @@
/* TODO: move this macro out to the build files.... */ /* TODO: move this macro out to the build files.... */
#define MOO_INCLUDE_COMPILER #define MOO_INCLUDE_COMPILER
/* define this to allow an pointer(OOP) object to have trailing bytes
* this is used to embed bytes codes into the back of a compile method
* object instead of putting in in a separate byte array. */
#define MOO_USE_METHOD_TRAILER
typedef struct moo_mod_t moo_mod_t; typedef struct moo_mod_t moo_mod_t;
/* ========================================================================== */ /* ========================================================================== */
@ -569,11 +563,8 @@ struct moo_methsig_t
moo_oop_t tmpr_nargs; /* SmallInteger */ moo_oop_t tmpr_nargs; /* SmallInteger */
}; };
#if defined(MOO_USE_METHOD_TRAILER)
#define MOO_METHOD_NAMED_INSTVARS 9 #define MOO_METHOD_NAMED_INSTVARS 9
#else
# define MOO_METHOD_NAMED_INSTVARS 10
#endif
typedef struct moo_method_t moo_method_t; typedef struct moo_method_t moo_method_t;
typedef struct moo_method_t* moo_oop_method_t; typedef struct moo_method_t* moo_oop_method_t;
struct moo_method_t struct moo_method_t
@ -594,22 +585,15 @@ struct moo_method_t
/* number of arguments in temporaries */ /* number of arguments in temporaries */
moo_oop_t tmpr_nargs; /* SmallInteger */ moo_oop_t tmpr_nargs; /* SmallInteger */
#if defined(MOO_USE_METHOD_TRAILER)
/* no code field is used. it's placed after literal_frame. */
#else
moo_oop_byte_t code; /* ByteArray */
#endif
moo_oop_t dbgi_file_offset; /* SmallInteger. source file path that contains the definition of this method. offset from moo->dbgi. 0 if unavailable */ moo_oop_t dbgi_file_offset; /* SmallInteger. source file path that contains the definition of this method. offset from moo->dbgi. 0 if unavailable */
moo_oop_t dbgi_method_offset; /* SmallInteger */ moo_oop_t dbgi_method_offset; /* SmallInteger */
/* == variable indexed part == */ /* == variable indexed part == */
moo_oop_t literal_frame[1]; /* it stores literals */ moo_oop_t literal_frame[1]; /* it stores literals */
/* after the literal frame comes the actual byte code, if MOO_USE_METHOD_TRAILER is defined */ /* after the literal frame comes the actual byte code */
}; };
#if defined(MOO_USE_METHOD_TRAILER)
/* the first byte after the main payload is the trailer size /* the first byte after the main payload is the trailer size
* the code bytes are placed after the trailer size. * the code bytes are placed after the trailer size.
* *
@ -618,10 +602,7 @@ struct moo_method_t
* size -> ((moo_oow_t)((moo_oop_oop_t)m)->slot[MOO_OBJ_GET_SIZE(m)])*/ * size -> ((moo_oow_t)((moo_oop_oop_t)m)->slot[MOO_OBJ_GET_SIZE(m)])*/
#define MOO_METHOD_GET_CODE_BYTE(m) MOO_OBJ_GET_TRAILER_BYTE(m) #define MOO_METHOD_GET_CODE_BYTE(m) MOO_OBJ_GET_TRAILER_BYTE(m)
#define MOO_METHOD_GET_CODE_SIZE(m) MOO_OBJ_GET_TRAILER_SIZE(m) #define MOO_METHOD_GET_CODE_SIZE(m) MOO_OBJ_GET_TRAILER_SIZE(m)
#else
# define MOO_METHOD_GET_CODE_BYTE(m) MOO_OBJ_GET_BYTE_SLOT(((m)->code)
# define MOO_METHOD_GET_CODE_SIZE(m) MOO_OBJ_GET_SIZE((m)->code)
#endif
/* The preamble field is composed of: /* The preamble field is composed of:
* 4-bit flag * 4-bit flag