* Good: instruction.is_unresolved
* Bad: for i in range(0, bb.icount): instr = bb.instructions[i]
* Good: for instr in bb.instructions
+
+ TODO:
+
+ * Everywhere we return a variable number, we should return a varinfo
+ (varinfo wrapper has an index member anyways)
*/
#include <Python.h>
F_CLASS_CALL_RETURN_TYPE,
F_CLASS_CALL_ARGS,
F_CLASSREF,
- F_DST,
+ F_CONTROL_FLOW,
+ F_CONTROL_FLOW_EX,
+ F_DATA_FLOW,
+ F_DATA_FLOW_EX,
F_DESCRIPTOR,
+ F_DST,
F_EXCEPTION_HANDLER,
F_FIELD_TYPE,
F_FIELD,
+ F_INDEX,
F_INSTRUCTIONS,
F_IS_CLASS_CONSTANT,
+ F_IS_INOUT,
+ F_IS_LOCAL,
+ F_IS_PREALLOCATED,
+ F_IS_SAVED,
+ F_IS_TEMPORARY,
F_IS_UNRESOLVED,
F_LOCAL_METHODINFO,
F_KLASS,
{ "call_return_type", F_CLASS_CALL_RETURN_TYPE },
{ "call_args", F_CLASS_CALL_ARGS },
{ "classref", F_CLASSREF },
- { "dst", F_DST },
+ { "control_flow", F_CONTROL_FLOW },
+ { "control_flow_ex", F_CONTROL_FLOW_EX },
+ { "data_flow", F_DATA_FLOW },
+ { "data_flow_ex", F_DATA_FLOW_EX },
{ "descriptor", F_DESCRIPTOR },
+ { "dst", F_DST },
{ "exception_handler", F_EXCEPTION_HANDLER },
{ "field", F_FIELD },
{ "field_type", F_FIELD_TYPE },
+ { "index", F_INDEX },
{ "instructions", F_INSTRUCTIONS },
- { "is_unresolved", F_IS_UNRESOLVED },
{ "is_class_constant", F_IS_CLASS_CONSTANT },
+ { "is_inout", F_IS_INOUT },
+ { "is_local", F_IS_LOCAL },
+ { "is_preallocated", F_IS_PREALLOCATED },
+ { "is_saved", F_IS_SAVED },
+ { "is_temporary", F_IS_TEMPORARY },
+ { "is_unresolved", F_IS_UNRESOLVED },
{ "klass", F_KLASS },
{ "line", F_LINE },
{ "local_map", F_LOCAL_MAP },
}
}
+static inline int instruction_opcode_ex(instruction *iptr) {
+ if (iptr->opc == ICMD_BUILTIN) {
+ return iptr->sx.s23.s3.bte->opcode;
+ } else {
+ return iptr->opc;
+ }
+}
+
ITERATOR_FUNC(call_args_iter_func) {
instruction *iptr = (instruction *)state->data;
switch (op) {
case F_OPCODE:
return get_int(arg->get.result, iptr->opc);
case F_OPCODE_EX:
- if (iptr->opc == ICMD_BUILTIN) {
- return get_int(arg->get.result, iptr->sx.s23.s3.bte->opcode);
- } else {
- return get_int(arg->get.result, iptr->opc);
- }
+ return get_int(arg->get.result, instruction_opcode_ex(iptr));
case F_NAME:
return get_string(arg->get.result, icmd_table[iptr->opc].name);
case F_NAME_EX:
- if (iptr->opc == ICMD_BUILTIN) {
- return get_string(arg->get.result, icmd_table[iptr->sx.s23.s3.bte->opcode].name);
- } else {
- return get_string(arg->get.result, icmd_table[iptr->opc].name);
- }
+ return get_string(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].name);
case F_S1:
return get_int(arg->get.result, iptr->s1.varindex);
case F_S2:
case F_PEI:
return get_bool(arg->get.result, icmd_table[iptr->opc].flags & ICMDTABLE_PEI);
case F_PEI_EX:
- if (iptr->opc == ICMD_BUILTIN) {
- return get_bool(arg->get.result, icmd_table[iptr->sx.s23.s3.bte->opcode].flags & ICMDTABLE_PEI);
- } else {
- return get_bool(arg->get.result, icmd_table[iptr->opc].flags & ICMDTABLE_PEI);
- }
+ return get_bool(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].flags & ICMDTABLE_PEI);
+ case F_DATA_FLOW:
+ return get_int(arg->get.result, icmd_table[iptr->opc].dataflow);
+ case F_DATA_FLOW_EX:
+ return get_int(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].dataflow);
+ case F_CONTROL_FLOW:
+ return get_int(arg->get.result, icmd_table[iptr->opc].controlflow);
+ case F_CONTROL_FLOW_EX:
+ return get_int(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].controlflow);
}
}
CLASS_FUNC(varinfo_func) {
+ jitdata *jd = state->jd;
varinfo *var = (varinfo *)state->vp;
+ int index = var - jd->var;
switch (op) {
case CLASS_GET_FIELD:
switch (arg->get.field) {
case F_TYPE:
return get_int(arg->get.result, var->type);
+ case F_IS_LOCAL:
+ return get_bool(arg->get.result, index < jd->localcount);
+ case F_IS_PREALLOCATED:
+ return get_bool(
+ arg->get.result,
+ (index >= jd->localcount) && (var->flags & PREALLOC)
+ );
+ case F_IS_INOUT:
+ return get_bool(
+ arg->get.result,
+ (index >= jd->localcount) && !(var->flags && PREALLOC) && (var->flags & INOUT)
+ );
+ case F_IS_TEMPORARY:
+ return get_bool(
+ arg->get.result,
+ (index >= jd->localcount) && !(var->flags && PREALLOC) && !(var->flags & INOUT)
+ );
+ case F_IS_SAVED:
+ return get_bool(arg->get.result, var->flags & SAVEDVAR);
+ case F_INDEX:
+ return get_int(arg->get.result, index);
}
+
}
return -1;
}
c(TYPE_VOID);
c(UNUSED);
+ /* data flow */
+
+ c(DF_0_TO_0);
+ c(DF_1_TO_0);
+ c(DF_2_TO_0);
+ c(DF_3_TO_0);
+ c(DF_DST_BASE);
+ c(DF_0_TO_1);
+ c(DF_1_TO_1);
+ c(DF_2_TO_1);
+ c(DF_3_TO_1);
+ c(DF_N_TO_1);
+ c(DF_INVOKE);
+ c(DF_BUILTIN);
+ c(DF_COPY);
+ c(DF_MOVE);
+ c(DF_DUP);
+ c(DF_DUP_X1);
+ c(DF_DUP_X2);
+ c(DF_DUP2);
+ c(DF_DUP2_X1);
+ c(DF_DUP2_X2);
+ c(DF_SWAP);
+ c(DF_LOAD);
+ c(DF_STORE);
+ c(DF_IINC);
+ c(DF_POP);
+ c(DF_POP2);
+
+ /* control flow */
+
+ c(CF_NORMAL);
+ c(CF_IF);
+ c(CF_END_BASE);
+ c(CF_END);
+ c(CF_GOTO);
+ c(CF_TABLE);
+ c(CF_LOOKUP);
+ c(CF_JSR);
+ c(CF_RET);
+
# undef c
}