Erlang中process_main的两种执行模式

非JUMP_TABLE使用switch

#include<string.h>                                                                      
#include<stdlib.h>                                                                    
#include<stdio.h>                                                        
typedef unsigned long Uint;                                                             
typedef unsigned long  BeamInstr;                                                         
typedef unsigned long  UWord;                                                                                                                                                           
#  define OpCase(OpCode)    case op_##OpCode                                                  #  define OpCode(OpCode)    ((Uint*)op_##OpCode)                                              
#  define Goto(Rel) {Go = (int)(UWord)(Rel); goto emulator_loop;}                                    
#define op_i_apply 80      
#define op_normal_exit 422

int main(){      
     int Go;                                                                              
     BeamInstr* I;        
     BeamInstr* next;  
     BeamInstr beam_apply[2]; 
     beam_apply[0]             = (BeamInstr) OpCode(i_apply);  
     beam_apply[1]             = (BeamInstr) OpCode(normal_exit);                                        
     printf("beam_apply %p\r\n",beam_apply);                                                       printf("beam_apply[0] %lu\r\n",beam_apply[0]);   
     printf("beam_apply[0] %p\r\n",beam_apply[0]);  
     
     I = (BeamInstr *) beam_apply;    
     next = (BeamInstr *) *I;    
     printf("next: %p\r\n",next);  
     Goto(next);
                        
emulator_loop:
     switch(Go){
     OpCase(i_apply):{  
               printf("i_apply %p %u \r\n",I,(*I)); 
               printf("i_apply %p %p \r\n",I,(*I));
               I = I + 1;
               Goto(*I); 
          }             
     OpCase(normal_exit):{   
               printf("normal_exit %p \r\n",I);  
               return 0;                                                                      
          }  
      }
      return 1;
}


使用JUMP_TABLE使用Goto

#include<string.h>      
#include<stdlib.h>       
#include<stdio.h>                                                                                                      
typedef unsigned long Uint;  
typedef unsigned long  BeamInstr;   
typedef unsigned long  UWord;                                                                                          
                                                                                                                       
#  define OpCase(OpCode)    lb_##OpCode 
#  define Goto(Rel) goto *((void *)Rel)   
#  define OpCode(OpCode)  (&&lb_##OpCode)                                                                             
int main(){                                                
     BeamInstr* I;                                                                         
     BeamInstr* next; 
     BeamInstr beam_apply[2];   
     
     beam_apply[0]             = (BeamInstr) OpCode(i_apply);   
     beam_apply[1]             = (BeamInstr) OpCode(normal_exit);   
     
     printf("beam_apply %p\r\n",beam_apply);    
     printf("beam_apply[0] %lu\r\n",beam_apply[0]);  
     printf("beam_apply[0] %p\r\n",beam_apply[0]);                                                                     
     I = (BeamInstr *) beam_apply;  
     next = (BeamInstr *) *I;   
     printf("next: %p\r\n",next);   
     Goto(next);
     OpCase(i_apply):{        
          printf("i_apply %p %u \r\n",I,(*I));  
          printf("i_apply %p %p \r\n",I,(*I)); 
          I = I + 1;                          
          Goto(*I);                                                                           
     }
     OpCase(normal_exit):{   
          printf("normal_exit %p \r\n",I);  
          return 0;     
     }         
     return 1;          
}


从这两段代码中看出,当我们不使用JUMP_TABLE的时候,beam_apply这个数组中存放的是整形数值的常量。当通过

next = (BeamInstr *) *I;

赋值给next的时候,next类型是指针,但是并不指向一个地址,而是一个整形值。

当我们使用JUMP_TABLE的时候,beam_apply这个数组中存放的是被转化成整形数值的地址。当通过

next = (BeamInstr *) *I;

赋值给next的时候,next类型是指针,并且指向相应lb地址。

gcc会吧switch编译成jmp这个和Goto语句没什么区别。但是有一个区别的是switch在jmp前需要进行一次判断,而使用JUMP TABLE是直接jmp到后面的地址。


你可能感兴趣的:(erlang,table,JUMP,指令执行)