Skip to content

Commit 0469d1b

Browse files
committed
[JSC] Generator CodeBlock generation should be idempotent
https://bugs.webkit.org/show_bug.cgi?id=197552 Reviewed by Keith Miller. JSTests: Add complex.yaml, which controls how to run JSC shell more. We split test files into two to run macro task between them which allows debugger to be attached to VM. * complex.yaml: Added. * complex/generator-regeneration-after.js: Added. * complex/generator-regeneration.js: Added. (gen): Source/JavaScriptCore: ES6 Generator saves and resumes the current execution state. Since ES6 generator can save the execution state at expression granularity (not statement granularity), the saved state involves locals. But if the underlying CodeBlock is jettisoned and recompiled with different code generation option (like, debugger, type profiler etc.), the generated instructions can be largely different and it does not have the same state previously used. If we resume the previously created generator with the newly generator function, resuming is messed up. function* gen () { ... } var g = gen(); g.next(); // CodeBlock is destroyed & Debugger is enabled. g.next(); In this patch, 1. In generatorification, we use index Identifier (localN => Identifier("N")) instead of private symbols to generate the same instructions every time we regenerate the CodeBlock. 2. We decouple the options which can affect on the generated code (Debugger, TypeProfiler, ControlFlowProfiler) from the BytecodeGenerator, and pass them as a parameter, OptionSet<CodeGeneratorMode>. 3. Generator ScriptExecutable remembers the previous CodeGeneratorMode and reuses this parameter to regenerate CodeBlock. It means that, even if the debugger is enabled, previously created generators are not debuggable. But newly created generators are debuggable. * bytecode/BytecodeGeneratorification.cpp: (JSC::BytecodeGeneratorification::storageForGeneratorLocal): (JSC::BytecodeGeneratorification::run): * bytecode/CodeBlock.cpp: (JSC::CodeBlock::finishCreation): (JSC::CodeBlock::setConstantRegisters): * bytecode/UnlinkedCodeBlock.cpp: (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock): * bytecode/UnlinkedCodeBlock.h: (JSC::UnlinkedCodeBlock::wasCompiledWithDebuggingOpcodes const): (JSC::UnlinkedCodeBlock::wasCompiledWithTypeProfilerOpcodes const): (JSC::UnlinkedCodeBlock::wasCompiledWithControlFlowProfilerOpcodes const): (JSC::UnlinkedCodeBlock::codeGenerationMode const): * bytecode/UnlinkedEvalCodeBlock.h: * bytecode/UnlinkedFunctionCodeBlock.h: * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::generateUnlinkedFunctionCodeBlock): (JSC::UnlinkedFunctionExecutable::fromGlobalCode): (JSC::UnlinkedFunctionExecutable::unlinkedCodeBlockFor): * bytecode/UnlinkedFunctionExecutable.h: * bytecode/UnlinkedGlobalCodeBlock.h: (JSC::UnlinkedGlobalCodeBlock::UnlinkedGlobalCodeBlock): * bytecode/UnlinkedModuleProgramCodeBlock.h: * bytecode/UnlinkedProgramCodeBlock.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::emitTypeProfilerExpressionInfo): (JSC::BytecodeGenerator::emitProfileType): (JSC::BytecodeGenerator::emitProfileControlFlow): (JSC::BytecodeGenerator::pushLexicalScopeInternal): (JSC::BytecodeGenerator::popLexicalScopeInternal): (JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration): (JSC::BytecodeGenerator::emitCall): (JSC::BytecodeGenerator::emitCallVarargs): (JSC::BytecodeGenerator::emitLogShadowChickenPrologueIfNecessary): (JSC::BytecodeGenerator::emitLogShadowChickenTailIfNecessary): (JSC::BytecodeGenerator::emitDebugHook): * bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::generate): (JSC::BytecodeGenerator::shouldEmitDebugHooks const): (JSC::BytecodeGenerator::shouldEmitTypeProfilerHooks const): (JSC::BytecodeGenerator::shouldEmitControlFlowProfilerHooks const): * bytecompiler/NodesCodegen.cpp: (JSC::PrefixNode::emitResolve): (JSC::EmptyVarExpression::emitBytecode): (JSC::ReturnNode::emitBytecode): (JSC::FunctionNode::emitBytecode): * parser/ParserModes.h: (): Deleted. * parser/SourceCodeKey.h: (JSC::SourceCodeFlags::SourceCodeFlags): (JSC::SourceCodeKey::SourceCodeKey): * runtime/CachedTypes.cpp: (JSC::CachedCodeBlock::isClassContext const): (JSC::CachedCodeBlock::codeGenerationMode const): (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock): (JSC::CachedCodeBlock<CodeBlockType>::encode): (JSC::CachedCodeBlock::wasCompiledWithDebuggingOpcodes const): Deleted. * runtime/CodeCache.cpp: (JSC::CodeCache::getUnlinkedGlobalCodeBlock): (JSC::CodeCache::getUnlinkedProgramCodeBlock): (JSC::CodeCache::getUnlinkedEvalCodeBlock): (JSC::CodeCache::getUnlinkedModuleProgramCodeBlock): (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable): (JSC::generateUnlinkedCodeBlockForFunctions): (JSC::sourceCodeKeyForSerializedBytecode): (JSC::sourceCodeKeyForSerializedProgram): (JSC::sourceCodeKeyForSerializedModule): (JSC::serializeBytecode): * runtime/CodeCache.h: (JSC::generateUnlinkedCodeBlockImpl): (JSC::generateUnlinkedCodeBlock): * runtime/Completion.cpp: (JSC::generateProgramBytecode): (JSC::generateModuleBytecode): * runtime/DirectEvalExecutable.cpp: (JSC::DirectEvalExecutable::create): * runtime/IndirectEvalExecutable.cpp: (JSC::IndirectEvalExecutable::create): * runtime/JSGlobalObject.h: (JSC::JSGlobalObject::defaultCodeGenerationMode const): * runtime/ModuleProgramExecutable.cpp: (JSC::ModuleProgramExecutable::create): * runtime/ProgramExecutable.cpp: (JSC::ProgramExecutable::initializeGlobalProperties): * runtime/ScriptExecutable.cpp: (JSC::ScriptExecutable::ScriptExecutable): (JSC::ScriptExecutable::newCodeBlockFor): * runtime/ScriptExecutable.h: * tools/JSDollarVM.cpp: (JSC::changeDebuggerModeWhenIdle): (JSC::functionEnableDebuggerModeWhenIdle): (JSC::functionDisableDebuggerModeWhenIdle): Tools: * Scripts/run-javascriptcore-tests: (runJSCStressTests): * Scripts/run-jsc-stress-tests: Canonical link: https://commits.webkit.org/211707@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244915 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 9b68654 commit 0469d1b

36 files changed

Lines changed: 386 additions & 170 deletions

‎JSTests/ChangeLog‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
2019-05-03 Yusuke Suzuki <ysuzuki@apple.com>
2+
3+
[JSC] Generator CodeBlock generation should be idempotent
4+
https://bugs.webkit.org/show_bug.cgi?id=197552
5+
6+
Reviewed by Keith Miller.
7+
8+
Add complex.yaml, which controls how to run JSC shell more.
9+
We split test files into two to run macro task between them which allows debugger to be attached to VM.
10+
11+
* complex.yaml: Added.
12+
* complex/generator-regeneration-after.js: Added.
13+
* complex/generator-regeneration.js: Added.
14+
(gen):
15+
116
2019-05-02 Michael Saboff <msaboff@apple.com>
217

318
Unreviewed rollout of r244862.

‎JSTests/complex.yaml‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Copyright (C) 2019 Apple Inc. All rights reserved.
2+
#
3+
# Redistribution and use in source and binary forms, with or without
4+
# modification, are permitted provided that the following conditions
5+
# are met:
6+
#
7+
# 1. Redistributions of source code must retain the above copyright
8+
# notice, this list of conditions and the following disclaimer.
9+
# 2. Redistributions in binary form must reproduce the above copyright
10+
# notice, this list of conditions and the following disclaimer in the
11+
# documentation and/or other materials provided with the distribution.
12+
#
13+
# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
14+
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16+
# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22+
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23+
#
24+
# This is for writing a bit complex tests to drive in JSC shell (e.g. including multiple files with some special options).
25+
26+
- path: complex/generator-regeneration.js
27+
cmd: runComplexTest [], ["generator-regeneration-after.js"], "--useDollarVM=1"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
g.next();
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
function* gen()
2+
{
3+
var ok = 2;
4+
ok = ok + (yield 42);
5+
yield ok;
6+
yield ok;
7+
yield ok;
8+
}
9+
10+
var g = gen();
11+
g.next();
12+
$vm.enableDebuggerModeWhenIdle();
13+
fullGC();
14+
g.next();

‎Source/JavaScriptCore/ChangeLog‎

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,129 @@
1+
2019-05-03 Yusuke Suzuki <ysuzuki@apple.com>
2+
3+
[JSC] Generator CodeBlock generation should be idempotent
4+
https://bugs.webkit.org/show_bug.cgi?id=197552
5+
6+
Reviewed by Keith Miller.
7+
8+
ES6 Generator saves and resumes the current execution state. Since ES6 generator can save the execution state at expression
9+
granularity (not statement granularity), the saved state involves locals. But if the underlying CodeBlock is jettisoned and
10+
recompiled with different code generation option (like, debugger, type profiler etc.), the generated instructions can be largely
11+
different and it does not have the same state previously used. If we resume the previously created generator with the newly
12+
generator function, resuming is messed up.
13+
14+
function* gen () { ... }
15+
var g = gen();
16+
g.next();
17+
18+
// CodeBlock is destroyed & Debugger is enabled.
19+
20+
g.next();
21+
22+
In this patch,
23+
24+
1. In generatorification, we use index Identifier (localN => Identifier("N")) instead of private symbols to generate the same
25+
instructions every time we regenerate the CodeBlock.
26+
27+
2. We decouple the options which can affect on the generated code (Debugger, TypeProfiler, ControlFlowProfiler) from the BytecodeGenerator,
28+
and pass them as a parameter, OptionSet<CodeGeneratorMode>.
29+
30+
3. Generator ScriptExecutable remembers the previous CodeGeneratorMode and reuses this parameter to regenerate CodeBlock. It means that,
31+
even if the debugger is enabled, previously created generators are not debuggable. But newly created generators are debuggable.
32+
33+
* bytecode/BytecodeGeneratorification.cpp:
34+
(JSC::BytecodeGeneratorification::storageForGeneratorLocal):
35+
(JSC::BytecodeGeneratorification::run):
36+
* bytecode/CodeBlock.cpp:
37+
(JSC::CodeBlock::finishCreation):
38+
(JSC::CodeBlock::setConstantRegisters):
39+
* bytecode/UnlinkedCodeBlock.cpp:
40+
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
41+
* bytecode/UnlinkedCodeBlock.h:
42+
(JSC::UnlinkedCodeBlock::wasCompiledWithDebuggingOpcodes const):
43+
(JSC::UnlinkedCodeBlock::wasCompiledWithTypeProfilerOpcodes const):
44+
(JSC::UnlinkedCodeBlock::wasCompiledWithControlFlowProfilerOpcodes const):
45+
(JSC::UnlinkedCodeBlock::codeGenerationMode const):
46+
* bytecode/UnlinkedEvalCodeBlock.h:
47+
* bytecode/UnlinkedFunctionCodeBlock.h:
48+
* bytecode/UnlinkedFunctionExecutable.cpp:
49+
(JSC::generateUnlinkedFunctionCodeBlock):
50+
(JSC::UnlinkedFunctionExecutable::fromGlobalCode):
51+
(JSC::UnlinkedFunctionExecutable::unlinkedCodeBlockFor):
52+
* bytecode/UnlinkedFunctionExecutable.h:
53+
* bytecode/UnlinkedGlobalCodeBlock.h:
54+
(JSC::UnlinkedGlobalCodeBlock::UnlinkedGlobalCodeBlock):
55+
* bytecode/UnlinkedModuleProgramCodeBlock.h:
56+
* bytecode/UnlinkedProgramCodeBlock.h:
57+
* bytecompiler/BytecodeGenerator.cpp:
58+
(JSC::BytecodeGenerator::BytecodeGenerator):
59+
(JSC::BytecodeGenerator::emitTypeProfilerExpressionInfo):
60+
(JSC::BytecodeGenerator::emitProfileType):
61+
(JSC::BytecodeGenerator::emitProfileControlFlow):
62+
(JSC::BytecodeGenerator::pushLexicalScopeInternal):
63+
(JSC::BytecodeGenerator::popLexicalScopeInternal):
64+
(JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration):
65+
(JSC::BytecodeGenerator::emitCall):
66+
(JSC::BytecodeGenerator::emitCallVarargs):
67+
(JSC::BytecodeGenerator::emitLogShadowChickenPrologueIfNecessary):
68+
(JSC::BytecodeGenerator::emitLogShadowChickenTailIfNecessary):
69+
(JSC::BytecodeGenerator::emitDebugHook):
70+
* bytecompiler/BytecodeGenerator.h:
71+
(JSC::BytecodeGenerator::generate):
72+
(JSC::BytecodeGenerator::shouldEmitDebugHooks const):
73+
(JSC::BytecodeGenerator::shouldEmitTypeProfilerHooks const):
74+
(JSC::BytecodeGenerator::shouldEmitControlFlowProfilerHooks const):
75+
* bytecompiler/NodesCodegen.cpp:
76+
(JSC::PrefixNode::emitResolve):
77+
(JSC::EmptyVarExpression::emitBytecode):
78+
(JSC::ReturnNode::emitBytecode):
79+
(JSC::FunctionNode::emitBytecode):
80+
* parser/ParserModes.h:
81+
(): Deleted.
82+
* parser/SourceCodeKey.h:
83+
(JSC::SourceCodeFlags::SourceCodeFlags):
84+
(JSC::SourceCodeKey::SourceCodeKey):
85+
* runtime/CachedTypes.cpp:
86+
(JSC::CachedCodeBlock::isClassContext const):
87+
(JSC::CachedCodeBlock::codeGenerationMode const):
88+
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
89+
(JSC::CachedCodeBlock<CodeBlockType>::encode):
90+
(JSC::CachedCodeBlock::wasCompiledWithDebuggingOpcodes const): Deleted.
91+
* runtime/CodeCache.cpp:
92+
(JSC::CodeCache::getUnlinkedGlobalCodeBlock):
93+
(JSC::CodeCache::getUnlinkedProgramCodeBlock):
94+
(JSC::CodeCache::getUnlinkedEvalCodeBlock):
95+
(JSC::CodeCache::getUnlinkedModuleProgramCodeBlock):
96+
(JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
97+
(JSC::generateUnlinkedCodeBlockForFunctions):
98+
(JSC::sourceCodeKeyForSerializedBytecode):
99+
(JSC::sourceCodeKeyForSerializedProgram):
100+
(JSC::sourceCodeKeyForSerializedModule):
101+
(JSC::serializeBytecode):
102+
* runtime/CodeCache.h:
103+
(JSC::generateUnlinkedCodeBlockImpl):
104+
(JSC::generateUnlinkedCodeBlock):
105+
* runtime/Completion.cpp:
106+
(JSC::generateProgramBytecode):
107+
(JSC::generateModuleBytecode):
108+
* runtime/DirectEvalExecutable.cpp:
109+
(JSC::DirectEvalExecutable::create):
110+
* runtime/IndirectEvalExecutable.cpp:
111+
(JSC::IndirectEvalExecutable::create):
112+
* runtime/JSGlobalObject.h:
113+
(JSC::JSGlobalObject::defaultCodeGenerationMode const):
114+
* runtime/ModuleProgramExecutable.cpp:
115+
(JSC::ModuleProgramExecutable::create):
116+
* runtime/ProgramExecutable.cpp:
117+
(JSC::ProgramExecutable::initializeGlobalProperties):
118+
* runtime/ScriptExecutable.cpp:
119+
(JSC::ScriptExecutable::ScriptExecutable):
120+
(JSC::ScriptExecutable::newCodeBlockFor):
121+
* runtime/ScriptExecutable.h:
122+
* tools/JSDollarVM.cpp:
123+
(JSC::changeDebuggerModeWhenIdle):
124+
(JSC::functionEnableDebuggerModeWhenIdle):
125+
(JSC::functionDisableDebuggerModeWhenIdle):
126+
1127
2019-05-03 Devin Rousso <drousso@apple.com>
2128

3129
Web Inspector: Record actions performed on WebGL2RenderingContext

‎Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class BytecodeGeneratorification {
146146
}
147147

148148
private:
149-
Storage storageForGeneratorLocal(unsigned index)
149+
Storage storageForGeneratorLocal(VM& vm, unsigned index)
150150
{
151151
// We assign a symbol to a register. There is one-on-one corresponding between a register and a symbol.
152152
// By doing so, we allocate the specific storage to save the given register.
@@ -158,7 +158,7 @@ class BytecodeGeneratorification {
158158
if (Optional<Storage> storage = m_storages[index])
159159
return *storage;
160160

161-
Identifier identifier = Identifier::fromUid(PrivateName());
161+
Identifier identifier = Identifier::from(&vm, index);
162162
unsigned identifierIndex = m_codeBlock->numberOfIdentifiers();
163163
m_codeBlock->addIdentifier(identifier);
164164
ScopeOffset scopeOffset = m_generatorFrameSymbolTable->takeNextScopeOffset(NoLockingNecessary);
@@ -211,6 +211,7 @@ void BytecodeGeneratorification::run()
211211
{
212212
// We calculate the liveness at each merge point. This gives us the information which registers should be saved and resumed conservatively.
213213

214+
VM& vm = *m_bytecodeGenerator.vm();
214215
{
215216
GeneratorLivenessAnalysis pass(*this);
216217
pass.run(m_codeBlock, m_instructions);
@@ -244,7 +245,7 @@ void BytecodeGeneratorification::run()
244245
rewriter.insertFragmentBefore(instruction, [&] (BytecodeRewriter::Fragment& fragment) {
245246
data.liveness.forEachSetBit([&](size_t index) {
246247
VirtualRegister operand = virtualRegisterForLocal(index);
247-
Storage storage = storageForGeneratorLocal(index);
248+
Storage storage = storageForGeneratorLocal(vm, index);
248249

249250
fragment.appendInstruction<OpPutToScope>(
250251
scope, // scope
@@ -264,7 +265,7 @@ void BytecodeGeneratorification::run()
264265
rewriter.insertFragmentAfter(instruction, [&] (BytecodeRewriter::Fragment& fragment) {
265266
data.liveness.forEachSetBit([&](size_t index) {
266267
VirtualRegister operand = virtualRegisterForLocal(index);
267-
Storage storage = storageForGeneratorLocal(index);
268+
Storage storage = storageForGeneratorLocal(vm, index);
268269

269270
fragment.appendInstruction<OpGetFromScope>(
270271
operand, // dst

‎Source/JavaScriptCore/bytecode/CodeBlock.cpp‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
392392

393393
auto throwScope = DECLARE_THROW_SCOPE(vm);
394394

395-
if (vm.typeProfiler() || vm.controlFlowProfiler())
395+
if (m_unlinkedCode->wasCompiledWithTypeProfilerOpcodes() || m_unlinkedCode->wasCompiledWithControlFlowProfilerOpcodes())
396396
vm.functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(vm), ownerExecutable->typeProfilingEndOffset(vm));
397397

398398
setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation());
@@ -408,14 +408,14 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
408408
// the module environments before linking the code block. We replace the stored symbol table with the already cloned one.
409409
if (UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock = jsDynamicCast<UnlinkedModuleProgramCodeBlock*>(vm, unlinkedCodeBlock)) {
410410
SymbolTable* clonedSymbolTable = jsCast<ModuleProgramExecutable*>(ownerExecutable)->moduleEnvironmentSymbolTable();
411-
if (vm.typeProfiler()) {
411+
if (m_unlinkedCode->wasCompiledWithTypeProfilerOpcodes()) {
412412
ConcurrentJSLocker locker(clonedSymbolTable->m_lock);
413413
clonedSymbolTable->prepareForTypeProfiling(locker);
414414
}
415415
replaceConstant(unlinkedModuleProgramCodeBlock->moduleEnvironmentSymbolTableConstantRegisterOffset(), clonedSymbolTable);
416416
}
417417

418-
bool shouldUpdateFunctionHasExecutedCache = vm.typeProfiler() || vm.controlFlowProfiler();
418+
bool shouldUpdateFunctionHasExecutedCache = m_unlinkedCode->wasCompiledWithTypeProfilerOpcodes() || m_unlinkedCode->wasCompiledWithControlFlowProfilerOpcodes();
419419
m_functionDecls = RefCountedArray<WriteBarrier<FunctionExecutable>>(unlinkedCodeBlock->numberOfFunctionDecls());
420420
for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
421421
UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
@@ -672,7 +672,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
672672
}
673673

674674
case op_profile_type: {
675-
RELEASE_ASSERT(vm.typeProfiler());
675+
RELEASE_ASSERT(m_unlinkedCode->wasCompiledWithTypeProfilerOpcodes());
676676

677677
INITIALIZE_METADATA(OpProfileType)
678678

@@ -781,7 +781,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
781781
#undef LINK_FIELD
782782
#undef LINK
783783

784-
if (vm.controlFlowProfiler())
784+
if (m_unlinkedCode->wasCompiledWithControlFlowProfilerOpcodes())
785785
insertBasicBlockBoundariesForControlFlowProfiler();
786786

787787
// Set optimization thresholds only after instructions is initialized, since these
@@ -880,15 +880,14 @@ void CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& consta
880880
ASSERT(constants.size() == constantsSourceCodeRepresentation.size());
881881
size_t count = constants.size();
882882
m_constantRegisters.resizeToFit(count);
883-
bool hasTypeProfiler = !!vm.typeProfiler();
884883
for (size_t i = 0; i < count; i++) {
885884
JSValue constant = constants[i].get();
886885

887886
if (!constant.isEmpty()) {
888887
if (constant.isCell()) {
889888
JSCell* cell = constant.asCell();
890889
if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(vm, cell)) {
891-
if (hasTypeProfiler) {
890+
if (m_unlinkedCode->wasCompiledWithTypeProfilerOpcodes()) {
892891
ConcurrentJSLocker locker(symbolTable->m_lock);
893892
symbolTable->prepareForTypeProfiling(locker);
894893
}

‎Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace JSC {
5454

5555
const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(UnlinkedCodeBlock) };
5656

57-
UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, DebuggerMode debuggerMode)
57+
UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, OptionSet<CodeGenerationMode> codeGenerationMode)
5858
: Base(*vm, structure)
5959
, m_usesEval(info.usesEval())
6060
, m_isStrictMode(info.isStrictMode())
@@ -65,14 +65,14 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType code
6565
, m_scriptMode(static_cast<unsigned>(info.scriptMode()))
6666
, m_isArrowFunctionContext(info.isArrowFunctionContext())
6767
, m_isClassContext(info.isClassContext())
68-
, m_wasCompiledWithDebuggingOpcodes(debuggerMode == DebuggerMode::DebuggerOn || Options::forceDebuggerBytecodeGeneration())
68+
, m_hasTailCalls(false)
6969
, m_constructorKind(static_cast<unsigned>(info.constructorKind()))
7070
, m_derivedContextType(static_cast<unsigned>(info.derivedContextType()))
7171
, m_evalContextType(static_cast<unsigned>(info.evalContextType()))
72-
, m_hasTailCalls(false)
7372
, m_codeType(static_cast<unsigned>(codeType))
7473
, m_didOptimize(static_cast<unsigned>(MixedTriState))
7574
, m_parseMode(info.parseMode())
75+
, m_codeGenerationMode(codeGenerationMode)
7676
, m_metadata(UnlinkedMetadataTable::create())
7777
{
7878
for (auto& constantRegisterIndex : m_linkTimeConstants)

‎Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,10 @@ class UnlinkedCodeBlock : public JSCell {
331331

332332
void dumpExpressionRangeInfo(); // For debugging purpose only.
333333

334-
bool wasCompiledWithDebuggingOpcodes() const { return m_wasCompiledWithDebuggingOpcodes; }
334+
bool wasCompiledWithDebuggingOpcodes() const { return m_codeGenerationMode.contains(CodeGenerationMode::Debugger); }
335+
bool wasCompiledWithTypeProfilerOpcodes() const { return m_codeGenerationMode.contains(CodeGenerationMode::TypeProfiler); }
336+
bool wasCompiledWithControlFlowProfilerOpcodes() const { return m_codeGenerationMode.contains(CodeGenerationMode::ControlFlowProfiler); }
337+
OptionSet<CodeGenerationMode> codeGenerationMode() const { return m_codeGenerationMode; }
335338

336339
TriState didOptimize() const { return static_cast<TriState>(m_didOptimize); }
337340
void setDidOptimize(TriState didOptimize) { m_didOptimize = static_cast<unsigned>(didOptimize); }
@@ -369,7 +372,7 @@ class UnlinkedCodeBlock : public JSCell {
369372

370373

371374
protected:
372-
UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, DebuggerMode);
375+
UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, OptionSet<CodeGenerationMode>);
373376

374377
template<typename CodeBlockType>
375378
UnlinkedCodeBlock(Decoder&, Structure*, const CachedCodeBlock<CodeBlockType>&);
@@ -415,18 +418,18 @@ class UnlinkedCodeBlock : public JSCell {
415418
unsigned m_scriptMode: 1;
416419
unsigned m_isArrowFunctionContext : 1;
417420
unsigned m_isClassContext : 1;
418-
unsigned m_wasCompiledWithDebuggingOpcodes : 1;
421+
unsigned m_hasTailCalls : 1;
419422
unsigned m_constructorKind : 2;
420423
unsigned m_derivedContextType : 2;
421424
unsigned m_evalContextType : 2;
422-
unsigned m_hasTailCalls : 1;
423425
unsigned m_codeType : 2;
424426
unsigned m_didOptimize : 2;
425427
public:
426428
ConcurrentJSLock m_lock;
427429
private:
428430
CodeFeatures m_features { 0 };
429431
SourceParseMode m_parseMode;
432+
OptionSet<CodeGenerationMode> m_codeGenerationMode;
430433

431434
unsigned m_lineCount { 0 };
432435
unsigned m_endColumn { UINT_MAX };

‎Source/JavaScriptCore/bytecode/UnlinkedEvalCodeBlock.h‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock {
3636
typedef UnlinkedGlobalCodeBlock Base;
3737
static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
3838

39-
static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info, DebuggerMode debuggerMode)
39+
static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info, OptionSet<CodeGenerationMode> codeGenerationMode)
4040
{
41-
UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info, debuggerMode);
41+
UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info, codeGenerationMode);
4242
instance->finishCreation(*vm);
4343
return instance;
4444
}
@@ -63,8 +63,8 @@ class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock {
6363
private:
6464
friend CachedEvalCodeBlock;
6565

66-
UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode)
67-
: Base(vm, structure, EvalCode, info, debuggerMode)
66+
UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, OptionSet<CodeGenerationMode> codeGenerationMode)
67+
: Base(vm, structure, EvalCode, info, codeGenerationMode)
6868
{
6969
}
7070

0 commit comments

Comments
 (0)