mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
Update lexical environment stuffs (#327)
* treat variable in catch() as let * add lexical environment record data into global environment for saving global permanently * re-implement variable access bytecode generation * re-implement class initialize operation * re-implement global variable access bytecode for support lexcial variables in global * fix bugs related with per-iteration lexical environment in for-statement Signed-off-by: seonghyun kim <sh8281.kim@samsung.com>
This commit is contained in:
parent
01521d2c0e
commit
2a54ab5e02
47 changed files with 1445 additions and 935 deletions
|
|
@ -33,98 +33,126 @@
|
|||
|
||||
namespace Escargot {
|
||||
|
||||
Value Script::execute(ExecutionState& state, bool isEvalMode, bool needNewEnv)
|
||||
Value Script::execute(ExecutionState& state, bool isExecuteOnEvalFunction, bool inStrictMode)
|
||||
{
|
||||
ASSERT(m_topCodeBlock != nullptr);
|
||||
|
||||
LexicalEnvironment* globalEnvironment = new LexicalEnvironment(new GlobalEnvironmentRecord(state, m_topCodeBlock, state.context()->globalObject(), isEvalMode, !needNewEnv), nullptr);
|
||||
ExecutionState newState(state.context());
|
||||
ExecutionState* codeExecutionState = &newState;
|
||||
|
||||
if (UNLIKELY(needNewEnv)) {
|
||||
EnvironmentRecord* globalRecord = new GlobalEnvironmentRecord(state, m_topCodeBlock, state.context()->globalObject(), &state.context()->globalDeclarativeRecord(), &state.context()->globalDeclarativeStorage());
|
||||
LexicalEnvironment* globalLexicalEnvironment = new LexicalEnvironment(globalRecord, nullptr);
|
||||
newState.setLexicalEnvironment(globalLexicalEnvironment, m_topCodeBlock->isStrict());
|
||||
|
||||
if (inStrictMode && isExecuteOnEvalFunction) {
|
||||
// NOTE: ES5 10.4.2.1 eval in strict mode
|
||||
newState.setParent(new ExecutionState(&state, globalEnvironment, m_topCodeBlock->isStrict()));
|
||||
EnvironmentRecord* newVariableRecord = new DeclarativeEnvironmentRecordNotIndexed(state, true);
|
||||
ExecutionState* newVariableState = new ExecutionState(state.context());
|
||||
newVariableState->setLexicalEnvironment(new LexicalEnvironment(newVariableRecord, globalLexicalEnvironment), m_topCodeBlock->isStrict());
|
||||
newVariableState->setParent(&newState);
|
||||
codeExecutionState = newVariableState;
|
||||
}
|
||||
|
||||
EnvironmentRecord* record = new DeclarativeEnvironmentRecordNotIndexed(state, m_topCodeBlock->identifierInfos());
|
||||
newState.setLexicalEnvironment(new LexicalEnvironment(record, globalEnvironment), m_topCodeBlock->isStrict());
|
||||
} else {
|
||||
newState.setLexicalEnvironment(globalEnvironment, m_topCodeBlock->isStrict());
|
||||
const InterpretedCodeBlock::IdentifierInfoVector& vec = m_topCodeBlock->identifierInfos();
|
||||
size_t len = vec.size();
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
// https://www.ecma-international.org/ecma-262/5.1/#sec-10.5
|
||||
// Step 2. If code is eval code, then let configurableBindings be true.
|
||||
if (vec[i].m_isVarDeclaration) {
|
||||
codeExecutionState->lexicalEnvironment()->record()->createBinding(*codeExecutionState, vec[i].m_name, isExecuteOnEvalFunction, vec[i].m_isMutable, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isExecuteOnEvalFunction) {
|
||||
const auto& globalLexicalVector = m_topCodeBlock->blockInfo(0)->m_identifiers;
|
||||
size_t len = globalLexicalVector.size();
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
codeExecutionState->lexicalEnvironment()->record()->createBinding(*codeExecutionState, globalLexicalVector[i].m_name, false, globalLexicalVector[i].m_isMutable, false);
|
||||
}
|
||||
}
|
||||
|
||||
Value thisValue(state.context()->globalObject());
|
||||
|
||||
size_t literalStorageSize = m_topCodeBlock->byteCodeBlock()->m_numeralLiteralData.size();
|
||||
Value* registerFile = (Value*)alloca((m_topCodeBlock->byteCodeBlock()->m_requiredRegisterFileSizeInValueSize + 1 + literalStorageSize) * sizeof(Value));
|
||||
Value* registerFile = (Value*)ALLOCA((m_topCodeBlock->byteCodeBlock()->m_requiredRegisterFileSizeInValueSize + 1 + literalStorageSize + m_topCodeBlock->lexicalBlockStackAllocatedIdentifierMaximumDepth()) * sizeof(Value), Value, state);
|
||||
registerFile[0] = Value();
|
||||
Value* stackStorage = registerFile + m_topCodeBlock->byteCodeBlock()->m_requiredRegisterFileSizeInValueSize;
|
||||
stackStorage[0] = thisValue;
|
||||
Value* literalStorage = stackStorage + 1;
|
||||
Value* literalStorage = stackStorage + 1 + m_topCodeBlock->lexicalBlockStackAllocatedIdentifierMaximumDepth();
|
||||
Value* src = m_topCodeBlock->byteCodeBlock()->m_numeralLiteralData.data();
|
||||
for (size_t i = 0; i < literalStorageSize; i++) {
|
||||
literalStorage[i] = src[i];
|
||||
}
|
||||
|
||||
Value resultValue = ByteCodeInterpreter::interpret(newState, m_topCodeBlock->byteCodeBlock(), 0, registerFile);
|
||||
Value resultValue = ByteCodeInterpreter::interpret(*codeExecutionState, m_topCodeBlock->byteCodeBlock(), 0, registerFile);
|
||||
clearStack<512>();
|
||||
|
||||
return resultValue;
|
||||
}
|
||||
|
||||
// NOTE: eval by direct call
|
||||
Value Script::executeLocal(ExecutionState& state, Value thisValue, InterpretedCodeBlock* parentCodeBlock, bool needNewRecord)
|
||||
Value Script::executeLocal(ExecutionState& state, Value thisValue, InterpretedCodeBlock* parentCodeBlock, bool isStrictModeOutside, bool isEvalCodeOnFunction)
|
||||
{
|
||||
ASSERT(m_topCodeBlock != nullptr);
|
||||
|
||||
bool isOnGlobal = true;
|
||||
FunctionEnvironmentRecord* fnRecord = nullptr;
|
||||
{
|
||||
LexicalEnvironment* env = state.lexicalEnvironment();
|
||||
while (env) {
|
||||
if (env->record()->isDeclarativeEnvironmentRecord() && env->record()->asDeclarativeEnvironmentRecord()->isFunctionEnvironmentRecord()) {
|
||||
isOnGlobal = false;
|
||||
fnRecord = env->record()->asDeclarativeEnvironmentRecord()->asFunctionEnvironmentRecord();
|
||||
break;
|
||||
}
|
||||
env = env->outerEnvironment();
|
||||
}
|
||||
}
|
||||
|
||||
EnvironmentRecord* record;
|
||||
bool inStrict = false;
|
||||
if (UNLIKELY(needNewRecord)) {
|
||||
if (UNLIKELY(isStrictModeOutside)) {
|
||||
// NOTE: ES5 10.4.2.1 eval in strict mode
|
||||
inStrict = true;
|
||||
record = new DeclarativeEnvironmentRecordNotIndexed();
|
||||
record = new DeclarativeEnvironmentRecordNotIndexed(state, true);
|
||||
} else {
|
||||
record = state.lexicalEnvironment()->record();
|
||||
}
|
||||
|
||||
const InterpretedCodeBlock::IdentifierInfoVector& vec = m_topCodeBlock->identifierInfos();
|
||||
size_t len = vec.size();
|
||||
EnvironmentRecord* recordToAddVariable = record;
|
||||
size_t vecLen = vec.size();
|
||||
|
||||
// test there was let on block scope
|
||||
LexicalEnvironment* e = state.lexicalEnvironment();
|
||||
while (!recordToAddVariable->isEvalTarget()) {
|
||||
while (e) {
|
||||
if (e->record()->isDeclarativeEnvironmentRecord() && e->record()->asDeclarativeEnvironmentRecord()->isFunctionEnvironmentRecord()) {
|
||||
break;
|
||||
}
|
||||
if (e->record()->isGlobalEnvironmentRecord()) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < vecLen; i++) {
|
||||
if (vec[i].m_isVarDeclaration) {
|
||||
auto slot = e->record()->hasBinding(state, vec[i].m_name);
|
||||
if (slot.m_isLexicallyDeclared && slot.m_index != SIZE_MAX) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::SyntaxError, vec[i].m_name.string(), false, String::emptyString, errorMessage_DuplicatedIdentifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e = e->outerEnvironment();
|
||||
}
|
||||
|
||||
EnvironmentRecord* recordToAddVariable = record;
|
||||
e = state.lexicalEnvironment();
|
||||
while (!recordToAddVariable->isVarDeclarationTarget()) {
|
||||
e = e->outerEnvironment();
|
||||
recordToAddVariable = e->record();
|
||||
}
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
for (size_t i = 0; i < vecLen; i++) {
|
||||
if (vec[i].m_isVarDeclaration) {
|
||||
recordToAddVariable->createBinding(state, vec[i].m_name, inStrict ? false : true, true);
|
||||
}
|
||||
}
|
||||
LexicalEnvironment* newEnvironment = new LexicalEnvironment(record, state.lexicalEnvironment());
|
||||
|
||||
LexicalEnvironment* newEnvironment = new LexicalEnvironment(record, state.lexicalEnvironment());
|
||||
ExecutionState newState(&state, newEnvironment, m_topCodeBlock->isStrict());
|
||||
|
||||
size_t stackStorageSize = m_topCodeBlock->totalStackAllocatedVariableSize();
|
||||
size_t identifierOnStackCount = m_topCodeBlock->identifierOnStackCount();
|
||||
size_t literalStorageSize = m_topCodeBlock->byteCodeBlock()->m_numeralLiteralData.size();
|
||||
Value* registerFile = ALLOCA((m_topCodeBlock->byteCodeBlock()->m_requiredRegisterFileSizeInValueSize + stackStorageSize + literalStorageSize) * sizeof(Value), Value, state);
|
||||
Value* registerFile = ALLOCA((m_topCodeBlock->byteCodeBlock()->m_requiredRegisterFileSizeInValueSize + stackStorageSize + literalStorageSize + m_topCodeBlock->lexicalBlockStackAllocatedIdentifierMaximumDepth()) * sizeof(Value), Value, state);
|
||||
registerFile[0] = Value();
|
||||
Value* stackStorage = registerFile + m_topCodeBlock->byteCodeBlock()->m_requiredRegisterFileSizeInValueSize;
|
||||
for (size_t i = 0; i < identifierOnStackCount; i++) {
|
||||
stackStorage[i] = Value();
|
||||
}
|
||||
Value* literalStorage = stackStorage + stackStorageSize;
|
||||
Value* literalStorage = stackStorage + stackStorageSize + m_topCodeBlock->lexicalBlockStackAllocatedIdentifierMaximumDepth();
|
||||
Value* src = m_topCodeBlock->byteCodeBlock()->m_numeralLiteralData.data();
|
||||
for (size_t i = 0; i < literalStorageSize; i++) {
|
||||
literalStorage[i] = src[i];
|
||||
|
|
@ -132,8 +160,21 @@ Value Script::executeLocal(ExecutionState& state, Value thisValue, InterpretedCo
|
|||
|
||||
stackStorage[0] = thisValue;
|
||||
|
||||
if (!isOnGlobal && m_topCodeBlock->usesArgumentsObject()) {
|
||||
if (isEvalCodeOnFunction && m_topCodeBlock->usesArgumentsObject()) {
|
||||
AtomicString arguments = state.context()->staticStrings().arguments;
|
||||
|
||||
FunctionEnvironmentRecord* fnRecord = nullptr;
|
||||
{
|
||||
LexicalEnvironment* env = state.lexicalEnvironment();
|
||||
while (env) {
|
||||
if (env->record()->isDeclarativeEnvironmentRecord() && env->record()->asDeclarativeEnvironmentRecord()->isFunctionEnvironmentRecord()) {
|
||||
fnRecord = env->record()->asDeclarativeEnvironmentRecord()->asFunctionEnvironmentRecord();
|
||||
break;
|
||||
}
|
||||
env = env->outerEnvironment();
|
||||
}
|
||||
}
|
||||
|
||||
if (fnRecord->hasBinding(newState, arguments).m_index == SIZE_MAX) {
|
||||
fnRecord->functionObject()->generateArgumentsObject(newState, fnRecord, nullptr);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue