diff options
Diffstat (limited to 'Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp')
-rw-r--r-- | Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp | 368 |
1 files changed, 165 insertions, 203 deletions
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp index 1dfb5ac6a..53defbfb3 100644 --- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved. + * Copyright (C) 2012-2013, 2015-2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,191 +28,52 @@ #include "UnlinkedCodeBlock.h" #include "BytecodeGenerator.h" +#include "BytecodeRewriter.h" #include "ClassInfo.h" #include "CodeCache.h" -#include "Executable.h" +#include "ExecutableInfo.h" +#include "FunctionOverrides.h" +#include "JSCInlines.h" #include "JSString.h" -#include "Operations.h" #include "Parser.h" +#include "PreciseJumpTargetsInlines.h" #include "SourceProvider.h" #include "Structure.h" #include "SymbolTable.h" +#include "UnlinkedEvalCodeBlock.h" +#include "UnlinkedFunctionCodeBlock.h" #include "UnlinkedInstructionStream.h" +#include "UnlinkedModuleProgramCodeBlock.h" +#include "UnlinkedProgramCodeBlock.h" #include <wtf/DataLog.h> namespace JSC { -const ClassInfo UnlinkedFunctionExecutable::s_info = { "UnlinkedFunctionExecutable", 0, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionExecutable) }; -const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) }; -const ClassInfo UnlinkedGlobalCodeBlock::s_info = { "UnlinkedGlobalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedGlobalCodeBlock) }; -const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedProgramCodeBlock) }; -const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) }; -const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) }; +const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) }; -static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(VM& vm, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) -{ - RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&vm, source, executable->parameters(), executable->name(), executable->isInStrictContext() ? JSParseStrict : JSParseNormal, JSParseFunctionCode, error); - - if (!body) { - ASSERT(error.m_type != ParserError::ErrorNone); - return 0; - } - - if (executable->forceUsesArguments()) - body->setUsesArguments(); - body->finishParsing(executable->parameters(), executable->name(), executable->functionNameIsInScopeToggle()); - executable->recordParse(body->features(), body->hasCapturedVariables()); - - UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(body->needsActivation(), body->usesEval(), body->isStrictMode(), kind == CodeForConstruct)); - OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(vm, body.get(), result, debuggerMode, profilerMode))); - error = generator->generate(); - body->destroyData(); - if (error.m_type != ParserError::ErrorNone) - return 0; - return result; -} - -unsigned UnlinkedCodeBlock::addOrFindConstant(JSValue v) -{ - unsigned numberOfConstants = numberOfConstantRegisters(); - for (unsigned i = 0; i < numberOfConstants; ++i) { - if (getConstant(FirstConstantRegisterIndex + i) == v) - return i; - } - return addConstant(v); -} - -UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, FunctionBodyNode* node, bool isFromGlobalCode) - : Base(*vm, structure) - , m_numCapturedVariables(node->capturedVariableCount()) - , m_forceUsesArguments(node->usesArguments()) - , m_isInStrictContext(node->isStrictMode()) - , m_hasCapturedVariables(node->hasCapturedVariables()) - , m_isFromGlobalCode(isFromGlobalCode) - , m_name(node->ident()) - , m_inferredName(node->inferredName()) - , m_parameters(node->parameters()) - , m_firstLineOffset(node->firstLine() - source.firstLine()) - , m_lineCount(node->lastLine() - node->firstLine()) - , m_unlinkedFunctionNameStart(node->functionNameStart() - source.startOffset()) - , m_unlinkedBodyStartColumn(node->startColumn()) - , m_unlinkedBodyEndColumn(m_lineCount ? node->endColumn() : node->endColumn() - node->startColumn()) - , m_startOffset(node->source().startOffset() - source.startOffset()) - , m_sourceLength(node->source().length()) - , m_features(node->features()) - , m_functionNameIsInScopeToggle(node->functionNameIsInScopeToggle()) -{ -} - -size_t UnlinkedFunctionExecutable::parameterCount() const -{ - return m_parameters->size(); -} - -void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - UnlinkedFunctionExecutable* thisObject = jsCast<UnlinkedFunctionExecutable*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - visitor.append(&thisObject->m_codeBlockForCall); - visitor.append(&thisObject->m_codeBlockForConstruct); - visitor.append(&thisObject->m_nameValue); - visitor.append(&thisObject->m_symbolTableForCall); - visitor.append(&thisObject->m_symbolTableForConstruct); -} - -FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& source, size_t lineOffset, size_t sourceOffset) -{ - unsigned firstLine = lineOffset + m_firstLineOffset; - unsigned startOffset = sourceOffset + m_startOffset; - bool startColumnIsOnFirstSourceLine = !m_firstLineOffset; - unsigned startColumn = m_unlinkedBodyStartColumn + (startColumnIsOnFirstSourceLine ? source.startColumn() : 1); - bool endColumnIsOnStartLine = !m_lineCount; - unsigned endColumn = m_unlinkedBodyEndColumn + (endColumnIsOnStartLine ? startColumn : 1); - SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn); - return FunctionExecutable::create(vm, code, this, firstLine, firstLine + m_lineCount, startColumn, endColumn); -} - -UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger*, const SourceCode& source, JSObject** exception) -{ - ParserError error; - VM& vm = exec->vm(); - CodeCache* codeCache = vm.codeCache(); - UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(vm, name, source, error); - - if (exec->lexicalGlobalObject()->hasDebugger()) - exec->lexicalGlobalObject()->debugger()->sourceParsed(exec, source.provider(), error.m_line, error.m_message); - - if (error.m_type != ParserError::ErrorNone) { - *exception = error.toErrorObject(exec->lexicalGlobalObject(), source); - return 0; - } - - return executable; -} - -UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(VM& vm, const SourceCode& source, CodeSpecializationKind specializationKind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) -{ - switch (specializationKind) { - case CodeForCall: - if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForCall.get()) - return codeBlock; - break; - case CodeForConstruct: - if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get()) - return codeBlock; - break; - } - - UnlinkedFunctionCodeBlock* result = generateFunctionCodeBlock(vm, this, source, specializationKind, debuggerMode, profilerMode, error); - - if (error.m_type != ParserError::ErrorNone) - return 0; - - switch (specializationKind) { - case CodeForCall: - m_codeBlockForCall.set(vm, this, result); - m_symbolTableForCall.set(vm, this, result->symbolTable()); - break; - case CodeForConstruct: - m_codeBlockForConstruct.set(vm, this, result); - m_symbolTableForConstruct.set(vm, this, result->symbolTable()); - break; - } - return result; -} - -String UnlinkedFunctionExecutable::paramString() const -{ - FunctionParameters& parameters = *m_parameters; - StringBuilder builder; - for (size_t pos = 0; pos < parameters.size(); ++pos) { - if (!builder.isEmpty()) - builder.appendLiteral(", "); - parameters.at(pos)->toString(builder); - } - return builder.toString(); -} - -UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info) +UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, DebuggerMode debuggerMode) : Base(*vm, structure) , m_numVars(0) - , m_numCalleeRegisters(0) + , m_numCalleeLocals(0) , m_numParameters(0) - , m_vm(vm) - , m_argumentsRegister(VirtualRegister()) , m_globalObjectRegister(VirtualRegister()) - , m_needsFullScopeChain(info.m_needsActivation) - , m_usesEval(info.m_usesEval) - , m_isNumericCompareFunction(false) - , m_isStrictMode(info.m_isStrictMode) - , m_isConstructor(info.m_isConstructor) + , m_usesEval(info.usesEval()) + , m_isStrictMode(info.isStrictMode()) + , m_isConstructor(info.isConstructor()) , m_hasCapturedVariables(false) - , m_firstLine(0) + , m_isBuiltinFunction(info.isBuiltinFunction()) + , m_superBinding(static_cast<unsigned>(info.superBinding())) + , m_scriptMode(static_cast<unsigned>(info.scriptMode())) + , m_isArrowFunctionContext(info.isArrowFunctionContext()) + , m_isClassContext(info.isClassContext()) + , m_wasCompiledWithDebuggingOpcodes(debuggerMode == DebuggerMode::DebuggerOn || Options::forceDebuggerBytecodeGeneration()) + , m_constructorKind(static_cast<unsigned>(info.constructorKind())) + , m_derivedContextType(static_cast<unsigned>(info.derivedContextType())) + , m_evalContextType(static_cast<unsigned>(info.evalContextType())) , m_lineCount(0) , m_endColumn(UINT_MAX) + , m_didOptimize(MixedTriState) + , m_parseMode(info.parseMode()) , m_features(0) , m_codeType(codeType) , m_arrayProfileCount(0) @@ -220,32 +81,38 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType code , m_objectAllocationProfileCount(0) , m_valueProfileCount(0) , m_llintCallLinkInfoCount(0) -#if ENABLE(BYTECODE_COMMENTS) - , m_bytecodeCommentIterator(0) -#endif { - + for (auto& constantRegisterIndex : m_linkTimeConstants) + constantRegisterIndex = 0; + ASSERT(m_constructorKind == static_cast<unsigned>(info.constructorKind())); } void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) { UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); Base::visitChildren(thisObject, visitor); - visitor.append(&thisObject->m_symbolTable); + auto locker = holdLock(*thisObject); for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr) - visitor.append(ptr); + visitor.append(*ptr); for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++ptr) - visitor.append(ptr); + visitor.append(*ptr); visitor.appendValues(thisObject->m_constantRegisters.data(), thisObject->m_constantRegisters.size()); + if (thisObject->m_unlinkedInstructions) + visitor.reportExtraMemoryVisited(thisObject->m_unlinkedInstructions->sizeInBytes()); if (thisObject->m_rareData) { for (size_t i = 0, end = thisObject->m_rareData->m_regexps.size(); i != end; i++) - visitor.append(&thisObject->m_rareData->m_regexps[i]); + visitor.append(thisObject->m_rareData->m_regexps[i]); } } +size_t UnlinkedCodeBlock::estimatedSize(JSCell* cell) +{ + UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell); + size_t extraSize = thisObject->m_unlinkedInstructions ? thisObject->m_unlinkedInstructions->sizeInBytes() : 0; + return Base::estimatedSize(cell) + extraSize; +} + int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset) { ASSERT(bytecodeOffset < instructions().count()); @@ -258,8 +125,8 @@ int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset) return line; } -inline void UnlinkedCodeBlock::getLineAndColumn(ExpressionRangeInfo& info, - unsigned& line, unsigned& column) +inline void UnlinkedCodeBlock::getLineAndColumn(const ExpressionRangeInfo& info, + unsigned& line, unsigned& column) const { switch (info.mode) { case ExpressionRangeInfo::FatLineMode: @@ -292,6 +159,7 @@ static void dumpLineColumnEntry(size_t index, const UnlinkedInstructionStream& i case DidReachBreakpoint: event = " DidReachBreakpoint"; break; case WillLeaveCallFrame: event = " WillLeaveCallFrame"; break; case WillExecuteStatement: event = " WillExecuteStatement"; break; + case WillExecuteExpression: event = " WillExecuteExpression"; break; } } dataLogF(" [%zu] pc %u @ line %u col %u : %s%s\n", index, instructionOffset, line, column, opcodeNames[opcode], event); @@ -315,7 +183,7 @@ void UnlinkedCodeBlock::dumpExpressionRangeInfo() #endif void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, - int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) + int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) const { ASSERT(bytecodeOffset < instructions().count()); @@ -328,7 +196,7 @@ void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset return; } - Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo; + const Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo; int low = 0; int high = expressionInfo.size(); @@ -343,7 +211,7 @@ void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset if (!low) low = 1; - ExpressionRangeInfo& info = expressionInfo[low - 1]; + const ExpressionRangeInfo& info = expressionInfo[low - 1]; startOffset = info.startOffset; endOffset = info.endOffset; divot = info.divotPoint; @@ -404,51 +272,145 @@ void UnlinkedCodeBlock::addExpressionInfo(unsigned instructionOffset, m_expressionInfo.append(info); } -void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) +bool UnlinkedCodeBlock::typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot) { - UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - for (size_t i = 0, end = thisObject->m_functionDeclarations.size(); i != end; i++) - visitor.append(&thisObject->m_functionDeclarations[i].second); + static const bool verbose = false; + if (!m_rareData) { + if (verbose) + dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset); + startDivot = UINT_MAX; + endDivot = UINT_MAX; + return false; + } + + auto iter = m_rareData->m_typeProfilerInfoMap.find(bytecodeOffset); + if (iter == m_rareData->m_typeProfilerInfoMap.end()) { + if (verbose) + dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset); + startDivot = UINT_MAX; + endDivot = UINT_MAX; + return false; + } + + RareData::TypeProfilerExpressionRange& range = iter->value; + startDivot = range.m_startDivot; + endDivot = range.m_endDivot; + return true; } -UnlinkedCodeBlock::~UnlinkedCodeBlock() +void UnlinkedCodeBlock::addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot) { + createRareDataIfNecessary(); + RareData::TypeProfilerExpressionRange range; + range.m_startDivot = startDivot; + range.m_endDivot = endDivot; + m_rareData->m_typeProfilerInfoMap.set(instructionOffset, range); } -void UnlinkedProgramCodeBlock::destroy(JSCell* cell) +UnlinkedCodeBlock::~UnlinkedCodeBlock() { - jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock(); } -void UnlinkedEvalCodeBlock::destroy(JSCell* cell) +void UnlinkedCodeBlock::setInstructions(std::unique_ptr<UnlinkedInstructionStream> instructions) { - jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock(); + ASSERT(instructions); + { + auto locker = holdLock(*this); + m_unlinkedInstructions = WTFMove(instructions); + } + Heap::heap(this)->reportExtraMemoryAllocated(m_unlinkedInstructions->sizeInBytes()); } -void UnlinkedFunctionCodeBlock::destroy(JSCell* cell) +const UnlinkedInstructionStream& UnlinkedCodeBlock::instructions() const { - jsCast<UnlinkedFunctionCodeBlock*>(cell)->~UnlinkedFunctionCodeBlock(); + ASSERT(m_unlinkedInstructions.get()); + return *m_unlinkedInstructions; } -void UnlinkedFunctionExecutable::destroy(JSCell* cell) +UnlinkedHandlerInfo* UnlinkedCodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler requiredHandler) { - jsCast<UnlinkedFunctionExecutable*>(cell)->~UnlinkedFunctionExecutable(); + return handlerForIndex(bytecodeOffset, requiredHandler); } -void UnlinkedCodeBlock::setInstructions(std::unique_ptr<UnlinkedInstructionStream> instructions) +UnlinkedHandlerInfo* UnlinkedCodeBlock::handlerForIndex(unsigned index, RequiredHandler requiredHandler) { - m_unlinkedInstructions = std::move(instructions); + if (!m_rareData) + return nullptr; + return UnlinkedHandlerInfo::handlerForIndex(m_rareData->m_exceptionHandlers, index, requiredHandler); } -const UnlinkedInstructionStream& UnlinkedCodeBlock::instructions() const +void UnlinkedCodeBlock::applyModification(BytecodeRewriter& rewriter) { - ASSERT(m_unlinkedInstructions.get()); - return *m_unlinkedInstructions; + // Before applying the changes, we adjust the jumps based on the original bytecode offset, the offset to the jump target, and + // the insertion information. + + BytecodeGraph<UnlinkedCodeBlock>& graph = rewriter.graph(); + UnlinkedInstruction* instructionsBegin = graph.instructions().begin(); + + for (int bytecodeOffset = 0, instructionCount = graph.instructions().size(); bytecodeOffset < instructionCount;) { + UnlinkedInstruction* current = instructionsBegin + bytecodeOffset; + OpcodeID opcodeID = current[0].u.opcode; + extractStoredJumpTargetsForBytecodeOffset(this, vm()->interpreter, instructionsBegin, bytecodeOffset, [&](int32_t& relativeOffset) { + relativeOffset = rewriter.adjustJumpTarget(bytecodeOffset, bytecodeOffset + relativeOffset); + }); + bytecodeOffset += opcodeLength(opcodeID); + } + + // Then, exception handlers should be adjusted. + if (m_rareData) { + for (UnlinkedHandlerInfo& handler : m_rareData->m_exceptionHandlers) { + handler.target = rewriter.adjustAbsoluteOffset(handler.target); + handler.start = rewriter.adjustAbsoluteOffset(handler.start); + handler.end = rewriter.adjustAbsoluteOffset(handler.end); + } + + for (size_t i = 0; i < m_rareData->m_opProfileControlFlowBytecodeOffsets.size(); ++i) + m_rareData->m_opProfileControlFlowBytecodeOffsets[i] = rewriter.adjustAbsoluteOffset(m_rareData->m_opProfileControlFlowBytecodeOffsets[i]); + + if (!m_rareData->m_typeProfilerInfoMap.isEmpty()) { + HashMap<unsigned, RareData::TypeProfilerExpressionRange> adjustedTypeProfilerInfoMap; + for (auto& entry : m_rareData->m_typeProfilerInfoMap) + adjustedTypeProfilerInfoMap.set(rewriter.adjustAbsoluteOffset(entry.key), entry.value); + m_rareData->m_typeProfilerInfoMap.swap(adjustedTypeProfilerInfoMap); + } + } + + for (size_t i = 0; i < m_propertyAccessInstructions.size(); ++i) + m_propertyAccessInstructions[i] = rewriter.adjustAbsoluteOffset(m_propertyAccessInstructions[i]); + + for (size_t i = 0; i < m_expressionInfo.size(); ++i) + m_expressionInfo[i].instructionOffset = rewriter.adjustAbsoluteOffset(m_expressionInfo[i].instructionOffset); + + // Then, modify the unlinked instructions. + rewriter.applyModification(); + + // And recompute the jump target based on the modified unlinked instructions. + m_jumpTargets.clear(); + recomputePreciseJumpTargets(this, graph.instructions().begin(), graph.instructions().size(), m_jumpTargets); } +void UnlinkedCodeBlock::shrinkToFit() +{ + auto locker = holdLock(*this); + + m_jumpTargets.shrinkToFit(); + m_identifiers.shrinkToFit(); + m_bitVectors.shrinkToFit(); + m_constantRegisters.shrinkToFit(); + m_constantsSourceCodeRepresentation.shrinkToFit(); + m_functionDecls.shrinkToFit(); + m_functionExprs.shrinkToFit(); + m_propertyAccessInstructions.shrinkToFit(); + m_expressionInfo.shrinkToFit(); + + if (m_rareData) { + m_rareData->m_exceptionHandlers.shrinkToFit(); + m_rareData->m_regexps.shrinkToFit(); + m_rareData->m_constantBuffers.shrinkToFit(); + m_rareData->m_switchJumpTables.shrinkToFit(); + m_rareData->m_stringSwitchJumpTables.shrinkToFit(); + m_rareData->m_expressionInfoFatPositions.shrinkToFit(); + } } +} // namespace JSC |