Files
palemoon27/js/src/jit/BytecodeAnalysis.cpp
T
roytam1 202db2bd0f import changes from `dev' branch of rmottola/Arctic-Fox:
- pointer style (34e9d556e)
- Bug 1175466 - Allocate arguments objects in the nursery. r=terrence (14e7d019d)
- Bug 1175511 - Use template objects for arguments object allocation. r=bhackett (09c43e10e)
- Bug 1169250 - Zero-initialize all function object members r=jandem (55e6c44d7)
- Bug 987514, part 3 - Make every global have a (usually empty) Reflect object; rename JS_InitReflect -> JS_InitReflectParse. r=Waldo. (f7beebe35)
- Bug 987514, part 4 - Implement most of the standard Reflect methods. r=Waldo. (0ee01d6da)
- Bug 1160665 - Use the same implementation for both internal and external barriers; r=jonco (5291b100f)
- Bug 1175511 - Use template objects for arguments object allocation. r=bhackett (980240980)
- Bug 1170182 - Remove dead functions from js/src. r=jorendorff (2f6130fa2)
- Bug 1167468: Assert that JSObjects and their metadata are always in the same compartment. r=fitzgen (dc780d455)
- Bug 1172138 - Call PR_LogInit before profiler_init. r=froydnj (bd23dafce)
- re-add WebM NesteggReporter (b22381367)
- Bug 1159507 - make allocation times consistent with timeline; r=fitzgen,mccr8 (3a9c8e3dc)
- Bug 1174906 - Add a mozilla::Variant<T1, T2, ...> template class; r=Waldo (7c12bcf74)
- Bug 1068988 - Part 1: Add byte size to the allocation log; r=shu (4cbbbd8db)
- Bug 1068988 - Part 2: Add a test for byte sizes in the allocations log; r=shu (aa7d187db)
- Bug 1068988 - Part 3: Document the size property in the allocations log; r=shu (fa774e0bd)
- Bug 1068988 - Part 4: Fix object-pending-metadata root marking; r=shu (89961c6ee)
- Bug 1155211: Part 3.1 - Update tests for extractLane; r=h4writer (e8d0da406)
- Bug 1155211: Part 3.2 - Remove lanes getters; r=nbp (840230594)
- Bug 1155211: Part 3.3 - New tests; r=h4writer (9e8a8a456)
- Bug 1174850 - Remove the explicitly relocatable store buffers; r=jonco (02bc4962b)
- Bug 1165843 - Don't fire the pre-barrier in HeapPtr destructor r=terrence (d6277ed50)
- pointer style (5c58f858d)
- Bug 1175642 - Fix the interface that RelocatablePtr uses to interact with the StoreBuffer; r=jonco (30c4c1b47)
- Bug 1165054 - Add API to clear postbarrier callbacks and use it when CPOW tables are destroyed r=terrence (e8d62c559)
- Bug 1131285 - Propagate checkTypeSet flag correctly, r=jandem. (2baae056d)
- re-shufflemethods due to bad patching (5bb9a0ae5)
- Bug 977805 followup - Fix some issues with IonCache::reset reprotection. r=luke (11bcad882)
- Bug 1180854 - Record and expose Ion IC stub optimization info to Jit Coach. r=shu (fa00fd728)
- Bug 1179264 - Only assert markedness of sampled scripts in JitcodeMap during finalization. (r=terrence) (e9639d963)
- Bug 1173764 - Enable LAllocation/LUse serialization in optimized builds. r=bhackett (a10398167)
- Bug 1173764 - Disable JitSpew argument computation in optimizied builds. r=bhackett (54d0f0b5e)
- cleanup spaces and pointer style (d79dba082)
- Bug 1175761 - Avoid using types in the nursery during optimization tracking, r=shu. (739174bd3)
- Bug 1176511 - Minor GC when tracking types as a better bandaid. (r=terrence) (3913d0b0d)
- Bug 1182730 - Mark the JitcodeGlobalTable unconditionally when minor collecting. (r=terrence) (86ace1dcd)
- Bug 1182730 - Followup: only mark the JitcodeGlobalMap when profiling is on. (r=djvj) (be105dff4)
- Bug 1187512 - Fix accumulated unified bustage in SpiderMonkey; r=jonco (8a663452f)
- Bug 1155211: Rename bitselect into selectBits; r=nbp (b644a0731)
- Bug 1155211: Remove selectBits on Float types; r=nbp (588ffbc3e)
- Bug 1175494 - comprehensive atomics tests for asm.js. r=luke (1ef4b9c1d)
- Bug 1141986 - Atomics.exchange on integer elements -- asm.js parts. r=bbouvier (d7eeba2b4)
- Bug 1183308 - Fix ARM64 bustage from Bug 1141986. r=efaust (8915a33ac)
- real part of previous partial Bug 1038839 - Use type information for alias analysis. r=jandem (98f3ac4f9)
- Bug 1148375 - Ignore unhandled Elements. r=jandem (a74a4954e)
- Bug 1180990 - Add checks for nursery objects when building MIR. r=jandem (55117882e)
- Bug 1180049 - Add OOM check in MNewArray constructor. r=bhackett (95dca3f7d)
- Bug 1186271: IonMonkey: Honor truncated flag during folding of binary operations, r=nbp (34d66ad0b)
- Bug 1173869: IonMonkey - Cleanup of some dead code in MBinaryArithInstruction::infer, r=jandem (4d42ac15a)
- Bug 1193112: IonMonkey - Let the float32 optimization work with Float32, r=bbouvier (fae4514b6)
2020-11-18 07:49:03 +08:00

227 lines
7.4 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/BytecodeAnalysis.h"
#include "jsopcode.h"
#include "jit/JitSpewer.h"
#include "jsopcodeinlines.h"
#include "jsscriptinlines.h"
using namespace js;
using namespace js::jit;
BytecodeAnalysis::BytecodeAnalysis(TempAllocator& alloc, JSScript* script)
: script_(script),
infos_(alloc),
usesScopeChain_(false),
hasTryFinally_(false),
hasSetArg_(false)
{
}
// Bytecode range containing only catch or finally code.
struct CatchFinallyRange
{
uint32_t start; // Inclusive.
uint32_t end; // Exclusive.
CatchFinallyRange(uint32_t start, uint32_t end)
: start(start), end(end)
{
MOZ_ASSERT(end > start);
}
bool contains(uint32_t offset) const {
return start <= offset && offset < end;
}
};
bool
BytecodeAnalysis::init(TempAllocator& alloc, GSNCache& gsn)
{
if (!infos_.growByUninitialized(script_->length()))
return false;
// We need a scope chain if the function is heavyweight.
usesScopeChain_ = (script_->functionDelazifying() &&
script_->functionDelazifying()->isHeavyweight());
MOZ_ASSERT_IF(script_->hasAnyAliasedBindings(), usesScopeChain_);
jsbytecode* end = script_->codeEnd();
// Clear all BytecodeInfo.
mozilla::PodZero(infos_.begin(), infos_.length());
infos_[0].init(/*stackDepth=*/0);
Vector<CatchFinallyRange, 0, JitAllocPolicy> catchFinallyRanges(alloc);
jsbytecode* nextpc;
for (jsbytecode* pc = script_->code(); pc < end; pc = nextpc) {
JSOp op = JSOp(*pc);
nextpc = pc + GetBytecodeLength(pc);
unsigned offset = script_->pcToOffset(pc);
JitSpew(JitSpew_BaselineOp, "Analyzing op @ %d (end=%d): %s",
int(script_->pcToOffset(pc)), int(script_->length()), js_CodeName[op]);
// If this bytecode info has not yet been initialized, it's not reachable.
if (!infos_[offset].initialized)
continue;
unsigned stackDepth = infos_[offset].stackDepth;
#ifdef DEBUG
for (jsbytecode* chkpc = pc + 1; chkpc < (pc + GetBytecodeLength(pc)); chkpc++)
MOZ_ASSERT(!infos_[script_->pcToOffset(chkpc)].initialized);
#endif
unsigned nuses = GetUseCount(script_, offset);
unsigned ndefs = GetDefCount(script_, offset);
MOZ_ASSERT(stackDepth >= nuses);
stackDepth -= nuses;
stackDepth += ndefs;
// If stack depth exceeds max allowed by analysis, fail fast.
MOZ_ASSERT(stackDepth <= BytecodeInfo::MAX_STACK_DEPTH);
switch (op) {
case JSOP_TABLESWITCH: {
unsigned defaultOffset = offset + GET_JUMP_OFFSET(pc);
jsbytecode* pc2 = pc + JUMP_OFFSET_LEN;
int32_t low = GET_JUMP_OFFSET(pc2);
pc2 += JUMP_OFFSET_LEN;
int32_t high = GET_JUMP_OFFSET(pc2);
pc2 += JUMP_OFFSET_LEN;
infos_[defaultOffset].init(stackDepth);
infos_[defaultOffset].jumpTarget = true;
for (int32_t i = low; i <= high; i++) {
unsigned targetOffset = offset + GET_JUMP_OFFSET(pc2);
if (targetOffset != offset) {
infos_[targetOffset].init(stackDepth);
infos_[targetOffset].jumpTarget = true;
}
pc2 += JUMP_OFFSET_LEN;
}
break;
}
case JSOP_TRY: {
JSTryNote* tn = script_->trynotes()->vector;
JSTryNote* tnlimit = tn + script_->trynotes()->length;
for (; tn < tnlimit; tn++) {
unsigned startOffset = script_->mainOffset() + tn->start;
if (startOffset == offset + 1) {
unsigned catchOffset = startOffset + tn->length;
if (tn->kind != JSTRY_FOR_IN) {
infos_[catchOffset].init(stackDepth);
infos_[catchOffset].jumpTarget = true;
}
}
}
// Get the pc of the last instruction in the try block. It's a JSOP_GOTO to
// jump over the catch/finally blocks.
jssrcnote* sn = GetSrcNote(gsn, script_, pc);
MOZ_ASSERT(SN_TYPE(sn) == SRC_TRY);
jsbytecode* endOfTry = pc + GetSrcNoteOffset(sn, 0);
MOZ_ASSERT(JSOp(*endOfTry) == JSOP_GOTO);
jsbytecode* afterTry = endOfTry + GET_JUMP_OFFSET(endOfTry);
MOZ_ASSERT(afterTry > endOfTry);
// Pop CatchFinallyRanges that are no longer needed.
while (!catchFinallyRanges.empty() && catchFinallyRanges.back().end <= offset)
catchFinallyRanges.popBack();
CatchFinallyRange range(script_->pcToOffset(endOfTry), script_->pcToOffset(afterTry));
if (!catchFinallyRanges.append(range))
return false;
break;
}
case JSOP_LOOPENTRY:
for (size_t i = 0; i < catchFinallyRanges.length(); i++) {
if (catchFinallyRanges[i].contains(offset))
infos_[offset].loopEntryInCatchOrFinally = true;
}
break;
case JSOP_GETNAME:
case JSOP_BINDNAME:
case JSOP_SETNAME:
case JSOP_STRICTSETNAME:
case JSOP_DELNAME:
case JSOP_GETALIASEDVAR:
case JSOP_SETALIASEDVAR:
case JSOP_LAMBDA:
case JSOP_LAMBDA_ARROW:
case JSOP_DEFFUN:
case JSOP_DEFVAR:
case JSOP_DEFCONST:
case JSOP_SETCONST:
usesScopeChain_ = true;
break;
case JSOP_GETGNAME:
case JSOP_SETGNAME:
case JSOP_STRICTSETGNAME:
if (script_->hasPollutedGlobalScope())
usesScopeChain_ = true;
break;
case JSOP_FINALLY:
hasTryFinally_ = true;
break;
case JSOP_SETARG:
hasSetArg_ = true;
break;
default:
break;
}
bool jump = IsJumpOpcode(op);
if (jump) {
// Case instructions do not push the lvalue back when branching.
unsigned newStackDepth = stackDepth;
if (op == JSOP_CASE)
newStackDepth--;
unsigned targetOffset = offset + GET_JUMP_OFFSET(pc);
// If this is a a backedge to an un-analyzed segment, analyze from there.
bool jumpBack = (targetOffset < offset) && !infos_[targetOffset].initialized;
infos_[targetOffset].init(newStackDepth);
infos_[targetOffset].jumpTarget = true;
if (jumpBack)
nextpc = script_->offsetToPC(targetOffset);
}
// Handle any fallthrough from this opcode.
if (BytecodeFallsThrough(op)) {
jsbytecode* fallthrough = pc + GetBytecodeLength(pc);
MOZ_ASSERT(fallthrough < end);
unsigned fallthroughOffset = script_->pcToOffset(fallthrough);
infos_[fallthroughOffset].init(stackDepth);
// Treat the fallthrough of a branch instruction as a jump target.
if (jump)
infos_[fallthroughOffset].jumpTarget = true;
}
}
return true;
}