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 (void)
21 register struct st_cpu
*cpu
= &__cpu
;
27 large
= st_method_get_large_context (cpu
->new_method
);
28 temp_count
= st_method_get_arg_count (cpu
->new_method
) + st_method_get_temp_count (cpu
->new_method
);
30 context
= st_memory_allocate_context (large
);
32 ST_CONTEXT_PART_SENDER (context
) = cpu
->context
;
33 ST_CONTEXT_PART_IP (context
) = st_smi_new (0);
34 ST_CONTEXT_PART_SP (context
) = st_smi_new (temp_count
);
35 ST_METHOD_CONTEXT_RECEIVER (context
) = cpu
->message_receiver
;
36 ST_METHOD_CONTEXT_METHOD (context
) = cpu
->new_method
;
38 /* clear temporaries (and nothing above) */
39 stack
= ST_METHOD_CONTEXT_STACK (context
);
40 for (st_uint i
=0; i
< temp_count
; i
++)
47 block_context_new (st_uint initial_ip
, st_uint argcount
)
49 register struct st_cpu
*cpu
= &__cpu
;
58 context
= st_memory_allocate (ST_SIZE_OOPS (struct st_block_context
) + stack_size
);
59 st_object_initialize_header (context
, ST_BLOCK_CONTEXT_CLASS
);
60 st_object_set_large_context (context
, true);
62 if (ST_OBJECT_CLASS (cpu
->context
) == ST_BLOCK_CONTEXT_CLASS
)
63 home
= ST_BLOCK_CONTEXT_HOME (cpu
->context
);
67 ST_CONTEXT_PART_SENDER (context
) = ST_NIL
;
68 ST_CONTEXT_PART_IP (context
) = st_smi_new (0);
69 ST_CONTEXT_PART_SP (context
) = st_smi_new (0);
71 ST_BLOCK_CONTEXT_INITIALIP (context
) = st_smi_new (initial_ip
);
72 ST_BLOCK_CONTEXT_ARGCOUNT (context
) = st_smi_new (argcount
);
73 ST_BLOCK_CONTEXT_CALLER (context
) = ST_NIL
;
74 ST_BLOCK_CONTEXT_HOME (context
) = home
;
76 /* don't nil stack, not needed */
82 create_actual_message (void)
84 register struct st_cpu
*cpu
= &__cpu
;
89 array
= st_object_new_arrayed (ST_ARRAY_CLASS
, cpu
->message_argcount
);
91 elements
= st_array_elements (array
);
92 for (st_uint i
= 0; i
< cpu
->message_argcount
; i
++)
93 elements
[i
] = cpu
->stack
[cpu
->sp
- cpu
->message_argcount
+ i
];
95 cpu
->sp
-= cpu
->message_argcount
;
96 message
= st_message_new (cpu
->message_selector
, array
);
97 if (st_memory_compaction_occurred ()) {
98 array
= st_memory_remap_reference (array
);
101 ST_STACK_PUSH (cpu
, message
);
103 cpu
->message_selector
= ST_SELECTOR_DOESNOTUNDERSTAND
;
104 cpu
->message_argcount
= 1;
108 lookup_method (st_oop
class)
110 register struct st_cpu
*cpu
= &__cpu
;
112 st_oop parent
= class;
115 while (parent
!= ST_NIL
) {
116 method
= st_dictionary_at (ST_BEHAVIOR_METHOD_DICTIONARY (parent
), cpu
->message_selector
);
117 if (method
!= ST_NIL
)
119 parent
= ST_BEHAVIOR_SUPERCLASS (parent
);
122 if (cpu
->message_selector
== ST_SELECTOR_DOESNOTUNDERSTAND
) {
123 fprintf (stderr
, "panda: error: no method found for #doesNotUnderstand:\n");
127 create_actual_message ();
129 return lookup_method (class);
133 st_cpu_lookup_method (st_oop
class)
135 return lookup_method (class);
139 * Creates a new method context. Parameterised by
140 * @sender, @receiver, @method, and @argcount
142 * Message arguments are copied into the new context's temporary
143 * frame. Receiver and arguments are then popped off the stack.
147 activate_method (void)
149 register struct st_cpu
*cpu
= &__cpu
;
153 context
= method_context_new ();
155 arguments
= ST_METHOD_CONTEXT_STACK (context
);
156 for (st_uint i
= 0; i
< cpu
->message_argcount
; i
++)
157 arguments
[i
] = cpu
->stack
[cpu
->sp
- cpu
->message_argcount
+ i
];
159 cpu
->sp
-= cpu
->message_argcount
+ 1;
161 st_cpu_set_active_context (context
);
165 st_cpu_execute_method (void)
167 register struct st_cpu
*cpu
= &__cpu
;
168 st_uint primitive_index
;
169 st_method_flags flags
;
171 flags
= st_method_get_flags (cpu
->new_method
);
172 if (flags
== ST_METHOD_PRIMITIVE
) {
173 primitive_index
= st_method_get_primitive_index (cpu
->new_method
);
175 st_primitives
[primitive_index
].func (cpu
);
176 if (ST_LIKELY (cpu
->success
))
185 st_cpu_set_active_context (st_oop context
)
187 register struct st_cpu
*cpu
= &__cpu
;
190 /* save executation state of active context */
191 if (ST_UNLIKELY (cpu
->context
!= ST_NIL
)) {
192 ST_CONTEXT_PART_IP (cpu
->context
) = st_smi_new (cpu
->ip
);
193 ST_CONTEXT_PART_SP (cpu
->context
) = st_smi_new (cpu
->sp
);
196 if (ST_OBJECT_CLASS (context
) == ST_BLOCK_CONTEXT_CLASS
) {
197 home
= ST_BLOCK_CONTEXT_HOME (context
);
198 cpu
->method
= ST_METHOD_CONTEXT_METHOD (home
);
199 cpu
->receiver
= ST_METHOD_CONTEXT_RECEIVER (home
);
200 cpu
->literals
= st_array_elements (ST_METHOD_LITERALS (cpu
->method
));
201 cpu
->temps
= ST_METHOD_CONTEXT_STACK (home
);
202 cpu
->stack
= ST_BLOCK_CONTEXT_STACK (context
);
204 cpu
->method
= ST_METHOD_CONTEXT_METHOD (context
);
205 cpu
->receiver
= ST_METHOD_CONTEXT_RECEIVER (context
);
206 cpu
->literals
= st_array_elements (ST_METHOD_LITERALS (cpu
->method
));
207 cpu
->temps
= ST_METHOD_CONTEXT_STACK (context
);
208 cpu
->stack
= ST_METHOD_CONTEXT_STACK (context
);
211 cpu
->context
= context
;
212 cpu
->sp
= st_smi_value (ST_CONTEXT_PART_SP (context
));
213 cpu
->ip
= st_smi_value (ST_CONTEXT_PART_IP (context
));
214 cpu
->bytecode
= st_method_bytecode_bytes (cpu
->method
);
218 st_cpu_prologue (void)
220 if (st_verbose_mode ()) {
221 fprintf (stderr
, "** gc: totalPauseTime: %.6fs\n", st_timespec_to_double_seconds (&memory
->total_pause_time
));
225 #define SEND_SELECTOR(selector, argcount) \
226 cpu->message_argcount = argcount; \
227 cpu->message_receiver = sp[- argcount - 1]; \
228 cpu->message_selector = selector; \
231 #define ACTIVATE_CONTEXT(context) \
232 st_cpu_set_active_context (context);
234 #define SEND_TEMPLATE() \
235 cpu->lookup_class = st_object_class (cpu->message_receiver); \
240 #define HAVE_COMPUTED_GOTO
243 #ifdef HAVE_COMPUTED_GOTO
245 static const st_pointer labels[] = \
248 && PUSH_TEMP, && PUSH_INSTVAR, \
249 && PUSH_LITERAL_CONST, && PUSH_LITERAL_VAR, \
251 && STORE_LITERAL_VAR, && STORE_TEMP, && STORE_INSTVAR, \
252 && STORE_POP_LITERAL_VAR, && STORE_POP_TEMP, && STORE_POP_INSTVAR, \
254 && PUSH_SELF, && PUSH_NIL, && PUSH_TRUE, && PUSH_FALSE, && PUSH_INTEGER, \
256 && RETURN_STACK_TOP, && BLOCK_RETURN, \
257 && POP_STACK_TOP, && DUPLICATE_STACK_TOP, \
259 && PUSH_ACTIVE_CONTEXT, && BLOCK_COPY, \
261 && JUMP_TRUE, && JUMP_FALSE, && JUMP, \
263 && SEND, && SEND_SUPER, \
265 && SEND_PLUS, && SEND_MINUS, \
266 && SEND_LT, && SEND_GT, \
267 && SEND_LE, && SEND_GE, \
268 && SEND_EQ, && SEND_NE, \
269 && SEND_MUL, && SEND_DIV, \
270 && SEND_MOD, && SEND_BITSHIFT, \
271 && SEND_BITAND, && SEND_BITOR, \
274 && SEND_AT, && SEND_AT_PUT, \
275 && SEND_SIZE, && SEND_VALUE, \
276 && SEND_VALUE_ARG, && SEND_IDENTITY_EQ, \
277 && SEND_CLASS, && SEND_NEW, \
287 #ifdef HAVE_COMPUTED_GOTO
290 #define CASE(OP) case OP:
293 #ifdef HAVE_COMPUTED_GOTO
294 #define NEXT() goto *labels[*ip]
296 #define NEXT() goto start
300 install_method_in_cache (void)
302 register struct st_cpu
*cpu
= &__cpu
;
305 index
= ST_METHOD_CACHE_HASH (cpu
->lookup_class
, cpu
->message_selector
) & ST_METHOD_CACHE_MASK
;
306 cpu
->method_cache
[index
].class = cpu
->lookup_class
;
307 cpu
->method_cache
[index
].selector
= cpu
->message_selector
;
308 cpu
->method_cache
[index
].method
= cpu
->new_method
;
312 lookup_method_in_cache (void)
314 register struct st_cpu
*cpu
= &__cpu
;
317 index
= ST_METHOD_CACHE_HASH (cpu
->lookup_class
, cpu
->message_selector
) & ST_METHOD_CACHE_MASK
;
318 if (cpu
->method_cache
[index
].class == cpu
->lookup_class
&&
319 cpu
->method_cache
[index
].selector
== cpu
->message_selector
) {
320 cpu
->new_method
= cpu
->method_cache
[index
].method
;
326 #define STACK_POP(oop) (*--sp)
327 #define STACK_PUSH(oop) (*sp++ = (oop))
328 #define STACK_PEEK(oop) (*(sp-1))
329 #define STACK_UNPOP(count) (sp += count)
330 #define STORE_REGISTERS() \
331 cpu->ip = ip - cpu->bytecode; \
332 cpu->sp = sp - cpu->stack;
333 #define LOAD_REGISTERS() \
334 ip = cpu->bytecode + cpu->ip; \
335 sp = cpu->stack + cpu->sp;
340 register struct st_cpu
*cpu
= &__cpu
;
341 register const st_uchar
*ip
;
342 register st_oop
*sp
= cpu
->stack
;
344 if (setjmp (cpu
->main_loop
))
347 ip
= cpu
->bytecode
+ cpu
->ip
;
353 STACK_PUSH (cpu
->temps
[ip
[1]]);
359 CASE (PUSH_INSTVAR
) {
361 STACK_PUSH (ST_OBJECT_FIELDS (cpu
->receiver
)[ip
[1]]);
367 CASE (STORE_POP_INSTVAR
) {
369 ST_OBJECT_FIELDS (cpu
->receiver
)[ip
[1]] = STACK_POP ();
375 CASE (STORE_INSTVAR
) {
377 ST_OBJECT_FIELDS (cpu
->receiver
)[ip
[1]] = STACK_PEEK ();
383 CASE (STORE_POP_TEMP
) {
385 cpu
->temps
[ip
[1]] = STACK_POP ();
393 cpu
->temps
[ip
[1]] = STACK_PEEK ();
399 CASE (STORE_LITERAL_VAR
) {
401 ST_ASSOCIATION_VALUE (cpu
->literals
[ip
[1]]) = STACK_PEEK ();
407 CASE (STORE_POP_LITERAL_VAR
) {
409 ST_ASSOCIATION_VALUE (cpu
->literals
[ip
[1]]) = STACK_POP ();
417 STACK_PUSH (cpu
->receiver
);
425 STACK_PUSH (ST_TRUE
);
433 STACK_PUSH (ST_FALSE
);
447 CASE (PUSH_INTEGER
) {
449 STACK_PUSH (st_smi_new ((signed char) ip
[1]));
455 CASE (PUSH_ACTIVE_CONTEXT
) {
457 STACK_PUSH (cpu
->context
);
463 CASE (PUSH_LITERAL_CONST
) {
465 STACK_PUSH (cpu
->literals
[ip
[1]]);
471 CASE (PUSH_LITERAL_VAR
) {
475 var
= ST_ASSOCIATION_VALUE (cpu
->literals
[ip
[1]]);
485 if (STACK_PEEK () == ST_TRUE
) {
487 ip
+= *((unsigned short *) (ip
+ 1)) + 3;
488 } else if (ST_LIKELY (STACK_PEEK () == ST_FALSE
)) {
493 SEND_SELECTOR (ST_SELECTOR_MUSTBEBOOLEAN
, 0);
502 if (STACK_PEEK () == ST_FALSE
) {
504 ip
+= *((unsigned short *) (ip
+ 1)) + 3;
505 } else if (ST_LIKELY (STACK_PEEK () == ST_TRUE
)) {
510 SEND_SELECTOR (ST_SELECTOR_MUSTBEBOOLEAN
, 0);
518 ip
+= *((short *) (ip
+ 1)) + 3;
526 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
527 st_object_is_smi (sp
[-2]))) {
530 STACK_PUSH (st_smi_new (st_smi_value (a
) + st_smi_value (b
)));
535 cpu
->message_argcount
= 1;
536 cpu
->message_selector
= ST_SELECTOR_PLUS
;
537 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
538 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
547 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
548 st_object_is_smi (sp
[-2]))) {
551 STACK_PUSH (st_smi_new (st_smi_value (a
) - st_smi_value (b
)));
556 cpu
->message_argcount
= 1;
557 cpu
->message_selector
= ST_SELECTOR_MINUS
;
558 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
559 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
568 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
569 st_object_is_smi (sp
[-2]))) {
572 STACK_PUSH (st_smi_new (st_smi_value (a
) * st_smi_value (b
)));
577 cpu
->message_argcount
= 1;
578 cpu
->message_selector
= ST_SELECTOR_MUL
;
579 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
580 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
590 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
591 st_object_is_smi (sp
[-2]))) {
594 STACK_PUSH (st_smi_new (st_smi_value (a
) % st_smi_value (b
)));
599 cpu
->message_argcount
= 1;
600 cpu
->message_selector
= ST_SELECTOR_MOD
;
601 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
602 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
609 cpu
->message_argcount
= 1;
610 cpu
->message_selector
= ST_SELECTOR_DIV
;
611 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
612 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
617 CASE (SEND_BITSHIFT
) {
621 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
622 st_object_is_smi (sp
[-2]))) {
625 if (st_smi_value (b
) < 0) {
626 STACK_PUSH (st_smi_new (st_smi_value (a
) >> -st_smi_value (b
)));
628 STACK_PUSH (st_smi_new (st_smi_value (a
) << st_smi_value (b
)));
633 cpu
->message_argcount
= 1;
634 cpu
->message_selector
= ST_SELECTOR_BITSHIFT
;
635 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
636 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
645 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
646 st_object_is_smi (sp
[-2]))) {
649 STACK_PUSH (st_smi_new (st_smi_value (a
) & st_smi_value (b
)));
654 cpu
->message_argcount
= 1;
655 cpu
->message_selector
= ST_SELECTOR_BITAND
;
656 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
657 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
666 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
667 st_object_is_smi (sp
[-2]))) {
670 STACK_PUSH (st_smi_new (st_smi_value (a
) | st_smi_value (b
)));
675 cpu
->message_argcount
= 1;
676 cpu
->message_selector
= ST_SELECTOR_BITOR
;
677 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
678 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
688 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
689 st_object_is_smi (sp
[-2]))) {
692 STACK_PUSH (st_smi_new (st_smi_value (a
) ^ st_smi_value (b
)));
697 cpu
->message_argcount
= 1;
698 cpu
->message_selector
= ST_SELECTOR_BITXOR
;
699 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
700 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
709 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
710 st_object_is_smi (sp
[-2]))) {
713 STACK_PUSH (st_smi_value (a
) < st_smi_value (b
) ? ST_TRUE
: ST_FALSE
);
718 cpu
->message_argcount
= 1;
719 cpu
->message_selector
= ST_SELECTOR_LT
;
720 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
721 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
730 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
731 st_object_is_smi (sp
[-2]))) {
734 STACK_PUSH (st_smi_value (a
) > st_smi_value (b
) ? ST_TRUE
: ST_FALSE
);
739 cpu
->message_argcount
= 1;
740 cpu
->message_selector
= ST_SELECTOR_GT
;
741 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
742 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
752 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
753 st_object_is_smi (sp
[-2]))) {
756 STACK_PUSH (st_smi_value (a
) <= st_smi_value (b
) ? ST_TRUE
: ST_FALSE
);
761 cpu
->message_argcount
= 1;
762 cpu
->message_selector
= ST_SELECTOR_LE
;
763 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
764 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
773 if (ST_LIKELY (st_object_is_smi (sp
[-1]) &&
774 st_object_is_smi (sp
[-2]))) {
777 STACK_PUSH (st_smi_value (a
) >= st_smi_value (b
) ? ST_TRUE
: ST_FALSE
);
782 cpu
->message_argcount
= 1;
783 cpu
->message_selector
= ST_SELECTOR_GE
;
784 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
785 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
793 cpu
->message_argcount
= 0;
794 cpu
->message_selector
= ST_SELECTOR_CLASS
;
795 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
796 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
803 cpu
->message_argcount
= 0;
804 cpu
->message_selector
= ST_SELECTOR_SIZE
;
805 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
806 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
817 integer
= STACK_POP ();
818 receiver
= STACK_POP ();
819 if (st_object_is_heap (receiver
) &&
820 st_object_format (receiver
) == ST_FORMAT_ARRAY
) {
822 if (ST_LIKELY (st_object_is_smi (integer
)))
823 index
= st_smi_value (integer
);
824 else if (ST_UNLIKELY (st_object_is_character (integer
))) {
827 } else if (ST_LIKELY (ST_OBJECT_CLASS (integer
) == ST_LARGE_INTEGER_CLASS
))
828 index
= mp_get_int (st_large_integer_value (integer
));
834 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
839 STACK_PUSH (st_array_at (receiver
, index
));
850 cpu
->message_argcount
= 1;
851 cpu
->message_selector
= ST_SELECTOR_AT
;
852 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
853 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
865 value
= STACK_POP ();
866 integer
= STACK_POP ();
867 receiver
= STACK_POP ();
868 if (st_object_is_heap (receiver
) &&
869 st_object_format (receiver
) == ST_FORMAT_ARRAY
) {
871 if (ST_LIKELY (st_object_is_smi (integer
))) {
872 index
= st_smi_value (integer
);
873 } else if (ST_UNLIKELY (st_object_is_character (integer
))) {
876 } else if (ST_LIKELY (ST_OBJECT_CLASS (integer
) == ST_LARGE_INTEGER_CLASS
)) {
877 index
= mp_get_int (st_large_integer_value (integer
));
883 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
888 st_array_at_put (receiver
, index
, value
);
900 cpu
->message_argcount
= 2;
901 cpu
->message_selector
= ST_SELECTOR_ATPUT
;
902 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
903 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
910 cpu
->message_argcount
= 1;
911 cpu
->message_selector
= ST_SELECTOR_EQ
;
912 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
913 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
920 cpu
->message_argcount
= 1;
921 cpu
->message_selector
= ST_SELECTOR_NE
;
922 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
923 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
928 CASE (SEND_IDENTITY_EQ
) {
934 STACK_PUSH ((a
== b
) ? ST_TRUE
: ST_FALSE
);
942 cpu
->message_argcount
= 0;
943 cpu
->message_selector
= ST_SELECTOR_VALUE
;
944 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
945 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
950 CASE (SEND_VALUE_ARG
) {
952 cpu
->message_argcount
= 1;
953 cpu
->message_selector
= ST_SELECTOR_VALUE_ARG
;
954 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
955 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
962 cpu
->message_argcount
= 0;
963 cpu
->message_selector
= ST_SELECTOR_NEW
;
964 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
965 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
970 CASE (SEND_NEW_ARG
) {
972 cpu
->message_argcount
= 1;
973 cpu
->message_selector
= ST_SELECTOR_NEW_ARG
;
974 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
975 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
982 st_uint primitive_index
;
983 st_method_flags flags
;
987 cpu
->message_argcount
= ip
[1];
988 cpu
->message_selector
= cpu
->literals
[ip
[2]];
989 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
990 cpu
->lookup_class
= st_object_class (cpu
->message_receiver
);
995 if (!lookup_method_in_cache ()) {
997 cpu
->new_method
= lookup_method (cpu
->lookup_class
);
999 install_method_in_cache ();
1002 flags
= st_method_get_flags (cpu
->new_method
);
1003 if (flags
== ST_METHOD_PRIMITIVE
) {
1004 primitive_index
= st_method_get_primitive_index (cpu
->new_method
);
1006 cpu
->success
= true;
1008 st_primitives
[primitive_index
].func (cpu
);
1011 if (ST_LIKELY (cpu
->success
))
1015 context
= method_context_new ();
1016 arguments
= ST_METHOD_CONTEXT_STACK (context
);
1017 for (int i
= 0; i
< cpu
->message_argcount
; i
++)
1018 arguments
[i
] = sp
[- cpu
->message_argcount
+ i
];
1019 sp
-= cpu
->message_argcount
+ 1;
1021 ST_CONTEXT_PART_IP (cpu
->context
) = st_smi_new (ip
- cpu
->bytecode
);
1022 ST_CONTEXT_PART_SP (cpu
->context
) = st_smi_new (sp
- cpu
->stack
);
1023 cpu
->context
= context
;
1024 cpu
->method
= ST_METHOD_CONTEXT_METHOD (context
);
1025 cpu
->receiver
= ST_METHOD_CONTEXT_RECEIVER (context
);
1026 cpu
->literals
= st_array_elements (ST_METHOD_LITERALS (cpu
->method
));
1027 cpu
->temps
= ST_METHOD_CONTEXT_STACK (context
);
1028 cpu
->stack
= ST_METHOD_CONTEXT_STACK (context
);
1029 cpu
->sp
= st_smi_value (ST_CONTEXT_PART_SP (context
));
1030 cpu
->ip
= st_smi_value (0);
1031 cpu
->bytecode
= st_method_bytecode_bytes (cpu
->method
);
1034 /* We have to nil these fields here. Its possible that
1035 that the objects they reference may be zapped by the gc.
1036 Another GC invocation may try to remap these fields not knowing that
1037 the references are invalid.
1038 FIXME: move this nilling out of such a critical execution path */
1039 cpu
->message_receiver
= ST_NIL
;
1040 cpu
->message_selector
= ST_NIL
;
1049 cpu
->message_argcount
= ip
[1];
1050 cpu
->message_selector
= cpu
->literals
[ip
[2]];
1051 cpu
->message_receiver
= sp
[- cpu
->message_argcount
- 1];
1053 index
= st_smi_value (st_arrayed_object_size (ST_METHOD_LITERALS (cpu
->method
))) - 1;
1054 cpu
->lookup_class
= ST_BEHAVIOR_SUPERCLASS (cpu
->literals
[index
]);
1061 CASE (POP_STACK_TOP
) {
1063 (void) STACK_POP ();
1069 CASE (DUPLICATE_STACK_TOP
) {
1071 STACK_PUSH (STACK_PEEK ());
1081 st_uint argcount
= ip
[1];
1086 initial_ip
= ip
- cpu
->bytecode
+ 3;
1089 block
= block_context_new (initial_ip
, argcount
);
1097 CASE (RETURN_STACK_TOP
) {
1103 value
= STACK_PEEK ();
1105 if (ST_OBJECT_CLASS (cpu
->context
) == ST_BLOCK_CONTEXT_CLASS
)
1106 sender
= ST_CONTEXT_PART_SENDER (ST_BLOCK_CONTEXT_HOME (cpu
->context
));
1108 sender
= ST_CONTEXT_PART_SENDER (cpu
->context
);
1109 st_memory_recycle_context (cpu
->context
);
1112 if (ST_UNLIKELY (sender
== ST_NIL
)) {
1113 STACK_PUSH (cpu
->context
);
1115 SEND_SELECTOR (ST_SELECTOR_CANNOTRETURN
, 1);
1119 if (ST_OBJECT_CLASS (sender
) == ST_BLOCK_CONTEXT_CLASS
) {
1120 home
= ST_BLOCK_CONTEXT_HOME (sender
);
1121 cpu
->method
= ST_METHOD_CONTEXT_METHOD (home
);
1122 cpu
->receiver
= ST_METHOD_CONTEXT_RECEIVER (home
);
1123 cpu
->literals
= st_array_elements (ST_METHOD_LITERALS (cpu
->method
));
1124 cpu
->temps
= ST_METHOD_CONTEXT_STACK (home
);
1125 cpu
->stack
= ST_BLOCK_CONTEXT_STACK (sender
);
1127 cpu
->method
= ST_METHOD_CONTEXT_METHOD (sender
);
1128 cpu
->receiver
= ST_METHOD_CONTEXT_RECEIVER (sender
);
1129 cpu
->literals
= st_array_elements (ST_METHOD_LITERALS (cpu
->method
));
1130 cpu
->temps
= ST_METHOD_CONTEXT_STACK (sender
);
1131 cpu
->stack
= ST_METHOD_CONTEXT_STACK (sender
);
1134 cpu
->context
= sender
;
1135 cpu
->sp
= st_smi_value (ST_CONTEXT_PART_SP (sender
));
1136 cpu
->ip
= st_smi_value (ST_CONTEXT_PART_IP (sender
));
1137 cpu
->bytecode
= st_method_bytecode_bytes (cpu
->method
);
1145 CASE (BLOCK_RETURN
) {
1151 caller
= ST_BLOCK_CONTEXT_CALLER (cpu
->context
);
1152 value
= STACK_PEEK ();
1154 if (ST_OBJECT_CLASS (caller
) == ST_BLOCK_CONTEXT_CLASS
) {
1155 home
= ST_BLOCK_CONTEXT_HOME (caller
);
1156 cpu
->method
= ST_METHOD_CONTEXT_METHOD (home
);
1157 cpu
->receiver
= ST_METHOD_CONTEXT_RECEIVER (home
);
1158 cpu
->literals
= st_array_elements (ST_METHOD_LITERALS (cpu
->method
));
1159 cpu
->temps
= ST_METHOD_CONTEXT_STACK (home
);
1160 cpu
->stack
= ST_BLOCK_CONTEXT_STACK (caller
);
1162 cpu
->method
= ST_METHOD_CONTEXT_METHOD (caller
);
1163 cpu
->receiver
= ST_METHOD_CONTEXT_RECEIVER (caller
);
1164 cpu
->literals
= st_array_elements (ST_METHOD_LITERALS (cpu
->method
));
1165 cpu
->temps
= ST_METHOD_CONTEXT_STACK (caller
);
1166 cpu
->stack
= ST_METHOD_CONTEXT_STACK (caller
);
1169 cpu
->context
= caller
;
1170 cpu
->sp
= st_smi_value (ST_CONTEXT_PART_SP (caller
));
1171 cpu
->ip
= st_smi_value (ST_CONTEXT_PART_IP (caller
));
1172 cpu
->bytecode
= st_method_bytecode_bytes (cpu
->method
);
1175 /* push returned value onto caller's stack */
1187 st_cpu_clear_caches (void)
1189 memset (__cpu
.method_cache
, 0, ST_METHOD_CACHE_SIZE
* 3 * sizeof (st_oop
));
1193 st_cpu_initialize (void)
1198 /* clear contents */
1199 __cpu
.context
= ST_NIL
;
1200 __cpu
.receiver
= ST_NIL
;
1201 __cpu
.method
= ST_NIL
;
1207 st_cpu_clear_caches ();
1209 __cpu
.message_argcount
= 0;
1210 __cpu
.message_receiver
= ST_SMALLTALK
;
1211 __cpu
.message_selector
= ST_SELECTOR_STARTUPSYSTEM
;
1213 __cpu
.new_method
= lookup_method (st_object_class (__cpu
.message_receiver
));
1214 st_assert (st_method_get_flags (__cpu
.new_method
) == ST_METHOD_NORMAL
);
1216 context
= method_context_new ();
1217 st_cpu_set_active_context (context
);