mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
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:
parent
1e459af46c
commit
b9a6f92b27
14 changed files with 310 additions and 94 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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")) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
4
third_party/yarr/WTFBridge.h
vendored
4
third_party/yarr/WTFBridge.h
vendored
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue