// Allocates memory (parameter(), literal(), emit_epilog, emit_with_literal) void quotation_jit::iterate_quotation() { bool stack_frame = stack_frame_p(); set_position(0); if (stack_frame) { emit(parent->special_objects[JIT_SAFEPOINT]); emit(parent->special_objects[JIT_PROLOG]); } cell length = array_capacity(elements.untagged()); bool tail_call = false; for (cell i = 0; i < length; i++) { set_position(i); data_root<object> obj(nth(i), parent); switch (obj.type()) { case WORD_TYPE: // Sub-primitives if (to_boolean(obj.as<word>()->subprimitive)) { tail_call = emit_subprimitive(obj.value(), // word i == length - 1, // tail_call_p stack_frame); // stack_frame_p } // Everything else else if (i == length - 1) { emit_epilog(stack_frame); tail_call = true; word_jump(obj.value()); } else word_call(obj.value()); break; case WRAPPER_TYPE: push(obj.as<wrapper>()->object); break; case BYTE_ARRAY_TYPE: // Primitive calls if (primitive_call_p(i, length)) { // On x86-64 and PowerPC, the VM pointer is stored in a register; // on other platforms, the RT_VM relocation is used and it needs // an offset parameter #ifdef FACTOR_X86 parameter(tag_fixnum(0)); #endif parameter(obj.value()); parameter(false_object); #ifdef FACTOR_PPC_TOC parameter(obj.value()); parameter(false_object); #endif emit(parent->special_objects[JIT_PRIMITIVE]); i++; } else push(obj.value()); break; case QUOTATION_TYPE: // 'if' preceded by two literal quotations (this is why if and ? are // mutually recursive in the library, but both still work) if (fast_if_p(i, length)) { emit_epilog(stack_frame); tail_call = true; emit_quotation(nth(i)); emit_quotation(nth(i + 1)); emit(parent->special_objects[JIT_IF]); i += 2; } // dip else if (fast_dip_p(i, length)) { emit_quotation(obj.value()); emit(parent->special_objects[JIT_DIP]); i++; } // 2dip else if (fast_2dip_p(i, length)) { emit_quotation(obj.value()); emit(parent->special_objects[JIT_2DIP]); i++; } // 3dip else if (fast_3dip_p(i, length)) { emit_quotation(obj.value()); emit(parent->special_objects[JIT_3DIP]); i++; } else push(obj.value()); break; case ARRAY_TYPE: // Method dispatch if (mega_lookup_p(i, length)) { tail_call = true; emit_mega_cache_lookup(nth(i), untag_fixnum(nth(i + 1)), nth(i + 2)); i += 3; } // Non-optimizing compiler ignores declarations else if (declare_p(i, length)) i++; else push(obj.value()); break; default: push(obj.value()); break; } } if (!tail_call) { set_position(length); emit_epilog(stack_frame); emit(parent->special_objects[JIT_RETURN]); } }
/* Allocates memory (parameter(), literal(), emit_epilog, emit_with_literal)*/ void quotation_jit::iterate_quotation() { bool no_non_safepoint_words = no_non_safepoint_words_p(); set_position(0); if (no_non_safepoint_words) { emit(parent->special_objects[JIT_SAFEPOINT]); emit(parent->special_objects[JIT_PROLOG]); } cell length = array_capacity(elements.untagged()); bool tail_call = false; for (cell i = 0; i < length; i++) { set_position(i); data_root<object> obj(array_nth(elements.untagged(), i), parent); switch (obj.type()) { case WORD_TYPE: /* Sub-primitives */ if (to_boolean(obj.as<word>()->subprimitive)) { tail_call = emit_subprimitive(obj.value(), /* word */ i == length - 1, /* tail_call_p */ no_non_safepoint_words); /* stack_frame_p */ } /* Everything else */ else if (i == length - 1) { emit_epilog(no_non_safepoint_words); tail_call = true; word_jump(obj.value()); } else word_call(obj.value()); break; case WRAPPER_TYPE: push(obj.as<wrapper>()->object); break; case BYTE_ARRAY_TYPE: /* Primitive calls */ if (primitive_call_p(i, length)) { /* On x86-64 and PowerPC, the VM pointer is stored in a register; on other platforms, the RT_VM relocation is used and it needs an offset parameter */ #ifdef FACTOR_X86 parameter(tag_fixnum(0)); #endif parameter(obj.value()); parameter(false_object); #ifdef FACTOR_PPC_TOC parameter(obj.value()); parameter(false_object); #endif emit(parent->special_objects[JIT_PRIMITIVE]); i++; } else push(obj.value()); break; case QUOTATION_TYPE: /* 'if' preceded by two literal quotations (this is why if and ? are mutually recursive in the library, but both still work) */ if (fast_if_p(i, length)) { emit_epilog(no_non_safepoint_words); tail_call = true; emit_quotation(array_nth(elements.untagged(), i)); emit_quotation(array_nth(elements.untagged(), i + 1)); emit(parent->special_objects[JIT_IF]); i += 2; } /* dip */ else if (fast_dip_p(i, length)) { emit_quotation(obj.value()); emit(parent->special_objects[JIT_DIP]); i++; } /* 2dip */ else if (fast_2dip_p(i, length)) { emit_quotation(obj.value()); emit(parent->special_objects[JIT_2DIP]); i++; } /* 3dip */ else if (fast_3dip_p(i, length)) { emit_quotation(obj.value()); emit(parent->special_objects[JIT_3DIP]); i++; } else push(obj.value()); break; case ARRAY_TYPE: /* Method dispatch */ if (mega_lookup_p(i, length)) { fixnum index = untag_fixnum(array_nth(elements.untagged(), i + 1)); /* Load the object from the datastack, then remove our stack frame. */ emit_with_literal(parent->special_objects[PIC_LOAD], tag_fixnum(-index * sizeof(cell))); emit_epilog(no_non_safepoint_words); tail_call = true; emit_mega_cache_lookup(array_nth(elements.untagged(), i), index, array_nth(elements.untagged(), i + 2)); i += 3; } /* Non-optimizing compiler ignores declarations */ else if (declare_p(i, length)) i++; else push(obj.value()); break; default: push(obj.value()); break; } } if (!tail_call) { set_position(length); emit_epilog(no_non_safepoint_words); emit(parent->special_objects[JIT_RETURN]); } }