Optimize AST tree & Script parser Scanner functions (#69)

* This patch increase octane score +2~3%(x86 intel)
* We suggest jobs number in third party build even if failed to find cpu core count
  Using -j options cause system fail some legacy system

Signed-off-by: seonghyun kim <sh8281.kim@samsung.com>
This commit is contained in:
김승현/Tizen Platform Lab(SR)/Engineer/삼성전자 2018-05-03 07:29:55 +09:00 committed by 최영일/Tizen Platform Lab(SR)/Principal Engineer/삼성전자
commit 112221ab22
15 changed files with 257 additions and 270 deletions

View file

@ -1,6 +1,14 @@
#!/bin/bash
#set -x
if [ ! -f /proc/cpuinfo ]; then
echo "Is this Linux? Cannot find or read /proc/cpuinfo"
NUMPROC=8
else
NUMPROC=$(grep 'processor' /proc/cpuinfo | wc -l)
fi
INCREMENTAL=false
if [[ $1 == incremental ]]; then
INCREMENTAL=true
@ -107,7 +115,7 @@ function build_gc_for_linux() {
if [[ $INCREMENTAL == false ]]; then
CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS $CFLAGS" ../../../../configure $GCCONFFLAGS > /dev/null
fi
make -j > /dev/null
make -j$NUMPROC > /dev/null
echo Building bdwgc for $host $arch $mode $libtype done
cd -
@ -171,7 +179,7 @@ function build_gc_for_tizen() {
NM=$TIZEN_TOOLCHAIN/bin/${COMPILER_PREFIX}${TOOLCHAIN_GCC_WRAPPER}-nm \
RANLIB=$TIZEN_TOOLCHAIN/bin/${COMPILER_PREFIX}${TOOLCHAIN_GCC_WRAPPER}-ranlib \
LD=$TIZEN_TOOLCHAIN/bin/$COMPILER_PREFIX-ld ../../../../configure --host=$COMPILER_PREFIX $GCCONFFLAGS > /dev/null
make -j > /dev/null
make -j$NUMPROC > /dev/null
echo Building bdwgc for tizen $version $host $arch $mode $libtype done
cd -
@ -220,7 +228,7 @@ function build_gc_for_tizen_obs() {
fi
CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS $CFLAGS" ARFLAGS="$PLUGINFLAGS" NMFLAGS="$PLUGINFLAGS" RANLIBFLAGS="$PLUGINFLAGS" ../../../../configure $GCCONFFLAGS
make -j
make -j$NUMPROC
echo Building bdwgc for $host $arch $mode $libtype done
cd -

View file

@ -1,6 +1,14 @@
#!/bin/bash
#set -x
if [ ! -f /proc/cpuinfo ]; then
echo "Is this Linux? Cannot find or read /proc/cpuinfo"
NUMPROC=8
else
NUMPROC=$(grep 'processor' /proc/cpuinfo | wc -l)
fi
INCREMENTAL=false
if [[ $1 == incremental ]]; then
INCREMENTAL=true
@ -101,7 +109,7 @@ function build_gc_for_tizen() {
NM=$TIZEN_TOOLCHAIN/bin/${COMPILER_PREFIX}${TOOLCHAIN_GCC_WRAPPER}-nm \
RANLIB=$TIZEN_TOOLCHAIN/bin/${COMPILER_PREFIX}${TOOLCHAIN_GCC_WRAPPER}-ranlib \
LD=$TIZEN_TOOLCHAIN/bin/$COMPILER_PREFIX-ld
make -j
make -j$NUMPROC
echo Building bdwgc for android $version $host $arch $mode $libtype done
cd -

View file

@ -1,6 +1,13 @@
#!/bin/bash
#set -x
if [ ! -f /proc/cpuinfo ]; then
echo "Is this Linux? Cannot find or read /proc/cpuinfo"
NUMPROC=8
else
NUMPROC=$(grep 'processor' /proc/cpuinfo | wc -l)
fi
INCREMENTAL=false
if [[ $1 == incremental ]]; then
INCREMENTAL=true
@ -101,7 +108,7 @@ function build_gc_for_tizen() {
NM=$TIZEN_TOOLCHAIN/bin/${COMPILER_PREFIX}${TOOLCHAIN_GCC_WRAPPER}-nm \
RANLIB=$TIZEN_TOOLCHAIN/bin/${COMPILER_PREFIX}${TOOLCHAIN_GCC_WRAPPER}-ranlib \
LD=$TIZEN_TOOLCHAIN/bin/$COMPILER_PREFIX-ld
make -j
make -j$NUMPROC
echo Building bdwgc for android $version $host $arch $mode $libtype done
cd -

View file

@ -143,7 +143,14 @@ ByteCodeBlock* ByteCodeGenerator::generateByteCode(Context* c, InterpretedCodeBl
ast->generateStatementByteCode(block, &ctx);
if (!isGlobalScope && !isEvalMode) {
ASSERT(ast->type() == ASTNodeType::BlockStatement);
if (((BlockStatementNode*)ast)->body().size() && ((BlockStatementNode*)ast)->body().back()->type() == ASTNodeType::ReturnStatement) {
BlockStatementNode* blk = (BlockStatementNode*)ast;
StatementNode* nd = blk->firstChild();
StatementNode* last = nullptr;
while (nd) {
last = nd;
nd = nd->nextSilbing();
}
if (last && last->type() == ASTNodeType::ReturnStatement) {
} else {
block->pushCode(ReturnFunction(ByteCodeLOC(SIZE_MAX)), &ctx, nullptr);
}

View file

@ -181,8 +181,9 @@ ScriptParser::ScriptParserResult ScriptParser::parse(StringView scriptSource, St
Script* script = nullptr;
ScriptParseError* error = nullptr;
int orgFreeSpaceDivisor = GC_get_free_space_divisor();
GC_set_free_space_divisor(1);
GC_disable();
// int orgFreeSpaceDivisor = GC_get_free_space_divisor();
// GC_set_free_space_divisor(1);
try {
RefPtr<ProgramNode> program = esprima::parseProgram(m_context, scriptSource, nullptr, strictFromOutside, stackSizeRemain);
@ -269,7 +270,8 @@ ScriptParser::ScriptParserResult ScriptParser::parse(StringView scriptSource, St
delete orgError;
}
GC_set_free_space_divisor(orgFreeSpaceDivisor);
GC_enable();
// GC_set_free_space_divisor(orgFreeSpaceDivisor);
ScriptParser::ScriptParserResult result(script, error);
return result;

View file

@ -28,28 +28,28 @@ namespace Escargot {
class BlockStatementNode : public StatementNode {
public:
friend class ScriptParser;
BlockStatementNode(StatementNodeVector&& body)
BlockStatementNode(StatementContainer* body)
: StatementNode()
{
m_body = body;
m_container = body;
}
virtual ~BlockStatementNode()
{
}
virtual ASTNodeType type() { return ASTNodeType::BlockStatement; }
size_t size() { return m_body.size(); }
StatementNodeVector& body() { return m_body; }
virtual void generateStatementByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context)
{
size_t len = m_body.size();
for (size_t i = 0; i < len; i++) {
m_body[i]->generateStatementByteCode(codeBlock, context);
}
m_container->generateStatementByteCode(codeBlock, context);
}
StatementNode* firstChild()
{
return m_container->firstChild();
}
protected:
StatementNodeVector m_body; // body: [ Statement ];
RefPtr<StatementContainer> m_container;
};
}

View file

@ -25,10 +25,10 @@
namespace Escargot {
class DirectiveNode : public Node {
class DirectiveNode : public StatementNode {
public:
DirectiveNode(ExpressionNode* expr, StringView value)
: Node()
: StatementNode()
{
m_expr = expr;
m_value = value;

View file

@ -155,6 +155,7 @@ struct ExtendedNodeLOC {
class LiteralNode;
class IdentifierNode;
class MemberExpressionNode;
class StatementNode;
class Node : public RefCounted<Node> {
friend class ScriptParser;
@ -205,6 +206,12 @@ public:
return (LiteralNode *)this;
}
StatementNode *asStatementNode()
{
ASSERT(isStatementNode());
return (StatementNode *)this;
}
bool isLiteral()
{
return type() == ASTNodeType::Literal;
@ -398,7 +405,6 @@ struct ASTScopeContext : public gc {
typedef std::vector<RefPtr<Node>> NodeVector;
typedef std::vector<RefPtr<Node>> ArgumentVector;
typedef std::vector<RefPtr<Node>> ExpressionNodeVector;
typedef std::vector<RefPtr<Node>> StatementNodeVector;
typedef std::vector<RefPtr<Node>> PatternNodeVector;
class PropertyNode;
typedef std::vector<RefPtr<PropertyNode>> PropertiesNodeVector;

View file

@ -26,13 +26,13 @@
namespace Escargot {
class ProgramNode : public Node {
class ProgramNode : public StatementNode {
public:
friend class ScriptParser;
ProgramNode(StatementNodeVector&& body, ASTScopeContext* scopeContext)
: Node()
ProgramNode(StatementContainer* body, ASTScopeContext* scopeContext)
: StatementNode()
{
m_body = body;
m_container = body;
m_scopeContext = scopeContext;
m_scopeContext->m_nodeType = type();
}
@ -45,16 +45,12 @@ public:
ASTScopeContext* scopeContext() { return m_scopeContext; }
virtual void generateStatementByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context)
{
size_t len = m_body.size();
for (size_t i = 0; i < len; i++) {
m_body[i]->generateStatementByteCode(codeBlock, context);
}
m_container->generateStatementByteCode(codeBlock, context);
codeBlock->pushCode(End(ByteCodeLOC(SIZE_MAX)), context, this);
}
protected:
StatementNodeVector m_body; // body: [ Statement ];
RefPtr<StatementContainer> m_container;
ASTScopeContext* m_scopeContext;
};
}

View file

@ -25,6 +25,8 @@
namespace Escargot {
class StatementNode : public Node {
friend class StatementContainer;
public:
StatementNode()
: Node()
@ -36,7 +38,73 @@ public:
return true;
}
StatementNode* nextSilbing()
{
return m_nextSilbing.get();
}
protected:
RefPtr<StatementNode> m_nextSilbing;
};
class StatementContainer : public RefCounted<StatementContainer> {
public:
static RefPtr<StatementContainer> create()
{
return adoptRef(new StatementContainer());
}
void generateStatementByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context)
{
StatementNode* nd = m_firstChild.get();
while (nd) {
nd->generateStatementByteCode(codeBlock, context);
nd = nd->nextSilbing();
}
}
StatementNode* appendChild(RefPtr<StatementNode> c)
{
return appendChild(c.get());
}
StatementNode* appendChild(RefPtr<StatementNode> c, RefPtr<StatementNode> referNode)
{
return appendChild(c.get(), referNode.get());
}
StatementNode* appendChild(StatementNode* c, StatementNode* referNode)
{
if (referNode == nullptr) {
appendChild(c);
} else {
referNode->m_nextSilbing = c;
}
return c;
}
StatementNode* appendChild(StatementNode* c)
{
ASSERT(c->nextSilbing() == nullptr);
if (m_firstChild == nullptr) {
m_firstChild = c;
} else {
StatementNode* tail = m_firstChild.get();
while (tail->m_nextSilbing != nullptr) {
tail = tail->m_nextSilbing.get();
}
tail->m_nextSilbing = c;
}
return c;
};
StatementNode* firstChild()
{
return m_firstChild.get();
}
protected:
RefPtr<StatementNode> m_firstChild;
};
}

View file

@ -29,11 +29,11 @@ class SwitchCaseNode : public StatementNode {
public:
friend class ScriptParser;
friend class SwitchStatementNode;
SwitchCaseNode(Node* test, StatementNodeVector&& consequent)
SwitchCaseNode(Node* test, StatementContainer* consequent)
: StatementNode()
{
m_test = (ExpressionNode*)test;
m_consequent = std::move(consequent);
m_consequent = consequent;
}
virtual ~SwitchCaseNode()
@ -48,15 +48,12 @@ public:
virtual void generateStatementByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context)
{
size_t len = m_consequent.size();
for (size_t i = 0; i < len; i++) {
m_consequent[i]->generateStatementByteCode(codeBlock, context);
}
m_consequent->generateStatementByteCode(codeBlock, context);
}
protected:
RefPtr<ExpressionNode> m_test;
StatementNodeVector m_consequent;
RefPtr<StatementContainer> m_consequent;
};
}

View file

@ -29,7 +29,7 @@ namespace Escargot {
class SwitchStatementNode : public StatementNode {
public:
friend class ScriptParser;
SwitchStatementNode(Node* discriminant, StatementNodeVector&& casesA, Node* deflt, StatementNodeVector&& casesB, bool lexical)
SwitchStatementNode(Node* discriminant, StatementContainer* casesA, Node* deflt, StatementContainer* casesB, bool lexical)
: StatementNode()
{
m_discriminant = (ExpressionNode*)discriminant;
@ -55,8 +55,9 @@ public:
newContext.m_canSkipCopyToRegister = canSkipCopyToRegister;
std::vector<size_t> jumpCodePerCaseNodePosition;
for (unsigned i = 0; i < m_casesB.size(); i++) {
SwitchCaseNode* caseNode = (SwitchCaseNode*)m_casesB[i].get();
StatementNode* nd = m_casesB->firstChild();
while (nd) {
SwitchCaseNode* caseNode = (SwitchCaseNode*)nd;
size_t refIndex = caseNode->m_test->getRegister(codeBlock, &newContext);
caseNode->m_test->generateExpressionByteCode(codeBlock, &newContext, refIndex);
size_t resultIndex = newContext.getRegister();
@ -65,12 +66,13 @@ public:
codeBlock->pushCode(JumpIfTrue(ByteCodeLOC(m_loc.index), resultIndex), &newContext, this);
newContext.giveUpRegister();
newContext.giveUpRegister();
nd = nd->nextSilbing();
}
ASSERT(rIndex0 == newContext.getLastRegisterIndex());
for (unsigned i = 0; i < m_casesA.size(); i++) {
SwitchCaseNode* caseNode = (SwitchCaseNode*)m_casesA[i].get();
nd = m_casesA->firstChild();
while (nd) {
SwitchCaseNode* caseNode = (SwitchCaseNode*)nd;
size_t refIndex = caseNode->m_test->getRegister(codeBlock, &newContext);
caseNode->m_test->generateExpressionByteCode(codeBlock, &newContext, refIndex);
size_t resultIndex = newContext.getRegister();
@ -79,6 +81,7 @@ public:
codeBlock->pushCode(JumpIfTrue(ByteCodeLOC(m_loc.index), resultIndex), &newContext, this);
newContext.giveUpRegister();
newContext.giveUpRegister();
nd = nd->nextSilbing();
}
newContext.giveUpRegister();
@ -88,19 +91,23 @@ public:
jmpToDefault = codeBlock->currentCodeSize();
codeBlock->pushCode(Jump(ByteCodeLOC(m_loc.index), SIZE_MAX), &newContext, this);
size_t caseIdx = 0;
for (unsigned i = 0; i < m_casesB.size(); i++) {
SwitchCaseNode* caseNode = (SwitchCaseNode*)m_casesB[i].get();
nd = m_casesB->firstChild();
while (nd) {
SwitchCaseNode* caseNode = (SwitchCaseNode*)nd;
codeBlock->peekCode<JumpIfTrue>(jumpCodePerCaseNodePosition[caseIdx++])->m_jumpPosition = codeBlock->currentCodeSize();
caseNode->generateStatementByteCode(codeBlock, &newContext);
nd = nd->nextSilbing();
}
if (m_default) {
codeBlock->peekCode<Jump>(jmpToDefault)->m_jumpPosition = codeBlock->currentCodeSize();
m_default->generateStatementByteCode(codeBlock, &newContext);
}
for (unsigned i = 0; i < m_casesA.size(); i++) {
SwitchCaseNode* caseNode = (SwitchCaseNode*)m_casesA[i].get();
nd = m_casesA->firstChild();
while (nd) {
SwitchCaseNode* caseNode = (SwitchCaseNode*)nd;
codeBlock->peekCode<JumpIfTrue>(jumpCodePerCaseNodePosition[caseIdx++])->m_jumpPosition = codeBlock->currentCodeSize();
caseNode->generateStatementByteCode(codeBlock, &newContext);
nd = nd->nextSilbing();
}
size_t breakPos = codeBlock->currentCodeSize();
newContext.consumeBreakPositions(codeBlock, breakPos, context->m_tryStatementScopeCount);
@ -115,9 +122,9 @@ public:
virtual ASTNodeType type() { return ASTNodeType::SwitchStatement; }
protected:
RefPtr<ExpressionNode> m_discriminant;
StatementNodeVector m_casesA;
RefPtr<StatementContainer> m_casesA;
RefPtr<StatementNode> m_default;
StatementNodeVector m_casesB;
RefPtr<StatementContainer> m_casesB;
bool m_lexical;
};
}

View file

@ -376,7 +376,7 @@ struct ParserError : public gc {
}
};
struct ScanTemplteResult {
struct ScanTemplteResult : public gc {
UTF16StringData valueCooked;
StringView raw;
bool head;
@ -397,25 +397,26 @@ public:
bool startWithZero : 1;
bool octal : 1;
bool plain : 1;
bool head : 1;
char prec : 8; // max prec is 11
// we don't needs init prec.
// prec is initialized by another function before use
int prec;
size_t lineNumber;
size_t lineStart;
size_t start;
size_t end;
size_t index;
// TODO remove valueString
StringView valueString;
KeywordKind valueKeywordKind;
union {
KeywordKind valueKeywordKind : 8;
PunctuatorsKind valuePunctuatorsKind;
double valueNumber;
ScanTemplteResult valueTemplate;
ScanTemplteResult* valueTemplate;
ScanRegExpResult valueRegexp;
};
~ScannerResult();
inline ~ScannerResult();
inline void operator delete(void* obj)
{
@ -434,31 +435,25 @@ public:
this->type = type;
this->startWithZero = this->octal = false;
this->plain = false;
this->head = false;
this->prec = -1;
this->valueKeywordKind = NotKeyword;
this->lineNumber = lineNumber;
this->valueNumber = 0;
this->lineStart = lineStart;
this->start = start;
this->end = this->index = end;
this->end = end;
}
ScannerResult(Scanner* scanner, Token type, StringView valueString, size_t lineNumber, size_t lineStart, size_t start, size_t end)
: valueString(valueString)
{
this->scanner = scanner;
this->type = type;
this->startWithZero = this->octal = false;
this->plain = false;
this->head = false;
this->prec = -1;
this->valueKeywordKind = NotKeyword;
this->valueString = valueString;
this->lineNumber = lineNumber;
this->valueNumber = 0;
this->lineStart = lineStart;
this->start = start;
this->end = this->index = end;
this->end = end;
}
ScannerResult(Scanner* scanner, Token type, double value, size_t lineNumber, size_t lineStart, size_t start, size_t end)
@ -467,36 +462,25 @@ public:
this->type = type;
this->startWithZero = this->octal = false;
this->plain = false;
this->head = false;
this->valueKeywordKind = NotKeyword;
this->valueNumber = value;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;
this->end = this->index = end;
if (end != SIZE_MAX) {
this->end = end;
}
this->end = end;
}
ScannerResult(Scanner* scanner, Token type, ScanTemplteResult value, size_t lineNumber, size_t lineStart, size_t start, size_t end)
ScannerResult(Scanner* scanner, Token type, ScanTemplteResult* value, size_t lineNumber, size_t lineStart, size_t start, size_t end)
{
this->scanner = scanner;
this->type = type;
this->startWithZero = this->octal = false;
this->plain = false;
this->head = value.head;
this->prec = -1;
this->valueKeywordKind = NotKeyword;
this->valueNumber = 0;
this->valueTemplate = value;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;
this->end = this->index = end;
if (end != SIZE_MAX) {
this->end = end;
}
this->end = end;
}
};
@ -584,7 +568,7 @@ public:
#define SCANNER_RESULT_POOL_INITIAL_SIZE 128
class Scanner : public gc {
public:
BufferedStringView source;
StringView source;
ErrorHandler* errorHandler;
// trackComment: boolean;
@ -605,7 +589,7 @@ public:
}
Scanner(BufferedStringView code, ErrorHandler* handler, size_t startLine = 0, size_t startColumn = 0)
Scanner(StringView code, ErrorHandler* handler, size_t startLine = 0, size_t startColumn = 0)
{
isPoolEnabled = true;
source = code;
@ -1213,16 +1197,16 @@ public:
return code;
};
BufferedStringView getIdentifier()
StringView getIdentifier()
{
const size_t start = this->index++;
while (!this->eof()) {
while (UNLIKELY(!this->eof())) {
const char16_t ch = this->source.bufferedCharAt(this->index);
if (ch == 0x5C) {
if (UNLIKELY(ch == 0x5C)) {
// Blackslash (U+005C) marks Unicode escape sequence.
this->index = start;
return this->getComplexIdentifier();
} else if (ch >= 0xD800 && ch < 0xDFFF) {
} else if (UNLIKELY(ch >= 0xD800 && ch < 0xDFFF)) {
// Need to handle surrogate pairs.
this->index = start;
return this->getComplexIdentifier();
@ -1234,10 +1218,10 @@ public:
}
}
return BufferedStringView(this->source, start, this->index);
return StringView(this->source, start, this->index);
}
BufferedStringView getComplexIdentifier()
StringView getComplexIdentifier()
{
char32_t cp = this->codePointAt(this->index);
ParserCharPiece piece = ParserCharPiece(cp);
@ -1302,7 +1286,7 @@ public:
}
String* str = new UTF16String(id.data(), id.length());
return BufferedStringView(StringView(str, 0, str->length()));
return StringView(str, 0, str->length());
}
struct OctalToDecimalResult {
@ -1338,18 +1322,18 @@ public:
// ECMA-262 11.6 Names and Keywords
RefPtr<ScannerResult> scanIdentifier()
RefPtr<ScannerResult> scanIdentifier(char16_t ch0)
{
Token type;
const size_t start = this->index;
// Backslash (U+005C) starts an escaped character.
BufferedStringView id = this->source.bufferedCharAt(start) == 0x5C ? this->getComplexIdentifier() : this->getIdentifier();
StringView id = UNLIKELY(ch0 == 0x5C) ? this->getComplexIdentifier() : this->getIdentifier();
// There is no keyword or literal with only one character.
// Thus, it must be an identifier.
KeywordKind keywordKind = NotKeyword;
auto data = id.BufferedStringView::bufferAccessData();
auto data = id.StringView::bufferAccessData();
if (data.length == 1) {
type = Token::IdentifierToken;
} else if ((keywordKind = this->isKeyword(data))) {
@ -1369,23 +1353,22 @@ public:
}
if (keywordKind) {
RefPtr<ScannerResult> r = adoptRef(new (createScannerResult()) ScannerResult(this, type, id.src(), this->lineNumber, this->lineStart, start, this->index));
RefPtr<ScannerResult> r = adoptRef(new (createScannerResult()) ScannerResult(this, type, id, this->lineNumber, this->lineStart, start, this->index));
r->valueKeywordKind = keywordKind;
return r;
} else {
return adoptRef(new (createScannerResult()) ScannerResult(this, type, id.src(), this->lineNumber, this->lineStart, start, this->index));
return adoptRef(new (createScannerResult()) ScannerResult(this, type, id, this->lineNumber, this->lineStart, start, this->index));
}
}
// ECMA-262 11.7 Punctuators
RefPtr<ScannerResult> scanPunctuator()
RefPtr<ScannerResult> scanPunctuator(char16_t ch0)
{
RefPtr<ScannerResult> token = adoptRef(new (createScannerResult()) ScannerResult(this, Token::PunctuatorToken, StringView(), this->lineNumber, this->lineStart, this->index, this->index));
PunctuatorsKind kind;
// Check for most common single-character punctuators.
size_t start = this->index;
char16_t ch0 = this->source.bufferedCharAt(this->index);
char ch1, ch2, ch3;
switch (ch0) {
case '(':
@ -1633,9 +1616,8 @@ public:
this->throwUnexpectedToken();
}
token->end = this->index;
token->valuePunctuatorsKind = kind;
token->valueString = StringView(this->source.src(), start, this->index);
token->valueString = StringView(this->source, start, this->index);
return RefPtr<ScannerResult>(token);
}
@ -1952,7 +1934,7 @@ public:
if (ch >= 256) {
stringViewAllLatin1 = false;
}
str = StringView(this->source.src(), start + 1, start + 1 + str.length() + 1);
str = StringView(this->source, start + 1, start + 1 + str.length() + 1);
} else {
stringUTF16 += ch;
}
@ -2098,11 +2080,11 @@ public:
this->curlyStack.pop_back();
}
ScanTemplteResult result;
result.head = head;
result.tail = tail;
result.raw = StringView(this->source.src(), start + 1, this->index - rawOffset);
result.valueCooked = UTF16StringData(cooked.data(), cooked.length());
ScanTemplteResult* result = new ScanTemplteResult();
result->head = head;
result->tail = tail;
result->raw = StringView(this->source, start + 1, this->index - rawOffset);
result->valueCooked = UTF16StringData(cooked.data(), cooked.length());
return adoptRef(new (createScannerResult()) ScannerResult(this, Token::TemplateToken, result, this->lineNumber, this->lineStart, start, this->index));
}
@ -2292,20 +2274,22 @@ public:
RefPtr<ScannerResult> lex()
{
if (this->eof()) {
if (UNLIKELY(this->eof())) {
return adoptRef(new (createScannerResult()) ScannerResult(this, Token::EOFToken, this->lineNumber, this->lineStart, this->index, this->index));
}
const char16_t cp = this->source.bufferedCharAt(this->index);
if (isIdentifierStart(cp)) {
return this->scanIdentifier();
return this->scanIdentifier(cp);
}
// Very common: ( and ) and ;
/*
if (cp == 0x28 || cp == 0x29 || cp == 0x3B) {
return this->scanPunctuator();
return this->scanPunctuator(cp0);
}
*/
// String literal starts with single quote (U+0027) or double quote (U+0022).
if (cp == 0x27 || cp == 0x22) {
@ -2318,7 +2302,7 @@ public:
if (isDecimalDigit(this->source.bufferedCharAt(this->index + 1))) {
return this->scanNumericLiteral();
}
return this->scanPunctuator();
return this->scanPunctuator(cp);
}
if (isDecimalDigit(cp)) {
@ -2334,14 +2318,14 @@ public:
// Possible identifier start in a surrogate pair.
if (cp >= 0xD800 && cp < 0xDFFF) {
if (isIdentifierStart(this->codePointAt(this->index))) {
return this->scanIdentifier();
return this->scanIdentifier(cp);
}
}
return this->scanPunctuator();
return this->scanPunctuator(cp);
}
};
ScannerResult::~ScannerResult()
inline ScannerResult::~ScannerResult()
{
if (this->scanner->isPoolEnabled) {
if (this->scanner->initialResultMemoryPoolSize < SCANNER_RESULT_POOL_INITIAL_SIZE) {
@ -2623,7 +2607,7 @@ public:
}
}
value = new StringView((token->type == Token::TemplateToken) ? token->valueTemplate.raw : token->valueString);
value = new StringView((token->type == Token::TemplateToken) ? token->valueTemplate->raw : token->valueString);
} else {
value = new ASCIIString("ILLEGAL");
}
@ -2713,8 +2697,7 @@ public:
this->startMarker.lineNumber = this->scanner->lineNumber;
this->startMarker.lineStart = this->scanner->lineStart;
RefPtr<ScannerResult> next;
next = this->scanner->lex();
RefPtr<ScannerResult> next = this->scanner->lex();
this->hasLineTerminator = (token && next) ? (token->lineNumber != next->lineNumber) : false;
if (next && this->context->strict && next->type == Token::IdentifierToken) {
@ -3663,9 +3646,9 @@ public:
MetaNode node = this->createNode();
RefPtr<ScannerResult> token = this->nextToken();
TemplateElement* tm = new TemplateElement();
tm->value = token->valueTemplate.valueCooked;
tm->raw = token->valueTemplate.raw;
tm->tail = token->valueTemplate.tail;
tm->value = token->valueTemplate->valueCooked;
tm->raw = token->valueTemplate->raw;
tm->tail = token->valueTemplate->tail;
return tm;
}
@ -3678,9 +3661,9 @@ public:
MetaNode node = this->createNode();
RefPtr<ScannerResult> token = this->nextToken();
TemplateElement* tm = new TemplateElement();
tm->value = token->valueTemplate.valueCooked;
tm->raw = token->valueTemplate.raw;
tm->tail = token->valueTemplate.tail;
tm->value = token->valueTemplate->valueCooked;
tm->raw = token->valueTemplate->raw;
tm->tail = token->valueTemplate->tail;
return tm;
}
@ -4035,7 +4018,7 @@ public:
this->expect(RightSquareBracket);
expr = this->finalize(this->startNode(startToken), new MemberExpressionNode(expr.get(), property.get(), false));
} else if (this->lookahead->type == Token::TemplateToken && this->lookahead->head) {
} else if (this->lookahead->type == Token::TemplateToken && this->lookahead->valueTemplate->head) {
RefPtr<Node> quasi = this->parseTemplateLiteral();
expr = this->convertTaggedTempleateExpressionToCallExpression(this->startNode(startToken), this->finalize(this->startNode(startToken), new TaggedTemplateExpressionNode(expr.get(), quasi.get())));
} else {
@ -4089,7 +4072,7 @@ public:
this->trackUsingNames = trackUsingNamesBefore;
expr = this->finalize(node, new MemberExpressionNode(expr.get(), property.get(), true));
} else if (this->lookahead->type == Token::TemplateToken && this->lookahead->head) {
} else if (this->lookahead->type == Token::TemplateToken && this->lookahead->valueTemplate->head) {
RefPtr<Node> quasi = this->parseTemplateLiteral();
expr = this->convertTaggedTempleateExpressionToCallExpression(node, this->finalize(node, new TaggedTemplateExpressionNode(expr.get(), quasi.get())).get());
} else {
@ -4364,7 +4347,6 @@ public:
RefPtr<ScannerResult> token = this->lookahead;
std::vector<RefPtr<ScannerResult>, GCUtil::gc_malloc_ignore_off_page_allocator<RefPtr<ScannerResult>>> tokenKeeper;
std::vector<RefPtr<Node>> exprKeeper;
int prec = this->binaryPrecedence(token);
if (prec > 0) {
this->nextToken();
@ -4380,11 +4362,11 @@ public:
RefPtr<Node> right = this->isolateCoverGrammar(&Parser::parseExponentiationExpression);
std::vector<void*, GCUtil::gc_malloc_ignore_off_page_allocator<void*>> stack;
exprKeeper.push_back(left);
left->ref();
stack.push_back(left.get());
tokenKeeper.push_back(token);
token->ref();
stack.push_back(token.get());
exprKeeper.push_back(right);
right->ref();
stack.push_back(right.get());
while (true) {
@ -4396,38 +4378,45 @@ public:
// Reduce: make a binary expression from the three topmost entries.
while ((stack.size() > 2) && (prec <= ((ScannerResult*)stack[stack.size() - 2])->prec)) {
right = (Node*)stack.back();
right->deref();
stack.pop_back();
ScannerResult* operator_ = (ScannerResult*)stack.back();
RefPtr<ScannerResult> operator_ = (ScannerResult*)stack.back();
operator_->deref();
stack.pop_back();
left = (Node*)stack.back();
left->deref();
stack.pop_back();
markers.pop_back();
MetaNode node = this->startNode(markers.back());
auto e = this->finalize(node, finishBinaryExpression(left.get(), right.get(), operator_));
exprKeeper.push_back(e);
auto e = this->finalize(node, finishBinaryExpression(left.get(), right.get(), operator_.get()));
e->ref();
stack.push_back(e.get());
}
// Shift.
token = this->nextToken();
token->prec = prec;
tokenKeeper.push_back(token);
token->ref();
stack.push_back(token.get());
markers.push_back(this->lookahead);
auto e = this->isolateCoverGrammar(&Parser::parseExponentiationExpression);
exprKeeper.push_back(e);
e->ref();
stack.push_back(e.get());
}
// Final reduce to clean-up the stack.
size_t i = stack.size() - 1;
expr = (Node*)stack[i];
expr->deref();
markers.pop_back();
while (i > 1) {
MetaNode node = this->startNode(markers.back());
expr = this->finalize(node, finishBinaryExpression((Node*)stack[i - 2], expr.get(), (ScannerResult*)stack[i - 1]));
((Node*)stack[i - 2])->deref();
((ScannerResult*)stack[i - 1])->deref();
i -= 2;
}
RELEASE_ASSERT(i == 0);
}
return expr;
@ -4494,6 +4483,7 @@ public:
else
RELEASE_ASSERT_NOT_REACHED();
} else {
ASSERT(token->type == Token::KeywordToken);
if (token->valueKeywordKind == KeywordKind::In)
nd = new BinaryExpressionInNode(left, right);
else if (token->valueKeywordKind == KeywordKind::InstanceofKeyword)
@ -4861,16 +4851,17 @@ public:
MetaNode node = this->createNode();
this->expect(LeftBrace);
StatementNodeVector block;
RefPtr<StatementContainer> block = StatementContainer::create();
StatementNode* referNode = nullptr;
while (true) {
if (this->match(RightBrace)) {
break;
}
block.push_back(this->parseStatementListItem());
referNode = block->appendChild(this->parseStatementListItem().get(), referNode);
}
this->expect(RightBrace);
return this->finalize(node, new BlockStatementNode(std::move(block)));
return this->finalize(node, new BlockStatementNode(block.get()));
}
/*
// ECMA-262 13.3.1 Let and Const Declarations
@ -5594,15 +5585,15 @@ public:
}
this->expect(Colon);
StatementNodeVector consequent;
RefPtr<StatementContainer> consequent = StatementContainer::create();
while (true) {
if (this->match(RightBrace) || this->matchKeyword(Default) || this->matchKeyword(Case)) {
break;
}
consequent.push_back(this->parseStatementListItem());
consequent->appendChild(this->parseStatementListItem());
}
return this->finalize(node, new SwitchCaseNode(test.get(), std::move(consequent)));
return this->finalize(node, new SwitchCaseNode(test.get(), consequent.get()));
}
RefPtr<SwitchStatementNode> parseSwitchStatement()
@ -5617,7 +5608,7 @@ public:
bool previousInSwitch = this->context->inSwitch;
this->context->inSwitch = true;
StatementNodeVector casesA, casesB;
RefPtr<StatementContainer> casesA = StatementContainer::create(), casesB = StatementContainer::create();
RefPtr<Node> deflt;
bool defaultFound = false;
this->expect(LeftBrace);
@ -5634,9 +5625,9 @@ public:
defaultFound = true;
} else {
if (defaultFound) {
casesA.push_back(clause);
casesA->appendChild(clause);
} else {
casesB.push_back(clause);
casesB->appendChild(clause);
}
}
}
@ -5644,7 +5635,7 @@ public:
this->context->inSwitch = previousInSwitch;
return this->finalize(node, new SwitchStatementNode(discriminant.get(), std::move(casesA), deflt.get(), std::move(casesB), false));
return this->finalize(node, new SwitchStatementNode(discriminant.get(), casesA.get(), deflt.get(), casesB.get(), false));
}
// ECMA-262 13.13 Labelled Statements
@ -5889,7 +5880,7 @@ public:
size_t realIndex = this->config.parseSingleFunctionChildIndex.asUint32() - 1;
this->config.parseSingleFunctionChildIndex = SmallValue(this->config.parseSingleFunctionChildIndex.asUint32() + 1);
InterpretedCodeBlock* currentTarget = this->config.parseSingleFunctionTarget->asInterpretedCodeBlock();
size_t orgIndex = this->lookahead->index;
size_t orgIndex = this->lookahead->end;
this->expect(LeftBrace);
StringView src = currentTarget->childBlocks()[realIndex]->src();
@ -5902,7 +5893,7 @@ public:
this->lookahead->type = Token::PunctuatorToken;
this->lookahead->valuePunctuatorsKind = PunctuatorsKind::RightBrace;
this->expect(RightBrace);
return this->finalize(this->createNode(), new BlockStatementNode(std::move(StatementNodeVector())));
return this->finalize(this->createNode(), new BlockStatementNode(StatementContainer::create().get()));
}
this->config.parseSingleFunctionChildIndex = SmallValue(this->config.parseSingleFunctionChildIndex.asUint32() + 1);
}
@ -5912,7 +5903,7 @@ public:
MetaNode nodeStart = this->createNode();
this->expect(LeftBrace);
StatementNodeVector body = this->parseDirectivePrologues();
RefPtr<StatementContainer> body = this->parseDirectivePrologues();
auto previousLabelSet = this->context->labelSet;
bool previousInIteration = this->context->inIteration;
@ -5924,11 +5915,12 @@ public:
this->context->inSwitch = false;
this->context->inFunctionBody = true;
StatementNode* referNode = nullptr;
while (this->startMarker.index < this->scanner->length) {
if (this->match(RightBrace)) {
break;
}
body.push_back(this->parseStatementListItem());
referNode = body->appendChild(this->parseStatementListItem().get(), referNode);
}
this->expect(RightBrace);
@ -5951,9 +5943,9 @@ public:
this->context->inDirectCatchScope = prevInDirectCatchScope;
if (this->config.parseSingleFunction) {
return this->finalize(nodeStart, new BlockStatementNode(std::move(body)));
return this->finalize(nodeStart, new BlockStatementNode(body.get()));
} else {
return this->finalize(nodeStart, new BlockStatementNode(std::move(StatementNodeVector())));
return this->finalize(nodeStart, new BlockStatementNode(StatementContainer::create().get()));
}
}
@ -6122,11 +6114,11 @@ public:
}
}
StatementNodeVector parseDirectivePrologues()
RefPtr<StatementContainer> parseDirectivePrologues()
{
RefPtr<ScannerResult> firstRestricted = nullptr;
StatementNodeVector body;
RefPtr<StatementContainer> body = StatementContainer::create();
while (true) {
RefPtr<ScannerResult> token = this->lookahead;
if (token->type != StringLiteralToken) {
@ -6134,7 +6126,7 @@ public:
}
RefPtr<Node> statement = this->parseDirective();
body.push_back(statement);
body->appendChild(statement->asStatementNode());
if (statement->type() != Directive) {
break;
@ -6414,9 +6406,10 @@ public:
{
MetaNode node = this->createNode();
scopeContexts.push_back(new ASTScopeContext(this->context->strict));
StatementNodeVector body = this->parseDirectivePrologues();
RefPtr<StatementContainer> body = this->parseDirectivePrologues();
StatementNode* referNode = nullptr;
while (this->startMarker.index < this->scanner->length) {
body.push_back(this->parseStatementListItem());
referNode = body->appendChild(this->parseStatementListItem().get(), referNode);
}
scopeContexts.back()->m_locStart.line = node.line;
scopeContexts.back()->m_locStart.column = node.column;
@ -6428,7 +6421,7 @@ public:
scopeContexts.back()->m_locEnd.column = endNode.column;
#endif
scopeContexts.back()->m_locEnd.index = endNode.index;
return this->finalize(node, new ProgramNode(std::move(body), scopeContexts.back() /*, this->sourceType*/));
return this->finalize(node, new ProgramNode(body.get(), scopeContexts.back() /*, this->sourceType*/));
}
// ECMA-262 15.2.2 Imports

View file

@ -186,48 +186,6 @@ public:
return m_string->characters16() + start();
}
void* operator new(size_t size);
void* operator new[](size_t size) = delete;
protected:
String* m_string;
};
class BufferedStringView : public String {
MAKE_STACK_ALLOCATED();
public:
BufferedStringView()
: m_src(StringView())
{
init();
}
BufferedStringView(StringView src)
: m_src(src)
{
init();
}
BufferedStringView(const BufferedStringView& src, size_t s, size_t e)
: m_src(StringView(src.src(), s, e))
{
StringBufferAccessData data;
data.has8BitContent = src.m_bufferAccessData.has8BitContent;
data.length = e - s;
if (src.m_bufferAccessData.has8BitContent) {
data.buffer = ((LChar*)src.m_bufferAccessData.buffer) + s;
} else {
data.buffer = ((char16_t*)src.m_bufferAccessData.buffer) + s;
}
m_bufferAccessData = data;
}
void init()
{
m_bufferAccessData = m_src.bufferAccessData();
}
char16_t bufferedCharAt(const size_t& idx) const
{
if (m_bufferAccessData.has8BitContent) {
@ -237,81 +195,11 @@ public:
}
}
virtual char16_t charAt(const size_t& idx) const
{
return m_src.charAt(idx);
}
virtual size_t length() const
{
return m_src.length();
}
virtual UTF16StringData toUTF16StringData() const
{
UTF16StringData ret;
size_t len = length();
ret.resizeWithUninitializedValues(len);
for (size_t i = 0; i < len; i++) {
ret[i] = charAt(i);
}
return ret;
}
virtual UTF8StringData toUTF8StringData() const
{
UTF8StringDataNonGCStd ret;
const auto& accessData = bufferAccessData();
for (size_t i = 0; i < accessData.length; i++) {
char16_t ch = accessData.charAt(i);
if (ch < 0x80) {
ret.append((char*)&ch, 1);
} else {
char buf[8];
auto len = utf32ToUtf8(ch, buf);
ret.append(buf, len);
}
}
return UTF8StringData(ret.data(), ret.length());
}
virtual UTF8StringDataNonGCStd toNonGCUTF8StringData() const
{
UTF8StringDataNonGCStd ret;
const auto& accessData = bufferAccessData();
for (size_t i = 0; i < accessData.length; i++) {
char16_t ch = accessData.charAt(i);
if (ch < 0x80) {
ret.append((char*)&ch, 1);
} else {
char buf[8];
auto len = utf32ToUtf8(ch, buf);
ret.append(buf, len);
}
}
return ret;
}
virtual const LChar* characters8() const
{
return m_src.characters8();
}
virtual const char16_t* characters16() const
{
return m_src.characters16();
}
StringView src() const
{
return m_src;
}
void* operator new(size_t size);
void* operator new[](size_t size) = delete;
protected:
StringView m_src;
String* m_string;
};
inline String* StringView::createStringView(String* str, const size_t& s, const size_t& e)

View file

@ -115,7 +115,7 @@ protected:
}
// Returns whether the pointer should be freed or not.
bool derefBase()
ALWAYS_INLINE bool derefBase()
{
#if CHECK_REF_COUNTED_LIFECYCLE
ASSERT(!m_deletionHasBegun);
@ -166,7 +166,7 @@ inline void adopted(RefCountedBase* object)
template<typename T> class RefCounted : public RefCountedBase {
public:
void deref()
ALWAYS_INLINE void deref()
{
if (derefBase())
delete static_cast<T*>(this);