X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..6fe7ccc865dc7d7541b93c5bcaf6368d2c98a174:/bytecompiler/BytecodeGenerator.cpp?ds=inline diff --git a/bytecompiler/BytecodeGenerator.cpp b/bytecompiler/BytecodeGenerator.cpp index c09a837..f43b4e6 100644 --- a/bytecompiler/BytecodeGenerator.cpp +++ b/bytecompiler/BytecodeGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich * * Redistribution and use in source and binary forms, with or without @@ -33,7 +33,9 @@ #include "BatchedTransitionOptimizer.h" #include "JSFunction.h" #include "Interpreter.h" +#include "LowLevelInterpreter.h" #include "ScopeChain.h" +#include "StrongInlines.h" #include "UString.h" using namespace std; @@ -115,40 +117,39 @@ namespace JSC { expected by the callee. */ -#ifndef NDEBUG static bool s_dumpsGeneratedCode = false; -#endif + +void Label::setLocation(unsigned location) +{ + m_location = location; + + unsigned size = m_unresolvedJumps.size(); + for (unsigned i = 0; i < size; ++i) + m_generator->m_instructions[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first; +} void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode) { -#ifndef NDEBUG s_dumpsGeneratedCode = dumpsGeneratedCode; -#else - UNUSED_PARAM(dumpsGeneratedCode); -#endif } bool BytecodeGenerator::dumpsGeneratedCode() { -#ifndef NDEBUG return s_dumpsGeneratedCode; -#else - return false; -#endif } JSObject* BytecodeGenerator::generate() { + SamplingRegion samplingRegion("Bytecode Generation"); + m_codeBlock->setThisRegister(m_thisRegister.index()); m_scopeNode->emitBytecode(*this); - -#ifndef NDEBUG - m_codeBlock->setInstructionCount(m_codeBlock->instructions().size()); + + m_codeBlock->instructions() = RefCountedArray(m_instructions); if (s_dumpsGeneratedCode) m_codeBlock->dump(m_scopeChain->globalObject->globalExec()); -#endif if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode) symbolTable().clear(); @@ -164,10 +165,10 @@ bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, Registe { int index = m_calleeRegisters.size(); SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); - pair result = symbolTable().add(ident.impl(), newEntry); + SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry); - if (!result.second) { - r0 = ®isterFor(result.first->second.getIndex()); + if (!result.isNewEntry) { + r0 = ®isterFor(result.iterator->second.getIndex()); return false; } @@ -175,21 +176,14 @@ bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, Registe return true; } -bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0) +int BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant) { - int index = m_nextGlobalIndex; + int index = symbolTable().size(); SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); - pair result = symbolTable().add(ident.impl(), newEntry); - - if (!result.second) - index = result.first->second.getIndex(); - else { - --m_nextGlobalIndex; - m_globals.append(index + m_globalVarStorageOffset); - } - - r0 = ®isterFor(index); - return result.second; + SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry); + if (!result.isNewEntry) + index = result.iterator->second.getIndex(); + return index; } void BytecodeGenerator::preserveLastVar() @@ -198,20 +192,19 @@ void BytecodeGenerator::preserveLastVar() m_lastVar = &m_calleeRegisters.last(); } -BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock) +BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock, CompilationKind compilationKind) : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger()) - , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling()) - , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo()) + , m_shouldEmitProfileHooks(scopeChain->globalObject->globalObjectMethodTable()->supportsProfiling(scopeChain->globalObject.get())) + , m_shouldEmitRichSourceInfo(scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get())) , m_scopeChain(*scopeChain->globalData, scopeChain) , m_symbolTable(symbolTable) , m_scopeNode(programNode) , m_codeBlock(codeBlock) - , m_thisRegister(RegisterFile::ProgramCodeThisRegister) + , m_thisRegister(CallFrame::thisArgumentOffset()) , m_finallyDepth(0) , m_dynamicScopeDepth(0) , m_baseScopeDepth(0) , m_codeType(GlobalCode) - , m_nextGlobalIndex(-1) , m_nextConstantOffset(0) , m_globalConstantIndex(0) , m_hasCreatedActivation(true) @@ -222,10 +215,11 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s #ifndef NDEBUG , m_lastOpcodePosition(0) #endif - , m_stack(m_globalData->stack()) + , m_stack(wtfThreadData().stack()) , m_usesExceptions(false) , m_expressionTooDeep(false) { + m_globalData->startedCompiling(m_codeBlock); if (m_shouldEmitDebugHooks) m_codeBlock->setNeedsFullScopeChain(true); @@ -234,96 +228,45 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s // FIXME: Move code that modifies the global object to Interpreter::execute. - m_codeBlock->m_numParameters = 1; // Allocate space for "this" + m_codeBlock->setNumParameters(1); // Allocate space for "this" + codeBlock->m_numCapturedVars = codeBlock->m_numVars; + + if (compilationKind == OptimizingCompilation) + return; JSGlobalObject* globalObject = scopeChain->globalObject.get(); ExecState* exec = globalObject->globalExec(); - RegisterFile* registerFile = &exec->globalData().interpreter->registerFile(); - // Shift register indexes in generated code to elide registers allocated by intermediate stack frames. - m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters - registerFile->size(); - - // Add previously defined symbols to bookkeeping. - m_globals.grow(symbolTable->size()); - SymbolTable::iterator end = symbolTable->end(); - for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it) - registerFor(it->second.getIndex()).setIndex(it->second.getIndex() + m_globalVarStorageOffset); - BatchedTransitionOptimizer optimizer(*m_globalData, globalObject); const VarStack& varStack = programNode->varStack(); const FunctionStack& functionStack = programNode->functionStack(); - bool canOptimizeNewGlobals = symbolTable->size() + functionStack.size() + varStack.size() < registerFile->maxGlobals(); - if (canOptimizeNewGlobals) { - // Shift new symbols so they get stored prior to existing symbols. - m_nextGlobalIndex -= symbolTable->size(); - - HashSet newGlobals; - Vector, 16> functionInfo(functionStack.size()); - for (size_t i = 0; i < functionStack.size(); ++i) { - FunctionBodyNode* function = functionStack[i]; - globalObject->removeDirect(*m_globalData, function->ident()); // Make sure our new function is not shadowed by an old property. - SymbolTableEntry entry = symbolTable->inlineGet(function->ident().impl()); - - if (entry.isNull()) - newGlobals.add(function->ident().impl()); - functionInfo[i] = make_pair(entry.getIndex(), entry.isReadOnly()); - } - - Vector shouldCreateVar(varStack.size()); - for (size_t i = 0; i < varStack.size(); ++i) { - if (newGlobals.contains(varStack[i].first->impl()) || globalObject->hasProperty(exec, *varStack[i].first)) { - shouldCreateVar[i] = false; - continue; - } - shouldCreateVar[i] = true; - newGlobals.add(varStack[i].first->impl()); - } - int expectedSize = symbolTable->size() + newGlobals.size(); - globalObject->resizeRegisters(symbolTable->size(), expectedSize); - - for (size_t i = 0; i < functionStack.size(); ++i) { - FunctionBodyNode* function = functionStack[i]; - if (functionInfo[i].second) - continue; - RegisterID* dst = addGlobalVar(function->ident(), false); - JSValue value = new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain); - globalObject->registerAt(dst->index() - m_globalVarStorageOffset).set(*m_globalData, globalObject, value); - } + size_t newGlobals = varStack.size() + functionStack.size(); + if (!newGlobals) + return; + globalObject->resizeRegisters(symbolTable->size() + newGlobals); - for (size_t i = 0; i < varStack.size(); ++i) { - if (!shouldCreateVar[i]) - continue; - addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant); - } - if (symbolTable->size() != expectedSize) - CRASH(); + for (size_t i = 0; i < functionStack.size(); ++i) { + FunctionBodyNode* function = functionStack[i]; + globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties. - preserveLastVar(); - } else { - for (size_t i = 0; i < functionStack.size(); ++i) { - FunctionBodyNode* function = functionStack[i]; - globalObject->putWithAttributes(exec, function->ident(), new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain), DontDelete); - } - for (size_t i = 0; i < varStack.size(); ++i) { - if (globalObject->symbolTableHasProperty(*varStack[i].first) || 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); - } + JSValue value = JSFunction::create(exec, makeFunction(exec, function), scopeChain); + int index = addGlobalVar(function->ident(), false); + globalObject->registerAt(index).set(*m_globalData, globalObject, value); + } - preserveLastVar(); + for (size_t i = 0; i < varStack.size(); ++i) { + if (globalObject->hasProperty(exec, *varStack[i].first)) + continue; + addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant); } - codeBlock->m_numCapturedVars = codeBlock->m_numVars; } -BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainNode* scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock) +BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainNode* scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock, CompilationKind) : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger()) - , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling()) - , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo()) + , m_shouldEmitProfileHooks(scopeChain->globalObject->globalObjectMethodTable()->supportsProfiling(scopeChain->globalObject.get())) + , m_shouldEmitRichSourceInfo(scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get())) , m_scopeChain(*scopeChain->globalData, scopeChain) , m_symbolTable(symbolTable) , m_scopeNode(functionBody) @@ -343,10 +286,11 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN #ifndef NDEBUG , m_lastOpcodePosition(0) #endif - , m_stack(m_globalData->stack()) + , m_stack(wtfThreadData().stack()) , m_usesExceptions(false) , m_expressionTooDeep(false) { + m_globalData->startedCompiling(m_codeBlock); if (m_shouldEmitDebugHooks) m_codeBlock->setNeedsFullScopeChain(true); @@ -445,21 +389,20 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN if (!functionBody->captures(ident)) addVar(ident, varStack[i].second & DeclarationStacks::IsConstant); } - + if (m_shouldEmitDebugHooks) codeBlock->m_numCapturedVars = codeBlock->m_numVars; FunctionParameters& parameters = *functionBody->parameters(); - size_t parameterCount = parameters.size(); - int nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1; - m_parameters.grow(1 + parameterCount); // reserve space for "this" + m_parameters.grow(parameters.size() + 1); // reserve space for "this" // Add "this" as a parameter - m_thisRegister.setIndex(nextParameterIndex); - ++m_codeBlock->m_numParameters; + int nextParameterIndex = CallFrame::thisArgumentOffset(); + m_thisRegister.setIndex(nextParameterIndex--); + m_codeBlock->addParameter(); - for (size_t i = 0; i < parameterCount; ++i) - addParameter(parameters[i], ++nextParameterIndex); + for (size_t i = 0; i < parameters.size(); ++i) + addParameter(parameters[i], nextParameterIndex--); preserveLastVar(); @@ -475,24 +418,21 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN emitOpcode(op_create_this); instructions().append(m_thisRegister.index()); instructions().append(funcProto->index()); - } else if (functionBody->usesThis() || m_shouldEmitDebugHooks) { - if (codeBlock->isStrictMode()) - emitOpcode(op_convert_this_strict); - else - emitOpcode(op_convert_this); + } else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) { + emitOpcode(op_convert_this); instructions().append(m_thisRegister.index()); } } -BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock) +BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock, CompilationKind) : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger()) - , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling()) - , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo()) + , m_shouldEmitProfileHooks(scopeChain->globalObject->globalObjectMethodTable()->supportsProfiling(scopeChain->globalObject.get())) + , m_shouldEmitRichSourceInfo(scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get())) , m_scopeChain(*scopeChain->globalData, scopeChain) , m_symbolTable(symbolTable) , m_scopeNode(evalNode) , m_codeBlock(codeBlock) - , m_thisRegister(RegisterFile::ProgramCodeThisRegister) + , m_thisRegister(CallFrame::thisArgumentOffset()) , m_finallyDepth(0) , m_dynamicScopeDepth(0) , m_baseScopeDepth(codeBlock->baseScopeDepth()) @@ -507,16 +447,17 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeCh #ifndef NDEBUG , m_lastOpcodePosition(0) #endif - , m_stack(m_globalData->stack()) + , m_stack(wtfThreadData().stack()) , m_usesExceptions(false) , m_expressionTooDeep(false) { + m_globalData->startedCompiling(m_codeBlock); if (m_shouldEmitDebugHooks || m_baseScopeDepth) m_codeBlock->setNeedsFullScopeChain(true); emitOpcode(op_enter); codeBlock->setGlobalData(m_globalData); - m_codeBlock->m_numParameters = 1; // Allocate space for "this" + m_codeBlock->setNumParameters(1); const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack(); for (size_t i = 0; i < functionStack.size(); ++i) @@ -533,6 +474,11 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeCh preserveLastVar(); } +BytecodeGenerator::~BytecodeGenerator() +{ + m_globalData->finishedCompiling(m_codeBlock); +} + RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg) { emitOpcode(op_init_lazy_reg); @@ -552,13 +498,16 @@ void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex // To maintain the calling convention, we have to allocate unique space for // each parameter, even if the parameter doesn't make it into the symbol table. - ++m_codeBlock->m_numParameters; + m_codeBlock->addParameter(); } RegisterID* BytecodeGenerator::registerFor(const Identifier& ident) { if (ident == propertyNames().thisIdentifier) return &m_thisRegister; + + if (m_codeType == GlobalCode) + return 0; if (!shouldOptimizeLocals()) return 0; @@ -573,6 +522,21 @@ RegisterID* BytecodeGenerator::registerFor(const Identifier& ident) return createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); } +RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident) +{ + if (m_codeType == EvalCode) + return 0; + + if (m_codeType == GlobalCode) + return 0; + + SymbolTableEntry entry = symbolTable().get(ident.impl()); + if (entry.isNull()) + return 0; + + return createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); +} + bool BytecodeGenerator::willResolveToArguments(const Identifier& ident) { if (ident != propertyNames().arguments) @@ -608,18 +572,6 @@ RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg) return reg; } -RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident) -{ - if (m_codeType == EvalCode) - return 0; - - SymbolTableEntry entry = symbolTable().get(ident.impl()); - if (entry.isNull()) - return 0; - - return createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); -} - bool BytecodeGenerator::isLocal(const Identifier& ident) { if (ident == propertyNames().thisIdentifier) @@ -678,7 +630,7 @@ PassRefPtr