summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp')
-rw-r--r--Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp261
1 files changed, 174 insertions, 87 deletions
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
index 83d9054a3..1dfb5ac6a 100644
--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013, 2015 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,10 +31,8 @@
#include "ClassInfo.h"
#include "CodeCache.h"
#include "Executable.h"
-#include "ExecutableInfo.h"
-#include "FunctionOverrides.h"
#include "JSString.h"
-#include "JSCInlines.h"
+#include "Operations.h"
#include "Parser.h"
#include "SourceProvider.h"
#include "Structure.h"
@@ -44,33 +42,177 @@
namespace JSC {
-const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) };
-const ClassInfo UnlinkedGlobalCodeBlock::s_info = { "UnlinkedGlobalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedGlobalCodeBlock) };
-const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedProgramCodeBlock) };
-const ClassInfo UnlinkedModuleProgramCodeBlock::s_info = { "UnlinkedModuleProgramCodeBlock", &Base::s_info, nullptr, CREATE_METHOD_TABLE(UnlinkedModuleProgramCodeBlock) };
-const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) };
-const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) };
+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) };
+
+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)
: Base(*vm, structure)
, m_numVars(0)
- , m_numCalleeLocals(0)
+ , m_numCalleeRegisters(0)
, m_numParameters(0)
+ , m_vm(vm)
+ , m_argumentsRegister(VirtualRegister())
, m_globalObjectRegister(VirtualRegister())
- , m_usesEval(info.usesEval())
- , m_isStrictMode(info.isStrictMode())
- , m_isConstructor(info.isConstructor())
+ , m_needsFullScopeChain(info.m_needsActivation)
+ , m_usesEval(info.m_usesEval)
+ , m_isNumericCompareFunction(false)
+ , m_isStrictMode(info.m_isStrictMode)
+ , m_isConstructor(info.m_isConstructor)
, m_hasCapturedVariables(false)
- , m_isBuiltinFunction(info.isBuiltinFunction())
- , m_constructorKind(static_cast<unsigned>(info.constructorKind()))
- , m_superBinding(static_cast<unsigned>(info.superBinding()))
- , m_derivedContextType(static_cast<unsigned>(info.derivedContextType()))
- , m_isArrowFunctionContext(info.isArrowFunctionContext())
- , m_isClassContext(info.isClassContext())
, m_firstLine(0)
, m_lineCount(0)
, m_endColumn(UINT_MAX)
- , m_parseMode(info.parseMode())
, m_features(0)
, m_codeType(codeType)
, m_arrayProfileCount(0)
@@ -78,42 +220,32 @@ 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()));
-}
-VM* UnlinkedCodeBlock::vm() const
-{
- return MarkedBlock::blockFor(this)->vm();
}
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);
for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr)
visitor.append(ptr);
for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++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]);
}
}
-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());
@@ -272,53 +404,15 @@ void UnlinkedCodeBlock::addExpressionInfo(unsigned instructionOffset,
m_expressionInfo.append(info);
}
-bool UnlinkedCodeBlock::typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot)
-{
- 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;
-}
-
-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::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
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);
-}
-
-void UnlinkedModuleProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
- UnlinkedModuleProgramCodeBlock* thisObject = jsCast<UnlinkedModuleProgramCodeBlock*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- Base::visitChildren(thisObject, visitor);
+ for (size_t i = 0, end = thisObject->m_functionDeclarations.size(); i != end; i++)
+ visitor.append(&thisObject->m_functionDeclarations[i].second);
}
UnlinkedCodeBlock::~UnlinkedCodeBlock()
@@ -330,11 +424,6 @@ void UnlinkedProgramCodeBlock::destroy(JSCell* cell)
jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock();
}
-void UnlinkedModuleProgramCodeBlock::destroy(JSCell* cell)
-{
- jsCast<UnlinkedModuleProgramCodeBlock*>(cell)->~UnlinkedModuleProgramCodeBlock();
-}
-
void UnlinkedEvalCodeBlock::destroy(JSCell* cell)
{
jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock();
@@ -352,9 +441,7 @@ void UnlinkedFunctionExecutable::destroy(JSCell* cell)
void UnlinkedCodeBlock::setInstructions(std::unique_ptr<UnlinkedInstructionStream> instructions)
{
- ASSERT(instructions);
- m_unlinkedInstructions = WTFMove(instructions);
- Heap::heap(this)->reportExtraMemoryAllocated(m_unlinkedInstructions->sizeInBytes());
+ m_unlinkedInstructions = std::move(instructions);
}
const UnlinkedInstructionStream& UnlinkedCodeBlock::instructions() const