mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
126 lines
3.7 KiB
C++
126 lines
3.7 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 jsopcodeinlines_h__
|
|
#define jsopcodeinlines_h__
|
|
|
|
#include "jsautooplen.h"
|
|
|
|
#include "frontend/BytecodeEmitter.h"
|
|
|
|
namespace js {
|
|
|
|
static inline PropertyName *
|
|
GetNameFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc, JSOp op)
|
|
{
|
|
if (op == JSOP_LENGTH)
|
|
return cx->names().length;
|
|
|
|
// The method JIT's implementation of instanceof contains an internal lookup
|
|
// of the prototype property.
|
|
if (op == JSOP_INSTANCEOF)
|
|
return cx->names().classPrototype;
|
|
|
|
PropertyName *name;
|
|
GET_NAME_FROM_BYTECODE(script, pc, 0, name);
|
|
return name;
|
|
}
|
|
|
|
class BytecodeRange {
|
|
public:
|
|
BytecodeRange(JSContext *cx, JSScript *script)
|
|
: script(cx, 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:
|
|
RootedScript 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 <PC offset from prev src note, type, args>. 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; }
|
|
};
|
|
|
|
}
|
|
|
|
#endif /* jsopcodeinlines_h__ */
|