Implement CodeCache for bytecode

* store/load global ByteCodeBlock

Signed-off-by: HyukWoo Park <hyukwoo.park@samsung.com>
This commit is contained in:
HyukWoo Park 2020-07-23 15:35:31 +09:00 committed by Boram Bae
commit 11e469c6fa
26 changed files with 1463 additions and 674 deletions

View file

@ -2827,9 +2827,9 @@ ScriptRef* ScriptParserRef::InitializeScriptResult::fetchScriptThrowsExceptionIf
return script.value();
}
ScriptParserRef::InitializeScriptResult ScriptParserRef::initializeScript(StringRef* script, StringRef* fileName, bool isModule)
ScriptParserRef::InitializeScriptResult ScriptParserRef::initializeScript(StringRef* script, StringRef* srcName, bool isModule)
{
auto internalResult = toImpl(this)->initializeScript(toImpl(script), toImpl(fileName), isModule);
auto internalResult = toImpl(this)->initializeScript(toImpl(script), toImpl(srcName), isModule);
ScriptParserRef::InitializeScriptResult result;
if (internalResult.script) {
result.script = toRef(internalResult.script.value());
@ -2853,7 +2853,7 @@ bool ScriptRef::isExecuted()
StringRef* ScriptRef::src()
{
return toRef(toImpl(this)->src());
return toRef(toImpl(this)->srcName());
}
StringRef* ScriptRef::sourceCode()

View file

@ -1601,7 +1601,7 @@ public:
ScriptRef* fetchScriptThrowsExceptionIfParseError(ExecutionStateRef* state);
};
InitializeScriptResult initializeScript(StringRef* scriptSource, StringRef* fileName, bool isModule = false);
InitializeScriptResult initializeScript(StringRef* scriptSource, StringRef* srcName, bool isModule = false);
};
class ESCARGOT_EXPORT ScriptRef {

View file

@ -39,19 +39,26 @@ CodeCache::~CodeCache()
{
delete m_writer;
delete m_reader;
for (auto iter = m_stringTableMap->begin(); iter != m_stringTableMap->end(); iter++) {
delete iter->second;
}
delete m_stringTableMap;
}
CacheStringTable* CodeCache::addStringTable(Script* script)
{
ASSERT(m_stringTableMap->find(script) == m_stringTableMap->end());
auto iter = m_stringTableMap->find(script);
if (iter != m_stringTableMap->end()) {
return iter->second;
}
CacheStringTable* table = new CacheStringTable();
m_stringTableMap->insert(std::make_pair(script, table));
return table;
}
void CodeCache::loadMetaInfos(Script* script)
bool CodeCache::loadMetaInfos(Script* script)
{
char metaFileName[128] = { 0 };
getMetaFileName(script, metaFileName);
@ -61,7 +68,12 @@ void CodeCache::loadMetaInfos(Script* script)
CodeCacheMetaInfo meta;
size_t sourceOffset;
size_t codeBlockDataSize;
CodeCacheMetaInfoMap* metaInfoMap = new (GC) CodeCacheMetaInfoMap;
CodeCacheMetaInfoMap* codeBlockMetaInfoMap = new (GC) CodeCacheMetaInfoMap;
CodeCacheMetaInfoMap* byteCodeMetaInfoMap = new (GC) CodeCacheMetaInfoMap;
#ifndef NDEBUG
size_t metaCount = 0;
#endif
while (!feof(metaFile)) {
fread(&sourceOffset, sizeof(size_t), 1, metaFile);
@ -72,13 +84,28 @@ void CodeCache::loadMetaInfos(Script* script)
}
ASSERT(meta.cacheType != CodeCacheType::CACHE_INVALID);
ASSERT(metaInfoMap->find(sourceOffset) == metaInfoMap->end());
metaInfoMap->insert(std::make_pair(sourceOffset, meta));
if (meta.cacheType == CodeCacheType::CACHE_CODEBLOCK) {
ASSERT(codeBlockMetaInfoMap->find(sourceOffset) == codeBlockMetaInfoMap->end());
codeBlockMetaInfoMap->insert(std::make_pair(sourceOffset, meta));
} else {
ASSERT(meta.cacheType == CodeCacheType::CACHE_BYTECODE);
ASSERT(byteCodeMetaInfoMap->find(sourceOffset) == byteCodeMetaInfoMap->end());
byteCodeMetaInfoMap->insert(std::make_pair(sourceOffset, meta));
}
#ifndef NDEBUG
metaCount++;
#endif
}
script->setCodeCacheMetaInfo(metaInfoMap);
ASSERT(metaCount == 2);
script->setCodeCacheMetaInfo(codeBlockMetaInfoMap, byteCodeMetaInfoMap);
fclose(metaFile);
return true;
}
return false;
}
void CodeCache::storeStringTable(Script* script)
@ -113,8 +140,8 @@ void CodeCache::storeStringTable(Script* script)
for (size_t i = 0; i < tableSize; i++) {
String* string = table[i].string();
bool is8Bit = string->has8BitContent();
fwrite(&is8Bit, sizeof(bool), 1, stringFile);
length = string->length();
fwrite(&is8Bit, sizeof(bool), 1, stringFile);
fwrite(&length, sizeof(size_t), 1, stringFile);
if (is8Bit) {
fwrite(string->characters8(), sizeof(LChar), length, stringFile);
@ -194,8 +221,6 @@ CacheStringTable* CodeCache::loadStringTable(Context* context, Script* script)
void CodeCache::storeCodeBlockTree(Script* script)
{
// m_writer->clear();
CacheStringTable* table = addStringTable(script);
m_writer->setStringTable(table);
@ -205,8 +230,6 @@ void CodeCache::storeCodeBlockTree(Script* script)
writeCodeBlockToFile(script, nodeCount);
//printf("STORE CodeBlock Num: %lu\n", nodeCount);
m_writer->clear();
}
@ -214,8 +237,6 @@ void CodeCache::storeCodeBlockTreeNode(InterpretedCodeBlock* codeBlock, size_t&
{
ASSERT(!!codeBlock);
//printf("STORE CodeBlock: %lu\n", codeBlock->src().end());
m_writer->storeInterpretedCodeBlock(codeBlock);
nodeCount++;
@ -227,6 +248,17 @@ void CodeCache::storeCodeBlockTreeNode(InterpretedCodeBlock* codeBlock, size_t&
}
}
void CodeCache::storeByteCodeBlock(Script* script, ByteCodeBlock* block)
{
CacheStringTable* table = addStringTable(script);
m_writer->setStringTable(table);
m_writer->storeByteCodeBlock(block);
writeByteCodeBlockToFile(script);
m_writer->clear();
}
InterpretedCodeBlock* CodeCache::loadCodeBlockTree(Context* context, Script* script, CacheStringTable* table)
{
ASSERT(!!context);
@ -234,8 +266,8 @@ InterpretedCodeBlock* CodeCache::loadCodeBlockTree(Context* context, Script* scr
m_reader->setStringTable(table);
ASSERT(!!script->codeCacheMetaInfoMap());
CodeCacheMetaInfoMap* map = script->codeCacheMetaInfoMap();
ASSERT(!!script->codeBlockMetaInfoMap());
CodeCacheMetaInfoMap* map = script->codeBlockMetaInfoMap();
// CodeBlock info has 0 as its source offset
auto iter = map->find(0);
@ -248,13 +280,11 @@ InterpretedCodeBlock* CodeCache::loadCodeBlockTree(Context* context, Script* scr
// CodeCacheMetaInfo::dataOffset has the value of nodeCount for CACHE_CODEBLOCK
size_t nodeCount = iter->second.dataOffset;
//printf("LOAD CodeBlock Num: %lu\n", nodeCount);
for (size_t i = 0; i < nodeCount; i++) {
InterpretedCodeBlock* codeBlock = m_reader->loadInterpretedCodeBlock(context, script);
// end position is used as cache id of each CodeBlock
ASSERT(tempCodeBlockMap.find(codeBlock->src().end()) == tempCodeBlockMap.end());
tempCodeBlockMap.insert(std::make_pair(codeBlock->src().end(), codeBlock));
//printf("LOAD CodeBlock: %lu\n", codeBlock->src().end());
if (i == 0) {
// GlobalCodeBlock is firstly stored and loaded
@ -293,6 +323,30 @@ InterpretedCodeBlock* CodeCache::loadCodeBlockTree(Context* context, Script* scr
return topCodeBlock;
}
ByteCodeBlock* CodeCache::loadByteCodeBlock(Context* context, Script* script, CacheStringTable* table)
{
ASSERT(!!context);
ByteCodeBlock* block = nullptr;
m_reader->setStringTable(table);
ASSERT(!!script->byteCodeMetaInfoMap());
CodeCacheMetaInfoMap* map = script->byteCodeMetaInfoMap();
// ByteCode info has 0 as its source offset
auto iter = map->find(0);
ASSERT(iter != map->end() && iter->second.cacheType == CodeCacheType::CACHE_BYTECODE);
loadFromDataFile(script, iter->second);
block = m_reader->loadByteCodeBlock(context, script);
// clear
m_reader->clear();
return block;
}
void CodeCache::writeCodeBlockToFile(Script* script, size_t nodeCount)
{
size_t sourceOffset = 0;
@ -315,6 +369,27 @@ void CodeCache::writeCodeBlockToFile(Script* script, size_t nodeCount)
fclose(dataFile);
}
void CodeCache::writeByteCodeBlockToFile(Script* script)
{
size_t sourceOffset = 0;
CodeCacheMetaInfo meta(CodeCacheType::CACHE_BYTECODE, 0, m_writer->bufferSize());
char metaFileName[128] = { 0 };
getMetaFileName(script, metaFileName);
FILE* metaFile = fopen(metaFileName, "ab");
ASSERT(metaFile);
fwrite(&sourceOffset, sizeof(size_t), 1, metaFile);
fwrite(&meta, sizeof(CodeCacheMetaInfo), 1, metaFile);
fclose(metaFile);
char dataFileName[128] = { 0 };
getByteDataFileName(script, dataFileName);
FILE* dataFile = fopen(dataFileName, "ab");
ASSERT(dataFile);
fwrite(m_writer->bufferData(), sizeof(char), m_writer->bufferSize(), dataFile);
fclose(dataFile);
}
void CodeCache::loadFromDataFile(Script* script, CodeCacheMetaInfo& metaInfo)
{
ASSERT(metaInfo.cacheType != CodeCacheType::CACHE_INVALID);
@ -324,6 +399,15 @@ void CodeCache::loadFromDataFile(Script* script, CodeCacheMetaInfo& metaInfo)
FILE* dataFile = fopen(dataFileName, "rb");
ASSERT(!!dataFile);
size_t dataSize = metaInfo.dataSize;
m_reader->loadDataFile(dataFile, dataSize);
fclose(dataFile);
} else if (metaInfo.cacheType == CodeCacheType::CACHE_BYTECODE) {
char dataFileName[128] = { 0 };
getByteDataFileName(script, dataFileName);
FILE* dataFile = fopen(dataFileName, "rb");
ASSERT(!!dataFile);
size_t dataSize = metaInfo.dataSize;
m_reader->loadDataFile(dataFile, dataSize);
fclose(dataFile);
@ -335,10 +419,10 @@ void CodeCache::getMetaFileName(Script* script, char* buffer)
size_t srcNameLength;
char srcName[128] = { 0 };
ASSERT(script->src()->has8BitContent());
ASSERT(script->src()->length() < 120);
srcNameLength = script->src()->length();
strncpy(srcName, script->src()->characters<char>(), srcNameLength);
ASSERT(script->srcName()->has8BitContent());
ASSERT(script->srcName()->length() < 120);
srcNameLength = script->srcName()->length();
strncpy(srcName, script->srcName()->characters<char>(), srcNameLength);
srcName[srcNameLength] = '\0';
// replace '/' with '_'
@ -357,10 +441,10 @@ void CodeCache::getStringFileName(Script* script, char* buffer)
size_t srcNameLength;
char srcName[128] = { 0 };
ASSERT(script->src()->has8BitContent());
ASSERT(script->src()->length() < 120);
srcNameLength = script->src()->length();
strncpy(srcName, script->src()->characters<char>(), srcNameLength);
ASSERT(script->srcName()->has8BitContent());
ASSERT(script->srcName()->length() < 120);
srcNameLength = script->srcName()->length();
strncpy(srcName, script->srcName()->characters<char>(), srcNameLength);
srcName[srcNameLength] = '\0';
// replace '/' with '_'
@ -379,10 +463,10 @@ void CodeCache::getDataFileName(Script* script, char* buffer)
size_t srcNameLength;
char srcName[128] = { 0 };
ASSERT(script->src()->has8BitContent());
ASSERT(script->src()->length() < 120);
srcNameLength = script->src()->length();
strncpy(srcName, script->src()->characters<char>(), srcNameLength);
ASSERT(script->srcName()->has8BitContent());
ASSERT(script->srcName()->length() < 120);
srcNameLength = script->srcName()->length();
strncpy(srcName, script->srcName()->characters<char>(), srcNameLength);
srcName[srcNameLength] = '\0';
// replace '/' with '_'
@ -395,5 +479,27 @@ void CodeCache::getDataFileName(Script* script, char* buffer)
strncpy(buffer, srcName, srcNameLength + 1);
strncat(buffer, "_data", 5);
}
void CodeCache::getByteDataFileName(Script* script, char* buffer)
{
size_t srcNameLength;
char srcName[128] = { 0 };
ASSERT(script->srcName()->has8BitContent());
ASSERT(script->srcName()->length() < 120);
srcNameLength = script->srcName()->length();
strncpy(srcName, script->srcName()->characters<char>(), srcNameLength);
srcName[srcNameLength] = '\0';
// replace '/' with '_'
char* pch = strchr(srcName, '/');
while (pch) {
*pch = '_';
pch = strchr(srcName, '/');
}
strncpy(buffer, srcName, srcNameLength + 1);
strncat(buffer, "_byte", 5);
}
}
#endif // ENABLE_CODE_CACHE

View file

@ -28,6 +28,7 @@ class Script;
class CodeCacheWriter;
class CodeCacheReader;
class CacheStringTable;
class ByteCodeBlock;
class InterpretedCodeBlock;
enum class CodeCacheType : uint8_t {
@ -66,13 +67,16 @@ public:
CacheStringTable* addStringTable(Script* script);
void loadMetaInfos(Script* script);
bool loadMetaInfos(Script* script);
void storeStringTable(Script* script);
CacheStringTable* loadStringTable(Context* context, Script* script);
void storeCodeBlockTree(Script* script);
void storeByteCodeBlock(Script* script, ByteCodeBlock* block);
InterpretedCodeBlock* loadCodeBlockTree(Context* context, Script* script, CacheStringTable* table);
ByteCodeBlock* loadByteCodeBlock(Context* context, Script* script, CacheStringTable* table);
private:
CodeCacheWriter* m_writer;
@ -85,11 +89,13 @@ private:
InterpretedCodeBlock* loadCodeBlockTreeNode(Script* script);
void writeCodeBlockToFile(Script* script, size_t nodeCount);
void writeByteCodeBlockToFile(Script* script);
void loadFromDataFile(Script* script, CodeCacheMetaInfo& metaInfo);
void getMetaFileName(Script* script, char* buffer);
void getStringFileName(Script* script, char* buffer);
void getDataFileName(Script* script, char* buffer);
void getByteDataFileName(Script* script, char* buffer);
};
}

View file

@ -23,7 +23,10 @@
#include "CodeCacheReaderWriter.h"
#include "parser/Script.h"
#include "parser/CodeBlock.h"
#include "interpreter/ByteCode.h"
#include "runtime/Context.h"
#include "runtime/AtomicString.h"
#include "runtime/ObjectStructurePropertyName.h"
namespace Escargot {
@ -96,7 +99,6 @@ void CodeCacheWriter::storeInterpretedCodeBlock(InterpretedCodeBlock* codeBlock)
{
ASSERT(GC_is_disabled());
ASSERT(!!codeBlock && codeBlock->isInterpretedCodeBlock());
ASSERT(!codeBlock->m_byteCodeBlock);
size_t size;
@ -258,6 +260,270 @@ void CodeCacheWriter::storeInterpretedCodeBlock(InterpretedCodeBlock* codeBlock)
}
}
void CodeCacheWriter::storeByteCodeBlock(ByteCodeBlock* block)
{
ASSERT(GC_is_disabled());
ASSERT(!!block);
size_t size;
m_buffer.ensureSize(4 * sizeof(bool) + sizeof(uint16_t));
m_buffer.put(block->m_isEvalMode);
m_buffer.put(block->m_isOnGlobal);
m_buffer.put(block->m_shouldClearStack);
m_buffer.put(block->m_isOwnerMayFreed);
m_buffer.put((uint16_t)block->m_requiredRegisterFileSizeInValueSize);
// ByteCodeBlock::m_numeralLiteralData
ByteCodeNumeralLiteralData& numeralLiteralData = block->m_numeralLiteralData;
m_buffer.putData(numeralLiteralData.data(), numeralLiteralData.size());
// ByteCodeBlock::m_stringLiteralData
ByteCodeStringLiteralData& stringLiteralData = block->m_stringLiteralData;
size = stringLiteralData.size();
m_buffer.ensureSize(sizeof(size_t));
m_buffer.put(size);
for (size_t i = 0; i < size; i++) {
m_buffer.putString(stringLiteralData[i]);
}
// ByteCodeBlock::m_otherLiteralData
ByteCodeOtherLiteralData& otherLiteralData = block->m_otherLiteralData;
size = otherLiteralData.size();
m_buffer.ensureSize(sizeof(size_t) + size * sizeof(ControlFlowRecord));
m_buffer.put(size);
for (size_t i = 0; i < size; i++) {
ControlFlowRecord* record = (ControlFlowRecord*)otherLiteralData[i];
ASSERT(record->m_reason == ControlFlowRecord::NeedsJump);
m_buffer.put(*record);
}
// ByteCodeBlock::m_code bytecode stream
storeByteCodeStream(block);
// Do not store m_inlineCacheDataSize and m_locData
// these members are used during the runtime
ASSERT(block->m_inlineCacheDataSize == 0);
ASSERT(!block->m_locData);
}
#define STORE_ATOMICSTRING_RELOC(member) \
size_t stringIndex = m_stringTable->add(bc->member); \
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_ATOMICSTRING, (size_t)currentCode - codeBase, stringIndex));
void CodeCacheWriter::storeByteCodeStream(ByteCodeBlock* block)
{
ByteCodeBlockData& byteCodeStream = block->m_code;
ASSERT(byteCodeStream.size() > 0);
// store ByteCode stream
m_buffer.putData(byteCodeStream.data(), byteCodeStream.size());
Vector<ByteCodeRelocInfo, std::allocator<ByteCodeRelocInfo>> relocInfoVector;
ByteCodeStringLiteralData& stringLiteralData = block->m_stringLiteralData;
// mark bytecode relocation infos
{
char* code = byteCodeStream.data();
size_t codeBase = (size_t)code;
char* end = code + byteCodeStream.size();
Context* context = block->codeBlock()->context();
while (code < end) {
ByteCode* currentCode = (ByteCode*)code;
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
Opcode opcode = (Opcode)(size_t)currentCode->m_opcodeInAddress;
#else
Opcode opcode = currentCode->m_opcode;
#endif
switch (opcode) {
case LoadLiteralOpcode: {
LoadLiteral* bc = (LoadLiteral*)currentCode;
if (bc->m_value.isPointerValue()) {
ASSERT(bc->m_value.asPointerValue()->isString());
String* string = bc->m_value.asPointerValue()->asString();
size_t stringIndex = VectorUtil::findInVector(stringLiteralData, string);
if (stringIndex != VectorUtil::invalidIndex) {
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_STRING, (size_t)currentCode - codeBase, stringIndex));
} else {
ASSERT(string->isAtomicStringSource());
stringIndex = m_stringTable->add(AtomicString(context, string));
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_ATOMICSTRING, (size_t)currentCode - codeBase, stringIndex));
}
}
break;
}
case LoadByNameOpcode: {
LoadByName* bc = (LoadByName*)currentCode;
STORE_ATOMICSTRING_RELOC(m_name);
break;
}
case StoreByNameOpcode: {
StoreByName* bc = (StoreByName*)currentCode;
STORE_ATOMICSTRING_RELOC(m_name);
break;
}
case InitializeByNameOpcode: {
InitializeByName* bc = (InitializeByName*)currentCode;
STORE_ATOMICSTRING_RELOC(m_name);
break;
}
case CreateFunctionOpcode: {
CreateFunction* bc = (CreateFunction*)currentCode;
InterpretedCodeBlock* codeBlock = bc->m_codeBlock;
ASSERT(!!codeBlock);
size_t codeBlockIndex = VectorUtil::findInVector(block->codeBlock()->children(), codeBlock);
ASSERT(codeBlockIndex != VectorUtil::invalidIndex);
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_CODEBLOCK, (size_t)currentCode - codeBase, codeBlockIndex));
break;
}
case CreateClassOpcode: {
CreateClass* bc = (CreateClass*)currentCode;
InterpretedCodeBlock* codeBlock = bc->m_codeBlock;
if (codeBlock) {
size_t codeBlockIndex = VectorUtil::findInVector(block->codeBlock()->children(), codeBlock);
ASSERT(codeBlockIndex != VectorUtil::invalidIndex);
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_CODEBLOCK, (size_t)currentCode - codeBase, codeBlockIndex));
}
String* string = bc->m_classSrc;
ASSERT(!!string && string->length() > 0);
size_t stringIndex = VectorUtil::findInVector(stringLiteralData, string);
ASSERT(stringIndex != VectorUtil::invalidIndex);
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_STRING, (size_t)currentCode - codeBase, stringIndex));
break;
}
case ObjectDefineOwnPropertyWithNameOperationOpcode: {
ObjectDefineOwnPropertyWithNameOperation* bc = (ObjectDefineOwnPropertyWithNameOperation*)currentCode;
STORE_ATOMICSTRING_RELOC(m_propertyName);
break;
}
case InitializeGlobalVariableOpcode: {
InitializeGlobalVariable* bc = (InitializeGlobalVariable*)currentCode;
STORE_ATOMICSTRING_RELOC(m_variableName);
break;
}
case UnaryTypeofOpcode: {
UnaryTypeof* bc = (UnaryTypeof*)currentCode;
STORE_ATOMICSTRING_RELOC(m_id);
break;
}
case UnaryDeleteOpcode: {
UnaryDelete* bc = (UnaryDelete*)currentCode;
STORE_ATOMICSTRING_RELOC(m_id);
break;
}
case JumpComplexCaseOpcode: {
JumpComplexCase* bc = (JumpComplexCase*)currentCode;
ControlFlowRecord* record = bc->m_controlFlowRecord;
size_t recordIndex = VectorUtil::findInVector(block->m_otherLiteralData, (void*)record);
ASSERT(recordIndex != VectorUtil::invalidIndex);
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_CONTROLFLOWRECORD, (size_t)currentCode - codeBase, recordIndex));
break;
}
case CallFunctionComplexCaseOpcode: {
CallFunctionComplexCase* bc = (CallFunctionComplexCase*)currentCode;
if (bc->m_kind == CallFunctionComplexCase::InWithScope) {
STORE_ATOMICSTRING_RELOC(m_calleeName);
}
break;
}
case GetMethodOpcode: {
GetMethod* bc = (GetMethod*)currentCode;
STORE_ATOMICSTRING_RELOC(m_propertyName);
break;
}
case LoadRegexpOpcode: {
LoadRegexp* bc = (LoadRegexp*)currentCode;
String* bodyString = bc->m_body;
String* optionString = bc->m_option;
ASSERT(!!bodyString && bodyString->length() > 0);
ASSERT(!!optionString && optionString->length() > 0);
size_t bodyIndex = VectorUtil::findInVector(stringLiteralData, bodyString);
size_t optionIndex = VectorUtil::findInVector(stringLiteralData, optionString);
ASSERT(bodyIndex != VectorUtil::invalidIndex);
ASSERT(optionIndex != VectorUtil::invalidIndex);
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_STRING, (size_t)currentCode - codeBase, bodyIndex));
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_STRING, (size_t)currentCode - codeBase, optionIndex));
break;
}
case BlockOperationOpcode: {
BlockOperation* bc = (BlockOperation*)currentCode;
InterpretedCodeBlock::BlockInfo* info = bc->m_blockInfo;
size_t infoIndex = VectorUtil::findInVector(block->codeBlock()->m_blockInfos, info);
ASSERT(infoIndex != VectorUtil::invalidIndex);
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_BLOCKINFO, (size_t)currentCode - codeBase, infoIndex));
break;
}
case ReplaceBlockLexicalEnvironmentOperationOpcode: {
ReplaceBlockLexicalEnvironmentOperation* bc = (ReplaceBlockLexicalEnvironmentOperation*)currentCode;
InterpretedCodeBlock::BlockInfo* info = bc->m_blockInfo;
size_t infoIndex = VectorUtil::findInVector(block->codeBlock()->m_blockInfos, info);
ASSERT(infoIndex != VectorUtil::invalidIndex);
relocInfoVector.push_back(ByteCodeRelocInfo(ByteCodeRelocType::RELOC_BLOCKINFO, (size_t)currentCode - codeBase, infoIndex));
break;
}
case ResolveNameAddressOpcode: {
ResolveNameAddress* bc = (ResolveNameAddress*)currentCode;
STORE_ATOMICSTRING_RELOC(m_name);
break;
}
case StoreByNameWithAddressOpcode: {
StoreByNameWithAddress* bc = (StoreByNameWithAddress*)currentCode;
STORE_ATOMICSTRING_RELOC(m_name);
break;
}
case GetObjectPreComputedCaseOpcode: {
GetObjectPreComputedCase* bc = (GetObjectPreComputedCase*)currentCode;
ASSERT(!bc->m_inlineCache);
ASSERT(bc->m_propertyName.hasAtomicString());
STORE_ATOMICSTRING_RELOC(m_propertyName.asAtomicString());
break;
}
case SetObjectPreComputedCaseOpcode: {
SetObjectPreComputedCase* bc = (SetObjectPreComputedCase*)currentCode;
ASSERT(!bc->m_inlineCache);
ASSERT(bc->m_propertyName.hasAtomicString());
STORE_ATOMICSTRING_RELOC(m_propertyName.asAtomicString());
break;
}
case GetGlobalVariableOpcode: {
GetGlobalVariable* bc = (GetGlobalVariable*)currentCode;
ASSERT(!!bc->m_slot);
STORE_ATOMICSTRING_RELOC(m_slot->m_propertyName);
break;
}
case SetGlobalVariableOpcode: {
SetGlobalVariable* bc = (SetGlobalVariable*)currentCode;
ASSERT(!!bc->m_slot);
STORE_ATOMICSTRING_RELOC(m_slot->m_propertyName);
break;
}
// TODO
case ThrowStaticErrorOperationOpcode:
case ExecutionResumeOpcode:
RELEASE_ASSERT_NOT_REACHED();
break;
default:
break;
}
ASSERT(opcode <= EndOpcode);
code += byteCodeLengths[opcode];
}
}
// store relocInfoVector
{
m_buffer.putData(relocInfoVector.data(), relocInfoVector.size());
}
}
void CodeCacheReader::CacheBuffer::resize(size_t size)
{
ASSERT(!m_buffer && m_capacity == 0 && m_index == 0);
@ -361,11 +627,12 @@ InterpretedCodeBlock* CodeCacheReader::loadInterpretedCodeBlock(Context* context
size_t vectorSize = m_buffer.get<size_t>();
info->m_identifiers.resizeWithUninitializedValues(vectorSize);
for (size_t j = 0; j < vectorSize; j++) {
InterpretedCodeBlock::BlockIdentifierInfo info;
info.m_needToAllocateOnStack = m_buffer.get<bool>();
info.m_isMutable = m_buffer.get<bool>();
info.m_indexForIndexedStorage = m_buffer.get<size_t>();
info.m_name = m_stringTable->get(m_buffer.get<size_t>());
InterpretedCodeBlock::BlockIdentifierInfo idInfo;
idInfo.m_needToAllocateOnStack = m_buffer.get<bool>();
idInfo.m_isMutable = m_buffer.get<bool>();
idInfo.m_indexForIndexedStorage = m_buffer.get<size_t>();
idInfo.m_name = m_stringTable->get(m_buffer.get<size_t>());
info->m_identifiers[j] = idInfo;
}
blockInfoVector[i] = info;
@ -439,6 +706,264 @@ InterpretedCodeBlock* CodeCacheReader::loadInterpretedCodeBlock(Context* context
return codeBlock;
}
ByteCodeBlock* CodeCacheReader::loadByteCodeBlock(Context* context, Script* script)
{
ASSERT(GC_is_disabled());
ASSERT(!!script->topCodeBlock());
size_t size;
ByteCodeBlock* block = new ByteCodeBlock(script->topCodeBlock());
block->m_isEvalMode = m_buffer.get<bool>();
block->m_isOnGlobal = m_buffer.get<bool>();
block->m_shouldClearStack = m_buffer.get<bool>();
block->m_isOwnerMayFreed = m_buffer.get<bool>();
block->m_requiredRegisterFileSizeInValueSize = m_buffer.get<uint16_t>();
// ByteCodeBlock::m_numeralLiteralData
ByteCodeNumeralLiteralData& numeralLiteralData = block->m_numeralLiteralData;
size = m_buffer.get<size_t>();
numeralLiteralData.resizeWithUninitializedValues(size);
m_buffer.getData(numeralLiteralData.data(), size);
// ByteCodeBlock::m_stringLiteralData
ByteCodeStringLiteralData& stringLiteralData = block->m_stringLiteralData;
size = m_buffer.get<size_t>();
stringLiteralData.resizeWithUninitializedValues(size);
for (size_t i = 0; i < size; i++) {
stringLiteralData[i] = m_buffer.getString();
}
// ByteCodeBlock::m_otherLiteralData
ByteCodeOtherLiteralData& otherLiteralData = block->m_otherLiteralData;
size = m_buffer.get<size_t>();
otherLiteralData.resizeWithUninitializedValues(size);
for (size_t i = 0; i < size; i++) {
ControlFlowRecord* record = new ControlFlowRecord(ControlFlowRecord::ControlFlowReason::NeedsJump, SIZE_MAX, SIZE_MAX);
m_buffer.getData(record, 1);
otherLiteralData[i] = record;
}
// ByteCodeBlock::m_code bytecode stream
loadByteCodeStream(context, block);
// finally, relocate opcode address and register index for each bytecode
ByteCodeGenerator::relocateByteCode(block);
return block;
}
#define LOAD_ATOMICSTRING_RELOC(member) \
size_t stringIndex = info.dataOffset; \
bc->member = m_stringTable->get(stringIndex);
void CodeCacheReader::loadByteCodeStream(Context* context, ByteCodeBlock* block)
{
ByteCodeBlockData& byteCodeStream = block->m_code;
// load ByteCode stream
{
size_t codeSize = m_buffer.get<size_t>();
byteCodeStream.resizeWithUninitializedValues(codeSize);
m_buffer.getData(byteCodeStream.data(), codeSize);
}
Vector<ByteCodeRelocInfo, std::allocator<ByteCodeRelocInfo>> relocInfoVector;
ByteCodeStringLiteralData& stringLiteralData = block->m_stringLiteralData;
// load relocInfoVector
{
size_t relocSize = m_buffer.get<size_t>();
relocInfoVector.resizeWithUninitializedValues(relocSize);
m_buffer.getData(relocInfoVector.data(), relocSize);
}
// relocate ByteCodeStream
{
char* code = byteCodeStream.data();
size_t codeBase = (size_t)code;
char* end = code + byteCodeStream.size();
InterpretedCodeBlock* codeBlock = block->codeBlock();
// mark for LoadRegexp bytecode
bool bodyStringForLoadRegexp = true;
for (size_t i = 0; i < relocInfoVector.size(); i++) {
ByteCodeRelocInfo& info = relocInfoVector[i];
ByteCode* currentCode = (ByteCode*)(code + info.codeOffset);
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
Opcode opcode = (Opcode)(size_t)currentCode->m_opcodeInAddress;
#else
Opcode opcode = currentCode->m_opcode;
#endif
switch (opcode) {
case LoadLiteralOpcode: {
LoadLiteral* bc = (LoadLiteral*)currentCode;
size_t stringIndex = info.dataOffset;
if (info.relocType == ByteCodeRelocType::RELOC_STRING) {
ASSERT(stringIndex < stringLiteralData.size());
String* string = stringLiteralData[stringIndex];
bc->m_value = Value(string);
} else {
ASSERT(info.relocType == ByteCodeRelocType::RELOC_ATOMICSTRING);
bc->m_value = Value(m_stringTable->get(stringIndex).string());
}
break;
}
case LoadByNameOpcode: {
LoadByName* bc = (LoadByName*)currentCode;
LOAD_ATOMICSTRING_RELOC(m_name);
break;
}
case StoreByNameOpcode: {
StoreByName* bc = (StoreByName*)currentCode;
LOAD_ATOMICSTRING_RELOC(m_name);
break;
}
case InitializeByNameOpcode: {
InitializeByName* bc = (InitializeByName*)currentCode;
LOAD_ATOMICSTRING_RELOC(m_name);
break;
}
case CreateFunctionOpcode: {
CreateFunction* bc = (CreateFunction*)currentCode;
InterpretedCodeBlockVector& children = codeBlock->children();
size_t childIndex = info.dataOffset;
ASSERT(childIndex < children.size());
bc->m_codeBlock = children[childIndex];
break;
}
case CreateClassOpcode: {
CreateClass* bc = (CreateClass*)currentCode;
if (info.relocType == ByteCodeRelocType::RELOC_CODEBLOCK) {
InterpretedCodeBlockVector& children = codeBlock->children();
size_t childIndex = info.dataOffset;
ASSERT(childIndex < children.size());
bc->m_codeBlock = children[childIndex];
} else {
ASSERT(info.relocType == ByteCodeRelocType::RELOC_STRING);
size_t stringIndex = info.dataOffset;
ASSERT(stringIndex < stringLiteralData.size());
bc->m_classSrc = stringLiteralData[stringIndex];
}
break;
}
case ObjectDefineOwnPropertyWithNameOperationOpcode: {
ObjectDefineOwnPropertyWithNameOperation* bc = (ObjectDefineOwnPropertyWithNameOperation*)currentCode;
LOAD_ATOMICSTRING_RELOC(m_propertyName);
break;
}
case InitializeGlobalVariableOpcode: {
InitializeGlobalVariable* bc = (InitializeGlobalVariable*)currentCode;
LOAD_ATOMICSTRING_RELOC(m_variableName);
break;
}
case UnaryTypeofOpcode: {
UnaryTypeof* bc = (UnaryTypeof*)currentCode;
LOAD_ATOMICSTRING_RELOC(m_id);
break;
}
case UnaryDeleteOpcode: {
UnaryDelete* bc = (UnaryDelete*)currentCode;
LOAD_ATOMICSTRING_RELOC(m_id);
break;
}
case JumpComplexCaseOpcode: {
JumpComplexCase* bc = (JumpComplexCase*)currentCode;
size_t recordIndex = info.dataOffset;
ByteCodeOtherLiteralData& otherLiteralData = block->m_otherLiteralData;
ASSERT(recordIndex < otherLiteralData.size());
bc->m_controlFlowRecord = (ControlFlowRecord*)otherLiteralData[recordIndex];
break;
}
case CallFunctionComplexCaseOpcode: {
CallFunctionComplexCase* bc = (CallFunctionComplexCase*)currentCode;
ASSERT(bc->m_kind == CallFunctionComplexCase::InWithScope);
LOAD_ATOMICSTRING_RELOC(m_calleeName);
break;
}
case GetMethodOpcode: {
GetMethod* bc = (GetMethod*)currentCode;
LOAD_ATOMICSTRING_RELOC(m_propertyName);
break;
}
case LoadRegexpOpcode: {
LoadRegexp* bc = (LoadRegexp*)currentCode;
String* bodyString = bc->m_body;
String* optionString = bc->m_option;
if (bodyStringForLoadRegexp) {
ASSERT(info.dataOffset < stringLiteralData.size());
bc->m_body = stringLiteralData[info.dataOffset];
bodyStringForLoadRegexp = false;
} else {
ASSERT(info.dataOffset < stringLiteralData.size());
bc->m_option = stringLiteralData[info.dataOffset];
bodyStringForLoadRegexp = true;
}
break;
}
case BlockOperationOpcode: {
BlockOperation* bc = (BlockOperation*)currentCode;
size_t blockIndex = info.dataOffset;
ASSERT(blockIndex < codeBlock->m_blockInfos.size());
bc->m_blockInfo = codeBlock->m_blockInfos[blockIndex];
break;
}
case ReplaceBlockLexicalEnvironmentOperationOpcode: {
ReplaceBlockLexicalEnvironmentOperation* bc = (ReplaceBlockLexicalEnvironmentOperation*)currentCode;
size_t blockIndex = info.dataOffset;
ASSERT(blockIndex < codeBlock->m_blockInfos.size());
bc->m_blockInfo = codeBlock->m_blockInfos[blockIndex];
break;
}
case ResolveNameAddressOpcode: {
ResolveNameAddress* bc = (ResolveNameAddress*)currentCode;
LOAD_ATOMICSTRING_RELOC(m_name);
break;
}
case StoreByNameWithAddressOpcode: {
StoreByNameWithAddress* bc = (StoreByNameWithAddress*)currentCode;
LOAD_ATOMICSTRING_RELOC(m_name);
break;
}
case GetObjectPreComputedCaseOpcode: {
GetObjectPreComputedCase* bc = (GetObjectPreComputedCase*)currentCode;
ASSERT(!bc->m_inlineCache);
LOAD_ATOMICSTRING_RELOC(m_propertyName);
break;
}
case SetObjectPreComputedCaseOpcode: {
SetObjectPreComputedCase* bc = (SetObjectPreComputedCase*)currentCode;
ASSERT(!bc->m_inlineCache);
LOAD_ATOMICSTRING_RELOC(m_propertyName);
break;
}
case GetGlobalVariableOpcode: {
GetGlobalVariable* bc = (GetGlobalVariable*)currentCode;
size_t stringIndex = info.dataOffset;
bc->m_slot = context->ensureGlobalVariableAccessCacheSlot(m_stringTable->get(stringIndex));
break;
}
case SetGlobalVariableOpcode: {
SetGlobalVariable* bc = (SetGlobalVariable*)currentCode;
size_t stringIndex = info.dataOffset;
bc->m_slot = context->ensureGlobalVariableAccessCacheSlot(m_stringTable->get(stringIndex));
break;
}
default:
RELEASE_ASSERT_NOT_REACHED();
break;
}
}
}
}
}
#endif // ENABLE_CODE_CACHE

View file

@ -29,8 +29,38 @@ namespace Escargot {
class Script;
class StringView;
class AtomicString;
class ByteCodeBlock;
class InterpretedCodeBlock;
enum class ByteCodeRelocType : uint8_t {
RELOC_INVALID,
RELOC_STRING,
RELOC_ATOMICSTRING,
RELOC_CODEBLOCK,
RELOC_CONTROLFLOWRECORD,
RELOC_BLOCKINFO,
};
struct ByteCodeRelocInfo {
ByteCodeRelocInfo()
: relocType(ByteCodeRelocType::RELOC_INVALID)
, codeOffset(SIZE_MAX)
, dataOffset(SIZE_MAX)
{
}
ByteCodeRelocInfo(ByteCodeRelocType type, size_t cOffset, size_t dOffset)
: relocType(type)
, codeOffset(cOffset)
, dataOffset(dOffset)
{
}
ByteCodeRelocType relocType;
size_t codeOffset;
size_t dataOffset;
};
class CacheStringTable {
public:
CacheStringTable()
@ -95,6 +125,29 @@ public:
m_index += sizeof(IntegralType);
}
template <typename IntegralType>
void putData(IntegralType* data, size_t size)
{
ensureSize(sizeof(size_t) + size * sizeof(IntegralType));
put(size);
memcpy(m_buffer + m_index, data, size * sizeof(IntegralType));
m_index += (size * sizeof(IntegralType));
}
void putString(String* string)
{
bool is8Bit = string->has8BitContent();
ensureSize(sizeof(bool));
put(is8Bit);
if (LIKELY(is8Bit)) {
putData(string->characters8(), string->length());
} else {
ASSERT(string->length() > 0);
putData(string->characters16(), string->length());
}
}
private:
char* m_buffer;
size_t m_capacity;
@ -116,15 +169,23 @@ public:
m_stringTable = table;
}
CacheStringTable* stringTable()
{
return m_stringTable;
}
char* bufferData() { return m_buffer.data(); }
size_t bufferSize() { return m_buffer.size(); }
void clear() { m_buffer.reset(); }
void storeInterpretedCodeBlock(InterpretedCodeBlock* codeBlock);
void storeByteCodeBlock();
void storeByteCodeBlock(ByteCodeBlock* block);
private:
CacheBuffer m_buffer;
CacheStringTable* m_stringTable;
void storeByteCodeStream(ByteCodeBlock* block);
void storeGlobalVariableAccessCache(Context* context);
};
class CodeCacheReader {
@ -158,6 +219,42 @@ public:
return value;
}
template <typename IntegralType>
void getData(IntegralType* data, size_t size)
{
size_t dataSize = size * sizeof(IntegralType);
memcpy(data, m_buffer + m_index, dataSize);
m_index += dataSize;
}
// FIXME
String* getString()
{
String* str = nullptr;
bool is8Bit = get<bool>();
if (LIKELY(is8Bit)) {
size_t length = get<size_t>();
if (length == 0) {
str = String::emptyString;
} else {
LChar* buffer = new LChar[length + 1];
buffer[length] = '\0';
getData(buffer, length);
str = new Latin1String(buffer, length);
delete[] buffer;
}
} else {
size_t length = get<size_t>();
ASSERT(length > 0);
UChar* buffer = new UChar[length + 1];
buffer[length] = '\0';
getData(buffer, length);
str = new UTF16String(buffer, length);
delete[] buffer;
}
return str;
}
private:
char* m_buffer;
size_t m_capacity;
@ -179,16 +276,25 @@ public:
m_stringTable = table;
}
CacheStringTable* stringTable()
{
return m_stringTable;
}
char* bufferData() { return m_buffer.data(); }
size_t bufferIndex() { return m_buffer.index(); }
void clear() { m_buffer.reset(); }
void loadDataFile(FILE*, size_t);
InterpretedCodeBlock* loadInterpretedCodeBlock(Context* context, Script* script);
ByteCodeBlock* loadByteCodeBlock(Context* context, Script* script);
private:
CacheBuffer m_buffer;
CacheStringTable* m_stringTable;
void loadByteCodeStream(Context* context, ByteCodeBlock* block);
void loadGlobalVariableAccessCache(Context* context);
};
}

View file

@ -647,15 +647,15 @@ bool Debugger::processIncomingMessages(ExecutionState* state, ByteCodeBlock* byt
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
if (buffer[1] != 0) {
if (breakpoint->m_opcodeInAddress != g_opcodeTable.m_table[BreakpointDisabledOpcode]) {
if (breakpoint->m_opcodeInAddress != g_opcodeTable.m_addressTable[BreakpointDisabledOpcode]) {
break;
}
breakpoint->m_opcodeInAddress = g_opcodeTable.m_table[BreakpointEnabledOpcode];
breakpoint->m_opcodeInAddress = g_opcodeTable.m_addressTable[BreakpointEnabledOpcode];
} else {
if (breakpoint->m_opcodeInAddress != g_opcodeTable.m_table[BreakpointEnabledOpcode]) {
if (breakpoint->m_opcodeInAddress != g_opcodeTable.m_addressTable[BreakpointEnabledOpcode]) {
break;
}
breakpoint->m_opcodeInAddress = g_opcodeTable.m_table[BreakpointDisabledOpcode];
breakpoint->m_opcodeInAddress = g_opcodeTable.m_addressTable[BreakpointDisabledOpcode];
}
#else
if (buffer[1] != 0) {

View file

@ -84,8 +84,8 @@ ByteCodeBlock::ByteCodeBlock(InterpretedCodeBlock* codeBlock)
, m_isOwnerMayFreed(false)
, m_requiredRegisterFileSizeInValueSize(2)
, m_inlineCacheDataSize(0)
, m_locData(nullptr)
, m_codeBlock(codeBlock)
, m_locData(nullptr)
{
auto& v = m_codeBlock->context()->vmInstance()->compiledByteCodeBlocks();
v.push_back(this);
@ -99,8 +99,8 @@ ByteCodeBlock::ByteCodeBlock(InterpretedCodeBlock* codeBlock)
}
#endif /* ESCARGOT_DEBUGGER */
self->m_numeralLiteralData.clear();
self->m_code.clear();
self->m_numeralLiteralData.clear();
if (self->m_locData) {
delete self->m_locData;
self->m_locData = nullptr;
@ -120,7 +120,8 @@ void* ByteCodeBlock::operator new(size_t size)
static GC_descr descr;
if (!typeInited) {
GC_word obj_bitmap[GC_BITMAP_SIZE(ByteCodeBlock)] = { 0 };
GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ByteCodeBlock, m_literalData));
GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ByteCodeBlock, m_stringLiteralData));
GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ByteCodeBlock, m_otherLiteralData));
GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ByteCodeBlock, m_codeBlock));
descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(ByteCodeBlock));
typeInited = true;

View file

@ -22,15 +22,11 @@
#include "interpreter/ByteCodeGenerator.h"
#include "parser/CodeBlock.h"
#include "parser/ast/Node.h"
#include "runtime/String.h"
#include "runtime/Value.h"
#include "runtime/EncodedValue.h"
#include "runtime/ExecutionPauser.h"
namespace Escargot {
class ObjectStructure;
class Node;
class ObjectStructure;
struct GlobalVariableAccessCacheItem;
// <OpcodeName, PushCount, PopCount>
@ -154,8 +150,12 @@ enum Opcode {
#endif
struct OpcodeTable {
void* m_table[OpcodeKindEnd];
OpcodeTable();
void* m_addressTable[OpcodeKindEnd];
#if defined(ENABLE_CODE_CACHE)
std::unordered_map<void*, size_t, std::hash<void*>, std::equal_to<void*>, std::allocator<std::pair<void*, size_t>>> m_opcodeMap;
#endif
};
extern OpcodeTable g_opcodeTable;
@ -201,18 +201,21 @@ public:
void assignOpcodeInAddress()
{
#ifndef NDEBUG
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
m_orgOpcode = (Opcode)(size_t)m_opcodeInAddress;
#else
m_orgOpcode = m_opcode;
#endif
#endif
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
m_opcodeInAddress = g_opcodeTable.m_table[(Opcode)(size_t)m_opcodeInAddress];
m_opcodeInAddress = g_opcodeTable.m_addressTable[(Opcode)(size_t)m_opcodeInAddress];
#endif
}
#if defined(ENABLE_CODE_CACHE)
void assignAddressInOpcode()
{
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
ASSERT(g_opcodeTable.m_opcodeMap.find(m_opcodeInAddress) != g_opcodeTable.m_opcodeMap.end());
m_opcodeInAddress = (void*)g_opcodeTable.m_opcodeMap.find(m_opcodeInAddress)->second;
#endif
}
#endif
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
void* m_opcodeInAddress;
#else
@ -879,31 +882,6 @@ public:
#endif
};
class ObjectStructureChainItem : public gc {
public:
ObjectStructureChainItem()
: m_objectStructure(nullptr)
{
}
ObjectStructureChainItem(ObjectStructure* structure)
: m_objectStructure(structure)
{
}
ObjectStructure* m_objectStructure;
bool operator==(const ObjectStructureChainItem& item) const
{
return m_objectStructure == item.m_objectStructure;
}
bool operator!=(const ObjectStructureChainItem& item) const
{
return !operator==(item);
}
};
struct GetObjectInlineCacheData {
GetObjectInlineCacheData()
{
@ -1343,6 +1321,10 @@ public:
class ControlFlowRecord : public gc {
friend class ByteCodeInterpreter;
#if defined(ENABLE_CODE_CACHE)
friend class CodeCacheWriter;
friend class CodeCacheReader;
#endif
public:
enum ControlFlowReason {
@ -1674,6 +1656,7 @@ public:
, m_argumentsStartIndex(argumentsStartIndex)
, m_resultIndex(resultIndex)
{
ASSERT(m_kind != InWithScope);
}
CallFunctionComplexCase(const ByteCodeLOC& loc, bool hasSpreadElement, bool isOptional,
@ -2497,24 +2480,19 @@ public:
#endif
};
typedef Vector<char, std::allocator<char>, ComputeReservedCapacityFunctionWithLog2<200>> ByteCodeBlockData;
typedef std::vector<std::pair<size_t, size_t>, std::allocator<std::pair<size_t, size_t>>> ByteCodeLOCData;
typedef Vector<void*, GCUtil::gc_malloc_allocator<void*>> ByteCodeLiteralData;
typedef Vector<Value, std::allocator<Value>> ByteCodeNumeralLiteralData;
typedef Vector<String*, GCUtil::gc_malloc_allocator<String*>> ByteCodeStringLiteralData;
typedef Vector<void*, GCUtil::gc_malloc_allocator<void*>> ByteCodeOtherLiteralData;
typedef std::vector<std::pair<size_t, size_t>, std::allocator<std::pair<size_t, size_t>>> ByteCodeLOCData;
class ByteCodeBlock : public gc {
friend struct OpcodeTable;
friend class VMInstance;
friend int getValidValueInByteCodeBlock(void* ptr, GC_mark_custom_result* arr);
ByteCodeBlock()
{
}
public:
explicit ByteCodeBlock(InterpretedCodeBlock* codeBlock);
void* operator new(size_t size);
template <typename CodeType>
void pushCode(const CodeType& code, ByteCodeGenerateContext* context, Node* node)
{
@ -2534,12 +2512,6 @@ public:
}
#endif
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
Opcode opcode = (Opcode)(size_t)code.m_opcodeInAddress;
#else
Opcode opcode = code.m_opcode;
#endif
char* first = (char*)&code;
size_t start = m_code.size();
if (context->m_shouldGenerateLOCData)
@ -2575,6 +2547,7 @@ public:
{
}
};
ByteCodeLexicalBlockContext pushLexicalBlock(ByteCodeGenerateContext* context, InterpretedCodeBlock::BlockInfo* bi, Node* node, bool initFunctionDeclarationInside = true);
void finalizeLexicalBlock(ByteCodeGenerateContext* context, const ByteCodeBlock::ByteCodeLexicalBlockContext& ctx);
void initFunctionDeclarationWithinBlock(ByteCodeGenerateContext* context, InterpretedCodeBlock::BlockInfo* bi, Node* node);
@ -2582,6 +2555,7 @@ public:
void updateMaxPauseStatementExtraDataLength(ByteCodeGenerateContext* context);
void pushPauseStatementExtraData(ByteCodeGenerateContext* context);
InterpretedCodeBlock* codeBlock() { return m_codeBlock; }
template <typename CodeType>
CodeType* peekCode(size_t position)
{
@ -2607,7 +2581,8 @@ public:
siz += sizeof(ByteCodeBlock);
siz += m_locData ? (m_locData->size() * sizeof(std::pair<size_t, size_t>)) : 0;
siz += m_numeralLiteralData.size() * sizeof(Value);
siz += m_literalData.size() * sizeof(size_t);
siz += m_stringLiteralData.size() * sizeof(intptr_t);
siz += m_otherLiteralData.size() * sizeof(intptr_t);
siz += m_inlineCacheDataSize;
return siz;
}
@ -2621,16 +2596,19 @@ public:
bool m_shouldClearStack : 1;
bool m_isOwnerMayFreed : 1;
ByteCodeRegisterIndex m_requiredRegisterFileSizeInValueSize : REGISTER_INDEX_IN_BIT;
size_t m_inlineCacheDataSize;
ByteCodeBlockData m_code;
ByteCodeNumeralLiteralData m_numeralLiteralData;
ByteCodeLiteralData m_literalData;
size_t m_inlineCacheDataSize;
ByteCodeLOCData* m_locData;
// m_stringLiteralData only holds String addesses not to be deallocated by GC
ByteCodeStringLiteralData m_stringLiteralData;
// m_otherLiteralData only holds various typed addesses not to be deallocated by GC
ByteCodeOtherLiteralData m_otherLiteralData;
InterpretedCodeBlock* m_codeBlock;
void* operator new(size_t size);
ByteCodeLOCData* m_locData;
};
} // namespace Escargot

File diff suppressed because it is too large Load diff

View file

@ -20,17 +20,18 @@
#ifndef __EscargotByteCodeGenerator__
#define __EscargotByteCodeGenerator__
#include "parser/CodeBlock.h"
#include "runtime/String.h"
#include "runtime/Value.h"
#include "parser/ast/Node.h"
#include "debugger/Debugger.h"
namespace Escargot {
extern const uint8_t byteCodeLengths[];
class Context;
class CodeBlock;
class ByteCodeBlock;
class Node;
class InterpretedCodeBlock;
struct ClassContextInformation {
ClassContextInformation()
@ -65,11 +66,6 @@ struct ParserContextInformation {
bool m_isWithScope : 1;
};
struct ByteCodeGenerateError {
size_t m_index;
std::string m_message;
};
#ifdef ESCARGOT_DEBUGGER
struct ByteCodeBreakpointContext {
size_t m_lastBreakpointLineOffset;
@ -405,7 +401,12 @@ struct ByteCodeGenerateContext {
class ByteCodeGenerator {
public:
static ByteCodeBlock* generateByteCode(Context* c, InterpretedCodeBlock* codeBlock, Node* ast, bool isEvalMode = false, bool isOnGlobal = false, bool inWithFromRuntime = false, bool shouldGenerateLOCData = false);
static ByteCodeBlock* generateByteCode(Context* context, InterpretedCodeBlock* codeBlock, Node* ast, bool isEvalMode = false, bool isOnGlobal = false, bool inWithFromRuntime = false, bool shouldGenerateLOCData = false, bool cacheByteCode = false);
static void relocateByteCode(ByteCodeBlock* block);
#ifndef NDEBUG
static void printByteCode(Context* context, ByteCodeBlock* block);
#endif
};
}

View file

@ -1380,8 +1380,16 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
FillOpcodeTableLbl:
#define REGISTER_TABLE(opcode, pushCount, popCount) g_opcodeTable.m_table[opcode##Opcode] = &&opcode##OpcodeLbl;
#if defined(ENABLE_CODE_CACHE)
#define REGISTER_TABLE(opcode, pushCount, popCount) \
g_opcodeTable.m_addressTable[opcode##Opcode] = &&opcode##OpcodeLbl; \
g_opcodeTable.m_opcodeMap.insert(std::make_pair(&&opcode##OpcodeLbl, (size_t)opcode##Opcode));
#else
#define REGISTER_TABLE(opcode, pushCount, popCount) \
g_opcodeTable.m_addressTable[opcode##Opcode] = &&opcode##OpcodeLbl;
#endif
FOR_EACH_BYTECODE_OP(REGISTER_TABLE);
#undef REGISTER_TABLE
#endif
@ -1798,7 +1806,7 @@ NEVER_INLINE Value ByteCodeInterpreter::getObjectPrecomputedCaseOperationCacheMi
code->m_inlineCache = new GetObjectInlineCache();
block->m_inlineCacheDataSize += sizeof(GetObjectInlineCache);
currentCodeSizeTotal += sizeof(GetObjectInlineCache);
block->m_literalData.push_back(code->m_inlineCache);
block->m_otherLiteralData.push_back(code->m_inlineCache);
}
auto inlineCache = code->m_inlineCache;
@ -1945,7 +1953,7 @@ NEVER_INLINE void ByteCodeInterpreter::setObjectPreComputedCaseOperationCacheMis
code->m_inlineCache = new SetObjectInlineCache();
block->m_inlineCacheDataSize += sizeof(SetObjectInlineCache);
currentCodeSizeTotal += sizeof(SetObjectInlineCache);
block->m_literalData.push_back(code->m_inlineCache);
block->m_otherLiteralData.push_back(code->m_inlineCache);
}
auto inlineCache = code->m_inlineCache;

View file

@ -214,7 +214,7 @@ Script::ResolveExportResult Script::resolveExport(ExecutionState& state, AtomicS
// Assert: A default export was not explicitly defined by this module.
// Throw a SyntaxError exception.
// NOTE A default export cannot be provided by an export *.
ErrorObject::throwBuiltinError(state, ErrorObject::Code::SyntaxError, "The module '%s' does not provide an export named 'default'", src());
ErrorObject::throwBuiltinError(state, ErrorObject::Code::SyntaxError, "The module '%s' does not provide an export named 'default'", srcName());
}
// Let starResolution be null.
@ -298,7 +298,7 @@ Value Script::execute(ExecutionState& state, bool isExecuteOnEvalFunction, bool
ESCARGOT_LOG_ERROR("You cannot re-execute this type of Script object");
RELEASE_ASSERT_NOT_REACHED();
}
m_topCodeBlock = state.context()->scriptParser().initializeScript(m_sourceCode, m_src, m_moduleData).script->m_topCodeBlock;
m_topCodeBlock = state.context()->scriptParser().initializeScript(m_sourceCode, m_srcName, m_moduleData).script->m_topCodeBlock;
}
if (isModule()) {
@ -975,7 +975,7 @@ Object* Script::importMetaProperty(ExecutionState& state)
// Perform ! CreateDataPropertyOrThrow(importMeta, p.[[Key]], p.[[Value]]).
// Perform ! HostFinalizeImportMeta(importMeta, module).
importMeta->defineOwnProperty(state, state.context()->staticStrings().lazyURL(),
ObjectPropertyDescriptor(Value(src()), ObjectPropertyDescriptor::AllPresent));
ObjectPropertyDescriptor(Value(srcName()), ObjectPropertyDescriptor::AllPresent));
// Set module.[[ImportMeta]] to importMeta.
moduleData()->m_importMeta = importMeta;

View file

@ -120,9 +120,9 @@ public:
};
Value execute(ExecutionState& state, bool isExecuteOnEvalFunction = false, bool inStrictMode = false);
String* src()
String* srcName()
{
return m_src;
return m_srcName;
}
String* sourceCode()
@ -161,30 +161,38 @@ public:
ModuleNamespaceObject* getModuleNamespace(ExecutionState& state);
#if defined(ENABLE_CODE_CACHE)
void setCodeCacheMetaInfo(CodeCacheMetaInfoMap* map)
void setCodeCacheMetaInfo(CodeCacheMetaInfoMap* codeBlockMap, CodeCacheMetaInfoMap* byteCodeMap)
{
ASSERT(!m_codeCacheMetaInfoMap);
m_codeCacheMetaInfoMap = map;
ASSERT(!m_codeBlockMetaInfoMap && !m_byteCodeMetaInfoMap);
m_codeBlockMetaInfoMap = codeBlockMap;
m_byteCodeMetaInfoMap = byteCodeMap;
}
CodeCacheMetaInfoMap* codeCacheMetaInfoMap()
CodeCacheMetaInfoMap* codeBlockMetaInfoMap()
{
return m_codeCacheMetaInfoMap;
return m_codeBlockMetaInfoMap;
}
CodeCacheMetaInfoMap* byteCodeMetaInfoMap()
{
return m_byteCodeMetaInfoMap;
}
#endif
private:
Script(String* src, String* sourceCode, ModuleData* moduleData, bool canExecuteAgain)
Script(String* srcName, String* sourceCode, ModuleData* moduleData, bool canExecuteAgain)
: m_canExecuteAgain(canExecuteAgain && !moduleData)
, m_src(src)
, m_srcName(srcName)
, m_sourceCode(sourceCode)
, m_topCodeBlock(nullptr)
, m_moduleData(moduleData)
#if defined(ENABLE_CODE_CACHE)
, m_codeCacheMetaInfoMap(nullptr)
, m_codeBlockMetaInfoMap(nullptr)
, m_byteCodeMetaInfoMap(nullptr)
#endif
{
}
Value executeLocal(ExecutionState& state, Value thisValue, InterpretedCodeBlock* parentCodeBlock, bool isStrictModeOutside = false, bool isEvalCodeOnFunction = false);
Script* loadModuleFromScript(ExecutionState& state, String* src);
void loadExternalModule(ExecutionState& state);
@ -251,12 +259,13 @@ private:
ModuleExecutionResult moduleExecute(ExecutionState& state);
bool m_canExecuteAgain;
String* m_src;
String* m_srcName;
String* m_sourceCode;
InterpretedCodeBlock* m_topCodeBlock;
ModuleData* m_moduleData;
#if defined(ENABLE_CODE_CACHE)
CodeCacheMetaInfoMap* m_codeCacheMetaInfoMap;
CodeCacheMetaInfoMap* m_codeBlockMetaInfoMap;
CodeCacheMetaInfoMap* m_byteCodeMetaInfoMap;
#endif
};
}

View file

@ -236,14 +236,44 @@ void ScriptParser::generateCodeBlockTreeFromASTWalkerPostProcess(InterpretedCode
}
}
ScriptParser::InitializeScriptResult ScriptParser::initializeScript(StringView scriptSource, String* fileName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, size_t stackSizeRemain, bool needByteCodeGeneration, bool allowSuperCall, bool allowSuperProperty, bool allowNewTarget)
ScriptParser::InitializeScriptResult ScriptParser::initializeScript(StringView scriptSource, String* srcName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, size_t stackSizeRemain, bool needByteCodeGeneration, bool allowSuperCall, bool allowSuperProperty, bool allowNewTarget)
{
#ifdef ESCARGOT_DEBUGGER
if (LIKELY(needByteCodeGeneration) && m_context->debugger() != nullptr && m_context->debugger()->enabled()) {
return initializeScriptWithDebugger(scriptSource, fileName, isModule, parentCodeBlock, strictFromOutside, isEvalCodeInFunction, isEvalMode, inWithOperation, allowSuperCall, allowSuperProperty, allowNewTarget);
return initializeScriptWithDebugger(scriptSource, srcName, isModule, parentCodeBlock, strictFromOutside, isEvalCodeInFunction, isEvalMode, inWithOperation, allowSuperCall, allowSuperProperty, allowNewTarget);
}
#endif /* ESCARGOT_DEBUGGER */
#if defined(ENABLE_CODE_CACHE)
bool cacheable = needByteCodeGeneration && !isModule && !isEvalMode && !srcName->equals(m_context->staticStrings().lazyFunctionInput().string());
CodeCache* codeCache = m_context->vmInstance()->codeCache();
if (cacheable && getenv("LOAD_CODE_CACHE")) {
ASSERT(!parentCodeBlock);
Script* script = new Script(srcName, new StringView(scriptSource), nullptr, !parentCodeBlock);
if (codeCache->loadMetaInfos(script)) {
GC_disable();
CacheStringTable* table = codeCache->loadStringTable(m_context, script);
// load CodeBlockTree
InterpretedCodeBlock* topCodeBlock = codeCache->loadCodeBlockTree(m_context, script, table);
script->m_topCodeBlock = topCodeBlock;
// load global ByteCodeBlock
topCodeBlock->m_byteCodeBlock = codeCache->loadByteCodeBlock(m_context, script, table);
GC_enable();
ScriptParser::InitializeScriptResult result;
result.script = script;
return result;
}
}
#endif
GC_disable();
bool inWith = (parentCodeBlock ? parentCodeBlock->inWith() : false) || inWithOperation;
@ -255,7 +285,7 @@ ScriptParser::InitializeScriptResult ScriptParser::initializeScript(StringView s
InterpretedCodeBlock* topCodeBlock = nullptr;
ProgramNode* programNode = esprima::parseProgram(m_context, scriptSource, isModule, strictFromOutside, inWith, stackSizeRemain, allowSC, allowSP, allowNewTarget);
Script* script = new Script(fileName, new StringView(scriptSource), programNode->moduleData(), !parentCodeBlock);
Script* script = new Script(srcName, new StringView(scriptSource), programNode->moduleData(), !parentCodeBlock);
if (parentCodeBlock) {
programNode->scopeContext()->m_hasEval = parentCodeBlock->hasEval();
programNode->scopeContext()->m_hasWith = parentCodeBlock->hasWith();
@ -269,39 +299,19 @@ ScriptParser::InitializeScriptResult ScriptParser::initializeScript(StringView s
topCodeBlock = generateCodeBlockTreeFromASTWalker(m_context, scriptSource, script, programNode->scopeContext(), parentCodeBlock, isEvalMode, isEvalCodeInFunction);
generateCodeBlockTreeFromASTWalkerPostProcess(topCodeBlock);
} else {
#if defined(ENABLE_CODE_CACHE)
m_context->vmInstance()->codeCache()->loadMetaInfos(script);
if (getenv("LOAD_CODE_CACHE") && script->codeCacheMetaInfoMap()) {
CacheStringTable* table = m_context->vmInstance()->codeCache()->loadStringTable(m_context, script);
topCodeBlock = m_context->vmInstance()->codeCache()->loadCodeBlockTree(m_context, script, table);
} else {
topCodeBlock = generateCodeBlockTreeFromAST(m_context, scriptSource, script, programNode, isEvalMode, isEvalCodeInFunction);
generateCodeBlockTreeFromASTWalkerPostProcess(topCodeBlock);
}
#else
topCodeBlock = generateCodeBlockTreeFromAST(m_context, scriptSource, script, programNode, isEvalMode, isEvalCodeInFunction);
generateCodeBlockTreeFromASTWalkerPostProcess(topCodeBlock);
#endif
}
script->m_topCodeBlock = topCodeBlock;
#if defined(ENABLE_CODE_CACHE)
// Code Cache does not support eval code and dynamic function code
if (getenv("STORE_CODE_CACHE")) {
if (!fileName->equals(m_context->staticStrings().lazyEvalInput().string()) && !fileName->equals(m_context->staticStrings().lazyFunctionInput().string())) {
ASSERT(!isEvalMode && !parentCodeBlock);
m_context->vmInstance()->codeCache()->storeCodeBlockTree(script);
m_context->vmInstance()->codeCache()->storeStringTable(script);
}
}
#endif
// dump Code Block
#ifndef NDEBUG
char* dumpCodeBlockTreeValue = getenv("DUMP_CODEBLOCK_TREE");
if (dumpCodeBlockTreeValue && (strcmp(dumpCodeBlockTreeValue, "1") == 0)) {
dumpCodeBlockTree(topCodeBlock);
{
char* dumpCodeBlockTreeValue = getenv("DUMP_CODEBLOCK_TREE");
if (dumpCodeBlockTreeValue && (strcmp(dumpCodeBlockTreeValue, "1") == 0)) {
dumpCodeBlockTree(topCodeBlock);
}
}
#endif
@ -309,11 +319,23 @@ ScriptParser::InitializeScriptResult ScriptParser::initializeScript(StringView s
// Generate ByteCode
if (LIKELY(needByteCodeGeneration)) {
#if defined(ENABLE_CODE_CACHE)
topCodeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(m_context, topCodeBlock, programNode, isEvalMode, !isEvalCodeInFunction, inWith, false, cacheable);
#else
topCodeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(m_context, topCodeBlock, programNode, isEvalMode, !isEvalCodeInFunction, inWith);
#endif
}
// reset ASTAllocator
m_context->astAllocator().reset();
#if defined(ENABLE_CODE_CACHE)
if (cacheable && getenv("STORE_CODE_CACHE")) {
codeCache->storeCodeBlockTree(script);
codeCache->storeStringTable(script);
}
#endif
GC_enable();
ScriptParser::InitializeScriptResult result;
@ -403,7 +425,7 @@ void ScriptParser::recursivelyGenerateChildrenByteCode(InterpretedCodeBlock* par
}
}
ScriptParser::InitializeScriptResult ScriptParser::initializeScriptWithDebugger(StringView scriptSource, String* fileName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, bool allowSuperCall, bool allowSuperProperty, bool allowNewTarget)
ScriptParser::InitializeScriptResult ScriptParser::initializeScriptWithDebugger(StringView scriptSource, String* srcName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, bool allowSuperCall, bool allowSuperProperty, bool allowNewTarget)
{
GC_disable();
@ -422,12 +444,12 @@ ScriptParser::InitializeScriptResult ScriptParser::initializeScriptWithDebugger(
m_context->debugger()->sendString(Debugger::ESCARGOT_MESSAGE_SOURCE_8BIT, scriptSourceView);
if (m_context->debugger()->enabled()) {
StringView* fileNameView = new StringView(fileName);
m_context->debugger()->sendString(Debugger::ESCARGOT_MESSAGE_FILE_NAME_8BIT, fileNameView);
StringView* srcNameView = new StringView(srcName);
m_context->debugger()->sendString(Debugger::ESCARGOT_MESSAGE_FILE_NAME_8BIT, srcNameView);
}
}
Script* script = new Script(fileName, scriptSourceView, programNode->moduleData(), !parentCodeBlock);
Script* script = new Script(srcName, scriptSourceView, programNode->moduleData(), !parentCodeBlock);
if (parentCodeBlock) {
programNode->scopeContext()->m_hasEval = parentCodeBlock->hasEval();
programNode->scopeContext()->m_hasWith = parentCodeBlock->hasWith();
@ -447,9 +469,11 @@ ScriptParser::InitializeScriptResult ScriptParser::initializeScriptWithDebugger(
// dump Code Block
#ifndef NDEBUG
char* dumpCodeBlockTreeValue = getenv("DUMP_CODEBLOCK_TREE");
if (dumpCodeBlockTreeValue && (strcmp(dumpCodeBlockTreeValue, "1") == 0)) {
dumpCodeBlockTree(topCodeBlock);
{
char* dumpCodeBlockTreeValue = getenv("DUMP_CODEBLOCK_TREE");
if (dumpCodeBlockTreeValue && (strcmp(dumpCodeBlockTreeValue, "1") == 0)) {
dumpCodeBlockTree(topCodeBlock);
}
}
#endif

View file

@ -58,10 +58,10 @@ public:
}
};
InitializeScriptResult initializeScript(StringView scriptSource, String* fileName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, size_t stackSizeRemain, bool needByteCodeGeneration, bool allowSuperCall, bool allowSuperProperty, bool allowNewTarget);
InitializeScriptResult initializeScript(String* scriptSource, String* fileName, bool isModule, bool strictFromOutside = false, bool isRunningEvalOnFunction = false, bool isEvalMode = false, size_t stackSizeRemain = SIZE_MAX)
InitializeScriptResult initializeScript(StringView scriptSource, String* srcName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, size_t stackSizeRemain, bool needByteCodeGeneration, bool allowSuperCall, bool allowSuperProperty, bool allowNewTarget);
InitializeScriptResult initializeScript(String* scriptSource, String* srcName, bool isModule, bool strictFromOutside = false, bool isRunningEvalOnFunction = false, bool isEvalMode = false, size_t stackSizeRemain = SIZE_MAX)
{
return initializeScript(StringView(scriptSource, 0, scriptSource->length()), fileName, isModule, nullptr, strictFromOutside, isRunningEvalOnFunction, isEvalMode, false, stackSizeRemain, true, false, false, false);
return initializeScript(StringView(scriptSource, 0, scriptSource->length()), srcName, isModule, nullptr, strictFromOutside, isRunningEvalOnFunction, isEvalMode, false, stackSizeRemain, true, false, false, false);
}
void generateFunctionByteCode(ExecutionState& state, InterpretedCodeBlock* codeBlock, size_t stackSizeRemain);
@ -76,7 +76,7 @@ private:
#ifdef ESCARGOT_DEBUGGER
void recursivelyGenerateChildrenByteCode(InterpretedCodeBlock* topCodeBlock);
InitializeScriptResult initializeScriptWithDebugger(StringView scriptSource, String* fileName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, bool allowSuperCall, bool allowSuperProperty, bool allowNewTarget);
InitializeScriptResult initializeScriptWithDebugger(StringView scriptSource, String* srcName, bool isModule, InterpretedCodeBlock* parentCodeBlock, bool strictFromOutside, bool isEvalCodeInFunction, bool isEvalMode, bool inWithOperation, bool allowSuperCall, bool allowSuperProperty, bool allowNewTarget);
#endif /* ESCARGOT_DEBUGGER */
Context* m_context;

View file

@ -55,7 +55,7 @@ public:
context->m_classInfo.m_name = classIdent ? classIdent->asIdentifier()->name() : AtomicString();
context->m_classInfo.m_src = new StringView(m_class.classSrc());
codeBlock->m_literalData.push_back(context->m_classInfo.m_src);
codeBlock->m_stringLiteralData.push_back(context->m_classInfo.m_src);
size_t lexicalBlockIndexBefore = context->m_lexicalBlockIndex;
ByteCodeBlock::ByteCodeLexicalBlockContext blockContext;

View file

@ -53,7 +53,7 @@ public:
context->m_classInfo.m_superIndex = m_class.superClass() ? context->getRegister() : SIZE_MAX;
context->m_classInfo.m_name = classIdent ? classIdent->asIdentifier()->name() : AtomicString();
context->m_classInfo.m_src = new StringView(m_class.classSrc());
codeBlock->m_literalData.push_back(context->m_classInfo.m_src);
codeBlock->m_stringLiteralData.push_back(context->m_classInfo.m_src);
size_t lexicalBlockIndexBefore = context->m_lexicalBlockIndex;
ByteCodeBlock::ByteCodeLexicalBlockContext blockContext;

View file

@ -32,6 +32,8 @@ public:
: ExpressionNode()
, m_value(value)
{
// LiteralNode is allowed to have non-pointer value or string value only
ASSERT(!value.isPointerValue() || value.asPointerValue()->isString());
}
virtual ASTNodeType type() override { return ASTNodeType::Literal; }
@ -39,7 +41,8 @@ public:
virtual void generateExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister) override
{
if (m_value.isPointerValue()) {
codeBlock->m_literalData.pushBack(m_value.asPointerValue());
ASSERT(m_value.asPointerValue()->isString());
codeBlock->m_stringLiteralData.pushBack(m_value.asPointerValue()->asString());
}
if (dstRegister < REGULAR_REGISTER_LIMIT + VARIABLE_LIMIT) {
codeBlock->pushCode(LoadLiteral(ByteCodeLOC(m_loc.index), dstRegister, m_value), context, this);

View file

@ -39,8 +39,8 @@ public:
String* flag() { return m_flag; }
virtual void generateExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister) override
{
codeBlock->m_literalData.pushBack(m_body);
codeBlock->m_literalData.pushBack(m_flag);
codeBlock->m_stringLiteralData.pushBack(m_body);
codeBlock->m_stringLiteralData.pushBack(m_flag);
codeBlock->pushCode(LoadRegexp(ByteCodeLOC(m_loc.index), dstRegister, m_body, m_flag), context, this);
}

View file

@ -58,7 +58,7 @@ public:
Value value;
if ((*m_quasis)[0]->value) {
String* str = new UTF16String(std::move((*m_quasis)[0]->value.value()));
codeBlock->m_literalData.push_back(str);
codeBlock->m_stringLiteralData.push_back(str);
value = str;
}
codeBlock->pushCode(LoadLiteral(ByteCodeLOC(m_loc.index), dstRegister, value), context, this);
@ -73,7 +73,7 @@ public:
if ((*m_quasis)[index + 1]->value) {
String* str = new UTF16String(std::move((*m_quasis)[index + 1]->value.value()));
if (str->length()) {
codeBlock->m_literalData.push_back(str);
codeBlock->m_stringLiteralData.push_back(str);
size_t reg = context->getRegister();
codeBlock->pushCode(LoadLiteral(ByteCodeLOC(m_loc.index), reg, Value(str)), context, this);
codeBlock->pushCode(TemplateOperation(ByteCodeLOC(m_loc.index), dstRegister, reg, dstRegister), context, this);

View file

@ -83,6 +83,10 @@ class Context : public gc {
friend class ByteCodeInterpreter;
friend struct OpcodeTable;
friend class ContextRef;
#if defined(ENABLE_CODE_CACHE)
friend class CodeCacheWriter;
friend class CodeCacheReader;
#endif
public:
struct RegExpStatus {

View file

@ -181,7 +181,7 @@ ObjectGetResult ModuleNamespaceObject::get(ExecutionState& state, const ObjectPr
// Let targetEnv be targetModule.[[Environment]].
if (!targetModule->moduleData()->m_moduleRecord) {
// If targetEnv is undefined, throw a ReferenceError exception.
ErrorObject::throwBuiltinError(state, ErrorObject::Code::ReferenceError, "module '%s' is not correctly loaded", targetModule->src());
ErrorObject::throwBuiltinError(state, ErrorObject::Code::ReferenceError, "module '%s' is not correctly loaded", targetModule->srcName());
return ObjectGetResult();
}
// Let targetEnvRec be targetEnvs EnvironmentRecord.
@ -228,7 +228,7 @@ void ModuleNamespaceObject::enumeration(ExecutionState& state, bool (*callback)(
}
Script* targetModule = std::get<0>(binding.m_record.value());
if (!targetModule->moduleData()->m_moduleRecord) {
ErrorObject::throwBuiltinError(state, ErrorObject::Code::ReferenceError, "module '%s' is not correctly loaded", targetModule->src());
ErrorObject::throwBuiltinError(state, ErrorObject::Code::ReferenceError, "module '%s' is not correctly loaded", targetModule->srcName());
}
targetModule->moduleData()->m_moduleRecord->getBindingValue(state, std::get<1>(binding.m_record.value()));
}

View file

@ -74,7 +74,7 @@ void SandBox::processCatch(const Value& error, SandBoxResult& result)
StackTraceData traceData;
traceData.loc = loc;
InterpretedCodeBlock* cb = m_stackTraceData[i].second.loc.actualCodeBlock->m_codeBlock;
traceData.src = cb->script()->src();
traceData.src = cb->script()->srcName();
traceData.sourceCode = cb->script()->sourceCode();
traceData.functionName = m_stackTraceData[i].second.functionName;
traceData.isFunction = m_stackTraceData[i].second.isFunction;
@ -177,7 +177,7 @@ void SandBox::createStackTraceData(StackTraceDataVector& stackTraceData, Executi
}
SandBox::StackTraceData data;
data.loc = loc;
data.src = cb->script()->src();
data.src = cb->script()->srcName();
data.sourceCode = cb->script()->sourceCode();
data.isEval = true;
data.isFunction = false;
@ -194,7 +194,7 @@ void SandBox::createStackTraceData(StackTraceDataVector& stackTraceData, Executi
ExtendedNodeLOC loc(SIZE_MAX, SIZE_MAX, SIZE_MAX);
SandBox::StackTraceData data;
data.loc = loc;
data.src = cb->asInterpretedCodeBlock()->script()->src();
data.src = cb->asInterpretedCodeBlock()->script()->srcName();
data.sourceCode = String::emptyString;
data.isEval = true;
data.isFunction = false;
@ -219,7 +219,7 @@ void SandBox::createStackTraceData(StackTraceDataVector& stackTraceData, Executi
SandBox::StackTraceData data;
data.loc = loc;
if (cb->isInterpretedCodeBlock() && cb->asInterpretedCodeBlock()->script()) {
data.src = cb->asInterpretedCodeBlock()->script()->src();
data.src = cb->asInterpretedCodeBlock()->script()->srcName();
#ifdef ESCARGOT_DEBUGGER
data.executionStateDepth = executionStateDepthIndex;
#endif /* ESCARGOT_DEBUGGER */
@ -338,7 +338,7 @@ void ErrorObject::StackTraceData::buildStackTrace(Context* context, StringBuilde
} else {
ExtendedNodeLOC loc = gcValues[i].byteCodeBlock->computeNodeLOCFromByteCode(context,
nonGCValues[i].byteCodePosition, gcValues[i].byteCodeBlock->m_codeBlock);
builder.appendString(gcValues[i].byteCodeBlock->m_codeBlock->script()->src());
builder.appendString(gcValues[i].byteCodeBlock->m_codeBlock->script()->srcName());
builder.appendChar(':');
builder.appendString(String::fromDouble(loc.line));
builder.appendChar(':');

View file

@ -288,10 +288,12 @@ public:
{
return m_bufferData.length;
}
virtual char16_t charAt(const size_t idx) const
{
return bufferAccessData().charAt(idx);
}
char16_t operator[](const size_t idx) const
{
return charAt(idx);
@ -305,6 +307,11 @@ public:
return m_bufferData;
}
bool isAtomicStringSource() const
{
return (m_tag > POINTER_VALUE_STRING_TAG_IN_DATA);
}
bool equals(const String* src) const;
template <const size_t srcLen>

View file

@ -563,13 +563,13 @@ public:
}
};
static bool evalScript(ContextRef* context, StringRef* str, StringRef* fileName, bool shouldPrintScriptResult, bool isModule)
static bool evalScript(ContextRef* context, StringRef* str, StringRef* srcName, bool shouldPrintScriptResult, bool isModule)
{
if (stringEndsWith(fileName->toStdUTF8String(), "mjs")) {
if (stringEndsWith(srcName->toStdUTF8String(), "mjs")) {
isModule = isModule || true;
}
auto scriptInitializeResult = context->scriptParser()->initializeScript(str, fileName, isModule);
auto scriptInitializeResult = context->scriptParser()->initializeScript(str, srcName, isModule);
if (!scriptInitializeResult.script) {
fprintf(stderr, "Script parsing error: ");
switch (scriptInitializeResult.parseErrorCode) {