bool TypesystemStructHandler::startCommand(Variant::mapType &args) { scope().setFlag(ParserFlag::POST_HEAD, true); // Fetch the arguments used for creating this type const std::string &structName = args["name"].asString(); const std::string &parent = args["parent"].asString(); // Fetch the current typesystem and create the struct node Rooted<Typesystem> typesystem = scope().selectOrThrow<Typesystem>(); Rooted<StructType> structType = typesystem->createStructType(structName); structType->setLocation(location()); // Try to resolve the parent type and set it as parent structure if (!parent.empty()) { scope().resolve<StructType>( parent, structType, logger(), [](Handle<Node> parent, Handle<Node> structType, Logger &logger) { if (parent != nullptr) { structType.cast<StructType>()->setParentStructure( parent.cast<StructType>(), logger); } }); } scope().push(structType); return true; }
static inline void MarkExactStackRootList(JSTracer* trc, Source* s, const char* name) { Rooted<T>* rooter = s->roots.template gcRooters<T>(); while (rooter) { T* addr = rooter->address(); TraceFn(trc, addr, name); rooter = rooter->previous(); } }
static inline void MarkExactStackRootList(JSTracer *trc, Source *s, const char *name) { Rooted<T> *rooter = s->template gcRooters<T>(); while (rooter) { T *addr = rooter->address(); if (!IgnoreExactRoot(addr)) MarkFunc(trc, addr, name); rooter = rooter->previous(); } }
static void GatherRooters(Vector<Rooter, 0, SystemAllocPolicy> &rooters, Rooted<void*> **thingGCRooters, unsigned thingRootKind) { Rooted<void*> *rooter = thingGCRooters[thingRootKind]; while (rooter) { Rooter r = { rooter, ThingRootKind(thingRootKind) }; JS_ALWAYS_TRUE(rooters.append(r)); rooter = rooter->previous(); } }
bool TypesystemEnumHandler::startCommand(Variant::mapType &args) { scope().setFlag(ParserFlag::POST_HEAD, true); // Fetch the current typesystem and create the enum node Rooted<Typesystem> typesystem = scope().selectOrThrow<Typesystem>(); Rooted<EnumType> enumType = typesystem->createEnumType(args["name"].asString()); enumType->setLocation(location()); scope().push(enumType); return true; }
~EvalScriptGuard() { if (script_) { script_->cacheForEval(); EvalCacheEntry cacheEntry = {script_, lookup_.callerScript, lookup_.pc}; lookup_.str = lookupStr_; if (lookup_.str && IsEvalCacheCandidate(script_)) cx_->runtime()->evalCache.relookupOrAdd(p_, lookup_, cacheEntry); } }
static inline void MarkExactStackRooters(JSTracer *trc, Rooted<void*> rooter, ThingRootKind kind) { Rooted<void*> *rooter = cx->thingGCRooters[i]; while (rooter) { MarkExactStackRoot(trc, rooter, ThingRootKind(i)); rooter = rooter->previous(); } }
~EvalScriptGuard() { if (script_) { CallDestroyScriptHook(cx_->runtime()->defaultFreeOp(), script_); script_->cacheForEval(); EvalCacheEntry cacheEntry = {script_, lookup_.callerScript, lookup_.pc}; lookup_.str = lookupStr_; if (lookup_.str && IsEvalCacheCandidate(script_)) cx_->runtime()->evalCache.relookupOrAdd(p_, lookup_, cacheEntry); } }
~EvalScriptGuard() { if (script_) { script_->cacheForEval(); EvalCacheEntry cacheEntry = {lookupStr_, script_, lookup_.callerScript, lookup_.pc}; lookup_.str = lookupStr_; if (lookup_.str && IsEvalCacheCandidate(script_)) { bool ok = cx_->runtime()->evalCache.relookupOrAdd(p_, lookup_, cacheEntry); (void)ok; // Ignore failure to add cache entry. } } }
bool TypesystemHandler::startCommand(Variant::mapType &args) { // Create the typesystem instance Rooted<Typesystem> typesystem = context().getProject()->createTypesystem(args["name"].asString()); typesystem->setLocation(location()); // If the typesystem is defined inside a ontology, add a reference to the // typesystem to the ontology -- do the same with a document, if no ontology // is found Rooted<Ontology> ontology = scope().select<Ontology>(); if (ontology != nullptr) { ontology->reference(typesystem); } else { Rooted<Document> document = scope().select<Document>(); if (document != nullptr) { document->reference(typesystem); } } // Push the typesystem onto the scope, set the POST_HEAD flag to true scope().push(typesystem); scope().setFlag(ParserFlag::POST_HEAD, false); return true; }
void lookupInEvalCache(JSLinearString *str, JSScript *callerScript, jsbytecode *pc) { lookupStr_ = str; lookup_.str = str; lookup_.callerScript = callerScript; lookup_.version = cx_->findVersion(); lookup_.pc = pc; p_ = cx_->runtime()->evalCache.lookupForAdd(lookup_); if (p_) { script_ = p_->script; cx_->runtime()->evalCache.remove(p_); script_->uncacheForEval(); } }
bool TypesystemConstantHandler::startCommand(Variant::mapType &args) { scope().setFlag(ParserFlag::POST_HEAD, true); // Read the argument values const std::string &constantName = args["name"].asString(); const std::string &type = args["type"].asString(); const Variant &value = args["value"]; Rooted<Typesystem> typesystem = scope().selectOrThrow<Typesystem>(); Rooted<Constant> constant = typesystem->createConstant(constantName, value); constant->setLocation(location()); // Try to resolve the type scope().resolveTypeWithValue( type, constant, constant->getValue(), logger(), [](Handle<Node> type, Handle<Node> constant, Logger &logger) { if (type != nullptr) { constant.cast<Constant>()->setType(type.cast<Type>(), logger); } }); return true; }
bool TypesystemStructFieldHandler::startCommand(Variant::mapType &args) { // Read the argument values const std::string &fieldName = args["name"].asString(); const std::string &type = args["type"].asString(); const Variant &defaultValue = args["default"]; const bool optional = !(defaultValue.isObject() && defaultValue.asObject() == nullptr); Rooted<StructType> structType = scope().selectOrThrow<StructType>(); Rooted<Attribute> attribute = structType->createAttribute( fieldName, defaultValue, optional, logger()); attribute->setLocation(location()); // Try to resolve the type and default value if (optional) { scope().resolveTypeWithValue( type, attribute, attribute->getDefaultValue(), logger(), [](Handle<Node> type, Handle<Node> attribute, Logger &logger) { if (type != nullptr) { attribute.cast<Attribute>()->setType(type.cast<Type>(), logger); } }); } else { scope().resolveType(type, attribute, logger(), [](Handle<Node> type, Handle<Node> attribute, Logger &logger) { if (type != nullptr) { attribute.cast<Attribute>()->setType(type.cast<Type>(), logger); } }); } return true; }
static inline void MarkExactStackRooter(JSTracer *trc, Rooted<void*> rooter, ThingRootKind kind) { void **addr = (void **)rooter->address(); if (!*addr) return; switch (kind) { case THING_ROOT_OBJECT: MarkObjectRoot(trc, (JSObject **)addr, "exact-object"); break; case THING_ROOT_STRING: MarkStringRoot(trc, (JSSTring **)addr, "exact-string"); break; case THING_ROOT_SCRIPT: MarkScriptRoot(trc, (JSScript **)addr, "exact-script"); break; case THING_ROOT_SHAPE: MarkShapeRoot(trc, (Shape **)addr, "exact-shape"); break; case THING_ROOT_BASE_SHAPE: MarkBaseShapeRoot(trc, (BaseShape **)addr, "exact-baseshape"); break; case THING_ROOT_TYPE: MarkTypeRoot(trc, (types::Type *)addr, "exact-type"); break; case THING_ROOT_TYPE_OBJECT: MarkTypeObjectRoot(trc, (types::TypeObject **)addr, "exact-typeobject"); break; case THING_ROOT_VALUE: MarkValueRoot(trc, (Value *)addr, "exact-value"); break; case THING_ROOT_ID: MarkIdRoot(trc, (jsid *)addr, "exact-id"); break; case THING_ROOT_PROPERTY_ID: MarkIdRoot(trc, &((js::PropertyId *)addr)->asId(), "exact-propertyid"); break; case THING_ROOT_BINDINGS: ((Bindings *)addr)->trace(trc); break; default: JS_NOT_REACHED("Invalid THING_ROOT kind"); break; } }
void TypesystemEnumEntryHandler::doHandle(const Variant &fieldData, Variant::mapType &args) { Rooted<EnumType> enumType = scope().selectOrThrow<EnumType>(); enumType->addEntry(fieldData.asString(), logger()); }
void setNewScript(JSScript *script) { // JSScript::initFromEmitter has already called js_CallNewScriptHook. JS_ASSERT(!script_ && script); script_ = script; script_->setActiveEval(); }
void JS::CheckStackRoots(JSContext *cx) { JSRuntime *rt = cx->runtime; if (rt->gcZeal_ != ZealStackRootingSafeValue && rt->gcZeal_ != ZealStackRootingValue) return; if (rt->gcZeal_ == ZealStackRootingSafeValue && !rt->gcExactScanningEnabled) return; // If this assertion fails, it means that an AutoAssertNoGC was placed // around code that could trigger GC, and is therefore wrong. The // AutoAssertNoGC should be removed and the code it was guarding should be // modified to properly root any gcthings, and very possibly any code // calling that function should also be modified if it was improperly // assuming that GC could not happen at all within the called function. // (The latter may not apply if the AutoAssertNoGC only protected a portion // of a function, so the callers were already assuming that GC could // happen.) JS_ASSERT(!InNoGCScope()); // GCs can't happen when analysis/inference/compilation are active. if (cx->compartment->activeAnalysis) return; // Can switch to the atoms compartment during analysis. if (IsAtomsCompartment(cx->compartment)) { for (CompartmentsIter c(rt); !c.done(); c.next()) { if (c.get()->activeAnalysis) return; } } AutoCopyFreeListToArenas copy(rt); ConservativeGCData *cgcd = &rt->conservativeGC; cgcd->recordStackTop(); JS_ASSERT(cgcd->hasStackToScan()); uintptr_t *stackMin, *stackEnd; #if JS_STACK_GROWTH_DIRECTION > 0 stackMin = rt->nativeStackBase; stackEnd = cgcd->nativeStackTop; #else stackMin = cgcd->nativeStackTop + 1; stackEnd = reinterpret_cast<uintptr_t *>(rt->nativeStackBase); #endif // Gather up all of the rooters Vector< Rooter, 0, SystemAllocPolicy> rooters; for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) { Rooted<void*> *rooter = rt->mainThread.thingGCRooters[i]; while (rooter) { Rooter r = { rooter, ThingRootKind(i) }; JS_ALWAYS_TRUE(rooters.append(r)); rooter = rooter->previous(); } for (ContextIter cx(rt); !cx.done(); cx.next()) { rooter = cx->thingGCRooters[i]; while (rooter) { Rooter r = { rooter, ThingRootKind(i) }; JS_ALWAYS_TRUE(rooters.append(r)); rooter = rooter->previous(); } } } if (SuppressCheckRoots(rooters)) return; // Truncate stackEnd to just after the address of the youngest // already-scanned rooter on the stack, to avoid re-scanning the rest of // the stack. void *firstScanned = NULL; for (Rooter *p = rooters.begin(); p != rooters.end(); p++) { if (p->rooter->scanned) { uintptr_t *addr = reinterpret_cast<uintptr_t*>(p->rooter); #if JS_STACK_GROWTH_DIRECTION < 0 if (stackEnd > addr) #else if (stackEnd < addr) #endif { stackEnd = addr; firstScanned = p->rooter; } } } // Partition the stack by the already-scanned start address. Put everything // that needs to be searched at the end of the vector. Rooter *firstToScan = rooters.begin(); if (firstScanned) { for (Rooter *p = rooters.begin(); p != rooters.end(); p++) { #if JS_STACK_GROWTH_DIRECTION < 0 if (p->rooter >= firstScanned) #else if (p->rooter <= firstScanned) #endif { Swap(*firstToScan, *p); ++firstToScan; } } } JS_ASSERT(stackMin <= stackEnd); CheckStackRootsRangeAndSkipIon(rt, stackMin, stackEnd, firstToScan, rooters.end()); CheckStackRootsRange(rt, cgcd->registerSnapshot.words, ArrayEnd(cgcd->registerSnapshot.words), firstToScan, rooters.end()); // Mark all rooters as scanned for (Rooter *p = rooters.begin(); p != rooters.end(); p++) p->rooter->scanned = true; }