int main(int argc, char ** argv) { char op; char mStr[1024]; matrix ans, m1, m2; int sc = 0; if(argc > 1){ op = getOp(argv[1]); } else { printf("Which operation: "); op = getOp(NULL); } printf("First matrix:\n"); scanf("%s", mStr); m1 = MatrixInit(mStr); if(op == 'a' || op == 's' || op == 'm'){ printf("Second matrix:\n"); scanf("%s", mStr); m2 = MatrixInit(mStr); } else if(op == 'c') { printf("Scalar multiple:\n"); scanf("%d", &sc); } switch(op){ case 'a': ans = MatrixAdd(m1, m2); break; case 's': ans = MatrixSub(m1, m2); break; case 'm': ans = MatrixMul(m1, m2); break; case 'i': ans = MatrixInv(m1); break; case 'c': ans = MatrixSMul(m1, i2f(sc)); break; default: printf("Something went very wrong.\n"); return 1; } printf("Answer:\n"); MatrixPrint(ans); MatrixFree(m1); MatrixFree(ans); if(op == 'a' || op == 's' || op == 'm'){ MatrixFree(m2); } return 0; }
ExprTree * getTree() { int lex; int opcode; ExprTree *left; ExprTree *right; ExprTree *node; left = getOp(&lex); for (;;) { if ( lex == 0 || lex == 2 ) { if ( lex == 2 ) Bc--; break; } if (lex != 3 && lex != 4 ) { Err = 1; break; } opcode = lex; right = getOp(&lex); node = newNode(); if (Err) break; node->left = left; node->right = right; node->opcode = opcode; left = node; } return left; }
void Move::checkOp(string toTest) { Parse_Strings p; if (toTest.find(getOp()) != string::npos) { vector<string> use(2); use = p.split_string(toTest, getOp()); moveTo(use[0], use[1]); p.test(p.getCheck()); } }
TEST(IfElseBuilding, CanBuildWithIfAsFirstParameter) { spOp ifOp(new If(getOp("drop"))); IfElse ifElseOp(ifOp, getOp("swap")); values.push(4); values.push(9); values.push(1); ifElseOp.invoke(values); LONGS_EQUAL(4, values.top()); }
int main(int argc, char** argv) { int i,j,tem, flag=0, res[2]; char c, stem[20]; ++argv; while(*argv != NULL) { flag=0; c=*argv[0]; switch(c) { case '+': getOp(res); /* printf("\nAdd ");*/ push(res[0]+res[1]); break; case '-': /* printf("\nSub ");*/ getOp(res); push(res[0]-res[1]); break; case 'x': /* printf("\nMul ");*/ getOp(res); push(res[0]*res[1]); break; case '/': /* printf("\nDivide ");*/ getOp(res); push(res[0]/res[1]); break; default: /* printf("\nDefault ");*/ flag=1; break; } if(flag) push(atoi(*argv)); /* printf("\nTop is %d ",top);*/ /* printf("\nEle\n");*/ /* for(i=0;i<top;i++)*/ /* printf(" %d ",stk[i]);*/ ++argv; } if(!flag) printf("%d\n",pop()); }
void WorkloadGenerator::addConstraint(simple_filter *filter, set<int> &alreadyConsidered) { int nameRand = 0; bool isNew; do { if (paramHandler->getZipfNames()) nameRand = getZipf(1, paramHandler->getNumNames())-1; else nameRand = rand()%paramHandler->getNumNames(); // check if this name has already been used in this filter if (alreadyConsidered.find(nameRand)==alreadyConsidered.end()) isNew=true; else isNew=false; } while(!isNew); alreadyConsidered.insert(nameRand); siena::type_id type = getType(nameRand); siena::operator_id opId = getOp(type); siena::string_t name = names[nameRand]; simple_op_value *opValue; if (type==siena::int_id) { siena::int_t intVal = rand()%paramHandler->getNumAttVal(); opValue = new simple_op_value(opId, intVal); } else { int stringValRand = rand()%paramHandler->getNumAttVal(); siena::string_t stringVal = stringValues[stringValRand]; opValue = new simple_op_value(opId, stringVal); } filter->add(name, opValue); }
void interpOne(IRGS& env, folly::Optional<Type> outType, int popped, int pushed, InterpOneData& idata) { auto const unit = curUnit(env); spillStack(env); env.irb->exceptionStackBoundary(); auto const op = unit->getOp(bcOff(env)); idata.bcOff = bcOff(env); idata.cellsPopped = popped; idata.cellsPushed = pushed; idata.opcode = op; gen( env, opcodeChangesPC(idata.opcode) ? InterpOneCF : InterpOne, outType, idata, sp(env), fp(env) ); assertx(env.irb->stackDeficit() == 0); }
void InstArithmetic::dump(const Cfg *Func) const { Ostream &Str = Func->getContext()->getStrDump(); dumpDest(Func); Str << " = " << InstArithmeticAttributes[getOp()].DisplayString << " " << getDest()->getType() << " "; dumpSources(Func); }
AutoGetCollectionForRead::~AutoGetCollectionForRead() { // Report time spent in read lock auto currentOp = CurOp::get(_txn); Top::get(_txn->getClient()->getServiceContext()) .record(currentOp->getNS(), currentOp->getOp(), -1, // "read locked" _timer.micros(), currentOp->isCommand()); }
/** * The main function that runs when program is being run */ int main() { MatrixOperation selectedOp = getOp(); string errorStr = selectedOp._opHandler(selectedOp); if (errorStr != EMPTY_STRING) { // If operation failed, print the error message. cout << "Error: " << selectedOp._name << " failed - " << errorStr << "." << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
OldClientContext::~OldClientContext() { // Lock must still be held invariant(_txn->lockState()->isLocked()); auto currentOp = CurOp::get(_txn); Top::get(_txn->getClient()->getServiceContext()) .record(currentOp->getNS(), currentOp->getOp(), _txn->lockState()->isWriteLocked() ? 1 : -1, _timer.micros(), currentOp->isCommand()); }
char *TKGetNextToken( TokenizerT * tk ) { if(tk->str[tk->pindex] == ' ' || tk->str[tk->pindex] == '\t' || tk->str[tk->pindex] == '\v' || tk->str[tk->pindex] == '\f' || tk->str[tk->pindex] == '\n' || tk->str[tk->pindex] == '\r'){ tk->pindex++; return NULL; } int charIndex = 0; char *tmp = (char*)malloc(sizeof(char)*strlen(tk->str)); if(isalnum(tk->str[tk->pindex])){ if(isalpha(tk->str[tk->pindex])){ //checks for word tmp[charIndex] = tk->str[tk->pindex]; charIndex++; tk->pindex++; tmp = getWord(tk, tmp, charIndex); return tmp; }else{ if(tk->str[tk->pindex] == '0' && isalnum(tk->str[tk->pindex + 1])){ //checks for hex if(tk->str[tk->pindex + 1] == 'x' || tk->str[tk->pindex + 1] == 'X'){ if(isdigit(tk->str[tk->pindex + 2]) || tk->str[tk->pindex + 2] == 'a' || tk->str[tk->pindex + 2] == 'b' || tk->str[tk->pindex + 2] == 'c' || tk->str[tk->pindex + 2] == 'd' || tk->str[tk->pindex + 2] == 'e' || tk->str[tk->pindex + 2] == 'f'){ tmp[charIndex] = tk->str[tk->pindex]; charIndex++; tk->pindex++; tmp = getHex(tk, tmp, charIndex); return tmp; } }else if(tk->str[tk->pindex + 1] == '0' || tk->str[tk->pindex + 1] == '1' || tk->str[tk->pindex + 1] == '2' || tk->str[tk->pindex + 1] == '3' || tk->str[tk->pindex + 1] == '4' || tk->str[tk->pindex + 1] == '5' || tk->str[tk->pindex + 1] == '6' || tk->str[tk->pindex + 1] == '7'){ // checks for octal tmp[charIndex] = tk->str[tk->pindex]; charIndex++; tk->pindex++; tmp = getOctal(tk, tmp, charIndex); return tmp; } } } //if not sends to number(decimal or floats) tmp[charIndex] = tk->str[tk->pindex]; charIndex++; tk->pindex++; tmp = getNumber(tk, tmp, charIndex); return tmp; }else{ // C-Operators tmp = getOp(tk, tmp, charIndex); } return tmp; }
void SXNode::canInline(std::map<const SXNode*, int>& nodeind) const { // Add or mark node in map std::map<const SXNode*, int>::iterator it=nodeind.find(this); if (it==nodeind.end()) { // First time encountered, mark inlined nodeind.insert(it, make_pair(this, 0)); // Handle dependencies with recursion for (int i=0; i<ndep(); ++i) { dep(i)->canInline(nodeind); } } else if (it->second==0 && getOp()!=OP_PARAMETER) { // Node encountered before, do not inline (except if symbolic primitive) it->second = -1; } }
int main(int argc, char const *argv[]) { /* code */ int tab[max]; int opr ; if (argv[1] == NULL) opr =1; else opr = getOp(argv[1]); for (int i=0;i<max;i++) { tab[i] = i; } save(createLine(opr,tab,op(opr,tab)),tab); printf("\nDone\n\n"); return 0; }
void abstract_interpreter_method_info::init(byteVectorOop c, objVectorOop l) { codes_object = c; literals_object = l; codes = (unsigned char*)codes_object->bytes(); literals = literals_object->objs(); length_codes = codes_object->length(); length_literals = literals_object->length(); if (codes_object->length() == 0) instruction_set = TWENTIETH_CENTURY_INSTRUCTION_SET; else { char first_code = codes_object->byte_at(0); instruction_set = getOp((u_char)first_code) == INSTRUCTION_SET_SELECTION_CODE ? (InstructionSetKind) getIndex(first_code) : TWENTIETH_CENTURY_INSTRUCTION_SET; assert( instruction_set == TWENTIETH_CENTURY_INSTRUCTION_SET || 0 <= instruction_set && instruction_set <= LAST_INSTRUCTION_SET, "bad instruction set"); } }
void abstract_interpreter_method_info::init(ByteVectorOop c, ObjVectorOop l) { codes_object = c; literals_object = l; codes = (unsigned char*) ByteVectorLayout().for_AddressOfIndexableAt(codes_object, 0); literals = ObjVectorLayout().for_AddressOfIndexableAt(literals_object, 0); length_codes = ByteVectorLayout().indexableSizeOf( codes_object); length_literals = ObjVectorLayout().indexableSizeOf(literals_object); if (length_codes == 0) { instruction_set = TWENTIETH_CENTURY_INSTRUCTION_SET; } else { char first_code = ByteVectorLayout().for_IndexableAt(codes_object, 0); instruction_set = getOp((u_char)first_code) == INSTRUCTION_SET_SELECTION_CODE ? (InstructionSetKind) getIndex(first_code) : TWENTIETH_CENTURY_INSTRUCTION_SET; always_assert( instruction_set == TWENTIETH_CENTURY_INSTRUCTION_SET || 0 <= instruction_set && instruction_set <= LAST_INSTRUCTION_SET, "bad instruction set"); } }
int main(int argc, char** argv) { int i; struct symbol s; if (argc < 2) { printf ("Expected at least one argument...\n"); return 0; } for (i=0; i <= strlen(argv[1]); i++) { s = getOp(argv[1][i]); if (s.type == NUMBER) printf ("Integer: %d\n", s.ival); if (s.type == OPERATOR) printf ("Operator: '%c'\n", s.cval); if (s.type == FLOAT) printf ("Float: %f\n",s.fval); } return 0; }
void interpOne(IRGS& env, folly::Optional<Type> outType, int popped, int pushed, InterpOneData& idata) { auto const unit = curUnit(env); auto const op = unit->getOp(bcOff(env)); idata.bcOff = bcOff(env); idata.cellsPopped = popped; idata.cellsPushed = pushed; idata.opcode = op; gen( env, opcodeChangesPC(idata.opcode) ? InterpOneCF : InterpOne, outType, idata, sp(env), fp(env) ); }
//processes a statement void processString(char *str){ Var *tmp = variables, *var1, *var2; int varLen, opLen, isNumeric, var3; char *lValue, *op, *rValue; lValue = getVarName(str); varLen = strlen(lValue); op = getOp(str, varLen); opLen = strlen(op); rValue = getRValue(str, varLen, opLen); var1 = getVar(lValue); isNumeric = isnumeric(rValue); if(1 == isNumeric){ var3 = atoi(rValue); } else{ var2 = getVar(rValue); var3 = var2->value; } switch(op[0]){ case '+': var1->value+=var3; break; case '-': var1->value-=var3; break; case '*': var1->value*=var3; break; case '/': var1->value/=var3; break; } }
/* fixa diverse opmoden ** postinc och predec ** minne,minne */ static void doOpModes(void) { INPUT *in; OPERAND op1,op2,rop1,rop2; /* 1. l�s instruktion */ in=READER(); if(!in) return; switch(in->type) { case IS_INSTR: /* Eleminera PC relativt om m�jligt */ in->data.instr.op1=fixPC(in->data.instr.op1); in->data.instr.op2=fixPC(in->data.instr.op2); op1=in->data.instr.op1; op2=in->data.instr.op2; /* 2. pre op 1 */ fixPre(in,op1); /* 3. get op 1 */ op1=fixIndex(in,op1); rop1=getOp(in,op1); /* 4. post op 1 */ fixPost(in,op1); /* 5. pre op 2 */ fixPre(in,op2); /* 6. instruktion */ rop2=cleanOp(op2); rop2=fixIndex(in,rop2); genInstr(in,rop1,rop2); /* 7. post op 2 */ fixPost(in,op2); break; default: output(in); break; } }
bool InstArithmetic::isCommutative() const { return InstArithmeticAttributes[getOp()].IsCommutative; }
/* * Subtract From Pointer Immediate * Pn <- Pn - XX, X: {0 .. 9}. * * 02 Pn XX * * Pointer decremented by integer XX */ void o2(Vm* vm){ setPointer(vm, charToInt(vm->IR[3]), getPointer(vm, charToInt(vm->IR[3])) - opToInt(getOp(4,vm->IR))); }
oop_t ActivationObj::loop(oop_t this_activation) { The::set_active_context( this_activation, this); DECLARE_STACK; smi bci = get_pc_quickly(io); ActivationMapObj* m_addr = map_addr(); oop_t codes_oop = m_addr->codes(); ByteVectorObj* codes_addr = ByteVectorObj::from(codes_oop); char* codes = codes_addr->bytes(); fint codes_length = codes_addr->indexableSize(); oop_t literals = m_addr->literals(); ObjVectorObj* literals_addr = ObjVectorObj::from(literals); fint literals_io = literals_addr->indexableOrigin(); fint index = 0, temp_index; # define UC_index ((temp_index = index << INDEXWIDTH), (index = 0), temp_index | bc_index) bool undirected_resend = false; # define UC_undirected_resend (undirected_resend ? (undirected_resend = false, true) : false) fint lexical_level = 0; # define use_lit (literals_addr->read_oop(literals_io + UC_index)) oop_t delegatee = 0, temp_del; # define UC_del ((temp_del = delegatee), (delegatee = 0), temp_del) fint arg_count = 0, temp_arg_count; # define UC_arg_count ((temp_arg_count = arg_count), (arg_count = 0), temp_arg_count) fint temp_bci; // for process pre-emption, stop on backward branches // todo optimize should probably just stop every 10 or 100 backward branches, or even just every N bytecodes # define set_bci(bci_oop) (temp_bci = value_of_smiOop(assert_smi(bci_oop)), stop = temp_bci < bci, bci = temp_bci) oop_t self = get_self_quickly(io); oop_t rcvr = get_rcvr_quickly(io); for ( bool stop = false; !stop; ) { if (bci >= codes_length) { oop_t r = pop(); oop_t s = get_sender_quickly(io); if (s != NULL) // it'll be NULL if we're returning from the start method ActivationObj::from(s)->remote_push(r); // todo optimize time slow; quits this routine just for a return -- dmu 1/06 return s; } unsigned char bc = codes[bci++]; ByteCodeKind kind = getOp(bc); fint bc_index = getIndex(bc); // printf("interpreting a bytecode in activationMap %i, bc is %i, kind is %i, bc_index is %i\n", map_oop(), bc, kind, bc_index); switch (kind) { default: fatal("unknown kind of bytecode"); break; case INDEX_CODE: index = UC_index; break; case LEXICAL_LEVEL_CODE: lexical_level = UC_index; break; case ARGUMENT_COUNT_CODE: arg_count = UC_index; break; case READ_LOCAL_CODE: push(local_obj_addr(lexical_level)-> read_arg_or_local(UC_index) ); lexical_level = 0; break; case WRITE_LOCAL_CODE: local_obj_addr(lexical_level)->write_arg_or_local(UC_index, pop()); lexical_level = 0; push(self); break; case BRANCH_CODE: set_bci(use_lit); break; case BRANCH_TRUE_CODE: if ( pop() == The::oop_of(The:: true_object)) set_bci(use_lit); else index = 0; break; case BRANCH_FALSE_CODE: if ( pop() == The::oop_of(The::false_object)) set_bci(use_lit); else index = 0; break; case BRANCH_INDEXED_CODE: { ObjVectorObj* branch_vector_addr = ObjVectorObj::from(assert_objVector(use_lit)); oop_t branch_index_oop = pop(); if ( is_smi(branch_index_oop) ) { smi branch_index = value_of_smiOop(branch_index_oop); if ( 0 <= branch_index && branch_index < branch_vector_addr->indexableSize() ) { oop_t dest_oop = branch_vector_addr->indexable_at(branch_index); set_bci(dest_oop); } } } break; case DELEGATEE_CODE: delegatee = use_lit; break; case LITERAL_CODE: { oop_t lit = use_lit; if (::is_block(lit)) { put_sp_quickly(io, sp); // make sure that the sp is stored correctly, because an allocation could trigger a GC oop_t cloned_block = BlockObj::clone_block(lit, this_activation); ActivationObj* possibly_moved_act_addr = ActivationObj::from(this_activation); // mightHaveScavengedTheActivation if (possibly_moved_act_addr != this) { possibly_moved_act_addr->remote_push(cloned_block); possibly_moved_act_addr->put_pc_quickly( io, bci ); return this_activation; } else { push(cloned_block); } } else { push(lit); } } break; case IMPLICIT_SEND_CODE: // fall through case SEND_CODE: { oop_t selector = use_lit; if (selector == The::oop_of(The::restart_selector)) { put_sp_quickly( io, sp = first_stack_offset ); put_pc_quickly( io, bci = get_pc_after_endInit_quickly(io) ); break; } put_sp_quickly( io, sp ); // todo optimize dmu 3/6. This is here for the _Breakpoint primitve to help debugging by storing the PC. // But it slows every primitive, sigh. put_pc_quickly( io, bci); oop_t a = send(kind == IMPLICIT_SEND_CODE, selector, UC_undirected_resend, UC_del, UC_arg_count, this_activation); if (a != this_activation || ActivationObj::from(a) != this) { // mightHaveScavengedTheActivation // put_pc_quickly( io, bci); // commented out after I added the put_pc_quickly above, dmu 3/6 return a; } sp = get_sp_quickly(io); } break; case NO_OPERAND_CODE: switch(bc_index) { default: fatal("???"); break; case POP_CODE: pop(); break; case SELF_CODE: push(self); break; case END_INIT_CODE: put_pc_after_endInit_quickly(io, bci); break; case NONLOCAL_RETURN_CODE: return nonlocal_return(pop(), rcvr); break; case UNDIRECTED_RESEND_CODE: undirected_resend = true; break; } break; } } put_sp_quickly( io, sp ); put_pc_quickly( io, bci ); return this_activation; }
uint32_t eval(uint32_t p,uint32_t q){ // Log("%d %d\n",p,q); assert(p<=q); if (p==q) { //解析数字 uint32_t n; if(tokens[q].type == INT_16) sscanf(tokens[q].str,"%x",&n); else if (tokens[q].type == INT_10) { sscanf(tokens[q].str,"%d",&n); }else{ int i=0;int flag=-1; for (; i < 8; i++) { if (strcmp(*(regsl+i),tokens[q].str)==0) { flag = 1; break; } } if (flag) { //找到 switch(i){ case 0:return cpu.eax; case 1:return cpu.ecx; case 2:return cpu.edx; case 3:return cpu.ebx; case 4:return cpu.esp; case 5:return cpu.ebp; case 6:return cpu.esi; case 7:return cpu.edi; } }else { panic("reg can not find error"); } } return n; }else if(check_parentheses(p,q) == true){ //判断括号 return eval(p+1,q-1); }else if (tokens[p].type =='!') { return !eval(++p,q); }else if (tokens[p].type == DEREF) { return swaddr_read(eval(++p,q),4); }else{ //递归计算 uint32_t op = getOp(p,q); //获取dominat operator uint32_t val1 = eval(p,op-1); uint32_t val2 = eval(op+1,q); // printf("\n%u %c %u\n",val1,tokens[op].type,val2); switch(tokens[op].type){ case '+':return val1+val2; case '-':return val1-val2; case '*':return val1*val2; case '/':return val1/val2; case EQ:return val1==val2; case NEQ:return val1!=val2; case AND:return val1&&val2; case OR:return val1||val2; default: assert(0); } } }
Array createBacktrace(const BacktraceArgs& btArgs) { auto bt = Array::Create(); folly::small_vector<c_WaitableWaitHandle*, 64> visitedWHs; // If there is a parser frame, put it at the beginning of the backtrace. if (btArgs.m_parserFrame) { bt.append( make_map_array( s_file, btArgs.m_parserFrame->filename, s_line, btArgs.m_parserFrame->lineNumber ) ); } VMRegAnchor _; // If there are no VM frames, we're done. if (!rds::header() || !vmfp()) return bt; int depth = 0; ActRec* fp = nullptr; Offset pc = 0; // Get the fp and pc of the top frame (possibly skipping one frame). if (btArgs.m_skipTop) { fp = getPrevActRec(vmfp(), &pc, visitedWHs); // We skipped over the only VM frame, we're done. if (!fp) return bt; } else { fp = vmfp(); auto const unit = fp->func()->unit(); assert(unit); pc = unit->offsetOf(vmpc()); } // Handle the top frame. if (btArgs.m_withSelf) { // Builtins don't have a file and line number. if (!fp->func()->isBuiltin()) { auto const unit = fp->func()->unit(); assert(unit); auto const filename = fp->func()->filename(); ArrayInit frame(btArgs.m_parserFrame ? 4 : 2, ArrayInit::Map{}); frame.set(s_file, Variant{const_cast<StringData*>(filename)}); frame.set(s_line, unit->getLineNumber(pc)); if (btArgs.m_parserFrame) { frame.set(s_function, s_include); frame.set(s_args, Array::Create(btArgs.m_parserFrame->filename)); } bt.append(frame.toVariant()); depth++; } } // Handle the subsequent VM frames. Offset prevPc = 0; for (auto prevFp = getPrevActRec(fp, &prevPc, visitedWHs); fp != nullptr && (btArgs.m_limit == 0 || depth < btArgs.m_limit); fp = prevFp, pc = prevPc, prevFp = getPrevActRec(fp, &prevPc, visitedWHs)) { // Do not capture frame for HPHP only functions. if (fp->func()->isNoInjection()) continue; ArrayInit frame(7, ArrayInit::Map{}); auto const curUnit = fp->func()->unit(); auto const curOp = curUnit->getOp(pc); auto const isReturning = curOp == Op::RetC || curOp == Op::RetV || curOp == Op::CreateCont || curOp == Op::Await || fp->localsDecRefd(); // Builtins and generators don't have a file and line number if (prevFp && !prevFp->func()->isBuiltin()) { auto const prevUnit = prevFp->func()->unit(); auto prevFile = prevUnit->filepath(); if (prevFp->func()->originalFilename()) { prevFile = prevFp->func()->originalFilename(); } assert(prevFile); frame.set(s_file, Variant{const_cast<StringData*>(prevFile)}); // In the normal method case, the "saved pc" for line number printing is // pointing at the cell conversion (Unbox/Pop) instruction, not the call // itself. For multi-line calls, this instruction is associated with the // subsequent line which results in an off-by-n. We're subtracting one // in order to look up the line associated with the FCall/FCallArray // instruction. Exception handling and the other opcodes (ex. BoxR) // already do the right thing. The emitter associates object access with // the subsequent expression and this would be difficult to modify. auto const opAtPrevPc = prevUnit->getOp(prevPc); Offset pcAdjust = 0; if (opAtPrevPc == Op::PopR || opAtPrevPc == Op::UnboxR || opAtPrevPc == Op::UnboxRNop) { pcAdjust = 1; } frame.set(s_line, prevFp->func()->unit()->getLineNumber(prevPc - pcAdjust)); } // Check for include. String funcname{const_cast<StringData*>(fp->func()->name())}; if (fp->func()->isClosureBody()) { // Strip the file hash from the closure name. String fullName{const_cast<StringData*>(fp->func()->baseCls()->name())}; funcname = fullName.substr(0, fullName.find(';')); } // Check for pseudomain. if (funcname.empty()) { if (!prevFp && !btArgs.m_withPseudoMain) continue; else if (!prevFp) funcname = s_main; else funcname = s_include; } frame.set(s_function, funcname); if (!funcname.same(s_include)) { // Closures have an m_this but they aren't in object context. auto ctx = arGetContextClass(fp); if (ctx != nullptr && !fp->func()->isClosureBody()) { frame.set(s_class, Variant{const_cast<StringData*>(ctx->name())}); if (fp->hasThis() && !isReturning) { if (btArgs.m_withThis) { frame.set(s_object, Object(fp->getThis())); } frame.set(s_type, s_arrow); } else { frame.set(s_type, s_double_colon); } } } bool const mayUseVV = fp->func()->attrs() & AttrMayUseVV; auto const withNames = btArgs.m_withArgNames; auto const withValues = btArgs.m_withArgValues; if (!btArgs.m_withArgNames && !btArgs.m_withArgValues) { // do nothing } else if (funcname.same(s_include)) { if (depth != 0) { auto filepath = const_cast<StringData*>(curUnit->filepath()); frame.set(s_args, make_packed_array(filepath)); } } else if (!RuntimeOption::EnableArgsInBacktraces || isReturning) { // Provide an empty 'args' array to be consistent with hphpc. frame.set(s_args, empty_array()); } else { auto args = Array::Create(); auto const nparams = fp->func()->numNonVariadicParams(); auto const nargs = fp->numArgs(); auto const nformals = std::min<int>(nparams, nargs); if (UNLIKELY(mayUseVV) && UNLIKELY(fp->hasVarEnv() && fp->getVarEnv()->getFP() != fp)) { // VarEnv is attached to eval or debugger frame, other than the current // frame. Access locals thru VarEnv. auto varEnv = fp->getVarEnv(); auto func = fp->func(); for (int i = 0; i < nformals; i++) { auto const argname = func->localVarName(i); auto const tv = varEnv->lookup(argname); Variant val; if (tv != nullptr) { // the variable hasn't been unset val = withValues ? tvAsVariant(tv) : ""; } if (withNames) { args.set(String(const_cast<StringData*>(argname)), val); } else { args.append(val); } } } else { for (int i = 0; i < nformals; i++) { Variant val = withValues ? tvAsVariant(frame_local(fp, i)) : ""; if (withNames) { auto const argname = fp->func()->localVarName(i); args.set(String(const_cast<StringData*>(argname)), val); } else { args.append(val); } } } // Builtin extra args are not stored in varenv. if (UNLIKELY(mayUseVV) && nargs > nparams && fp->hasExtraArgs()) { for (int i = nparams; i < nargs; i++) { auto arg = fp->getExtraArg(i - nparams); args.append(tvAsVariant(arg)); } } frame.set(s_args, args); } if (btArgs.m_withMetadata && !isReturning) { if (UNLIKELY(mayUseVV) && UNLIKELY(fp->hasVarEnv())) { auto tv = fp->getVarEnv()->lookup(s_86metadata.get()); if (tv != nullptr && tv->m_type != KindOfUninit) { frame.set(s_metadata, tvAsVariant(tv)); } } else { auto local = fp->func()->lookupVarId(s_86metadata.get()); if (local != kInvalidId) { auto tv = frame_local(fp, local); if (tv->m_type != KindOfUninit) { frame.set(s_metadata, tvAsVariant(tv)); } } } } bt.append(frame.toVariant()); depth++; } return bt; }