static void create_miter_for_walk(folly::Optional<MArrayIter>& miter, Variant& var) { if (!var.is(KindOfObject)) { miter.emplace(var.asRef()->m_data.pref); return; } auto const odata = var.getObjectData(); if (odata->isCollection()) { raise_error("Collection elements cannot be taken by reference"); } bool isIterable; Object iterable = odata->iterableObject(isIterable); if (isIterable) { raise_fatal_error("An iterator cannot be used with " "foreach by reference"); } Array properties = iterable->o_toIterArray(null_string, ObjectData::CreateRefs); miter.emplace(properties.detach()); }
VALUE engine_write(VALUE self, VALUE str) { ms_conn* conn; int bytes; Data_Get_Struct(self, ms_conn, conn); StringValue(str); ERR_clear_error(); bytes = SSL_write(conn->ssl, (void*)RSTRING_PTR(str), (int)RSTRING_LEN(str)); if(bytes > 0) { return INT2FIX(bytes); } if(SSL_want_write(conn->ssl)) return Qnil; raise_error(conn->ssl, bytes); return Qnil; }
/** * build mtree from serialized mtree data * * @params[in] pointer to serialized data * @returns handle to new mtree * */ H _m_unserialize(S *s) { M *m = malloc(sizeof(M)); m->magic = s->magic; m->levels = s->levels; m->lP = malloc(sizeof(L)*m->levels); H h = {m,{0,0}}; void *blob = s->blob_offset + (void *)s; uint32_t s_size = SERIALIZED_HEADER_SIZE(m->levels); for(h.a.l=0; h.a.l<m->levels; h.a.l++) { L *sl = (L *) (((void *)s) + s_size + ((S *)s)->level_offsets[h.a.l]); L *l = GET_LEVEL(h); l->nodes = sl->nodes; l->nP = malloc(sizeof(N)*l->nodes); N *sn = sizeof(Mindex)+(void *)sl; for(h.a.i=0;h.a.i < l->nodes;h.a.i++) { N *n = GET_NODE(h,l); *n = *sn; void *surface = blob+*(size_t *)&sn->surface; if (n->flags & TFLAG_SURFACE_IS_TREE && !(n->flags & TFLAG_SURFACE_IS_RECEPTOR)) { if (!(n->flags & TFLAG_ALLOCATED)) { raise_error("whoa! orthogonal tree handles are supposed to be allocated!"); } H sh = _m_unserialize((S *)surface); n->surface = malloc(sizeof(H)); memcpy(n->surface,&sh,sn->size); } else if (n->flags & TFLAG_ALLOCATED) { n->surface = malloc(sn->size); memcpy(n->surface,surface,sn->size); } else { memcpy(&n->surface,&sn->surface,sn->size); } sn = (N *) (SERIALIZED_NODE_SIZE + ((void*)sn)); } } h.a.i = h.a.l = 0; return h; }
XDEBUG_NOTIMPLEMENTED static void HHVM_FUNCTION(xdebug_start_code_coverage, int64_t options /* = 0 */) { // XDEBUG_CC_UNUSED and XDEBUG_CC_DEAD_CODE not supported right now primarily // because the internal CodeCoverage class does support either unexecuted line // tracking or dead code analysis if (options != 0) { raise_error("XDEBUG_CC_UNUSED and XDEBUG_CC_DEAD_CODE constants are not " "currently supported."); return; } // If we get here, turn on coverage auto ti = ThreadInfo::s_threadInfo.getNoCheck(); ti->m_reqInjectionData.setCoverage(true); if (g_context->isNested()) { raise_notice("Calling xdebug_start_code_coverage from a nested VM instance " "may cause unpredicable results"); } throw VMSwitchModeBuiltin(); }
void FiberReferenceMap::unmarshal(Array &dest, CArrRef src, char strategy) { switch (strategy) { case FiberAsyncFunc::GlobalStateIgnore: // do nothing break; case FiberAsyncFunc::GlobalStateOverwrite: dest = src.fiberUnmarshal(*this); break; case FiberAsyncFunc::GlobalStateSkip: for (ArrayIter iter(src); iter; ++iter) { Variant key = iter.first(); if (!dest.exists(key)) { dest.set(key.fiberUnmarshal(*this), ref(iter.secondRef().fiberUnmarshal(*this))); } } break; default: raise_error("unknown strategy: %d", (int)strategy); break; } }
String StringUtil::HtmlEncode(CStrRef input, QuoteStyle quoteStyle, const char *charset, bool nbsp) { if (input.empty()) return input; assert(charset); bool utf8 = true; if (strcasecmp(charset, "ISO-8859-1") == 0) { utf8 = false; } else if (strcasecmp(charset, "UTF-8")) { throw NotImplementedException(charset); } int len = input.size(); char *ret = string_html_encode(input.data(), len, quoteStyle != QuoteStyle::No, quoteStyle == QuoteStyle::Both, utf8, nbsp); if (!ret) { raise_error("HtmlEncode called on too large input (%d)", len); } return String(ret, len, AttachString); }
/***************************************************************************** * Function: init_vsim * Description: Initializes a Modelsim .mem data structure *****************************************************************************/ void init_vsim(config_type *config, vsim_file_info *vsim) { // You might have to change this output manually // Allocate memory for the vsim_file_info variable vsim->comment = (char *)calloc(1024, 1); vsim->instance = (char *)calloc(1024, 1); vsim->flags = (char *)calloc(1024, 1); if ((!vsim->comment) || (!vsim->instance) || (!vsim->flags)) { raise_error(config, ERR_NOMEM); } strcpy(vsim->comment, "// memory data file (do not edit the following line - required for mem load use)\n"); strcpy(vsim->instance, "// instance=/fb_dualport/ram\n"); strcpy(vsim->flags, "// format=hex addressradix=h dataradix=h version=1.0 wordsperline=1 noaddress\n"); return; }
static void read_text(PInfo pi) { char buf[MAX_TEXT_LEN]; char *b = buf; char *alloc_buf = 0; char *end = b + sizeof(buf) - 2; char c; int done = 0; while (!done) { c = *pi->s++; switch(c) { case '<': done = 1; pi->s--; break; case '\0': raise_error("invalid format, document not terminated", pi->str, pi->s); default: if ('&' == c) { c = read_coded_char(pi); } if (end <= b) { unsigned long size; if (0 == alloc_buf) { size = sizeof(buf) * 2; alloc_buf = ALLOC_N(char, size); memcpy(alloc_buf, buf, b - buf); b = alloc_buf + (b - buf); } else { unsigned long pos = b - alloc_buf; size = (end - alloc_buf) * 2; REALLOC_N(alloc_buf, char, size); b = alloc_buf + pos; } end = alloc_buf + size - 2; }
void light_t::add(vec4 amb, vec4 diff, vec4 spec, int window[2], int shad_size) { cnt++; ambient.push_back(amb); diffuse.push_back(diff); specular.push_back(spec); depth_tex.push_back(texture_create_depth(window[0] * shad_size, window[1] * shad_size)); depthFBO.push_back(-1); GLenum fboStatus; glGenFramebuffers(1, &depthFBO[cnt - 1]); glBindFramebuffer(GL_FRAMEBUFFER, depthFBO[cnt - 1]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_tex[cnt - 1], 0); glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); if ((fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) raise_error("Framebuffer error ", false, true); glBindFramebuffer(GL_FRAMEBUFFER, 0); }
void HHVM_FUNCTION(pcntl_exec, const String& path, const Array& args /* = null_array */, const Array& envs /* = null_array */) { if (RuntimeOption::WhitelistExec && !check_cmd(path.data())) { return; } if (Repo::prefork()) { raise_error("execing is disallowed in multi-threaded mode"); return; } // build argumnent list std::vector<String> sargs; // holding those char * int size = args.size(); char **argv = (char **)malloc((size + 2) * sizeof(char *)); *argv = (char *)path.data(); int i = 1; if (size) { sargs.reserve(size); for (ArrayIter iter(args); iter; ++iter, ++i) { String arg = iter.second().toString(); sargs.push_back(arg); *(argv + i) = (char *)arg.data(); } } *(argv + i) = NULL; // build environment pair list std::vector<String> senvs; // holding those char * char **envp = build_envp(envs, senvs); if (execve(path.c_str(), argv, envp) == -1) { raise_warning("Error has occurred: (errno %d) %s", errno, folly::errnoStr(errno).c_str()); } free(envp); free(argv); }
int main() { //Declare buffers for user input char line[LINE_LEN]; //Initialize socket file descriptor int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) raise_error("Error opening socket"); //Prompt user to enter the port number int port_num; printf("Enter the port number: "); if ( fgets(line, sizeof(line), stdin) ) sscanf(line, "%d", &port_num); //Prompt user to enter the server's IP address char server_ip[IP_LEN]; printf("Enter the IP address of server: "); if ( fgets(line, sizeof(line), stdin) ) sscanf(line, "%[^\n]s", server_ip); //Set up remote server address struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(port_num); server.sin_addr.s_addr = inet_addr(server_ip); //Prompt user to enter the message to server printf("Enter the message: \n"); char msg[BUFF_SIZE]; if ( fgets(line, sizeof(line), stdin) ) sscanf(line, "%[^\n]s", msg); sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr *) &server, sizeof(server)); //Terminate the transfer close(sockfd); }
CAMLprim value stub_pcap_stats (value p_p) { CAMLparam1 (p_p); CAMLlocal1 (ret); pcap_t *p; struct pcap_stat ps; p = (pcap_t *) p_p; if (pcap_stats(p, &ps)) { raise_error (pcap_geterr (p)); } ret = caml_alloc (3, 0); Store_field (ret, 0, copy_int64 (ps.ps_recv)); Store_field (ret, 1, copy_int64 (ps.ps_drop)); Store_field (ret, 2, copy_int64 (ps.ps_ifdrop)); CAMLreturn (ret); }
void checkHHConfig(const Unit* unit) { if (RuntimeOption::RepoAuthoritative || !RuntimeOption::LookForTypechecker || s_foundHHConfig || !unit->isHHFile() || isDebuggerAttached()) { return; } const std::string &s = unit->filepath()->toCppString(); boost::filesystem::path p(s); while (p != "/" && p != "") { p.remove_filename(); p /= ".hhconfig"; if (boost::filesystem::exists(p)) { break; } p.remove_filename(); } if (p == "/" || p == "") { raise_error( "%s appears to be a Hack file, but you do not appear to be running " "the Hack typechecker. See the documentation at %s for information on " "getting it running. You can also set " "`-d hhvm.hack.lang.look_for_typechecker=0` " "to disable this check (not recommended).", s.c_str(), "http://docs.hhvm.com/hack/typechecker/setup" ); } else { s_foundHHConfig = true; } }
/** A more generic function than exec_call, this one actually lets you * execute any piece of code (more than just a simple function call). * It automatically wraps the snippet in a function. * * \param code The code to execute. */ string exec_code(string code) { string buf, err; mixed ret; string fname; if( !this_player() ) raise_error("exec_code must have a valid this_player() using it"); fname = this_player()->make_path_absolute( EXEC_OBJ ); if( ret = find_object(fname) ) destruct(ret); if( file_exists(fname + ".c") && !rm( fname + ".c" ) ) return "Unable to remove file "+fname+" to execute call."; buf = HEADER + EXEC_MACROS +"\ndo_exec() {\n"; buf += code + "\n}\n"; write_file( fname + ".c", buf ); err = catch(ret = load_object( fname )); if( err ) { msg("==> [Exec Error] "+err); return "<Invalid>"; } seteuid( getuid(this_player()) ); export_uid( ret ); seteuid( getuid(this_object()) ); ret = 0; err = catch(ret = fname->do_exec()); if( err ) { msg("==> [Call Runtime Error] "+err); return "<Invalid>"; } return as_lpc(ret); }
static MaybeDataType convert_for_pow(const Variant& val, int64_t& ival, double& dval) { switch (val.getType()) { case KindOfUninit: case KindOfNull: case KindOfBoolean: case KindOfInt64: case KindOfResource: case KindOfObject: ival = val.toInt64(); return KindOfInt64; case KindOfDouble: dval = val.toDouble(); return KindOfDouble; case KindOfPersistentString: case KindOfString: { auto dt = val.toNumeric(ival, dval, true); if ((dt != KindOfInt64) && (dt != KindOfDouble)) { ival = 0; return KindOfInt64; } return dt; } case KindOfPersistentArray: case KindOfArray: // Not reachable since HHVM_FN(pow) deals with these base cases first. case KindOfRef: case KindOfClass: break; } // Unknown data type. raise_error("Unsupported operand types"); not_reached(); }
/**Transforms a point in WGS84 LonLat in radians to projected coordinates. This version of the method changes the point in-place. call-seq: forward!(point) -> point */ static VALUE proj_forward(VALUE self,VALUE point){ _wrap_pj* wpj; int pj_errno_ref; projLP pj_point; projXY pj_result; Data_Get_Struct(self,_wrap_pj,wpj); pj_point.u = NUM2DBL( rb_funcall(point, idGetX, 0) ); pj_point.v = NUM2DBL( rb_funcall(point, idGetY, 0) ); pj_result = pj_fwd(pj_point, wpj->pj); pj_errno_ref = *pj_get_errno_ref(); if (pj_errno_ref == 0) { rb_funcall(point, idSetX, 1, rb_float_new(pj_result.u) ); rb_funcall(point, idSetY, 1, rb_float_new(pj_result.v) ); return point; } else if (pj_errno_ref > 0) { rb_raise(rb_eSystemCallError, "Unknown system call error"); } else { raise_error(pj_errno_ref); } return self; /* Makes gcc happy */ }
static PyObject * close_channel( PyObject *self, PyObject *args ) { (void)self; PyObject *py_chan; if( !PyArg_ParseTuple(args, "O", &py_chan) ) { return NULL; } ach_channel_t *c = parse_channel_pointer(py_chan); if( NULL == c ) { return NULL; } ach_status_t r = ach_close(c); if( ACH_OK != r ) { return raise_error(r); } free(c); Py_RETURN_NONE; }
VALUE engine_read(VALUE self) { ms_conn* conn; char buf[512]; int bytes, n; Data_Get_Struct(self, ms_conn, conn); bytes = SSL_read(conn->ssl, (void*)buf, sizeof(buf)); if(bytes > 0) { return rb_str_new(buf, bytes); } if(SSL_want_read(conn->ssl)) return Qnil; if(SSL_get_error(conn->ssl, bytes) == SSL_ERROR_ZERO_RETURN) { rb_eof_error(); } raise_error(conn->ssl, bytes); return Qnil; }
/**Transforms a point from one projection to another. The second parameter is either a Proj4::Point object or you can use any object which responds to the x, y, z read and write accessor methods. (In fact you don't even need the z accessor methods, 0 is assumed if they don't exist). This is the destructive variant of the method, i.e. it will overwrite your existing point coordinates but otherwise leave the point object alone. call-seq: transform!(destinationProjection, point) -> point */ static VALUE proj_transform(VALUE self, VALUE dst, VALUE point){ _wrap_pj* wpjsrc; _wrap_pj* wpjdst; double array_x[1]; double array_y[1]; double array_z[1]; int result; Data_Get_Struct(self,_wrap_pj,wpjsrc); Data_Get_Struct(dst,_wrap_pj,wpjdst); array_x[0] = NUM2DBL( rb_funcall(point, idGetX, 0) ); array_y[0] = NUM2DBL( rb_funcall(point, idGetY, 0) ); /* if point objects has a method 'z' we get the z coordinate, otherwise we just assume 0 */ if ( rb_respond_to(point, idGetZ) ) { array_z[0] = NUM2DBL( rb_funcall(point, idGetZ, 0) ); } else { array_z[0] = 0.0; } result = pj_transform(wpjsrc->pj, wpjdst->pj, 1, 1, array_x, array_y, array_z); if (! result) { rb_funcall(point, idSetX, 1, rb_float_new(array_x[0]) ); rb_funcall(point, idSetY, 1, rb_float_new(array_y[0]) ); /* if point objects has a method 'z=' we set the z coordinate, otherwise we ignore it */ if ( rb_respond_to(point, idSetZ) ) { rb_funcall(point, idSetZ, 1, rb_float_new(array_z[0]) ); } return point; } else if (result > 0) { rb_raise(rb_eSystemCallError, "Unknown system call error"); } else { raise_error(result); } return self; /* Makes gcc happy */ }
void raise_message(ErrorConstants::ErrorModes mode, const std::string &msg) { switch (mode) { case ErrorConstants::ErrorModes::ERROR: raise_error(msg); break; case ErrorConstants::ErrorModes::WARNING: raise_warning(msg); break; case ErrorConstants::ErrorModes::NOTICE: case ErrorConstants::ErrorModes::PHP_DEPRECATED: { // This is here rather than in the individual functions to reduce the // copy+paste if (RuntimeOption::NoticeFrequency <= 0 || (g_notice_counter++) % RuntimeOption::NoticeFrequency != 0) { break; } int errnum = static_cast<int>(mode); if (!g_context->errorNeedsHandling(errnum, true, ExecutionContext::ErrorThrowMode::Never)) { return; } if (mode == ErrorConstants::ErrorModes::NOTICE) { g_context->handleError(msg, errnum, true, ExecutionContext::ErrorThrowMode::Never, "\nNotice: "); } else { g_context->handleError(msg, errnum, true, ExecutionContext::ErrorThrowMode::Never, "\nDeprecated: "); } } break; default: always_assert(!"Unhandled type of error"); } }
static VALUE cCommand_execute_non_query(int argc, VALUE *argv[], VALUE self) { VALUE connection = rb_iv_get(self, "@connection"); VALUE postgres_connection = rb_iv_get(connection, "@connection"); if (Qnil == postgres_connection) { rb_raise(eConnectionError, "This connection has already been closed."); } PGconn *db = DATA_PTR(postgres_connection); PGresult *response; int status; VALUE affected_rows = Qnil; VALUE insert_id = Qnil; VALUE query = build_query_from_args(self, argc, argv); response = cCommand_execute(self, db, query); status = PQresultStatus(response); if ( status == PGRES_TUPLES_OK ) { insert_id = INT2NUM(atoi(PQgetvalue(response, 0, 0))); affected_rows = INT2NUM(atoi(PQcmdTuples(response))); } else if ( status == PGRES_COMMAND_OK ) { insert_id = Qnil; affected_rows = INT2NUM(atoi(PQcmdTuples(response))); } else { raise_error(self, response, query); } PQclear(response); return rb_funcall(cResult, ID_NEW, 3, self, affected_rows, insert_id); }
struct Token * scan(struct Scanner * scanner) { char * forword = scanner->forword; char * lexeme = scanner->lexeme; enum TYPE type; if(level_p(* forword)) { forword += 1; if(!number_p(* forword)) { raise_error(); } do { forword += 1; } while(number_p(* forword)); type = LEVEL; } else if(first_name_p(forword)) { } else if(last_name_p(forword)) { } else if(cid_p(forword)) { } else if(battle_p(forword)) { } else if(end_of_line_p(forword)) { } scanner->forword = forword; scanner->lexeme = forword; return new_token(type, lexeme, forword - lexeme); }
void ensure_uniform_sequence( boost::python::object seq, index_type expected_length=-1 ){ ensure_sequence( seq, expected_length ); index_type length = sequence_len( seq ); for( index_type index = 0; index < length; ++index ){ boost::python::object item = seq[index]; boost::python::extract<ExpectedType> type_checker( item ); if( !type_checker.check() ){ std::string expected_type_name( boost::python::type_id<ExpectedType>().name() ); std::string item_type_name("different"); PyObject* item_impl = item.ptr(); if( item_impl && item_impl->ob_type && item_impl->ob_type->tp_name ){ item_type_name = std::string( item_impl->ob_type->tp_name ); } std::stringstream err; err << "Sequence should contain only items with type \"" << expected_type_name << "\". " << "Item at position " << index << " has \"" << item_type_name << "\" type."; raise_error( PyExc_ValueError, err.str().c_str() ); } } }
static uint32_t read_hex(ParseInfo pi, char *h) { uint32_t b = 0; int i; /* TBD this can be made faster with a table */ for (i = 0; i < 4; i++, h++) { b = b << 4; if ('0' <= *h && *h <= '9') { b += *h - '0'; } else if ('A' <= *h && *h <= 'F') { b += *h - 'A' + 10; } else if ('a' <= *h && *h <= 'f') { b += *h - 'a' + 10; } else { pi->s = h; if (pi->has_error) { call_error("invalid hex character", pi, __FILE__, __LINE__); } raise_error("invalid hex character", pi->str, pi->s); } } return b; }
/** * free the memory used by an mtree * * @param[in] h handle to mtree to free * @param[in] free_surface boolean to indicate whether to free the surface values */ void __m_free(H h,int free_surface) { int i = h.m->levels; while(i--) { L *l = _GET_LEVEL(h,i); Mindex j = l->nodes; if (free_surface) { while(j--) { N *n = _GET_NODE(h,l,j); if (!(n->flags & TFLAG_REFERENCE)) { if (n->flags & TFLAG_SURFACE_IS_RECEPTOR) raise_error("mtree can't free receptor!"); if (n->flags & TFLAG_SURFACE_IS_TREE && !(n->flags & TFLAG_SURFACE_IS_RECEPTOR)) { _m_free(*(H *)n->surface); } if (n->flags & TFLAG_ALLOCATED) { free(n->surface); } } } } free(l->nP); } free(h.m->lP); free(h.m); }
void raise_call_to_undefined(const StringData* name, const Class* cls) { if (LIKELY(!needsStripInOut(name))) { if (cls) { raise_error("Call to undefined method %s::%s()", cls->name()->data(), name->data()); } raise_error("Call to undefined function %s()", name->data()); } else { auto stripped = stripInOutSuffix(name); if (cls) { if (cls->lookupMethod(stripped)) { raise_error("Call to method %s::%s() with incorrectly annotated inout " "parameter", cls->name()->data(), stripped->data()); } raise_error("Call to undefined method %s::%s()", cls->name()->data(), stripped->data()); } else if (Unit::lookupFunc(stripped)) { raise_error("Call to function %s() with incorrectly annotated inout " "parameter", stripped->data()); } raise_error("Call to undefined function %s()", stripped->data()); } }
void raise_typehint_error(const std::string& msg) { raise_recoverable_error(msg); if (RuntimeOption::RepoAuthoritative && Repo::global().HardTypeHints) { raise_error("Error handler tried to recover from typehint violation"); } }
Structure _sem_get_symbol_structure(SemTable *sem,Symbol s){ if (!is_symbol(s)) raise_error("Bad symbol: semantic type not SEM_TYPE_SYMBOL"); return __d_get_symbol_structure(_sem_get_defs(sem,s),s); }
bool EventHook::RunInterceptHandler(ActRec* ar) { const Func* func = ar->func(); if (LIKELY(func->maybeIntercepted() == 0)) return true; // Intercept only original generator / async function calls, not resumption. if (ar->resumed()) return true; Variant* h = get_intercept_handler(func->fullNameStr(), &func->maybeIntercepted()); if (!h) return true; /* * In production mode, only functions that we have assumed can be * intercepted during static analysis should actually be * intercepted. */ if (RuntimeOption::RepoAuthoritative && !RuntimeOption::EvalJitEnableRenameFunction) { if (!(func->attrs() & AttrInterceptable)) { raise_error("fb_intercept was used on a non-interceptable function (%s) " "in RepoAuthoritative mode", func->fullName()->data()); } } VMRegAnchor _; PC savePc = vmpc(); Variant doneFlag = true; Variant called_on; if (ar->hasThis()) { called_on = Variant(ar->getThis()); } else if (ar->hasClass()) { // For static methods, give handler the name of called class called_on = Variant(const_cast<StringData*>(ar->getClass()->name())); } Variant intArgs = PackedArrayInit(5) .append(VarNR(ar->func()->fullName())) .append(called_on) .append(get_frame_args_with_ref(ar)) .append(h->asCArrRef()[1]) .appendRef(doneFlag) .toArray(); Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs); if (doneFlag.toBoolean()) { Offset pcOff; ActRec* outer = g_context->getPrevVMState(ar, &pcOff); frame_free_locals_inl_no_hook<true>(ar, ar->func()->numLocals()); Stack& stack = vmStack(); stack.top() = (Cell*)(ar + 1); cellDup(*ret.asCell(), *stack.allocTV()); vmfp() = outer; vmpc() = outer ? outer->func()->unit()->at(pcOff) : nullptr; return false; } vmfp() = ar; vmpc() = savePc; return true; }
Class* Unit::defClass(PreClass* preClass, bool failIsFatal /* = true */) { Class* const* clsList = preClass->namedEntity()->clsList(); Class* top = *clsList; if (top) { Class *cls = top->getCached(); if (cls) { // Raise a fatal unless the existing class definition is identical to the // one this invocation would create. if (cls->preClass() != preClass) { if (failIsFatal) { raise_error("Class already declared: %s", preClass->name()->data()); } return NULL; } return cls; } } // Get a compatible Class, and add it to the list of defined classes. Class* parent = NULL; for (;;) { // Search for a compatible extant class. Searching from most to least // recently created may have better locality than alternative search orders. // In addition, its the only simple way to make this work lock free... for (Class* class_ = top; class_ != NULL; class_ = class_->m_nextClass) { if (class_->preClass() != preClass) continue; Class::Avail avail = class_->avail(parent, failIsFatal /*tryAutoload*/); if (LIKELY(avail == Class::AvailTrue)) { class_->setCached(); DEBUGGER_ATTACHED_ONLY(phpDefClassHook(class_)); return class_; } if (avail == Class::AvailFail) { if (failIsFatal) { raise_error("unknown class %s", parent->name()->data()); } return NULL; } ASSERT(avail == Class::AvailFalse); } // Create a new class. if (!parent && preClass->parent()->size() != 0) { parent = Unit::getClass(preClass->parent(), failIsFatal); if (parent == NULL) { if (failIsFatal) { raise_error("unknown class %s", preClass->parent()->data()); } return NULL; } } VMExecutionContext* ec = g_vmContext; ActRec* fp = ec->getFP(); PC pc = ec->getPC(); bool needsFrame = ec->m_stack.top() && (!fp || fp->m_func->unit() != preClass->unit()); if (needsFrame) { /* we can be called from Unit::merge, which hasnt yet setup the frame (because often it doesnt need to). Set up a fake frame here, in case of errors. But note that mergeUnit is called for systemlib etc before the stack has been setup. So dont do anything if m_stack.top() is NULL */ ActRec &tmp = *ec->m_stack.allocA(); tmp.m_savedRbp = (uint64_t)fp; tmp.m_savedRip = 0; tmp.m_func = preClass->unit()->getMain(); tmp.m_soff = preClass->getOffset() - tmp.m_func->base(); tmp.setThis(NULL); tmp.m_varEnv = 0; tmp.initNumArgs(0); ec->m_fp = &tmp; ec->m_pc = preClass->unit()->at(preClass->getOffset()); ec->pushLocalsAndIterators(tmp.m_func); } ClassPtr newClass(Class::newClass(preClass, parent)); if (needsFrame) { ec->m_stack.top() = (Cell*)(ec->m_fp+1); ec->m_fp = fp; ec->m_pc = pc; } Lock l(Unit::s_classesMutex); /* We could re-enter via Unit::getClass() or class_->avail(), so no need for *clsList to be volatile */ if (UNLIKELY(top != *clsList)) { top = *clsList; continue; } if (top) { newClass->m_cachedOffset = top->m_cachedOffset; } else { newClass->m_cachedOffset = Transl::TargetCache::allocKnownClass(preClass->name()); } newClass->m_nextClass = top; Util::compiler_membar(); *const_cast<Class**>(clsList) = newClass.get(); newClass.get()->incAtomicCount(); newClass.get()->setCached(); DEBUGGER_ATTACHED_ONLY(phpDefClassHook(newClass.get())); return newClass.get(); } }