/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * 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 "jsautooplen.h" #include "frontend/BytecodeEmitter.h" namespace js { static inline PropertyName * GetNameFromBytecode(JSContext *cx, jsbytecode *pc, JSOp op, const JSCodeSpec &cs) { if (op == JSOP_LENGTH) return cx->runtime->atomState.lengthAtom; // The method JIT's implementation of instanceof contains an internal lookup // of the prototype property. if (op == JSOP_INSTANCEOF) return cx->runtime->atomState.classPrototypeAtom; JSScript *script = cx->stack.currentScriptWithDiagnostics(); PropertyName *name; GET_NAME_FROM_BYTECODE(script, pc, 0, name); return name; } class BytecodeRange { public: BytecodeRange(JSScript *script) : script(script), pc(script->code), end(pc + script->length) {} bool empty() const { return pc == end; } jsbytecode *frontPC() const { return pc; } JSOp frontOpcode() const { return JSOp(*pc); } size_t frontOffset() const { return pc - script->code; } void popFront() { pc += GetBytecodeLength(pc); } private: JSScript *script; jsbytecode *pc, *end; }; class SrcNoteLineScanner { /* offset of the current JSOp in the bytecode */ ptrdiff_t offset; /* next src note to process */ jssrcnote *sn; /* line number of the current JSOp */ uint32_t lineno; /* * Is the current op the first one after a line change directive? Note that * multiple ops may be "first" if a line directive is used to return to a * previous line (eg, with a for loop increment expression.) */ bool lineHeader; public: SrcNoteLineScanner(jssrcnote *sn, uint32_t lineno) : offset(0), sn(sn), lineno(lineno) { } /* * This is called repeatedly with always-advancing relpc values. The src * notes are tuples of . Scan * through, updating the lineno, until the next src note is for a later * bytecode. * * When looking at the desired PC offset ('relpc'), the op is first in that * line iff there is a SRC_SETLINE or SRC_NEWLINE src note for that exact * bytecode. * * Note that a single bytecode may have multiple line-modifying notes (even * though only one should ever be needed.) */ void advanceTo(ptrdiff_t relpc) { // Must always advance! If the same or an earlier PC is erroneously // passed in, we will already be past the relevant src notes JS_ASSERT_IF(offset > 0, relpc > offset); // Next src note should be for after the current offset JS_ASSERT_IF(offset > 0, SN_IS_TERMINATOR(sn) || SN_DELTA(sn) > 0); // The first PC requested is always considered to be a line header lineHeader = (offset == 0); if (SN_IS_TERMINATOR(sn)) return; ptrdiff_t nextOffset; while ((nextOffset = offset + SN_DELTA(sn)) <= relpc && !SN_IS_TERMINATOR(sn)) { offset = nextOffset; SrcNoteType type = (SrcNoteType) SN_TYPE(sn); if (type == SRC_SETLINE || type == SRC_NEWLINE) { if (type == SRC_SETLINE) lineno = js_GetSrcNoteOffset(sn, 0); else lineno++; if (offset == relpc) lineHeader = true; } sn = SN_NEXT(sn); } } bool isLineHeader() const { return lineHeader; } uint32_t getLine() const { return lineno; } }; }