/* * The CreateCl opcode is specified as not being allowed before the * class it creates exists, and closure classes are always unique. * * This means even if we're not in RepoAuthoritative mode, as long as * this code is reachable it will always use the same closure Class*, * so we can just burn it into the TC without using RDS. */ void emitCreateCl(HTS& env, int32_t numParams, const StringData* clsName) { auto const cls = Unit::lookupClassOrUniqueClass(clsName); auto const invokeFunc = cls->lookupMethod(s_uuinvoke.get()); auto const clonedFunc = invokeFunc->cloneAndSetClass( const_cast<Class*>(curClass(env)) ); assert(cls && (cls->attrs() & AttrUnique)); auto const closure = allocObjFast(env, cls); gen(env, IncRef, closure); auto const ctx = [&]{ if (!curClass(env)) return cns(env, nullptr); auto const ldctx = gen(env, LdCtx, fp(env)); if (invokeFunc->attrs() & AttrStatic) { return gen(env, ConvClsToCctx, gen(env, LdClsCtx, ldctx)); } gen(env, IncRefCtx, ldctx); return ldctx; }(); gen(env, StClosureCtx, closure, ctx); gen(env, StClosureFunc, FuncData(clonedFunc), closure); SSATmp* args[numParams]; for (int32_t i = 0; i < numParams; ++i) { args[numParams - i - 1] = popF(env); } int32_t propId = 0; for (; propId < numParams; ++propId) { gen( env, StClosureArg, PropByteOffset(cls->declPropOffset(propId)), closure, args[propId] ); } // Closure static variables are per instance, and need to start // uninitialized. After numParams use vars, the remaining instance // properties hold any static locals. assert(cls->numDeclProperties() == clonedFunc->numStaticLocals() + numParams); for (int32_t numDeclProperties = cls->numDeclProperties(); propId < numDeclProperties; ++propId) { gen( env, StClosureArg, PropByteOffset(cls->declPropOffset(propId)), closure, cns(env, Type::Uninit) ); } push(env, closure); }
/* * Check instanceof using the superclass vector on the end of the Class entry. */ void cgExtendsClass(IRLS& env, const IRInstruction* inst) { auto const extra = inst->extra<ExtendsClassData>(); auto const dst = dstLoc(env, inst, 0).reg(); auto const lhs = srcLoc(env, inst, 0).reg(); auto const rhsCls = extra->cls; auto& v = vmain(env); assertx(rhsCls != nullptr); // Check whether `lhs' points to a subclass of rhsCls, set `d' with the // boolean result, and return `d'. auto check_subclass = [&](Vreg d) { if (rhsCls->classVecLen() == 1) { // Every class has at least one entry in its class vec, so there's no // need to check the length. return check_clsvec(v, d, lhs, rhsCls, 1); } assertx(rhsCls->classVecLen() > 1); // Check the length of the class vectors. If the candidate's is at least // as long as the potential base (`rhsCls'), it might be a subclass. auto const sf = v.makeReg(); emitCmpVecLen(v, sf, static_cast<int32_t>(rhsCls->classVecLen()), lhs[Class::classVecLenOff()]); return check_subcls(v, sf, d, lhs, rhsCls, rhsCls->classVecLen()); }; if (rhsCls->attrs() & AttrAbstract || (extra->strictLikely && !(rhsCls->attrs() & AttrNoOverride))) { // If the test must be extended, or the hint says it's probably not an // exact match, don't check for the same class. check_subclass(dst); return; } // Test if it is the exact same class. // TODO(#2044801): We should be doing this control flow at the IR level. auto const sf = v.makeReg(); emitCmpLowPtr<Class>(v, sf, v.cns(rhsCls), lhs); if (rhsCls->attrs() & AttrNoOverride) { // If the test class cannot be extended, we only need to do the same-class // check, never the subclass check. v << setcc{CC_E, sf, dst}; return; } cond( v, CC_E, sf, dst, [&] (Vout& v) { return v.cns(true); }, [&] (Vout& v) { return check_subclass(v.makeReg()); } ); }
void QgsMapToolOffsetCurve::canvasReleaseEvent( QMouseEvent * e ) { Q_UNUSED( e ); QgsVectorLayer* vlayer = currentVectorLayer(); if ( !vlayer ) { deleteRubberBandAndGeometry(); return; } if ( !mGeometryModified ) { deleteRubberBandAndGeometry(); vlayer->destroyEditCommand(); return; } if ( mMultiPartGeometry ) { mModifiedGeometry.convertToMultiType(); } vlayer->beginEditCommand( tr( "Offset curve" ) ); bool editOk; if ( mSourceLayerId == vlayer->id() && !mForceCopy ) { editOk = vlayer->changeGeometry( mModifiedFeature, &mModifiedGeometry ); } else { QgsFeature f; f.setGeometry( mModifiedGeometry ); //add empty values for all fields (allows inserting attribute values via the feature form in the same session) QgsAttributes attrs( vlayer->pendingFields().count() ); const QgsFields& fields = vlayer->pendingFields(); for ( int idx = 0; idx < fields.count(); ++idx ) { attrs[idx] = QVariant(); } f.setAttributes( attrs ); editOk = vlayer->addFeature( f ); } if ( editOk ) { vlayer->endEditCommand(); } else { vlayer->destroyEditCommand(); } deleteRubberBandAndGeometry(); deleteDistanceItem(); delete mSnapVertexMarker; mSnapVertexMarker = 0; mForceCopy = false; mCanvas->refresh(); }
void Properties::parsePropertyKeyValue(const std::string &property, const char kvpsep, const char kvsep) { size_t coma = 0, curPos = 0; std::string attrs(property); Utils::trim(attrs); size_t len = attrs.size(); while(coma < len) { coma = attrs.find(kvpsep, curPos); std::string attrPair = attrs.substr(curPos, coma - curPos); while(coma < len && attrs.at(coma) == kvpsep) coma++; curPos = coma; Utils::trim(attrPair); if(attrPair.size() == 0) continue; size_t pipe = attrPair.find(kvsep); if(pipe != std::string::npos) { std::string key = attrPair.substr(0, pipe); std::string value = attrPair.substr(pipe + 1); Utils::trim(key); Utils::trim(value); set(key, value); } } return; }
void c_Closure::init(int numArgs, ActRec* ar, TypedValue* sp) { auto const invokeFunc = getVMClass()->lookupMethod(s_uuinvoke.get()); m_thisOrClass = ar->m_this; if (ar->hasThis()) { if (invokeFunc->attrs() & AttrStatic) { // Only set the class for static closures. m_thisOrClass = reinterpret_cast<ObjectData*>( reinterpret_cast<intptr_t>(ar->getThis()->getVMClass()) | 1LL ); } else { ar->getThis()->incRefCount(); } } // Change my __invoke's m_cls to be the same as my creator's Class* scope = ar->m_func->cls(); m_func = invokeFunc->cloneAndSetClass(scope); // copy the props to instance variables assert(m_cls->numDeclProperties() == numArgs); TypedValue* beforeCurUseVar = sp + numArgs; TypedValue* curProperty = propVec(); for (int i = 0; i < numArgs; i++) { // teleport the references in here so we don't incref tvCopy(*--beforeCurUseVar, *curProperty++); } }
Type typeFromTV(const TypedValue* tv) { assertx(tv->m_type == KindOfClass || tvIsPlausible(*tv)); if (tv->m_type == KindOfObject) { auto const cls = tv->m_data.pobj->getVMClass(); // We only allow specialization on classes that can't be overridden for // now. If this changes, then this will need to specialize on sub object // types instead. if (!cls || !(cls->attrs() & AttrNoOverride)) return TObj; return Type::ExactObj(cls); } if (isArrayType(tv->m_type)) { return Type::Array(tv->m_data.parr->kind()); } auto outer = tv->m_type; auto inner = KindOfUninit; if (outer == KindOfPersistentString) outer = KindOfString; if (outer == KindOfRef) { inner = tv->m_data.pref->tv()->m_type; if (inner == KindOfPersistentString) inner = KindOfString; else if (inner == KindOfPersistentArray) inner = KindOfArray; } return Type(outer, inner); }
void IAttributeData::deserialise(LoadingState *state, data::Table *data) { Handle<data::Table> attrs(data->at<data::Table>("attributes")); if (attrs) { mAttributes = attrs; } }
const Func* lookupImmutableCtor(const Class* cls, const Class* ctx) { if (!cls) return nullptr; auto const func = cls->getCtor(); if (func && !(func->attrs() & AttrPublic)) { auto fcls = func->cls(); if (fcls != ctx) { if (!ctx) return nullptr; if ((func->attrs() & AttrPrivate) || !(ctx->classof(fcls) || fcls->classof(ctx))) { return nullptr; } } } return func; }
/* static */ void ChromeUtils::OriginAttributesToSuffix(dom::GlobalObject& aGlobal, const dom::OriginAttributesDictionary& aAttrs, nsCString& aSuffix) { GenericOriginAttributes attrs(aAttrs); attrs.CreateSuffix(aSuffix); }
/* static */ bool ChromeUtils::OriginAttributesMatchPattern(dom::GlobalObject& aGlobal, const dom::OriginAttributesDictionary& aAttrs, const dom::OriginAttributesPatternDictionary& aPattern) { GenericOriginAttributes attrs(aAttrs); OriginAttributesPattern pattern(aPattern); return pattern.Matches(attrs); }
static void setHotFuncAttr() { static bool synced = false; if (synced) return; Lock lock(syncLock); if (synced) return; /* * s_treadmill forces any Funcs that are being destroyed to go through a * treadmill pass, to make sure we won't try to dereference something that's * being pulled out from under us. */ Func::s_treadmill = true; SCOPE_EXIT { Func::s_treadmill = false; }; if (RuntimeOption::EvalHotFuncCount) { std::priority_queue<FuncHotness, std::vector<FuncHotness>, bool(*)(const FuncHotness& a, const FuncHotness& b)> queue(comp); Func::getFuncVec().foreach([&](const Func* f) { if (!f) return; auto const profCounter = [&]() -> uint32_t { FuncProfileCounters::const_accessor acc; if (s_func_counters.find(acc, f->getFuncId())) { return acc->second; } return 0; }(); auto fh = FuncHotness(f, profCounter); if (queue.size() >= RuntimeOption::EvalHotFuncCount) { if (!comp(fh, queue.top())) return; queue.pop(); } queue.push(fh); }); while (queue.size()) { auto f = queue.top().first; queue.pop(); const_cast<Func*>(f)->setAttrs(f->attrs() | AttrHot); } } // We won't need the counters anymore. But there might be requests in flight // that still thought they were profiling, so we need to clear it on the // treadmill. Treadmill::enqueue([&] { FuncProfileCounters newMap(0); swap(s_func_counters, newMap); }); synced = true; }
void handlePossibleStackOverflow(ActRec* calleeAR) { assert_native_stack_aligned(); // If it's not an overflow, it was probably a surprise flag trip. But we // can't assert that it is because background threads are allowed to clear // surprise bits concurrently, so it could be cleared again by now. if (!checkCalleeStackOverflow(calleeAR)) return; auto const func = calleeAR->func(); /* * Stack overflows in this situation are a slightly different case than * handleStackOverflow: * * A function prologue already did all the work to prepare to enter the * function, but then it found out it didn't have enough room on the stack. * It may even have written uninits deeper than the stack base (but we limit * it to sSurprisePageSize, so it's harmless). * * Most importantly, it might have pulled args /off/ the eval stack and * shoved them into an ExtraArgs on the calleeAR, or into an array for a * variadic capture param. We need to get things into an appropriate state * for handleStackOverflow to be able to synchronize things to throw from the * PC of the caller's FCall. * * We don't actually need to make sure the stack is the right depth for the * FCall: the unwinder will expect to see a pre-live ActRec (and we'll set it * up so it will), but it doesn't care how many args (or what types of args) * are below it on the stack. * * It is tempting to try to free the ExtraArgs structure here, but it's ok to * not to: * * o We're about to raise an uncatchable fatal, which will end the * request. We leak ExtraArgs in other similar situations for this too * (e.g. if called via FCallArray and then a stack overflow happens). * * o If we were going to free the ExtraArgs structure, we'd need to make * sure we can re-enter the VM right now, which means performing a * manual fixup first. (We aren't in a situation where we can do a * normal VMRegAnchor fixup right now.) But moreover we shouldn't be * running destructors if a fatal is happening anyway, so we don't want * that either. * * So, all that boils down to this: we ignore the extra args field (the * unwinder will not consult the ExtraArgs field because it believes the * ActRec is pre-live). And set calleeAR->m_numArgs to indicate how many * things are actually on the stack (so handleStackOverflow knows what to set * the vmsp to)---we just set it to the function's numLocals, which might * mean decreffing some uninits unnecessarily, but that's ok. */ if (debug && func->attrs() & AttrMayUseVV && calleeAR->getExtraArgs()) { calleeAR->trashVarEnv(); } calleeAR->setNumArgs(calleeAR->m_func->numLocals()); handleStackOverflow(calleeAR); }
static QVector<HB_CharAttributes> getCharAttributes(const QString &str, HB_Script script = HB_Script_Common) { QVector<HB_CharAttributes> attrs(str.length()); HB_ScriptItem item; item.pos = 0; item.length = str.length(); item.script = script; HB_GetCharAttributes(str.utf16(), str.length(), &item, 1, attrs.data()); return attrs; }
const Func* lookupImmutableCtor(const Class* cls, const Class* ctx) { if (!cls || RuntimeOption::EvalJitEnableRenameFunction) return nullptr; if (!(cls->attrs() & AttrUnique)) { if (!ctx || !ctx->classof(cls)) { return nullptr; } } auto const func = cls->getCtor(); if (func && !(func->attrs() & AttrPublic)) { auto fcls = func->cls(); if (fcls != ctx) { if (!ctx) return nullptr; if ((func->attrs() & AttrPrivate) || !(ctx->classof(fcls) || fcls->classof(ctx))) { return nullptr; } } } return func; }
TypedValue* methodWrapper(ActRec* ar) { auto func = ar->m_func; auto numArgs = func->numParams(); auto numNonDefault = ar->numArgs(); bool isStatic = func->isStatic(); assert(!func->hasVariadicCaptureParam()); TypedValue* args = ((TypedValue*)ar) - 1; TypedValue rv; rv.m_type = KindOfNull; if (LIKELY(numNonDefault == numArgs) || LIKELY(nativeWrapperCheckArgs(ar))) { if (coerceFCallArgs(args, numArgs, numNonDefault, func)) { // Prepend a context arg for methods // KindOfClass when it's being called statically Foo::bar() // KindOfObject when it's being called on an instance $foo->bar() TypedValue ctx; if (ar->hasThis()) { if (isStatic) { throw_instance_method_fatal(getInvokeName(ar)->data()); } ctx.m_type = KindOfObject; ctx.m_data.pobj = ar->getThis(); } else { if (!isStatic) { throw_instance_method_fatal(getInvokeName(ar)->data()); } ctx.m_type = KindOfClass; ctx.m_data.pcls = const_cast<Class*>(ar->getClass()); } callFunc(func, &ctx, args, numArgs, rv); } else if (func->attrs() & AttrParamCoerceModeFalse) { rv.m_type = KindOfBoolean; rv.m_data.num = 0; } } assert(rv.m_type != KindOfUninit); if (isStatic) { frame_free_locals_no_this_inl(ar, func->numLocals(), &rv); } else { frame_free_locals_inl(ar, func->numLocals(), &rv); } tvCopy(rv, ar->m_r); return &ar->m_r; }
// try to get the maximum number of supported sounds, this is similar to code CSound::StartThread // but should be more safe int CSound::GetMaxMonoSources(ALCdevice* device, int maxSounds) { ALCint size; alcGetIntegerv(device, ALC_ATTRIBUTES_SIZE, 1, &size); std::vector<ALCint> attrs(size); alcGetIntegerv(device, ALC_ALL_ATTRIBUTES, size, &attrs[0] ); for (int i=0; i<attrs.size(); ++i){ if (attrs[i] == ALC_MONO_SOURCES) { const int maxMonoSources = attrs.at(i + 1); if (maxMonoSources < maxSounds) { LOG_L(L_WARNING, "Hardware supports only %d Sound sources, MaxSounds=%d, using Hardware Limit", maxMonoSources, maxSounds); } return std::min(maxSounds, maxMonoSources); } } return maxSounds; }
KoFilter::ConversionStatus PptxXmlCommentAuthorsReader::read_cmAuthor() { READ_PROLOGUE QXmlStreamAttributes attrs( attributes() ); READ_ATTR_WITHOUT_NS(id) READ_ATTR_WITHOUT_NS(name) d->context->authors.insert(id.toInt(), name); while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) // if (isStartElement()) { // TRY_READ_IF(extLst) // ELSE_WRONG_FORMAT // } } READ_EPILOGUE }
Node& Node::sanitize(const Whitelist& whitelist){ // Element nodes get checked if(is_element()){ // Is tag name allowed? bool ok = false; std::string tag = name(); for(auto item : whitelist){ if(tag==item.first){ ok = true; // Are attribute names allowed? for(auto attr : attrs()){ bool ok = false; for(auto allowed : item.second){ if(attr==allowed){ ok = true; break; } } // Attribute is not allowed...erase it if(not ok) erase(attr); } break; } } if(not ok) { // Tag name is not allowed... remove it from parent destroy(); } else { // Tag name is allowed...check children for(Node& child : children()) child.sanitize(whitelist); } } // Document and text nodes are not checked, only their children (if any) else { for(Node& child : children()) child.sanitize(whitelist); } return *this; }
TypedValue* functionWrapper(ActRec* ar) { auto func = ar->m_func; auto numArgs = func->numParams(); auto numNonDefault = ar->numArgs(); assert(!func->hasVariadicCaptureParam()); TypedValue* args = ((TypedValue*)ar) - 1; TypedValue rv; rv.m_type = KindOfNull; if (LIKELY(numNonDefault == numArgs) || LIKELY(nativeWrapperCheckArgs(ar))) { if (coerceFCallArgs(args, numArgs, numNonDefault, func)) { callFunc(func, nullptr, args, numArgs, rv); } else if (func->attrs() & AttrParamCoerceModeFalse) { rv.m_type = KindOfBoolean; rv.m_data.num = 0; } } assert(rv.m_type != KindOfUninit); frame_free_locals_no_this_inl(ar, func->numLocals(), &rv); tvCopy(rv, ar->m_r); return &ar->m_r; }
bool QgsGeometryAnalyzer::extent( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures, QProgressDialog * ) { if ( !layer ) { return false; } QgsVectorDataProvider* dp = layer->dataProvider(); if ( !dp ) { return false; } QgsWkbTypes::Type outputType = QgsWkbTypes::Polygon; QgsCoordinateReferenceSystem crs = layer->crs(); QgsFields fields; fields.append( QgsField( QStringLiteral( "MINX" ), QVariant::Double ) ); fields.append( QgsField( QStringLiteral( "MINY" ), QVariant::Double ) ); fields.append( QgsField( QStringLiteral( "MAXX" ), QVariant::Double ) ); fields.append( QgsField( QStringLiteral( "MAXY" ), QVariant::Double ) ); fields.append( QgsField( QStringLiteral( "CNTX" ), QVariant::Double ) ); fields.append( QgsField( QStringLiteral( "CNTY" ), QVariant::Double ) ); fields.append( QgsField( QStringLiteral( "AREA" ), QVariant::Double ) ); fields.append( QgsField( QStringLiteral( "PERIM" ), QVariant::Double ) ); fields.append( QgsField( QStringLiteral( "HEIGHT" ), QVariant::Double ) ); fields.append( QgsField( QStringLiteral( "WIDTH" ), QVariant::Double ) ); QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, crs ); QgsRectangle rect; if ( onlySelectedFeatures ) // take only selection { rect = layer->boundingBoxOfSelected(); } else { rect = layer->extent(); } double minx = rect.xMinimum(); double miny = rect.yMinimum(); double maxx = rect.xMaximum(); double maxy = rect.yMaximum(); double height = rect.height(); double width = rect.width(); double cntx = minx + ( width / 2.0 ); double cnty = miny + ( height / 2.0 ); double area = width * height; double perim = ( 2 * width ) + ( 2 * height ); QgsFeature feat; QgsAttributes attrs( 10 ); attrs[0] = QVariant( minx ); attrs[1] = QVariant( miny ); attrs[2] = QVariant( maxx ); attrs[3] = QVariant( maxy ); attrs[4] = QVariant( cntx ); attrs[5] = QVariant( cnty ); attrs[6] = QVariant( area ); attrs[7] = QVariant( perim ); attrs[8] = QVariant( height ); attrs[9] = QVariant( width ); feat.setAttributes( attrs ); feat.setGeometry( QgsGeometry::fromRect( rect ) ); vWriter.addFeature( feat ); return true; }
already_AddRefed<nsIPrincipal> PrincipalInfoToPrincipal(const PrincipalInfo& aPrincipalInfo, nsresult* aOptionalResult) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipalInfo.type() != PrincipalInfo::T__None); nsresult stackResult; nsresult& rv = aOptionalResult ? *aOptionalResult : stackResult; nsCOMPtr<nsIScriptSecurityManager> secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } nsCOMPtr<nsIPrincipal> principal; switch (aPrincipalInfo.type()) { case PrincipalInfo::TSystemPrincipalInfo: { rv = secMan->GetSystemPrincipal(getter_AddRefs(principal)); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } return principal.forget(); } case PrincipalInfo::TNullPrincipalInfo: { principal = do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } return principal.forget(); } case PrincipalInfo::TContentPrincipalInfo: { const ContentPrincipalInfo& info = aPrincipalInfo.get_ContentPrincipalInfo(); nsCOMPtr<nsIURI> uri; rv = NS_NewURI(getter_AddRefs(uri), info.spec()); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } if (info.appId() == nsIScriptSecurityManager::UNKNOWN_APP_ID) { rv = secMan->GetSimpleCodebasePrincipal(uri, getter_AddRefs(principal)); } else { // TODO: Bug 1167100 - User nsIPrincipal.originAttribute in ContentPrincipalInfo OriginAttributes attrs(info.appId(), info.isInBrowserElement()); principal = BasePrincipal::CreateCodebasePrincipal(uri, attrs); rv = principal ? NS_OK : NS_ERROR_FAILURE; } if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } return principal.forget(); } case PrincipalInfo::TExpandedPrincipalInfo: { const ExpandedPrincipalInfo& info = aPrincipalInfo.get_ExpandedPrincipalInfo(); nsTArray< nsCOMPtr<nsIPrincipal> > whitelist; nsCOMPtr<nsIPrincipal> wlPrincipal; for (uint32_t i = 0; i < info.whitelist().Length(); i++) { wlPrincipal = PrincipalInfoToPrincipal(info.whitelist()[i], &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } // append that principal to the whitelist whitelist.AppendElement(wlPrincipal); } nsRefPtr<nsExpandedPrincipal> expandedPrincipal = new nsExpandedPrincipal(whitelist); if (!expandedPrincipal) { NS_WARNING("could not instantiate expanded principal"); return nullptr; } principal = expandedPrincipal; return principal.forget(); } default: MOZ_CRASH("Unknown PrincipalInfo type!"); } MOZ_CRASH("Should never get here!"); }
void cgCallBuiltin(IRLS& env, const IRInstruction* inst) { auto const extra = inst->extra<CallBuiltin>(); auto const callee = extra->callee; auto const returnType = inst->typeParam(); auto const funcReturnType = callee->returnType(); auto const returnByValue = callee->isReturnByValue(); auto const dstData = dstLoc(env, inst, 0).reg(0); auto const dstType = dstLoc(env, inst, 0).reg(1); auto& v = vmain(env); // Whether `t' is passed in/out of C++ as String&/Array&/Object&. auto const isReqPtrRef = [] (MaybeDataType t) { return isStringType(t) || isArrayLikeType(t) || t == KindOfObject || t == KindOfResource; }; if (FixupMap::eagerRecord(callee)) { auto const sp = srcLoc(env, inst, 1).reg(); auto const spOffset = cellsToBytes(extra->spOffset.offset); auto const& marker = inst->marker(); auto const pc = marker.fixupSk().unit()->entry() + marker.fixupBcOff(); auto const synced_sp = v.makeReg(); v << lea{sp[spOffset], synced_sp}; emitEagerSyncPoint(v, pc, rvmtl(), srcLoc(env, inst, 0).reg(), synced_sp); } int returnOffset = rds::kVmMInstrStateOff + offsetof(MInstrState, tvBuiltinReturn); auto args = argGroup(env, inst); if (!returnByValue) { if (isBuiltinByRef(funcReturnType)) { if (isReqPtrRef(funcReturnType)) { returnOffset += TVOFF(m_data); } // Pass the address of tvBuiltinReturn to the native function as the // location where it can construct the return Array, String, Object, or // Variant. args.addr(rvmtl(), returnOffset); args.indirect(); } } // The srcs past the first two (sp and fp) are the arguments to the callee. auto srcNum = uint32_t{2}; // Add the this_ or self_ argument for HNI builtins. if (callee->isMethod()) { if (callee->isStatic()) { args.ssa(srcNum); ++srcNum; } else { // Note that we don't support objects with vtables here (if they may need // a $this pointer adjustment). This should be filtered out during irgen // or before. args.ssa(srcNum); ++srcNum; } } // Add the func_num_args() value if needed. if (callee->attrs() & AttrNumArgs) { // If `numNonDefault' is negative, this is passed as an src. if (extra->numNonDefault >= 0) { args.imm((int64_t)extra->numNonDefault); } else { args.ssa(srcNum); ++srcNum; } } // Add the positional arguments. for (uint32_t i = 0; i < callee->numParams(); ++i, ++srcNum) { auto const& pi = callee->params()[i]; // Non-pointer and NativeArg args are passed by value. String, Array, // Object, and Variant are passed by const&, i.e. a pointer to stack memory // holding the value, so we expect PtrToT types for these. Pointers to // req::ptr types (String, Array, Object) need adjusting to point to // &ptr->m_data. if (TVOFF(m_data) && !pi.nativeArg && isReqPtrRef(pi.builtinType)) { assertx(inst->src(srcNum)->type() <= TPtrToGen); args.addr(srcLoc(env, inst, srcNum).reg(), TVOFF(m_data)); } else if (pi.nativeArg && !pi.builtinType && !callee->byRef(i)) { // This condition indicates a MixedTV (i.e., TypedValue-by-value) arg. args.typedValue(srcNum); } else { args.ssa(srcNum, pi.builtinType == KindOfDouble); } } auto dest = [&] () -> CallDest { if (isBuiltinByRef(funcReturnType)) { if (!returnByValue) return kVoidDest; // indirect return return funcReturnType ? callDest(dstData) // String, Array, or Object : callDest(dstData, dstType); // Variant } return funcReturnType == KindOfDouble ? callDestDbl(env, inst) : callDest(env, inst); }(); cgCallHelper(v, env, CallSpec::direct(callee->nativeFuncPtr()), dest, SyncOptions::Sync, args); // For primitive return types (int, bool, double) and returnByValue, the // return value is already in dstData/dstType. if (returnType.isSimpleType() || returnByValue) return; // For return by reference (String, Object, Array, Variant), the builtin // writes the return value into MInstrState::tvBuiltinReturn, from where it // has to be tested and copied. if (returnType.isReferenceType()) { // The return type is String, Array, or Object; fold nullptr to KindOfNull. assertx(isBuiltinByRef(funcReturnType) && isReqPtrRef(funcReturnType)); v << load{rvmtl()[returnOffset], dstData}; if (dstType.isValid()) { auto const sf = v.makeReg(); auto const rtype = v.cns(returnType.toDataType()); auto const nulltype = v.cns(KindOfNull); v << testq{dstData, dstData, sf}; v << cmovb{CC_Z, sf, rtype, nulltype, dstType}; } return; } if (returnType <= TCell || returnType <= TBoxedCell) { // The return type is Variant; fold KindOfUninit to KindOfNull. assertx(isBuiltinByRef(funcReturnType) && !isReqPtrRef(funcReturnType)); static_assert(KindOfUninit == 0, "KindOfUninit must be 0 for test"); v << load{rvmtl()[returnOffset + TVOFF(m_data)], dstData}; if (dstType.isValid()) { auto const rtype = v.makeReg(); v << loadb{rvmtl()[returnOffset + TVOFF(m_type)], rtype}; auto const sf = v.makeReg(); auto const nulltype = v.cns(KindOfNull); v << testb{rtype, rtype, sf}; v << cmovb{CC_Z, sf, rtype, nulltype, dstType}; } return; } not_reached(); }
bool InsertIterator::nextImpl(store::Item_t& result, PlanState& aPlanState) const { store::StoreConsts::NodeKind targetKind; bool elemParent; bool elemTarget; store::Item_t parent; store::Item_t target; store::Item_t source; std::vector<store::Item_t> attrs(16); std::vector<store::Item_t> nodes(16); ulong numAttrs = 0; ulong numNodes = 0; std::unique_ptr<store::PUL> pul; store::Item_t temp; store::CopyMode lCopyMode; bool typePreserve; bool nsPreserve; bool nsInherit; PlanIteratorState* state; DEFAULT_STACK_INIT(PlanIteratorState, state, aPlanState); typePreserve = (theSctx->construction_mode() == StaticContextConsts::cons_preserve ? true : false); nsPreserve = theSctx->preserve_ns(); nsInherit = theSctx->inherit_ns(); lCopyMode.set(theDoCopy, typePreserve, nsPreserve, nsInherit); if (!consumeNext(target, theChild1, aPlanState)) throw XQUERY_EXCEPTION( err::XUDY0027, ERROR_LOC( loc ) ); if (theType == store::UpdateConsts::BEFORE || theType == store::UpdateConsts::AFTER) { if (!target->isNode() || target->getNodeKind() == store::StoreConsts::attributeNode || target->getNodeKind() == store::StoreConsts::documentNode) throw XQUERY_EXCEPTION( err::XUTY0006, ERROR_LOC( loc ) ); if (consumeNext(temp, theChild1, aPlanState)) throw XQUERY_EXCEPTION( err::XUTY0006, ERROR_LOC( loc ) ); if (target->getParent() == NULL) throw XQUERY_EXCEPTION( err::XUDY0029, ERROR_LOC( loc ) ); parent = target->getParent(); elemParent = (parent->getNodeKind() == store::StoreConsts::elementNode); // Do not preserve the type of the source nodes (we do this here so that // we don't have to use the upd::setToUntyped() primitive later, during // the application of the PUL). if (lCopyMode.theTypePreserve && (!elemParent || parent->getType()->equals(GENV_TYPESYSTEM.XS_UNTYPED_QNAME))) lCopyMode.theTypePreserve = false; while (consumeNext(source, theChild0, aPlanState)) { ZORBA_FATAL(source->isNode(), ""); if (source->getNodeKind() == store::StoreConsts::attributeNode) { if (numNodes > 0) throw XQUERY_EXCEPTION( err::XUTY0004, ERROR_LOC( loc ) ); if (!elemParent) throw XQUERY_EXCEPTION( err::XUDY0030, ERROR_LOC( loc ) ); attrs[numAttrs++].transfer(source); if (numAttrs == attrs.size()) attrs.resize(2 * numAttrs); } else { nodes[numNodes++].transfer(source); if (numNodes == nodes.size()) nodes.resize(2 * numNodes); } } areNodeModifiersViolated(theSctx, target, loc); pul.reset(GENV_ITEMFACTORY->createPendingUpdateList()); if (numAttrs > 0) { attrs.resize(numAttrs); for (ulong i = 0; i < numAttrs; ++i) attrs[i] = attrs[i]->copy(NULL, lCopyMode); pul->addInsertAttributes(&loc, parent, attrs); } if (numNodes > 0) { nodes.resize(numNodes); for (ulong i = 0; i < numNodes; ++i) nodes[i] = nodes[i]->copy(NULL, lCopyMode); if (theType == store::UpdateConsts::BEFORE) pul->addInsertBefore(&loc, target, nodes); else pul->addInsertAfter(&loc, target, nodes); } result = pul.release(); STACK_PUSH(result != NULL, state); } else { if (!target->isNode()) throw XQUERY_EXCEPTION( err::XUTY0005, ERROR_LOC( loc ) ); targetKind = target->getNodeKind(); if (targetKind != store::StoreConsts::documentNode && targetKind != store::StoreConsts::elementNode) throw XQUERY_EXCEPTION( err::XUTY0005, ERROR_LOC( loc ) ); if (consumeNext(temp, theChild1, aPlanState)) throw XQUERY_EXCEPTION( err::XUTY0005, ERROR_LOC( loc ) ); elemTarget = (targetKind == store::StoreConsts::elementNode); if (lCopyMode.theTypePreserve && (!elemTarget || target->getType()->equals(GENV_TYPESYSTEM.XS_UNTYPED_QNAME))) lCopyMode.theTypePreserve = false; while (consumeNext(source, theChild0, aPlanState)) { ZORBA_FATAL(source->isNode(), ""); if (source->getNodeKind() == store::StoreConsts::attributeNode) { if (numNodes > 0) throw XQUERY_EXCEPTION( err::XUTY0004, ERROR_LOC( loc ) ); if (!elemTarget) throw XQUERY_EXCEPTION( err::XUTY0022, ERROR_LOC( loc ) ); attrs[numAttrs++].transfer(source); if (numAttrs == attrs.size()) attrs.resize(2 * numAttrs); } else { nodes[numNodes++].transfer(source); if (numNodes == nodes.size()) nodes.resize(2 * numNodes); } } areNodeModifiersViolated(theSctx, target, loc); pul.reset(GENV_ITEMFACTORY->createPendingUpdateList()); if (numAttrs > 0) { attrs.resize(numAttrs); for (ulong i = 0; i < numAttrs; ++i) attrs[i] = attrs[i]->copy(NULL, lCopyMode); pul->addInsertAttributes(&loc, target, attrs); } if (numNodes > 0) { nodes.resize(numNodes); for (ulong i = 0; i < numNodes; ++i) nodes[i] = nodes[i]->copy(NULL, lCopyMode); if (theType == store::UpdateConsts::INTO) pul->addInsertInto(&loc, target, nodes); else if (theType == store::UpdateConsts::AS_FIRST_INTO) pul->addInsertFirst(&loc, target, nodes); else pul->addInsertLast(&loc, target, nodes); } result = pul.release(); STACK_PUSH(result != NULL, state); } STACK_END (state); }
void init() { if (g_initFlag.load(std::memory_order_acquire)) return; Lock l(s_initLock); if (g_initFlag.load(std::memory_order_acquire)) return; // Stop profiling before attempting to acquire the instance-counts lock. The // reason for having two flags is because ReadWriteLock can in certain // implementations favor readers over writers. Thus if there's a steady stream // of calls to profile(), we'll block indefinitely waiting to acquire the // instance-counts lock. Since this function is called from JITing threads, // this can eventually lead to starvation. So, set this flag to stop other // threads from attempting to acquire the instance-counts lock, and avoid // starvation. g_profileDoneFlag.store(true, std::memory_order_release); if (!RuntimeOption::RepoAuthoritative) { g_initFlag.store(true, std::memory_order_release); return; } if (do_assert) s_initThread.store(pthread_self(), std::memory_order_release); // First, grab a write lock on s_instanceCounts and grab the current set of // counts as quickly as possible to minimize blocking other threads still // trying to profile instance checks. typedef std::pair<const StringData*, unsigned> Count; std::vector<Count> counts; uint64_t total = 0; { // If you think of the read-write lock as a shared-exclusive lock instead, // the fact that we're grabbing a write lock to iterate over the table // makes more sense: it's safe to concurrently modify a // tbb::concurrent_hash_map, but iteration is not guaranteed to be safe // with concurrent insertions. WriteLock l(s_instanceCountsLock); for (auto& pair : s_instanceCounts) { counts.push_back(pair); total += pair.second; } } std::sort(counts.begin(), counts.end(), [&](const Count& a, const Count& b) { return a.second > b.second; }); // Next, initialize s_instanceBitsMap with the top 127 most checked // classes. Bit 0 is reserved as an 'initialized' flag unsigned i = 1; uint64_t accum = 0; for (auto& item : counts) { if (i >= kNumInstanceBits) break; auto const cls = Unit::lookupUniqueClassInContext(item.first, nullptr); if (cls) { assertx(cls->attrs() & AttrUnique); s_instanceBitsMap[item.first] = i; accum += item.second; ++i; } } // Print out stats about what we ended up using if (Trace::moduleEnabledRelease(Trace::instancebits, 1)) { Trace::traceRelease("%s: %u classes, %" PRIu64 " (%.2f%%) of warmup" " checks\n", __FUNCTION__, i-1, accum, 100.0 * accum / total); if (Trace::moduleEnabledRelease(Trace::instancebits, 2)) { accum = 0; i = 1; for (auto& pair : counts) { if (i >= 256) { Trace::traceRelease("skipping the remainder of the %zu classes\n", counts.size()); break; } accum += pair.second; Trace::traceRelease("%3u %5.2f%% %7u -- %6.2f%% %7" PRIu64 " %s\n", i++, 100.0 * pair.second / total, pair.second, 100.0 * accum / total, accum, pair.first->data()); } } } // Finally, update m_instanceBits on every Class that currently exists. This // must be done while holding a lock that blocks insertion of new Classes // into their class lists, but in practice most Classes will already be // created by now and this process is very fast. WriteLock clsLocker(g_clsInitLock); NamedEntity::foreach_class([&](Class* cls) { cls->setInstanceBitsAndParents(); }); if (do_assert) { // There isn't a canonical invalid pthread_t, but this is only used for the // assert in lookup() and it's ok to have false negatives. s_initThread.store(pthread_t{}, std::memory_order_release); } g_initFlag.store(true, std::memory_order_release); }
void cgCall(IRLS& env, const IRInstruction* inst) { auto const sp = srcLoc(env, inst, 0).reg(); auto const fp = srcLoc(env, inst, 1).reg(); auto const extra = inst->extra<Call>(); auto const callee = extra->callee; auto const argc = extra->numParams; auto& v = vmain(env); auto& vc = vcold(env); auto const catchBlock = label(env, inst->taken()); auto const calleeSP = sp[cellsToBytes(extra->spOffset.offset)]; auto const calleeAR = calleeSP + cellsToBytes(argc); v << store{fp, calleeAR + AROFF(m_sfp)}; v << storeli{safe_cast<int32_t>(extra->after), calleeAR + AROFF(m_soff)}; if (extra->fcallAwait) { // This clobbers any flags that might have already been set on the callee // AR (e.g., by SpillFrame), but this is okay because there should never be // any conflicts; see the documentation in act-rec.h. auto const imm = static_cast<int32_t>( ActRec::encodeNumArgsAndFlags(argc, ActRec::Flags::IsFCallAwait) ); v << storeli{imm, calleeAR + AROFF(m_numArgsAndFlags)}; } auto const isNativeImplCall = callee && callee->builtinFuncPtr() && !callee->nativeFuncPtr() && argc == callee->numParams(); if (isNativeImplCall) { // The assumption here is that for builtins, the generated func contains // only a single opcode (NativeImpl), and there are no non-argument locals. if (do_assert) { assertx(argc == callee->numLocals()); assertx(callee->numIterators() == 0); auto addr = callee->getEntry(); while (peek_op(addr) == Op::AssertRATL) { addr += instrLen(addr); } assertx(peek_op(addr) == Op::NativeImpl); assertx(addr + instrLen(addr) == callee->unit()->entry() + callee->past()); } v << store{v.cns(mcg->ustubs().retHelper), calleeAR + AROFF(m_savedRip)}; if (callee->attrs() & AttrMayUseVV) { v << storeqi{0, calleeAR + AROFF(m_invName)}; } v << lea{calleeAR, rvmfp()}; emitCheckSurpriseFlagsEnter(v, vc, fp, Fixup(0, argc), catchBlock); auto const builtinFuncPtr = callee->builtinFuncPtr(); TRACE(2, "Calling builtin preClass %p func %p\n", callee->preClass(), builtinFuncPtr); // We sometimes call this while curFunc() isn't really the builtin, so make // sure to record the sync point as if we are inside the builtin. if (FixupMap::eagerRecord(callee)) { auto const syncSP = v.makeReg(); v << lea{calleeSP, syncSP}; emitEagerSyncPoint(v, callee->getEntry(), rvmtl(), rvmfp(), syncSP); } // Call the native implementation. This will free the locals for us in the // normal case. In the case where an exception is thrown, the VM unwinder // will handle it for us. auto const done = v.makeBlock(); v << vinvoke{CallSpec::direct(builtinFuncPtr), v.makeVcallArgs({{rvmfp()}}), v.makeTuple({}), {done, catchBlock}, Fixup(0, argc)}; env.catch_calls[inst->taken()] = CatchCall::CPP; v = done; // The native implementation already put the return value on the stack for // us, and handled cleaning up the arguments. We have to update the frame // pointer and the stack pointer, and load the return value into the return // register so the trace we are returning to has it where it expects. // TODO(#1273094): We should probably modify the actual builtins to return // values via registers using the C ABI and do a reg-to-reg move. loadTV(v, inst->dst(), dstLoc(env, inst, 0), rvmfp()[AROFF(m_r)], true); v << load{rvmfp()[AROFF(m_sfp)], rvmfp()}; emitRB(v, Trace::RBTypeFuncExit, callee->fullName()->data()); return; } v << lea{calleeAR, rvmfp()}; if (RuntimeOption::EvalHHIRGenerateAsserts) { v << syncvmsp{v.cns(0x42)}; constexpr uint64_t kUninitializedRIP = 0xba5eba11acc01ade; emitImmStoreq(v, kUninitializedRIP, rvmfp()[AROFF(m_savedRip)]); } // Emit a smashable call that initially calls a recyclable service request // stub. The stub and the eventual targets take rvmfp() as an argument, // pointing to the callee ActRec. auto const target = callee ? mcg->ustubs().immutableBindCallStub : mcg->ustubs().bindCallStub; auto const done = v.makeBlock(); v << callphp{target, php_call_regs(), {{done, catchBlock}}}; env.catch_calls[inst->taken()] = CatchCall::PHP; v = done; auto const dst = dstLoc(env, inst, 0); v << defvmret{dst.reg(0), dst.reg(1)}; }
/* * Command line options for autostart (keep synchronized with binaries/system/readme.txt): * * -autostart="TYPEDIR/MAPNAME" enables autostart and sets MAPNAME; TYPEDIR is skirmishes, scenarios, or random * -autostart-ai=PLAYER:AI sets the AI for PLAYER (e.g. 2:petra) * -autostart-aidiff=PLAYER:DIFF sets the DIFFiculty of PLAYER's AI (0: sandbox, 5: very hard) * -autostart-civ=PLAYER:CIV sets PLAYER's civilisation to CIV (skirmish and random maps only) * -autostart-aiseed=AISEED sets the seed used for the AI random generator (default 0, use -1 for random) * Multiplayer: * -autostart-playername=NAME sets local player NAME (default 'anonymous') * -autostart-host sets multiplayer host mode * -autostart-host-players=NUMBER sets NUMBER of human players for multiplayer game (default 2) * -autostart-client=IP sets multiplayer client to join host at given IP address * Random maps only: * -autostart-seed=SEED sets random map SEED value (default 0, use -1 for random) * -autostart-size=TILES sets random map size in TILES (default 192) * -autostart-players=NUMBER sets NUMBER of players on random map (default 2) * * Examples: * 1) "Bob" will host a 2 player game on the Arcadia map: * -autostart="scenarios/Arcadia 02" -autostart-host -autostart-host-players=2 -autostart-playername="Bob" * 2) Load Alpine Lakes random map with random seed, 2 players (Athens and Britons), and player 2 is PetraBot: * -autostart="random/alpine_lakes" -autostart-seed=-1 -autostart-players=2 -autostart-civ=1:athen -autostart-civ=2:brit -autostart-ai=2:petra */ bool Autostart(const CmdLineArgs& args) { CStr autoStartName = args.Get("autostart"); if (autoStartName.empty()) return false; g_Game = new CGame(); ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface(); JSContext* cx = scriptInterface.GetContext(); JSAutoRequest rq(cx); JS::RootedValue attrs(cx); scriptInterface.Eval("({})", &attrs); JS::RootedValue settings(cx); scriptInterface.Eval("({})", &settings); JS::RootedValue playerData(cx); scriptInterface.Eval("([])", &playerData); // The directory in front of the actual map name indicates which type // of map is being loaded. Drawback of this approach is the association // of map types and folders is hard-coded, but benefits are: // - No need to pass the map type via command line separately // - Prevents mixing up of scenarios and skirmish maps to some degree Path mapPath = Path(autoStartName); std::wstring mapDirectory = mapPath.Parent().Filename().string(); std::string mapType; if (mapDirectory == L"random") { // Default seed is 0 u32 seed = 0; CStr seedArg = args.Get("autostart-seed"); if (!seedArg.empty()) { // Random seed value if (seedArg == "-1") seed = rand(); else seed = seedArg.ToULong(); } // Random map definition will be loaded from JSON file, so we need to parse it std::wstring scriptPath = L"maps/" + autoStartName.FromUTF8() + L".json"; JS::RootedValue scriptData(cx); scriptInterface.ReadJSONFile(scriptPath, &scriptData); if (!scriptData.isUndefined() && scriptInterface.GetProperty(scriptData, "settings", &settings)) { // JSON loaded ok - copy script name over to game attributes std::wstring scriptFile; scriptInterface.GetProperty(settings, "Script", scriptFile); scriptInterface.SetProperty(attrs, "script", scriptFile); // RMS filename } else { // Problem with JSON file LOGERROR("Autostart: Error reading random map script '%s'", utf8_from_wstring(scriptPath)); throw PSERROR_Game_World_MapLoadFailed("Error reading random map script.\nCheck application log for details."); } // Get optional map size argument (default 192) uint mapSize = 192; if (args.Has("autostart-size")) { CStr size = args.Get("autostart-size"); mapSize = size.ToUInt(); } scriptInterface.SetProperty(settings, "Seed", seed); // Random seed scriptInterface.SetProperty(settings, "Size", mapSize); // Random map size (in patches) // Get optional number of players (default 2) size_t numPlayers = 2; if (args.Has("autostart-players")) { CStr num = args.Get("autostart-players"); numPlayers = num.ToUInt(); } // Set up player data for (size_t i = 0; i < numPlayers; ++i) { JS::RootedValue player(cx); scriptInterface.Eval("({})", &player); // We could load player_defaults.json here, but that would complicate the logic // even more and autostart is only intended for developers anyway scriptInterface.SetProperty(player, "Civ", std::string("athen")); scriptInterface.SetPropertyInt(playerData, i, player); } mapType = "random"; } else if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes") { // Initialize general settings from the map data so some values // (e.g. name of map) are always present, even when autostart is // partially configured CStr8 mapSettingsJSON = LoadSettingsOfScenarioMap("maps/" + autoStartName + ".xml"); scriptInterface.ParseJSON(mapSettingsJSON, &settings); // Initialize the playerData array being modified by autostart // with the real map data, so sensible values are present: scriptInterface.GetProperty(settings, "PlayerData", &playerData); if (mapDirectory == L"scenarios") mapType = "scenario"; else mapType = "skirmish"; } else { LOGERROR("Autostart: Unrecognized map type '%s'", utf8_from_wstring(mapDirectory)); throw PSERROR_Game_World_MapLoadFailed("Unrecognized map type.\nConsult readme.txt for the currently supported types."); } scriptInterface.SetProperty(attrs, "mapType", mapType); scriptInterface.SetProperty(attrs, "map", std::string("maps/" + autoStartName)); scriptInterface.SetProperty(settings, "mapType", mapType); // Set seed for AIs u32 aiseed = 0; if (args.Has("autostart-aiseed")) { CStr seedArg = args.Get("autostart-aiseed"); if (seedArg == "-1") aiseed = rand(); else aiseed = seedArg.ToULong(); } scriptInterface.SetProperty(settings, "AISeed", aiseed); // Set player data for AIs // attrs.settings = { PlayerData: [ { AI: ... }, ... ] }: if (args.Has("autostart-ai")) { std::vector<CStr> aiArgs = args.GetMultiple("autostart-ai"); for (size_t i = 0; i < aiArgs.size(); ++i) { int playerID = aiArgs[i].BeforeFirst(":").ToInt(); // Instead of overwriting existing player data, modify the array JS::RootedValue player(cx); if (!scriptInterface.GetPropertyInt(playerData, playerID-1, &player) || player.isUndefined()) { if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes") { // playerID is certainly bigger than this map player number LOGWARNING("Autostart: Invalid player %d in autostart-ai option", playerID); continue; } scriptInterface.Eval("({})", &player); } CStr name = aiArgs[i].AfterFirst(":"); scriptInterface.SetProperty(player, "AI", std::string(name)); scriptInterface.SetProperty(player, "AIDiff", 3); scriptInterface.SetPropertyInt(playerData, playerID-1, player); } } // Set AI difficulty if (args.Has("autostart-aidiff")) { std::vector<CStr> civArgs = args.GetMultiple("autostart-aidiff"); for (size_t i = 0; i < civArgs.size(); ++i) { int playerID = civArgs[i].BeforeFirst(":").ToInt(); // Instead of overwriting existing player data, modify the array JS::RootedValue player(cx); if (!scriptInterface.GetPropertyInt(playerData, playerID-1, &player) || player.isUndefined()) { if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes") { // playerID is certainly bigger than this map player number LOGWARNING("Autostart: Invalid player %d in autostart-aidiff option", playerID); continue; } scriptInterface.Eval("({})", &player); } int difficulty = civArgs[i].AfterFirst(":").ToInt(); scriptInterface.SetProperty(player, "AIDiff", difficulty); scriptInterface.SetPropertyInt(playerData, playerID-1, player); } } // Set player data for Civs if (args.Has("autostart-civ")) { if (mapDirectory != L"scenarios") { std::vector<CStr> civArgs = args.GetMultiple("autostart-civ"); for (size_t i = 0; i < civArgs.size(); ++i) { int playerID = civArgs[i].BeforeFirst(":").ToInt(); // Instead of overwriting existing player data, modify the array JS::RootedValue player(cx); if (!scriptInterface.GetPropertyInt(playerData, playerID-1, &player) || player.isUndefined()) { if (mapDirectory == L"skirmishes") { // playerID is certainly bigger than this map player number LOGWARNING("Autostart: Invalid player %d in autostart-civ option", playerID); continue; } scriptInterface.Eval("({})", &player); } CStr name = civArgs[i].AfterFirst(":"); scriptInterface.SetProperty(player, "Civ", std::string(name)); scriptInterface.SetPropertyInt(playerData, playerID-1, player); } } else LOGWARNING("Autostart: Option 'autostart-civ' is invalid for scenarios"); } // Add player data to map settings scriptInterface.SetProperty(settings, "PlayerData", playerData); // Add map settings to game attributes scriptInterface.SetProperty(attrs, "settings", settings); JS::RootedValue mpInitData(cx); scriptInterface.Eval("({isNetworked:true, playerAssignments:{}})", &mpInitData); scriptInterface.SetProperty(mpInitData, "attribs", attrs); // Get optional playername CStrW userName = L"anonymous"; if (args.Has("autostart-playername")) { userName = args.Get("autostart-playername").FromUTF8(); } if (args.Has("autostart-host")) { InitPs(true, L"page_loading.xml", &scriptInterface, mpInitData); size_t maxPlayers = 2; if (args.Has("autostart-host-players")) maxPlayers = args.Get("autostart-host-players").ToUInt(); g_NetServer = new CNetServer(maxPlayers); g_NetServer->UpdateGameAttributes(&attrs, scriptInterface); bool ok = g_NetServer->SetupConnection(); ENSURE(ok); g_NetClient = new CNetClient(g_Game); g_NetClient->SetUserName(userName); g_NetClient->SetupConnection("127.0.0.1"); } else if (args.Has("autostart-client")) { InitPs(true, L"page_loading.xml", &scriptInterface, mpInitData); g_NetClient = new CNetClient(g_Game); g_NetClient->SetUserName(userName); CStr ip = args.Get("autostart-client"); if (ip.empty()) ip = "127.0.0.1"; bool ok = g_NetClient->SetupConnection(ip); ENSURE(ok); } else { g_Game->SetPlayerID(1); g_Game->StartGame(&attrs, ""); LDR_NonprogressiveLoad(); PSRETURN ret = g_Game->ReallyStartGame(); ENSURE(ret == PSRETURN_OK); InitPs(true, L"page_session.xml", NULL, JS::UndefinedHandleValue); } return true; }
int runTests( int argc, char* argv[]) { // Just hoist everything... XALAN_CPP_NAMESPACE_USE MemoryManagerType& theManager = XalanMemMgrs::getDefaultXercesMemMgr(); XalanFileUtility h(theManager); // Set the program help string, then get the command line parameters. // setHelp(h); bool setGold = false; const XalanDOMString processorType(XALAN_STATIC_UCODE_STRING("XalanC")); if (h.getParams(argc, argv, "PERFT-RESULTS", setGold) == true) { XalanTransformer xalan; // Generate Unique Run id and processor info XalanDOMString UniqRunid; h.generateUniqRunid(UniqRunid); // Defined basic constants for file manipulation and open results file const XalanDOMString resultFilePrefix("cpp"); XalanDOMString resultsFile= h.args.output; resultsFile += resultFilePrefix; resultsFile += UniqRunid; resultsFile += XalanFileUtility::s_xmlSuffix; XalanXMLFileReporter logFile(theManager, resultsFile); logFile.logTestFileInit("Performance Testing - Reports various performance metrics using the Transformer"); // Get the list of sub-directories below "base" and iterate through them bool foundDir = false; // Flag indicates directory found. Used in conjunction with -sub cmd-line arg. typedef XalanFileUtility::FileNameVectorType FileNameVectorType; FileNameVectorType dirs; h.getDirectoryNames(h.args.base, dirs); for(FileNameVectorType::size_type j = 0; j < dirs.size(); j++) { // Run specific category of files from given directory if (length(h.args.sub) > 0 && !equals(dirs[j], h.args.sub)) { continue; } cout << "Processing files in Directory: " << dirs[j] << endl; // Check that output directory is there. XalanDOMString theOutputDir = h.args.output; theOutputDir += dirs[j]; h.checkAndCreateDir(theOutputDir); // Indicate that directory was processed and get test files from the directory foundDir = true; FileNameVectorType files; h.getTestFileNames(h.args.base, dirs[j], false, files); XalanDOMString logEntry; logEntry = "Performance Directory: "; logEntry += dirs[j]; logFile.logTestCaseInit(logEntry); const long iterCount = h.args.iters; for(FileNameVectorType::size_type i = 0; i < files.size(); i++) { // Define variables used for timing and reporting ... clock_t startTime, endTime, accmTime, avgEtoe; double timeinMilliseconds = 0, theAverage =0; int transformResult = 0; typedef XalanXMLFileReporter::Hashtable Hashtable; Hashtable attrs(theManager); attrs.insert(Hashtable::value_type(XalanDOMString("idref"), files[i])); attrs.insert(Hashtable::value_type(XalanDOMString("UniqRunid"),UniqRunid)); attrs.insert(Hashtable::value_type(XalanDOMString("processor"),processorType)); logFile.addMetricToAttrs("Iterations",iterCount, attrs); if (h.args.skip) { if (checkForExclusion(files[i])) continue; } XalanDOMString theXSLFile = h.args.base; theXSLFile += dirs[j]; theXSLFile += XalanFileUtility::s_pathSep; theXSLFile += files[i]; XalanDOMString theXMLFile; h.generateFileName(theXSLFile,"xml", theXMLFile); XalanDOMString outbase = h.args.output; outbase += dirs[j]; outbase += XalanFileUtility::s_pathSep; outbase += files[i]; XalanDOMString theOutputFile; h.generateFileName(outbase, "out", theOutputFile); const XSLTInputSource xslInputSource(theXSLFile); const XSLTInputSource xmlInputSource(theXMLFile); const XSLTResultTarget theResultTarget(theOutputFile); attrs.insert(Hashtable::value_type(XalanDOMString("href"), theXSLFile)); cout << endl << files[i] << endl; // Time the parsing(compile) of the XSL stylesheet and report the results.. // startTime = clock(); const XalanCompiledStylesheet* compiledSS = 0; xalan.compileStylesheet(xslInputSource, compiledSS); endTime = clock(); if (compiledSS == 0) { continue; } timeinMilliseconds = calculateElapsedTime(startTime, endTime); cout << " XSL: " << timeinMilliseconds << " milliseconds, Parse" << endl; logFile.addMetricToAttrs("parsexsl",timeinMilliseconds, attrs); // Time the parsing of the input XML and report the results.. // startTime = clock(); const XalanParsedSource* parsedSource = 0; xalan.parseSource(xmlInputSource, parsedSource); endTime = clock(); if (parsedSource == 0) { continue; } timeinMilliseconds = calculateElapsedTime(startTime, endTime); cout << " XML: " << timeinMilliseconds << " milliseconds, Parse" <<endl; logFile.addMetricToAttrs("parsexml",timeinMilliseconds, attrs); // Perform One transform using parsed stylesheet and unparsed xml source, report results... // startTime = clock(); transformResult = xalan.transform(xmlInputSource, compiledSS, theResultTarget); endTime = clock(); if(!transformResult) { timeinMilliseconds = calculateElapsedTime(startTime, endTime); cout << endl << " One: " << timeinMilliseconds << " w/Parsed XSL." << endl; logFile.addMetricToAttrs("single", timeinMilliseconds, attrs); } else { cout << xalan.getLastError(); return -1; } // Do One eTOe transform with no pre parsing of either xsl or xml files. // And output metrics to console and result log startTime = clock(); transformResult = xalan.transform(xmlInputSource, xslInputSource, theResultTarget); endTime = clock(); if(!transformResult) { timeinMilliseconds = calculateElapsedTime(startTime, endTime); cout << " One: " << timeinMilliseconds << " eTOe." << endl; logFile.addMetricToAttrs("etoe", timeinMilliseconds, attrs); } else { cout << xalan.getLastError(); return -1; } // Perform multiple transforms and calculate the average time .. // These are done 3 different ways. // // FIRST: Parsed XSL Stylesheet and Parsed XML Source. // accmTime = 0; for(int j = 0; j < iterCount; ++j) { startTime = clock(); transformResult = xalan.transform(*parsedSource, compiledSS, theResultTarget); endTime = clock(); accmTime += endTime - startTime; } theAverage = calculateAvgTime(accmTime, iterCount); cout << endl << " Avg: " << theAverage << " for " << iterCount << " iter's w/Parsed files" << endl; logFile.addMetricToAttrs("avgparsedxml",theAverage, attrs); // SECOND: Parsed Stylesheet and UnParsed XML Source. // This is currently how the XalanJ 2.0 is performing transforms // accmTime = 0; for(int k = 0; k < iterCount; ++k) { startTime = clock(); transformResult = xalan.transform(xmlInputSource, compiledSS, theResultTarget); endTime = clock(); accmTime += endTime - startTime; } theAverage = calculateAvgTime(accmTime, iterCount); cout << " Avg: " << theAverage << " for " << iterCount << " iter's w/UnParsed XML" << endl; logFile.addMetricToAttrs("avgunparsedxml",theAverage, attrs); // THIRD: Neither Stylesheet nor XML Source are parsed. // Perform multiple etoe transforms and calculate the average ... // avgEtoe = 0; for(int jj = 0; jj < iterCount; ++jj) { startTime = clock(); transformResult = xalan.transform(xmlInputSource, xslInputSource, theResultTarget); endTime = clock(); avgEtoe += endTime - startTime; } theAverage = calculateAvgTime(avgEtoe,iterCount); // Output average transform time to console and result log cout << " Avg: " << theAverage << " for " << iterCount << " iter's of eToe" << endl; logFile.addMetricToAttrs("avgetoe",theAverage, attrs); logFile.logElementWAttrs(10, "perf", attrs, "xxx"); xalan.destroyParsedSource(parsedSource); xalan.destroyStylesheet(compiledSS); } logEntry = "Performance Directory: "; logEntry += dirs[j]; logFile.logTestCaseClose(logEntry, XalanDOMString("Done")); } // Check to see if -sub cmd-line directory was processed correctly. if (!foundDir) { cout << "Specified test directory: \"" << c_str(TranscodeToLocalCodePage(h.args.sub)) << "\" not found" << endl; } h.reportPassFail(logFile, UniqRunid); logFile.logTestFileClose("Performance", "Done"); logFile.close(); } return 0; }
ScXmlStreamAttributes ScXmlStreamReader::scAttributes(void) const { ScXmlStreamAttributes attrs(attributes()); return attrs; }
Object c_Closure::t_bindto(const Variant& newthis, const Variant& scope) { if (RuntimeOption::RepoAuthoritative && RuntimeOption::EvalAllowScopeBinding) { raise_warning("Closure binding is not supported in RepoAuthoritative mode"); return Object{}; } auto const cls = getVMClass(); auto const invoke = cls->getCachedInvoke(); ObjectData* od = nullptr; if (newthis.isObject()) { if (invoke->isStatic()) { raise_warning("Cannot bind an instance to a static closure"); } else { od = newthis.getObjectData(); } } else if (!newthis.isNull()) { raise_warning("Closure::bindto() expects parameter 1 to be object"); return Object{}; } auto const curscope = invoke->cls(); auto newscope = curscope; if (scope.isObject()) { newscope = scope.getObjectData()->getVMClass(); } else if (scope.isString()) { auto const className = scope.getStringData(); if (!className->equal(s_static.get())) { newscope = Unit::loadClass(className); if (!newscope) { raise_warning("Class '%s' not found", className->data()); return Object{}; } } } else if (scope.isNull()) { newscope = nullptr; } else { raise_warning("Closure::bindto() expects parameter 2 " "to be string or object"); return Object{}; } if (od && !newscope) { // Bound closures should be scoped. If no scope is specified, scope it to // the Closure class. newscope = static_cast<Class*>(c_Closure::classof()); } bool thisNotOfCtx = od && !od->getVMClass()->classof(newscope); if (!RuntimeOption::EvalAllowScopeBinding) { if (newscope != curscope) { raise_warning("Re-binding closure scopes is disabled"); return Object{}; } if (thisNotOfCtx) { raise_warning("Binding to objects not subclassed from closure " "context is disabled"); return Object{}; } } c_Closure* clone = Clone(this); clone->setClass(nullptr); Attr curattrs = invoke->attrs(); Attr newattrs = static_cast<Attr>(curattrs & ~AttrHasForeignThis); if (od) { od->incRefCount(); clone->setThis(od); if (thisNotOfCtx) { // If the bound $this is not a subclass of the context class, then we // have to pessimize translation. newattrs |= AttrHasForeignThis; } } else if (newscope) { // If we attach a scope to a function with no bound $this we need to make // the function static. newattrs |= AttrStatic; clone->setClass(newscope); } // If we are changing either the scope or the attributes of the closure, we // need to re-scope its Closure subclass. if (newscope != curscope || newattrs != curattrs) { assert(newattrs != AttrNone); auto newcls = cls->rescope(newscope, newattrs); clone->setVMClass(newcls); } return Object(clone); }
string conf_gen::gen_conf() { string spec_line = "# COMPUTE NODES"; string ctlmachine_line = "ControlMachine=##"; string ctladdr_line = "ControlAddr=##"; bool spec_line_hit = false; string conf_line; ifstream ifs(_conf_file); while (getline(ifs, conf_line)) { // string line = replace_at_tok(conf_line); string line = conf_line; if (line == spec_line) { //"# COMPUTE NODES"; spec_line_hit = true; _conf_list.push_back(line); } else if (line == ctlmachine_line) { //ControlMachine=## char buf[100]; sprintf(buf, "ControlMachine=%s", _ctlmachine.c_str()); string tmp(buf); _conf_list.push_back(tmp); } else if (line == ctladdr_line) { //ControlAddr=## char buf[100]; sprintf(buf, "ControlAddr=%s", _ctladdr.c_str()); string tmp(buf); _conf_list.push_back(tmp); } else { if (spec_line_hit) { _store_list.push_back(line); //spec_line_hit = false; } else { _conf_list.push_back(line); } } } /*NodeName=node-[3-4] Nodeaddr=node-[3-4].xiaobing.usrc CPUs=2 Sockets=2 CoresPerSocket=1 ThreadsPerCore=1 State=UNKNOWN*/ for (IT it = _store_list.begin(); it != _store_list.end(); it++) { str_tok attrs(*it); // " ", delimiter bool nodes_hit = false; bool nodename_hit = false; bool nodeaddr_hit = false; string nodes = "Nodes"; //Nodes=node-[2-101] string nodename = "NodeName"; //NodeName=node-[2-101] string nodeaddr = "Nodeaddr"; //Nodeaddr=node-[3-4].xiaobing.usrc while (attrs.has_more_tokens()) { string attr = trim(attrs.next_token()); //Nodeaddr=node-[3-4].xiaobing.usrc str_tok name_value(attr, "="); string name = name_value.next_token(); //e.g. Nodeaddr if (name == nodes) { //"Nodes" nodes_hit = true; } else if (name == nodename) { //"NodeName" nodename_hit = true; } else if (name == nodeaddr) { //"Nodeaddr" nodeaddr_hit = true; } else ; if (nodes_hit) { char buf[100]; sprintf(buf, "Nodes=node-[%d-%d]", _start, _end); string tmp(buf); _spec_list.push_back(tmp); nodes_hit = false; } else if (nodename_hit) { char buf[100]; sprintf(buf, "NodeName=node-[%d-%d]", _start, _end); string tmp(buf); _spec_list.push_back(tmp); nodename_hit = false; } else if (nodeaddr_hit) { string node_addr_list = gen_node_arr_list(); char buf[10000]; sprintf(buf, "Nodeaddr=%s", node_addr_list.c_str()); string tmp(buf); _spec_list.push_back(tmp); nodeaddr_hit = false; } else { _spec_list.push_back(attr); } } _spec_list.push_back("\n"); } return to_string(); }