X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/93a3786624b2768d89bfa27e46598dc64e2fb70a..ef99ff287df9046eb88937225e0554eabb00e33c:/bytecompiler/BytecodeGenerator.cpp diff --git a/bytecompiler/BytecodeGenerator.cpp b/bytecompiler/BytecodeGenerator.cpp index e719380..734546a 100644 --- a/bytecompiler/BytecodeGenerator.cpp +++ b/bytecompiler/BytecodeGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2012, 2013, 2014 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich * Copyright (C) 2012 Igalia, S.L. * @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -31,16 +31,18 @@ #include "config.h" #include "BytecodeGenerator.h" -#include "BatchedTransitionOptimizer.h" #include "Interpreter.h" #include "JSActivation.h" #include "JSFunction.h" #include "JSNameScope.h" #include "LowLevelInterpreter.h" -#include "Operations.h" +#include "JSCInlines.h" #include "Options.h" +#include "StackAlignment.h" #include "StrongInlines.h" #include "UnlinkedCodeBlock.h" +#include "UnlinkedInstructionStream.h" +#include #include using namespace std; @@ -56,32 +58,15 @@ void Label::setLocation(unsigned location) m_generator->m_instructions[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first; } -#ifndef NDEBUG -void ResolveResult::checkValidity() -{ - switch (m_type) { - case Register: - case ReadOnlyRegister: - ASSERT(m_local); - return; - case Dynamic: - ASSERT(!m_local); - return; - case Lexical: - case ReadOnlyLexical: - ASSERT(!m_local); - return; - default: - RELEASE_ASSERT_NOT_REACHED(); - } -} -#endif - ParserError BytecodeGenerator::generate() { SamplingRegion samplingRegion("Bytecode Generation"); - m_codeBlock->setThisRegister(m_thisRegister.index()); + m_codeBlock->setThisRegister(m_thisRegister.virtualRegister()); + for (size_t i = 0; i < m_deconstructedParameters.size(); i++) { + auto& entry = m_deconstructedParameters[i]; + entry.second->bindValue(*this, entry.first.get()); + } m_scopeNode->emitBytecode(*this); @@ -126,27 +111,43 @@ ParserError BytecodeGenerator::generate() m_codeBlock->addExceptionHandler(info); } - m_codeBlock->instructions() = RefCountedArray(m_instructions); + m_codeBlock->setInstructions(std::make_unique(m_instructions)); m_codeBlock->shrinkToFit(); + if (m_codeBlock->symbolTable()) + m_codeBlock->setSymbolTable(m_codeBlock->symbolTable()->cloneCapturedNames(*m_codeBlock->vm())); + if (m_expressionTooDeep) return ParserError(ParserError::OutOfMemory); return ParserError(ParserError::ErrorNone); } -bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0) +bool BytecodeGenerator::addVar( + const Identifier& ident, ConstantMode constantMode, WatchMode watchMode, RegisterID*& r0) { - int index = m_calleeRegisters.size(); - SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); - SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry); + ASSERT(static_cast(m_codeBlock->m_numVars) == m_calleeRegisters.size()); + + ConcurrentJITLocker locker(symbolTable().m_lock); + int index = virtualRegisterForLocal(m_calleeRegisters.size()).offset(); + SymbolTableEntry newEntry(index, constantMode == IsConstant ? ReadOnly : 0); + SymbolTable::Map::AddResult result = symbolTable().add(locker, ident.impl(), newEntry); if (!result.isNewEntry) { r0 = ®isterFor(result.iterator->value.getIndex()); return false; } - + + if (watchMode == IsWatchable) { + while (m_watchableVariables.size() < static_cast(m_codeBlock->m_numVars)) + m_watchableVariables.append(Identifier()); + m_watchableVariables.append(ident); + } + r0 = addVar(); + + ASSERT(watchMode == NotWatchable || static_cast(m_codeBlock->m_numVars) == m_watchableVariables.size()); + return true; } @@ -156,21 +157,21 @@ void BytecodeGenerator::preserveLastVar() m_lastVar = &m_calleeRegisters.last(); } -BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope*, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode) - : m_shouldEmitDebugHooks(debuggerMode == DebuggerOn) - , m_shouldEmitProfileHooks(profilerMode == ProfilerOn) +BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode) + : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn) + , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn) , m_symbolTable(0) , m_scopeNode(programNode) , m_codeBlock(vm, codeBlock) , m_thisRegister(CallFrame::thisArgumentOffset()) + , m_activationRegister(0) , m_emptyValueRegister(0) , m_globalObjectRegister(0) , m_finallyDepth(0) - , m_dynamicScopeDepth(0) + , m_localScopeDepth(0) , m_codeType(GlobalCode) , m_nextConstantOffset(0) , m_globalConstantIndex(0) - , m_hasCreatedActivation(true) , m_firstLazyFunction(0) , m_lastLazyFunction(0) , m_staticPropertyAnalyzer(&m_instructions) @@ -179,13 +180,10 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope*, ProgramNode* programNode, #ifndef NDEBUG , m_lastOpcodePosition(0) #endif - , m_stack(wtfThreadData().stack()) , m_usesExceptions(false) , m_expressionTooDeep(false) + , m_isBuiltinFunction(false) { - if (m_shouldEmitDebugHooks) - m_codeBlock->setNeedsFullScopeChain(true); - m_codeBlock->setNumParameters(1); // Allocate space for "this" emitOpcode(op_enter); @@ -200,26 +198,24 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope*, ProgramNode* programNode, } for (size_t i = 0; i < varStack.size(); ++i) - codeBlock->addVariableDeclaration(*varStack[i].first, !!(varStack[i].second & DeclarationStacks::IsConstant)); + codeBlock->addVariableDeclaration(varStack[i].first, !!(varStack[i].second & DeclarationStacks::IsConstant)); } -BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope* scope, FunctionBodyNode* functionBody, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode) - : m_shouldEmitDebugHooks(debuggerMode == DebuggerOn) - , m_shouldEmitProfileHooks(profilerMode == ProfilerOn) +BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode) + : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn) + , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn) , m_symbolTable(codeBlock->symbolTable()) , m_scopeNode(functionBody) - , m_scope(vm, scope) , m_codeBlock(vm, codeBlock) , m_activationRegister(0) , m_emptyValueRegister(0) , m_globalObjectRegister(0) , m_finallyDepth(0) - , m_dynamicScopeDepth(0) + , m_localScopeDepth(0) , m_codeType(FunctionCode) , m_nextConstantOffset(0) , m_globalConstantIndex(0) - , m_hasCreatedActivation(false) , m_firstLazyFunction(0) , m_lastLazyFunction(0) , m_staticPropertyAnalyzer(&m_instructions) @@ -228,47 +224,48 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope* scope, FunctionBodyNode* f #ifndef NDEBUG , m_lastOpcodePosition(0) #endif - , m_stack(wtfThreadData().stack()) , m_usesExceptions(false) , m_expressionTooDeep(false) + , m_isBuiltinFunction(codeBlock->isBuiltinFunction()) { - if (m_shouldEmitDebugHooks) - m_codeBlock->setNeedsFullScopeChain(true); + if (m_isBuiltinFunction) + m_shouldEmitDebugHooks = false; m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode()); + Vector boundParameterProperties; + FunctionParameters& parameters = *functionBody->parameters(); + for (size_t i = 0; i < parameters.size(); i++) { + auto pattern = parameters.at(i); + if (pattern->isBindingNode()) + continue; + pattern->collectBoundIdentifiers(boundParameterProperties); + continue; + } m_symbolTable->setParameterCountIncludingThis(functionBody->parameters()->size() + 1); emitOpcode(op_enter); - if (m_codeBlock->needsFullScopeChain()) { + if (m_codeBlock->needsFullScopeChain() || m_shouldEmitDebugHooks) { m_activationRegister = addVar(); emitInitLazyRegister(m_activationRegister); - m_codeBlock->setActivationRegister(m_activationRegister->index()); + m_codeBlock->setActivationRegister(m_activationRegister->virtualRegister()); } - m_symbolTable->setCaptureStart(m_codeBlock->m_numVars); + m_symbolTable->setCaptureStart(virtualRegisterForLocal(m_codeBlock->m_numVars).offset()); - if (functionBody->usesArguments() || codeBlock->usesEval() || m_shouldEmitDebugHooks) { // May reify arguments object. + if (functionBody->usesArguments() || codeBlock->usesEval()) { // May reify arguments object. RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code. - RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'. + RegisterID* argumentsRegister = addVar(propertyNames().arguments, IsVariable, NotWatchable); // Can be changed by assigning to 'arguments'. // We can save a little space by hard-coding the knowledge that the two // 'arguments' values are stored in consecutive registers, and storing // only the index of the assignable one. - codeBlock->setArgumentsRegister(argumentsRegister->index()); - ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister())); + codeBlock->setArgumentsRegister(argumentsRegister->virtualRegister()); + ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->virtualRegister() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister())); emitInitLazyRegister(argumentsRegister); emitInitLazyRegister(unmodifiedArgumentsRegister); - if (m_codeBlock->isStrictMode()) { - emitOpcode(op_create_arguments); - instructions().append(argumentsRegister->index()); - } - - // 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) { + if (shouldTearOffArgumentsEagerly()) { emitOpcode(op_create_arguments); instructions().append(argumentsRegister->index()); } @@ -283,16 +280,20 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope* scope, FunctionBodyNode* f capturedArguments.resize(parameters.size()); for (size_t i = 0; i < parameters.size(); ++i) { capturedArguments[i] = 0; - if (!functionBody->captures(parameters.at(i)) && !shouldCaptureAllTheThings) + auto pattern = parameters.at(i); + if (!pattern->isBindingNode()) + continue; + const Identifier& ident = static_cast(pattern)->boundProperty(); + if (!functionBody->captures(ident) && !shouldCaptureAllTheThings) continue; capturesAnyArgumentByName = true; capturedArguments[i] = addVar(); } } - if (capturesAnyArgumentByName && !codeBlock->isStrictMode()) { + if (capturesAnyArgumentByName && !shouldTearOffArgumentsEagerly()) { size_t parameterCount = m_symbolTable->parameterCount(); - OwnArrayPtr slowArguments = adoptArrayPtr(new SlowArgument[parameterCount]); + auto slowArguments = std::make_unique(parameterCount); for (size_t i = 0; i < parameterCount; ++i) { if (!capturedArguments[i]) { ASSERT(slowArguments[i].status == SlowArgument::Normal); @@ -302,90 +303,100 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope* scope, FunctionBodyNode* f slowArguments[i].status = SlowArgument::Captured; slowArguments[i].index = capturedArguments[i]->index(); } - m_symbolTable->setSlowArguments(slowArguments.release()); + m_symbolTable->setSlowArguments(WTF::move(slowArguments)); } 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(); + IdentifierSet test; // Captured variables and functions go first so that activations don't have // to step over the non-captured locals to mark them. - m_hasCreatedActivation = false; if (functionBody->hasCapturedVariables()) { + for (size_t i = 0; i < boundParameterProperties.size(); i++) { + const Identifier& ident = boundParameterProperties[i]; + if (functionBody->captures(ident)) + addVar(ident, IsVariable, IsWatchable); + } for (size_t i = 0; i < functionStack.size(); ++i) { FunctionBodyNode* function = functionStack[i]; const Identifier& ident = function->ident(); if (functionBody->captures(ident)) { - if (!m_hasCreatedActivation) { - m_hasCreatedActivation = true; - emitOpcode(op_create_activation); - instructions().append(m_activationRegister->index()); - } m_functions.add(ident.impl()); - emitNewFunction(addVar(ident, false), function); + emitNewFunction(addVar(ident, IsVariable, IsWatchable), IsCaptured, function); } } for (size_t i = 0; i < varStack.size(); ++i) { - const Identifier& ident = *varStack[i].first; + const Identifier& ident = varStack[i].first; if (functionBody->captures(ident)) - addVar(ident, varStack[i].second & DeclarationStacks::IsConstant); + addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, IsWatchable); } } - bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks; - if (!canLazilyCreateFunctions && !m_hasCreatedActivation) { - m_hasCreatedActivation = true; - emitOpcode(op_create_activation); - instructions().append(m_activationRegister->index()); - } - m_symbolTable->setCaptureEnd(codeBlock->m_numVars); + m_symbolTable->setCaptureEnd(virtualRegisterForLocal(codeBlock->m_numVars).offset()); + bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks; m_firstLazyFunction = codeBlock->m_numVars; for (size_t i = 0; i < functionStack.size(); ++i) { FunctionBodyNode* function = functionStack[i]; const Identifier& ident = function->ident(); if (!functionBody->captures(ident)) { m_functions.add(ident.impl()); - RefPtr reg = addVar(ident, false); + RefPtr reg = addVar(ident, IsVariable, NotWatchable); // Don't lazily create functions that override the name 'arguments' // as this would complicate lazy instantiation of actual arguments. if (!canLazilyCreateFunctions || ident == propertyNames().arguments) - emitNewFunction(reg.get(), function); + emitNewFunction(reg.get(), NotCaptured, function); else { emitInitLazyRegister(reg.get()); - m_lazyFunctions.set(reg->index(), function); + m_lazyFunctions.set(reg->virtualRegister().toLocal(), function); } } } m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction; + for (size_t i = 0; i < boundParameterProperties.size(); i++) { + const Identifier& ident = boundParameterProperties[i]; + if (!functionBody->captures(ident)) + addVar(ident, IsVariable, IsWatchable); + } for (size_t i = 0; i < varStack.size(); ++i) { - const Identifier& ident = *varStack[i].first; + const Identifier& ident = varStack[i].first; if (!functionBody->captures(ident)) - addVar(ident, varStack[i].second & DeclarationStacks::IsConstant); + addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, NotWatchable); } if (shouldCaptureAllTheThings) - m_symbolTable->setCaptureEnd(codeBlock->m_numVars); + m_symbolTable->setCaptureEnd(virtualRegisterForLocal(codeBlock->m_numVars).offset()); - FunctionParameters& parameters = *functionBody->parameters(); + if (m_symbolTable->captureCount()) + emitOpcode(op_touch_entry); + m_parameters.grow(parameters.size() + 1); // reserve space for "this" // Add "this" as a parameter int nextParameterIndex = CallFrame::thisArgumentOffset(); - m_thisRegister.setIndex(nextParameterIndex--); + m_thisRegister.setIndex(nextParameterIndex++); m_codeBlock->addParameter(); - - for (size_t i = 0; i < parameters.size(); ++i, --nextParameterIndex) { + for (size_t i = 0; i < parameters.size(); ++i, ++nextParameterIndex) { int index = nextParameterIndex; + auto pattern = parameters.at(i); + if (!pattern->isBindingNode()) { + m_codeBlock->addParameter(); + RegisterID& parameter = registerFor(index); + parameter.setIndex(index); + m_deconstructedParameters.append(std::make_pair(¶meter, pattern)); + continue; + } + auto simpleParameter = static_cast(pattern); if (capturedArguments.size() && capturedArguments[i]) { - ASSERT((functionBody->hasCapturedVariables() && functionBody->captures(parameters.at(i))) || shouldCaptureAllTheThings); + ASSERT((functionBody->hasCapturedVariables() && functionBody->captures(simpleParameter->boundProperty())) || shouldCaptureAllTheThings); index = capturedArguments[i]->index(); RegisterID original(nextParameterIndex); emitMove(capturedArguments[i], &original); } - addParameter(parameters.at(i), index); + addParameter(simpleParameter->boundProperty(), index); } preserveLastVar(); @@ -394,29 +405,29 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope* scope, FunctionBodyNode* f if (isConstructor()) { emitCreateThis(&m_thisRegister); - } else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) { - UnlinkedValueProfile profile = emitProfiledOpcode(op_convert_this); + } else if (functionBody->usesThis() || codeBlock->usesEval()) { + m_codeBlock->addPropertyAccessInstruction(instructions().size()); + emitOpcode(op_to_this); instructions().append(kill(&m_thisRegister)); - instructions().append(profile); + instructions().append(0); } } -BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope* scope, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode) - : m_shouldEmitDebugHooks(debuggerMode == DebuggerOn) - , m_shouldEmitProfileHooks(profilerMode == ProfilerOn) +BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode) + : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn) + , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn) , m_symbolTable(codeBlock->symbolTable()) , m_scopeNode(evalNode) - , m_scope(vm, scope) , m_codeBlock(vm, codeBlock) , m_thisRegister(CallFrame::thisArgumentOffset()) + , m_activationRegister(0) , m_emptyValueRegister(0) , m_globalObjectRegister(0) , m_finallyDepth(0) - , m_dynamicScopeDepth(0) + , m_localScopeDepth(0) , m_codeType(EvalCode) , m_nextConstantOffset(0) , m_globalConstantIndex(0) - , m_hasCreatedActivation(true) , m_firstLazyFunction(0) , m_lastLazyFunction(0) , m_staticPropertyAnalyzer(&m_instructions) @@ -425,12 +436,10 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope* scope, EvalNode* evalNode, #ifndef NDEBUG , m_lastOpcodePosition(0) #endif - , m_stack(wtfThreadData().stack()) , m_usesExceptions(false) , m_expressionTooDeep(false) + , m_isBuiltinFunction(false) { - m_codeBlock->setNeedsFullScopeChain(true); - m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode()); m_codeBlock->setNumParameters(1); @@ -444,8 +453,10 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope* scope, EvalNode* evalNode, unsigned numVariables = varStack.size(); Vector variables; variables.reserveCapacity(numVariables); - for (size_t i = 0; i < numVariables; ++i) - variables.append(*varStack[i].first); + for (size_t i = 0; i < numVariables; ++i) { + ASSERT(varStack[i].first.impl()->isAtomic()); + variables.append(varStack[i].first); + } codeBlock->adoptVariables(variables); preserveLastVar(); } @@ -458,42 +469,30 @@ RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg) { emitOpcode(op_init_lazy_reg); instructions().append(reg->index()); + ASSERT(!hasWatchableVariable(reg->index())); return reg; } RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode) { - if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope()) + if (!functionNameIsInScope(functionBodyNode->ident(), functionBodyNode->functionMode())) return 0; - m_calleeRegister.setIndex(JSStack::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); + if (functionNameScopeIsDynamic(m_codeBlock->usesEval(), m_codeBlock->isStrictMode())) return 0; - } - if (!functionBodyNode->captures(functionBodyNode->ident())) - return &m_calleeRegister; + m_calleeRegister.setIndex(JSStack::Callee); + if (functionBodyNode->captures(functionBodyNode->ident())) + return emitMove(addVar(), IsCaptured, &m_calleeRegister); - // Move the callee into the captured section of the stack. - return emitMove(addVar(), &m_calleeRegister); + return &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) + if (!calleeRegister) return; - ASSERT(calleeRegister); symbolTable().add(functionBodyNode->ident().impl(), SymbolTableEntry(calleeRegister->index(), ReadOnly)); } @@ -541,16 +540,23 @@ RegisterID* BytecodeGenerator::uncheckedRegisterForArguments() RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg) { - if (m_lastLazyFunction <= reg->index() || reg->index() < m_firstLazyFunction) + if (!reg->virtualRegister().isLocal()) + return reg; + + int localVariableNumber = reg->virtualRegister().toLocal(); + + if (m_lastLazyFunction <= localVariableNumber || localVariableNumber < m_firstLazyFunction) return reg; - emitLazyNewFunction(reg, m_lazyFunctions.get(reg->index())); + emitLazyNewFunction(reg, m_lazyFunctions.get(localVariableNumber)); return reg; } RegisterID* BytecodeGenerator::newRegister() { - m_calleeRegisters.append(m_calleeRegisters.size()); - m_codeBlock->m_numCalleeRegisters = max(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size()); + m_calleeRegisters.append(virtualRegisterForLocal(m_calleeRegisters.size())); + int numCalleeRegisters = max(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size()); + numCalleeRegisters = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numCalleeRegisters); + m_codeBlock->m_numCalleeRegisters = numCalleeRegisters; return &m_calleeRegisters.last(); } @@ -574,7 +580,7 @@ LabelScopePtr BytecodeGenerator::newLabelScope(LabelScope::Type type, const Iden // Allocate new label scope. LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr