summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-10-18 10:55:06 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2012-10-18 10:55:06 +0200
commitee4c86d1990a9e26277a6948e7027ad8d525ebfa (patch)
tree1e2d3408cd097606571f40ab63353c27bcb7dd5c /Source/JavaScriptCore
parentd882bec96d0d30aeeda2141bfadfca7f038ee862 (diff)
downloadqtwebkit-ee4c86d1990a9e26277a6948e7027ad8d525ebfa.tar.gz
Imported WebKit commit 795dcd25a9649fccaf1c9b685f6e2ffedaf7e620 (http://svn.webkit.org/repository/webkit/trunk@131718)
New snapshot that includes the return of -fkeep-memory at link time to reduce memory pressure as well as modularized documentation
Diffstat (limited to 'Source/JavaScriptCore')
-rw-r--r--Source/JavaScriptCore/ChangeLog628
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp11
-rw-r--r--Source/JavaScriptCore/bytecode/Opcode.h1
-rw-r--r--Source/JavaScriptCore/bytecode/ResolveOperation.h178
-rw-r--r--Source/JavaScriptCore/bytecode/SpecialPointer.h2
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp97
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h20
-rw-r--r--Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp36
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp6
-rw-r--r--Source/JavaScriptCore/dfg/DFGCapabilities.h1
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.cpp4
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp19
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp18
-rw-r--r--Source/JavaScriptCore/heap/BlockAllocator.cpp28
-rw-r--r--Source/JavaScriptCore/heap/HeapStatistics.cpp6
-rw-r--r--Source/JavaScriptCore/heap/HeapStatistics.h1
-rw-r--r--Source/JavaScriptCore/jit/JIT.cpp1
-rw-r--r--Source/JavaScriptCore/jit/JIT.h1
-rw-r--r--Source/JavaScriptCore/jit/JITOpcodes.cpp11
-rw-r--r--Source/JavaScriptCore/jit/JITPropertyAccess.cpp2
-rw-r--r--Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp2
-rw-r--r--Source/JavaScriptCore/jit/JITStubs.cpp8
-rw-r--r--Source/JavaScriptCore/jit/JITStubs.h1
-rw-r--r--Source/JavaScriptCore/llint/LLIntSlowPaths.cpp7
-rw-r--r--Source/JavaScriptCore/llint/LLIntSlowPaths.h1
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter.asm6
-rw-r--r--Source/JavaScriptCore/runtime/ArrayConstructor.cpp19
-rw-r--r--Source/JavaScriptCore/runtime/ArrayConstructor.h3
-rw-r--r--Source/JavaScriptCore/runtime/CommonIdentifiers.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/StringPrototype.cpp20
-rw-r--r--Source/JavaScriptCore/yarr/YarrPattern.cpp4
32 files changed, 1066 insertions, 84 deletions
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 69429a65d..3574aa0d8 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,631 @@
+2012-10-17 Zoltan Horvath <zoltan@webkit.org>
+
+ Remove the JSHeap memory measurement of the PageLoad performacetests since it creates bogus JSGlobalDatas
+ https://bugs.webkit.org/show_bug.cgi?id=99609
+
+ Reviewed by Ryosuke Niwa.
+
+ Remove the implementation since it creates bogus JSGlobalDatas in the layout tests.
+
+ * heap/HeapStatistics.cpp:
+ (JSC):
+ * heap/HeapStatistics.h:
+ (HeapStatistics):
+
+2012-10-17 Sam Weinig <sam@webkit.org>
+
+ Attempt to fix the build.
+
+ * bytecode/GlobalResolveInfo.h: Copied from bytecode/GlobalResolveInfo.h.
+
+2012-10-17 Oliver Hunt <oliver@apple.com>
+
+ Roll out r131645 as it causes random site crashes.
+
+ * GNUmakefile.list.am:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * bytecode/CodeBlock.cpp:
+ (JSC):
+ (JSC::isGlobalResolve):
+ (JSC::instructionOffsetForNth):
+ (JSC::printGlobalResolveInfo):
+ (JSC::CodeBlock::printStructures):
+ (JSC::CodeBlock::dump):
+ (JSC::CodeBlock::CodeBlock):
+ (JSC::CodeBlock::visitStructures):
+ (JSC::CodeBlock::finalizeUnconditionally):
+ (JSC::CodeBlock::hasGlobalResolveInfoAtBytecodeOffset):
+ (JSC::CodeBlock::globalResolveInfoForBytecodeOffset):
+ (JSC::CodeBlock::shrinkToFit):
+ * bytecode/CodeBlock.h:
+ (CodeBlock):
+ (JSC::CodeBlock::addGlobalResolveInstruction):
+ (JSC::CodeBlock::addGlobalResolveInfo):
+ (JSC::CodeBlock::globalResolveInfo):
+ (JSC::CodeBlock::numberOfGlobalResolveInfos):
+ (JSC::CodeBlock::globalResolveInfoCount):
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * bytecode/ResolveGlobalStatus.cpp:
+ (JSC):
+ (JSC::computeForStructure):
+ (JSC::computeForLLInt):
+ (JSC::ResolveGlobalStatus::computeFor):
+ * bytecode/ResolveGlobalStatus.h:
+ (JSC):
+ (ResolveGlobalStatus):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::ResolveResult::checkValidity):
+ (JSC::ResolveResult::registerPointer):
+ (JSC):
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::resolve):
+ (JSC::BytecodeGenerator::resolveConstDecl):
+ (JSC::BytecodeGenerator::shouldAvoidResolveGlobal):
+ (JSC::BytecodeGenerator::emitResolve):
+ (JSC::BytecodeGenerator::emitResolveBase):
+ (JSC::BytecodeGenerator::emitResolveBaseForPut):
+ (JSC::BytecodeGenerator::emitResolveWithBase):
+ (JSC::BytecodeGenerator::emitResolveWithThis):
+ (JSC::BytecodeGenerator::emitGetStaticVar):
+ (JSC::BytecodeGenerator::emitInitGlobalConst):
+ (JSC::BytecodeGenerator::emitPutStaticVar):
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::ResolveResult::registerResolve):
+ (JSC::ResolveResult::dynamicResolve):
+ (JSC::ResolveResult::lexicalResolve):
+ (JSC::ResolveResult::indexedGlobalResolve):
+ (JSC::ResolveResult::dynamicIndexedGlobalResolve):
+ (JSC::ResolveResult::globalResolve):
+ (JSC::ResolveResult::dynamicGlobalResolve):
+ (JSC::ResolveResult::type):
+ (JSC::ResolveResult::index):
+ (JSC::ResolveResult::depth):
+ (JSC::ResolveResult::globalObject):
+ (ResolveResult):
+ (JSC::ResolveResult::isStatic):
+ (JSC::ResolveResult::isIndexed):
+ (JSC::ResolveResult::isScoped):
+ (JSC::ResolveResult::isGlobal):
+ (JSC::ResolveResult::ResolveResult):
+ (BytecodeGenerator):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ResolveNode::isPure):
+ (JSC::FunctionCallResolveNode::emitBytecode):
+ (JSC::PostfixNode::emitResolve):
+ (JSC::PrefixNode::emitResolve):
+ (JSC::ReadModifyResolveNode::emitBytecode):
+ (JSC::AssignResolveNode::emitBytecode):
+ (JSC::ConstDeclNode::emitCodeSingle):
+ (JSC::ForInNode::emitBytecode):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGByteCodeParser.cpp:
+ (ByteCodeParser):
+ (InlineStackEntry):
+ (JSC::DFG::ByteCodeParser::handleGetByOffset):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
+ * dfg/DFGCapabilities.h:
+ (DFG):
+ (JSC::DFG::canCompileOpcode):
+ (JSC::DFG::canInlineOpcode):
+ * dfg/DFGGraph.h:
+ (ResolveGlobalData):
+ (DFG):
+ (Graph):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::hasIdentifier):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGOSRExit.cpp:
+ (JSC::DFG::OSRExit::OSRExit):
+ * dfg/DFGOSRExit.h:
+ (OSRExit):
+ * dfg/DFGOSRExitCompiler.cpp:
+ * dfg/DFGOSRExitCompiler32_64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOSRExitCompiler64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ (JSC):
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::tryCacheGetByID):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::convertLastOSRExitToForward):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGStructureCheckHoistingPhase.cpp:
+ (JSC::DFG::StructureCheckHoistingPhase::run):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ (JSC::JIT::privateCompileSlowCases):
+ * jit/JIT.h:
+ (JIT):
+ (JSC::JIT::emit_op_get_global_var_watchable):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_resolve):
+ (JSC):
+ (JSC::JIT::emit_op_resolve_base):
+ (JSC::JIT::emit_op_resolve_skip):
+ (JSC::JIT::emit_op_resolve_global):
+ (JSC::JIT::emitSlow_op_resolve_global):
+ (JSC::JIT::emit_op_resolve_with_base):
+ (JSC::JIT::emit_op_resolve_with_this):
+ (JSC::JIT::emit_op_resolve_global_dynamic):
+ (JSC::JIT::emitSlow_op_resolve_global_dynamic):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_resolve):
+ (JSC):
+ (JSC::JIT::emit_op_resolve_base):
+ (JSC::JIT::emit_op_resolve_skip):
+ (JSC::JIT::emit_op_resolve_global):
+ (JSC::JIT::emitSlow_op_resolve_global):
+ (JSC::JIT::emit_op_resolve_with_base):
+ (JSC::JIT::emit_op_resolve_with_this):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_get_scoped_var):
+ (JSC):
+ (JSC::JIT::emit_op_put_scoped_var):
+ (JSC::JIT::emit_op_get_global_var):
+ (JSC::JIT::emit_op_put_global_var):
+ (JSC::JIT::emit_op_put_global_var_check):
+ (JSC::JIT::emitSlow_op_put_global_var_check):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_get_scoped_var):
+ (JSC):
+ (JSC::JIT::emit_op_put_scoped_var):
+ (JSC::JIT::emit_op_get_global_var):
+ (JSC::JIT::emit_op_put_global_var):
+ (JSC::JIT::emit_op_put_global_var_check):
+ (JSC::JIT::emitSlow_op_put_global_var_check):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ (JSC):
+ * jit/JITStubs.h:
+ * llint/LLIntSlowPaths.cpp:
+ (LLInt):
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * llint/LLIntSlowPaths.h:
+ (LLInt):
+ * llint/LowLevelInterpreter.asm:
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/JSScope.cpp:
+ (JSC::JSScope::resolve):
+ (JSC::JSScope::resolveSkip):
+ (JSC::JSScope::resolveGlobal):
+ (JSC::JSScope::resolveGlobalDynamic):
+ (JSC::JSScope::resolveBase):
+ (JSC::JSScope::resolveWithBase):
+ (JSC::JSScope::resolveWithThis):
+ * runtime/JSScope.h:
+ (JSScope):
+ * runtime/JSVariableObject.cpp:
+ * runtime/JSVariableObject.h:
+ * runtime/Structure.h:
+
+2012-10-17 Filip Pizlo <fpizlo@apple.com>
+
+ REGRESSION (r130826 or r130828): Twitter top bar is dysfunctional
+ https://bugs.webkit.org/show_bug.cgi?id=99577
+ <rdar://problem/12518883>
+
+ Reviewed by Mark Hahnenberg.
+
+ It turns out that it's a good idea to maintain the invariants of your object model, such as that
+ elements past publicLength should have the hole value.
+
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::dump):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
+2012-10-17 Anders Carlsson <andersca@apple.com>
+
+ Clean up Vector.h
+ https://bugs.webkit.org/show_bug.cgi?id=99622
+
+ Reviewed by Benjamin Poulain.
+
+ Fix fallout from removing std::max and std::min using declarations.
+
+ * runtime/StringPrototype.cpp:
+ (JSC::jsSpliceSubstrings):
+ (JSC::jsSpliceSubstringsWithSeparators):
+ (JSC::stringProtoFuncIndexOf):
+ * yarr/YarrPattern.cpp:
+ (JSC::Yarr::YarrPatternConstructor::setupDisjunctionOffsets):
+
+2012-10-17 Oliver Hunt <oliver@apple.com>
+
+ Committing new files is so overrated.
+
+ * bytecode/ResolveOperation.h: Added.
+ (JSC):
+ (JSC::ResolveOperation::getAndReturnScopedVar):
+ (JSC::ResolveOperation::checkForDynamicEntriesBeforeGlobalScope):
+ (ResolveOperation):
+ (JSC::ResolveOperation::getAndReturnGlobalVar):
+ (JSC::ResolveOperation::getAndReturnGlobalProperty):
+ (JSC::ResolveOperation::resolveFail):
+ (JSC::ResolveOperation::skipTopScopeNode):
+ (JSC::ResolveOperation::skipScopes):
+ (JSC::ResolveOperation::returnGlobalObjectAsBase):
+ (JSC::ResolveOperation::setBaseToGlobal):
+ (JSC::ResolveOperation::setBaseToUndefined):
+ (JSC::ResolveOperation::setBaseToScope):
+ (JSC::ResolveOperation::returnScopeAsBase):
+ (JSC::PutToBaseOperation::PutToBaseOperation):
+
+2012-10-17 Michael Saboff <msaboff@apple.com>
+
+ StringPrototype::jsSpliceSubstringsWithSeparators() doesn't optimally handle 8 bit strings
+ https://bugs.webkit.org/show_bug.cgi?id=99230
+
+ Reviewed by Geoffrey Garen.
+
+ Added code to select characters8() or characters16() on the not all 8 bit path for both the
+ processing of the source and the separators.
+
+ * runtime/StringPrototype.cpp:
+ (JSC::jsSpliceSubstringsWithSeparators):
+
+2012-10-17 Filip Pizlo <fpizlo@apple.com>
+
+ Array and object allocations via 'new Object' or 'new Array' should be inlined in bytecode to allow allocation site profiling
+ https://bugs.webkit.org/show_bug.cgi?id=99557
+
+ Reviewed by Geoffrey Garen.
+
+ Removed an inaccurate and misleading comment as per Geoff's review. (I forgot
+ to make this change as part of http://trac.webkit.org/changeset/131644).
+
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::FunctionCallResolveNode::emitBytecode):
+
+2012-10-17 Oliver Hunt <oliver@apple.com>
+
+ Bytecode should not have responsibility for determining how to perform non-local resolves
+ https://bugs.webkit.org/show_bug.cgi?id=99349
+
+ Reviewed by Gavin Barraclough.
+
+ This patch removes lexical analysis from the bytecode generation. This allows
+ us to delay lookup of a non-local variables until the lookup is actually necessary,
+ and simplifies a lot of the resolve logic in BytecodeGenerator.
+
+ Once a lookup is performed we cache the lookup information in a set of out-of-line
+ buffers in CodeBlock. This allows subsequent lookups to avoid unnecessary hashing,
+ etc, and allows the respective JITs to recreated optimal lookup code.
+
+ This is currently still a performance regression in LLInt, but most of the remaining
+ regression is caused by a lot of indirection that I'll remove in future work, as well
+ as some work necessary to allow LLInt to perform in line instruction repatching.
+ We will also want to improve the behaviour of the baseline JIT for some of the lookup
+ operations, however this patch was getting quite large already so I'm landing it now
+ that we've reached the bar of "performance-neutral".
+
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::printStructures):
+ (JSC::CodeBlock::dump):
+ (JSC::CodeBlock::CodeBlock):
+ (JSC::CodeBlock::visitStructures):
+ (JSC):
+ (JSC::CodeBlock::finalizeUnconditionally):
+ (JSC::CodeBlock::shrinkToFit):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::addResolve):
+ (JSC::CodeBlock::addPutToBase):
+ (CodeBlock):
+ (JSC::CodeBlock::resolveOperations):
+ (JSC::CodeBlock::putToBaseOperation):
+ (JSC::CodeBlock::numberOfResolveOperations):
+ (JSC::CodeBlock::numberOfPutToBaseOperations):
+ (JSC::CodeBlock::addPropertyAccessInstruction):
+ (JSC::CodeBlock::globalObjectConstant):
+ (JSC::CodeBlock::setGlobalObjectConstant):
+ * bytecode/GlobalResolveInfo.h: Removed.
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * bytecode/ResolveGlobalStatus.cpp:
+ (JSC::computeForStructure):
+ (JSC::ResolveGlobalStatus::computeFor):
+ * bytecode/ResolveGlobalStatus.h:
+ (JSC):
+ (ResolveGlobalStatus):
+ * bytecode/ResolveOperation.h: Added.
+ The new types and logic we use to perform the cached lookups.
+ (JSC):
+ (ResolveOperation):
+ (JSC::ResolveOperation::getAndReturnScopedVar):
+ (JSC::ResolveOperation::checkForDynamicEntriesBeforeGlobalScope):
+ (JSC::ResolveOperation::getAndReturnGlobalVar):
+ (JSC::ResolveOperation::getAndReturnGlobalProperty):
+ (JSC::ResolveOperation::resolveFail):
+ (JSC::ResolveOperation::skipTopScopeNode):
+ (JSC::ResolveOperation::skipScopes):
+ (JSC::ResolveOperation::returnGlobalObjectAsBase):
+ (JSC::ResolveOperation::setBaseToGlobal):
+ (JSC::ResolveOperation::setBaseToUndefined):
+ (JSC::ResolveOperation::setBaseToScope):
+ (JSC::ResolveOperation::returnScopeAsBase):
+ (JSC::PutToBaseOperation::PutToBaseOperation):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::ResolveResult::checkValidity):
+ (JSC):
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::resolve):
+ (JSC::BytecodeGenerator::resolveConstDecl):
+ (JSC::BytecodeGenerator::shouldAvoidResolveGlobal):
+ (JSC::BytecodeGenerator::emitResolve):
+ (JSC::BytecodeGenerator::emitResolveBase):
+ (JSC::BytecodeGenerator::emitResolveBaseForPut):
+ (JSC::BytecodeGenerator::emitResolveWithBaseForPut):
+ (JSC::BytecodeGenerator::emitResolveWithThis):
+ (JSC::BytecodeGenerator::emitGetLocalVar):
+ (JSC::BytecodeGenerator::emitInitGlobalConst):
+ (JSC::BytecodeGenerator::emitPutToBase):
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::ResolveResult::registerResolve):
+ (JSC::ResolveResult::dynamicResolve):
+ (ResolveResult):
+ (JSC::ResolveResult::ResolveResult):
+ (JSC):
+ (NonlocalResolveInfo):
+ (JSC::NonlocalResolveInfo::NonlocalResolveInfo):
+ (JSC::NonlocalResolveInfo::~NonlocalResolveInfo):
+ (JSC::NonlocalResolveInfo::resolved):
+ (JSC::NonlocalResolveInfo::put):
+ (BytecodeGenerator):
+ (JSC::BytecodeGenerator::getResolveOperations):
+ (JSC::BytecodeGenerator::getResolveWithThisOperations):
+ (JSC::BytecodeGenerator::getResolveBaseOperations):
+ (JSC::BytecodeGenerator::getResolveBaseForPutOperations):
+ (JSC::BytecodeGenerator::getResolveWithBaseForPutOperations):
+ (JSC::BytecodeGenerator::getPutToBaseOperation):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ResolveNode::isPure):
+ (JSC::FunctionCallResolveNode::emitBytecode):
+ (JSC::PostfixNode::emitResolve):
+ (JSC::PrefixNode::emitResolve):
+ (JSC::ReadModifyResolveNode::emitBytecode):
+ (JSC::AssignResolveNode::emitBytecode):
+ (JSC::ConstDeclNode::emitCodeSingle):
+ (JSC::ForInNode::emitBytecode):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGByteCodeParser.cpp:
+ (ByteCodeParser):
+ (InlineStackEntry):
+ (JSC::DFG::ByteCodeParser::handleGetByOffset):
+ (DFG):
+ (JSC::DFG::ByteCodeParser::parseResolveOperations):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
+ * dfg/DFGCapabilities.h:
+ (JSC::DFG::canCompileResolveOperations):
+ (DFG):
+ (JSC::DFG::canCompilePutToBaseOperation):
+ (JSC::DFG::canCompileOpcode):
+ (JSC::DFG::canInlineOpcode):
+ * dfg/DFGGraph.h:
+ (ResolveGlobalData):
+ (ResolveOperationData):
+ (DFG):
+ (PutToBaseOperationData):
+ (Graph):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::hasIdentifier):
+ (JSC::DFG::Node::resolveOperationsDataIndex):
+ (Node):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGOSRExit.cpp:
+ (JSC::DFG::OSRExit::OSRExit):
+ * dfg/DFGOSRExit.h:
+ (OSRExit):
+ * dfg/DFGOSRExitCompiler.cpp:
+ * dfg/DFGOSRExitCompiler32_64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOSRExitCompiler64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::tryCacheGetByID):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::convertLastOSRExitToForward):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::resolveOperations):
+ (SpeculativeJIT):
+ (JSC::DFG::SpeculativeJIT::putToBaseOperation):
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGStructureCheckHoistingPhase.cpp:
+ (JSC::DFG::StructureCheckHoistingPhase::run):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ (JSC::JIT::privateCompileSlowCases):
+ * jit/JIT.h:
+ (JIT):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_put_to_base):
+ (JSC):
+ (JSC::JIT::emit_resolve_operations):
+ (JSC::JIT::emitSlow_link_resolve_operations):
+ (JSC::JIT::emit_op_resolve):
+ (JSC::JIT::emitSlow_op_resolve):
+ (JSC::JIT::emit_op_resolve_base):
+ (JSC::JIT::emitSlow_op_resolve_base):
+ (JSC::JIT::emit_op_resolve_with_base):
+ (JSC::JIT::emitSlow_op_resolve_with_base):
+ (JSC::JIT::emit_op_resolve_with_this):
+ (JSC::JIT::emitSlow_op_resolve_with_this):
+ (JSC::JIT::emitSlow_op_put_to_base):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_put_to_base):
+ (JSC):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_init_global_const):
+ (JSC::JIT::emit_op_init_global_const_check):
+ (JSC::JIT::emitSlow_op_init_global_const_check):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_init_global_const):
+ (JSC::JIT::emit_op_init_global_const_check):
+ (JSC::JIT::emitSlow_op_init_global_const_check):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ (JSC):
+ * jit/JITStubs.h:
+ * llint/LLIntSlowPaths.cpp:
+ (LLInt):
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * llint/LLIntSlowPaths.h:
+ (LLInt):
+ * llint/LowLevelInterpreter.asm:
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/JSScope.cpp:
+ (JSC::LookupResult::base):
+ (JSC::LookupResult::value):
+ (JSC::LookupResult::setBase):
+ (JSC::LookupResult::setValue):
+ (LookupResult):
+ (JSC):
+ (JSC::setPutPropertyAccessOffset):
+ (JSC::executeResolveOperations):
+ (JSC::JSScope::resolveContainingScopeInternal):
+ (JSC::JSScope::resolveContainingScope):
+ (JSC::JSScope::resolve):
+ (JSC::JSScope::resolveBase):
+ (JSC::JSScope::resolveWithBase):
+ (JSC::JSScope::resolveWithThis):
+ (JSC::JSScope::resolvePut):
+ (JSC::JSScope::resolveGlobal):
+ * runtime/JSScope.h:
+ (JSScope):
+ * runtime/JSVariableObject.cpp:
+ (JSC):
+ * runtime/JSVariableObject.h:
+ (JSVariableObject):
+ * runtime/Structure.h:
+ (JSC::Structure::propertyAccessesAreCacheable):
+ (Structure):
+
+2012-10-17 Filip Pizlo <fpizlo@apple.com>
+
+ Array and object allocations via 'new Object' or 'new Array' should be inlined in bytecode to allow allocation site profiling
+ https://bugs.webkit.org/show_bug.cgi?id=99557
+
+ Reviewed by Geoffrey Garen.
+
+ This uses the old jneq_ptr trick to allow for the bytecode to "see" that the
+ operation in question is what we almost certainly know it to be.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * bytecode/SpecialPointer.h:
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitCall):
+ (JSC::BytecodeGenerator::emitCallEval):
+ (JSC::BytecodeGenerator::expectedFunctionForIdentifier):
+ (JSC):
+ (JSC::BytecodeGenerator::emitExpectedFunctionSnippet):
+ (JSC::BytecodeGenerator::emitConstruct):
+ * bytecompiler/BytecodeGenerator.h:
+ (BytecodeGenerator):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::NewExprNode::emitBytecode):
+ (JSC::FunctionCallValueNode::emitBytecode):
+ (JSC::FunctionCallResolveNode::emitBytecode):
+ (JSC::FunctionCallBracketNode::emitBytecode):
+ (JSC::FunctionCallDotNode::emitBytecode):
+ (JSC::CallFunctionCallDotNode::emitBytecode):
+ (JSC::ApplyFunctionCallDotNode::emitBytecode):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCapabilities.h:
+ (JSC::DFG::canCompileOpcode):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * jit/JIT.h:
+ (JIT):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_new_array_with_size):
+ (JSC):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ (JSC):
+ * jit/JITStubs.h:
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ (LLInt):
+ * llint/LLIntSlowPaths.h:
+ (LLInt):
+ * llint/LowLevelInterpreter.asm:
+ * runtime/ArrayConstructor.cpp:
+ (JSC::constructArrayWithSizeQuirk):
+ (JSC):
+ * runtime/ArrayConstructor.h:
+ (JSC):
+ * runtime/CommonIdentifiers.h:
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::reset):
+ (JSC):
+
+2012-10-17 Filip Pizlo <fpizlo@apple.com>
+
+ JIT op_get_by_pname should call cti_get_by_val_generic and not cti_get_by_val
+ https://bugs.webkit.org/show_bug.cgi?id=99631
+ <rdar://problem/12483221>
+
+ Reviewed by Mark Hahnenberg.
+
+ cti_get_by_val assumes that the return address has patching metadata associated with it, which won't
+ be true for op_get_by_pname. cti_get_by_val_generic makes no such assumptions.
+
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emitSlow_op_get_by_pname):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emitSlow_op_get_by_pname):
+
+2012-10-17 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Block freeing thread should sleep indefinitely when there's no work to do
+ https://bugs.webkit.org/show_bug.cgi?id=98084
+
+ Reviewed by Geoffrey Garen.
+
+ r130212 didn't fully fix the problem.
+
+ * heap/BlockAllocator.cpp:
+ (JSC::BlockAllocator::blockFreeingThreadMain): We would just continue to the next iteration if
+ we found that we had zero blocks to copy. We should move the indefinite wait up to where that
+ check is done so that we properly detect the "no more blocks to copy, wait for more" condition.
+
2012-10-16 Csaba Osztrogonác <ossy@webkit.org>
Unreviewed, rolling out r131516 and r131550.
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 9b8260a79..d1151482e 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -704,6 +704,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
dumpBytecodeCommentAndNewLine(location);
break;
}
+ case op_new_array_with_size: {
+ int dst = (++it)->u.operand;
+ int length = (++it)->u.operand;
+ dataLog("[%4d] new_array_with_size\t %s, %s", location, registerName(exec, dst).data(), registerName(exec, length).data());
+ dumpBytecodeCommentAndNewLine(location);
+ break;
+ }
case op_new_array_buffer: {
int dst = (++it)->u.operand;
int argv = (++it)->u.operand;
@@ -1245,9 +1252,9 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
}
case op_jneq_ptr: {
int r0 = (++it)->u.operand;
- void* pointer = (++it)->u.pointer;
+ Special::Pointer pointer = (++it)->u.specialPointer;
int offset = (++it)->u.operand;
- dataLog("[%4d] jneq_ptr\t\t %s, %p, %d(->%d)", location, registerName(exec, r0).data(), pointer, offset, location + offset);
+ dataLog("[%4d] jneq_ptr\t\t %s, %d (%p), %d(->%d)", location, registerName(exec, r0).data(), pointer, m_globalObject->actualPointerFor(pointer), offset, location + offset);
dumpBytecodeCommentAndNewLine(location);
break;
}
diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h
index a5d466154..dd62df700 100644
--- a/Source/JavaScriptCore/bytecode/Opcode.h
+++ b/Source/JavaScriptCore/bytecode/Opcode.h
@@ -49,6 +49,7 @@ namespace JSC {
\
macro(op_new_object, 2) \
macro(op_new_array, 4) \
+ macro(op_new_array_with_size, 3) \
macro(op_new_array_buffer, 4) \
macro(op_new_regexp, 3) \
macro(op_mov, 3) \
diff --git a/Source/JavaScriptCore/bytecode/ResolveOperation.h b/Source/JavaScriptCore/bytecode/ResolveOperation.h
new file mode 100644
index 000000000..1543ef209
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/ResolveOperation.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ResolveOperation_h
+#define ResolveOperation_h
+
+#include "PropertyOffset.h"
+#include "WriteBarrier.h"
+
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class Structure;
+
+struct ResolveOperation {
+ typedef enum {
+ Fail,
+ SetBaseToUndefined,
+ ReturnScopeAsBase,
+ SetBaseToScope,
+ SetBaseToGlobal,
+ GetAndReturnScopedVar,
+ GetAndReturnGlobalVar,
+ GetAndReturnGlobalVarWatchable,
+ SkipTopScopeNode,
+ SkipScopes,
+ ReturnGlobalObjectAsBase,
+ GetAndReturnGlobalProperty,
+ CheckForDynamicEntriesBeforeGlobalScope
+ } ResolveOperationType;
+
+ ResolveOperationType m_operation;
+ WriteBarrier<Structure> m_structure;
+ union {
+ PropertyOffset m_offset;
+ WriteBarrier<Unknown>* m_registerAddress;
+ int m_scopesToSkip;
+ int m_activationRegister;
+ };
+ static ResolveOperation getAndReturnScopedVar(PropertyOffset offset)
+ {
+ ResolveOperation op;
+ op.m_operation = GetAndReturnScopedVar;
+ op.m_offset = offset;
+ return op;
+ }
+ static ResolveOperation checkForDynamicEntriesBeforeGlobalScope()
+ {
+ ResolveOperation op;
+ op.m_operation = CheckForDynamicEntriesBeforeGlobalScope;
+ return op;
+ }
+
+ static ResolveOperation getAndReturnGlobalVar(WriteBarrier<Unknown>* registerAddress, bool couldBeWatched)
+ {
+ ResolveOperation op;
+ op.m_operation = couldBeWatched ? GetAndReturnGlobalVarWatchable : GetAndReturnGlobalVar;
+ op.m_registerAddress = registerAddress;
+ return op;
+ }
+ static ResolveOperation getAndReturnGlobalProperty()
+ {
+ ResolveOperation op;
+ op.m_operation = GetAndReturnGlobalProperty;
+ return op;
+ }
+ static ResolveOperation resolveFail()
+ {
+ ResolveOperation op;
+ op.m_operation = Fail;
+ return op;
+ }
+ static ResolveOperation skipTopScopeNode(int activationRegister)
+ {
+ ResolveOperation op;
+ op.m_operation = SkipTopScopeNode;
+ op.m_activationRegister = activationRegister;
+ return op;
+ }
+ static ResolveOperation skipScopes(int scopesToSkip)
+ {
+ ResolveOperation op;
+ op.m_operation = SkipScopes;
+ op.m_scopesToSkip = scopesToSkip;
+ return op;
+ }
+ static ResolveOperation returnGlobalObjectAsBase()
+ {
+ ResolveOperation op;
+ op.m_operation = ReturnGlobalObjectAsBase;
+ return op;
+ }
+ static ResolveOperation setBaseToGlobal()
+ {
+ ResolveOperation op;
+ op.m_operation = SetBaseToGlobal;
+ return op;
+ }
+ static ResolveOperation setBaseToUndefined()
+ {
+ ResolveOperation op;
+ op.m_operation = SetBaseToUndefined;
+ return op;
+ }
+ static ResolveOperation setBaseToScope()
+ {
+ ResolveOperation op;
+ op.m_operation = SetBaseToScope;
+ return op;
+ }
+ static ResolveOperation returnScopeAsBase()
+ {
+ ResolveOperation op;
+ op.m_operation = ReturnScopeAsBase;
+ return op;
+ }
+};
+
+typedef Vector<ResolveOperation> ResolveOperations;
+
+struct PutToBaseOperation {
+ PutToBaseOperation(bool isStrict)
+ : m_kind(Uninitialised)
+ , m_isDynamic(false)
+ , m_isStrict(isStrict)
+ , m_predicatePointer(0)
+ {
+
+ }
+ enum Kind { Uninitialised, Generic, Readonly, GlobalVariablePut, GlobalVariablePutChecked, GlobalPropertyPut, VariablePut };
+ union {
+ Kind m_kind : 8;
+ uint8_t m_kindAsUint8;
+ };
+ bool m_isDynamic : 8;
+ bool m_isStrict : 8;
+ union {
+ bool* m_predicatePointer;
+ unsigned m_scopeDepth;
+ };
+ WriteBarrier<Structure> m_structure;
+ union {
+ // Used for GlobalVariablePut
+ WriteBarrier<Unknown>* m_registerAddress;
+
+ // Used for GlobalPropertyPut and VariablePut
+ struct {
+ PropertyOffset m_offset;
+ int32_t m_offsetInButterfly;
+ };
+ };
+};
+}
+
+#endif // ResolveOperation_h
diff --git a/Source/JavaScriptCore/bytecode/SpecialPointer.h b/Source/JavaScriptCore/bytecode/SpecialPointer.h
index 2c624784b..c18a6e904 100644
--- a/Source/JavaScriptCore/bytecode/SpecialPointer.h
+++ b/Source/JavaScriptCore/bytecode/SpecialPointer.h
@@ -35,6 +35,8 @@ namespace Special {
enum Pointer {
CallFunction,
ApplyFunction,
+ ObjectConstructor,
+ ArrayConstructor,
TableSize // Not a real special pointer. Use this to determine the number of pointers.
};
} // namespace Special
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 4308148b3..1160a1888 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -2013,9 +2013,9 @@ RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExp
return r0;
}
-RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
+RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
{
- return emitCall(op_call, dst, func, callArguments, divot, startOffset, endOffset);
+ return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, startOffset, endOffset);
}
void BytecodeGenerator::createArgumentsIfNecessary()
@@ -2048,10 +2048,85 @@ void BytecodeGenerator::createActivationIfNecessary()
RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
{
- return emitCall(op_call_eval, dst, func, callArguments, divot, startOffset, endOffset);
+ return emitCall(op_call_eval, dst, func, NoExpectedFunction, callArguments, divot, startOffset, endOffset);
}
-RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
+ExpectedFunction BytecodeGenerator::expectedFunctionForIdentifier(const Identifier& identifier)
+{
+ if (identifier == m_globalData->propertyNames->Object)
+ return ExpectObjectConstructor;
+ if (identifier == m_globalData->propertyNames->Array)
+ return ExpectArrayConstructor;
+ return NoExpectedFunction;
+}
+
+ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, Label* done)
+{
+ RefPtr<Label> realCall = newLabel();
+ switch (expectedFunction) {
+ case ExpectObjectConstructor: {
+ // If the number of arguments is non-zero, then we can't do anything interesting.
+ if (callArguments.argumentCountIncludingThis() >= 2)
+ return NoExpectedFunction;
+
+ size_t begin = instructions().size();
+ emitOpcode(op_jneq_ptr);
+ instructions().append(func->index());
+ instructions().append(Special::ObjectConstructor);
+ instructions().append(realCall->bind(begin, instructions().size()));
+
+ if (dst != ignoredResult()) {
+ emitOpcode(op_new_object);
+ instructions().append(dst->index());
+ }
+ break;
+ }
+
+ case ExpectArrayConstructor: {
+ // If you're doing anything other than "new Array()" or "new Array(foo)" then we
+ // don't do inline it, for now. The only reason is that call arguments are in
+ // the opposite order of what op_new_array expects, so we'd either need to change
+ // how op_new_array works or we'd need an op_new_array_reverse. Neither of these
+ // things sounds like it's worth it.
+ if (callArguments.argumentCountIncludingThis() > 2)
+ return NoExpectedFunction;
+
+ size_t begin = instructions().size();
+ emitOpcode(op_jneq_ptr);
+ instructions().append(func->index());
+ instructions().append(Special::ArrayConstructor);
+ instructions().append(realCall->bind(begin, instructions().size()));
+
+ if (dst != ignoredResult()) {
+ if (callArguments.argumentCountIncludingThis() == 2) {
+ emitOpcode(op_new_array_with_size);
+ instructions().append(dst->index());
+ instructions().append(callArguments.argumentRegister(0)->index());
+ } else {
+ ASSERT(callArguments.argumentCountIncludingThis() == 1);
+ emitOpcode(op_new_array);
+ instructions().append(dst->index());
+ instructions().append(0);
+ instructions().append(0);
+ }
+ }
+ break;
+ }
+
+ default:
+ ASSERT(expectedFunction == NoExpectedFunction);
+ return NoExpectedFunction;
+ }
+
+ size_t begin = instructions().size();
+ emitOpcode(op_jmp);
+ instructions().append(done->bind(begin, instructions().size()));
+ emitLabel(realCall.get());
+
+ return expectedFunction;
+}
+
+RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
{
ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
ASSERT(func->refCount());
@@ -2076,6 +2151,9 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
emitExpressionInfo(divot, startOffset, endOffset);
+ RefPtr<Label> done = newLabel();
+ expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
+
// Emit call.
ArrayProfile* arrayProfile = newArrayProfile();
emitOpcode(opcodeID);
@@ -2093,6 +2171,9 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
instructions().append(dst->index()); // dst
instructions().append(profile);
}
+
+ if (expectedFunction != NoExpectedFunction)
+ emitLabel(done.get());
if (m_shouldEmitProfileHooks) {
emitOpcode(op_profile_did_call);
@@ -2162,7 +2243,7 @@ RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* s
return src;
}
-RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
+RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
{
ASSERT(func->refCount());
@@ -2187,6 +2268,9 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
callFrame.append(newTemporary());
emitExpressionInfo(divot, startOffset, endOffset);
+
+ RefPtr<Label> done = newLabel();
+ expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
emitOpcode(op_construct);
instructions().append(func->index()); // func
@@ -2204,6 +2288,9 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
instructions().append(profile);
}
+ if (expectedFunction != NoExpectedFunction)
+ emitLabel(done.get());
+
if (m_shouldEmitProfileHooks) {
emitOpcode(op_profile_did_call);
instructions().append(callArguments.profileHookRegister()->index());
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index a429c710e..ae79a13ae 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -51,6 +51,12 @@ namespace JSC {
class Label;
class JSScope;
+ enum ExpectedFunction {
+ NoExpectedFunction,
+ ExpectObjectConstructor,
+ ExpectArrayConstructor
+ };
+
class CallArguments {
public:
CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode);
@@ -483,8 +489,9 @@ namespace JSC {
RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
void emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter);
-
- RegisterID* emitCall(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
+ RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, RegisterID* profileHookRegister, unsigned divot, unsigned startOffset, unsigned endOffset);
RegisterID* emitLoadVarargs(RegisterID* argCountDst, RegisterID* thisRegister, RegisterID* args);
@@ -492,7 +499,7 @@ namespace JSC {
RegisterID* emitReturn(RegisterID* src);
RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
- RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
+ RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
void emitToPrimitive(RegisterID* dst, RegisterID* src);
@@ -590,7 +597,12 @@ namespace JSC {
typedef HashMap<double, JSValue> NumberMap;
typedef HashMap<StringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
- RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
+ // Helper for emitCall() and emitConstruct(). This works because the set of
+ // expected functions have identical behavior for both call and construct
+ // (i.e. "Object()" is identical to "new Object()").
+ ExpectedFunction emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, Label* done);
+
+ RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
RegisterID* newRegister();
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index 0ac4149b6..10a873d1c 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -366,9 +366,14 @@ RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, Registe
RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
+ ExpectedFunction expectedFunction;
+ if (m_expr->isResolveNode())
+ expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
+ else
+ expectedFunction = NoExpectedFunction;
RefPtr<RegisterID> func = generator.emitNode(m_expr);
CallArguments callArguments(generator, m_args);
- return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), callArguments, divot(), startOffset(), endOffset());
+ return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), expectedFunction, callArguments, divot(), startOffset(), endOffset());
}
inline CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode)
@@ -415,20 +420,23 @@ RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, Re
RefPtr<RegisterID> func = generator.emitNode(m_expr);
CallArguments callArguments(generator, m_args);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
- return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
}
// ------------------------------ FunctionCallResolveNode ----------------------------------
RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
+ ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
ResolveResult resolveResult = generator.resolve(m_ident);
if (RegisterID* local = resolveResult.local()) {
RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
CallArguments callArguments(generator, m_args);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
- return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), func.get(), callArguments, divot(), startOffset(), endOffset());
+ // This passes NoExpectedFunction because we expect that if the function is in a
+ // local variable, then it's not one of our built-in constructors.
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), func.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
}
if (resolveResult.isStatic()) {
@@ -436,7 +444,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
CallArguments callArguments(generator, m_args);
generator.emitGetStaticVar(func.get(), resolveResult, m_ident);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
- return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), expectedFunction, callArguments, divot(), startOffset(), endOffset());
}
RefPtr<RegisterID> func = generator.newTemporary();
@@ -445,7 +453,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0);
generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), resolveResult, m_ident);
- return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), expectedFunction, callArguments, divot(), startOffset(), endOffset());
}
// ------------------------------ FunctionCallBracketNode ----------------------------------
@@ -458,7 +466,7 @@ RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator,
RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
CallArguments callArguments(generator, m_args);
generator.emitMove(callArguments.thisRegister(), base.get());
- return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
}
// ------------------------------ FunctionCallDotNode ----------------------------------
@@ -471,7 +479,7 @@ RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, Regi
generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
generator.emitMethodCheck();
generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
- return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
}
RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
@@ -491,7 +499,7 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
CallArguments callArguments(generator, m_args);
generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
- generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
generator.emitJump(end.get());
m_args->m_listNode = oldList;
@@ -499,7 +507,7 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
CallArguments callArguments(generator, m_args);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
- generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
generator.emitJump(end.get());
}
}
@@ -507,7 +515,7 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
{
CallArguments callArguments(generator, m_args);
generator.emitMove(callArguments.thisRegister(), base.get());
- generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), function.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
}
generator.emitLabel(end.get());
return finalDestinationOrIgnored.get();
@@ -544,20 +552,20 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
CallArguments callArguments(generator, m_args);
generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
- generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
} else {
m_args->m_listNode = m_args->m_listNode->m_next;
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
CallArguments callArguments(generator, m_args);
generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
- generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
}
m_args->m_listNode = oldList;
} else {
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
CallArguments callArguments(generator, m_args);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
- generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
}
} else {
ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
@@ -586,7 +594,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
{
CallArguments callArguments(generator, m_args);
generator.emitMove(callArguments.thisRegister(), base.get());
- generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), function.get(), NoExpectedFunction, callArguments, divot(), startOffset(), endOffset());
}
generator.emitLabel(end.get());
return finalDestinationOrIgnored.get();
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index dc668d93e..4869cf8c1 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -1966,6 +1966,12 @@ bool ByteCodeParser::parseBlock(unsigned limit)
NEXT_OPCODE(op_new_array);
}
+ case op_new_array_with_size: {
+ int lengthOperand = currentInstruction[2].u.operand;
+ set(currentInstruction[1].u.operand, addToGraph(NewArrayWithSize, get(lengthOperand)));
+ NEXT_OPCODE(op_new_array_with_size);
+ }
+
case op_new_array_buffer: {
int startConstant = currentInstruction[2].u.operand;
int numConstants = currentInstruction[3].u.operand;
diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.h b/Source/JavaScriptCore/dfg/DFGCapabilities.h
index e1760699a..dc6f7aa1c 100644
--- a/Source/JavaScriptCore/dfg/DFGCapabilities.h
+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.h
@@ -162,6 +162,7 @@ inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instructi
case op_resolve_global:
case op_new_object:
case op_new_array:
+ case op_new_array_with_size:
case op_new_array_buffer:
case op_strcat:
case op_to_primitive:
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp
index f4d260b9e..b9a0db2a2 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.cpp
+++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp
@@ -246,12 +246,12 @@ void Graph::dump(const char* prefix, NodeIndex nodeIndex)
}
if (node.hasStructureSet()) {
for (size_t i = 0; i < node.structureSet().size(); ++i) {
- dataLog("%sstruct(%p)", hasPrinted ? ", " : "", node.structureSet()[i]);
+ dataLog("%sstruct(%p: %s)", hasPrinted ? ", " : "", node.structureSet()[i], indexingTypeToString(node.structureSet()[i]->indexingType()));
hasPrinted = true;
}
}
if (node.hasStructure()) {
- dataLog("%sstruct(%p)", hasPrinted ? ", " : "", node.structure());
+ dataLog("%sstruct(%p: %s)", hasPrinted ? ", " : "", node.structure(), indexingTypeToString(node.structure()->indexingType()));
hasPrinted = true;
}
if (node.hasStructureTransitionData()) {
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 0396f8696..41fe8db0f 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -3157,19 +3157,22 @@ void SpeculativeJIT::compile(Node& node)
case Array::ArrayWithContiguous:
case Array::ArrayWithContiguousOutOfBounds: {
m_jit.load32(
- MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valueTagGPR);
+ MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
MacroAssembler::Jump undefinedCase =
- m_jit.branchTest32(MacroAssembler::Zero, valueTagGPR);
- m_jit.sub32(TrustedImm32(1), valueTagGPR);
+ m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
+ m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
m_jit.store32(
- valueTagGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+ valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
m_jit.load32(
- MacroAssembler::BaseIndex(storageGPR, valueTagGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
- valuePayloadGPR);
- m_jit.load32(
- MacroAssembler::BaseIndex(storageGPR, valueTagGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
+ MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
valueTagGPR);
MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
+ m_jit.store32(
+ MacroAssembler::TrustedImm32(JSValue::EmptyValueTag),
+ MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+ m_jit.load32(
+ MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
+ valuePayloadGPR);
addSlowPathGenerator(
slowPathMove(
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 0928dfa58..daca71da7 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -3191,24 +3191,30 @@ void SpeculativeJIT::compile(Node& node)
SpeculateCellOperand base(this, node.child1());
StorageOperand storage(this, node.child2());
GPRTemporary value(this);
+ GPRTemporary storageLength(this);
GPRReg baseGPR = base.gpr();
GPRReg storageGPR = storage.gpr();
GPRReg valueGPR = value.gpr();
+ GPRReg storageLengthGPR = storageLength.gpr();
switch (node.arrayMode()) {
case Array::ArrayWithContiguous:
case Array::ArrayWithContiguousOutOfBounds: {
m_jit.load32(
- MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valueGPR);
+ MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
MacroAssembler::Jump undefinedCase =
- m_jit.branchTest32(MacroAssembler::Zero, valueGPR);
- m_jit.sub32(TrustedImm32(1), valueGPR);
+ m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
+ m_jit.sub32(TrustedImm32(1), storageLengthGPR);
m_jit.store32(
- valueGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+ storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
m_jit.loadPtr(
- MacroAssembler::BaseIndex(storageGPR, valueGPR, MacroAssembler::ScalePtr),
+ MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr),
valueGPR);
+ // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
+ // length and the new length.
+ m_jit.storePtr(
+ MacroAssembler::TrustedImmPtr(0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr));
MacroAssembler::Jump slowCase = m_jit.branchTestPtr(MacroAssembler::Zero, valueGPR);
addSlowPathGenerator(
@@ -3225,8 +3231,6 @@ void SpeculativeJIT::compile(Node& node)
case Array::ArrayWithArrayStorage:
case Array::ArrayWithArrayStorageOutOfBounds: {
- GPRTemporary storageLength(this);
- GPRReg storageLengthGPR = storageLength.gpr();
m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
JITCompiler::Jump undefinedCase =
diff --git a/Source/JavaScriptCore/heap/BlockAllocator.cpp b/Source/JavaScriptCore/heap/BlockAllocator.cpp
index 9a2e0bf60..16f607396 100644
--- a/Source/JavaScriptCore/heap/BlockAllocator.cpp
+++ b/Source/JavaScriptCore/heap/BlockAllocator.cpp
@@ -102,6 +102,7 @@ void BlockAllocator::blockFreeingThreadStartFunc(void* blockAllocator)
void BlockAllocator::blockFreeingThreadMain()
{
+ size_t currentNumberOfEmptyRegions;
while (!m_blockFreeingThreadShouldQuit) {
// Generally wait for one second before scavenging free blocks. This
// may return early, particularly when we're being asked to quit.
@@ -114,12 +115,17 @@ void BlockAllocator::blockFreeingThreadMain()
continue;
}
- // Now process the list of free blocks. Keep freeing until half of the
- // blocks that are currently on the list are gone. Assume that a size_t
- // field can be accessed atomically.
- size_t currentNumberOfEmptyRegions = m_numberOfEmptyRegions;
- if (!currentNumberOfEmptyRegions)
- continue;
+ // Sleep until there is actually work to do rather than waking up every second to check.
+ {
+ MutexLocker locker(m_emptyRegionConditionLock);
+ SpinLockHolder regionLocker(&m_regionLock);
+ while (!m_numberOfEmptyRegions && !m_blockFreeingThreadShouldQuit) {
+ m_regionLock.Unlock();
+ m_emptyRegionCondition.wait(m_emptyRegionConditionLock);
+ m_regionLock.Lock();
+ }
+ currentNumberOfEmptyRegions = m_numberOfEmptyRegions;
+ }
size_t desiredNumberOfEmptyRegions = currentNumberOfEmptyRegions / 2;
@@ -141,16 +147,6 @@ void BlockAllocator::blockFreeingThreadMain()
delete region;
}
-
- // Sleep until there is actually work to do rather than waking up every second to check.
- MutexLocker locker(m_emptyRegionConditionLock);
- m_regionLock.Lock();
- while (!m_numberOfEmptyRegions && !m_blockFreeingThreadShouldQuit) {
- m_regionLock.Unlock();
- m_emptyRegionCondition.wait(m_emptyRegionConditionLock);
- m_regionLock.Lock();
- }
- m_regionLock.Unlock();
}
}
diff --git a/Source/JavaScriptCore/heap/HeapStatistics.cpp b/Source/JavaScriptCore/heap/HeapStatistics.cpp
index 68044e0b3..8340bfa37 100644
--- a/Source/JavaScriptCore/heap/HeapStatistics.cpp
+++ b/Source/JavaScriptCore/heap/HeapStatistics.cpp
@@ -138,12 +138,6 @@ void HeapStatistics::reportSuccess()
#endif // OS(UNIX)
-size_t HeapStatistics::usedJSHeap()
-{
- JSGlobalData* globalData = &JSGlobalData::sharedInstance();
- return globalData->heap.size();
-}
-
size_t HeapStatistics::parseMemoryAmount(char* s)
{
size_t multiplier = 1;
diff --git a/Source/JavaScriptCore/heap/HeapStatistics.h b/Source/JavaScriptCore/heap/HeapStatistics.h
index 34d05af7c..0800f0c16 100644
--- a/Source/JavaScriptCore/heap/HeapStatistics.h
+++ b/Source/JavaScriptCore/heap/HeapStatistics.h
@@ -36,7 +36,6 @@ class HeapStatistics {
public:
NO_RETURN static void exitWithFailure();
JS_EXPORT_PRIVATE static void reportSuccess();
- JS_EXPORT_PRIVATE static size_t usedJSHeap();
static void initialize();
static void recordGCPauseTime(double start, double end);
diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp
index 49f9ec3b5..4eab17661 100644
--- a/Source/JavaScriptCore/jit/JIT.cpp
+++ b/Source/JavaScriptCore/jit/JIT.cpp
@@ -312,6 +312,7 @@ void JIT::privateCompileMainPass()
DEFINE_OP(op_neq)
DEFINE_OP(op_neq_null)
DEFINE_OP(op_new_array)
+ DEFINE_OP(op_new_array_with_size)
DEFINE_OP(op_new_array_buffer)
DEFINE_OP(op_new_func)
DEFINE_OP(op_new_func_exp)
diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h
index 3e16972e2..054718573 100644
--- a/Source/JavaScriptCore/jit/JIT.h
+++ b/Source/JavaScriptCore/jit/JIT.h
@@ -718,6 +718,7 @@ namespace JSC {
void emit_op_neq(Instruction*);
void emit_op_neq_null(Instruction*);
void emit_op_new_array(Instruction*);
+ void emit_op_new_array_with_size(Instruction*);
void emit_op_new_array_buffer(Instruction*);
void emit_op_new_func(Instruction*);
void emit_op_new_func_exp(Instruction*);
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index 33db1d44f..c187e4725 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -1694,6 +1694,17 @@ void JIT::emitSlow_op_new_array(Instruction* currentInstruction, Vector<SlowCase
stubCall.call(currentInstruction[1].u.operand);
}
+void JIT::emit_op_new_array_with_size(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_new_array_with_size);
+#if USE(JSVALUE64)
+ stubCall.addArgument(currentInstruction[2].u.operand, regT2);
+#else
+ stubCall.addArgument(currentInstruction[2].u.operand);
+#endif
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
void JIT::emit_op_new_array_buffer(Instruction* currentInstruction)
{
JITStubCall stubCall(this, cti_op_new_array_buffer);
diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
index 9deded62a..8a4017f1d 100644
--- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
+++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
@@ -278,7 +278,7 @@ void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowC
linkSlowCase(iter);
linkSlowCase(iter);
- JITStubCall stubCall(this, cti_op_get_by_val);
+ JITStubCall stubCall(this, cti_op_get_by_val_generic);
stubCall.addArgument(base, regT2);
stubCall.addArgument(property, regT2);
stubCall.call(dst);
diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
index e7c4a479b..a4a547889 100644
--- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
@@ -1226,7 +1226,7 @@ void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowC
linkSlowCase(iter);
linkSlowCase(iter);
- JITStubCall stubCall(this, cti_op_get_by_val);
+ JITStubCall stubCall(this, cti_op_get_by_val_generic);
stubCall.addArgument(base);
stubCall.addArgument(property);
stubCall.call(dst);
diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp
index 1a2c654bc..f1f2f4c9d 100644
--- a/Source/JavaScriptCore/jit/JITStubs.cpp
+++ b/Source/JavaScriptCore/jit/JITStubs.cpp
@@ -35,6 +35,7 @@
#include "CommonSlowPaths.h"
#include "Arguments.h"
+#include "ArrayConstructor.h"
#include "CallFrame.h"
#include "CodeBlock.h"
#include "CodeProfiling.h"
@@ -2360,6 +2361,13 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
return constructArray(stackFrame.callFrame, reinterpret_cast<JSValue*>(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()]), stackFrame.args[1].int32());
}
+DEFINE_STUB_FUNCTION(JSObject*, op_new_array_with_size)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return constructArrayWithSizeQuirk(stackFrame.callFrame, stackFrame.callFrame->lexicalGlobalObject(), stackFrame.args[0].jsValue());
+}
+
DEFINE_STUB_FUNCTION(JSObject*, op_new_array_buffer)
{
STUB_INIT_STACK_FRAME(stackFrame);
diff --git a/Source/JavaScriptCore/jit/JITStubs.h b/Source/JavaScriptCore/jit/JITStubs.h
index ecf415d1f..4a3b252d6 100644
--- a/Source/JavaScriptCore/jit/JITStubs.h
+++ b/Source/JavaScriptCore/jit/JITStubs.h
@@ -413,6 +413,7 @@ extern "C" {
EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION) WTF_INTERNAL;
EncodedJSValue JIT_STUB cti_to_object(STUB_ARGS_DECLARATION) WTF_INTERNAL;
JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+ JSObject* JIT_STUB cti_op_new_array_with_size(STUB_ARGS_DECLARATION) WTF_INTERNAL;
JSObject* JIT_STUB cti_op_new_array_buffer(STUB_ARGS_DECLARATION) WTF_INTERNAL;
JSObject* JIT_STUB cti_op_new_func(STUB_ARGS_DECLARATION) WTF_INTERNAL;
JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS_DECLARATION) WTF_INTERNAL;
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
index 5a9b41da7..fbf5b8598 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
@@ -29,6 +29,7 @@
#if ENABLE(LLINT)
#include "Arguments.h"
+#include "ArrayConstructor.h"
#include "CallFrame.h"
#include "CommonSlowPaths.h"
#include "GetterSetter.h"
@@ -504,6 +505,12 @@ LLINT_SLOW_PATH_DECL(slow_path_new_array)
LLINT_RETURN(constructArray(exec, bitwise_cast<JSValue*>(&LLINT_OP(2)), pc[3].u.operand));
}
+LLINT_SLOW_PATH_DECL(slow_path_new_array_with_size)
+{
+ LLINT_BEGIN();
+ LLINT_RETURN(constructArrayWithSizeQuirk(exec, exec->lexicalGlobalObject(), LLINT_OP_C(2).jsValue()));
+}
+
LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer)
{
LLINT_BEGIN();
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.h b/Source/JavaScriptCore/llint/LLIntSlowPaths.h
index 5bfb0ccdf..3d770f3c5 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.h
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.h
@@ -121,6 +121,7 @@ LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_create_this);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_convert_this);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_object);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_array);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_array_with_size);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_array_buffer);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_regexp);
LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_not);
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
index a971abf4f..ad509e05d 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
@@ -428,6 +428,12 @@ _llint_op_new_array:
dispatch(4)
+_llint_op_new_array_with_size:
+ traceExecution()
+ callSlowPath(_llint_slow_path_new_array_with_size)
+ dispatch(3)
+
+
_llint_op_new_array_buffer:
traceExecution()
callSlowPath(_llint_slow_path_new_array_buffer)
diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp
index a13648442..5c2cd7167 100644
--- a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp
@@ -77,17 +77,24 @@ bool ArrayConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exe
// ------------------------------ Functions ---------------------------
+JSObject* constructArrayWithSizeQuirk(ExecState* exec, JSGlobalObject* globalObject, JSValue length)
+{
+ if (!length.isNumber())
+ return constructArray(exec, globalObject, &length, 1);
+
+ uint32_t n = length.toUInt32(exec);
+ if (n != length.toNumber(exec))
+ return throwError(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer.")));
+ return constructEmptyArray(exec, globalObject, n);
+}
+
static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args)
{
JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
// a single numeric argument denotes the array size (!)
- if (args.size() == 1 && args.at(0).isNumber()) {
- uint32_t n = args.at(0).toUInt32(exec);
- if (n != args.at(0).toNumber(exec))
- return throwError(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer.")));
- return constructEmptyArray(exec, globalObject, n);
- }
+ if (args.size() == 1)
+ return constructArrayWithSizeQuirk(exec, globalObject, args.at(0));
// otherwise the array is constructed with the arguments in it
return constructArray(exec, globalObject, args);
diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.h b/Source/JavaScriptCore/runtime/ArrayConstructor.h
index b223a0f13..dcbf0a1b3 100644
--- a/Source/JavaScriptCore/runtime/ArrayConstructor.h
+++ b/Source/JavaScriptCore/runtime/ArrayConstructor.h
@@ -26,6 +26,7 @@
namespace JSC {
class ArrayPrototype;
+ class JSArray;
class ArrayConstructor : public InternalFunction {
public:
@@ -59,6 +60,8 @@ namespace JSC {
static CallType getCallData(JSCell*, CallData&);
};
+ JSObject* constructArrayWithSizeQuirk(ExecState*, JSGlobalObject*, JSValue);
+
} // namespace JSC
#endif // ArrayConstructor_h
diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.h b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
index e15335ef0..ae3b45b8c 100644
--- a/Source/JavaScriptCore/runtime/CommonIdentifiers.h
+++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
@@ -29,6 +29,7 @@
#define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
macro(apply) \
macro(arguments) \
+ macro(Array) \
macro(bind) \
macro(call) \
macro(callee) \
@@ -54,6 +55,7 @@
macro(multiline) \
macro(name) \
macro(now) \
+ macro(Object) \
macro(parse) \
macro(propertyIsEnumerable) \
macro(prototype) \
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 9eb266135..03252fad1 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -289,9 +289,9 @@ void JSGlobalObject::reset(JSValue prototype)
m_regExpPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum);
m_errorPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Object"), objectConstructor, DontEnum);
+ putDirectWithoutTransition(exec->globalData(), exec->propertyNames().Object, objectConstructor, DontEnum);
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Function"), functionConstructor, DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Array"), arrayConstructor, DontEnum);
+ putDirectWithoutTransition(exec->globalData(), exec->propertyNames().Array, arrayConstructor, DontEnum);
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum);
putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum);
@@ -320,6 +320,8 @@ void JSGlobalObject::reset(JSValue prototype)
m_specialPointers[Special::CallFunction] = m_callFunction.get();
m_specialPointers[Special::ApplyFunction] = m_applyFunction.get();
+ m_specialPointers[Special::ObjectConstructor] = objectConstructor;
+ m_specialPointers[Special::ArrayConstructor] = arrayConstructor;
if (m_experimentsEnabled) {
NamePrototype* privateNamePrototype = NamePrototype::create(exec, NamePrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()));
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp
index 1540177be..4d3ccfda2 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp
@@ -280,7 +280,7 @@ static ALWAYS_INLINE JSValue jsSpliceSubstrings(ExecState* exec, JSString* sourc
if (position <= 0 && length >= sourceSize)
return sourceVal;
// We could call String::substringSharingImpl(), but this would result in redundant checks.
- return jsString(exec, StringImpl::create(source.impl(), max(0, position), min(sourceSize, length)));
+ return jsString(exec, StringImpl::create(source.impl(), std::max(0, position), std::min(sourceSize, length)));
}
int totalLength = 0;
@@ -335,7 +335,7 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J
if (position <= 0 && length >= sourceSize)
return sourceVal;
// We could call String::substringSharingImpl(), but this would result in redundant checks.
- return jsString(exec, StringImpl::create(source.impl(), max(0, position), min(sourceSize, length)));
+ return jsString(exec, StringImpl::create(source.impl(), std::max(0, position), std::min(sourceSize, length)));
}
int totalLength = 0;
@@ -359,7 +359,7 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J
if (!impl)
return throwOutOfMemoryError(exec);
- int maxCount = max(rangeCount, separatorCount);
+ int maxCount = std::max(rangeCount, separatorCount);
int bufferPos = 0;
for (int i = 0; i < maxCount; i++) {
if (i < rangeCount) {
@@ -384,18 +384,24 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J
if (!impl)
return throwOutOfMemoryError(exec);
- int maxCount = max(rangeCount, separatorCount);
+ int maxCount = std::max(rangeCount, separatorCount);
int bufferPos = 0;
for (int i = 0; i < maxCount; i++) {
if (i < rangeCount) {
if (int srcLen = substringRanges[i].length) {
- StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, srcLen);
+ if (source.is8Bit())
+ StringImpl::copyChars(buffer + bufferPos, source.characters8() + substringRanges[i].position, srcLen);
+ else
+ StringImpl::copyChars(buffer + bufferPos, source.characters16() + substringRanges[i].position, srcLen);
bufferPos += srcLen;
}
}
if (i < separatorCount) {
if (int sepLen = separators[i].length()) {
- StringImpl::copyChars(buffer + bufferPos, separators[i].characters(), sepLen);
+ if (separators[i].is8Bit())
+ StringImpl::copyChars(buffer + bufferPos, separators[i].characters8(), sepLen);
+ else
+ StringImpl::copyChars(buffer + bufferPos, separators[i].characters16(), sepLen);
bufferPos += sepLen;
}
}
@@ -767,7 +773,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec)
unsigned pos;
int len = s.length();
if (a1.isUInt32())
- pos = min<uint32_t>(a1.asUInt32(), len);
+ pos = std::min<uint32_t>(a1.asUInt32(), len);
else {
double dpos = a1.toInteger(exec);
if (dpos < 0)
diff --git a/Source/JavaScriptCore/yarr/YarrPattern.cpp b/Source/JavaScriptCore/yarr/YarrPattern.cpp
index 5080929f4..c953a38d2 100644
--- a/Source/JavaScriptCore/yarr/YarrPattern.cpp
+++ b/Source/JavaScriptCore/yarr/YarrPattern.cpp
@@ -657,8 +657,8 @@ public:
for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
PatternAlternative* alternative = disjunction->m_alternatives[alt];
unsigned currentAlternativeCallFrameSize = setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition);
- minimumInputSize = min(minimumInputSize, alternative->m_minimumSize);
- maximumCallFrameSize = max(maximumCallFrameSize, currentAlternativeCallFrameSize);
+ minimumInputSize = std::min(minimumInputSize, alternative->m_minimumSize);
+ maximumCallFrameSize = std::max(maximumCallFrameSize, currentAlternativeCallFrameSize);
hasFixedSize &= alternative->m_hasFixedSize;
}