3 #include "st-compiler.h"
4 #include "st-universe.h"
5 #include "st-dictionary.h"
8 #include "st-behavior.h"
9 #include "st-context.h"
10 #include "st-primitives.h"
11 #include "st-method.h"
13 #include "st-association.h"
19 method_context_new (st_processor
*pr
)
26 large
= st_method_get_large_context (pr
->new_method
);
27 stack_size
= large
? 32 : 12;
29 context
= st_memory_allocate_context (large
);
31 ST_CONTEXT_PART_SENDER (context
) = pr
->context
;
32 ST_CONTEXT_PART_IP (context
) = st_smi_new (0);
33 ST_CONTEXT_PART_SP (context
) = st_smi_new (0);
34 ST_METHOD_CONTEXT_RECEIVER (context
) = pr
->message_receiver
;
35 ST_METHOD_CONTEXT_METHOD (context
) = pr
->new_method
;
37 stack
= ST_METHOD_CONTEXT (context
)->stack
;
38 for (st_uint i
=0; i
< stack_size
; i
++)
45 block_context_new (st_processor
*pr
, st_uint initial_ip
, st_uint argcount
)
55 context
= st_memory_allocate (ST_SIZE_OOPS (struct st_block_context
) + stack_size
);
56 st_object_initialize_header (context
, st_block_context_class
);
57 st_object_set_large_context (context
, true);
59 if (ST_OBJECT_CLASS (pr
->context
) == st_block_context_class
)
60 home
= ST_BLOCK_CONTEXT_HOME (pr
->context
);
64 ST_CONTEXT_PART_SENDER (context
) = st_nil
;
65 ST_CONTEXT_PART_IP (context
) = st_smi_new (0);
66 ST_CONTEXT_PART_SP (context
) = st_smi_new (0);
68 ST_BLOCK_CONTEXT_INITIALIP (context
) = st_smi_new (initial_ip
);
69 ST_BLOCK_CONTEXT_ARGCOUNT (context
) = st_smi_new (argcount
);
70 ST_BLOCK_CONTEXT_CALLER (context
) = st_nil
;
71 ST_BLOCK_CONTEXT_HOME (context
) = home
;
73 stack
= ST_BLOCK_CONTEXT (context
)->stack
;
74 for (st_uint i
=0; i
< stack_size
; i
++)
81 create_actual_message (st_processor
*pr
)
86 array
= st_object_new_arrayed (st_array_class
, pr
->message_argcount
);
87 elements
= st_array_elements (array
);
88 for (st_uint i
= 0; i
< pr
->message_argcount
; i
++)
89 elements
[i
] = pr
->stack
[pr_sp
- pr
->message_argcount
+ i
];
91 pr_sp
-= pr
->message_argcount
;
93 ST_STACK_PUSH (pr
, st_message_new (pr
->message_selector
, array
));
95 pr
->message_selector
= st_selector_doesNotUnderstand
;
96 pr
->message_argcount
= 1;
100 lookup_method (st_processor
*pr
, st_oop
class)
103 st_oop parent
= class;
106 index
= ST_METHOD_CACHE_HASH (class, pr
->message_selector
);
108 if (pr
->method_cache
[index
].class == class &&
109 pr
->method_cache
[index
].selector
== pr
->message_selector
)
110 return pr
->method_cache
[index
].method
;
112 while (parent
!= st_nil
) {
113 method
= st_dictionary_at (ST_BEHAVIOR_METHOD_DICTIONARY (parent
), pr
->message_selector
);
114 if (method
!= st_nil
) {
115 index
= ST_METHOD_CACHE_HASH (parent
, pr
->message_selector
);
116 pr
->method_cache
[index
].class = class;
117 pr
->method_cache
[index
].selector
= pr
->message_selector
;
118 pr
->method_cache
[index
].method
= method
;
121 parent
= ST_BEHAVIOR_SUPERCLASS (parent
);
124 if (pr
->message_selector
== st_selector_doesNotUnderstand
) {
125 fprintf (stderr
, "no method found for #doesNotUnderstand:");
129 create_actual_message (pr
);
131 return lookup_method (pr
, class);
135 st_processor_lookup_method (st_processor
*pr
, st_oop
class)
137 return lookup_method (pr
, class);
141 * Creates a new method context. Parameterised by
142 * @sender, @receiver, @method, and @argcount
144 * Message arguments are copied into the new context's temporary
145 * frame. Receiver and arguments are then popped off the stack.
149 activate_method (st_processor
*pr
)
154 context
= method_context_new (pr
);
156 arguments
= ST_METHOD_CONTEXT_TEMPORARY_FRAME (context
);
157 for (st_uint i
= 0; i
< pr
->message_argcount
; i
++)
158 arguments
[i
] = pr
->stack
[pr_sp
- pr
->message_argcount
+ i
];
160 pr_sp
-= pr
->message_argcount
+ 1;
162 st_processor_set_active_context (pr
, context
);
166 st_processor_execute_method (st_processor
*pr
)
168 st_uint primitive_index
;
169 st_method_flags flags
;
171 flags
= st_method_get_flags (pr
->new_method
);
172 if (flags
== ST_METHOD_PRIMITIVE
) {
173 primitive_index
= st_method_get_primitive_index (pr
->new_method
);
175 st_primitives
[primitive_index
].func (pr
);
176 if (ST_LIKELY (pr
->success
))
180 activate_method (pr
);
185 st_processor_set_active_context (st_processor
*pr
,
190 /* save executation state of active context */
191 if (pr
->context
!= st_nil
) {
192 ST_CONTEXT_PART_IP (pr
->context
) = st_smi_new (pr_ip
- st_method_bytecode_bytes (pr
->method
));
193 ST_CONTEXT_PART_SP (pr
->context
) = st_smi_new (pr_sp
);
196 if (st_object_class (context
) == st_block_context_class
) {
198 home
= ST_BLOCK_CONTEXT_HOME (context
);
200 pr
->method
= ST_METHOD_CONTEXT_METHOD (home
);
201 pr
->receiver
= ST_METHOD_CONTEXT_RECEIVER (home
);
202 pr
->literals
= st_array_elements (ST_METHOD_LITERALS (pr
->method
));
203 pr
->temps
= ST_METHOD_CONTEXT_TEMPORARY_FRAME (home
);
204 pr
->stack
= ST_BLOCK_CONTEXT_STACK (context
);
206 pr
->method
= ST_METHOD_CONTEXT_METHOD (context
);
207 pr
->receiver
= ST_METHOD_CONTEXT_RECEIVER (context
);
208 pr
->literals
= st_array_elements (ST_METHOD_LITERALS (pr
->method
));
209 pr
->temps
= ST_METHOD_CONTEXT_TEMPORARY_FRAME (context
);
210 pr
->stack
= ST_METHOD_CONTEXT_STACK (context
);
213 pr
->context
= context
;
214 pr_sp
= st_smi_value (ST_CONTEXT_PART_SP (context
));
215 pr_ip
= st_method_bytecode_bytes (pr
->method
) + st_smi_value (ST_CONTEXT_PART_IP (context
));
216 pr
->bytecode
= st_method_bytecode_bytes (pr
->method
);
221 st_processor_prologue (st_processor
*pr
)
223 if (st_verbose_mode ()) {
224 fprintf (stderr
, "** gc: totalPauseTime: %.6fs\n", st_timespec_to_double_seconds (&memory
->total_pause_time
));
229 st_processor_send_selector (st_processor
*pr
,
234 st_uint primitive_index
;
235 st_method_flags flags
;
237 pr
->message_argcount
= argcount
;
238 pr
->message_receiver
= pr
->stack
[pr_sp
- argcount
- 1];
239 pr
->message_selector
= selector
;
241 pr
->new_method
= st_processor_lookup_method (pr
, st_object_class (pr
->message_receiver
));
243 flags
= st_method_get_flags (pr
->new_method
);
244 if (flags
== ST_METHOD_PRIMITIVE
) {
245 primitive_index
= st_method_get_primitive_index (pr
->new_method
);
247 st_primitives
[primitive_index
].func (pr
);
248 if (ST_LIKELY (pr
->success
))
252 activate_method (pr
);
255 #define SEND_SELECTOR(pr, selector, argcount) \
256 st_processor_send_selector (pr, selector, argcount); \
258 #define ACTIVATE_CONTEXT(pr, context) \
259 st_processor_set_active_context (pr, context); \
261 #define ACTIVATE_METHOD(pr) \
262 activate_method (pr); \
264 #define EXECUTE_PRIMITIVE(pr, index) \
265 pr->success = true; \
266 st_primitives[index].func (pr);
268 #define SEND_TEMPLATE(pr) \
270 st_method_flags flags; \
274 pr->new_method = st_processor_lookup_method (pr, st_object_class (pr->message_receiver));\
276 flags = st_method_get_flags (pr->new_method); \
277 if (flags == ST_METHOD_PRIMITIVE) { \
278 prim = st_method_get_primitive_index (pr->new_method); \
280 EXECUTE_PRIMITIVE (pr, prim); \
281 if (ST_LIKELY (pr->success)) \
285 ACTIVATE_METHOD (pr);
289 #define I_HAS_COMPUTED_GOTO
292 #ifdef I_HAS_COMPUTED_GOTO
294 static const st_pointer labels[] = \
297 && PUSH_TEMP, && PUSH_INSTVAR, \
298 && PUSH_LITERAL_CONST, && PUSH_LITERAL_VAR, \
300 && STORE_LITERAL_VAR, && STORE_TEMP, && STORE_INSTVAR, \
301 && STORE_POP_LITERAL_VAR, && STORE_POP_TEMP, && STORE_POP_INSTVAR, \
303 && PUSH_SELF, && PUSH_NIL, && PUSH_TRUE, && PUSH_FALSE, && PUSH_INTEGER, \
305 && RETURN_STACK_TOP, && BLOCK_RETURN, \
306 && POP_STACK_TOP, && DUPLICATE_STACK_TOP, \
308 && PUSH_ACTIVE_CONTEXT, && BLOCK_COPY, \
310 && JUMP_TRUE, && JUMP_FALSE, && JUMP, \
312 && SEND, && SEND_SUPER, \
314 && SEND_PLUS, && SEND_MINUS, \
315 && SEND_LT, && SEND_GT, \
316 && SEND_LE, && SEND_GE, \
317 && SEND_EQ, && SEND_NE, \
318 && SEND_MUL, && SEND_DIV, \
319 && SEND_MOD, && SEND_BITSHIFT, \
320 && SEND_BITAND, && SEND_BITOR, \
323 && SEND_AT, && SEND_AT_PUT, \
324 && SEND_SIZE, && SEND_VALUE, \
325 && SEND_VALUE_ARG, && SEND_IDENTITY_EQ, \
326 && SEND_CLASS, && SEND_NEW, \
336 #ifdef I_HAS_COMPUTED_GOTO
339 #define CASE(OP) case OP:
342 #ifdef I_HAS_COMPUTED_GOTO
343 #define NEXT() goto *labels[*pr_ip]
345 #define NEXT() goto start
348 const st_uchar
*pr_ip
;
352 st_processor_main (st_processor
*pr
)
354 if (setjmp (pr
->main_loop
))
357 pr_ip
= pr
->bytecode
;
363 ST_STACK_PUSH (pr
, pr
->temps
[pr_ip
[1]]);
369 CASE (PUSH_INSTVAR
) {
371 ST_STACK_PUSH (pr
, ST_OBJECT_FIELDS (pr
->receiver
)[pr_ip
[1]]);
377 CASE (STORE_POP_INSTVAR
) {
379 ST_OBJECT_FIELDS (pr
->receiver
)[pr_ip
[1]] = ST_STACK_POP (pr
);
385 CASE (STORE_INSTVAR
) {
387 ST_OBJECT_FIELDS (pr
->receiver
)[pr_ip
[1]] = ST_STACK_PEEK (pr
);
393 CASE (STORE_POP_TEMP
) {
395 pr
->temps
[pr_ip
[1]] = ST_STACK_POP (pr
);
403 pr
->temps
[pr_ip
[1]] = ST_STACK_PEEK (pr
);
409 CASE (STORE_LITERAL_VAR
) {
411 ST_ASSOCIATION_VALUE (pr
->literals
[pr_ip
[1]]) = ST_STACK_PEEK (pr
);
417 CASE (STORE_POP_LITERAL_VAR
) {
419 ST_ASSOCIATION_VALUE (pr
->literals
[pr_ip
[1]]) = ST_STACK_POP (pr
);
427 ST_STACK_PUSH (pr
, pr
->receiver
);
435 ST_STACK_PUSH (pr
, st_true
);
443 ST_STACK_PUSH (pr
, st_false
);
451 ST_STACK_PUSH (pr
, st_nil
);
457 CASE (PUSH_INTEGER
) {
459 ST_STACK_PUSH (pr
, st_smi_new ((signed char) pr_ip
[1]));
465 CASE (PUSH_ACTIVE_CONTEXT
) {
467 ST_STACK_PUSH (pr
, pr
->context
);
473 CASE (PUSH_LITERAL_CONST
) {
475 ST_STACK_PUSH (pr
, pr
->literals
[pr_ip
[1]]);
481 CASE (PUSH_LITERAL_VAR
) {
485 var
= ST_ASSOCIATION (pr
->literals
[pr_ip
[1]])->value
;
487 ST_STACK_PUSH (pr
, var
);
495 if (ST_STACK_PEEK (pr
) == st_true
) {
496 (void) ST_STACK_POP (pr
);
497 pr_ip
+= 3 + *((short *) (pr_ip
+ 1));
498 } else if (ST_LIKELY (ST_STACK_PEEK (pr
) == st_false
)) {
499 (void) ST_STACK_POP (pr
);
503 SEND_SELECTOR (pr
, st_selector_mustBeBoolean
, 0);
511 if (ST_STACK_PEEK (pr
) == st_false
) {
512 (void) ST_STACK_POP (pr
);
513 pr_ip
+= 3 + *((short *) (pr_ip
+ 1));
514 } else if (ST_LIKELY (ST_STACK_PEEK (pr
) == st_true
)) {
515 (void) ST_STACK_POP (pr
);
519 SEND_SELECTOR (pr
, st_selector_mustBeBoolean
, 0);
527 short offset
= *((short *) (pr_ip
+ 1));
529 pr_ip
+= ((offset
>= 0) ? 3 : 0) + offset
;
538 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
539 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
540 b
= ST_STACK_POP (pr
);
541 a
= ST_STACK_POP (pr
);
542 ST_STACK_PUSH (pr
, st_smi_new (st_smi_value (a
) + st_smi_value (b
)));
547 pr
->message_argcount
= 1;
548 pr
->message_selector
= st_specials
[ST_SPECIAL_PLUS
];
549 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
560 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
561 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
562 b
= ST_STACK_POP (pr
);
563 a
= ST_STACK_POP (pr
);
564 ST_STACK_PUSH (pr
, st_smi_new (st_smi_value (a
) - st_smi_value (b
)));
569 pr
->message_argcount
= 1;
570 pr
->message_selector
= st_specials
[ST_SPECIAL_MINUS
];
571 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
582 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
583 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
584 b
= ST_STACK_POP (pr
);
585 a
= ST_STACK_POP (pr
);
586 ST_STACK_PUSH (pr
, st_smi_new (st_smi_value (a
) * st_smi_value (b
)));
591 pr
->message_argcount
= 1;
592 pr
->message_selector
= st_specials
[ST_SPECIAL_MUL
];
593 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
605 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
606 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
607 b
= ST_STACK_POP (pr
);
608 a
= ST_STACK_POP (pr
);
609 ST_STACK_PUSH (pr
, st_smi_new (st_smi_value (a
) % st_smi_value (b
)));
614 pr
->message_argcount
= 1;
615 pr
->message_selector
= st_specials
[ST_SPECIAL_MOD
];
616 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
626 pr
->message_argcount
= 1;
627 pr
->message_selector
= st_specials
[ST_SPECIAL_DIV
];
628 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
635 CASE (SEND_BITSHIFT
) {
639 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
640 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
641 b
= ST_STACK_POP (pr
);
642 a
= ST_STACK_POP (pr
);
643 if (st_smi_value (b
) < 0) {
644 ST_STACK_PUSH (pr
, st_smi_new (st_smi_value (a
) >> -st_smi_value (b
)));
646 ST_STACK_PUSH (pr
, st_smi_new (st_smi_value (a
) << st_smi_value (b
)));
651 pr
->message_argcount
= 1;
652 pr
->message_selector
= st_specials
[ST_SPECIAL_BITSHIFT
];
653 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
664 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
665 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
666 b
= ST_STACK_POP (pr
);
667 a
= ST_STACK_POP (pr
);
668 ST_STACK_PUSH (pr
, st_smi_new (st_smi_value (a
) & st_smi_value (b
)));
673 pr
->message_argcount
= 1;
674 pr
->message_selector
= st_specials
[ST_SPECIAL_BITAND
];
675 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
686 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
687 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
688 b
= ST_STACK_POP (pr
);
689 a
= ST_STACK_POP (pr
);
690 ST_STACK_PUSH (pr
, st_smi_new (st_smi_value (a
) | st_smi_value (b
)));
695 pr
->message_argcount
= 1;
696 pr
->message_selector
= st_specials
[ST_SPECIAL_BITOR
];
697 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
708 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
709 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
710 b
= ST_STACK_POP (pr
);
711 a
= ST_STACK_POP (pr
);
712 ST_STACK_PUSH (pr
, st_smi_new (st_smi_value (a
) ^ st_smi_value (b
)));
717 pr
->message_argcount
= 1;
718 pr
->message_selector
= st_specials
[ST_SPECIAL_BITXOR
];
719 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
730 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
731 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
732 b
= ST_STACK_POP (pr
);
733 a
= ST_STACK_POP (pr
);
734 ST_STACK_PUSH (pr
, st_smi_value (a
) < st_smi_value (b
) ? st_true
: st_false
);
739 pr
->message_argcount
= 1;
740 pr
->message_selector
= st_specials
[ST_SPECIAL_LT
];
741 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
752 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
753 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
754 b
= ST_STACK_POP (pr
);
755 a
= ST_STACK_POP (pr
);
756 ST_STACK_PUSH (pr
, st_smi_value (a
) > st_smi_value (b
) ? st_true
: st_false
);
761 pr
->message_argcount
= 1;
762 pr
->message_selector
= st_specials
[ST_SPECIAL_GT
];
763 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
774 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
775 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
776 b
= ST_STACK_POP (pr
);
777 a
= ST_STACK_POP (pr
);
778 ST_STACK_PUSH (pr
, st_smi_value (a
) <= st_smi_value (b
) ? st_true
: st_false
);
783 pr
->message_argcount
= 1;
784 pr
->message_selector
= st_specials
[ST_SPECIAL_LE
];
785 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
796 if (ST_LIKELY (st_object_is_smi (pr
->stack
[pr_sp
- 1]) &&
797 st_object_is_smi (pr
->stack
[pr_sp
- 2]))) {
798 b
= ST_STACK_POP (pr
);
799 a
= ST_STACK_POP (pr
);
800 ST_STACK_PUSH (pr
, st_smi_value (a
) >= st_smi_value (b
) ? st_true
: st_false
);
805 pr
->message_argcount
= 1;
806 pr
->message_selector
= st_specials
[ST_SPECIAL_GE
];
807 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
816 pr
->message_argcount
= 0;
817 pr
->message_selector
= st_specials
[ST_SPECIAL_CLASS
];
818 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
827 pr
->message_argcount
= 0;
828 pr
->message_selector
= st_specials
[ST_SPECIAL_SIZE
];
829 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
838 pr
->message_argcount
= 1;
839 pr
->message_selector
= st_specials
[ST_SPECIAL_AT
];
840 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
849 pr
->message_argcount
= 2;
850 pr
->message_selector
= st_specials
[ST_SPECIAL_ATPUT
];
851 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
860 pr
->message_argcount
= 1;
861 pr
->message_selector
= st_specials
[ST_SPECIAL_EQ
];
862 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
871 pr
->message_argcount
= 1;
872 pr
->message_selector
= st_specials
[ST_SPECIAL_NE
];
873 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
880 CASE (SEND_IDENTITY_EQ
) {
883 a
= ST_STACK_POP (pr
);
884 b
= ST_STACK_POP (pr
);
886 ST_STACK_PUSH (pr
, (a
== b
) ? st_true
: st_false
);
894 pr
->message_argcount
= 0;
895 pr
->message_selector
= st_specials
[ST_SPECIAL_VALUE
];
896 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
903 CASE (SEND_VALUE_ARG
) {
905 pr
->message_argcount
= 1;
906 pr
->message_selector
= st_specials
[ST_SPECIAL_VALUE_ARG
];
907 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
916 pr
->message_argcount
= 0;
917 pr
->message_selector
= st_specials
[ST_SPECIAL_NEW
];
918 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
925 CASE (SEND_NEW_ARG
) {
927 pr
->message_argcount
= 1;
928 pr
->message_selector
= st_specials
[ST_SPECIAL_NEW_ARG
];
929 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
938 st_uint primitive_index
;
939 st_method_flags flags
;
941 pr
->message_argcount
= pr_ip
[1];
942 pr
->message_selector
= pr
->literals
[pr_ip
[2]];
943 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
947 pr
->new_method
= st_processor_lookup_method (pr
, st_object_class (pr
->message_receiver
));
949 flags
= st_method_get_flags (pr
->new_method
);
950 if (flags
== ST_METHOD_PRIMITIVE
) {
951 primitive_index
= st_method_get_primitive_index (pr
->new_method
);
953 EXECUTE_PRIMITIVE (pr
, primitive_index
);
954 if (ST_LIKELY (pr
->success
))
958 ACTIVATE_METHOD (pr
);
964 st_oop literal_index
;
965 st_uint primitive_index
;
966 st_method_flags flags
;
968 pr
->message_argcount
= pr_ip
[1];
969 pr
->message_selector
= pr
->literals
[pr_ip
[2]];
970 pr
->message_receiver
= pr
->stack
[pr_sp
- pr
->message_argcount
- 1];
974 literal_index
= st_smi_value (st_arrayed_object_size (ST_METHOD_LITERALS (pr
->method
))) - 1;
976 pr
->new_method
= st_processor_lookup_method (pr
, ST_BEHAVIOR_SUPERCLASS (pr
->literals
[literal_index
]));
978 flags
= st_method_get_flags (pr
->new_method
);
979 if (flags
== ST_METHOD_PRIMITIVE
) {
980 primitive_index
= st_method_get_primitive_index (pr
->new_method
);
982 EXECUTE_PRIMITIVE (pr
, primitive_index
);
983 if (ST_LIKELY (pr
->success
))
987 ACTIVATE_METHOD (pr
);
991 CASE (POP_STACK_TOP
) {
993 (void) ST_STACK_POP (pr
);
999 CASE (DUPLICATE_STACK_TOP
) {
1001 ST_STACK_PUSH (pr
, ST_STACK_PEEK (pr
));
1011 st_uint argcount
= pr_ip
[1];
1016 initial_ip
= pr_ip
- pr
->bytecode
+ 3;
1018 block
= block_context_new (pr
, initial_ip
, argcount
);
1020 ST_STACK_PUSH (pr
, block
);
1025 CASE (RETURN_STACK_TOP
) {
1030 value
= ST_STACK_PEEK (pr
);
1032 if (ST_OBJECT_CLASS (pr
->context
) == st_block_context_class
)
1033 sender
= ST_CONTEXT_PART_SENDER (ST_BLOCK_CONTEXT_HOME (pr
->context
));
1035 sender
= ST_CONTEXT_PART_SENDER (pr
->context
);
1037 st_assert (st_object_is_heap (sender
));
1039 if (sender
== st_nil
) {
1040 ST_STACK_PUSH (pr
, pr
->context
);
1041 ST_STACK_PUSH (pr
, value
);
1042 SEND_SELECTOR (pr
, st_selector_cannotReturn
, 1);
1046 if (ST_OBJECT_CLASS (pr
->context
) == st_method_context_class
)
1047 st_memory_recycle_context (pr
->context
);
1049 ACTIVATE_CONTEXT (pr
, sender
);
1050 ST_STACK_PUSH (pr
, value
);
1055 CASE (BLOCK_RETURN
) {
1060 caller
= ST_BLOCK_CONTEXT_CALLER (pr
->context
);
1061 value
= ST_STACK_PEEK (pr
);
1062 ACTIVATE_CONTEXT (pr
, caller
);
1064 /* push returned value onto caller's stack */
1065 ST_STACK_PUSH (pr
, value
);
1066 st_assert (pr
->context
== caller
);
1073 st_processor_prologue (pr
);
1077 st_processor_clear_caches (st_processor
*pr
)
1079 for (st_uint i
= 0; i
< ST_METHOD_CACHE_SIZE
; i
++) {
1080 pr
->method_cache
[i
].class = st_nil
;
1081 pr
->method_cache
[i
].selector
= st_nil
;
1082 pr
->method_cache
[i
].method
= st_nil
;
1087 st_processor_initialize (st_processor
*pr
)
1092 /* clear contents */
1093 memset (pr
, 0, sizeof (st_processor
));
1094 pr
->context
= st_nil
;
1095 pr
->receiver
= st_nil
;
1096 pr
->method
= st_nil
;
1101 st_processor_clear_caches (pr
);
1103 pr
->message_argcount
= 0;
1104 pr
->message_receiver
= st_smalltalk
;
1105 pr
->message_selector
= st_selector_startupSystem
;
1107 pr
->new_method
= st_processor_lookup_method (pr
, st_object_class (pr
->message_receiver
));
1108 st_assert (st_method_get_flags (pr
->new_method
) == ST_METHOD_NORMAL
);
1110 context
= method_context_new (pr
);
1111 st_processor_set_active_context (pr
, context
);