mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
Implement CodeCache for bytecode
* store/load global ByteCodeBlock Signed-off-by: HyukWoo Park <hyukwoo.park@samsung.com>
This commit is contained in:
parent
3ec80377db
commit
11e469c6fa
26 changed files with 1463 additions and 674 deletions
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 targetEnv’s 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()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(':');
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue