mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	support set_trace_func (incomplete. id and klass don't be passed). And support Thread#set_trace_func which hook only specified thread and Thread#add_trace_func which add new trace func instead of replace old one. C level API was modified. See thread.c (logic) and yarvcore.h (data structures). * vm.c, vm_macro.def: add hook points. * compile.c, insns.def: fix "trace" instruction. * iseq.c, vm_macro.h: add compile option "trace_instruction". * test/ruby/test_settracefunc.rb: hook "c-return" of set_trace_func. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12195 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			217 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**********************************************************************
 | 
						|
 | 
						|
  compile.h -
 | 
						|
 | 
						|
  $Author$
 | 
						|
  $Date$
 | 
						|
  created at: 04/01/01 23:36:57 JST
 | 
						|
 | 
						|
  Copyright (C) 2004-2006 Koichi Sasada
 | 
						|
 | 
						|
**********************************************************************/
 | 
						|
 | 
						|
#ifndef RUBY_COMPILE_H
 | 
						|
#define RUBY_COMPILE_H
 | 
						|
 | 
						|
 | 
						|
#if YARVDEBUG > CPDEBUG
 | 
						|
#undef  CPDEBUG
 | 
						|
#define CPDEBUG YARVDEBUG
 | 
						|
#endif
 | 
						|
 | 
						|
/*  */
 | 
						|
/**
 | 
						|
 * debug function(macro) interface depend on CPDEBUG
 | 
						|
 *
 | 
						|
 * debug level:
 | 
						|
 *  0: no debug output
 | 
						|
 *  1: show node type
 | 
						|
 *  2: show node important parameters
 | 
						|
 *  ...
 | 
						|
 *  5: show other parameters
 | 
						|
 * 10: show every AST array
 | 
						|
 */
 | 
						|
 | 
						|
#if 0
 | 
						|
#undef  CPDEBUG
 | 
						|
#define CPDEBUG 2
 | 
						|
#endif
 | 
						|
 | 
						|
#if CPDEBUG > 0
 | 
						|
 | 
						|
#define debugp(header, value)                   \
 | 
						|
  (ruby_debug_indent(0, CPDEBUG, gl_node_level * 2), \
 | 
						|
   ruby_debug_value(0, CPDEBUG, header, value))
 | 
						|
 | 
						|
#define debugi(header, id)                      \
 | 
						|
  (ruby_debug_indent(0, CPDEBUG, gl_node_level * 2), \
 | 
						|
   ruby_debug_id(0, CPDEBUG, header, id))
 | 
						|
 | 
						|
#define debugp_param(header, value)             \
 | 
						|
  (ruby_debug_indent(1, CPDEBUG, gl_node_level * 2), \
 | 
						|
   ruby_debug_value(1, CPDEBUG, header, value))
 | 
						|
 | 
						|
#define debugp_verbose(header, value)           \
 | 
						|
  (ruby_debug_indent(2, CPDEBUG, gl_node_level * 2), \
 | 
						|
   ruby_debug_value(2, CPDEBUG, header, value))
 | 
						|
 | 
						|
#define debugp_verbose_node(header, value)       \
 | 
						|
  (ruby_debug_indent(10, CPDEBUG, gl_node_level * 2), \
 | 
						|
   ruby_debug_value(10, CPDEBUG, header, value))
 | 
						|
 | 
						|
#define debug_nodeprint(node)                    \
 | 
						|
  ruby_debug_indent(-1, CPDEBUG, gl_node_level*2);    \
 | 
						|
  printf("node: %s (%d)\n", ruby_node_name(nd_type(node)), nd_line(node)); \
 | 
						|
  gl_node_level ++;
 | 
						|
 | 
						|
#define debug_nodeprint_close()  gl_node_level --;
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
static inline ID
 | 
						|
r_id(ID id)
 | 
						|
{
 | 
						|
    return id;
 | 
						|
}
 | 
						|
 | 
						|
static inline VALUE
 | 
						|
r_value(VALUE value)
 | 
						|
{
 | 
						|
    return value;
 | 
						|
}
 | 
						|
 | 
						|
#define debugi(header, id)                 r_id(id)
 | 
						|
#define debugp(header, value)              r_value(value)
 | 
						|
#define debugp_verbose(header, value)      r_value(value)
 | 
						|
#define debugp_verbose_node(header, value) r_value(value)
 | 
						|
#define debugp_param(header, value)        r_value(value)
 | 
						|
#define debug_nodeprint(node)
 | 
						|
#define debug_nodeprint_close()
 | 
						|
#endif
 | 
						|
 | 
						|
#if CPDEBUG > 1
 | 
						|
#define debugs ruby_debug_indent(-1, CPDEBUG, gl_node_level*2), printf
 | 
						|
#define debug_compile(msg, v) (ruby_debug_indent(-1, CPDEBUG, gl_node_level*2), printf("%s", msg), (v))
 | 
						|
#else
 | 
						|
#define debugs                             if(0)printf
 | 
						|
#define debug_compile(msg, v) (v)
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
/* create new label */
 | 
						|
#define NEW_LABEL(l) new_label_body(iseq, l)
 | 
						|
 | 
						|
#define iseq_filename(iseq) \
 | 
						|
  (((rb_iseq_t*)DATA_PTR(iseq))->filename)
 | 
						|
 | 
						|
#define NEW_ISEQVAL(node, name, type)       \
 | 
						|
  new_child_iseq(iseq, node, name, 0, type)
 | 
						|
 | 
						|
#define NEW_CHILD_ISEQVAL(node, name, type)       \
 | 
						|
  new_child_iseq(iseq, node, name, iseq->self, type)
 | 
						|
 | 
						|
#define NEW_SPECIAQL_BLOCK_ISEQVAL(iseq, sym) \
 | 
						|
  new_child_iseq(iseq, iseq->node, iseq->name, iseq->parent_iseq, iseq->type, sym)
 | 
						|
 | 
						|
/* add instructions */
 | 
						|
#define ADD_SEQ(seq1, seq2) \
 | 
						|
  APPEND_LIST(seq1, seq2)
 | 
						|
 | 
						|
/* add an instruction */
 | 
						|
#define ADD_INSN(seq, line, insn) \
 | 
						|
  ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line, BIN(insn), 0))
 | 
						|
 | 
						|
/* add an instruction with label operand */
 | 
						|
#define ADD_INSNL(seq, line, insn, label) \
 | 
						|
  ADD_ELEM(seq, (LINK_ELEMENT *) \
 | 
						|
           new_insn_body(iseq, line, BIN(insn), 1, (VALUE)label))
 | 
						|
 | 
						|
/* add an instruction with some operands (1, 2, 3, 5) */
 | 
						|
#define ADD_INSN1(seq, line, insn, op1) \
 | 
						|
  ADD_ELEM(seq, (LINK_ELEMENT *) \
 | 
						|
           new_insn_body(iseq, line, BIN(insn), 1, (VALUE)op1))
 | 
						|
 | 
						|
#define ADD_INSN2(seq, line, insn, op1, op2) \
 | 
						|
  ADD_ELEM(seq, (LINK_ELEMENT *) \
 | 
						|
           new_insn_body(iseq, line, BIN(insn), 2, (VALUE)op1, (VALUE)op2))
 | 
						|
 | 
						|
#define ADD_INSN3(seq, line, insn, op1, op2, op3) \
 | 
						|
  ADD_ELEM(seq, (LINK_ELEMENT *) \
 | 
						|
           new_insn_body(iseq, line, BIN(insn), 3, (VALUE)op1, (VALUE)op2, (VALUE)op3))
 | 
						|
 | 
						|
/* Specific Insn factory */
 | 
						|
#define ADD_SEND(seq, line, id, argc) \
 | 
						|
  ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(0))
 | 
						|
 | 
						|
#define ADD_CALL_RECEIVER(seq, line) \
 | 
						|
  ADD_INSN(seq, line, putnil)
 | 
						|
 | 
						|
#define ADD_CALL(seq, line, id, argc) \
 | 
						|
  ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(VM_CALL_FCALL_BIT))
 | 
						|
 | 
						|
#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \
 | 
						|
  ADD_SEND_R(seq, line, id, argc, block, (VALUE)INT2FIX(VM_CALL_FCALL_BIT))
 | 
						|
 | 
						|
#define ADD_SEND_R(seq, line, id, argc, block, flag) \
 | 
						|
  ADD_ELEM(seq, (LINK_ELEMENT *) \
 | 
						|
           new_insn_send(iseq, line, \
 | 
						|
                         (VALUE)id, (VALUE)argc, (VALUE)block, (VALUE)flag))
 | 
						|
 | 
						|
#define ADD_TRACE(seq, line, event) \
 | 
						|
  if (iseq->compile_data->option->trace_instruction) { \
 | 
						|
      ADD_INSN1(seq, line, trace, INT2FIX(event)); \
 | 
						|
  }
 | 
						|
 | 
						|
/* add label */
 | 
						|
#define ADD_LABEL(seq, label) \
 | 
						|
  ADD_ELEM(seq, (LINK_ELEMENT *)label)
 | 
						|
 | 
						|
#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc)		\
 | 
						|
    (rb_ary_push(iseq->compile_data->catch_table_ary,		\
 | 
						|
		 rb_ary_new3(5, type,				\
 | 
						|
			     (VALUE)(ls) | 1, (VALUE)(le) | 1,	\
 | 
						|
			     iseqv, (VALUE)(lc) | 1)))
 | 
						|
 | 
						|
/* compile node */
 | 
						|
#define COMPILE(anchor, desc, node) \
 | 
						|
  (debug_compile("== " desc "\n", \
 | 
						|
                 iseq_compile_each(iseq, anchor, node, 0)))
 | 
						|
 | 
						|
/* compile node, this node's value will be poped */
 | 
						|
#define COMPILE_POPED(anchor, desc, node)    \
 | 
						|
  (debug_compile("== " desc "\n", \
 | 
						|
                 iseq_compile_each(iseq, anchor, node, 1)))
 | 
						|
 | 
						|
/* compile node, which is poped when 'poped' is true */
 | 
						|
#define COMPILE_(anchor, desc, node, poped)  \
 | 
						|
  (debug_compile("== " desc "\n", \
 | 
						|
                 iseq_compile_each(iseq, anchor, node, poped)))
 | 
						|
 | 
						|
#define OPERAND_AT(insn, idx) \
 | 
						|
  (((INSN*)(insn))->operands[idx])
 | 
						|
 | 
						|
#define INSN_OF(insn) \
 | 
						|
  (((INSN*)(insn))->insn_id)
 | 
						|
 | 
						|
/* error */
 | 
						|
#define COMPILE_ERROR(strs)                        \
 | 
						|
{                                                  \
 | 
						|
  VALUE tmp = GET_THREAD()->errinfo;               \
 | 
						|
  if(CPDEBUG)rb_bug strs;                          \
 | 
						|
  GET_THREAD()->errinfo = iseq->compile_data->err_info;  \
 | 
						|
  rb_compile_error strs;                           \
 | 
						|
  iseq->compile_data->err_info = GET_THREAD()->errinfo; \
 | 
						|
  GET_THREAD()->errinfo = tmp;                     \
 | 
						|
  ret = 0;                                         \
 | 
						|
  break;                                           \
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#define COMPILE_OK 1
 | 
						|
#define COMPILE_NG 0
 | 
						|
 | 
						|
#define DECL_ANCHOR(name) \
 | 
						|
  LINK_ANCHOR  name##_body__ = {{0,}, &name##_body__.anchor}; \
 | 
						|
  LINK_ANCHOR *name = & name##_body__
 | 
						|
 | 
						|
#endif /* RUBY_COMPILE_H */
 |