bool gentrace_needed(ast_t* type) { switch(trace_type(type)) { case TRACE_NONE: assert(0); return false; case TRACE_PRIMITIVE: return false; case TRACE_TUPLE: { for(ast_t* child = ast_child(type); child != NULL; child = ast_sibling(child)) { if(gentrace_needed(child)) return true; } return false; } default: break; } return true; }
void gentrace(compile_t* c, LLVMValueRef ctx, LLVMValueRef value, ast_t* type) { switch(trace_type(type)) { case TRACE_NONE: assert(0); return; case TRACE_PRIMITIVE: return; case TRACE_MAYBE: trace_maybe(c, ctx, value, type); return; case TRACE_ACTOR: trace_actor(c, ctx, value); return; case TRACE_KNOWN_VAL: trace_known(c, ctx, value, type, true); return; case TRACE_UNKNOWN_VAL: trace_unknown(c, ctx, value, true); return; case TRACE_KNOWN: trace_known(c, ctx, value, type, false); return; case TRACE_UNKNOWN: trace_unknown(c, ctx, value, false); return; case TRACE_TAG: trace_tag(c, ctx, value); return; case TRACE_TAG_OR_ACTOR: trace_tag_or_actor(c, ctx, value); return; case TRACE_DYNAMIC: { LLVMBasicBlockRef next_block = codegen_block(c, ""); trace_dynamic(c, ctx, value, type, type, NULL, next_block); LLVMBuildBr(c->builder, next_block); LLVMPositionBuilderAtEnd(c->builder, next_block); return; } case TRACE_TUPLE: trace_tuple(c, ctx, value, type); return; } }
static void trace_dynamic_nominal(compile_t* c, LLVMValueRef ctx, LLVMValueRef object, ast_t* type, ast_t* orig, ast_t* tuple, LLVMBasicBlockRef next_block) { // Skip if a primitive. ast_t* def = (ast_t*)ast_data(type); if(ast_id(def) == TK_PRIMITIVE) return; // If it's not possible to use match or as to extract this type from the // original type, there's no need to trace as this type. if(tuple != NULL) { // We are a tuple element. Our type is in the correct position in the // tuple, everything else is TK_DONTCARE. if(is_matchtype(orig, tuple) != MATCHTYPE_ACCEPT) return; } else { // We aren't a tuple element. if(is_matchtype(orig, type) != MATCHTYPE_ACCEPT) return; } // We aren't always this type. We need to check dynamically. LLVMValueRef desc = gendesc_fetch(c, object); LLVMValueRef test = gendesc_isnominal(c, desc, type); LLVMBasicBlockRef is_true = codegen_block(c, ""); LLVMBasicBlockRef is_false = codegen_block(c, ""); LLVMBuildCondBr(c->builder, test, is_true, is_false); // Trace as this type. LLVMPositionBuilderAtEnd(c->builder, is_true); gentrace(c, ctx, object, type); // If we have traced as known, unknown or actor, we're done with this // element. Otherwise, continue tracing this as if the match had been // unsuccessful. switch(trace_type(type)) { case TRACE_KNOWN: case TRACE_UNKNOWN: case TRACE_KNOWN_VAL: case TRACE_UNKNOWN_VAL: case TRACE_ACTOR: LLVMBuildBr(c->builder, next_block); break; default: LLVMBuildBr(c->builder, is_false); break; } // Carry on, whether we have traced or not. LLVMPositionBuilderAtEnd(c->builder, is_false); }
static trace_t trace_type_union(ast_t* type) { trace_t trace = TRACE_NONE; for(ast_t* child = ast_child(type); child != NULL; child = ast_sibling(child)) { trace_t t = trace_type(child); switch(trace) { case TRACE_NONE: trace = t; break; case TRACE_MAYBE: // Can't be in a union. pony_assert(0); return TRACE_NONE; case TRACE_MACHINE_WORD: trace = trace_union_machine_word(t); break; case TRACE_PRIMITIVE: trace = trace_union_primitive(t); break; case TRACE_MUT_KNOWN: case TRACE_MUT_UNKNOWN: trace = trace_union_mut(t); break; case TRACE_VAL_KNOWN: case TRACE_VAL_UNKNOWN: trace = trace_union_val(t); break; case TRACE_TAG_KNOWN: case TRACE_TAG_UNKNOWN: trace = trace_union_tag(t); break; case TRACE_DYNAMIC: case TRACE_TUPLE: return TRACE_DYNAMIC; case TRACE_STATIC: // Can't happen here. pony_assert(0); return TRACE_DYNAMIC; } } return trace; }
void gentrace(compile_t* c, LLVMValueRef ctx, LLVMValueRef value, ast_t* type) { switch(trace_type(type)) { case TRACE_NONE: assert(0); return; case TRACE_MACHINE_WORD: case TRACE_PRIMITIVE: return; case TRACE_MAYBE: trace_maybe(c, ctx, value, type); return; case TRACE_VAL_KNOWN: trace_known(c, ctx, value, type, PONY_TRACE_IMMUTABLE); return; case TRACE_VAL_UNKNOWN: trace_unknown(c, ctx, value, PONY_TRACE_IMMUTABLE); return; case TRACE_MUT_KNOWN: trace_known(c, ctx, value, type, PONY_TRACE_MUTABLE); return; case TRACE_MUT_UNKNOWN: trace_unknown(c, ctx, value, PONY_TRACE_MUTABLE); return; case TRACE_TAG_KNOWN: trace_known(c, ctx, value, type, PONY_TRACE_OPAQUE); return; case TRACE_TAG_UNKNOWN: trace_unknown(c, ctx, value, PONY_TRACE_OPAQUE); return; case TRACE_DYNAMIC: { LLVMBasicBlockRef next_block = codegen_block(c, ""); trace_dynamic(c, ctx, value, type, type, NULL, next_block); LLVMBuildBr(c->builder, next_block); LLVMPositionBuilderAtEnd(c->builder, next_block); return; } case TRACE_TUPLE: trace_tuple(c, ctx, value, type); return; } }
static trace_t trace_type_isect(ast_t* type) { trace_t trace = TRACE_DYNAMIC; for(ast_t* child = ast_child(type); child != NULL; child = ast_sibling(child)) { trace_t t = trace_type(child); switch(t) { case TRACE_NONE: case TRACE_MAYBE: // Can't be in an isect. pony_assert(0); return TRACE_NONE; case TRACE_PRIMITIVE: return TRACE_PRIMITIVE; case TRACE_MACHINE_WORD: case TRACE_VAL_KNOWN: case TRACE_VAL_UNKNOWN: trace = TRACE_VAL_UNKNOWN; break; case TRACE_MUT_KNOWN: case TRACE_MUT_UNKNOWN: if(trace != TRACE_VAL_UNKNOWN) trace = TRACE_MUT_UNKNOWN; break; case TRACE_TAG_KNOWN: case TRACE_TAG_UNKNOWN: if((trace != TRACE_MUT_UNKNOWN) && (trace != TRACE_VAL_UNKNOWN)) trace = TRACE_TAG_UNKNOWN; break; case TRACE_DYNAMIC: case TRACE_TUPLE: break; case TRACE_STATIC: // Can't happen here. pony_assert(0); break; } } return trace; }
static trace_t trace_type_union(ast_t* type) { trace_t trace = TRACE_NONE; for(ast_t* child = ast_child(type); child != NULL; child = ast_sibling(child)) { trace = trace_type_combine(trace, trace_type(child)); } return trace; }
bool gentrace_needed(compile_t* c, ast_t* src_type, ast_t* dst_type) { switch(trace_type(src_type)) { case TRACE_NONE: pony_assert(0); return false; case TRACE_MACHINE_WORD: { if(ast_id(dst_type) == TK_NOMINAL) { ast_t* def = (ast_t*)ast_data(dst_type); if(ast_id(def) == TK_PRIMITIVE) return false; } return true; } case TRACE_PRIMITIVE: return false; case TRACE_TUPLE: { if(ast_id(dst_type) == TK_TUPLETYPE) { ast_t* src_child = ast_child(src_type); ast_t* dst_child = ast_child(dst_type); while((src_child != NULL) && (dst_child != NULL)) { if(gentrace_needed(c, src_child, dst_child)) return true; src_child = ast_sibling(src_child); dst_child = ast_sibling(dst_child); } pony_assert(src_child == NULL && dst_child == NULL); } else { // This is a boxed tuple. We'll have to trace the box anyway. return true; } return false; } default: break; } return true; }
static trace_t trace_type_isect(ast_t* type) { trace_t trace = TRACE_DYNAMIC; for(ast_t* child = ast_child(type); child != NULL; child = ast_sibling(child)) { trace_t t = trace_type(child); switch(t) { case TRACE_NONE: case TRACE_MAYBE: // Maybe, any refcap. // Can't be in an isect. assert(0); return TRACE_NONE; case TRACE_PRIMITIVE: // Primitive, any refcap. case TRACE_ACTOR: // Actor, tag. case TRACE_KNOWN_VAL: case TRACE_KNOWN: // Class or struct, not tag. return t; case TRACE_UNKNOWN_VAL: case TRACE_UNKNOWN: // Trait or interface, not tag. case TRACE_TAG: // Class or struct, tag. case TRACE_TAG_OR_ACTOR: // Trait or interface, tag. if(trace > t) trace = t; break; case TRACE_DYNAMIC: case TRACE_TUPLE: break; } } return trace; }
static void trace_dynamic_tuple(compile_t* c, LLVMValueRef ctx, LLVMValueRef ptr, LLVMValueRef desc, ast_t* type, ast_t* orig, ast_t* tuple) { // Build a "don't care" type of our cardinality. size_t cardinality = ast_childcount(type); ast_t* dontcare = ast_from(type, TK_TUPLETYPE); for(size_t i = 0; i < cardinality; i++) ast_append(dontcare, ast_from(type, TK_DONTCARE)); // Replace our type in the tuple type with the "don't care" type. bool in_tuple = (tuple != NULL); if(in_tuple) ast_swap(type, dontcare); else tuple = dontcare; // If the original type is a subtype of the test type, then we are always // the correct cardinality. Otherwise, we need to dynamically check // cardinality. LLVMBasicBlockRef is_true = codegen_block(c, ""); LLVMBasicBlockRef is_false = codegen_block(c, ""); if(!is_subtype(orig, tuple, NULL)) { LLVMValueRef dynamic_count = gendesc_fieldcount(c, desc); LLVMValueRef static_count = LLVMConstInt(c->i32, cardinality, false); LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntEQ, static_count, dynamic_count, ""); // Skip if not the right cardinality. LLVMBuildCondBr(c->builder, test, is_true, is_false); } else { LLVMBuildBr(c->builder, is_true); } LLVMPositionBuilderAtEnd(c->builder, is_true); size_t index = 0; ast_t* child = ast_child(type); ast_t* dc_child = ast_child(dontcare); while(child != NULL) { switch(trace_type(child)) { case TRACE_PRIMITIVE: // Skip this element. break; case TRACE_ACTOR: case TRACE_KNOWN: case TRACE_UNKNOWN: case TRACE_KNOWN_VAL: case TRACE_UNKNOWN_VAL: case TRACE_TAG: case TRACE_TAG_OR_ACTOR: case TRACE_DYNAMIC: { // If we are (A, B), turn (_, _) into (A, _). ast_t* swap = ast_dup(child); ast_swap(dc_child, swap); // Create a next block. LLVMBasicBlockRef next_block = codegen_block(c, ""); // Load the object from the tuple field. LLVMValueRef field_info = gendesc_fieldinfo(c, desc, index); LLVMValueRef object = gendesc_fieldload(c, ptr, field_info); // Trace dynamic, even if the tuple thinks the field isn't dynamic. trace_dynamic(c, ctx, object, swap, orig, tuple, next_block); // Continue into the next block. LLVMBuildBr(c->builder, next_block); LLVMPositionBuilderAtEnd(c->builder, next_block); // Restore (A, _) to (_, _). ast_swap(swap, dc_child); ast_free_unattached(swap); break; } case TRACE_TUPLE: { // If we are (A, B), turn (_, _) into (A, _). ast_t* swap = ast_dup(child); ast_swap(dc_child, swap); // Get a pointer to the unboxed tuple and it's descriptor. LLVMValueRef field_info = gendesc_fieldinfo(c, desc, index); LLVMValueRef field_ptr = gendesc_fieldptr(c, ptr, field_info); LLVMValueRef field_desc = gendesc_fielddesc(c, field_info); // Trace the tuple dynamically. trace_dynamic_tuple(c, ctx, field_ptr, field_desc, swap, orig, tuple); // Restore (A, _) to (_, _). ast_swap(swap, dc_child); ast_free_unattached(swap); break; } default: {} } index++; child = ast_sibling(child); dc_child = ast_sibling(dc_child); } // Restore the tuple type. if(in_tuple) ast_swap(dontcare, type); ast_free_unattached(dontcare); // Continue with other possible tracings. LLVMBuildBr(c->builder, is_false); LLVMPositionBuilderAtEnd(c->builder, is_false); }
/*{ ** Name: rdf_trace - Call RDF trace operation. ** ** External call format: status = rdf_trace(&db_debug_cb) ** ** Description: ** This function is the standard entry point to RDF for setting and ** clearing tracepoints(the "set trace point" command). Because RDF ** is a service facility, trace point for RDF can only be set on ** the server basis. There is no session level trace point. ** Db_debug_cb is the tracing control block that contains the trace ** flag information. ** ** See file <rdftrace.h> for a description of all possible ** RDF trace points. ** ** Inputs: ** debug_cb Pointer to a DB_DEBUG_CB ** .db_trswitch What operation to perform ** DB_TR_NOCHANGE None ** DB_TR_ON Turn on a tracepoint ** DB_TR_OFF Turn off a tracepoint ** .db_trace_point Trace point ID(the flag number) ** .db_value_count The number of values specified in ** the value array ** .db_vals[2] Optional values, to be interpreted ** differently for each tracepoint ** Outputs: ** none ** ** Returns: ** E_DB_OK Function completed normally. ** E_DB_ERROR Function failed due to error by caller; ** E_DB_FATAL Function failed due to some internal ** problem; ** Exceptions: ** none ** ** Side Effects: ** The trace vector in the server control block of RDF will be updated ** to contain the trace information. The trace information will be persist ** throughout the life of the server. ** ** History: ** 15-apr-86 (ac) ** written ** 02-mar-87 (puree) ** replace global server control block with global pointer. ** 14-dec-1989 (teg) ** modify to go get svcb from SCF instead of using a global pointer ** to it. ** 16-jul-92 (teresa) ** prototypes ** 16-sep-92 (teresa) ** implement trace points rd3 and rd4 to clear ldbdesc cache. ** 22-apr-94 (teresa) ** added trace points rd11 and rd12 to dump memory statistics or all ** statistics. This is an action trace point -- the dump occurs when ** the trace point is selected rather than during query execution. ** 20-nov-2007 (thaju02) ** If trace point RD0022/RDU_CHECKSUM specified, invalidate ** relcache. Entries need rdr_checksum to be calc/init'd ** otherwise E_RD010D errors may be reported. (B119499) */ DB_STATUS rdf_trace(DB_DEBUG_CB *debug_cb) { i4 flag; i4 firstval; i4 secondval; DB_STATUS status; i4 trace_scope; /* assure flag is legal */ flag = debug_cb->db_trace_point; if (flag >= RDF_NB) { return (E_DB_ERROR); } /* There can be UP TO two values, but maybe they weren't given */ firstval = (debug_cb->db_value_count > 0) ? debug_cb->db_vals[0] : 0L; secondval = (debug_cb->db_value_count > 1) ? debug_cb->db_vals[1] : 0L; /* see if this is an action trace. Action traces require an immediate ** action rather than turning trace flags on/off/etc. */ if ( (debug_cb->db_trswitch==DB_TR_ON) && (flag <= RD_ACT_MAX) ) { /* see which action is requested. Not all actions are implemented ** yet, so its possible that this call may become a no-opt */ switch (flag) { case RD0001: case RD0002: case RD0003: case RD0004: case RD0005: case RD0010: status=rdt_clear_cache(flag); if (DB_FAILURE_MACRO(status)) { return(E_DB_ERROR); } break; case RD0011: /* dump memory info. This trace is used by tech support when ** debugging out of memory errors. */ TRdisplay("\n...............................................\n"); TRdisplay("RDF Cache Memory Available: %d\n",Rdi_svcb->rdv_memleft); TRdisplay("RDF memory cache size : %d\n", Rdi_svcb->rdv_pool_size); TRdisplay("Max number of objects allowed on Cache:\n"); TRdisplay(" RELcache: %d, QTREE Cache: %d, \n", Rdi_svcb->rdv_cnt0_rdesc, Rdi_svcb->rdv_cnt1_qtree); TRdisplay(" LDBDesc Cache %d, DEFAULTS cache: %d\n", Rdi_svcb->rdv_cnt2_dist, Rdi_svcb->rdv_cnt3_default); TRdisplay("Hashids:\n"); TRdisplay(" RELcache: %d, QTREE Cache: %d, \n", Rdi_svcb->rdv_rdesc_hashid, Rdi_svcb->rdv_qtree_hashid); TRdisplay(" LDBDesc Cache %d, DEFAULTS cache: %d\n", Rdi_svcb->rdv_dist_hashid, Rdi_svcb->rdv_def_hashid); TRdisplay("...............................................\n"); break; case RD0012: /* dump all of the RDF statistics */ rdf_report ( &Rdi_svcb->rdvstat ); break; default: break; } } else { /* ** determine if this is a session wide trace or a server wide trace ** and process accordingly */ trace_scope = trace_type(flag); if (trace_scope == SVR_WIDE_TRACE) { /* turn trace on in svcb ** ** Three possible actions: Turn on flag, turn it off, or do nothing. */ switch (debug_cb->db_trswitch) { case DB_TR_ON: if ((flag == RD0022) && !(ult_check_macro(&Rdi_svcb->rdf_trace, flag, &firstval, &secondval))) { /* setting RDU_CHECKSUM */ RDF_GLOBAL global; RDF_CB rdfcb; RDI_FCB fcb; global.rdfcb = &rdfcb; rdfcb.rdf_rb.rdr_fcb = (PTR)&fcb; rdfcb.rdf_info_blk = NULL; rdfcb.rdf_rb.rdr_db_id = NULL; rdfcb.rdf_rb.rdr_types_mask = 0; rdfcb.rdf_rb.rdr_2types_mask = 0; CSget_sid(&rdfcb.rdf_rb.rdr_session_id); fcb.rdi_fac_id = DB_RDF_ID; status = rdf_invalidate(&global, &rdfcb); if (DB_FAILURE_MACRO(status)) return(E_DB_ERROR); } ult_set_macro(&Rdi_svcb->rdf_trace, flag, firstval, secondval); break; case DB_TR_OFF: ult_clear_macro(&Rdi_svcb->rdf_trace, flag); break; case DB_TR_NOCHANGE: /* Do nothing */ break; default: return (E_DB_ERROR); }; } else { CS_SID sid; RDF_SESS_CB *rdf_sess_cb; /* ** this trace point is session specific, so use the session control ** block for this trace point. */ CSget_sid(&sid); rdf_sess_cb = GET_RDF_SESSCB(sid); /* ** Three possible actions: Turn on flag, turn it off, or do nothing. */ switch (debug_cb->db_trswitch) { case DB_TR_ON: ult_set_macro(&rdf_sess_cb->rds_strace, flag, firstval, secondval); break; case DB_TR_OFF: ult_clear_macro(&rdf_sess_cb->rds_strace, flag); break; case DB_TR_NOCHANGE: /* Do nothing */ break; default: return (E_DB_ERROR); } } } return (E_DB_OK); }
void gentrace(compile_t* c, LLVMValueRef ctx, LLVMValueRef src_value, LLVMValueRef dst_value, ast_t* src_type, ast_t* dst_type) { trace_t trace_method = trace_type(src_type); if(src_type != dst_type) { trace_method = trace_type_dst_cap(trace_method, trace_type(dst_type), src_type); } switch(trace_method) { case TRACE_NONE: pony_assert(0); return; case TRACE_MACHINE_WORD: { bool boxed = true; if(ast_id(dst_type) == TK_NOMINAL) { ast_t* def = (ast_t*)ast_data(dst_type); if(ast_id(def) == TK_PRIMITIVE) boxed = false; } if(boxed) trace_known(c, ctx, dst_value, src_type, PONY_TRACE_IMMUTABLE); return; } case TRACE_PRIMITIVE: return; case TRACE_MAYBE: trace_maybe(c, ctx, dst_value, src_type); return; case TRACE_VAL_KNOWN: trace_known(c, ctx, dst_value, src_type, PONY_TRACE_IMMUTABLE); return; case TRACE_VAL_UNKNOWN: trace_unknown(c, ctx, dst_value, PONY_TRACE_IMMUTABLE); return; case TRACE_MUT_KNOWN: trace_known(c, ctx, dst_value, src_type, PONY_TRACE_MUTABLE); return; case TRACE_MUT_UNKNOWN: trace_unknown(c, ctx, dst_value, PONY_TRACE_MUTABLE); return; case TRACE_TAG_KNOWN: trace_known(c, ctx, dst_value, src_type, PONY_TRACE_OPAQUE); return; case TRACE_TAG_UNKNOWN: trace_unknown(c, ctx, dst_value, PONY_TRACE_OPAQUE); return; case TRACE_STATIC: trace_static(c, ctx, dst_value, src_type, dst_type); return; case TRACE_DYNAMIC: { LLVMBasicBlockRef next_block = codegen_block(c, ""); trace_dynamic(c, ctx, dst_value, src_type, dst_type, NULL, next_block); LLVMBuildBr(c->builder, next_block); LLVMPositionBuilderAtEnd(c->builder, next_block); return; } case TRACE_TUPLE: trace_tuple(c, ctx, src_value, dst_value, src_type, dst_type); return; } }