X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/9dae56ea45a0f5f8136a5c93d6f3a7f99399ca73..fb8617cde5834786bd4e4afd579883e4acf5666e:/bytecompiler/BytecodeGenerator.cpp diff --git a/bytecompiler/BytecodeGenerator.cpp b/bytecompiler/BytecodeGenerator.cpp index cd89c1e..b0a0877 100644 --- a/bytecompiler/BytecodeGenerator.cpp +++ b/bytecompiler/BytecodeGenerator.cpp @@ -31,6 +31,7 @@ #include "BytecodeGenerator.h" #include "BatchedTransitionOptimizer.h" +#include "PrototypeFunction.h" #include "JSFunction.h" #include "Interpreter.h" #include "UString.h" @@ -195,17 +196,10 @@ bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, R return result.second; } -void BytecodeGenerator::allocateConstants(size_t count) +void BytecodeGenerator::preserveLastVar() { - m_codeBlock->m_numConstants = count; - if (!count) - return; - - m_nextConstantIndex = m_calleeRegisters.size(); - - for (size_t i = 0; i < count; ++i) - newRegister(); - m_lastConstant = &m_calleeRegisters.last(); + if ((m_firstConstantIndex = m_calleeRegisters.size()) != 0) + m_lastVar = &m_calleeRegisters.last(); } BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock) @@ -221,6 +215,8 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d , m_baseScopeDepth(0) , m_codeType(GlobalCode) , m_nextGlobalIndex(-1) + , m_nextConstantOffset(0) + , m_globalConstantIndex(0) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) , m_emitNodeDepth(0) @@ -260,35 +256,35 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d m_nextGlobalIndex -= symbolTable->size(); for (size_t i = 0; i < functionStack.size(); ++i) { - FuncDeclNode* funcDecl = functionStack[i].get(); - globalObject->removeDirect(funcDecl->m_ident); // Make sure our new function is not shadowed by an old property. - emitNewFunction(addGlobalVar(funcDecl->m_ident, false), funcDecl); + FunctionBodyNode* function = functionStack[i]; + globalObject->removeDirect(function->ident()); // Make sure our new function is not shadowed by an old property. + emitNewFunction(addGlobalVar(function->ident(), false), function); } Vector newVars; for (size_t i = 0; i < varStack.size(); ++i) - if (!globalObject->hasProperty(exec, varStack[i].first)) - newVars.append(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant)); + if (!globalObject->hasProperty(exec, *varStack[i].first)) + newVars.append(addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant)); - allocateConstants(programNode->neededConstants()); + preserveLastVar(); for (size_t i = 0; i < newVars.size(); ++i) emitLoad(newVars[i], jsUndefined()); } else { for (size_t i = 0; i < functionStack.size(); ++i) { - FuncDeclNode* funcDecl = functionStack[i].get(); - globalObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec, scopeChain.node()), DontDelete); + FunctionBodyNode* function = functionStack[i]; + globalObject->putWithAttributes(exec, function->ident(), new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain.node()), DontDelete); } for (size_t i = 0; i < varStack.size(); ++i) { - if (globalObject->hasProperty(exec, varStack[i].first)) + if (globalObject->hasProperty(exec, *varStack[i].first)) continue; int attributes = DontDelete; if (varStack[i].second & DeclarationStacks::IsConstant) attributes |= ReadOnly; - globalObject->putWithAttributes(exec, varStack[i].first, jsUndefined(), attributes); + globalObject->putWithAttributes(exec, *varStack[i].first, jsUndefined(), attributes); } - allocateConstants(programNode->neededConstants()); + preserveLastVar(); } } @@ -303,6 +299,8 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug , m_dynamicScopeDepth(0) , m_baseScopeDepth(0) , m_codeType(FunctionCode) + , m_nextConstantOffset(0) + , m_globalConstantIndex(0) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) , m_emitNodeDepth(0) @@ -329,23 +327,30 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug } else emitOpcode(op_enter); - if (usesArguments) - emitOpcode(op_create_arguments); + if (usesArguments) { + emitOpcode(op_init_arguments); + + // The debugger currently retrieves the arguments object from an activation rather than pulling + // it from a call frame. In the long-term it should stop doing that (), + // but for now we force eager creation of the arguments object when debugging. + if (m_shouldEmitDebugHooks) + emitOpcode(op_create_arguments); + } const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack(); for (size_t i = 0; i < functionStack.size(); ++i) { - FuncDeclNode* funcDecl = functionStack[i].get(); - const Identifier& ident = funcDecl->m_ident; + FunctionBodyNode* function = functionStack[i]; + const Identifier& ident = function->ident(); m_functions.add(ident.ustring().rep()); - emitNewFunction(addVar(ident, false), funcDecl); + emitNewFunction(addVar(ident, false), function); } const DeclarationStacks::VarStack& varStack = functionBody->varStack(); for (size_t i = 0; i < varStack.size(); ++i) - addVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant); + addVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant); - const Identifier* parameters = functionBody->parameters(); - size_t parameterCount = functionBody->parameterCount(); + FunctionParameters& parameters = *functionBody->parameters(); + size_t parameterCount = parameters.size(); m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1; m_parameters.grow(1 + parameterCount); // reserve space for "this" @@ -362,7 +367,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug for (size_t i = 0; i < parameterCount; ++i) addParameter(parameters[i]); - allocateConstants(functionBody->neededConstants()); + preserveLastVar(); } BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock) @@ -377,6 +382,8 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge , m_dynamicScopeDepth(0) , m_baseScopeDepth(codeBlock->baseScopeDepth()) , m_codeType(EvalCode) + , m_nextConstantOffset(0) + , m_globalConstantIndex(0) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) , m_emitNodeDepth(0) @@ -390,7 +397,19 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge codeBlock->setGlobalData(m_globalData); m_codeBlock->m_numParameters = 1; // Allocate space for "this" - allocateConstants(evalNode->neededConstants()); + const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack(); + for (size_t i = 0; i < functionStack.size(); ++i) + m_codeBlock->addFunctionDecl(makeFunction(m_globalData, functionStack[i])); + + const DeclarationStacks::VarStack& varStack = evalNode->varStack(); + unsigned numVariables = varStack.size(); + Vector variables; + variables.reserveCapacity(numVariables); + for (size_t i = 0; i < numVariables; ++i) + variables.append(*varStack[i].first); + codeBlock->adoptVariables(variables); + + preserveLastVar(); } RegisterID* BytecodeGenerator::addParameter(const Identifier& ident) @@ -424,6 +443,36 @@ RegisterID* BytecodeGenerator::registerFor(const Identifier& ident) if (entry.isNull()) return 0; + if (ident == propertyNames().arguments) + createArgumentsIfNecessary(); + + return ®isterFor(entry.getIndex()); +} + +bool BytecodeGenerator::willResolveToArguments(const Identifier& ident) +{ + if (ident != propertyNames().arguments) + return false; + + if (!shouldOptimizeLocals()) + return false; + + SymbolTableEntry entry = symbolTable().get(ident.ustring().rep()); + if (entry.isNull()) + return false; + + if (m_codeBlock->usesArguments() && m_codeType == FunctionCode) + return true; + + return false; +} + +RegisterID* BytecodeGenerator::uncheckedRegisterForArguments() +{ + ASSERT(willResolveToArguments(propertyNames().arguments)); + + SymbolTableEntry entry = symbolTable().get(propertyNames().arguments.ustring().rep()); + ASSERT(!entry.isNull()); return ®isterFor(entry.getIndex()); } @@ -433,7 +482,8 @@ RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident) return 0; SymbolTableEntry entry = symbolTable().get(ident.ustring().rep()); - ASSERT(!entry.isNull()); + if (entry.isNull()) + return 0; return ®isterFor(entry.getIndex()); } @@ -484,7 +534,7 @@ PassRefPtr BytecodeGenerator::newLabelScope(LabelScope::Type type, c m_labelScopes.removeLast(); // Allocate new label scope. - LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : 0); // Only loops have continue targets. + LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr