mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
7adb8133f5
- missing bit of 989499 and some other files (23b0597ba6) - Bug 1233666 - Remove hacks for getting frame pointer for x86/x64 gcc. r=glandium (bfe8f59916) - Bug 1176266: In TimeStamp_posix.cpp, check for XP_LINUX instead of LINUX, and add missing #include, to allow strrchr usage. r=BenWa (56c725cffa) - Bug 1167230 - Don't pack ProfileEntry on ARM. r=shu (89f880e0cb) - Bug 1209779 - Ensure that all null elements are written when streaming profiler JSON; r=shu (2bae5addc6) - missing bit of Bug 1141712 - Make LUL (55f1276545) - Bug 1061800 - Add breakpad ids to profiler in Linux. r=BenWa (994fd1a941) - Bug 829621 - Compute the breakpad-id for OS X. r=BenWa. (e129580174) - missing of Bug 938157 - Lightweight CFI/EXIDX (b355dc3140) - Bug 1193838 - Allow ProfileGatherer to gather profiles from exiting processes. r=BenWa (5ab1a6a3c9) - align some missing stuff (5ebecd2364) - align some missing stuff (b8ff7aa361) - Bug 1164315 - Update key fingerprint for bitbucket.org; r=me (c1a3fbd930) - Bug 1178955 - Refactor config path selection; r=smacleod (89552bb0ac) - Bug 1195445 - Update host key fingerprint for bugzilla.mozilla.org (3783541088) - Bug 1218903 - Update bmo fingerprint. r=fubar, a=Tomcat (5b836fc585) - Bug 1178955 - Print config path on failure; r=smacleod (f5499f3771) - Bug 1185113 - Support setting more secure file permissions; r=smacleod (7dbf6b22fd) - Bug 1184229 - Detect multiple version-control-tools repos in Mercurial config; r=smacleod (16c24072a9) - Bug 978514 - mach mercurial-setup: Use mqext from the version-control-tools repo (1fa5765e8a) - Bug 1178955 - Don't pass config paths to updater; r=smacleod (80fcb05121) - Bug 1197527 - Don't unnecessarily attempt to create extensions directory in MercurialUpdater; r=gps (9b049c3ff8) - Bug 1164812 - mach mercurial-setup: Always mark the v-c-t repo as needing update (bd631208bd) - Bug 1197527 - Always clone version-control-tools in MercurialSetupWizard; r=gps (6990e8f589) - Bug 1197527 - Consolidate obtaining hg path into mozversioncontrol.get_hg_path; r=gps (e0b029a8e9) - Bug 1200458 - Skip permission check for .hgrc on Windows in hgsetup wizard. r=gps DONTBUILD (cc5b0d6daf) - Bug 1168466 - Bump minimum Mercurial version; r=smacleod (7fde47cfbe) - Bug 1185113 - Clarify language around Bugzilla credentials; r=smacleod (9166fdfbf9) - Bug 1185112 - Don't prompt for Bugzilla username/password if cookies defined; r=smacleod (cd87c96823) - Bug 1188931 - Fix hgsetup wizard. r=gps (68a6b46be4) - Bug 1200461 - Prompt for Bugzilla API Key instead of password; r=smacleod (780fb5d85d) - Bug 1228580 - ./mach mercurial-setup should use ~ to set up extension paths, not my literal home directory. r=gps (7a0c839880) - Bug 1231192 - Mark Mercurial 3.5.2 as oldest non-legacy version; r=smacleod (8f69483333) - Bug 1231192 - Bump some minimum Mercurial version; r=smacleod (916c56a852) - Bug 1162093 - Add "push-to-try" from version-control-tools to the mercurial setup wizard prompt.;r=gps (d29c7cf63a) - Bug 1168466 - Prompt to install bundleclone extension; r=smacleod (780ce90a08) - Bug 1185557 - Print relevant config options; r=smacleod (2f3f7e0161) - Bug 1231192 - Support clonebundles feature; r=smacleod (dcba1ccd34) - Bug 1231192 - Offer to install hg wip; r=smacleod (c42ebce5c8) - Bug 1231192 - Only install host fingerprints if not running secure Python+hg; r=smacleod (3154a2497b) - Bug 1178955 - Error when semicolon comments are seen; r=smacleod (e1f7081bb6) - Bug 1231989 - Prompt to install hgwatchman extension; r=ahal (0eddf0c1c8) - Bug 1178955 - Print line number for parse errors; r=smacleod (5369468cf1) - Bug 1185557 - Only prompt to install progress on Mercurial <3.5; r=smacleod (401f362265) - Bug 1232747 - Check for ssl.SSLContext existence; r=dminor (d505b07c5c) - Bug 1144629 - UnicodeDecodeError in ./mach mercurial-setup. r=gps, r=glandium (611d3ec83e) - Bug 1216970 - Make the copying more obvious in ProfilerImpl::GetStacktrace. r=froydnj (085625e113) - Bug 1190466 - tools/rb/find-leakers.pl re-written in Python r=mccr8 (4bfdcad13e) - Bug 1116478 - Open web content handlers in the proper tab in e10s. r=billm (ff8e11f45e) - Bug 1213437 - Less data copying when handling structured clones in MessageManager, r=baku (c4e2a13253) - const-var (69d17f312d) - Bug 1203090 - Ensure we always use '/' as the starting path separator for the DOM path of the Directorys initially returned by HTMLInputElement.getFilesAndDirectories. r=baku (1325bbc40c) - Bug 1209975 - Stop using dom::Promise::MaybeRejectBrokenly() in GetDirectoryListingTask. r=baku (2106790950) - Bug 1209924 - Implement a general filtering mechanism for Directory::GetFilesAndDirectories, and add filtering of sensitive files/directories. r=baku (27b4a26262) - Force a repaint after DXGI device resets. (bug 1188019, r=bas) (09c999e6e5) - Bug 1163911 - Make responsive images block the document load event while the load task is queued. r=jst (0ee0e3db79) - Bug 1166138 - Make img srcset react to resize/viewport changes, r=jdm (91674519e6) - Bug 1194893 - Pref for default file upload directory. r=smaug (ec6d33d983) - bug 1116409: switch update server to sha2 cert; update in-tree pinning. r=rstrong,snorp,mfinkle,dkeeler (7c8f631f27) - bug 1116409: fix cert pinning on backup cert for aus5.mozilla.org. r=typofix (3c690cbc6d) - Bug 1167048 - Change default font for Thai script from serif to sans-serif. r=smontagu (15dc86c389) - Bug 1205570 - fix up font prefs for x-math lang group. r=heycam (03f1820752) - Bug 1071769: Use DrawTargetTiled on B2G. r=Bas (b80ce768f1) - fix misspatch of 1149343 (541dd7aac8) - Bug 1199766 - Disable ICE TCP SO gathering via user pref. r=bwc (80cdc9c662) - Bug 1187472 - only log UDP and TCP candidate gathering failures. r=bwc (bc3dcb02d0) - Bug 1190615 - Skip non-UDP STUN servers for UDP sockets. r=bwc (a2d1d914b5) - Bug 1187775 - skip host and reflexive ICE candidates if relay-only. r=bwc (7e2cba1685) - Bug 1185198 - use port 9 for TCP active candidates. r=bwc (0a89cb199d) - Bug 1177921 - Fix typo in STUN server name. r=drno (1ad43ced6b) - Bug 1178349 - Enable ice_unittests on desktop linux on CI. r=bwc (ce5ece8264) - Bug 1189041 - Add option to only gather addresses for default route. r=bwc (3651f2ff06) - Bug 1189040: add a whitelist for network interfaces to use with ICE/webrtc r=ekr (6f693af72c) - Bug 1189198 - don't start STUN transactions with a protocol mis-match. r=mtseng (a3b410e2a8) - Bug 1208096 - Handle various failure cases for TURN gathering better. r=drno (1d8e173448) - Bug 1211389 - Make absolutely sure the relay->srflx pointer doesn't dangle. r=drno (d59b0bf08d) - Bug 1215616: use base address for server rflx ICE candidates r=bwc (89d07331ac) - Bug 1207451 - removed framing from multi_tcp API. r=bwc (317f40f490) - Bug 1186590 - Part 1 - Enable interface prioritizer on all platforms. r=drno (036a69fdb3) - Bug 1194019 - New defaults for gather tests. r=bwc (8343ceab56) - Bug 1144933: Only check that remote candidate is loopback in TestLoopbackOnlySortOf. r=drno (1f53d824e4) - Bug 1186590 - Part 2 - Move hard-coded interface priority list into nrinterfaceprioritizer, and simplify some functions. r=drno (9f20fad21b) - Bug 1152137 - Part 1: Test case. r=ekr (6b50f06d90) - Bug 1152137 - Part 2: Remove attributes that could not be initted properly instead of just freeing them. r=ekr (ccdf81294a) - Bug 1200763 - Remove hard-coded STUN IP address from ice_unittest, and do a DNS lookup instead. r=drno (ae54a83363) - Bug 1208176 - Part 1: Add a couple of interface names. r=drno (b7ead0b476) - Bug 1208176 - Part 2: Add a one-sided trickle test case to ice_unittest. r=drno (ad6afedb1c) - Bug 1037618 - Relax candidate verification for TCP. r=bwc (0cad14c89e) - Bug 1208176 - Part 3: Be forgiving when we see prflx instead of host candidates in ice_unittest. r=drno (50bdec2ba3) - Bug 1035428: Re-register writeable callback after partially servicing the send queue. r=drno (2fdb7880fa) - Bug 1135753 - Mark some overridden virtual functions in WebRTC as MOZ_OVERRIDE; r=mt (97f451c97d) - Bug 950660: Part 4: Bridge TCPSocketChild to nr_socket r=bwc,jdm (654587b321) - Bug 971357: Log STUN responses at INFO instead of DEBUG. r=ekr (81b500df17) - Bug 1006809 - update triggered check behavior to RFC 5245. r+bwc r=mjf (31b718b5e5) - Bug 1208278 - improved STUN request timeout handling. r=bwc (cf470fb12f) - Bug 1142964 - Fix ICE tiebreaker on Windows. r=bwc (0d2fd78252) - Bug 1219557 - don't pair candidates from different reserved networks. r=mt r=bwc (24d3e5106c) - Bug 1220441 - Improve gather trickle ice unit tests. r=bwc r=mjf (96f76c6c8c) - Bug 1205421 - fix DNS resolution of STUN server in ice_unittest. r=bwc (5d5b153358) - Bug 1206465 - removed ice_ctx from TestStunTcpServer. r=bwc (9a0df03894) - ug 1008792 - Check for valid pointer before using. r=bwc (7660fd0a71) - Bug 1233101 - Use MOZ_LIKELY in js_new etc to help branch prediction; r=terrence (31fb244734) - Bug 1225565 - Fix module import cycle detection r=shu (370dc26ee8) - Bug 1225558 - Improve module error messages r=shu (83b6038bb3) - Bug 1225561 - Don't allow a module to export non-existent local bindings r=shu (41f065891a) - Bug 1233124 - Remove mis-named duplicate typedefs for rooted import and export entries r=terrence (17a60bdb39) - Bug 1208464 - Implement proposed ES7 functions Object.values and Object.entries. r=evilpie (615193d0fb) - Bug 1226549 - added assert check for matches pointer in for prevent null dereference. r=hv1989 (d321ad0385) - Bug 1232113 - "Make the format specifiers in JS_snprintf() invocations more portable". r=jcoppeard (7c58b79a53) - Bug 1232446 - Re-enable method calls in SelfHosted code using new anti-content checks. (r=till) (ba7dc22ff8) - Bug 1232159 - Stop using pseudo-Uint32Array in SelfHosted code. (r=till) (c325f8ff58) - Bug 1226235 - Print file and line info for failing assert in self-hosted code. r=efaust (4a8d54d38b) - fix misspatch (fca2efc1f1) - Bug 1186003 - Switch automated builds to Gtk+3. r=mshal (658ad843b7) - Bug 1181342 - tooltool manifests and build-clang config for clang 3.6 r=rail (6264b4df68) - Bug 1181342 - Follow up to use the unpack feature of tooltool instead of setup.sh r=glandium (96bb3b2062) - Bug 1181255 - Mozconfigs for tsan builds. r=glandium (19250f4cc1) - Bug 1181255 - Get tsan builds on gtk3. r=glandium (e5ffd1c02f) - Bug 1187664 - Create a fontconfig cache so that Firefox doesn't have to do it itself when run on build automation. r=mshal (8ce567bd4c) - Bug 1188780 - Include debug symbols in gtk3 tooltool package. r=mshal (a5b573aa58) - Bug 1188780: remove setup.sh invocations, as they fail outside the mock environment; r=glandium a=RyanVM (058e306cac) - Bug 1178513 - Fix non-unified bustage. r=wchen (543d1e5497) - Bug 1162789 - Add a comment explaining why mForm is not set to null during unlink (eaa2a82048) - Bug 1189655 - Define MOZ_HAVE_CXX11_CONSTEXPR on VS2015 or later. r=Waldo (2d134e3b41) - Bug 1231758 - Fix bogus assertion in BCE for Annex B function assignment. (r=jorendorff) (701b2530b9) - Bug 1233100 - Ensure that derived constructor bad return value errors are thrown before leaving the containing block. (r=shu) (52f5bcf0a5) - Bug 1232022, 1232449 - Address forgotten review nits and fix bogus error message. (rs=Waldo) (dfd9d5e388) - Bug 1233121 - Refactor ObjectBox tracing r=terrence (876a140535) - Bug 1231647 - Check for duplicate exported let and const in modules r=shu (99f53ad443)
667 lines
26 KiB
C++
667 lines
26 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/. */
|
|
|
|
#ifndef frontend_BytecodeEmitter_h
|
|
#define frontend_BytecodeEmitter_h
|
|
|
|
/*
|
|
* JS bytecode generation.
|
|
*/
|
|
|
|
#include "jscntxt.h"
|
|
#include "jsopcode.h"
|
|
#include "jsscript.h"
|
|
|
|
#include "frontend/ParseMaps.h"
|
|
#include "frontend/Parser.h"
|
|
#include "frontend/SharedContext.h"
|
|
#include "frontend/SourceNotes.h"
|
|
|
|
namespace js {
|
|
|
|
class ScopeObject;
|
|
|
|
namespace frontend {
|
|
|
|
class FullParseHandler;
|
|
class ObjectBox;
|
|
class ParseNode;
|
|
template <typename ParseHandler> class Parser;
|
|
class SharedContext;
|
|
class TokenStream;
|
|
|
|
class CGConstList {
|
|
Vector<Value> list;
|
|
public:
|
|
explicit CGConstList(ExclusiveContext* cx) : list(cx) {}
|
|
bool append(Value v) { MOZ_ASSERT_IF(v.isString(), v.toString()->isAtom()); return list.append(v); }
|
|
size_t length() const { return list.length(); }
|
|
void finish(ConstArray* array);
|
|
};
|
|
|
|
struct CGObjectList {
|
|
uint32_t length; /* number of emitted so far objects */
|
|
ObjectBox* lastbox; /* last emitted object */
|
|
|
|
CGObjectList() : length(0), lastbox(nullptr) {}
|
|
|
|
unsigned add(ObjectBox* objbox);
|
|
unsigned indexOf(JSObject* obj);
|
|
void finish(ObjectArray* array);
|
|
ObjectBox* find(uint32_t index);
|
|
};
|
|
|
|
struct CGTryNoteList {
|
|
Vector<JSTryNote> list;
|
|
explicit CGTryNoteList(ExclusiveContext* cx) : list(cx) {}
|
|
|
|
bool append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end);
|
|
size_t length() const { return list.length(); }
|
|
void finish(TryNoteArray* array);
|
|
};
|
|
|
|
struct CGBlockScopeNote : public BlockScopeNote
|
|
{
|
|
// The end offset. Used to compute the length; may need adjusting first if
|
|
// in the prologue.
|
|
uint32_t end;
|
|
|
|
// Is the start offset in the prologue?
|
|
bool startInPrologue;
|
|
|
|
// Is the end offset in the prologue?
|
|
bool endInPrologue;
|
|
};
|
|
|
|
struct CGBlockScopeList {
|
|
Vector<CGBlockScopeNote> list;
|
|
explicit CGBlockScopeList(ExclusiveContext* cx) : list(cx) {}
|
|
|
|
bool append(uint32_t scopeObject, uint32_t offset, bool inPrologue, uint32_t parent);
|
|
uint32_t findEnclosingScope(uint32_t index);
|
|
void recordEnd(uint32_t index, uint32_t offset, bool inPrologue);
|
|
size_t length() const { return list.length(); }
|
|
void finish(BlockScopeArray* array, uint32_t prologueLength);
|
|
};
|
|
|
|
struct CGYieldOffsetList {
|
|
Vector<uint32_t> list;
|
|
explicit CGYieldOffsetList(ExclusiveContext* cx) : list(cx) {}
|
|
|
|
bool append(uint32_t offset) { return list.append(offset); }
|
|
size_t length() const { return list.length(); }
|
|
void finish(YieldOffsetArray& array, uint32_t prologueLength);
|
|
};
|
|
|
|
struct LoopStmtInfo;
|
|
struct StmtInfoBCE;
|
|
|
|
// Use zero inline elements because these go on the stack and affect how many
|
|
// nested functions are possible.
|
|
typedef Vector<jsbytecode, 0> BytecodeVector;
|
|
typedef Vector<jssrcnote, 0> SrcNotesVector;
|
|
|
|
// This enum tells BytecodeEmitter::emitVariables and the destructuring
|
|
// methods how emit the given Parser::variables parse tree.
|
|
enum VarEmitOption {
|
|
// The normal case. Emit code to evaluate initializer expressions and
|
|
// assign them to local variables. Also emit JSOP_DEF{VAR,LET,CONST}
|
|
// opcodes in the prologue if the declaration occurs at toplevel.
|
|
InitializeVars,
|
|
|
|
// Emit only JSOP_DEFVAR opcodes, in the prologue, if necessary. This is
|
|
// used in one case: `for (var $BindingPattern in/of obj)`. If we're at
|
|
// toplevel, the variable(s) must be defined with JSOP_DEFVAR, but they're
|
|
// populated inside the loop, via emitAssignment.
|
|
DefineVars,
|
|
|
|
// Emit code to evaluate initializer expressions and leave those values on
|
|
// the stack. This is used to implement `for (let/const ...;;)` and
|
|
// deprecated `let` blocks.
|
|
PushInitialValues,
|
|
|
|
// Like InitializeVars, but bind using BINDVAR instead of
|
|
// BINDNAME/BINDGNAME. Only used for emitting declarations synthesized for
|
|
// Annex B block-scoped function semantics.
|
|
AnnexB,
|
|
};
|
|
|
|
struct BytecodeEmitter
|
|
{
|
|
SharedContext* const sc; /* context shared between parsing and bytecode generation */
|
|
|
|
ExclusiveContext* const cx;
|
|
|
|
BytecodeEmitter* const parent; /* enclosing function or global context */
|
|
|
|
Rooted<JSScript*> script; /* the JSScript we're ultimately producing */
|
|
|
|
Rooted<LazyScript*> lazyScript; /* the lazy script if mode is LazyFunction,
|
|
nullptr otherwise. */
|
|
|
|
struct EmitSection {
|
|
BytecodeVector code; /* bytecode */
|
|
SrcNotesVector notes; /* source notes, see below */
|
|
ptrdiff_t lastNoteOffset; /* code offset for last source note */
|
|
uint32_t currentLine; /* line number for tree-based srcnote gen */
|
|
uint32_t lastColumn; /* zero-based column index on currentLine of
|
|
last SRC_COLSPAN-annotated opcode */
|
|
|
|
EmitSection(ExclusiveContext* cx, uint32_t lineNum)
|
|
: code(cx), notes(cx), lastNoteOffset(0), currentLine(lineNum), lastColumn(0)
|
|
{}
|
|
};
|
|
EmitSection prologue, main, *current;
|
|
|
|
/* the parser */
|
|
Parser<FullParseHandler>* const parser;
|
|
|
|
HandleScript evalCaller; /* scripted caller info for eval and dbgapi */
|
|
|
|
StmtInfoStack<StmtInfoBCE> stmtStack;
|
|
|
|
OwnedAtomIndexMapPtr atomIndices; /* literals indexed for mapping */
|
|
unsigned firstLine; /* first line, for JSScript::initFromEmitter */
|
|
|
|
/*
|
|
* Only unaliased locals have stack slots assigned to them. This vector is
|
|
* used to map a local index (which includes unaliased and aliased locals)
|
|
* to its stack slot index.
|
|
*/
|
|
Vector<uint32_t, 16> localsToFrameSlots_;
|
|
|
|
int32_t stackDepth; /* current stack depth in script frame */
|
|
uint32_t maxStackDepth; /* maximum stack depth so far */
|
|
|
|
uint32_t arrayCompDepth; /* stack depth of array in comprehension */
|
|
|
|
unsigned emitLevel; /* emitTree recursion level */
|
|
|
|
CGConstList constList; /* constants to be included with the script */
|
|
|
|
CGObjectList objectList; /* list of emitted objects */
|
|
CGObjectList regexpList; /* list of emitted regexp that will be
|
|
cloned during execution */
|
|
CGTryNoteList tryNoteList; /* list of emitted try notes */
|
|
CGBlockScopeList blockScopeList;/* list of emitted block scope notes */
|
|
|
|
/*
|
|
* For each yield op, map the yield index (stored as bytecode operand) to
|
|
* the offset of the next op.
|
|
*/
|
|
CGYieldOffsetList yieldOffsetList;
|
|
|
|
uint16_t typesetCount; /* Number of JOF_TYPESET opcodes generated */
|
|
|
|
bool hasSingletons:1; /* script contains singleton initializer JSOP_OBJECT */
|
|
|
|
bool hasTryFinally:1; /* script contains finally block */
|
|
|
|
bool emittingForInit:1; /* true while emitting init expr of for; exclude 'in' */
|
|
|
|
bool emittingRunOnceLambda:1; /* true while emitting a lambda which is only
|
|
expected to run once. */
|
|
|
|
bool isRunOnceLambda();
|
|
|
|
bool insideEval:1; /* True if compiling an eval-expression or a function
|
|
nested inside an eval. */
|
|
|
|
const bool insideNonGlobalEval:1; /* True if this is a direct eval
|
|
call in some non-global scope. */
|
|
|
|
bool insideModule:1; /* True if compiling inside a module. */
|
|
|
|
enum EmitterMode {
|
|
Normal,
|
|
|
|
/*
|
|
* Emit JSOP_GETINTRINSIC instead of JSOP_GETNAME and assert that
|
|
* JSOP_GETNAME and JSOP_*GNAME don't ever get emitted. See the comment
|
|
* for the field |selfHostingMode| in Parser.h for details.
|
|
*/
|
|
SelfHosting,
|
|
|
|
/*
|
|
* Check the static scope chain of the root function for resolving free
|
|
* variable accesses in the script.
|
|
*/
|
|
LazyFunction
|
|
};
|
|
|
|
const EmitterMode emitterMode;
|
|
|
|
/*
|
|
* Note that BytecodeEmitters are magic: they own the arena "top-of-stack"
|
|
* space above their tempMark points. This means that you cannot alloc from
|
|
* tempLifoAlloc and save the pointer beyond the next BytecodeEmitter
|
|
* destruction.
|
|
*/
|
|
BytecodeEmitter(BytecodeEmitter* parent, Parser<FullParseHandler>* parser, SharedContext* sc,
|
|
HandleScript script, Handle<LazyScript*> lazyScript,
|
|
bool insideEval, HandleScript evalCaller,
|
|
bool insideNonGlobalEval, uint32_t lineNum, EmitterMode emitterMode = Normal);
|
|
bool init();
|
|
bool updateLocalsToFrameSlots();
|
|
|
|
StmtInfoBCE* innermostStmt() const { return stmtStack.innermost(); }
|
|
StmtInfoBCE* innermostScopeStmt() const { return stmtStack.innermostScopeStmt(); }
|
|
JSObject* innermostStaticScope() const;
|
|
JSObject* blockScopeOfDef(Definition* dn) const {
|
|
return parser->blockScopes[dn->pn_blockid];
|
|
}
|
|
|
|
bool atBodyLevel(StmtInfoBCE* stmt) const;
|
|
bool atBodyLevel() const {
|
|
return atBodyLevel(innermostStmt());
|
|
}
|
|
uint32_t computeHops(ParseNode* pn, BytecodeEmitter** bceOfDefOut);
|
|
bool isAliasedName(BytecodeEmitter* bceOfDef, ParseNode* pn);
|
|
bool computeDefinitionIsAliased(BytecodeEmitter* bceOfDef, Definition* dn, JSOp* op);
|
|
|
|
MOZ_ALWAYS_INLINE
|
|
bool makeAtomIndex(JSAtom* atom, jsatomid* indexp) {
|
|
AtomIndexAddPtr p = atomIndices->lookupForAdd(atom);
|
|
if (p) {
|
|
*indexp = p.value();
|
|
return true;
|
|
}
|
|
|
|
jsatomid index = atomIndices->count();
|
|
if (!atomIndices->add(p, atom, index))
|
|
return false;
|
|
|
|
*indexp = index;
|
|
return true;
|
|
}
|
|
|
|
bool isInLoop();
|
|
bool checkSingletonContext();
|
|
|
|
// Check whether our function is in a run-once context (a toplevel
|
|
// run-one script or a run-once lambda).
|
|
bool checkRunOnceContext();
|
|
|
|
bool needsImplicitThis();
|
|
|
|
void tellDebuggerAboutCompiledScript(ExclusiveContext* cx);
|
|
|
|
inline TokenStream* tokenStream();
|
|
|
|
BytecodeVector& code() const { return current->code; }
|
|
jsbytecode* code(ptrdiff_t offset) const { return current->code.begin() + offset; }
|
|
ptrdiff_t offset() const { return current->code.end() - current->code.begin(); }
|
|
ptrdiff_t prologueOffset() const { return prologue.code.end() - prologue.code.begin(); }
|
|
void switchToMain() { current = &main; }
|
|
void switchToPrologue() { current = &prologue; }
|
|
bool inPrologue() const { return current == &prologue; }
|
|
|
|
SrcNotesVector& notes() const { return current->notes; }
|
|
ptrdiff_t lastNoteOffset() const { return current->lastNoteOffset; }
|
|
unsigned currentLine() const { return current->currentLine; }
|
|
unsigned lastColumn() const { return current->lastColumn; }
|
|
|
|
bool reportError(ParseNode* pn, unsigned errorNumber, ...);
|
|
bool reportStrictWarning(ParseNode* pn, unsigned errorNumber, ...);
|
|
bool reportStrictModeError(ParseNode* pn, unsigned errorNumber, ...);
|
|
|
|
// If pn contains a useful expression, return true with *answer set to true.
|
|
// If pn contains a useless expression, return true with *answer set to
|
|
// false. Return false on error.
|
|
//
|
|
// The caller should initialize *answer to false and invoke this function on
|
|
// an expression statement or similar subtree to decide whether the tree
|
|
// could produce code that has any side effects. For an expression
|
|
// statement, we define useless code as code with no side effects, because
|
|
// the main effect, the value left on the stack after the code executes,
|
|
// will be discarded by a pop bytecode.
|
|
bool checkSideEffects(ParseNode* pn, bool* answer);
|
|
|
|
#ifdef DEBUG
|
|
bool checkStrictOrSloppy(JSOp op);
|
|
#endif
|
|
|
|
// Append a new source note of the given type (and therefore size) to the
|
|
// notes dynamic array, updating noteCount. Return the new note's index
|
|
// within the array pointed at by current->notes as outparam.
|
|
bool newSrcNote(SrcNoteType type, unsigned* indexp = nullptr);
|
|
bool newSrcNote2(SrcNoteType type, ptrdiff_t offset, unsigned* indexp = nullptr);
|
|
bool newSrcNote3(SrcNoteType type, ptrdiff_t offset1, ptrdiff_t offset2,
|
|
unsigned* indexp = nullptr);
|
|
|
|
void copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes);
|
|
bool setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offset);
|
|
|
|
// NB: this function can add at most one extra extended delta note.
|
|
bool addToSrcNoteDelta(jssrcnote* sn, ptrdiff_t delta);
|
|
|
|
// Finish taking source notes in cx's notePool. If successful, the final
|
|
// source note count is stored in the out outparam.
|
|
bool finishTakingSrcNotes(uint32_t* out);
|
|
|
|
void setJumpOffsetAt(ptrdiff_t off);
|
|
|
|
// Control whether emitTree emits a line number note.
|
|
enum EmitLineNumberNote {
|
|
EMIT_LINENOTE,
|
|
SUPPRESS_LINENOTE
|
|
};
|
|
|
|
// Emit code for the tree rooted at pn.
|
|
bool emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
|
|
|
|
// Emit function code for the tree rooted at body.
|
|
bool emitFunctionScript(ParseNode* body);
|
|
|
|
// Emit module code for the tree rooted at body.
|
|
bool emitModuleScript(ParseNode* body);
|
|
|
|
// If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
|
|
// reserve a type set to store its result.
|
|
void checkTypeSet(JSOp op);
|
|
|
|
void updateDepth(ptrdiff_t target);
|
|
bool updateLineNumberNotes(uint32_t offset);
|
|
bool updateSourceCoordNotes(uint32_t offset);
|
|
|
|
bool bindNameToSlot(ParseNode* pn);
|
|
bool bindNameToSlotHelper(ParseNode* pn);
|
|
|
|
void strictifySetNameNode(ParseNode* pn);
|
|
JSOp strictifySetNameOp(JSOp op);
|
|
|
|
bool tryConvertFreeName(ParseNode* pn);
|
|
|
|
void popStatement();
|
|
void pushStatement(StmtInfoBCE* stmt, StmtType type, ptrdiff_t top);
|
|
void pushStatementInner(StmtInfoBCE* stmt, StmtType type, ptrdiff_t top);
|
|
void pushLoopStatement(LoopStmtInfo* stmt, StmtType type, ptrdiff_t top);
|
|
|
|
bool enterNestedScope(StmtInfoBCE* stmt, ObjectBox* objbox, StmtType stmtType);
|
|
bool leaveNestedScope(StmtInfoBCE* stmt);
|
|
|
|
bool enterBlockScope(StmtInfoBCE* stmtInfo, ObjectBox* objbox, JSOp initialValueOp,
|
|
unsigned alreadyPushed = 0);
|
|
|
|
bool computeAliasedSlots(Handle<StaticBlockObject*> blockObj);
|
|
|
|
bool lookupAliasedName(HandleScript script, PropertyName* name, uint32_t* pslot,
|
|
ParseNode* pn = nullptr);
|
|
bool lookupAliasedNameSlot(PropertyName* name, ScopeCoordinate* sc);
|
|
|
|
// In a function, block-scoped locals go after the vars, and form part of the
|
|
// fixed part of a stack frame. Outside a function, there are no fixed vars,
|
|
// but block-scoped locals still form part of the fixed part of a stack frame
|
|
// and are thus addressable via GETLOCAL and friends.
|
|
void computeLocalOffset(Handle<StaticBlockObject*> blockObj);
|
|
|
|
bool flushPops(int* npops);
|
|
|
|
bool emitCheck(ptrdiff_t delta, ptrdiff_t* offset);
|
|
|
|
// Emit one bytecode.
|
|
bool emit1(JSOp op);
|
|
|
|
// Emit two bytecodes, an opcode (op) with a byte of immediate operand
|
|
// (op1).
|
|
bool emit2(JSOp op, uint8_t op1);
|
|
|
|
// Emit three bytecodes, an opcode with two bytes of immediate operands.
|
|
bool emit3(JSOp op, jsbytecode op1, jsbytecode op2);
|
|
|
|
// Helper to emit JSOP_DUPAT. The argument is the value's depth on the
|
|
// JS stack, as measured from the top.
|
|
bool emitDupAt(unsigned slotFromTop);
|
|
|
|
// Emit a bytecode followed by an uint16 immediate operand stored in
|
|
// big-endian order.
|
|
bool emitUint16Operand(JSOp op, uint32_t operand);
|
|
|
|
// Emit a bytecode followed by an uint32 immediate operand.
|
|
bool emitUint32Operand(JSOp op, uint32_t operand);
|
|
|
|
// Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
|
|
bool emitN(JSOp op, size_t extra, ptrdiff_t* offset = nullptr);
|
|
|
|
bool emitNumberOp(double dval);
|
|
|
|
bool emitThisLiteral(ParseNode* pn);
|
|
bool emitCreateFunctionThis();
|
|
bool emitGetFunctionThis(ParseNode* pn);
|
|
bool emitGetThisForSuperBase(ParseNode* pn);
|
|
bool emitSetThis(ParseNode* pn);
|
|
|
|
// These functions are used to emit GETLOCAL/GETALIASEDVAR or
|
|
// SETLOCAL/SETALIASEDVAR for a particular binding. The CallObject must be
|
|
// on top of the scope chain.
|
|
bool emitLoadFromTopScope(BindingIter& bi);
|
|
bool emitStoreToTopScope(BindingIter& bi);
|
|
|
|
bool emitJump(JSOp op, ptrdiff_t off, ptrdiff_t* jumpOffset = nullptr);
|
|
bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr);
|
|
|
|
bool emitLoopHead(ParseNode* nextpn);
|
|
bool emitLoopEntry(ParseNode* nextpn);
|
|
|
|
// Emit a backpatch op with offset pointing to the previous jump of this
|
|
// type, so that we can walk back up the chain fixing up the op and jump
|
|
// offset.
|
|
bool emitBackPatchOp(ptrdiff_t* lastp);
|
|
void backPatch(ptrdiff_t last, jsbytecode* target, jsbytecode op);
|
|
|
|
bool emitGoto(StmtInfoBCE* toStmt, ptrdiff_t* lastp, SrcNoteType noteType = SRC_NULL);
|
|
|
|
bool emitIndex32(JSOp op, uint32_t index);
|
|
bool emitIndexOp(JSOp op, uint32_t index);
|
|
|
|
bool emitAtomOp(JSAtom* atom, JSOp op);
|
|
bool emitAtomOp(ParseNode* pn, JSOp op);
|
|
|
|
bool emitArrayLiteral(ParseNode* pn);
|
|
bool emitArray(ParseNode* pn, uint32_t count, JSOp op);
|
|
bool emitArrayComp(ParseNode* pn);
|
|
|
|
bool emitInternedObjectOp(uint32_t index, JSOp op);
|
|
bool emitObjectOp(ObjectBox* objbox, JSOp op);
|
|
bool emitObjectPairOp(ObjectBox* objbox1, ObjectBox* objbox2, JSOp op);
|
|
bool emitRegExp(uint32_t index);
|
|
|
|
MOZ_NEVER_INLINE bool emitFunction(ParseNode* pn, bool needsProto = false);
|
|
MOZ_NEVER_INLINE bool emitObject(ParseNode* pn);
|
|
|
|
bool emitHoistedFunctionsInList(ParseNode* pn);
|
|
|
|
bool emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp, PropListType type);
|
|
|
|
// To catch accidental misuse, emitUint16Operand/emit3 assert that they are
|
|
// not used to unconditionally emit JSOP_GETLOCAL. Variable access should
|
|
// instead be emitted using EmitVarOp. In special cases, when the caller
|
|
// definitely knows that a given local slot is unaliased, this function may be
|
|
// used as a non-asserting version of emitUint16Operand.
|
|
bool emitLocalOp(JSOp op, uint32_t slot);
|
|
|
|
bool emitScopeCoordOp(JSOp op, ScopeCoordinate sc);
|
|
bool emitAliasedVarOp(JSOp op, ParseNode* pn);
|
|
bool emitAliasedVarOp(JSOp op, ScopeCoordinate sc, MaybeCheckLexical checkLexical);
|
|
bool emitUnaliasedVarOp(JSOp op, uint32_t slot, MaybeCheckLexical checkLexical);
|
|
|
|
bool emitVarOp(ParseNode* pn, JSOp op);
|
|
bool emitVarIncDec(ParseNode* pn);
|
|
|
|
bool emitNameOp(ParseNode* pn, bool callContext);
|
|
bool emitNameIncDec(ParseNode* pn);
|
|
|
|
bool maybeEmitVarDecl(JSOp prologueOp, ParseNode* pn, jsatomid* result);
|
|
bool emitVariables(ParseNode* pn, VarEmitOption emitOption);
|
|
bool emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode* initializer,
|
|
VarEmitOption emitOption);
|
|
|
|
bool emitNewInit(JSProtoKey key);
|
|
bool emitSingletonInitialiser(ParseNode* pn);
|
|
|
|
bool emitPrepareIteratorResult();
|
|
bool emitFinishIteratorResult(bool done);
|
|
bool iteratorResultShape(unsigned* shape);
|
|
|
|
bool emitYield(ParseNode* pn);
|
|
bool emitYieldOp(JSOp op);
|
|
bool emitYieldStar(ParseNode* iter, ParseNode* gen);
|
|
|
|
bool emitPropLHS(ParseNode* pn);
|
|
bool emitPropOp(ParseNode* pn, JSOp op);
|
|
bool emitPropIncDec(ParseNode* pn);
|
|
|
|
bool emitComputedPropertyName(ParseNode* computedPropName);
|
|
|
|
// Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM
|
|
// opcode onto the stack in the right order. In the case of SETELEM, the
|
|
// value to be assigned must already be pushed.
|
|
enum class EmitElemOption { Get, Set, Call, IncDec };
|
|
bool emitElemOperands(ParseNode* pn, EmitElemOption opts);
|
|
|
|
bool emitElemOpBase(JSOp op);
|
|
bool emitElemOp(ParseNode* pn, JSOp op);
|
|
bool emitElemIncDec(ParseNode* pn);
|
|
|
|
bool emitCatch(ParseNode* pn);
|
|
bool emitIf(ParseNode* pn);
|
|
bool emitWith(ParseNode* pn);
|
|
|
|
MOZ_NEVER_INLINE bool emitLabeledStatement(const LabeledStatement* pn);
|
|
MOZ_NEVER_INLINE bool emitLetBlock(ParseNode* pnLet);
|
|
MOZ_NEVER_INLINE bool emitLexicalScope(ParseNode* pn);
|
|
MOZ_NEVER_INLINE bool emitSwitch(ParseNode* pn);
|
|
MOZ_NEVER_INLINE bool emitTry(ParseNode* pn);
|
|
|
|
// EmitDestructuringLHS assumes the to-be-destructured value has been pushed on
|
|
// the stack and emits code to destructure a single lhs expression (either a
|
|
// name or a compound []/{} expression).
|
|
//
|
|
// If emitOption is InitializeVars, the to-be-destructured value is assigned to
|
|
// locals and ultimately the initial slot is popped (-1 total depth change).
|
|
//
|
|
// If emitOption is PushInitialValues, the to-be-destructured value is replaced
|
|
// with the initial values of the N (where 0 <= N) variables assigned in the
|
|
// lhs expression. (Same post-condition as EmitDestructuringOpsHelper)
|
|
bool emitDestructuringLHS(ParseNode* target, VarEmitOption emitOption);
|
|
|
|
bool emitDestructuringOps(ParseNode* pattern, bool isLet = false);
|
|
bool emitDestructuringOpsHelper(ParseNode* pattern, VarEmitOption emitOption);
|
|
bool emitDestructuringOpsArrayHelper(ParseNode* pattern, VarEmitOption emitOption);
|
|
bool emitDestructuringOpsObjectHelper(ParseNode* pattern, VarEmitOption emitOption);
|
|
|
|
typedef bool
|
|
(*DestructuringDeclEmitter)(BytecodeEmitter* bce, JSOp prologueOp, ParseNode* pn);
|
|
|
|
template <DestructuringDeclEmitter EmitName>
|
|
bool emitDestructuringDeclsWithEmitter(JSOp prologueOp, ParseNode* pattern);
|
|
|
|
bool emitDestructuringDecls(JSOp prologueOp, ParseNode* pattern);
|
|
|
|
// Emit code to initialize all destructured names to the value on the top of
|
|
// the stack.
|
|
bool emitInitializeDestructuringDecls(JSOp prologueOp, ParseNode* pattern);
|
|
|
|
// Throw a TypeError if the value atop the stack isn't convertible to an
|
|
// object, with no overall effect on the stack.
|
|
bool emitRequireObjectCoercible();
|
|
|
|
// emitIterator expects the iterable to already be on the stack.
|
|
// It will replace that stack value with the corresponding iterator
|
|
bool emitIterator();
|
|
|
|
// Pops iterator from the top of the stack. Pushes the result of |.next()|
|
|
// onto the stack.
|
|
bool emitIteratorNext(ParseNode* pn);
|
|
|
|
// Check if the value on top of the stack is "undefined". If so, replace
|
|
// that value on the stack with the value defined by |defaultExpr|.
|
|
bool emitDefault(ParseNode* defaultExpr);
|
|
|
|
bool emitCallSiteObject(ParseNode* pn);
|
|
bool emitTemplateString(ParseNode* pn);
|
|
bool emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs);
|
|
|
|
bool emitReturn(ParseNode* pn);
|
|
bool emitStatement(ParseNode* pn);
|
|
bool emitStatementList(ParseNode* pn);
|
|
|
|
bool emitDeleteName(ParseNode* pn);
|
|
bool emitDeleteProperty(ParseNode* pn);
|
|
bool emitDeleteElement(ParseNode* pn);
|
|
bool emitDeleteExpression(ParseNode* pn);
|
|
|
|
// |op| must be JSOP_TYPEOF or JSOP_TYPEOFEXPR.
|
|
bool emitTypeof(ParseNode* node, JSOp op);
|
|
|
|
bool emitUnary(ParseNode* pn);
|
|
bool emitRightAssociative(ParseNode* pn);
|
|
bool emitLeftAssociative(ParseNode* pn);
|
|
bool emitLogical(ParseNode* pn);
|
|
bool emitSequenceExpr(ParseNode* pn);
|
|
|
|
MOZ_NEVER_INLINE bool emitIncOrDec(ParseNode* pn);
|
|
|
|
bool emitConditionalExpression(ConditionalExpression& conditional);
|
|
|
|
bool emitCallOrNew(ParseNode* pn);
|
|
bool emitDebugOnlyCheckSelfHosted();
|
|
bool emitSelfHostedCallFunction(ParseNode* pn);
|
|
bool emitSelfHostedResumeGenerator(ParseNode* pn);
|
|
bool emitSelfHostedForceInterpreter(ParseNode* pn);
|
|
|
|
bool emitComprehensionFor(ParseNode* compFor);
|
|
bool emitComprehensionForIn(ParseNode* pn);
|
|
bool emitComprehensionForInOrOfVariables(ParseNode* pn, bool* letBlockScope);
|
|
bool emitComprehensionForOf(ParseNode* pn);
|
|
|
|
bool emitDo(ParseNode* pn);
|
|
bool emitFor(ParseNode* pn);
|
|
bool emitForIn(ParseNode* pn);
|
|
bool emitForInOrOfVariables(ParseNode* pn);
|
|
bool emitCStyleFor(ParseNode* pn);
|
|
bool emitWhile(ParseNode* pn);
|
|
|
|
bool emitBreak(PropertyName* label);
|
|
bool emitContinue(PropertyName* label);
|
|
|
|
bool emitArgsBody(ParseNode* pn);
|
|
bool emitDefaultsAndDestructuring(ParseNode* pn);
|
|
bool emitLexicalInitialization(ParseNode* pn, JSOp globalDefOp);
|
|
|
|
bool pushInitialConstants(JSOp op, unsigned n);
|
|
bool initializeBlockScopedLocalsFromStack(Handle<StaticBlockObject*> blockObj);
|
|
|
|
// emitSpread expects the current index (I) of the array, the array itself
|
|
// and the iterator to be on the stack in that order (iterator on the bottom).
|
|
// It will pop the iterator and I, then iterate over the iterator by calling
|
|
// |.next()| and put the results into the I-th element of array with
|
|
// incrementing I, then push the result I (it will be original I +
|
|
// iteration count). The stack after iteration will look like |ARRAY INDEX|.
|
|
bool emitSpread();
|
|
|
|
// If type is StmtType::FOR_OF_LOOP, emit bytecode for a for-of loop.
|
|
// pn should be PNK_FOR, and pn->pn_left should be PNK_FOROF.
|
|
//
|
|
// If type is StmtType::SPREAD, emit bytecode for spread operator.
|
|
// pn should be nullptr.
|
|
//
|
|
// Please refer the comment above emitSpread for additional information about
|
|
// stack convention.
|
|
bool emitForOf(StmtType type, ParseNode* pn);
|
|
|
|
bool emitClass(ParseNode* pn);
|
|
bool emitSuperPropLHS(ParseNode* superBase, bool isCall = false);
|
|
bool emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall = false);
|
|
bool emitSuperElemOperands(ParseNode* pn, EmitElemOption opts = EmitElemOption::Get);
|
|
bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
|
|
};
|
|
|
|
} /* namespace frontend */
|
|
} /* namespace js */
|
|
|
|
#endif /* frontend_BytecodeEmitter_h */
|