Statistics::Statistics(JSRuntime* rt)
: runtime(rt),
startupTime(PRMJ_Now()),
fp(nullptr),
fullFormat(false),
gcDepth(0),
nonincrementalReason(nullptr),
timedGCStart(0),
preBytes(0),
maxPauseInInterval(0),
phaseNestingDepth(0),
activeDagSlot(PHASE_DAG_NONE),
suspendedPhaseNestingDepth(0),
sliceCallback(nullptr),
aborted(false)
{
PodArrayZero(phaseTotals);
PodArrayZero(counts);
PodArrayZero(phaseStartTimes);
for (size_t d = 0; d < MAX_MULTIPARENT_PHASES + 1; d++)
PodArrayZero(phaseTimes[d]);
static bool initialized = false;
if (!initialized) {
initialized = true;
for (size_t i = 0; i < PHASE_LIMIT; i++)
MOZ_ASSERT(phases[i].index == i);
// Create a static table of descendants for every phase with multiple
// children. This assumes that all descendants come linearly in the
// list, which is reasonable since full dags are not supported; any
// path from the leaf to the root must encounter at most one node with
// multiple parents.
size_t dagSlot = 0;
for (size_t i = 0; i < mozilla::ArrayLength(dagChildEdges); i++) {
Phase parent = dagChildEdges[i].parent;
if (!phaseExtra[parent].dagSlot)
phaseExtra[parent].dagSlot = ++dagSlot;
Phase child = dagChildEdges[i].child;
MOZ_ASSERT(phases[child].parent == PHASE_MULTI_PARENTS);
int j = child;
do {
dagDescendants[phaseExtra[parent].dagSlot].append(Phase(j));
j++;
} while (j != PHASE_LIMIT && phases[j].parent != PHASE_MULTI_PARENTS);
}
MOZ_ASSERT(dagSlot <= MAX_MULTIPARENT_PHASES);
// Fill in the depth of each node in the tree. Multi-parented nodes
// have depth 0.
mozilla::Vector<Phase> stack;
stack.append(PHASE_LIMIT); // Dummy entry to avoid special-casing the first node
for (int i = 0; i < PHASE_LIMIT; i++) {
if (phases[i].parent == PHASE_NO_PARENT ||
phases[i].parent == PHASE_MULTI_PARENTS)
{
stack.clear();
} else {
while (stack.back() != phases[i].parent)
stack.popBack();
}
phaseExtra[i].depth = stack.length();
stack.append(Phase(i));
}
}
char* env = getenv("MOZ_GCTIMER");
if (!env || strcmp(env, "none") == 0) {
fp = nullptr;
return;
}
if (strcmp(env, "stdout") == 0) {
fullFormat = false;
fp = stdout;
} else if (strcmp(env, "stderr") == 0) {
fullFormat = false;
fp = stderr;
} else {
fullFormat = true;
fp = fopen(env, "a");
MOZ_ASSERT(fp);
}
}
bool
ModuleGenerator::finishCodegen(StaticLinkData* link)
{
uint32_t offsetInWhole = masm_.size();
// Generate stubs in a separate MacroAssembler since, otherwise, for modules
// larger than the JumpImmediateRange, even local uses of Label will fail
// due to the large absolute offsets temporarily stored by Label::bind().
Vector<Offsets> entries(cx_);
Vector<ProfilingOffsets> interpExits(cx_);
Vector<ProfilingOffsets> jitExits(cx_);
EnumeratedArray<JumpTarget, JumpTarget::Limit, Offsets> jumpTargets;
ProfilingOffsets badIndirectCallExit;
Offsets interruptExit;
{
TempAllocator alloc(&lifo_);
MacroAssembler masm(MacroAssembler::AsmJSToken(), alloc);
if (!entries.resize(numExports()))
return false;
for (uint32_t i = 0; i < numExports(); i++) {
uint32_t target = exportMap_->exportFuncIndices[i];
const Sig& sig = module_->exports[i].sig();
entries[i] = GenerateEntry(masm, target, sig, usesHeap());
}
if (!interpExits.resize(numImports()))
return false;
if (!jitExits.resize(numImports()))
return false;
for (uint32_t i = 0; i < numImports(); i++) {
interpExits[i] = GenerateInterpExit(masm, module_->imports[i], i);
jitExits[i] = GenerateJitExit(masm, module_->imports[i], usesHeap());
}
for (JumpTarget target : MakeEnumeratedRange(JumpTarget::Limit))
jumpTargets[target] = GenerateJumpTarget(masm, target);
badIndirectCallExit = GenerateBadIndirectCallExit(masm);
interruptExit = GenerateInterruptStub(masm);
if (masm.oom() || !masm_.asmMergeWith(masm))
return false;
}
// Adjust each of the resulting Offsets (to account for being merged into
// masm_) and then create code ranges for all the stubs.
for (uint32_t i = 0; i < numExports(); i++) {
entries[i].offsetBy(offsetInWhole);
module_->exports[i].initStubOffset(entries[i].begin);
if (!module_->codeRanges.emplaceBack(CodeRange::Entry, entries[i]))
return false;
}
for (uint32_t i = 0; i < numImports(); i++) {
interpExits[i].offsetBy(offsetInWhole);
module_->imports[i].initInterpExitOffset(interpExits[i].begin);
if (!module_->codeRanges.emplaceBack(CodeRange::ImportInterpExit, interpExits[i]))
return false;
jitExits[i].offsetBy(offsetInWhole);
module_->imports[i].initJitExitOffset(jitExits[i].begin);
if (!module_->codeRanges.emplaceBack(CodeRange::ImportJitExit, jitExits[i]))
return false;
}
for (JumpTarget target : MakeEnumeratedRange(JumpTarget::Limit)) {
jumpTargets[target].offsetBy(offsetInWhole);
if (!module_->codeRanges.emplaceBack(CodeRange::Inline, jumpTargets[target]))
return false;
}
badIndirectCallExit.offsetBy(offsetInWhole);
if (!module_->codeRanges.emplaceBack(CodeRange::ErrorExit, badIndirectCallExit))
return false;
interruptExit.offsetBy(offsetInWhole);
if (!module_->codeRanges.emplaceBack(CodeRange::Inline, interruptExit))
return false;
// Fill in StaticLinkData with the offsets of these stubs.
link->pod.outOfBoundsOffset = jumpTargets[JumpTarget::OutOfBounds].begin;
link->pod.interruptOffset = interruptExit.begin;
for (uint32_t sigIndex = 0; sigIndex < numSigs_; sigIndex++) {
const TableModuleGeneratorData& table = shared_->sigToTable[sigIndex];
if (table.elemFuncIndices.empty())
continue;
Uint32Vector elemOffsets;
if (!elemOffsets.resize(table.elemFuncIndices.length()))
return false;
for (size_t i = 0; i < table.elemFuncIndices.length(); i++) {
uint32_t funcIndex = table.elemFuncIndices[i];
if (funcIndex == BadIndirectCall)
//.........这里部分代码省略.........
JSFlatString *
JSRope::flattenInternal(ExclusiveContext *maybecx)
{
/*
* Perform a depth-first dag traversal, splatting each node's characters
* into a contiguous buffer. Visit each rope node three times:
* 1. record position in the buffer and recurse into left child;
* 2. recurse into the right child;
* 3. transform the node into a dependent string.
* To avoid maintaining a stack, tree nodes are mutated to indicate how many
* times they have been visited. Since ropes can be dags, a node may be
* encountered multiple times during traversal. However, step 3 above leaves
* a valid dependent string, so everything works out.
*
* While ropes avoid all sorts of quadratic cases with string
* concatenation, they can't help when ropes are immediately flattened.
* One idiomatic case that we'd like to keep linear (and has traditionally
* been linear in SM and other JS engines) is:
*
* while (...) {
* s += ...
* s.flatten
* }
*
* To do this, when the buffer for a to-be-flattened rope is allocated, the
* allocation size is rounded up. Then, if the resulting flat string is the
* left-hand side of a new rope that gets flattened and there is enough
* capacity, the rope is flattened into the same buffer, thereby avoiding
* copying the left-hand side. Clearing the 'extensible' bit turns off this
* optimization. This is necessary, e.g., when the JSAPI hands out the raw
* null-terminated char array of a flat string.
*
* N.B. This optimization can create chains of dependent strings.
*/
const size_t wholeLength = length();
size_t wholeCapacity;
jschar *wholeChars;
JSString *str = this;
jschar *pos;
/*
* JSString::flattenData is a tagged pointer to the parent node.
* The tag indicates what to do when we return to the parent.
*/
static const uintptr_t Tag_Mask = 0x3;
static const uintptr_t Tag_FinishNode = 0x0;
static const uintptr_t Tag_VisitRightChild = 0x1;
/* Find the left most string, containing the first string. */
JSRope *leftMostRope = this;
while (leftMostRope->leftChild()->isRope())
leftMostRope = &leftMostRope->leftChild()->asRope();
if (leftMostRope->leftChild()->isExtensible()) {
JSExtensibleString &left = leftMostRope->leftChild()->asExtensible();
size_t capacity = left.capacity();
if (capacity >= wholeLength) {
/*
* Simulate a left-most traversal from the root to leftMost->leftChild()
* via first_visit_node
*/
JS_ASSERT(str->isRope());
while (str != leftMostRope) {
if (b == WithIncrementalBarrier) {
JSString::writeBarrierPre(str->d.s.u2.left);
JSString::writeBarrierPre(str->d.s.u3.right);
}
JSString *child = str->d.s.u2.left;
JS_ASSERT(child->isRope());
str->d.s.u2.nonInlineCharsTwoByte = left.nonInlineChars();
child->d.u1.flattenData = uintptr_t(str) | Tag_VisitRightChild;
str = child;
}
if (b == WithIncrementalBarrier) {
JSString::writeBarrierPre(str->d.s.u2.left);
JSString::writeBarrierPre(str->d.s.u3.right);
}
str->d.s.u2.nonInlineCharsTwoByte = left.nonInlineChars();
wholeCapacity = capacity;
wholeChars = const_cast<jschar *>(left.nonInlineChars());
pos = wholeChars + left.d.u1.length;
JS_STATIC_ASSERT(!(EXTENSIBLE_FLAGS & DEPENDENT_FLAGS));
left.d.u1.flags ^= (EXTENSIBLE_FLAGS | DEPENDENT_FLAGS);
left.d.s.u3.base = (JSLinearString *)this; /* will be true on exit */
StringWriteBarrierPostRemove(maybecx, &left.d.s.u2.left);
StringWriteBarrierPost(maybecx, (JSString **)&left.d.s.u3.base);
goto visit_right_child;
}
}
if (!AllocChars(maybecx, wholeLength, &wholeChars, &wholeCapacity))
return nullptr;
pos = wholeChars;
first_visit_node: {
if (b == WithIncrementalBarrier) {
JSString::writeBarrierPre(str->d.s.u2.left);
JSString::writeBarrierPre(str->d.s.u3.right);
}
//.........这里部分代码省略.........
开发者ID:,项目名称:,代码行数:101,代码来源:
示例9: spec
// static
nsresult
nsChannelClassifier::SetBlockedTrackingContent(nsIChannel *channel)
{
// Can be called in EITHER the parent or child process.
nsCOMPtr<nsIParentChannel> parentChannel;
NS_QueryNotificationCallbacks(channel, parentChannel);
if (parentChannel) {
// This channel is a parent-process proxy for a child process request. The
// actual channel will be notified via the status passed to
// nsIRequest::Cancel and do this for us.
return NS_OK;
}
nsresult rv;
nsCOMPtr<nsIDOMWindow> win;
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
do_GetService(THIRDPARTYUTIL_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, NS_OK);
rv = thirdPartyUtil->GetTopWindowForChannel(channel, getter_AddRefs(win));
NS_ENSURE_SUCCESS(rv, NS_OK);
nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(win, &rv);
NS_ENSURE_SUCCESS(rv, NS_OK);
nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
if (!docShell) {
return NS_OK;
}
nsCOMPtr<nsIDocument> doc = do_GetInterface(docShell, &rv);
NS_ENSURE_SUCCESS(rv, NS_OK);
// This event might come after the user has navigated to another page.
// To prevent showing the TrackingProtection UI on the wrong page, we need to
// check that the loading URI for the channel is the same as the URI currently
// loaded in the document.
if (!SameLoadingURI(doc, channel)) {
return NS_OK;
}
// Notify nsIWebProgressListeners of this security event.
// Can be used to change the UI state.
nsCOMPtr<nsISecurityEventSink> eventSink = do_QueryInterface(docShell, &rv);
NS_ENSURE_SUCCESS(rv, NS_OK);
uint32_t state = 0;
nsCOMPtr<nsISecureBrowserUI> securityUI;
docShell->GetSecurityUI(getter_AddRefs(securityUI));
if (!securityUI) {
return NS_OK;
}
doc->SetHasTrackingContentBlocked(true);
securityUI->GetState(&state);
state |= nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT;
eventSink->OnSecurityChange(nullptr, state);
// Log a warning to the web console.
nsCOMPtr<nsIURI> uri;
channel->GetURI(getter_AddRefs(uri));
nsCString utf8spec;
uri->GetSpec(utf8spec);
NS_ConvertUTF8toUTF16 spec(utf8spec);
const char16_t* params[] = { spec.get() };
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Tracking Protection"),
doc,
nsContentUtils::eNECKO_PROPERTIES,
"TrackingUriBlocked",
params, ArrayLength(params));
return NS_OK;
}
static bool
Str(JSContext *cx, const Value &v, StringifyContext *scx)
{
/* Step 11 must be handled by the caller. */
JS_ASSERT(!IsFilteredValue(v));
JS_CHECK_RECURSION(cx, return false);
/*
* This method implements the Str algorithm in ES5 15.12.3, but:
*
* * We move property retrieval (step 1) into callers to stream the
* stringification process and avoid constantly copying strings.
* * We move the preprocessing in steps 2-4 into a helper function to
* allow both JO and JA to use this method. While JA could use it
* without this move, JO must omit any |undefined|-valued property per
* so it can't stream out a value using the Str method exactly as
* defined by ES5.
* * We move step 11 into callers, again to ease streaming.
*/
/* Step 8. */
if (v.isString())
return Quote(cx, scx->sb, v.toString());
/* Step 5. */
if (v.isNull())
return scx->sb.append("null");
/* Steps 6-7. */
if (v.isBoolean())
return v.toBoolean() ? scx->sb.append("true") : scx->sb.append("false");
/* Step 9. */
if (v.isNumber()) {
if (v.isDouble()) {
if (!IsFinite(v.toDouble()))
return scx->sb.append("null");
}
StringBuffer sb(cx);
if (!NumberValueToStringBuffer(cx, v, sb))
return false;
return scx->sb.append(sb.begin(), sb.length());
}
/* Step 10. */
JS_ASSERT(v.isObject());
RootedObject obj(cx, &v.toObject());
scx->depth++;
bool ok;
if (ObjectClassIs(obj, ESClass_Array, cx))
ok = JA(cx, obj, scx);
else
ok = JO(cx, obj, scx);
scx->depth--;
return ok;
}
请发表评论