pike.git / src / code / amd64.c

version» Context lines:

pike.git/src/code/amd64.c:45:   #define ARG2_REG REG_RSI   #define ARG3_REG REG_RDX   #define ARG4_REG REG_RCX   #define ARG5_REG REG_R8   #define ARG6_REG REG_R9   #endif      static enum amd64_reg sp_reg = -1, fp_reg = -1, mark_sp_reg = -1;   static int dirty_regs = 0, ret_for_func = 0;   ptrdiff_t amd64_prev_stored_pc = -1; /* PROG_PC at the last point Pike_fp->pc was updated. */ - static int branch_check_threads_update_etc = -1; + static int branch_check_threads_update_etc = 0; + static int store_pc = 0;    -  +    #define MAX_LABEL_USES 6   struct label {    int n_label_uses;    ptrdiff_t addr;    ptrdiff_t offset[MAX_LABEL_USES];   };      static void label( struct label *l )   {    int i;
pike.git/src/code/amd64.c:868:   static void jg( struct label *l ) { return jump_rel8( l, 0x7f ); }         #define LABELS() struct label label_A, label_B, label_C, label_D, label_E;label_A.addr = -1;label_A.n_label_uses = 0;label_B.addr = -1;label_B.n_label_uses = 0;label_C.addr = -1;label_C.n_label_uses = 0;label_D.addr = -1;label_D.n_label_uses = 0;label_E.addr=-1;label_E.n_label_uses=0;   #define LABEL_A label(&label_A)   #define LABEL_B label(&label_B)   #define LABEL_C label(&label_C)   #define LABEL_D label(&label_D)   #define LABEL_E label(&label_E)    + static void amd64_ins_branch_check_threads_etc(int code_only); + static int func_start = 0; +  + /* Called at the start of a function. */ + void amd64_start_function(int store_lines ) + { +  store_pc = store_lines; +  branch_check_threads_update_etc = 0; +  /* +  * store_lines is true for any non-constant evaluation function +  * In reality we should only do this if we are going to be using +  * check_threads_etc (ie, if we have a loop). +  * +  * It does not really waste all that much space in the code, though. +  * +  * We could really do this one time per program instead of once per +  * function. +  * +  * But it is very hard to know when a new program starts, and +  * PIKE_PC is not reliable as a marker since constant evaluations +  * are also done using this code. So for now, waste ~20 bytes per +  * function in the program code. +  */ +  if( store_lines ) +  amd64_ins_branch_check_threads_etc(1); +  func_start = PIKE_PC; + } +  + /* Called when the current function is done */ + void amd64_end_function(int no_pc) + { +  branch_check_threads_update_etc = 0; + } +  +    /* Machine code entry prologue.    *    * On entry:    * RDI: Pike_interpreter (ARG1_REG)    *    * During interpreting:    * R15: Pike_interpreter    */   void amd64_ins_entry(void)   {    /* Push all registers that the ABI requires to be preserved. */    push(REG_RBP);    mov_reg_reg(REG_RSP, REG_RBP);    push(REG_R15);    push(REG_R14);    push(REG_R13);    push(REG_R12);    push(REG_RBX);    sub_reg_imm(REG_RSP, 8); /* Align on 16 bytes. */ -  +     mov_reg_reg(ARG1_REG, Pike_interpreter_reg); -  +     amd64_flush_code_generator_state();   }      void amd64_flush_code_generator_state(void)   {    sp_reg = -1;    fp_reg = -1; -  +  ret_for_func = 0;    mark_sp_reg = -1;    dirty_regs = 0; -  ret_for_func = 0; +     amd64_prev_stored_pc = -1; -  branch_check_threads_update_etc = -1; +    }      static void flush_dirty_regs(void)   {    /* NB: PIKE_FP_REG is currently never dirty. */    if (dirty_regs & (1 << PIKE_SP_REG)) {    mov_reg_mem(PIKE_SP_REG, Pike_interpreter_reg,    OFFSETOF(Pike_interpreter_struct, stack_pointer));    dirty_regs &= ~(1 << PIKE_SP_REG);    }
pike.git/src/code/amd64.c:1239: Inside #if 0
   }   #endif   #endif   }         static void maybe_update_pc(void)   {    static int last_prog_id=-1;    static size_t last_num_linenumbers=-1; +  if( !store_pc ) return;       if(   #ifdef PIKE_DEBUG    /* Update the pc more often for the sake of the opcode level trace. */    d_flag ||   #endif    (amd64_prev_stored_pc == -1) ||    last_prog_id != Pike_compiler->new_program->id ||    last_num_linenumbers != Pike_compiler->new_program->num_linenumbers    ) {    last_prog_id=Pike_compiler->new_program->id;    last_num_linenumbers = Pike_compiler->new_program->num_linenumbers;    UPDATE_PC();    }   }      static void maybe_load_fp(void)   {    static int last_prog_id=-1;    static size_t last_num_linenumbers=-1; -  +  if( !store_pc ) return;       if(   #ifdef PIKE_DEBUG    /* Update the pc more often for the sake of the opcode level trace. */    d_flag ||   #endif    (amd64_prev_stored_pc == -1) ||    last_prog_id != Pike_compiler->new_program->id ||    last_num_linenumbers != Pike_compiler->new_program->num_linenumbers    ) {
pike.git/src/code/amd64.c:1340:    amd64_load_fp_reg();    amd64_load_sp_reg();       mov_imm_mem( PIKE_T_OBJECT, sp_reg, OFFSETOF(svalue,type));    mov_mem_reg( fp_reg, OFFSETOF(pike_frame, current_object), REG_RAX );    mov_reg_mem( REG_RAX, sp_reg, OFFSETOF(svalue,u.object) );    add_mem32_imm( REG_RAX, (INT32)OFFSETOF(object, refs), 1);    amd64_add_sp( 1 );   }    - void amd64_ins_branch_check_threads_etc() + static void amd64_align()   { -  +  while( PIKE_PC & 3 ) +  ib( 0x90 ); + } +  + static void amd64_ins_branch_check_threads_etc(int code_only) + {    LABELS();    - #if 1 -  if( branch_check_threads_update_etc == -1 ) +  if( !branch_check_threads_update_etc )    { -  /* Create update + call to branch_checl_threds_etc */ +  /* Create update + call to branch_check_threds_etc */ +  if( !code_only )    jmp( &label_A ); -  mov_imm_mem32( 0, REG_RSP, 0); +     branch_check_threads_update_etc = PIKE_PC;    if( (unsigned long long)&fast_check_threads_counter < 0x7fffffffULL )    {    /* Short pointer. */    clear_reg( REG_RAX );    add_mem32_imm( REG_RAX,    (int)(ptrdiff_t)&fast_check_threads_counter,    0x80 );    }    else    {    mov_imm_reg( (long)&fast_check_threads_counter, REG_RAX);    add_mem_imm( REG_RAX, 0, 0x80 );    }    mov_imm_reg( (ptrdiff_t)branch_check_threads_etc, REG_RAX );    jmp_reg(REG_RAX); /* ret in BCTE will return to desired point. */ -  +  amd64_align();    } -  +  if( !code_only ) +  {    LABEL_A;    /* Use C-stack for counter. We have padding added in entry */    add_mem8_imm( REG_RSP, 0, 1 );    jno( &label_B );    call_rel_imm32( branch_check_threads_update_etc-PIKE_PC );    LABEL_B; - #else -  call_imm( &branch_check_threads_etc ); - #endif +     } -  + }         void amd64_init_interpreter_state(void)   {    instrs[F_CATCH - F_OFFSET].address = inter_return_opcode_F_CATCH;   }      static void amd64_return_from_function()   {    if( ret_for_func )
pike.git/src/code/amd64.c:1404:    pop(REG_RBX);    pop(REG_R12);    pop(REG_R13);    pop(REG_R14);    pop(REG_R15);    pop(REG_RBP);    ret();    }   }    - static void amd64_align() - { -  while( PIKE_PC & 7 ) -  ib( 0x90 ); - } -  +    void ins_f_byte(unsigned int b)   {    int flags;    void *addr;    INT32 rel_addr = 0;    LABELS();       b-=F_OFFSET;   #ifdef PIKE_DEBUG    if(b>255)
pike.git/src/code/amd64.c:1968: Inside #if defined(PIKE_DEBUG)
   if(off>255)    Pike_error("Instruction too big %d\n",off);   #endif    flags = instrs[off].flags;    if (!(flags & I_BRANCH)) return -1;      #define START_JUMP() do{ \    ins_debug_instr_prologue(off, 0, 0); \    if (backward_jump) { \    maybe_update_pc(); \ -  amd64_ins_branch_check_threads_etc(); \ +  amd64_ins_branch_check_threads_etc(0); \    } \    } while(0)       switch( op )    {    case F_QUICK_BRANCH_WHEN_ZERO:    case F_QUICK_BRANCH_WHEN_NON_ZERO:    START_JUMP();    amd64_load_sp_reg();    amd64_add_sp( -1 );
pike.git/src/code/amd64.c:2040:    -1: counter    */    amd64_load_sp_reg();    mov_mem_reg( sp_reg, -1*sizeof(struct svalue)+8, REG_RAX );    mov_mem_reg( sp_reg, -4*sizeof(struct svalue)+8, REG_RBX );    mov_mem32_reg( REG_RBX, OFFSETOF(array,size), REG_RCX );    cmp_reg_reg( REG_RAX, REG_RCX );    je(&label_A);       /* increase counter */ -  add_mem_imm( sp_reg, -1*sizeof(struct svalue)+8, 1 ); +  add_mem_imm( sp_reg, -1*(int)sizeof(struct svalue)+8, 1 );       /* get item */    mov_mem_reg( REG_RBX, OFFSETOF(array,item), REG_RBX );    shl_reg_imm( REG_RAX, 4 );    add_reg_reg( REG_RBX, REG_RAX );       mov_mem8_reg( sp_reg, -3*sizeof(struct svalue), REG_RAX );    cmp_reg_imm( REG_RAX,T_SVALUE_PTR);    jne( &label_C );   
pike.git/src/code/amd64.c:2207:    amd64_call_c_opcode(addr, flags);       amd64_load_sp_reg();    test_reg(REG_RAX);       if (backward_jump) {    INT32 skip;    add_to_program (0x74); /* jz rel8 */    add_to_program (0); /* Bytes to skip. */    skip = (INT32)PIKE_PC; -  amd64_ins_branch_check_threads_etc(); -  /* amd64_call_c_function (branch_check_threads_etc); */ +  amd64_ins_branch_check_threads_etc(0);    add_to_program (0xe9); /* jmp rel32 */    ret = DO_NOT_WARN ((INT32) PIKE_PC);    PUSH_INT (0);    /* Adjust the skip for the relative jump. */    Pike_compiler->new_program->program[skip-1] = ((INT32)PIKE_PC - skip);    }    else {    add_to_program (0x0f); /* jnz rel32 */    add_to_program (0x85);    ret = DO_NOT_WARN ((INT32) PIKE_PC);