diff --git a/kernel/Class.st b/kernel/Class.st index 18918e2..9bcc603 100644 --- a/kernel/Class.st +++ b/kernel/Class.st @@ -271,7 +271,21 @@ the class category.'> [:method :ann | method rewriteAsAsyncCCall: (ann arguments at: 1) args: (ann arguments at: 2)] - forPragma: #asyncCCall:args: + forPragma: #asyncCCall:args:. + self registerHandler: + [:method :ann | + method makeReadOnly: false. + method header: ((((method numArgs bitOr: (method numTemps bitShift: 11)) bitOr: (method stackDepth bitShift: 5)) bitOr: ((VMpr_MirrorPrimitive_executePrimitiveFailBlock bitShift: 17))) bitOr: (4 bitShift: 27)) literals: (method literals copyWith: (ann arguments at: 1)). + method makeReadOnly: true. + nil ] + forPragma: #mirrorPrimitive:. + self registerHandler: + [:method :ann | + method makeReadOnly: false. + method header: ((((method numArgs bitOr: (method numTemps bitShift: 11)) bitOr: (method stackDepth bitShift: 5)) bitOr: ((VMpr_MirrorPrimitive_executePrimitiveFailBlock bitShift: 17))) bitOr: (4 bitShift: 27)) literals: (method literals copyWith: (ann arguments at: 1)). + method makeReadOnly: true. + nil ] + forPragma: #mirrorPrimitiveWithBlock: ] initialize [ diff --git a/libgst/genpr-parse.y b/libgst/genpr-parse.y index 6d373ca..c3629d1 100644 --- a/libgst/genpr-parse.y +++ b/libgst/genpr-parse.y @@ -279,7 +279,8 @@ gen_proto (const char *s) filprintf (proto_fil, "static intptr_t\n" "%s (int id ATTRIBUTE_UNUSED,\n" - "%*svolatile int numArgs ATTRIBUTE_UNUSED);\n\n", + "%*svolatile int numArgs ATTRIBUTE_UNUSED,\n" + "OOP compiledMethod);\n\n", s, 2 + strlen(s), ""); } @@ -289,7 +290,8 @@ gen_prim_decl (const char *s) filprintf (stmt_fil, "intptr_t\n" "%s (int id,\n" - "%*svolatile int numArgs)\n", + "%*svolatile int numArgs,\n" + "OOP compiledMethod)\n", s, 2 + strlen(s), ""); } @@ -371,7 +373,8 @@ output() "%s\n" "intptr_t\n" "VMpr_HOLE (int id,\n" - " volatile int numArgs)\n" + " volatile int numArgs,\n" + " OOP compiledMethod)\n" "{\n" " _gst_primitives_executed++;\n" " _gst_errorf (\"Unhandled primitive operation %%d\", id);\n" diff --git a/libgst/interp-bc.inl b/libgst/interp-bc.inl index 8819481..c6c0a14 100644 --- a/libgst/interp-bc.inl +++ b/libgst/interp-bc.inl @@ -274,7 +274,8 @@ _gst_send_message_internal (OOP sendSelector, case MTH_PRIMITIVE: if COMMON (!execute_primitive_operation(header.primitiveIndex, - sendArgs)) + sendArgs, + methodOOP)) /* primitive succeeded. Continue with the parent context */ return; @@ -362,7 +363,8 @@ _gst_send_method (OOP methodOOP) case MTH_PRIMITIVE: if COMMON (!execute_primitive_operation(header.primitiveIndex, - sendArgs)) + sendArgs, + methodOOP)) /* primitive succeeded. Continue with the parent context */ return; diff --git a/libgst/interp.c b/libgst/interp.c index 6e3a1dd..92872fa 100644 --- a/libgst/interp.c +++ b/libgst/interp.c @@ -269,7 +269,8 @@ static int verbose_exec_tracing = false; correct id and the same NUMARGS and METHODOOP with which it was invoked. */ static inline intptr_t execute_primitive_operation (int primitive, - volatile int numArgs); + volatile int numArgs, + OOP compiledMethod); /* Execute a #at: primitive, with arguments REC and IDX, knowing that the receiver's class has an instance specification SPEC. */ @@ -2738,11 +2739,11 @@ cached_index_oop_put_primitive (OOP rec, OOP idx, OOP val, intptr_t spec) } static inline intptr_t -execute_primitive_operation (int primitive, volatile int numArgs) +execute_primitive_operation (int primitive, volatile int numArgs, OOP compiledMethod) { prim_table_entry *pte = &_gst_primitive_table[primitive]; - intptr_t result = pte->func (pte->id, numArgs); + intptr_t result = pte->func (pte->id, numArgs, compiledMethod); last_primitive = primitive; return result; } diff --git a/libgst/interp.h b/libgst/interp.h index e286e47..03a8fc7 100644 --- a/libgst/interp.h +++ b/libgst/interp.h @@ -582,7 +582,8 @@ extern OOP _gst_make_block_closure (OOP blockOOP) aided in the choice of which by the user-defined parameter ID, popping NUMARGS methods off the stack if they succeed. */ typedef intptr_t (*primitive_func) (int primitive, - volatile int numArgs); + volatile int numArgs, + OOP compiledMethod); /* Table of primitives, including a primitive and its attributes. */ typedef struct prim_table_entry diff --git a/libgst/prims.def b/libgst/prims.def index 131dc8c..2ad9b79 100644 --- a/libgst/prims.def +++ b/libgst/prims.def @@ -6229,5 +6229,51 @@ primitive VMpr_Random_next [succeed] PRIM_FAILED; } +primitive VMpr_MirrorPrimitive_privateExecutePrimitive : + prim_id VMpr_MirrorPrimitive_executePrimitive [fail,succeed], + prim_id VMpr_MirrorPrimitive_executePrimitiveFailBlock [fail,succeed] +{ + OOP blockOOP; + gst_compiled_method _method = (gst_compiled_method) OOP_TO_OBJ (compiledMethod); + int primitiveIndex; + _gst_primitives_executed++; + + if (!IS_INT (ARRAY_OOP_AT (OOP_TO_OBJ (_method->literals), NUM_INDEXABLE_FIELDS (_method->literals)))) + PRIM_FAILED; + + primitiveIndex = TO_INT (ARRAY_OOP_AT (OOP_TO_OBJ (_method->literals), NUM_INDEXABLE_FIELDS (_method->literals))); + + /* Pop the error block */ + if (id == prim_id (VMpr_MirrorPrimitive_executePrimitiveFailBlock)) + { + blockOOP = POP_OOP (); + numArgs--; + } + + /* Pop the selector */ + numArgs--; + + if COMMON (!execute_primitive_operation(primitiveIndex, numArgs, compiledMethod)) + { + OOP res = STACKTOP (); + + POP_OOP (); // object + SET_STACKTOP (res); // replace self + + PRIM_SUCCEEDED; + } + + numArgs++; + + /* Push the error block */ + if (id == prim_id (VMpr_MirrorPrimitive_executePrimitiveFailBlock)) + { + PUSH_OOP (blockOOP); + numArgs++; + } + + PRIM_FAILED; +} + #undef INT_BIN_OP #undef BOOL_BIN_OP diff --git a/libgst/vm.def b/libgst/vm.def index fb0b61b..167e21c 100644 --- a/libgst/vm.def +++ b/libgst/vm.def @@ -325,7 +325,7 @@ operation DIVIDE_SPECIAL ( op1 op2 -- op ) { EXPORT_REGS(); if (COMMON (ARE_INTS (op1, op2))) { - if (!VMpr_SmallInteger_divide (10, 1)) + if (!VMpr_SmallInteger_divide (10, 1, NULL)) { IMPORT_REGS (); NEXT_BC; @@ -341,7 +341,7 @@ operation REMAINDER_SPECIAL ( op1 op2 -- op ) { PREPARE_STACK (); EXPORT_REGS(); if (IS_INT (op1) && IS_INT (op2) - && !VMpr_SmallInteger_modulo (11, 1)) + && !VMpr_SmallInteger_modulo (11, 1, NULL)) { IMPORT_REGS (); NEXT_BC; @@ -403,7 +403,7 @@ operation INTEGER_DIVIDE_SPECIAL ( op1 op2 -- op1 op2 ) { PREPARE_STACK (); EXPORT_REGS(); if (IS_INT (op1) && IS_INT (op2) - && !VMpr_SmallInteger_intDiv (12, 1)) + && !VMpr_SmallInteger_intDiv (12, 1, NULL)) { IMPORT_REGS (); NEXT_BC; @@ -518,7 +518,7 @@ operation SIZE_SPECIAL ( rec -- val ) { } if COMMON (size_cache_class == (classOOP = OOP_CLASS (rec)) - && !execute_primitive_operation (size_cache_prim, 0)) + && !execute_primitive_operation (size_cache_prim, 0, NULL)) { IMPORT_REGS (); NEXT_BC; @@ -551,7 +551,7 @@ operation CLASS_SPECIAL ( rec -- val ) { } if COMMON (class_cache_class == (classOOP = OOP_CLASS (rec)) - && !execute_primitive_operation (class_cache_prim, 1)) + && !execute_primitive_operation (class_cache_prim, 1, NULL)) { IMPORT_REGS (); NEXT_BC;