Optimize script initialization performance (#462)

* Build numeral literal number in token only if needs
* Build string literal for ast only if needs
* Move NumeralData from ASTContext to ASTNode
* Fix compile error on gcc 7+

Signed-off-by: seonghyun kim <sh8281.kim@samsung.com>
This commit is contained in:
Patrick Kim 2019-10-14 19:18:39 +09:00 committed by Boram Bae
commit b9a6f92b27
14 changed files with 310 additions and 94 deletions

View file

@ -289,6 +289,18 @@ typedef int32_t UChar32;
#define UNUSED_PARAMETER(variable) (void)variable
#endif
#if !defined(FALLTHROUGH) && defined(COMPILER_GCC)
#if __GNUC__ >= 7
#define FALLTHROUGH __attribute__((fallthrough))
#else
#define FALLTHROUGH ((void)0)
#endif
#elif !defined(FALLTHROUGH) && defined(COMPILER_CLANG)
#define FALLTHROUGH /* fall through */
#else
#define FALLTHROUGH
#endif
#if defined(__BYTE_ORDER__) && __BYTE_ORDER == __LITTLE_ENDIAN || defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(_M_IX86) || defined(__ia64) || defined(__ia64__) || defined(_M_IA64) || defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || defined(ANDROID)
#define ESCARGOT_LITTLE_ENDIAN
// #pragma message "little endian"

View file

@ -122,7 +122,13 @@ ByteCodeBlock* ByteCodeGenerator::generateByteCode(Context* c, InterpretedCodeBl
}
ParserContextInformation info(isEvalMode, isGlobalScope, codeBlock->isStrict(), inWithFromRuntime || codeBlock->inWith());
Vector<Value, GCUtil::gc_malloc_atomic_allocator<Value>>* nData = &scopeCtx->m_numeralLiteralData;
NumeralLiteralVector* nData = nullptr;
if (ast->type() == ASTNodeType::Program) {
nData = &((ProgramNode*)ast)->numeralLiteralVector();
} else {
nData = &((FunctionNode*)ast)->numeralLiteralVector();
}
if (nData->size() == 0) {
nData = nullptr;

View file

@ -70,7 +70,7 @@ struct ByteCodeGenerateError {
};
struct ByteCodeGenerateContext {
ByteCodeGenerateContext(CodeBlock* codeBlock, ByteCodeBlock* byteCodeBlock, ParserContextInformation& parserContextInformation, Vector<Value, GCUtil::gc_malloc_atomic_allocator<Value>>* numeralLiteralData)
ByteCodeGenerateContext(CodeBlock* codeBlock, ByteCodeBlock* byteCodeBlock, ParserContextInformation& parserContextInformation, NumeralLiteralVector* numeralLiteralData)
: m_baseRegisterCount(0)
, m_codeBlock(codeBlock)
, m_byteCodeBlock(byteCodeBlock)
@ -344,7 +344,7 @@ struct ByteCodeGenerateContext {
ClassContextInformation m_classInfo;
std::map<size_t, size_t> m_complexCaseStatementPositions;
size_t m_maxYieldStatementExtraDataLength;
Vector<Value, GCUtil::gc_malloc_atomic_allocator<Value>>* m_numeralLiteralData;
NumeralLiteralVector* m_numeralLiteralData;
};
class ByteCodeGenerator {

View file

@ -508,6 +508,37 @@ StringView Scanner::ScannerResult::valueStringLiteral(Scanner* scannerInstance)
return StringView(scannerInstance->source, this->valueStringLiteralData.m_start, this->valueStringLiteralData.m_end);
}
double Scanner::ScannerResult::valueNumberLiteral(Scanner* scannerInstance)
{
if (this->hasNonComputedNumberLiteral) {
const auto& bd = scannerInstance->source.bufferAccessData();
char* buffer;
int length = this->end - this->start;
if (bd.has8BitContent) {
buffer = ((char*)bd.buffer) + this->start;
} else {
buffer = ALLOCA(this->end - this->start, char, ec);
for (int i = 0; i < length; i++) {
buffer[i] = bd.uncheckedCharAtFor16Bit(i + this->start);
}
}
int lengthDummy;
double_conversion::StringToDoubleConverter converter(double_conversion::StringToDoubleConverter::ALLOW_HEX
| double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES
| double_conversion::StringToDoubleConverter::ALLOW_TRAILING_SPACES,
0.0, double_conversion::Double::NaN(),
"Infinity", "NaN");
double ll = converter.StringToDouble(buffer, length, &lengthDummy);
this->valueNumber = ll;
this->hasNonComputedNumberLiteral = false;
}
return this->valueNumber;
}
void Scanner::ScannerResult::constructStringLiteralHelperAppendUTF16(Scanner* scannerInstance, char16_t ch, UTF16StringDataNonGCStd& stringUTF16, bool& isEveryCharLatin1)
{
switch (ch) {
@ -844,9 +875,7 @@ uint16_t Scanner::octalToDecimal(char16_t ch, bool octal)
void Scanner::scanPunctuator(Scanner::ScannerResult* token, char16_t ch)
{
ASSERT(token != nullptr);
token->setResult(Token::PunctuatorToken, this->lineNumber, this->lineStart, this->index, this->index);
const size_t start = this->index;
PunctuatorKind kind;
// Check for most common single-character punctuators.
++this->index;
@ -1068,8 +1097,7 @@ void Scanner::scanPunctuator(Scanner::ScannerResult* token, char16_t ch)
break;
}
token->valuePunctuatorKind = kind;
token->end = this->index;
token->setPunctuatorResult(this->lineNumber, this->lineStart, start, this->index, kind);
}
void Scanner::scanHexLiteral(Scanner::ScannerResult* token, size_t start)
@ -1110,10 +1138,10 @@ void Scanner::scanHexLiteral(Scanner::ScannerResult* token, size_t start)
if (shouldUseDouble) {
ASSERT(number == 0);
token->setResult(Token::NumericLiteralToken, numberDouble, this->lineNumber, this->lineStart, start, this->index);
token->setNumericLiteralResult(numberDouble, this->lineNumber, this->lineStart, start, this->index, false);
} else {
ASSERT(numberDouble == 0.0);
token->setResult(Token::NumericLiteralToken, number, this->lineNumber, this->lineStart, start, this->index);
token->setNumericLiteralResult(number, this->lineNumber, this->lineStart, start, this->index, false);
}
}
@ -1146,7 +1174,7 @@ void Scanner::scanBinaryLiteral(Scanner::ScannerResult* token, size_t start)
}
}
token->setResult(Token::NumericLiteralToken, number, this->lineNumber, this->lineStart, start, this->index);
token->setNumericLiteralResult(number, this->lineNumber, this->lineStart, start, this->index, false);
}
void Scanner::scanOctalLiteral(Scanner::ScannerResult* token, char16_t prefix, size_t start)
@ -1176,7 +1204,7 @@ void Scanner::scanOctalLiteral(Scanner::ScannerResult* token, char16_t prefix, s
throwUnexpectedToken();
}
token->setResult(Token::NumericLiteralToken, number, this->lineNumber, this->lineStart, start, this->index);
token->setNumericLiteralResult(number, this->lineNumber, this->lineStart, start, this->index, false);
token->octal = octal;
}
@ -1205,13 +1233,10 @@ void Scanner::scanNumericLiteral(Scanner::ScannerResult* token)
ASSERT(isDecimalDigit(ch) || (ch == '.'));
// 'Numeric literal must start with a decimal digit or a decimal point');
std::string number;
number.reserve(32);
bool seenDotOrE = false;
if (ch != '.') {
number = this->peekChar();
auto number = this->peekChar();
++this->index;
ch = this->peekChar();
@ -1219,7 +1244,7 @@ void Scanner::scanNumericLiteral(Scanner::ScannerResult* token)
// Octal number starts with '0'.
// Octal number in ES6 starts with '0o'.
// Binary number in ES6 starts with '0b'.
if (number == "0") {
if (number == '0') {
if (ch == 'x' || ch == 'X') {
++this->index;
return this->scanHexLiteral(token, start);
@ -1239,7 +1264,6 @@ void Scanner::scanNumericLiteral(Scanner::ScannerResult* token)
}
while (isDecimalDigit(this->peekChar())) {
number += this->peekChar();
++this->index;
}
ch = this->peekChar();
@ -1247,10 +1271,8 @@ void Scanner::scanNumericLiteral(Scanner::ScannerResult* token)
if (ch == '.') {
seenDotOrE = true;
number += this->peekChar();
++this->index;
while (isDecimalDigit(this->peekChar())) {
number += this->peekChar();
++this->index;
}
ch = this->peekChar();
@ -1258,19 +1280,16 @@ void Scanner::scanNumericLiteral(Scanner::ScannerResult* token)
if (ch == 'e' || ch == 'E') {
seenDotOrE = true;
number += this->peekChar();
++this->index;
ch = this->peekChar();
if (ch == '+' || ch == '-') {
number += ch;
++this->index;
ch = this->peekChar();
}
if (isDecimalDigit(ch)) {
do {
number += ch;
++this->index;
ch = this->peekChar();
} while (isDecimalDigit(ch));
@ -1283,17 +1302,8 @@ void Scanner::scanNumericLiteral(Scanner::ScannerResult* token)
this->throwUnexpectedToken();
}
int length = number.length();
int length_dummy;
double_conversion::StringToDoubleConverter converter(double_conversion::StringToDoubleConverter::ALLOW_HEX
| double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES
| double_conversion::StringToDoubleConverter::ALLOW_TRAILING_SPACES,
0.0, double_conversion::Double::NaN(),
"Infinity", "NaN");
double ll = converter.StringToDouble(number.data(), length, &length_dummy);
token->setResult(Token::NumericLiteralToken, ll, this->lineNumber, this->lineStart, start, this->index);
if (startChar == '0' && !seenDotOrE && number.length() > 1) {
token->setNumericLiteralResult(0, this->lineNumber, this->lineStart, start, this->index, true);
if (startChar == '0' && !seenDotOrE && (this->index - start) > 1) {
token->startWithZero = true;
}
}
@ -1371,12 +1381,10 @@ void Scanner::scanStringLiteral(Scanner::ScannerResult* token)
}
if (isPlainCase) {
token->setResult(Token::StringLiteralToken, start + 1, this->index - 1, this->lineNumber, this->lineStart, start, this->index);
token->octal = octal;
token->setResult(Token::StringLiteralToken, start + 1, this->index - 1, this->lineNumber, this->lineStart, start, this->index, octal);
} else {
// build string if needs
token->setResult(Token::StringLiteralToken, (String*)nullptr, this->lineNumber, this->lineStart, start, this->index);
token->octal = octal;
token->setResult(Token::StringLiteralToken, (String*)nullptr, this->lineNumber, this->lineStart, start, this->index, octal);
}
}
@ -1534,7 +1542,7 @@ void Scanner::scanTemplate(Scanner::ScannerResult* token, bool head)
start--;
}
token->setResult(Token::TemplateToken, result, this->lineNumber, this->lineStart, start, this->index);
token->setTemplateTokenResult(result, this->lineNumber, this->lineStart, start, this->index);
}
String* Scanner::scanRegExpBody()
@ -1835,9 +1843,7 @@ ALWAYS_INLINE void Scanner::scanIdentifier(Scanner::ScannerResult* token, char16
if (data.length == 1) {
type = Token::IdentifierToken;
} else if ((keywordKind = isKeyword(data))) {
token->setResult(Token::KeywordToken, this->lineNumber, this->lineStart, start, this->index);
token->valueKeywordKind = keywordKind;
token->hasKeywordButUseString = false;
token->setKeywordResult(this->lineNumber, this->lineStart, start, this->index, keywordKind);
return;
} else if (data.length == 4) {
if (data.equalsSameLength("null")) {

View file

@ -243,6 +243,7 @@ public:
, startWithZero(false)
, octal(false)
, hasAllocatedString(false)
, hasNonComputedNumberLiteral(false)
, hasKeywordButUseString(false)
, prec(0)
, lineNumber(0)
@ -260,6 +261,7 @@ public:
bool startWithZero : 1;
bool octal : 1;
bool hasAllocatedString : 1;
bool hasNonComputedNumberLiteral : 1;
bool hasKeywordButUseString : 1;
unsigned char prec : 8; // max prec is 11
// we don't needs init prec.
@ -282,6 +284,7 @@ public:
StringView relatedSource(const StringView& source);
StringView valueStringLiteral(Scanner* scannerInstance);
Value valueStringLiteralForAST(Scanner* scannerInstance);
double valueNumberLiteral(Scanner* scannerInstance);
inline operator bool() const
{
@ -299,6 +302,7 @@ public:
this->startWithZero = false;
this->octal = false;
this->hasAllocatedString = false;
this->hasNonComputedNumberLiteral = false;
this->hasKeywordButUseString = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
@ -307,12 +311,43 @@ public:
this->valueNumber = 0;
}
void setResult(Token type, String* s, size_t lineNumber, size_t lineStart, size_t start, size_t end)
void setPunctuatorResult(size_t lineNumber, size_t lineStart, size_t start, size_t end, PunctuatorKind p)
{
this->type = Token::PunctuatorToken;
this->startWithZero = false;
this->octal = false;
this->hasAllocatedString = false;
this->hasNonComputedNumberLiteral = false;
this->hasKeywordButUseString = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;
this->end = end;
this->valuePunctuatorKind = p;
}
void setKeywordResult(size_t lineNumber, size_t lineStart, size_t start, size_t end, KeywordKind p)
{
this->type = Token::KeywordToken;
this->startWithZero = false;
this->octal = false;
this->hasAllocatedString = false;
this->hasNonComputedNumberLiteral = false;
this->hasKeywordButUseString = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;
this->end = end;
this->valueKeywordKind = p;
}
void setResult(Token type, String* s, size_t lineNumber, size_t lineStart, size_t start, size_t end, bool octal = false)
{
this->type = type;
this->startWithZero = false;
this->octal = false;
this->octal = octal;
this->hasKeywordButUseString = true;
this->hasNonComputedNumberLiteral = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;
@ -322,12 +357,13 @@ public:
this->valueStringLiteralData.m_stringIfNewlyAllocated = s;
}
void setResult(Token type, size_t stringStart, size_t stringEnd, size_t lineNumber, size_t lineStart, size_t start, size_t end)
void setResult(Token type, size_t stringStart, size_t stringEnd, size_t lineNumber, size_t lineStart, size_t start, size_t end, bool octal = false)
{
this->type = type;
this->startWithZero = false;
this->octal = false;
this->octal = octal;
this->hasKeywordButUseString = true;
this->hasNonComputedNumberLiteral = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;
@ -339,13 +375,14 @@ public:
ASSERT(this->valueStringLiteralData.m_start <= this->valueStringLiteralData.m_end);
}
void setResult(Token type, double value, size_t lineNumber, size_t lineStart, size_t start, size_t end)
void setNumericLiteralResult(double value, size_t lineNumber, size_t lineStart, size_t start, size_t end, bool hasNonComputedNumberLiteral)
{
this->type = type;
this->type = Token::NumericLiteralToken;
this->startWithZero = false;
this->octal = false;
this->hasAllocatedString = false;
this->hasKeywordButUseString = true;
this->hasNonComputedNumberLiteral = hasNonComputedNumberLiteral;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;
@ -353,13 +390,14 @@ public:
this->valueNumber = value;
}
void setResult(Token type, ScanTemplateResult* value, size_t lineNumber, size_t lineStart, size_t start, size_t end)
void setTemplateTokenResult(ScanTemplateResult* value, size_t lineNumber, size_t lineStart, size_t start, size_t end)
{
this->type = type;
this->type = Token::TemplateToken;
this->startWithZero = false;
this->octal = false;
this->hasAllocatedString = false;
this->hasKeywordButUseString = true;
this->hasNonComputedNumberLiteral = false;
this->lineNumber = lineNumber;
this->lineStart = lineStart;
this->start = start;

View file

@ -156,7 +156,6 @@ struct ASTFunctionScopeContext : public gc {
bool m_isClassStaticMethod : 1;
bool m_isGenerator : 1;
bool m_hasSuperOrNewTarget : 1;
bool m_hasManyNumeralLiteral : 1;
bool m_hasArrowParameterPlaceHolder : 1;
bool m_hasParameterOtherThanIdentifier : 1;
bool m_needsToComputeLexicalBlockStuffs : 1;
@ -173,9 +172,6 @@ struct ASTFunctionScopeContext : public gc {
ASTFunctionScopeContext *m_nextSibling;
ASTBlockScopeContextVector m_childBlockScopes;
// we can use atomic allocator here because there is no pointer value on Vector<m_numeralLiteralData>
Vector<Value, GCUtil::gc_malloc_atomic_allocator<Value>> m_numeralLiteralData;
ExtendedNodeLOC m_paramsStartLOC;
ExtendedNodeLOC m_bodyStartLOC;
#ifndef NDEBUG
@ -293,22 +289,6 @@ struct ASTFunctionScopeContext : public gc {
}
}
void insertNumeralLiteral(Value v)
{
ASSERT(!v.isPointerValue());
if (m_hasManyNumeralLiteral) {
return;
}
if (VectorUtil::findInVector(m_numeralLiteralData, v) == VectorUtil::invalidIndex) {
if (m_numeralLiteralData.size() < KEEP_NUMERAL_LITERDATA_IN_REGISTERFILE_LIMIT)
m_numeralLiteralData.push_back(v);
else {
m_numeralLiteralData.clear();
m_hasManyNumeralLiteral = true;
}
}
}
void insertBlockScope(LexicalBlockIndex blockIndex, LexicalBlockIndex parentBlockIndex, ExtendedNodeLOC loc)
{
#ifndef NDEBUG
@ -417,7 +397,6 @@ struct ASTFunctionScopeContext : public gc {
, m_isClassStaticMethod(false)
, m_isGenerator(false)
, m_hasSuperOrNewTarget(false)
, m_hasManyNumeralLiteral(false)
, m_hasArrowParameterPlaceHolder(false)
, m_hasParameterOtherThanIdentifier(false)
, m_needsToComputeLexicalBlockStuffs(false)

View file

@ -28,10 +28,11 @@ namespace Escargot {
class FunctionNode : public StatementNode {
public:
FunctionNode(StatementContainer* params, BlockStatementNode* body)
FunctionNode(StatementContainer* params, BlockStatementNode* body, NumeralLiteralVector&& numeralLiteralVector)
: StatementNode()
, m_params(params)
, m_body(body)
, m_numeralLiteralVector(std::move(numeralLiteralVector))
{
}
@ -39,6 +40,7 @@ public:
{
}
NumeralLiteralVector& numeralLiteralVector() { return m_numeralLiteralVector; }
virtual ASTNodeType type() override { return ASTNodeType::Function; }
virtual void generateStatementByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context) override
{
@ -55,6 +57,7 @@ public:
private:
RefPtr<StatementContainer> m_params;
RefPtr<BlockStatementNode> m_body;
NumeralLiteralVector m_numeralLiteralVector;
};
}

View file

@ -79,7 +79,6 @@ void* ASTFunctionScopeContext::operator new(size_t size)
GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ASTFunctionScopeContext, m_firstChild));
GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ASTFunctionScopeContext, m_nextSibling));
GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ASTFunctionScopeContext, m_childBlockScopes));
GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ASTFunctionScopeContext, m_numeralLiteralData));
descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(ASTFunctionScopeContext));
typeInited = true;
}

View file

@ -487,6 +487,8 @@ public:
};
typedef std::vector<RefPtr<Node>> NodeVector;
// we can use atomic allocator here because there is no pointer value on Vector
typedef VectorWithInlineStorage<KEEP_NUMERAL_LITERDATA_IN_REGISTERFILE_LIMIT, Value, GCUtil::gc_malloc_atomic_allocator<Value>> NumeralLiteralVector;
}
#endif

View file

@ -30,11 +30,12 @@ namespace Escargot {
class ProgramNode : public StatementNode {
public:
friend class ScriptParser;
ProgramNode(StatementContainer* body, ASTFunctionScopeContext* scopeContext, Script::ModuleData* moduleData)
ProgramNode(StatementContainer* body, ASTFunctionScopeContext* scopeContext, Script::ModuleData* moduleData, NumeralLiteralVector&& numeralLiteralVector)
: StatementNode()
, m_container(body)
, m_scopeContext(scopeContext)
, m_moduleData(moduleData)
, m_numeralLiteralVector(std::move(numeralLiteralVector))
{
}
@ -46,6 +47,7 @@ public:
virtual ASTNodeType type() override { return ASTNodeType::Program; }
ASTFunctionScopeContext* scopeContext() { return m_scopeContext; }
Script::ModuleData* moduleData() { return m_moduleData; }
NumeralLiteralVector& numeralLiteralVector() { return m_numeralLiteralVector; }
virtual void generateStatementByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context) override
{
InterpretedCodeBlock::BlockInfo* bi = codeBlock->m_codeBlock->blockInfo(0);
@ -70,6 +72,7 @@ private:
RefPtr<StatementContainer> m_container;
ASTFunctionScopeContext* m_scopeContext;
Script::ModuleData* m_moduleData;
NumeralLiteralVector m_numeralLiteralVector;
};
}

View file

@ -156,6 +156,8 @@ public:
LexicalBlockIndex lexicalBlockIndex;
LexicalBlockIndex lexicalBlockCount;
NumeralLiteralVector numeralLiteralVector;
ASTFunctionScopeContext fakeContext;
struct ParseFormalParametersResult {
@ -267,6 +269,17 @@ public:
this->lastMarker.lineStart = this->scanner->lineStart;
}
void insertNumeralLiteral(Value v)
{
ASSERT(!v.isPointerValue());
if (VectorUtil::findInVector(numeralLiteralVector, v) == VectorUtil::invalidIndex) {
if (numeralLiteralVector.size() < KEEP_NUMERAL_LITERDATA_IN_REGISTERFILE_LIMIT) {
numeralLiteralVector.push_back(v);
}
}
}
ASTFunctionScopeContext* popScopeContext(ASTFunctionScopeContext* lastPushedScopeContext)
{
auto ret = this->currentScopeContext;
@ -919,12 +932,18 @@ public:
ALLOC_TOKEN(token);
this->nextToken(token);
// raw = this->getTokenRaw(token);
if (token->type == Token::NumericLiteralToken) {
if (this->context->inLoop || token->valueNumber == 0)
this->currentScopeContext->insertNumeralLiteral(Value(token->valueNumber));
return this->finalize(node, builder.createLiteralNode(Value(token->valueNumber)));
if (builder.isNodeGenerator()) {
if (token->type == Token::NumericLiteralToken) {
double d = token->valueNumberLiteral(this->scanner);
if (this->context->inLoop || d == 0) {
this->insertNumeralLiteral(Value(d));
}
return this->finalize(node, builder.createLiteralNode(Value(d)));
} else {
return this->finalize(node, builder.createLiteralNode(token->valueStringLiteralForAST(this->scanner)));
}
} else {
return this->finalize(node, builder.createLiteralNode(token->valueStringLiteralForAST(this->scanner)));
return this->finalize(node, builder.createLiteralNode(Value()));
}
}
break;
@ -938,7 +957,9 @@ public:
// raw = this->getTokenRaw(token);
{
bool value = token->relatedSource(this->scanner->source) == "true";
this->currentScopeContext->insertNumeralLiteral(Value(value));
if (builder.isNodeGenerator()) {
this->insertNumeralLiteral(Value(value));
}
return this->finalize(node, builder.createLiteralNode(Value(value)));
}
break;
@ -951,7 +972,9 @@ public:
this->nextToken(token);
// token.value = null;
// raw = this->getTokenRaw(token);
this->currentScopeContext->insertNumeralLiteral(Value(Value::Null));
if (builder.isNodeGenerator()) {
this->insertNumeralLiteral(Value(Value::Null));
}
return this->finalize(node, builder.createLiteralNode(Value(Value::Null)));
}
case Token::TemplateToken:
@ -1399,14 +1422,21 @@ public:
// const raw = this->getTokenRaw(token);
{
Value v;
if (token->type == Token::NumericLiteralToken) {
if (this->context->inLoop || token->valueNumber == 0) {
this->currentScopeContext->insertNumeralLiteral(Value(token->valueNumber));
if (builder.isNodeGenerator()) {
if (token->type == Token::NumericLiteralToken) {
double d = token->valueNumberLiteral(this->scanner);
if (this->context->inLoop || d == 0) {
this->insertNumeralLiteral(Value(d));
}
v = Value(d);
} else {
keyString = token->valueStringLiteral(this->scanner);
v = Value(token->valueStringLiteralForAST(this->scanner));
}
v = Value(token->valueNumber);
} else {
keyString = token->valueStringLiteral(this->scanner);
v = Value(token->valueStringLiteralForAST(this->scanner));
if (token->type == Token::StringLiteralToken) {
keyString = token->valueStringLiteral(this->scanner);
}
}
key = this->finalize(node, builder.createLiteralNode(v));
}
@ -5144,7 +5174,7 @@ public:
this->currentScopeContext->m_bodyEndLOC.column = endNode.column;
#endif
this->currentScopeContext->m_bodyEndLOC.index = endNode.index;
return this->finalize(startNode, new ProgramNode(container.get(), this->currentScopeContext, this->moduleData));
return this->finalize(startNode, new ProgramNode(container.get(), this->currentScopeContext, this->moduleData, std::move(this->numeralLiteralVector)));
}
PassRefPtr<FunctionNode> parseScriptFunction(NodeGenerator& builder)
@ -5155,7 +5185,7 @@ public:
RefPtr<StatementContainer> params = this->parseFunctionParameters(builder);
RefPtr<BlockStatementNode> body = this->parseFunctionBody(builder);
return this->finalize(node, new FunctionNode(params.get(), body.get()));
return this->finalize(node, new FunctionNode(params.get(), body.get(), std::move(this->numeralLiteralVector)));
}
PassRefPtr<FunctionNode> parseScriptArrowFunction(NodeGenerator& builder, bool hasArrowParameterPlaceHolder)
@ -5225,7 +5255,7 @@ public:
body = this->finalize(nodeStart, new BlockStatementNode(container.get()));
}
return this->finalize(node, new FunctionNode(params.get(), body.get()));
return this->finalize(node, new FunctionNode(params.get(), body.get(), std::move(this->numeralLiteralVector)));
}
};

View file

@ -109,6 +109,7 @@ void AtomicString::init(AtomicStringMap* ec, String* name)
m_string = (String*)(v & ~POINTER_VALUE_STRING_TAG_IN_DATA);
return;
}
auto iter = ec->find(name);
if (ec->end() == iter) {
ec->insert(name);

View file

@ -126,6 +126,19 @@ public:
Allocator().deallocate(m_buffer, m_capacity);
}
void assign(T* start, T* end)
{
clear();
m_size = std::distance(start, end);
m_capacity = computeAllocateSize(m_size);
T* newBuffer = Allocator().allocate(m_capacity);
m_buffer = newBuffer;
VectorCopier<T>::copy(m_buffer, start, m_size);
}
void pushBack(const T& val)
{
if (m_capacity <= (m_size + 1)) {
@ -475,6 +488,134 @@ private:
size_t m_capacity;
};
// Vector for special purpose
// It has InlineStorage, so push_back operation is fast with InlineStorage
template <unsigned int InlineStorageSize, typename T,
typename ExternalStoreageAllocator>
class VectorWithInlineStorage : public gc {
public:
VectorWithInlineStorage()
{
m_size = 0;
}
VectorWithInlineStorage(VectorWithInlineStorage<InlineStorageSize, T,
ExternalStoreageAllocator>&& src)
{
m_size = src.m_size;
if (LIKELY(m_size <= InlineStorageSize)) {
for (size_t i = 0; i < m_size; i++) {
m_inlineStorage[i] = std::move(src.m_inlineStorage[i]);
}
} else {
m_externalStorage = std::move(src.m_externalStorage);
}
src.m_size = 0;
}
VectorWithInlineStorage<InlineStorageSize, T, ExternalStoreageAllocator>&
operator=(VectorWithInlineStorage<InlineStorageSize, T,
ExternalStoreageAllocator>&& src)
{
m_size = src.m_size;
if (LIKELY(m_size <= InlineStorageSize)) {
for (size_t i = 0; i < m_size; i++) {
m_inlineStorage[i] = std::move(src.m_inlineStorage[i]);
}
} else {
m_externalStorage = std::move(src.m_externalStorage);
}
src.m_size = 0;
return *this;
}
VectorWithInlineStorage<InlineStorageSize, T, ExternalStoreageAllocator>&
operator=(const VectorWithInlineStorage<InlineStorageSize, T,
ExternalStoreageAllocator>& src)
{
m_size = src.m_size;
if (LIKELY(m_size <= InlineStorageSize)) {
for (size_t i = 0; i < m_size; i++) {
m_inlineStorage[i] = src.m_inlineStorage[i];
}
} else {
m_externalStorage = src.m_externalStorage;
}
return *this;
}
void push_back(const T& decl)
{
if (LIKELY(m_size < InlineStorageSize)) {
m_inlineStorage[m_size] = decl;
} else if (m_size == InlineStorageSize) {
m_externalStorage.assign(m_inlineStorage, m_inlineStorage + m_size);
m_externalStorage.push_back(decl);
} else {
m_externalStorage.push_back(decl);
}
m_size++;
}
void push_back(T&& decl)
{
if (LIKELY(m_size < InlineStorageSize)) {
m_inlineStorage[m_size] = std::move(decl);
} else if (m_size == InlineStorageSize) {
m_externalStorage.assign(m_inlineStorage, m_inlineStorage + m_size);
m_externalStorage.push_back(std::move(decl));
} else {
m_externalStorage.push_back(std::move(decl));
}
m_size++;
}
T& operator[](const size_t& idx)
{
if (LIKELY(m_size <= InlineStorageSize)) {
return m_inlineStorage[idx];
} else {
return m_externalStorage[idx];
}
}
const T& operator[](const size_t& idx) const
{
if (LIKELY(m_size <= InlineStorageSize)) {
return m_inlineStorage[idx];
} else {
return m_externalStorage[idx];
}
}
T* data()
{
if (LIKELY(m_size <= InlineStorageSize)) {
return m_inlineStorage;
} else {
return m_externalStorage.data();
}
}
size_t size() const
{
return m_size;
}
void clear()
{
m_size = 0;
m_externalStorage.clear();
}
protected:
size_t m_size;
T m_inlineStorage[InlineStorageSize];
Vector<T, ExternalStoreageAllocator> m_externalStorage;
};
class VectorUtil {
public:

View file

@ -215,10 +215,6 @@ const size_t notFound = static_cast<size_t>(-1);
#define HAVE_MMAP 1
#endif
#if !defined(FALLTHROUGH)
#define FALLTHROUGH
#endif
#define WTFMove std::move
// NOTE there is no make_unique in c++11