2 * vim: set ts=2 sw=2 tw=99 et:
3 * =============================================================================
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
36 #include "../sp_vm_engine.h"
37 #include "../engine2.h"
38 #include "../BaseRuntime.h"
39 #include "../sp_vm_basecontext.h"
40 #include "watchdog_timer.h"
41 #include "interpreter.h"
43 using namespace Knight;
45 #if defined USE_UNGEN_OPCODES
46 #include "ungen_opcodes.h"
52 KeCodeCache *g_pCodeCache = NULL;
53 ISourcePawnEngine *engine = &g_engine1;
55 static inline uint8_t *
56 LinkCode(AssemblerX86 &masm)
58 if (masm.outOfMemory())
61 void *code = Knight::KE_AllocCode(g_pCodeCache, masm.length());
65 masm.emitToExecutableMemory(code);
66 return reinterpret_cast<uint8_t *>(code);
69 static inline ConditionCode
70 OpToCondition(OPCODE op)
97 struct array_creation_t
99 const cell_t *dim_list; /* Dimension sizes */
100 cell_t dim_count; /* Number of dimensions */
101 cell_t *data_offs; /* Current offset AFTER the indirection vectors (data) */
102 cell_t *base; /* array base */
106 GenerateInnerArrayIndirectionVectors(array_creation_t *ar, int dim, cell_t cur_offs)
108 cell_t write_offs = cur_offs;
109 cell_t *data_offs = ar->data_offs;
111 cur_offs += ar->dim_list[dim];
113 // Dimension n-x where x > 2 will have sub-vectors.
114 // Otherwise, we just need to reference the data section.
115 if (ar->dim_count > 2 && dim < ar->dim_count - 2) {
116 // For each index at this dimension, write offstes to our sub-vectors.
117 // After we write one sub-vector, we generate its sub-vectors recursively.
118 // At the end, we're given the next offset we can use.
119 for (int i = 0; i < ar->dim_list[dim]; i++) {
120 ar->base[write_offs] = (cur_offs - write_offs) * sizeof(cell_t);
122 cur_offs = GenerateInnerArrayIndirectionVectors(ar, dim + 1, cur_offs);
125 // In this section, there are no sub-vectors, we need to write offsets
126 // to the data. This is separate so the data stays in one big chunk.
127 // The data offset will increment by the size of the last dimension,
128 // because that is where the data is finally computed as.
129 for (int i = 0; i < ar->dim_list[dim]; i++) {
130 ar->base[write_offs] = (*data_offs - write_offs) * sizeof(cell_t);
132 *data_offs = *data_offs + ar->dim_list[dim + 1];
140 calc_indirection(const array_creation_t *ar, cell_t dim)
142 cell_t size = ar->dim_list[dim];
143 if (dim < ar->dim_count - 2)
144 size += ar->dim_list[dim] * calc_indirection(ar, dim + 1);
149 GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], cell_t _dimcount, bool autozero)
154 /* Reverse the dimensions */
155 cell_t dim_list[sDIMEN_MAX];
157 for (int i = _dimcount - 1; i >= 0; i--)
158 dim_list[cur_dim++] = dims[i];
161 ar.dim_list = dim_list;
162 ar.dim_count = _dimcount;
163 ar.data_offs = &data_offs;
165 data_offs = calc_indirection(&ar, 0);
166 GenerateInnerArrayIndirectionVectors(&ar, 0, 0);
171 GenerateFullArray(BaseRuntime *rt, uint32_t argc, cell_t *argv, int autozero)
173 sp_context_t *ctx = rt->GetBaseContext()->GetCtx();
175 // Calculate how many cells are needed.
177 return SP_ERROR_ARRAY_TOO_BIG;
179 uint32_t cells = argv[0];
181 for (uint32_t dim = 1; dim < argc; dim++) {
182 cell_t dimsize = argv[dim];
184 return SP_ERROR_ARRAY_TOO_BIG;
185 if (!ke::IsUint32MultiplySafe(cells, dimsize))
186 return SP_ERROR_ARRAY_TOO_BIG;
187 cells *= uint32_t(dimsize);
188 if (!ke::IsUint32AddSafe(cells, dimsize))
189 return SP_ERROR_ARRAY_TOO_BIG;
190 cells += uint32_t(dimsize);
193 if (!ke::IsUint32MultiplySafe(cells, 4))
194 return SP_ERROR_ARRAY_TOO_BIG;
196 uint32_t bytes = cells * 4;
197 if (!ke::IsUint32AddSafe(ctx->hp, bytes))
198 return SP_ERROR_ARRAY_TOO_BIG;
200 uint32_t new_hp = ctx->hp + bytes;
201 cell_t *dat_hp = reinterpret_cast<cell_t *>(rt->plugin()->memory + new_hp);
203 // argv, coincidentally, is STK.
204 if (dat_hp >= argv - STACK_MARGIN)
205 return SP_ERROR_HEAPLOW;
207 if (int err = PushTracker(rt->GetBaseContext()->GetCtx(), bytes))
210 cell_t *base = reinterpret_cast<cell_t *>(rt->plugin()->memory + ctx->hp);
211 cell_t offs = GenerateArrayIndirectionVectors(base, argv, argc, !!autozero);
212 assert(size_t(offs) == cells);
214 argv[argc - 1] = ctx->hp;
216 return SP_ERROR_NONE;
221 GetFunctionName(const sp_plugin_t *plugin, uint32_t offs)
223 if (!plugin->debug.unpacked) {
225 sp_fdbg_symbol_t *sym;
226 sp_fdbg_arraydim_t *arr;
227 uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
229 max = plugin->debug.syms_num;
230 for (iter = 0; iter < max; iter++) {
231 sym = (sp_fdbg_symbol_t *)cursor;
233 if (sym->ident == SP_SYM_FUNCTION && sym->codestart <= offs && sym->codeend > offs)
234 return plugin->debug.stringbase + sym->name;
236 if (sym->dimcount > 0) {
237 cursor += sizeof(sp_fdbg_symbol_t);
238 arr = (sp_fdbg_arraydim_t *)cursor;
239 cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
243 cursor += sizeof(sp_fdbg_symbol_t);
247 sp_u_fdbg_symbol_t *sym;
248 sp_u_fdbg_arraydim_t *arr;
249 uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
251 max = plugin->debug.syms_num;
252 for (iter = 0; iter < max; iter++) {
253 sym = (sp_u_fdbg_symbol_t *)cursor;
255 if (sym->ident == SP_SYM_FUNCTION && sym->codestart <= offs && sym->codeend > offs)
256 return plugin->debug.stringbase + sym->name;
258 if (sym->dimcount > 0) {
259 cursor += sizeof(sp_u_fdbg_symbol_t);
260 arr = (sp_u_fdbg_arraydim_t *)cursor;
261 cursor += sizeof(sp_u_fdbg_arraydim_t) * sym->dimcount;
265 cursor += sizeof(sp_u_fdbg_symbol_t);
274 CompileFromThunk(BaseRuntime *runtime, cell_t pcode_offs, void **addrp, char *pc)
276 // If the watchdog timer has declared a timeout, we must process it now,
277 // and possibly refuse to compile, since otherwise we will compile a
278 // function that is not patched for timeouts.
279 if (!g_WatchdogTimer.HandleInterrupt())
280 return SP_ERROR_TIMEOUT;
282 JitFunction *fn = runtime->GetJittedFunctionByOffset(pcode_offs);
285 fn = g_Jit.CompileFunction(runtime, pcode_offs, &err);
291 g_engine1.GetDebugHook()->OnDebugSpew(
292 "Patching thunk to %s::%s\n",
293 runtime->plugin()->name,
294 GetFunctionName(runtime->plugin(), pcode_offs));
297 *addrp = fn->GetEntryAddress();
299 /* Right now, we always keep the code RWE */
300 *(intptr_t *)(pc - 4) = intptr_t(fn->GetEntryAddress()) - intptr_t(pc);
301 return SP_ERROR_NONE;
304 Compiler::Compiler(BaseRuntime *rt, cell_t pcode_offs)
306 plugin_(rt->plugin()),
307 error_(SP_ERROR_NONE),
308 pcode_start_(pcode_offs),
309 code_start_(reinterpret_cast<cell_t *>(plugin_->pcode + pcode_start_)),
311 code_end_(reinterpret_cast<cell_t *>(plugin_->pcode + plugin_->pcode_size))
313 size_t nmaxops = plugin_->pcode_size / sizeof(cell_t) + 1;
314 jump_map_ = new Label[nmaxops];
317 Compiler::~Compiler()
323 Compiler::emit(int *errp)
325 if (cip_ >= code_end_ || *cip_ != OP_PROC) {
326 *errp = SP_ERROR_INVALID_INSTRUCTION;
331 g_engine1.GetDebugHook()->OnDebugSpew(
332 "Compiling function %s::%s\n",
334 GetFunctionName(plugin_, pcode_start_));
338 SpewOpcode(plugin_, code_start_, cip_);
341 cell_t *codeseg = reinterpret_cast<cell_t *>(plugin_->pcode);
344 if (!emitOp(OP_PROC)) {
345 *errp = (error_ == SP_ERROR_NONE) ? SP_ERROR_OUT_OF_MEMORY : error_;
349 while (cip_ < code_end_) {
350 // If we reach the end of this function, or the beginning of a new
351 // procedure, then stop.
352 if (*cip_ == OP_PROC || *cip_ == OP_ENDPROC)
356 SpewOpcode(plugin_, code_start_, cip_);
359 // We assume every instruction is a jump target, so before emitting
360 // an opcode, we bind its corresponding label.
361 __ bind(&jump_map_[cip_ - codeseg]);
363 OPCODE op = (OPCODE)readCell();
364 if (!emitOp(op) || error_ != SP_ERROR_NONE) {
365 *errp = (error_ == SP_ERROR_NONE) ? SP_ERROR_OUT_OF_MEMORY : error_;
373 uint8_t *code = LinkCode(masm);
375 *errp = SP_ERROR_OUT_OF_MEMORY;
379 LoopEdge *edges = new LoopEdge[backward_jumps_.length()];
380 for (size_t i = 0; i < backward_jumps_.length(); i++) {
381 edges[i].offset = backward_jumps_[i];
382 edges[i].disp32 = *reinterpret_cast<int32_t *>(code + edges[i].offset - 4);
385 return new JitFunction(code, pcode_start_, edges, backward_jumps_.length());
389 Compiler::emitOp(OPCODE op)
406 cell_t offset = readCell();
407 __ movl(Operand(dat, offset), 0);
413 cell_t offset = readCell();
414 __ movl(Operand(frm, offset), 0);
421 Register reg = (op == OP_PUSH_PRI) ? pri : alt;
422 __ movl(Operand(stk, -4), reg);
434 if (op >= OP_PUSH2_C)
435 n = ((op - OP_PUSH2_C) / 4) + 2;
439 cell_t val = readCell();
440 __ movl(Operand(stk, -(4 * i)), val);
453 if (op >= OP_PUSH2_ADR)
454 n = ((op - OP_PUSH2_ADR) / 4) + 2;
458 // We temporarily relocate FRM to be a local address instead of an
462 cell_t offset = readCell();
463 __ lea(tmp, Operand(frm, offset));
464 __ movl(Operand(stk, -(4 * i)), tmp);
478 if (op >= OP_PUSH2_S)
479 n = ((op - OP_PUSH2_S) / 4) + 2;
483 cell_t offset = readCell();
484 __ movl(tmp, Operand(frm, offset));
485 __ movl(Operand(stk, -(4 * i)), tmp);
499 n = ((op - OP_PUSH2) / 4) + 2;
503 cell_t offset = readCell();
504 __ movl(tmp, Operand(dat, offset));
505 __ movl(Operand(stk, -(4 * i)), tmp);
534 // Push the old frame onto the stack.
535 __ movl(tmp, Operand(frmAddr()));
536 __ movl(Operand(stk, -4), tmp);
537 __ subl(stk, 8); // extra unused slot for non-existant CIP
539 // Get and store the new frame.
543 __ movl(Operand(frmAddr()), tmp);
545 // Align the stack to 16-bytes (each call adds 4 bytes).
551 cell_t val = readCell();
575 Register reg = (op == OP_SHL_C_PRI) ? pri : alt;
576 cell_t val = readCell();
584 Register reg = (op == OP_SHR_C_PRI) ? pri : alt;
585 cell_t val = readCell();
622 cell_t val = readCell();
629 cell_t val = readCell();
630 __ imull(pri, pri, val);
641 ConditionCode cc = OpToCondition(op);
651 Register reg = (op == OP_EQ_C_PRI) ? pri : alt;
652 cell_t val = readCell();
655 __ set(equal, r8_al);
662 Register reg = (OP_INC_PRI) ? pri : alt;
670 Register base = (op == OP_INC) ? dat : frm;
671 cell_t offset = readCell();
672 __ addl(Operand(base, offset), 1);
677 __ addl(Operand(dat, pri, NoScale), 1);
683 Register reg = (op == OP_DEC_PRI) ? pri : alt;
691 Register base = (op == OP_DEC) ? dat : frm;
692 cell_t offset = readCell();
693 __ subl(Operand(base, offset), 1);
698 __ subl(Operand(dat, pri, NoScale), 1);
704 Register reg = (op == OP_LOAD_PRI) ? pri : alt;
705 cell_t offset = readCell();
706 __ movl(reg, Operand(dat, offset));
712 cell_t offs1 = readCell();
713 cell_t offs2 = readCell();
714 __ movl(pri, Operand(dat, offs1));
715 __ movl(alt, Operand(dat, offs2));
722 Register reg = (op == OP_LOAD_S_PRI) ? pri : alt;
723 cell_t offset = readCell();
724 __ movl(reg, Operand(frm, offset));
730 cell_t offs1 = readCell();
731 cell_t offs2 = readCell();
732 __ movl(pri, Operand(frm, offs1));
733 __ movl(alt, Operand(frm, offs2));
740 Register reg = (op == OP_LREF_S_PRI) ? pri : alt;
741 cell_t offset = readCell();
742 __ movl(reg, Operand(frm, offset));
743 __ movl(reg, Operand(dat, reg, NoScale));
750 Register reg = (op == OP_CONST_PRI) ? pri : alt;
751 cell_t val = readCell();
759 Register reg = (op == OP_ADDR_PRI) ? pri : alt;
760 cell_t offset = readCell();
761 __ movl(reg, Operand(frmAddr()));
762 __ addl(reg, offset);
769 Register reg = (op == OP_STOR_PRI) ? pri : alt;
770 cell_t offset = readCell();
771 __ movl(Operand(dat, offset), reg);
778 Register reg = (op == OP_STOR_S_PRI) ? pri : alt;
779 cell_t offset = readCell();
780 __ movl(Operand(frm, offset), reg);
785 __ lea(pri, Operand(alt, pri, ScaleFour));
791 Register reg = (op == OP_SREF_S_PRI) ? pri : alt;
792 cell_t offset = readCell();
793 __ movl(tmp, Operand(frm, offset));
794 __ movl(Operand(dat, tmp, NoScale), reg);
801 Register reg = (op == OP_POP_PRI) ? pri : alt;
802 __ movl(reg, Operand(stk, 0));
810 Register reg = (op == OP_SWAP_PRI) ? pri : alt;
811 __ movl(tmp, Operand(stk, 0));
812 __ movl(Operand(stk, 0), reg);
818 __ lea(pri, Operand(alt, pri, ScaleFour));
819 __ movl(pri, Operand(dat, pri, NoScale));
824 cell_t val = readCell();
825 if (val >= 0 && val <= 3) {
826 __ lea(pri, Operand(alt, pri, Scale(val)));
831 emitCheckAddress(pri);
832 __ movl(pri, Operand(dat, pri, NoScale));
839 Register base = (op == OP_CONST) ? dat : frm;
840 cell_t offset = readCell();
841 cell_t val = readCell();
842 __ movl(Operand(base, offset), val);
847 emitCheckAddress(pri);
848 __ movl(pri, Operand(dat, pri, NoScale));
852 emitCheckAddress(alt);
853 __ movl(Operand(dat, alt, NoScale), pri);
859 Register dividend = (op == OP_SDIV) ? pri : alt;
860 Register divisor = (op == OP_SDIV) ? alt : pri;
862 // Guard against divide-by-zero.
863 __ testl(divisor, divisor);
864 __ j(zero, &error_divide_by_zero_);
866 // A more subtle case; -INT_MIN / -1 yields an overflow exception.
868 __ cmpl(divisor, -1);
869 __ j(not_equal, &ok);
870 __ cmpl(dividend, 0x80000000);
871 __ j(equal, &error_integer_overflow_);
874 // Now we can actually perform the divide.
875 __ movl(tmp, divisor);
877 __ movl(edx, dividend);
879 __ movl(eax, dividend);
887 cell_t val = readCell();
888 emitCheckAddress(pri);
889 __ movl(pri, Operand(dat, pri, NoScale));
893 __ andl(pri, 0xffff);
899 cell_t val = readCell();
900 emitCheckAddress(alt);
902 __ movb(Operand(dat, alt, NoScale), pri);
904 __ movw(Operand(dat, alt, NoScale), pri);
906 __ movl(Operand(dat, alt, NoScale), pri);
912 // Restore the old frame pointer.
913 __ movl(frm, Operand(stk, 4)); // get the old frm
914 __ addl(stk, 8); // pop stack
915 __ movl(Operand(frmAddr()), frm); // store back old frm
916 __ addl(frm, dat); // relocate
918 // Remove parameters.
919 __ movl(tmp, Operand(stk, 0));
920 __ lea(stk, Operand(stk, tmp, ScaleFour, 4));
928 cell_t val = readCell();
929 unsigned dwords = val / 4;
930 unsigned bytes = val % 4;
935 // Note: set edi first, since we need esi.
936 __ lea(edi, Operand(dat, alt, NoScale));
937 __ lea(esi, Operand(dat, pri, NoScale));
939 __ movl(ecx, dwords);
953 // eax/pri is used implicitly.
954 unsigned dwords = readCell() / 4;
956 __ lea(edi, Operand(dat, alt, NoScale));
957 __ movl(ecx, dwords);
964 case OP_STRADJUST_PRI:
970 __ movl(pri, Operand(stk, 0));
971 __ andl(pri, 0x7fffffff);
976 if (MacroAssemblerX86::Features().sse2) {
977 __ cvtsi2ss(xmm0, Operand(edi, 0));
980 __ fild32(Operand(edi, 0));
982 __ fstp32(Operand(esp, 0));
992 if (MacroAssemblerX86::Features().sse2) {
993 __ movss(xmm0, Operand(stk, 0));
994 if (op == OP_FLOATADD)
995 __ addss(xmm0, Operand(stk, 4));
996 else if (op == OP_FLOATSUB)
997 __ subss(xmm0, Operand(stk, 4));
998 else if (op == OP_FLOATMUL)
999 __ mulss(xmm0, Operand(stk, 4));
1000 else if (op == OP_FLOATDIV)
1001 __ divss(xmm0, Operand(stk, 4));
1005 __ fld32(Operand(stk, 0));
1007 if (op == OP_FLOATADD)
1008 __ fadd32(Operand(stk, 4));
1009 else if (op == OP_FLOATSUB)
1010 __ fsub32(Operand(stk, 4));
1011 else if (op == OP_FLOATMUL)
1012 __ fmul32(Operand(stk, 4));
1013 else if (op == OP_FLOATDIV)
1014 __ fdiv32(Operand(stk, 4));
1016 __ fstp32(Operand(esp, 0));
1022 case OP_RND_TO_NEAREST:
1024 if (MacroAssemblerX86::Features().sse) {
1025 // Assume no one is touching MXCSR.
1026 __ cvtss2si(pri, Operand(stk, 0));
1028 static float kRoundToNearest = 0.5f;
1029 // From http://wurstcaptures.untergrund.net/assembler_tricks.html#fastfloorf
1030 __ fld32(Operand(stk, 0));
1031 __ fadd32(st0, st0);
1032 __ fadd32(Operand(ExternalAddress(&kRoundToNearest)));
1034 __ fistp32(Operand(esp, 0));
1042 case OP_RND_TO_CEIL:
1044 static float kRoundToCeil = -0.5f;
1045 // From http://wurstcaptures.untergrund.net/assembler_tricks.html#fastfloorf
1046 __ fld32(Operand(stk, 0));
1047 __ fadd32(st0, st0);
1048 __ fsubr32(Operand(ExternalAddress(&kRoundToCeil)));
1050 __ fistp32(Operand(esp, 0));
1058 case OP_RND_TO_ZERO:
1059 if (MacroAssemblerX86::Features().sse) {
1060 __ cvttss2si(pri, Operand(stk, 0));
1062 __ fld32(Operand(stk, 0));
1064 __ fstcw(Operand(esp, 4));
1065 __ movl(Operand(esp, 0), 0xfff);
1066 __ fldcw(Operand(esp, 0));
1067 __ fistp32(Operand(esp, 0));
1069 __ fldcw(Operand(esp, 0));
1075 case OP_RND_TO_FLOOR:
1076 __ fld32(Operand(stk, 0));
1078 __ fstcw(Operand(esp, 4));
1079 __ movl(Operand(esp, 0), 0x7ff);
1080 __ fldcw(Operand(esp, 0));
1081 __ fistp32(Operand(esp, 0));
1083 __ fldcw(Operand(esp, 0));
1088 // This is the old float cmp, which returns ordered results. In newly
1089 // compiled code it should not be used or generated.
1091 // Note that the checks here are inverted: the test is |rhs OP lhs|.
1095 if (MacroAssemblerX86::Features().sse) {
1096 __ movss(xmm0, Operand(stk, 4));
1097 __ ucomiss(Operand(stk, 0), xmm0);
1099 __ fld32(Operand(stk, 0));
1100 __ fld32(Operand(stk, 4));
1119 emitFloatCmp(above);
1123 emitFloatCmp(above_equal);
1127 emitFloatCmp(below_equal);
1131 emitFloatCmp(below);
1135 emitFloatCmp(equal);
1139 emitFloatCmp(not_equal);
1144 if (MacroAssemblerX86::Features().sse) {
1145 __ xorps(xmm0, xmm0);
1146 __ ucomiss(Operand(stk, 0), xmm0);
1148 __ fld32(Operand(stk, 0));
1154 // See emitFloatCmp() - this is a shorter version.
1157 __ j(parity, &done);
1158 __ set(zero, r8_al);
1167 cell_t amount = readCell();
1168 __ addl(stk, amount);
1171 // Check if the stack went beyond the stack top - usually a compiler error.
1172 __ cmpl(stk, intptr_t(plugin_->memory + plugin_->mem_size));
1173 __ j(not_below, &error_stack_min_);
1175 // Check if the stack is going to collide with the heap.
1176 __ movl(tmp, Operand(hpAddr()));
1177 __ lea(tmp, Operand(dat, ecx, NoScale, STACK_MARGIN));
1179 __ j(below, &error_stack_low_);
1186 cell_t amount = readCell();
1187 __ movl(alt, Operand(hpAddr()));
1188 __ addl(Operand(hpAddr()), amount);
1191 __ cmpl(Operand(hpAddr()), plugin_->data_size);
1192 __ j(below, &error_heap_min_);
1194 __ movl(tmp, Operand(hpAddr()));
1195 __ lea(tmp, Operand(dat, ecx, NoScale, STACK_MARGIN));
1197 __ j(above, &error_heap_low_);
1204 Label *target = labelAt(readCell());
1207 if (target->bound()) {
1209 backward_jumps_.append(masm.pc());
1219 ConditionCode cc = (op == OP_JZER) ? zero : not_zero;
1220 Label *target = labelAt(readCell());
1224 if (target->bound()) {
1226 backward_jumps_.append(masm.pc());
1240 Label *target = labelAt(readCell());
1243 ConditionCode cc = OpToCondition(op);
1245 if (target->bound()) {
1247 backward_jumps_.append(masm.pc());
1254 case OP_TRACKER_PUSH_C:
1256 cell_t amount = readCell();
1261 __ push(amount * 4);
1262 __ push(intptr_t(rt_->GetBaseContext()->GetCtx()));
1263 __ call(ExternalAddress((void *)PushTracker));
1266 __ j(not_zero, &extern_error_);
1273 case OP_TRACKER_POP_SETHEAP:
1279 // Get the context pointer and call the sanity checker.
1280 __ push(intptr_t(rt_));
1281 __ call(ExternalAddress((void *)PopTrackerAndSetHeap));
1284 __ j(not_zero, &extern_error_);
1293 cell_t cip = uintptr_t(cip_ - 1) - uintptr_t(plugin_->pcode);
1294 __ movl(Operand(cipAddr()), cip);
1300 __ movl(tmp, intptr_t(rt_->GetBaseContext()->GetCtx()));
1301 __ movl(Operand(tmp, offsetof(sp_context_t, rval)), pri);
1302 __ movl(pri, readCell());
1303 __ jmp(&extern_error_);
1308 cell_t value = readCell();
1309 __ cmpl(eax, value);
1310 __ j(above, &error_bounds_);
1316 emitGenArray(op == OP_GENARRAY_Z);
1326 if (!emitNativeCall(op))
1337 size_t ncases = readCell();
1339 // Two cells per case, and one extra cell for the default address.
1340 cip_ += (ncases * 2) + 1;
1348 error_ = SP_ERROR_INVALID_INSTRUCTION;
1356 Compiler::labelAt(size_t offset)
1358 if (offset % 4 != 0 ||
1359 offset > plugin_->pcode_size ||
1360 offset <= pcode_start_)
1362 // If the jump target is misaligned, or out of pcode bounds, or is an
1363 // address out of the function bounds, we abort. Unfortunately we can't
1364 // test beyond the end of the function since we don't have a precursor
1366 error_ = SP_ERROR_INSTRUCTION_PARAM;
1370 return &jump_map_[offset / sizeof(cell_t)];
1374 Compiler::emitCheckAddress(Register reg)
1376 // Check if we're in memory bounds.
1377 __ cmpl(reg, plugin_->mem_size);
1378 __ j(not_below, &error_memaccess_);
1380 // Check if we're in the invalid region between hp and sp.
1382 __ cmpl(reg, Operand(hpAddr()));
1384 __ lea(tmp, Operand(dat, reg, NoScale));
1386 __ j(below, &error_memaccess_);
1391 Compiler::emitGenArray(bool autozero)
1393 cell_t val = readCell();
1396 // flat array; we can generate this without indirection tables.
1397 // Note that we can overwrite ALT because technically STACK should be destroying ALT
1398 __ movl(alt, Operand(hpAddr()));
1399 __ movl(tmp, Operand(stk, 0));
1400 __ movl(Operand(stk, 0), alt); // store base of the array into the stack.
1401 __ lea(alt, Operand(alt, tmp, ScaleFour));
1402 __ movl(Operand(hpAddr()), alt);
1405 __ j(not_below, &error_heap_low_);
1409 __ push(intptr_t(rt_->GetBaseContext()->GetCtx()));
1410 __ call(ExternalAddress((void *)PushTracker));
1415 __ j(not_zero, &extern_error_);
1418 // Note - tmp is ecx and still intact.
1422 __ movl(edi, Operand(stk, 0));
1432 // int GenerateArray(sp_plugin_t, vars[], uint32_t, cell_t *, int, unsigned *);
1433 __ push(autozero ? 1 : 0);
1436 __ push(intptr_t(rt_));
1437 __ call(ExternalAddress((void *)GenerateFullArray));
1438 __ addl(esp, 4 * sizeof(void *));
1440 // restore pri to tmp
1444 __ j(not_zero, &extern_error_);
1446 // Move tmp back to pri, remove pushed args.
1448 __ addl(stk, (val - 1) * 4);
1453 Compiler::emitCall()
1455 cell_t offset = readCell();
1457 // If this offset looks crappy, i.e. not aligned or out of bounds, we just
1459 if (offset % 4 != 0 || uint32_t(offset) >= plugin_->pcode_size) {
1460 error_ = SP_ERROR_INSTRUCTION_PARAM;
1466 __ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx()));
1467 __ movl(ecx, Operand(eax, offsetof(sp_context_t, rp)));
1469 // Check if the return stack is used up.
1470 __ cmpl(ecx, SP_MAX_RETURN_STACK);
1471 __ j(not_below, &error_stack_low_);
1473 // Add to the return stack.
1474 uintptr_t cip = uintptr_t(cip_ - 2) - uintptr_t(plugin_->pcode);
1475 __ movl(Operand(eax, ecx, ScaleFour, offsetof(sp_context_t, rstk_cips)), cip);
1477 // Increment the return stack pointer.
1478 __ addl(Operand(eax, offsetof(sp_context_t, rp)), 1);
1480 // Store the CIP of the function we're about to call.
1481 __ movl(Operand(cipAddr()), offset);
1483 JitFunction *fun = rt_->GetJittedFunctionByOffset(offset);
1485 // Need to emit a delayed thunk.
1486 CallThunk *thunk = new CallThunk(offset);
1487 __ call(&thunk->call);
1488 if (!thunks_.append(thunk))
1491 // Function is already emitted, we can do a direct call.
1492 __ call(ExternalAddress(fun->GetEntryAddress()));
1495 // Restore the last cip.
1496 __ movl(Operand(cipAddr()), cip);
1498 // Mark us as leaving the last frame.
1499 __ movl(tmp, intptr_t(rt_->GetBaseContext()->GetCtx()));
1500 __ subl(Operand(tmp, offsetof(sp_context_t, rp)), 1);
1505 Compiler::emitCallThunks()
1507 for (size_t i = 0; i < thunks_.length(); i++) {
1508 CallThunk *thunk = thunks_[i];
1511 __ bind(&thunk->call);
1512 // Huge hack - get the return address, since that is the call that we
1514 __ movl(eax, Operand(esp, 0));
1516 // We need to push 4 arguments, and one of them will need an extra word
1517 // on the stack. Allocate a big block so we're aligned, subtracting
1518 // 4 because we got here via a call.
1519 static const size_t kStackNeeded = 5 * sizeof(void *);
1520 static const size_t kStackReserve = ke::Align(kStackNeeded, 16) - sizeof(void *);
1521 __ subl(esp, kStackReserve);
1524 __ movl(Operand(esp, 3 * sizeof(void *)), eax);
1525 __ lea(edx, Operand(esp, 4 * sizeof(void *)));
1526 __ movl(Operand(esp, 2 * sizeof(void *)), edx);
1527 __ movl(Operand(esp, 1 * sizeof(void *)), intptr_t(thunk->pcode_offset));
1528 __ movl(Operand(esp, 0 * sizeof(void *)), intptr_t(rt_));
1530 __ call(ExternalAddress((void *)CompileFromThunk));
1531 __ movl(edx, Operand(esp, 4 * sizeof(void *)));
1532 __ addl(esp, kStackReserve);
1534 __ j(not_zero, &error);
1538 __ movl(Operand(cipAddr()), thunk->pcode_offset);
1539 __ jmp(g_Jit.GetUniversalReturn());
1544 Compiler::readCell()
1546 if (cip_ >= code_end_) {
1547 error_= SP_ERROR_INVALID_INSTRUCTION;
1554 Compiler::emitNativeCall(OPCODE op)
1556 uint32_t native_index = readCell();
1558 if (native_index >= plugin_->num_natives) {
1559 error_ = SP_ERROR_INSTRUCTION_PARAM;
1563 uint32_t num_params;
1564 if (op == OP_SYSREQ_N) {
1565 num_params = readCell();
1567 // See if we can get a replacement opcode. If we can, then recursively
1568 // call emitOp() to generate it. Note: it's important that we do this
1569 // before generating any code for the SYSREQ.N.
1570 unsigned replacement = rt_->GetNativeReplacement(native_index);
1571 if (replacement != OP_NOP)
1572 return emitOp((OPCODE)replacement);
1574 // Store the number of parameters.
1575 __ movl(Operand(stk, -4), num_params);
1582 // Push the last parameter for the C++ function.
1585 // Relocate our absolute stk to be dat-relative, and update the context's
1587 __ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx()));
1589 __ movl(Operand(eax, offsetof(sp_context_t, sp)), stk);
1591 __ movl(Operand(eax, offsetof(sp_context_t, n_idx)), native_index);
1593 sp_native_t *native = rt_->GetNativeByIndex(native_index);
1594 if ((native->status != SP_NATIVE_BOUND) ||
1595 (native->flags & (SP_NTVFLAG_OPTIONAL | SP_NTVFLAG_EPHEMERAL)))
1597 // The native is either unbound, or it could become unbound in the
1598 // future. Invoke the slower native callback.
1599 __ push(native_index);
1601 __ call(ExternalAddress((void *)NativeCallback));
1603 // The native is bound so we have a few more guarantees.
1604 __ push(intptr_t(native->pfn));
1606 __ call(ExternalAddress((void *)BoundNativeCallback));
1609 // Check for errors.
1610 __ movl(ecx, intptr_t(rt_->GetBaseContext()->GetCtx()));
1611 __ movl(ecx, Operand(ecx, offsetof(sp_context_t, n_err)));
1613 __ j(not_zero, &extern_error_);
1615 // Restore local state.
1620 if (op == OP_SYSREQ_N) {
1621 // Pop the stack. Do not check the margins.
1622 __ addl(stk, (num_params + 1) * sizeof(cell_t));
1628 Compiler::emitSwitch()
1630 cell_t offset = readCell();
1631 if (!labelAt(offset))
1634 cell_t *tbl = (cell_t *)((char *)plugin_->pcode + offset + sizeof(cell_t));
1641 size_t ncases = *tbl++;
1643 Label *defaultCase = labelAt(*tbl);
1647 // Degenerate - 0 cases.
1649 __ jmp(defaultCase);
1653 Entry *cases = (Entry *)(tbl + 1);
1655 // Degenerate - 1 case.
1657 Label *maybe = labelAt(cases[0].offset);
1660 __ cmpl(pri, cases[0].val);
1662 __ jmp(defaultCase);
1666 // We have two or more cases, so let's generate a full switch. Decide
1667 // whether we'll make an if chain, or a jump table, based on whether
1668 // the numbers are strictly sequential.
1669 bool sequential = true;
1671 cell_t first = cases[0].val;
1672 cell_t last = first;
1673 for (size_t i = 1; i < ncases; i++) {
1674 if (cases[i].val != ++last) {
1681 // First check whether the bounds are correct: if (a < LOW || a > HIGH);
1682 // this check is valid whether or not we emit a sequential-optimized switch.
1683 cell_t low = cases[0].val;
1685 // negate it so we'll get a lower bound of 0.
1687 __ lea(tmp, Operand(pri, low));
1692 cell_t high = abs(cases[0].val - cases[ncases - 1].val);
1694 __ j(above, defaultCase);
1697 // Optimized table version. The tomfoolery below is because we only have
1698 // one free register... it seems unlikely pri or alt will be used given
1699 // that we're at the end of a control-flow point, but we'll play it safe.
1702 __ movl(eax, &table);
1703 __ movl(ecx, Operand(eax, ecx, ScaleFour));
1708 for (size_t i = 0; i < ncases; i++) {
1709 Label *label = labelAt(cases[i].offset);
1712 __ emit_absolute_address(label);
1715 // Slower version. Go through each case and generate a check.
1716 for (size_t i = 0; i < ncases; i++) {
1717 Label *label = labelAt(cases[i].offset);
1720 __ cmpl(pri, cases[i].val);
1723 __ jmp(defaultCase);
1729 Compiler::emitErrorPath(Label *dest, int code)
1734 __ jmp(g_Jit.GetUniversalReturn());
1739 Compiler::emitFloatCmp(ConditionCode cc)
1743 if (cc == below || cc == below_equal) {
1744 // NaN results in ZF=1 PF=1 CF=1
1746 // ja/jae check for ZF,CF=0 and CF=0. If we make all relational compares
1747 // look like ja/jae, we'll guarantee all NaN comparisons will fail (which
1748 // would not be true for jb/jbe, unless we checked with jp).
1757 if (MacroAssemblerX86::Features().sse) {
1758 __ movss(xmm0, Operand(stk, rhs));
1759 __ ucomiss(Operand(stk, lhs), xmm0);
1761 __ fld32(Operand(stk, rhs));
1762 __ fld32(Operand(stk, lhs));
1767 // An equal or not-equal needs special handling for the parity bit.
1768 if (cc == equal || cc == not_equal) {
1769 // If NaN, PF=1, ZF=1, and E/Z tests ZF=1.
1771 // If NaN, PF=1, ZF=1 and NE/NZ tests Z=0. But, we want any != with NaNs
1772 // to return true, including NaN != NaN.
1774 // To make checks simpler, we set |eax| to the expected value of a NaN
1775 // beforehand. This also clears the top bits of |eax| for setcc.
1777 __ movl(eax, (cc == equal) ? 0 : 1);
1778 __ j(parity, &done);
1789 Compiler::emitErrorPaths()
1791 emitErrorPath(&error_divide_by_zero_, SP_ERROR_DIVIDE_BY_ZERO);
1792 emitErrorPath(&error_stack_low_, SP_ERROR_STACKLOW);
1793 emitErrorPath(&error_stack_min_, SP_ERROR_STACKMIN);
1794 emitErrorPath(&error_bounds_, SP_ERROR_ARRAY_BOUNDS);
1795 emitErrorPath(&error_memaccess_, SP_ERROR_MEMACCESS);
1796 emitErrorPath(&error_heap_low_, SP_ERROR_HEAPLOW);
1797 emitErrorPath(&error_heap_min_, SP_ERROR_HEAPMIN);
1798 emitErrorPath(&error_integer_overflow_, SP_ERROR_INTEGER_OVERFLOW);
1800 if (extern_error_.used()) {
1801 __ bind(&extern_error_);
1802 __ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx()));
1803 __ movl(eax, Operand(eax, offsetof(sp_context_t, n_err)));
1804 __ jmp(g_Jit.GetUniversalReturn());
1808 typedef int (*JIT_EXECUTE)(sp_context_t *ctx, uint8_t *memory, void *code);
1811 GenerateEntry(void **retp, void **timeoutp)
1818 __ push(esi); // ebp - 4
1819 __ push(edi); // ebp - 8
1820 __ push(ebx); // ebp - 12
1821 __ push(esp); // ebp - 16
1823 __ movl(ebx, Operand(ebp, 8 + 4 * 0));
1824 __ movl(eax, Operand(ebp, 8 + 4 * 1));
1825 __ movl(ecx, Operand(ebp, 8 + 4 * 2));
1827 // Set up run-time registers.
1828 __ movl(edi, Operand(ebx, offsetof(sp_context_t, sp)));
1834 __ andl(esp, 0xfffffff0);
1836 // Call into plugin (align the stack first).
1839 // Get input context, store rval.
1840 __ movl(ecx, Operand(ebp, 8 + 4 * 0));
1841 __ movl(Operand(ecx, offsetof(sp_context_t, rval)), pri);
1844 __ movl(eax, SP_ERROR_NONE);
1846 // Store latest stk. If we have an error code, we'll jump directly to here,
1847 // so eax will already be set.
1851 __ movl(Operand(ecx, offsetof(sp_context_t, sp)), stk);
1854 __ movl(esp, Operand(ebp, -16));
1856 // Restore registers and gtfo.
1863 // The universal emergency return will jump to here.
1866 __ movl(ecx, Operand(ebp, 8 + 4 * 0)); // ret-path expects ecx = ctx
1871 __ movl(eax, SP_ERROR_TIMEOUT);
1874 void *code = LinkCode(masm);
1878 *retp = reinterpret_cast<uint8_t *>(code) + error.offset();
1879 *timeoutp = reinterpret_cast<uint8_t *>(code) + timeout.offset();
1883 ICompilation *JITX86::ApplyOptions(ICompilation *_IN, ICompilation *_OUT)
1888 CompData *_in = (CompData * )_IN;
1889 CompData *_out = (CompData * )_OUT;
1891 _in->inline_level = _out->inline_level;
1892 _in->profile = _out->profile;
1904 JITX86::InitializeJIT()
1906 g_pCodeCache = KE_CreateCodeCache();
1908 m_pJitEntry = GenerateEntry(&m_pJitReturn, &m_pJitTimeout);
1912 MacroAssemblerX86 masm;
1913 MacroAssemblerX86::GenerateFeatureDetection(masm);
1914 void *code = LinkCode(masm);
1917 MacroAssemblerX86::RunFeatureDetection(code);
1918 KE_FreeCode(g_pCodeCache, code);
1924 JITX86::ShutdownJIT()
1926 KE_DestroyCodeCache(g_pCodeCache);
1930 JITX86::CompileFunction(BaseRuntime *prt, cell_t pcode_offs, int *err)
1932 Compiler cc(prt, pcode_offs);
1933 JitFunction *fun = cc.emit(err);
1937 // Grab the lock before linking code in, since the watchdog timer will look
1938 // at this list on another thread.
1939 ke::AutoLock lock(g_Jit.Mutex());
1941 prt->AddJittedFunction(fun);
1946 JITX86::SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx)
1948 ctx->tracker = new tracker_t;
1949 ctx->tracker->pBase = (ucell_t *)malloc(1024);
1950 ctx->tracker->pCur = ctx->tracker->pBase;
1951 ctx->tracker->size = 1024 / sizeof(cell_t);
1953 ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler();
1954 ctx->plugin = const_cast<sp_plugin_t *>(runtime->plugin());
1958 JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
1965 __ movl(edi, Operand(esp, 16)); // store ctx
1966 __ movl(esi, Operand(esp, 20)); // store params
1968 __ andl(esp, 0xfffffff0);
1971 __ push(intptr_t(pData));
1974 __ call(ExternalAddress((void *)callback));
1981 return (SPVM_NATIVE_FUNC)LinkCode(masm);
1985 JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
1987 KE_FreeCode(g_pCodeCache, (void *)func);
1991 JITX86::StartCompilation()
1993 return new CompData;
1997 JITX86::StartCompilation(BaseRuntime *runtime)
1999 return new CompData;
2009 JITX86::FreeContextVars(sp_context_t *ctx)
2011 free(ctx->tracker->pBase);
2012 delete ctx->tracker;
2016 CompData::SetOption(const char *key, const char *val)
2018 if (strcmp(key, SP_JITCONF_DEBUG) == 0)
2020 if (strcmp(key, SP_JITCONF_PROFILE) == 0) {
2021 profile = atoi(val);
2023 /** Callbacks must be profiled to profile functions! */
2024 if ((profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
2025 profile |= SP_PROF_CALLBACKS;
2034 JITX86::InvokeFunction(BaseRuntime *runtime, JitFunction *fn, cell_t *result)
2036 sp_context_t *ctx = runtime->GetBaseContext()->GetCtx();
2038 // Note that cip, hp, sp are saved and restored by Execute2().
2039 ctx->cip = fn->GetPCodeAddress();
2041 JIT_EXECUTE pfn = (JIT_EXECUTE)m_pJitEntry;
2045 int err = pfn(ctx, runtime->plugin()->memory, fn->GetEntryAddress());
2048 *result = ctx->rval;
2053 JITX86::AllocCode(size_t size)
2055 return Knight::KE_AllocCode(g_pCodeCache, size);
2059 JITX86::FreeCode(void *code)
2061 KE_FreeCode(g_pCodeCache, code);
2065 JITX86::RegisterRuntime(BaseRuntime *rt)
2067 mutex_.AssertCurrentThreadOwns();
2068 runtimes_.append(rt);
2072 JITX86::DeregisterRuntime(BaseRuntime *rt)
2074 mutex_.AssertCurrentThreadOwns();
2075 runtimes_.remove(rt);
2079 JITX86::PatchAllJumpsForTimeout()
2081 mutex_.AssertCurrentThreadOwns();
2082 for (ke::InlineList<BaseRuntime>::iterator iter = runtimes_.begin(); iter != runtimes_.end(); iter++) {
2083 BaseRuntime *rt = *iter;
2084 for (size_t i = 0; i < rt->NumJitFunctions(); i++) {
2085 JitFunction *fun = rt->GetJitFunction(i);
2086 uint8_t *base = reinterpret_cast<uint8_t *>(fun->GetEntryAddress());
2088 for (size_t j = 0; j < fun->NumLoopEdges(); j++) {
2089 const LoopEdge &e = fun->GetLoopEdge(j);
2090 int32_t diff = intptr_t(m_pJitTimeout) - intptr_t(base + e.offset);
2091 *reinterpret_cast<int32_t *>(base + e.offset - 4) = diff;
2098 JITX86::UnpatchAllJumpsFromTimeout()
2100 mutex_.AssertCurrentThreadOwns();
2101 for (ke::InlineList<BaseRuntime>::iterator iter = runtimes_.begin(); iter != runtimes_.end(); iter++) {
2102 BaseRuntime *rt = *iter;
2103 for (size_t i = 0; i < rt->NumJitFunctions(); i++) {
2104 JitFunction *fun = rt->GetJitFunction(i);
2105 uint8_t *base = reinterpret_cast<uint8_t *>(fun->GetEntryAddress());
2107 for (size_t j = 0; j < fun->NumLoopEdges(); j++) {
2108 const LoopEdge &e = fun->GetLoopEdge(j);
2109 *reinterpret_cast<int32_t *>(base + e.offset - 4) = e.disp32;