From 284837daa07b29d6a63a748544a90b1f5842ac5c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 10 Sep 2012 19:10:20 +0200 Subject: Imported WebKit commit 68645295d2e3e09af2c942f092556f06aa5f8b0d (http://svn.webkit.org/repository/webkit/trunk@128073) New snapshot --- .../bytecompiler/BytecodeGenerator.cpp | 261 +++++++++++++++------ .../bytecompiler/BytecodeGenerator.h | 69 ++++-- .../JavaScriptCore/bytecompiler/NodesCodegen.cpp | 229 ++++++++++-------- 3 files changed, 368 insertions(+), 191 deletions(-) (limited to 'Source/JavaScriptCore/bytecompiler') diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index c8cfa74b6..52b576da2 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -33,13 +33,13 @@ #include "BatchedTransitionOptimizer.h" #include "Comment.h" +#include "Interpreter.h" #include "JSActivation.h" #include "JSFunction.h" -#include "Interpreter.h" +#include "JSNameScope.h" #include "LowLevelInterpreter.h" -#include "ScopeChain.h" #include "StrongInlines.h" -#include "UString.h" +#include using namespace std; @@ -188,10 +188,28 @@ JSObject* BytecodeGenerator::generate() m_scopeNode->emitBytecode(*this); + for (unsigned i = 0; i < m_tryRanges.size(); ++i) { + TryRange& range = m_tryRanges[i]; + ASSERT(range.tryData->targetScopeDepth != UINT_MAX); + HandlerInfo info = { + range.start->bind(0, 0), range.end->bind(0, 0), + range.tryData->target->bind(0, 0), range.tryData->targetScopeDepth +#if ENABLE(JIT) + , +#if ENABLE(LLINT) + CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(llint_op_catch))) +#else + CodeLocationLabel() +#endif +#endif + }; + m_codeBlock->addExceptionHandler(info); + } + m_codeBlock->instructions() = RefCountedArray(m_instructions); if (s_dumpsGeneratedCode) - m_codeBlock->dump(m_scopeChain->globalObject->globalExec()); + m_codeBlock->dump(m_scope->globalObject()->globalExec()); #ifdef NDEBUG if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode) @@ -201,7 +219,7 @@ JSObject* BytecodeGenerator::generate() m_codeBlock->shrinkToFit(CodeBlock::EarlyShrink); if (m_expressionTooDeep) - return createOutOfMemoryError(m_scopeChain->globalObject.get()); + return createOutOfMemoryError(m_scope->globalObject()); return 0; } @@ -242,11 +260,11 @@ void BytecodeGenerator::preserveLastVar() m_lastVar = &m_calleeRegisters.last(); } -BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock, CompilationKind compilationKind) - : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger()) - , m_shouldEmitProfileHooks(scopeChain->globalObject->globalObjectMethodTable()->supportsProfiling(scopeChain->globalObject.get())) - , m_shouldEmitRichSourceInfo(scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get())) - , m_scopeChain(*scopeChain->globalData, scopeChain) +BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, JSScope* scope, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock, CompilationKind compilationKind) + : m_shouldEmitDebugHooks(scope->globalObject()->debugger()) + , m_shouldEmitProfileHooks(scope->globalObject()->globalObjectMethodTable()->supportsProfiling(scope->globalObject())) + , m_shouldEmitRichSourceInfo(scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject())) + , m_scope(*scope->globalData(), scope) , m_symbolTable(symbolTable) #if ENABLE(BYTECODE_COMMENTS) , m_currentCommentString(0) @@ -263,7 +281,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s , m_hasCreatedActivation(true) , m_firstLazyFunction(0) , m_lastLazyFunction(0) - , m_globalData(scopeChain->globalData) + , m_globalData(scope->globalData()) , m_lastOpcodeID(op_end) #ifndef NDEBUG , m_lastOpcodePosition(0) @@ -288,7 +306,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s if (compilationKind == OptimizingCompilation) return; - JSGlobalObject* globalObject = scopeChain->globalObject.get(); + JSGlobalObject* globalObject = scope->globalObject(); ExecState* exec = globalObject->globalExec(); BatchedTransitionOptimizer optimizer(*m_globalData, globalObject); @@ -306,7 +324,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s bool propertyDidExist = globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties. - JSValue value = JSFunction::create(exec, makeFunction(exec, function), scopeChain); + JSValue value = JSFunction::create(exec, FunctionExecutable::create(*m_globalData, function), scope); int index = addGlobalVar( function->ident(), IsVariable, !propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable); @@ -323,11 +341,11 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s } } -BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainNode* scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock, CompilationKind) - : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger()) - , m_shouldEmitProfileHooks(scopeChain->globalObject->globalObjectMethodTable()->supportsProfiling(scopeChain->globalObject.get())) - , m_shouldEmitRichSourceInfo(scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get())) - , m_scopeChain(*scopeChain->globalData, scopeChain) +BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* scope, SymbolTable* symbolTable, CodeBlock* codeBlock, CompilationKind) + : m_shouldEmitDebugHooks(scope->globalObject()->debugger()) + , m_shouldEmitProfileHooks(scope->globalObject()->globalObjectMethodTable()->supportsProfiling(scope->globalObject())) + , m_shouldEmitRichSourceInfo(scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject())) + , m_scope(*scope->globalData(), scope) , m_symbolTable(symbolTable) #if ENABLE(BYTECODE_COMMENTS) , m_currentCommentString(0) @@ -344,7 +362,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN , m_hasCreatedActivation(false) , m_firstLazyFunction(0) , m_lastLazyFunction(0) - , m_globalData(scopeChain->globalData) + , m_globalData(scope->globalData()) , m_lastOpcodeID(op_end) #ifndef NDEBUG , m_lastOpcodePosition(0) @@ -401,6 +419,8 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN } } + RegisterID* calleeRegister = resolveCallee(functionBody); // May push to the scope chain and/or add a captured var. + const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack(); const DeclarationStacks::VarStack& varStack = functionBody->varStack(); @@ -438,6 +458,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN } codeBlock->m_numCapturedVars = codeBlock->m_numVars; + m_firstLazyFunction = codeBlock->m_numVars; for (size_t i = 0; i < functionStack.size(); ++i) { FunctionBodyNode* function = functionStack[i]; @@ -479,6 +500,9 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN preserveLastVar(); + // We declare the callee's name last because it should lose to a var, function, and/or parameter declaration. + addCallee(functionBody, calleeRegister); + if (isConstructor()) { prependComment("'this' because we are a Constructor function"); emitOpcode(op_create_this); @@ -490,11 +514,11 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN } } -BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock, CompilationKind) - : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger()) - , m_shouldEmitProfileHooks(scopeChain->globalObject->globalObjectMethodTable()->supportsProfiling(scopeChain->globalObject.get())) - , m_shouldEmitRichSourceInfo(scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get())) - , m_scopeChain(*scopeChain->globalData, scopeChain) +BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, JSScope* scope, SymbolTable* symbolTable, EvalCodeBlock* codeBlock, CompilationKind) + : m_shouldEmitDebugHooks(scope->globalObject()->debugger()) + , m_shouldEmitProfileHooks(scope->globalObject()->globalObjectMethodTable()->supportsProfiling(scope->globalObject())) + , m_shouldEmitRichSourceInfo(scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject())) + , m_scope(*scope->globalData(), scope) , m_symbolTable(symbolTable) #if ENABLE(BYTECODE_COMMENTS) , m_currentCommentString(0) @@ -511,7 +535,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeCh , m_hasCreatedActivation(true) , m_firstLazyFunction(0) , m_lastLazyFunction(0) - , m_globalData(scopeChain->globalData) + , m_globalData(scope->globalData()) , m_lastOpcodeID(op_end) #ifndef NDEBUG , m_lastOpcodePosition(0) @@ -531,7 +555,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeCh const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack(); for (size_t i = 0; i < functionStack.size(); ++i) - m_codeBlock->addFunctionDecl(makeFunction(m_globalData, functionStack[i])); + m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i])); const DeclarationStacks::VarStack& varStack = evalNode->varStack(); unsigned numVariables = varStack.size(); @@ -556,6 +580,53 @@ RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg) return reg; } +RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode) +{ + if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope()) + return 0; + + m_calleeRegister.setIndex(RegisterFile::Callee); + + // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name. + if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) { + emitOpcode(op_push_name_scope); + instructions().append(addConstant(functionBodyNode->ident())); + instructions().append(m_calleeRegister.index()); + instructions().append(ReadOnly | DontDelete); + + // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime. + m_scope.set(*globalData(), + JSNameScope::create( + m_scope->globalObject()->globalExec(), + functionBodyNode->ident(), + jsUndefined(), + ReadOnly | DontDelete, + m_scope.get() + ) + ); + return 0; + } + + if (!functionBodyNode->captures(functionBodyNode->ident())) + return &m_calleeRegister; + + // Move the callee into the captured section of the stack. + return emitMove(addVar(), &m_calleeRegister); +} + +void BytecodeGenerator::addCallee(FunctionBodyNode* functionBodyNode, RegisterID* calleeRegister) +{ + if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope()) + return; + + // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name. + if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) + return; + + ASSERT(calleeRegister); + symbolTable().add(functionBodyNode->ident().impl(), SymbolTableEntry(calleeRegister->index(), ReadOnly)); +} + void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex) { // Parameters overwrite var declarations, but not function declarations. @@ -624,14 +695,6 @@ RegisterID* BytecodeGenerator::newTemporary() return result; } -RegisterID* BytecodeGenerator::highestUsedRegister() -{ - size_t count = m_codeBlock->m_numCalleeRegisters; - while (m_calleeRegisters.size() < count) - newRegister(); - return &m_calleeRegisters.last(); -} - PassRefPtr BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name) { // Reclaim free label scopes. @@ -1022,7 +1085,7 @@ PassRefPtr