diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-18 10:55:06 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-18 10:55:06 +0200 |
commit | ee4c86d1990a9e26277a6948e7027ad8d525ebfa (patch) | |
tree | 1e2d3408cd097606571f40ab63353c27bcb7dd5c /Source/JavaScriptCore | |
parent | d882bec96d0d30aeeda2141bfadfca7f038ee862 (diff) | |
download | qtwebkit-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')
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; } |