/* static */ bool SavedFrame::HashPolicy::match(SavedFrame *existing, const Lookup &lookup) { if (existing->getLine() != lookup.line) return false; if (existing->getColumn() != lookup.column) return false; if (existing->getParent() != lookup.parent) return false; if (existing->getPrincipals() != lookup.principals) return false; JSAtom *source = existing->getSource(); if (source->length() != lookup.source->length()) return false; if (source != lookup.source) return false; JSAtom *functionDisplayName = existing->getFunctionDisplayName(); if (functionDisplayName) { if (!lookup.functionDisplayName) return false; if (functionDisplayName->length() != lookup.functionDisplayName->length()) return false; if (0 != CompareAtoms(functionDisplayName, lookup.functionDisplayName)) return false; } else if (lookup.functionDisplayName) { return false; } return true; }
JSFlatString * RegExpObject::toString(JSContext *cx) const { JSAtom *src = getSource(); StringBuffer sb(cx); if (size_t len = src->length()) { if (!sb.reserve(len + 2)) return NULL; sb.infallibleAppend('/'); sb.infallibleAppend(src->chars(), len); sb.infallibleAppend('/'); } else { if (!sb.append("/(?:)/")) return NULL; } if (global() && !sb.append('g')) return NULL; if (ignoreCase() && !sb.append('i')) return NULL; if (multiline() && !sb.append('m')) return NULL; if (sticky() && !sb.append('y')) return NULL; return sb.finishString(); }
void GetDynamicName(JSContext *cx, JSObject *scopeChain, JSString *str, Value *vp) { // Lookup a string on the scope chain, returning either the value found or // undefined through rval. This function is infallible, and cannot GC or // invalidate. JSAtom *atom; if (str->isAtom()) { atom = &str->asAtom(); } else { atom = AtomizeString<NoGC>(cx, str); if (!atom) { vp->setUndefined(); return; } } if (!frontend::IsIdentifier(atom) || frontend::FindKeyword(atom->chars(), atom->length())) { vp->setUndefined(); return; } Shape *shape = NULL; JSObject *scope = NULL, *pobj = NULL; if (LookupNameNoGC(cx, atom->asPropertyName(), scopeChain, &scope, &pobj, &shape)) { if (FetchNameNoGC(pobj, shape, MutableHandleValue::fromMarkedLocation(vp))) return; } vp->setUndefined(); }
/* * Convert string indexes that convert to int jsvals as ints to save memory. * Care must be taken to use this macro every time a property name is used, or * else double-sets, incorrect property cache misses, or other mistakes could * occur. */ jsid js_CheckForStringIndex(jsid id) { if (!JSID_IS_ATOM(id)) return id; JSAtom *atom = JSID_TO_ATOM(id); const jschar *s = atom->chars(); jschar ch = *s; JSBool negative = (ch == '-'); if (negative) ch = *++s; if (!JS7_ISDEC(ch)) return id; size_t n = atom->length() - negative; if (n > sizeof(JSBOXEDWORD_INT_MAX_STRING) - 1) return id; const jschar *cp = s; const jschar *end = s + n; jsuint index = JS7_UNDEC(*cp++); jsuint oldIndex = 0; jsuint c = 0; if (index != 0) { while (JS7_ISDEC(*cp)) { oldIndex = index; c = JS7_UNDEC(*cp); index = 10 * index + c; cp++; } } /* * Non-integer indexes can't be represented as integers. Also, distinguish * index "-0" from "0", because JSBOXEDWORD_INT cannot. */ if (cp != end || (negative && index == 0)) return id; if (negative) { if (oldIndex < -(JSID_INT_MIN / 10) || (oldIndex == -(JSID_INT_MIN / 10) && c <= (-JSID_INT_MIN % 10))) { id = INT_TO_JSID(-jsint(index)); } } else { if (oldIndex < JSID_INT_MAX / 10 || (oldIndex == JSID_INT_MAX / 10 && c <= (JSID_INT_MAX % 10))) { id = INT_TO_JSID(jsint(index)); } } return id; }
/* * Serializes the script/function pair into a "descriptive string" which is * allowed to fail. This function cannot trigger a GC because it could finalize * some scripts, resize the hash table of profile strings, and invalidate the * AddPtr held while invoking allocProfileString. */ const char * SPSProfiler::allocProfileString(JSScript *script, JSFunction *maybeFun) { // Note: this profiler string is regexp-matched by // browser/devtools/profiler/cleopatra/js/parserWorker.js. // Get the function name, if any. JSAtom *atom = maybeFun ? maybeFun->displayAtom() : nullptr; // Get the script filename, if any, and its length. const char *filename = script->filename(); if (filename == nullptr) filename = "<unknown>"; size_t lenFilename = strlen(filename); // Get the line number and its length as a string. uint64_t lineno = script->lineno(); size_t lenLineno = 1; for (uint64_t i = lineno; i /= 10; lenLineno++); // Determine the required buffer size. size_t len = lenFilename + lenLineno + 1; // +1 for the ":" separating them. if (atom) len += atom->length() + 3; // +3 for the " (" and ")" it adds. // Allocate the buffer. char *cstr = js_pod_malloc<char>(len + 1); if (cstr == nullptr) return nullptr; // Construct the descriptive string. DebugOnly<size_t> ret; if (atom) { JS::AutoCheckCannotGC nogc; if (atom->hasLatin1Chars()) ret = JS_snprintf(cstr, len + 1, "%s (%s:%llu)", atom->latin1Chars(nogc), filename, lineno); else ret = JS_snprintf(cstr, len + 1, "%hs (%s:%llu)", atom->twoByteChars(nogc), filename, lineno); } else { ret = JS_snprintf(cstr, len + 1, "%s:%llu", filename, lineno); } MOZ_ASSERT(ret == len, "Computed length should match actual length!"); return cstr; }
void js::gc::TraceTypeNewScript(ObjectGroup *group) { const size_t bufLength = 128; static char buffer[bufLength]; MOZ_ASSERT(group->hasNewScript()); JSAtom *funName = group->newScript()->fun->displayAtom(); if (!funName) return; size_t length = funName->length(); MOZ_ALWAYS_TRUE(length < bufLength); CopyChars(reinterpret_cast<Latin1Char *>(buffer), *funName); buffer[length] = 0; TraceEvent(TraceEventTypeNewScript, uint64_t(group)); TraceString(buffer); }