diff options
Diffstat (limited to 'Source/JavaScriptCore')
101 files changed, 5248 insertions, 1750 deletions
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt index 4b030ca40..146a11910 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt @@ -94,6 +94,7 @@ SET(JavaScriptCore_SOURCES dfg/DFGSpeculativeJIT.cpp dfg/DFGSpeculativeJIT32_64.cpp dfg/DFGSpeculativeJIT64.cpp + dfg/DFGStructureCheckHoistingPhase.cpp dfg/DFGThunks.cpp dfg/DFGValueSource.cpp dfg/DFGVariableEvent.cpp diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index c71b441e2..063b2f519 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,20 +1,2443 @@ -2012-06-13 Patrick Gansterer <paroga@webkit.org> +2012-08-10 Yong Li <yoli@rim.com> + + [BlackBerry] GCActivityCallback should always schedule GC even allocated bytes is a small number + https://bugs.webkit.org/show_bug.cgi?id=93650 + + Reviewed by Rob Buis. + + Even a small number of allocated JS objects could hold expensive resources. + + * runtime/GCActivityCallbackBlackBerry.cpp: + (JSC::DefaultGCActivityCallback::didAllocate): + +2012-08-09 Yong Li <yoli@rim.com> + + [QNX] Implement getCPUTime() for OS(QNX) + https://bugs.webkit.org/show_bug.cgi?id=93516 + + Reviewed by George Staikos. + + Implement getCPUTime() with CLOCK_THREAD_CPUTIME_ID so it will tell + exactly how long the current thread has spent without being impacted + by other things. + + * runtime/TimeoutChecker.cpp: + (JSC::getCPUTime): + +2012-08-08 Shane Stephens <shanestephens@google.com> + + Compile flag for CSS Hierarchies + https://bugs.webkit.org/show_bug.cgi?id=92433 + + Reviewed by Tony Chang. + + * Configurations/FeatureDefines.xcconfig: + +2012-08-08 Benjamin Poulain <bpoulain@apple.com> + + Use char* instead of LChar* for the public interface of String construction from literals + https://bugs.webkit.org/show_bug.cgi?id=93402 + + Reviewed by Michael Saboff. + + Update JSC' Identifier to use StringImpl::createFromLiteral with a char*. + + * runtime/Identifier.cpp: + (JSC::IdentifierASCIIStringTranslator::translate): + +2012-08-08 Patrick Gansterer <paroga@webkit.org> + + Remove ce_time.(cpp|h) from list of source files + https://bugs.webkit.org/show_bug.cgi?id=93446 + + Reviewed by Simon Hausmann. + + r125004 removed the last dependency on functions defined in ce_time.cpp. + + * Target.pri: + +2012-08-08 Patrick Gansterer <paroga@webkit.org> + + [WIN] Use GetTimeZoneInformation() for getting the timezone name + https://bugs.webkit.org/show_bug.cgi?id=91936 + + Reviewed by Ryosuke Niwa. + + The MS CRT implementation of strftime calls the same functions in the background. + Using them directly avoids the overhead of parsing the format string and removes + the dependency on strftime() for WinCE where this function does not exist. + + * runtime/DateConversion.cpp: + (JSC::formatTime): + +2012-08-07 Gabor Ballabas <gaborb@inf.u-szeged.hu> + + Refactor magic numbers in the ARM port of DFG-JIT + https://bugs.webkit.org/show_bug.cgi?id=93348 + + Reviewed by Eric Seidel. + + Introduce new names for hard-coded magic numbers. + Refactor constant with confusing names to more descriptive ones. + + * assembler/ARMAssembler.cpp: + (JSC::ARMAssembler::patchConstantPoolLoad): + (JSC::ARMAssembler::getOp2): + (JSC::ARMAssembler::genInt): + (JSC::ARMAssembler::getImm): + (JSC::ARMAssembler::moveImm): + (JSC::ARMAssembler::encodeComplexImm): + (JSC::ARMAssembler::dataTransfer32): + (JSC::ARMAssembler::dataTransfer16): + (JSC::ARMAssembler::dataTransferFloat): + (JSC::ARMAssembler::executableCopy): + * assembler/ARMAssembler.h: + (JSC::ARMAssembler::emitInstruction): + (JSC::ARMAssembler::ands_r): + (JSC::ARMAssembler::eors_r): + (JSC::ARMAssembler::subs_r): + (JSC::ARMAssembler::rsbs_r): + (JSC::ARMAssembler::adds_r): + (JSC::ARMAssembler::adcs_r): + (JSC::ARMAssembler::sbcs_r): + (JSC::ARMAssembler::rscs_r): + (JSC::ARMAssembler::tst_r): + (JSC::ARMAssembler::teq_r): + (JSC::ARMAssembler::cmp_r): + (JSC::ARMAssembler::cmn_r): + (JSC::ARMAssembler::orrs_r): + (JSC::ARMAssembler::movs_r): + (JSC::ARMAssembler::bics_r): + (JSC::ARMAssembler::mvns_r): + (JSC::ARMAssembler::muls_r): + (JSC::ARMAssembler::ldr_imm): + (JSC::ARMAssembler::ldr_un_imm): + (JSC::ARMAssembler::dtr_u): + (JSC::ARMAssembler::dtr_ur): + (JSC::ARMAssembler::dtr_dr): + (JSC::ARMAssembler::dtrh_u): + (JSC::ARMAssembler::dtrh_ur): + (JSC::ARMAssembler::fdtr_u): + (JSC::ARMAssembler::push_r): + (JSC::ARMAssembler::pop_r): + (JSC::ARMAssembler::getLdrImmAddress): + (JSC::ARMAssembler::getLdrImmAddressOnPool): + (JSC::ARMAssembler::patchConstantPoolLoad): + (JSC::ARMAssembler::repatchCompact): + (JSC::ARMAssembler::replaceWithJump): + (JSC::ARMAssembler::replaceWithLoad): + (JSC::ARMAssembler::replaceWithAddressComputation): + (JSC::ARMAssembler::getOp2Byte): + (JSC::ARMAssembler::getOp2Half): + (JSC::ARMAssembler::getImm16Op2): + (JSC::ARMAssembler::placeConstantPoolBarrier): + (JSC::ARMAssembler::getConditionalField): + * assembler/MacroAssemblerARM.cpp: + (JSC::MacroAssemblerARM::load32WithUnalignedHalfWords): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::and32): + (JSC::MacroAssemblerARM::branch32): + (JSC::MacroAssemblerARM::branchTest32): + (JSC::MacroAssemblerARM::branchTruncateDoubleToInt32): + +2012-08-07 Benjamin Poulain <benjamin@webkit.org> + + Use the initialization from literal for JSC's Identifiers + https://bugs.webkit.org/show_bug.cgi?id=93193 + + Reviewed by Geoffrey Garen. + + This patches modify Identifier ot take advantage of the new initialization from literal. + + In addition to the memory savings (~600bytes per instance), this gives us a 2% speed + improvement on CommonIdentifiers on average. + + * runtime/CommonIdentifiers.cpp: + (JSC::CommonIdentifiers::CommonIdentifiers): + Null and empty strings are forbidden for literal initialization. Use the most efficient constructors + instead of a literal. + + * runtime/Identifier.cpp: + (IdentifierASCIIStringTranslator): + Rename IdentifierCStringTranslator to IdentifierASCIIStringTranslator to make the text encoding + explicit. + (JSC::IdentifierASCIIStringTranslator::hash): + (JSC::IdentifierASCIIStringTranslator::equal): + (JSC::IdentifierASCIIStringTranslator::translate): Use the fast initialization from literal. + (JSC::Identifier::add): + * runtime/Identifier.h: + (JSC::Identifier::Identifier): + +2012-08-07 Simon Hausmann <simon.hausmann@nokia.com> + + [Qt][Win] Remove pthreads linkage + + Reviewed by Csaba Osztrogonác. + + After r124823 linkage to pthreads is not needed anymore for the Windows + build. + + * JavaScriptCore.pri: + +2012-08-07 Gabor Ballabas <gaborb@inf.u-szeged.hu> + + Refactor emit*Inst functions and introduce toARMWord functions in DFG-JIT's traditional ARM port + https://bugs.webkit.org/show_bug.cgi?id=93266 + + Reviewed by Csaba Osztrogonác. + + First part of a bigger refactoring issue trying to make traditional + ARM DFG-JIT port easier to read and understand. + + + * assembler/ARMAssembler.h: + (JSC::ARMAssembler::emitInstruction): + (JSC::ARMAssembler::emitDoublePrecisionInstruction): + (JSC::ARMAssembler::emitSinglePrecisionInstruction): + (JSC::ARMAssembler::and_r): + (JSC::ARMAssembler::ands_r): + (JSC::ARMAssembler::eor_r): + (JSC::ARMAssembler::eors_r): + (JSC::ARMAssembler::sub_r): + (JSC::ARMAssembler::subs_r): + (JSC::ARMAssembler::rsb_r): + (JSC::ARMAssembler::rsbs_r): + (JSC::ARMAssembler::add_r): + (JSC::ARMAssembler::adds_r): + (JSC::ARMAssembler::adc_r): + (JSC::ARMAssembler::adcs_r): + (JSC::ARMAssembler::sbc_r): + (JSC::ARMAssembler::sbcs_r): + (JSC::ARMAssembler::rsc_r): + (JSC::ARMAssembler::rscs_r): + (JSC::ARMAssembler::tst_r): + (JSC::ARMAssembler::teq_r): + (JSC::ARMAssembler::cmp_r): + (JSC::ARMAssembler::cmn_r): + (JSC::ARMAssembler::orr_r): + (JSC::ARMAssembler::orrs_r): + (JSC::ARMAssembler::mov_r): + (JSC::ARMAssembler::movw_r): + (JSC::ARMAssembler::movt_r): + (JSC::ARMAssembler::movs_r): + (JSC::ARMAssembler::bic_r): + (JSC::ARMAssembler::bics_r): + (JSC::ARMAssembler::mvn_r): + (JSC::ARMAssembler::mvns_r): + (JSC::ARMAssembler::mul_r): + (JSC::ARMAssembler::muls_r): + (JSC::ARMAssembler::mull_r): + (JSC::ARMAssembler::vmov_f64_r): + (JSC::ARMAssembler::vadd_f64_r): + (JSC::ARMAssembler::vdiv_f64_r): + (JSC::ARMAssembler::vsub_f64_r): + (JSC::ARMAssembler::vmul_f64_r): + (JSC::ARMAssembler::vcmp_f64_r): + (JSC::ARMAssembler::vsqrt_f64_r): + (JSC::ARMAssembler::vabs_f64_r): + (JSC::ARMAssembler::vneg_f64_r): + (JSC::ARMAssembler::ldr_imm): + (JSC::ARMAssembler::ldr_un_imm): + (JSC::ARMAssembler::dtr_u): + (JSC::ARMAssembler::dtr_ur): + (JSC::ARMAssembler::dtr_d): + (JSC::ARMAssembler::dtr_dr): + (JSC::ARMAssembler::dtrh_u): + (JSC::ARMAssembler::dtrh_ur): + (JSC::ARMAssembler::dtrh_d): + (JSC::ARMAssembler::dtrh_dr): + (JSC::ARMAssembler::fdtr_u): + (JSC::ARMAssembler::fdtr_d): + (JSC::ARMAssembler::push_r): + (JSC::ARMAssembler::pop_r): + (JSC::ARMAssembler::vmov_vfp64_r): + (JSC::ARMAssembler::vmov_arm64_r): + (JSC::ARMAssembler::vmov_vfp32_r): + (JSC::ARMAssembler::vmov_arm32_r): + (JSC::ARMAssembler::vcvt_f64_s32_r): + (JSC::ARMAssembler::vcvt_s32_f64_r): + (JSC::ARMAssembler::vcvt_u32_f64_r): + (JSC::ARMAssembler::vcvt_f64_f32_r): + (JSC::ARMAssembler::vcvt_f32_f64_r): + (JSC::ARMAssembler::vmrs_apsr): + (JSC::ARMAssembler::clz_r): + (JSC::ARMAssembler::bx): + (JSC::ARMAssembler::blx): + (JSC::ARMAssembler::linkJump): + (JSC::ARMAssembler::toARMWord): + (ARMAssembler): + +2012-08-06 Patrick Gansterer <paroga@webkit.org> [WIN] Remove dependency on pthread from MachineStackMarker https://bugs.webkit.org/show_bug.cgi?id=68429 - Reviewed by NOBODY (OOPS!). + Reviewed by Geoffrey Garen. - Implement pthread TLS functionality with native windows functions. + Windows has no support for calling a destructor for thread specific data. + Since we need more control over creating and deleting thread specific keys + we can not simply extend WTF::ThreadSpecific with this functionality. - * heap/MachineStackMarker.cpp: Use the new functions instead of pthread directly. + All thread specific keys created via the new API get stored in a list. + After a thread function finished we iterate over this list and call + the registered destructor for every item if needed. + + * heap/MachineStackMarker.cpp: Use the new functions instead of pthread directly. + (JSC::MachineThreads::~MachineThreads): + (JSC::MachineThreads::makeUsableFromMultipleThreads): + (JSC::MachineThreads::addCurrentThread): * heap/MachineStackMarker.h: - * wtf/ThreadSpecific.h: - (WTF::ThreadSpecificKeyCreate): Added wrapper around pthread_key_create. - (WTF::ThreadSpecificKeyDelete): Added wrapper around pthread_key_delete. - (WTF::ThreadSpecificSet): Added wrapper around pthread_setspecific. - (WTF::ThreadSpecificGet): Added wrapper around pthread_getspecific. - * wtf/ThreadSpecificWin.cpp: + (MachineThreads): + +2012-08-06 Patrick Gansterer <paroga@webkit.org> + + Unify JSC date and time formating functions + https://bugs.webkit.org/show_bug.cgi?id=92282 + + Reviewed by Geoffrey Garen. + + Replace the existing functions for formating GregorianDateTime + with one single function. This removes some code duplications + in DatePrototype and is a preperation to fix encoding issues, + since we can add UChar* values to the resulting string now. + + * runtime/DateConstructor.cpp: + (JSC::callDate): + * runtime/DateConversion.cpp: + (JSC::formatDateTime): + * runtime/DateConversion.h: + (JSC): + * runtime/DatePrototype.cpp: + (JSC::formateDateInstance): + (JSC::dateProtoFuncToString): + (JSC::dateProtoFuncToUTCString): + (JSC::dateProtoFuncToDateString): + (JSC::dateProtoFuncToTimeString): + (JSC::dateProtoFuncToGMTString): + +2012-08-06 Carlos Garcia Campos <cgarcia@igalia.com> + + Unreviewed. Fix make distcheck. + + * GNUmakefile.list.am: Add missing header file. + +2012-08-05 Peter Wang <peter.wang@torchmobile.com.cn> + + Web Inspector: [JSC] implement setting breakpoints by line:column + https://bugs.webkit.org/show_bug.cgi?id=53003 + + Reviewed by Geoffrey Garen. + + Add a counter to Lexer to record the column info of each Token. Add a column parameter to + op_debug, cti_op_debug, and _llint_op_debug byte-code command. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + * bytecode/Opcode.h: + (JSC): + (JSC::padOpcodeName): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::resolve): + (JSC::BytecodeGenerator::emitDebugHook): + * bytecompiler/BytecodeGenerator.h: + (BytecodeGenerator): + * bytecompiler/NodesCodegen.cpp: + (JSC::ArrayNode::toArgumentList): + (JSC::ApplyFunctionCallDotNode::emitBytecode): + (JSC::ConstStatementNode::emitBytecode): + (JSC::EmptyStatementNode::emitBytecode): + (JSC::DebuggerStatementNode::emitBytecode): + (JSC::ExprStatementNode::emitBytecode): + (JSC::VarStatementNode::emitBytecode): + (JSC::IfNode::emitBytecode): + (JSC::IfElseNode::emitBytecode): + (JSC::DoWhileNode::emitBytecode): + (JSC::WhileNode::emitBytecode): + (JSC::ForNode::emitBytecode): + (JSC::ForInNode::emitBytecode): + (JSC::ContinueNode::emitBytecode): + (JSC::BreakNode::emitBytecode): + (JSC::ReturnNode::emitBytecode): + (JSC::WithNode::emitBytecode): + (JSC::SwitchNode::emitBytecode): + (JSC::LabelNode::emitBytecode): + (JSC::ThrowNode::emitBytecode): + (JSC::TryNode::emitBytecode): + (JSC::ProgramNode::emitBytecode): + (JSC::EvalNode::emitBytecode): + (JSC::FunctionBodyNode::emitBytecode): + * debugger/Debugger.h: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::unwindCallFrame): + (JSC::Interpreter::throwException): + (JSC::Interpreter::debug): + (JSC::Interpreter::privateExecute): + * interpreter/Interpreter.h: + (Interpreter): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_debug): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_debug): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + * llint/LowLevelInterpreter.asm: + * parser/ASTBuilder.h: + (ASTBuilder): + (JSC::ASTBuilder::createCommaExpr): + (JSC::ASTBuilder::createLogicalNot): + (JSC::ASTBuilder::createUnaryPlus): + (JSC::ASTBuilder::createVoid): + (JSC::ASTBuilder::thisExpr): + (JSC::ASTBuilder::createResolve): + (JSC::ASTBuilder::createObjectLiteral): + (JSC::ASTBuilder::createArray): + (JSC::ASTBuilder::createNumberExpr): + (JSC::ASTBuilder::createString): + (JSC::ASTBuilder::createBoolean): + (JSC::ASTBuilder::createNull): + (JSC::ASTBuilder::createBracketAccess): + (JSC::ASTBuilder::createDotAccess): + (JSC::ASTBuilder::createRegExp): + (JSC::ASTBuilder::createNewExpr): + (JSC::ASTBuilder::createConditionalExpr): + (JSC::ASTBuilder::createAssignResolve): + (JSC::ASTBuilder::createFunctionExpr): + (JSC::ASTBuilder::createFunctionBody): + (JSC::ASTBuilder::createGetterOrSetterProperty): + (JSC::ASTBuilder::createArgumentsList): + (JSC::ASTBuilder::createPropertyList): + (JSC::ASTBuilder::createFuncDeclStatement): + (JSC::ASTBuilder::createBlockStatement): + (JSC::ASTBuilder::createExprStatement): + (JSC::ASTBuilder::createIfStatement): + (JSC::ASTBuilder::createForLoop): + (JSC::ASTBuilder::createForInLoop): + (JSC::ASTBuilder::createEmptyStatement): + (JSC::ASTBuilder::createVarStatement): + (JSC::ASTBuilder::createReturnStatement): + (JSC::ASTBuilder::createBreakStatement): + (JSC::ASTBuilder::createContinueStatement): + (JSC::ASTBuilder::createTryStatement): + (JSC::ASTBuilder::createSwitchStatement): + (JSC::ASTBuilder::createWhileStatement): + (JSC::ASTBuilder::createDoWhileStatement): + (JSC::ASTBuilder::createLabelStatement): + (JSC::ASTBuilder::createWithStatement): + (JSC::ASTBuilder::createThrowStatement): + (JSC::ASTBuilder::createDebugger): + (JSC::ASTBuilder::createConstStatement): + (JSC::ASTBuilder::appendConstDecl): + (JSC::ASTBuilder::combineCommaNodes): + (JSC::ASTBuilder::appendBinaryOperation): + (JSC::ASTBuilder::createAssignment): + (JSC::ASTBuilder::createNumber): + (JSC::ASTBuilder::makeTypeOfNode): + (JSC::ASTBuilder::makeDeleteNode): + (JSC::ASTBuilder::makeNegateNode): + (JSC::ASTBuilder::makeBitwiseNotNode): + (JSC::ASTBuilder::makeMultNode): + (JSC::ASTBuilder::makeDivNode): + (JSC::ASTBuilder::makeModNode): + (JSC::ASTBuilder::makeAddNode): + (JSC::ASTBuilder::makeSubNode): + (JSC::ASTBuilder::makeLeftShiftNode): + (JSC::ASTBuilder::makeRightShiftNode): + (JSC::ASTBuilder::makeURightShiftNode): + (JSC::ASTBuilder::makeBitOrNode): + (JSC::ASTBuilder::makeBitAndNode): + (JSC::ASTBuilder::makeBitXOrNode): + (JSC::ASTBuilder::makeFunctionCallNode): + (JSC::ASTBuilder::makeBinaryNode): + (JSC::ASTBuilder::makeAssignNode): + (JSC::ASTBuilder::makePrefixNode): + (JSC::ASTBuilder::makePostfixNode): + * parser/Lexer.cpp: + (JSC::::setCode): + (JSC::::internalShift): + (JSC::::shift): + (JSC::::lex): + * parser/Lexer.h: + (Lexer): + (JSC::Lexer::currentColumnNumber): + (JSC::::lexExpectIdentifier): + * parser/NodeConstructors.h: + (JSC::Node::Node): + (JSC::ExpressionNode::ExpressionNode): + (JSC::StatementNode::StatementNode): + (JSC::NullNode::NullNode): + (JSC::BooleanNode::BooleanNode): + (JSC::NumberNode::NumberNode): + (JSC::StringNode::StringNode): + (JSC::RegExpNode::RegExpNode): + (JSC::ThisNode::ThisNode): + (JSC::ResolveNode::ResolveNode): + (JSC::ArrayNode::ArrayNode): + (JSC::PropertyListNode::PropertyListNode): + (JSC::ObjectLiteralNode::ObjectLiteralNode): + (JSC::BracketAccessorNode::BracketAccessorNode): + (JSC::DotAccessorNode::DotAccessorNode): + (JSC::ArgumentListNode::ArgumentListNode): + (JSC::NewExprNode::NewExprNode): + (JSC::EvalFunctionCallNode::EvalFunctionCallNode): + (JSC::FunctionCallValueNode::FunctionCallValueNode): + (JSC::FunctionCallResolveNode::FunctionCallResolveNode): + (JSC::FunctionCallBracketNode::FunctionCallBracketNode): + (JSC::FunctionCallDotNode::FunctionCallDotNode): + (JSC::CallFunctionCallDotNode::CallFunctionCallDotNode): + (JSC::ApplyFunctionCallDotNode::ApplyFunctionCallDotNode): + (JSC::PrePostResolveNode::PrePostResolveNode): + (JSC::PostfixResolveNode::PostfixResolveNode): + (JSC::PostfixBracketNode::PostfixBracketNode): + (JSC::PostfixDotNode::PostfixDotNode): + (JSC::PostfixErrorNode::PostfixErrorNode): + (JSC::DeleteResolveNode::DeleteResolveNode): + (JSC::DeleteBracketNode::DeleteBracketNode): + (JSC::DeleteDotNode::DeleteDotNode): + (JSC::DeleteValueNode::DeleteValueNode): + (JSC::VoidNode::VoidNode): + (JSC::TypeOfResolveNode::TypeOfResolveNode): + (JSC::TypeOfValueNode::TypeOfValueNode): + (JSC::PrefixResolveNode::PrefixResolveNode): + (JSC::PrefixBracketNode::PrefixBracketNode): + (JSC::PrefixDotNode::PrefixDotNode): + (JSC::PrefixErrorNode::PrefixErrorNode): + (JSC::UnaryOpNode::UnaryOpNode): + (JSC::UnaryPlusNode::UnaryPlusNode): + (JSC::NegateNode::NegateNode): + (JSC::BitwiseNotNode::BitwiseNotNode): + (JSC::LogicalNotNode::LogicalNotNode): + (JSC::BinaryOpNode::BinaryOpNode): + (JSC::MultNode::MultNode): + (JSC::DivNode::DivNode): + (JSC::ModNode::ModNode): + (JSC::AddNode::AddNode): + (JSC::SubNode::SubNode): + (JSC::LeftShiftNode::LeftShiftNode): + (JSC::RightShiftNode::RightShiftNode): + (JSC::UnsignedRightShiftNode::UnsignedRightShiftNode): + (JSC::LessNode::LessNode): + (JSC::GreaterNode::GreaterNode): + (JSC::LessEqNode::LessEqNode): + (JSC::GreaterEqNode::GreaterEqNode): + (JSC::ThrowableBinaryOpNode::ThrowableBinaryOpNode): + (JSC::InstanceOfNode::InstanceOfNode): + (JSC::InNode::InNode): + (JSC::EqualNode::EqualNode): + (JSC::NotEqualNode::NotEqualNode): + (JSC::StrictEqualNode::StrictEqualNode): + (JSC::NotStrictEqualNode::NotStrictEqualNode): + (JSC::BitAndNode::BitAndNode): + (JSC::BitOrNode::BitOrNode): + (JSC::BitXOrNode::BitXOrNode): + (JSC::LogicalOpNode::LogicalOpNode): + (JSC::ConditionalNode::ConditionalNode): + (JSC::ReadModifyResolveNode::ReadModifyResolveNode): + (JSC::AssignResolveNode::AssignResolveNode): + (JSC::ReadModifyBracketNode::ReadModifyBracketNode): + (JSC::AssignBracketNode::AssignBracketNode): + (JSC::AssignDotNode::AssignDotNode): + (JSC::ReadModifyDotNode::ReadModifyDotNode): + (JSC::AssignErrorNode::AssignErrorNode): + (JSC::CommaNode::CommaNode): + (JSC::ConstStatementNode::ConstStatementNode): + (JSC::EmptyStatementNode::EmptyStatementNode): + (JSC::DebuggerStatementNode::DebuggerStatementNode): + (JSC::ExprStatementNode::ExprStatementNode): + (JSC::VarStatementNode::VarStatementNode): + (JSC::IfNode::IfNode): + (JSC::IfElseNode::IfElseNode): + (JSC::DoWhileNode::DoWhileNode): + (JSC::WhileNode::WhileNode): + (JSC::ForNode::ForNode): + (JSC::ContinueNode::ContinueNode): + (JSC::BreakNode::BreakNode): + (JSC::ReturnNode::ReturnNode): + (JSC::WithNode::WithNode): + (JSC::LabelNode::LabelNode): + (JSC::ThrowNode::ThrowNode): + (JSC::TryNode::TryNode): + (JSC::FuncExprNode::FuncExprNode): + (JSC::FuncDeclNode::FuncDeclNode): + (JSC::SwitchNode::SwitchNode): + (JSC::ConstDeclNode::ConstDeclNode): + (JSC::BlockNode::BlockNode): + (JSC::ForInNode::ForInNode): + * parser/Nodes.cpp: + (JSC::StatementNode::setLoc): + (JSC): + (JSC::ScopeNode::ScopeNode): + (JSC::ProgramNode::ProgramNode): + (JSC::ProgramNode::create): + (JSC::EvalNode::EvalNode): + (JSC::EvalNode::create): + (JSC::FunctionBodyNode::FunctionBodyNode): + (JSC::FunctionBodyNode::create): + * parser/Nodes.h: + (Node): + (JSC::Node::columnNo): + (ExpressionNode): + (StatementNode): + (JSC::StatementNode::column): + (NullNode): + (BooleanNode): + (NumberNode): + (StringNode): + (RegExpNode): + (ThisNode): + (ResolveNode): + (ArrayNode): + (PropertyListNode): + (ObjectLiteralNode): + (BracketAccessorNode): + (DotAccessorNode): + (ArgumentListNode): + (NewExprNode): + (EvalFunctionCallNode): + (FunctionCallValueNode): + (FunctionCallResolveNode): + (FunctionCallBracketNode): + (FunctionCallDotNode): + (CallFunctionCallDotNode): + (ApplyFunctionCallDotNode): + (PrePostResolveNode): + (PostfixResolveNode): + (PostfixBracketNode): + (PostfixDotNode): + (PostfixErrorNode): + (DeleteResolveNode): + (DeleteBracketNode): + (DeleteDotNode): + (DeleteValueNode): + (VoidNode): + (TypeOfResolveNode): + (TypeOfValueNode): + (PrefixResolveNode): + (PrefixBracketNode): + (PrefixDotNode): + (PrefixErrorNode): + (UnaryOpNode): + (UnaryPlusNode): + (NegateNode): + (BitwiseNotNode): + (LogicalNotNode): + (BinaryOpNode): + (MultNode): + (DivNode): + (ModNode): + (AddNode): + (SubNode): + (LeftShiftNode): + (RightShiftNode): + (UnsignedRightShiftNode): + (LessNode): + (GreaterNode): + (LessEqNode): + (GreaterEqNode): + (ThrowableBinaryOpNode): + (InstanceOfNode): + (InNode): + (EqualNode): + (NotEqualNode): + (StrictEqualNode): + (NotStrictEqualNode): + (BitAndNode): + (BitOrNode): + (BitXOrNode): + (LogicalOpNode): + (ConditionalNode): + (ReadModifyResolveNode): + (AssignResolveNode): + (ReadModifyBracketNode): + (AssignBracketNode): + (AssignDotNode): + (ReadModifyDotNode): + (AssignErrorNode): + (CommaNode): + (ConstDeclNode): + (ConstStatementNode): + (BlockNode): + (EmptyStatementNode): + (DebuggerStatementNode): + (ExprStatementNode): + (VarStatementNode): + (IfNode): + (IfElseNode): + (DoWhileNode): + (WhileNode): + (ForNode): + (ForInNode): + (ContinueNode): + (BreakNode): + (ReturnNode): + (WithNode): + (LabelNode): + (ThrowNode): + (TryNode): + (ScopeNode): + (ProgramNode): + (EvalNode): + (FunctionBodyNode): + (FuncExprNode): + (FuncDeclNode): + (SwitchNode): + * parser/Parser.cpp: + (JSC::::parseSourceElements): + (JSC::::parseVarDeclaration): + (JSC::::parseConstDeclaration): + (JSC::::parseDoWhileStatement): + (JSC::::parseWhileStatement): + (JSC::::parseVarDeclarationList): + (JSC::::parseConstDeclarationList): + (JSC::::parseForStatement): + (JSC::::parseBreakStatement): + (JSC::::parseContinueStatement): + (JSC::::parseReturnStatement): + (JSC::::parseThrowStatement): + (JSC::::parseWithStatement): + (JSC::::parseSwitchStatement): + (JSC::::parseTryStatement): + (JSC::::parseDebuggerStatement): + (JSC::::parseBlockStatement): + (JSC::::parseStatement): + (JSC::::parseFunctionBody): + (JSC::::parseFunctionInfo): + (JSC::::parseFunctionDeclaration): + (JSC::::parseExpressionOrLabelStatement): + (JSC::::parseExpressionStatement): + (JSC::::parseIfStatement): + (JSC::::parseExpression): + (JSC::::parseAssignmentExpression): + (JSC::::parseConditionalExpression): + (JSC::::parseBinaryExpression): + (JSC::::parseProperty): + (JSC::::parseObjectLiteral): + (JSC::::parseStrictObjectLiteral): + (JSC::::parseArrayLiteral): + (JSC::::parsePrimaryExpression): + (JSC::::parseArguments): + (JSC::::parseMemberExpression): + (JSC::::parseUnaryExpression): + * parser/Parser.h: + (JSC::Parser::next): + (JSC::Parser::nextExpectIdentifier): + (JSC::Parser::tokenStart): + (JSC::Parser::tokenLine): + (JSC::Parser::tokenEnd): + (JSC::Parser::tokenLocation): + (Parser): + (JSC::Parser::getTokenName): + (JSC::::parse): + * parser/ParserTokens.h: + (JSC::JSTokenLocation::JSTokenLocation): + (JSTokenLocation): + (JSToken): + * parser/SourceProviderCacheItem.h: + (JSC::SourceProviderCacheItem::closeBraceToken): + * parser/SyntaxChecker.h: + (JSC::SyntaxChecker::makeFunctionCallNode): + (JSC::SyntaxChecker::createCommaExpr): + (JSC::SyntaxChecker::makeAssignNode): + (JSC::SyntaxChecker::makePrefixNode): + (JSC::SyntaxChecker::makePostfixNode): + (JSC::SyntaxChecker::makeTypeOfNode): + (JSC::SyntaxChecker::makeDeleteNode): + (JSC::SyntaxChecker::makeNegateNode): + (JSC::SyntaxChecker::makeBitwiseNotNode): + (JSC::SyntaxChecker::createLogicalNot): + (JSC::SyntaxChecker::createUnaryPlus): + (JSC::SyntaxChecker::createVoid): + (JSC::SyntaxChecker::thisExpr): + (JSC::SyntaxChecker::createResolve): + (JSC::SyntaxChecker::createObjectLiteral): + (JSC::SyntaxChecker::createArray): + (JSC::SyntaxChecker::createNumberExpr): + (JSC::SyntaxChecker::createString): + (JSC::SyntaxChecker::createBoolean): + (JSC::SyntaxChecker::createNull): + (JSC::SyntaxChecker::createBracketAccess): + (JSC::SyntaxChecker::createDotAccess): + (JSC::SyntaxChecker::createRegExp): + (JSC::SyntaxChecker::createNewExpr): + (JSC::SyntaxChecker::createConditionalExpr): + (JSC::SyntaxChecker::createAssignResolve): + (JSC::SyntaxChecker::createFunctionExpr): + (JSC::SyntaxChecker::createFunctionBody): + (JSC::SyntaxChecker::createArgumentsList): + (JSC::SyntaxChecker::createPropertyList): + (JSC::SyntaxChecker::createFuncDeclStatement): + (JSC::SyntaxChecker::createBlockStatement): + (JSC::SyntaxChecker::createExprStatement): + (JSC::SyntaxChecker::createIfStatement): + (JSC::SyntaxChecker::createForLoop): + (JSC::SyntaxChecker::createForInLoop): + (JSC::SyntaxChecker::createEmptyStatement): + (JSC::SyntaxChecker::createVarStatement): + (JSC::SyntaxChecker::createReturnStatement): + (JSC::SyntaxChecker::createBreakStatement): + (JSC::SyntaxChecker::createContinueStatement): + (JSC::SyntaxChecker::createTryStatement): + (JSC::SyntaxChecker::createSwitchStatement): + (JSC::SyntaxChecker::createWhileStatement): + (JSC::SyntaxChecker::createWithStatement): + (JSC::SyntaxChecker::createDoWhileStatement): + (JSC::SyntaxChecker::createLabelStatement): + (JSC::SyntaxChecker::createThrowStatement): + (JSC::SyntaxChecker::createDebugger): + (JSC::SyntaxChecker::createConstStatement): + (JSC::SyntaxChecker::appendConstDecl): + (JSC::SyntaxChecker::createGetterOrSetterProperty): + (JSC::SyntaxChecker::combineCommaNodes): + (JSC::SyntaxChecker::operatorStackPop): + +2012-08-03 Filip Pizlo <fpizlo@apple.com> + + Crashes in dfgBuildPutByIdList when clicking on just about anything on Google Maps + https://bugs.webkit.org/show_bug.cgi?id=92691 + + Reviewed by Mark Hahnenberg. + + The state of the stubs was changing after we determined the type (by virtue of the slow path + function that was called), since the get or put (in this case put) could cause arbitrary + side effects. Perhaps a full-blown fix would be to eliminate our reliance of the slow path + function to determine what to do, but an easier fix for now is to have the slow path give up + if its assumptions were invalidated by a side effect. + + * dfg/DFGOperations.cpp: + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + +2012-08-03 Filip Pizlo <fpizlo@apple.com> + + DFG handling of get_by_id should always inject a ForceOSRExit node if there is no prediction + https://bugs.webkit.org/show_bug.cgi?id=93162 + + Reviewed by Mark Hahnenberg. + + This simplifies the DFG IR by ensuring that all nodes that use value profiles will be preceded + by a ForceOSRExit if the value profile had no data. + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::parseBlock): + +2012-08-03 Filip Pizlo <fpizlo@apple.com> + + DFG::StructureCheckHoistingPhase keeps a Node& around for too long + https://bugs.webkit.org/show_bug.cgi?id=93157 + + Reviewed by Mark Hahnenberg. + + * dfg/DFGStructureCheckHoistingPhase.cpp: + (JSC::DFG::StructureCheckHoistingPhase::run): + +2012-08-02 Patrick Gansterer <paroga@webkit.org> + + Move getLocalTime() as static inline function to DateMath + https://bugs.webkit.org/show_bug.cgi?id=92955 + + Reviewed by Ryosuke Niwa. + + getCurrentLocalTime() and getLocalTime() has been superseded with the + GregorianDateTime class. So we can move it into DateMath.cpp as an static inline + function. This allows us to remove the dependecy on time() and localtime() + for Windows CE, where this functions require the ce_time library to work. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-08-02 Filip Pizlo <fpizlo@apple.com> + + ASSERTION FAILED: at(m_compileIndex).canExit() || m_isCheckingArgumentTypes + https://bugs.webkit.org/show_bug.cgi?id=91074 + + Reviewed by Mark Hahnenberg. + + Fixes a bug where the speculative JIT was performing an unnecessary speculation that the + CFA had proven shouldn't be performed, leading to asserts that a node should not have + exit sites. This is a debug-only assert with no release symptom - we were just emitting + a check that was not reachable. + + Also found, and fixed, a bug where structure check hoisting was slightly confusing the + CFA by inserting GetLocal's into the graph. CSE would clean the GetLocal's up, which + would make the backend happy - but the CFA would produce subtly wrong results. + + * bytecode/SpeculatedType.h: + (JSC::isOtherOrEmptySpeculation): + (JSC): + * dfg/DFGDriver.cpp: + (JSC::DFG::compile): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality): + (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality): + +2012-08-02 Filip Pizlo <fpizlo@apple.com> + + Unreviewed, build fix for DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE). + + * dfg/DFGStructureCheckHoistingPhase.cpp: + (JSC::DFG::StructureCheckHoistingPhase::run): + +2012-08-01 Mark Hahnenberg <mhahnenberg@apple.com> + + Remove all uses of ClassInfo for JSStrings in JIT code + https://bugs.webkit.org/show_bug.cgi?id=92935 + + Reviewed by Geoffrey Garen. + + This is the first step in removing our dependence on in-object ClassInfo pointers + in JIT code. Most of the changes are to check the Structure, which is unique for + JSString primitives. + + * bytecode/SpeculatedType.cpp: + (JSC::speculationFromClassInfo): + (JSC::speculationFromStructure): Changed to check the TypeInfo in the Structure + since there wasn't a JSGlobalData immediately available to grab the JSString + Structure out of. + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * jit/JITInlineMethods.h: + (JSC::JIT::emitLoadCharacterString): + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + (JSC::JIT::emit_op_to_primitive): + (JSC::JIT::emit_op_convert_this): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + (JSC::JIT::emit_op_to_primitive): + (JSC::JIT::emitSlow_op_eq): + (JSC::JIT::emitSlow_op_neq): + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::emit_op_convert_this): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::stringGetByValStubGenerator): + (JSC::JIT::emitSlow_op_get_by_val): + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::stringGetByValStubGenerator): + (JSC::JIT::emitSlow_op_get_by_val): + * jit/SpecializedThunkJIT.h: + (JSC::SpecializedThunkJIT::loadJSStringArgument): + * jit/ThunkGenerators.cpp: + (JSC::stringCharLoad): + (JSC::charCodeAtThunkGenerator): + (JSC::charAtThunkGenerator): + +2012-08-02 Filip Pizlo <fpizlo@apple.com> + + Unreviewed, missed a style goof in the previous patch: "NodeIndex nodeIndex" + in a method signature is painfully redundant. + + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + +2012-08-02 Filip Pizlo <fpizlo@apple.com> + + DFGSpeculativeJIT.h has too many inline method bodies + https://bugs.webkit.org/show_bug.cgi?id=92957 + + Reviewed by Antti Koivisto. + + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::speculationCheck): + (DFG): + (JSC::DFG::SpeculativeJIT::speculationWatchpoint): + (JSC::DFG::SpeculativeJIT::forwardSpeculationCheck): + (JSC::DFG::SpeculativeJIT::speculationCheckWithConditionalDirection): + (JSC::DFG::SpeculativeJIT::terminateSpeculativeExecution): + (JSC::DFG::SpeculativeJIT::terminateSpeculativeExecutionWithConditionalDirection): + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + +2012-08-01 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r124406. + http://trac.webkit.org/changeset/124406 + https://bugs.webkit.org/show_bug.cgi?id=92951 + + it set the Mac bots on fire (Requested by pizlo on #webkit). + + * bytecode/Opcode.h: + (JSC): + (JSC::padOpcodeName): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitDebugHook): + * bytecompiler/BytecodeGenerator.h: + (BytecodeGenerator): + * bytecompiler/NodesCodegen.cpp: + (JSC::ArrayNode::toArgumentList): + (JSC::ApplyFunctionCallDotNode::emitBytecode): + (JSC::ConditionalNode::emitBytecode): + (JSC::ConstStatementNode::emitBytecode): + (JSC::EmptyStatementNode::emitBytecode): + (JSC::DebuggerStatementNode::emitBytecode): + (JSC::ExprStatementNode::emitBytecode): + (JSC::VarStatementNode::emitBytecode): + (JSC::IfNode::emitBytecode): + (JSC::IfElseNode::emitBytecode): + (JSC::DoWhileNode::emitBytecode): + (JSC::WhileNode::emitBytecode): + (JSC::ForNode::emitBytecode): + (JSC::ForInNode::emitBytecode): + (JSC::ContinueNode::emitBytecode): + (JSC::BreakNode::emitBytecode): + (JSC::ReturnNode::emitBytecode): + (JSC::WithNode::emitBytecode): + (JSC::SwitchNode::emitBytecode): + (JSC::LabelNode::emitBytecode): + (JSC::ThrowNode::emitBytecode): + (JSC::TryNode::emitBytecode): + (JSC::ProgramNode::emitBytecode): + (JSC::EvalNode::emitBytecode): + (JSC::FunctionBodyNode::emitBytecode): + * debugger/Debugger.h: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::unwindCallFrame): + (JSC::Interpreter::throwException): + (JSC::Interpreter::debug): + * interpreter/Interpreter.h: + (Interpreter): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_debug): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_debug): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + * parser/ASTBuilder.h: + (ASTBuilder): + (JSC::ASTBuilder::createCommaExpr): + (JSC::ASTBuilder::createLogicalNot): + (JSC::ASTBuilder::createUnaryPlus): + (JSC::ASTBuilder::createVoid): + (JSC::ASTBuilder::thisExpr): + (JSC::ASTBuilder::createResolve): + (JSC::ASTBuilder::createObjectLiteral): + (JSC::ASTBuilder::createArray): + (JSC::ASTBuilder::createNumberExpr): + (JSC::ASTBuilder::createString): + (JSC::ASTBuilder::createBoolean): + (JSC::ASTBuilder::createNull): + (JSC::ASTBuilder::createBracketAccess): + (JSC::ASTBuilder::createDotAccess): + (JSC::ASTBuilder::createRegExp): + (JSC::ASTBuilder::createNewExpr): + (JSC::ASTBuilder::createConditionalExpr): + (JSC::ASTBuilder::createAssignResolve): + (JSC::ASTBuilder::createFunctionExpr): + (JSC::ASTBuilder::createFunctionBody): + (JSC::ASTBuilder::createGetterOrSetterProperty): + (JSC::ASTBuilder::createArgumentsList): + (JSC::ASTBuilder::createPropertyList): + (JSC::ASTBuilder::createFuncDeclStatement): + (JSC::ASTBuilder::createBlockStatement): + (JSC::ASTBuilder::createExprStatement): + (JSC::ASTBuilder::createIfStatement): + (JSC::ASTBuilder::createForLoop): + (JSC::ASTBuilder::createForInLoop): + (JSC::ASTBuilder::createEmptyStatement): + (JSC::ASTBuilder::createVarStatement): + (JSC::ASTBuilder::createReturnStatement): + (JSC::ASTBuilder::createBreakStatement): + (JSC::ASTBuilder::createContinueStatement): + (JSC::ASTBuilder::createTryStatement): + (JSC::ASTBuilder::createSwitchStatement): + (JSC::ASTBuilder::createWhileStatement): + (JSC::ASTBuilder::createDoWhileStatement): + (JSC::ASTBuilder::createLabelStatement): + (JSC::ASTBuilder::createWithStatement): + (JSC::ASTBuilder::createThrowStatement): + (JSC::ASTBuilder::createDebugger): + (JSC::ASTBuilder::createConstStatement): + (JSC::ASTBuilder::appendConstDecl): + (JSC::ASTBuilder::combineCommaNodes): + (JSC::ASTBuilder::appendBinaryOperation): + (JSC::ASTBuilder::createAssignment): + (JSC::ASTBuilder::createNumber): + (JSC::ASTBuilder::makeTypeOfNode): + (JSC::ASTBuilder::makeDeleteNode): + (JSC::ASTBuilder::makeNegateNode): + (JSC::ASTBuilder::makeBitwiseNotNode): + (JSC::ASTBuilder::makeMultNode): + (JSC::ASTBuilder::makeDivNode): + (JSC::ASTBuilder::makeModNode): + (JSC::ASTBuilder::makeAddNode): + (JSC::ASTBuilder::makeSubNode): + (JSC::ASTBuilder::makeLeftShiftNode): + (JSC::ASTBuilder::makeRightShiftNode): + (JSC::ASTBuilder::makeURightShiftNode): + (JSC::ASTBuilder::makeBitOrNode): + (JSC::ASTBuilder::makeBitAndNode): + (JSC::ASTBuilder::makeBitXOrNode): + (JSC::ASTBuilder::makeFunctionCallNode): + (JSC::ASTBuilder::makeBinaryNode): + (JSC::ASTBuilder::makeAssignNode): + (JSC::ASTBuilder::makePrefixNode): + (JSC::ASTBuilder::makePostfixNode): + * parser/Lexer.cpp: + (JSC::::setCode): + (JSC::::internalShift): + (JSC::::shift): + (JSC::::lex): + * parser/Lexer.h: + (Lexer): + (JSC::::lexExpectIdentifier): + * parser/NodeConstructors.h: + (JSC::Node::Node): + (JSC::ExpressionNode::ExpressionNode): + (JSC::StatementNode::StatementNode): + (JSC::NullNode::NullNode): + (JSC::BooleanNode::BooleanNode): + (JSC::NumberNode::NumberNode): + (JSC::StringNode::StringNode): + (JSC::RegExpNode::RegExpNode): + (JSC::ThisNode::ThisNode): + (JSC::ResolveNode::ResolveNode): + (JSC::ArrayNode::ArrayNode): + (JSC::PropertyListNode::PropertyListNode): + (JSC::ObjectLiteralNode::ObjectLiteralNode): + (JSC::BracketAccessorNode::BracketAccessorNode): + (JSC::DotAccessorNode::DotAccessorNode): + (JSC::ArgumentListNode::ArgumentListNode): + (JSC::NewExprNode::NewExprNode): + (JSC::EvalFunctionCallNode::EvalFunctionCallNode): + (JSC::FunctionCallValueNode::FunctionCallValueNode): + (JSC::FunctionCallResolveNode::FunctionCallResolveNode): + (JSC::FunctionCallBracketNode::FunctionCallBracketNode): + (JSC::FunctionCallDotNode::FunctionCallDotNode): + (JSC::CallFunctionCallDotNode::CallFunctionCallDotNode): + (JSC::ApplyFunctionCallDotNode::ApplyFunctionCallDotNode): + (JSC::PrePostResolveNode::PrePostResolveNode): + (JSC::PostfixResolveNode::PostfixResolveNode): + (JSC::PostfixBracketNode::PostfixBracketNode): + (JSC::PostfixDotNode::PostfixDotNode): + (JSC::PostfixErrorNode::PostfixErrorNode): + (JSC::DeleteResolveNode::DeleteResolveNode): + (JSC::DeleteBracketNode::DeleteBracketNode): + (JSC::DeleteDotNode::DeleteDotNode): + (JSC::DeleteValueNode::DeleteValueNode): + (JSC::VoidNode::VoidNode): + (JSC::TypeOfResolveNode::TypeOfResolveNode): + (JSC::TypeOfValueNode::TypeOfValueNode): + (JSC::PrefixResolveNode::PrefixResolveNode): + (JSC::PrefixBracketNode::PrefixBracketNode): + (JSC::PrefixDotNode::PrefixDotNode): + (JSC::PrefixErrorNode::PrefixErrorNode): + (JSC::UnaryOpNode::UnaryOpNode): + (JSC::UnaryPlusNode::UnaryPlusNode): + (JSC::NegateNode::NegateNode): + (JSC::BitwiseNotNode::BitwiseNotNode): + (JSC::LogicalNotNode::LogicalNotNode): + (JSC::BinaryOpNode::BinaryOpNode): + (JSC::MultNode::MultNode): + (JSC::DivNode::DivNode): + (JSC::ModNode::ModNode): + (JSC::AddNode::AddNode): + (JSC::SubNode::SubNode): + (JSC::LeftShiftNode::LeftShiftNode): + (JSC::RightShiftNode::RightShiftNode): + (JSC::UnsignedRightShiftNode::UnsignedRightShiftNode): + (JSC::LessNode::LessNode): + (JSC::GreaterNode::GreaterNode): + (JSC::LessEqNode::LessEqNode): + (JSC::GreaterEqNode::GreaterEqNode): + (JSC::ThrowableBinaryOpNode::ThrowableBinaryOpNode): + (JSC::InstanceOfNode::InstanceOfNode): + (JSC::InNode::InNode): + (JSC::EqualNode::EqualNode): + (JSC::NotEqualNode::NotEqualNode): + (JSC::StrictEqualNode::StrictEqualNode): + (JSC::NotStrictEqualNode::NotStrictEqualNode): + (JSC::BitAndNode::BitAndNode): + (JSC::BitOrNode::BitOrNode): + (JSC::BitXOrNode::BitXOrNode): + (JSC::LogicalOpNode::LogicalOpNode): + (JSC::ConditionalNode::ConditionalNode): + (JSC::ReadModifyResolveNode::ReadModifyResolveNode): + (JSC::AssignResolveNode::AssignResolveNode): + (JSC::ReadModifyBracketNode::ReadModifyBracketNode): + (JSC::AssignBracketNode::AssignBracketNode): + (JSC::AssignDotNode::AssignDotNode): + (JSC::ReadModifyDotNode::ReadModifyDotNode): + (JSC::AssignErrorNode::AssignErrorNode): + (JSC::CommaNode::CommaNode): + (JSC::ConstStatementNode::ConstStatementNode): + (JSC::EmptyStatementNode::EmptyStatementNode): + (JSC::DebuggerStatementNode::DebuggerStatementNode): + (JSC::ExprStatementNode::ExprStatementNode): + (JSC::VarStatementNode::VarStatementNode): + (JSC::IfNode::IfNode): + (JSC::IfElseNode::IfElseNode): + (JSC::DoWhileNode::DoWhileNode): + (JSC::WhileNode::WhileNode): + (JSC::ForNode::ForNode): + (JSC::ContinueNode::ContinueNode): + (JSC::BreakNode::BreakNode): + (JSC::ReturnNode::ReturnNode): + (JSC::WithNode::WithNode): + (JSC::LabelNode::LabelNode): + (JSC::ThrowNode::ThrowNode): + (JSC::TryNode::TryNode): + (JSC::FuncExprNode::FuncExprNode): + (JSC::FuncDeclNode::FuncDeclNode): + (JSC::SwitchNode::SwitchNode): + (JSC::ConstDeclNode::ConstDeclNode): + (JSC::BlockNode::BlockNode): + (JSC::ForInNode::ForInNode): + * parser/Nodes.cpp: + (JSC): + (JSC::StatementNode::setLoc): + (JSC::ScopeNode::ScopeNode): + (JSC::ProgramNode::ProgramNode): + (JSC::ProgramNode::create): + (JSC::EvalNode::EvalNode): + (JSC::EvalNode::create): + (JSC::FunctionBodyNode::FunctionBodyNode): + (JSC::FunctionBodyNode::create): + * parser/Nodes.h: + (Node): + (ExpressionNode): + (StatementNode): + (NullNode): + (BooleanNode): + (NumberNode): + (StringNode): + (RegExpNode): + (ThisNode): + (ResolveNode): + (ArrayNode): + (PropertyListNode): + (ObjectLiteralNode): + (BracketAccessorNode): + (DotAccessorNode): + (ArgumentListNode): + (NewExprNode): + (EvalFunctionCallNode): + (FunctionCallValueNode): + (FunctionCallResolveNode): + (FunctionCallBracketNode): + (FunctionCallDotNode): + (CallFunctionCallDotNode): + (ApplyFunctionCallDotNode): + (PrePostResolveNode): + (PostfixResolveNode): + (PostfixBracketNode): + (PostfixDotNode): + (PostfixErrorNode): + (DeleteResolveNode): + (DeleteBracketNode): + (DeleteDotNode): + (DeleteValueNode): + (VoidNode): + (TypeOfResolveNode): + (TypeOfValueNode): + (PrefixResolveNode): + (PrefixBracketNode): + (PrefixDotNode): + (PrefixErrorNode): + (UnaryOpNode): + (UnaryPlusNode): + (NegateNode): + (BitwiseNotNode): + (LogicalNotNode): + (BinaryOpNode): + (MultNode): + (DivNode): + (ModNode): + (AddNode): + (SubNode): + (LeftShiftNode): + (RightShiftNode): + (UnsignedRightShiftNode): + (LessNode): + (GreaterNode): + (LessEqNode): + (GreaterEqNode): + (ThrowableBinaryOpNode): + (InstanceOfNode): + (InNode): + (EqualNode): + (NotEqualNode): + (StrictEqualNode): + (NotStrictEqualNode): + (BitAndNode): + (BitOrNode): + (BitXOrNode): + (LogicalOpNode): + (ConditionalNode): + (ReadModifyResolveNode): + (AssignResolveNode): + (ReadModifyBracketNode): + (AssignBracketNode): + (AssignDotNode): + (ReadModifyDotNode): + (AssignErrorNode): + (CommaNode): + (ConstDeclNode): + (ConstStatementNode): + (BlockNode): + (EmptyStatementNode): + (DebuggerStatementNode): + (ExprStatementNode): + (VarStatementNode): + (IfNode): + (IfElseNode): + (DoWhileNode): + (WhileNode): + (ForNode): + (ForInNode): + (ContinueNode): + (BreakNode): + (ReturnNode): + (WithNode): + (LabelNode): + (ThrowNode): + (TryNode): + (ScopeNode): + (ProgramNode): + (EvalNode): + (FunctionBodyNode): + (FuncExprNode): + (FuncDeclNode): + (SwitchNode): + * parser/Parser.cpp: + (JSC::::parseSourceElements): + (JSC::::parseVarDeclaration): + (JSC::::parseConstDeclaration): + (JSC::::parseDoWhileStatement): + (JSC::::parseWhileStatement): + (JSC::::parseVarDeclarationList): + (JSC::::parseConstDeclarationList): + (JSC::::parseForStatement): + (JSC::::parseBreakStatement): + (JSC::::parseContinueStatement): + (JSC::::parseReturnStatement): + (JSC::::parseThrowStatement): + (JSC::::parseWithStatement): + (JSC::::parseSwitchStatement): + (JSC::::parseTryStatement): + (JSC::::parseDebuggerStatement): + (JSC::::parseBlockStatement): + (JSC::::parseStatement): + (JSC::::parseFunctionBody): + (JSC::::parseFunctionInfo): + (JSC::::parseFunctionDeclaration): + (JSC::::parseExpressionOrLabelStatement): + (JSC::::parseExpressionStatement): + (JSC::::parseIfStatement): + (JSC::::parseExpression): + (JSC::::parseAssignmentExpression): + (JSC::::parseConditionalExpression): + (JSC::::parseBinaryExpression): + (JSC::::parseProperty): + (JSC::::parseObjectLiteral): + (JSC::::parseStrictObjectLiteral): + (JSC::::parseArrayLiteral): + (JSC::::parsePrimaryExpression): + (JSC::::parseArguments): + (JSC::::parseMemberExpression): + (JSC::::parseUnaryExpression): + * parser/Parser.h: + (JSC::Parser::next): + (JSC::Parser::nextExpectIdentifier): + (JSC::Parser::tokenStart): + (JSC::Parser::tokenLine): + (JSC::Parser::tokenEnd): + (JSC::Parser::getTokenName): + (JSC::::parse): + * parser/ParserTokens.h: + (JSC::JSTokenInfo::JSTokenInfo): + (JSTokenInfo): + (JSToken): + * parser/SourceProviderCacheItem.h: + (JSC::SourceProviderCacheItem::closeBraceToken): + * parser/SyntaxChecker.h: + (JSC::SyntaxChecker::makeFunctionCallNode): + (JSC::SyntaxChecker::createCommaExpr): + (JSC::SyntaxChecker::makeAssignNode): + (JSC::SyntaxChecker::makePrefixNode): + (JSC::SyntaxChecker::makePostfixNode): + (JSC::SyntaxChecker::makeTypeOfNode): + (JSC::SyntaxChecker::makeDeleteNode): + (JSC::SyntaxChecker::makeNegateNode): + (JSC::SyntaxChecker::makeBitwiseNotNode): + (JSC::SyntaxChecker::createLogicalNot): + (JSC::SyntaxChecker::createUnaryPlus): + (JSC::SyntaxChecker::createVoid): + (JSC::SyntaxChecker::thisExpr): + (JSC::SyntaxChecker::createResolve): + (JSC::SyntaxChecker::createObjectLiteral): + (JSC::SyntaxChecker::createArray): + (JSC::SyntaxChecker::createNumberExpr): + (JSC::SyntaxChecker::createString): + (JSC::SyntaxChecker::createBoolean): + (JSC::SyntaxChecker::createNull): + (JSC::SyntaxChecker::createBracketAccess): + (JSC::SyntaxChecker::createDotAccess): + (JSC::SyntaxChecker::createRegExp): + (JSC::SyntaxChecker::createNewExpr): + (JSC::SyntaxChecker::createConditionalExpr): + (JSC::SyntaxChecker::createAssignResolve): + (JSC::SyntaxChecker::createFunctionExpr): + (JSC::SyntaxChecker::createFunctionBody): + (JSC::SyntaxChecker::createArgumentsList): + (JSC::SyntaxChecker::createPropertyList): + (JSC::SyntaxChecker::createFuncDeclStatement): + (JSC::SyntaxChecker::createBlockStatement): + (JSC::SyntaxChecker::createExprStatement): + (JSC::SyntaxChecker::createIfStatement): + (JSC::SyntaxChecker::createForLoop): + (JSC::SyntaxChecker::createForInLoop): + (JSC::SyntaxChecker::createEmptyStatement): + (JSC::SyntaxChecker::createVarStatement): + (JSC::SyntaxChecker::createReturnStatement): + (JSC::SyntaxChecker::createBreakStatement): + (JSC::SyntaxChecker::createContinueStatement): + (JSC::SyntaxChecker::createTryStatement): + (JSC::SyntaxChecker::createSwitchStatement): + (JSC::SyntaxChecker::createWhileStatement): + (JSC::SyntaxChecker::createWithStatement): + (JSC::SyntaxChecker::createDoWhileStatement): + (JSC::SyntaxChecker::createLabelStatement): + (JSC::SyntaxChecker::createThrowStatement): + (JSC::SyntaxChecker::createDebugger): + (JSC::SyntaxChecker::createConstStatement): + (JSC::SyntaxChecker::appendConstDecl): + (JSC::SyntaxChecker::createGetterOrSetterProperty): + (JSC::SyntaxChecker::combineCommaNodes): + (JSC::SyntaxChecker::operatorStackPop): + +2012-08-01 Peter Wang <peter.wang@torchmobile.com.cn> + + Web Inspector: [JSC] implement setting breakpoints by line:column + https://bugs.webkit.org/show_bug.cgi?id=53003 + + Reviewed by Geoffrey Garen. + + Add a counter in lexer to record the column of each token. Debugger will use column info + in "Pretty Print" debug mode of Inspector. + + * bytecode/Opcode.h: + (JSC): + (JSC::padOpcodeName): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitDebugHook): + * bytecompiler/BytecodeGenerator.h: + (BytecodeGenerator): + * bytecompiler/NodesCodegen.cpp: + (JSC::ArrayNode::toArgumentList): + (JSC::ApplyFunctionCallDotNode::emitBytecode): + (JSC::ConditionalNode::emitBytecode): + (JSC::ConstStatementNode::emitBytecode): + (JSC::EmptyStatementNode::emitBytecode): + (JSC::DebuggerStatementNode::emitBytecode): + (JSC::ExprStatementNode::emitBytecode): + (JSC::VarStatementNode::emitBytecode): + (JSC::IfNode::emitBytecode): + (JSC::IfElseNode::emitBytecode): + (JSC::DoWhileNode::emitBytecode): + (JSC::WhileNode::emitBytecode): + (JSC::ForNode::emitBytecode): + (JSC::ForInNode::emitBytecode): + (JSC::ContinueNode::emitBytecode): + (JSC::BreakNode::emitBytecode): + (JSC::ReturnNode::emitBytecode): + (JSC::WithNode::emitBytecode): + (JSC::SwitchNode::emitBytecode): + (JSC::LabelNode::emitBytecode): + (JSC::ThrowNode::emitBytecode): + (JSC::TryNode::emitBytecode): + (JSC::ProgramNode::emitBytecode): + (JSC::EvalNode::emitBytecode): + (JSC::FunctionBodyNode::emitBytecode): + * debugger/Debugger.h: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::unwindCallFrame): + (JSC::Interpreter::throwException): + (JSC::Interpreter::debug): + * interpreter/Interpreter.h: + (Interpreter): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_debug): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_debug): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + * parser/ASTBuilder.h: + (ASTBuilder): + (JSC::ASTBuilder::createCommaExpr): + (JSC::ASTBuilder::createLogicalNot): + (JSC::ASTBuilder::createUnaryPlus): + (JSC::ASTBuilder::createVoid): + (JSC::ASTBuilder::thisExpr): + (JSC::ASTBuilder::createResolve): + (JSC::ASTBuilder::createObjectLiteral): + (JSC::ASTBuilder::createArray): + (JSC::ASTBuilder::createNumberExpr): + (JSC::ASTBuilder::createString): + (JSC::ASTBuilder::createBoolean): + (JSC::ASTBuilder::createNull): + (JSC::ASTBuilder::createBracketAccess): + (JSC::ASTBuilder::createDotAccess): + (JSC::ASTBuilder::createRegExp): + (JSC::ASTBuilder::createNewExpr): + (JSC::ASTBuilder::createConditionalExpr): + (JSC::ASTBuilder::createAssignResolve): + (JSC::ASTBuilder::createFunctionExpr): + (JSC::ASTBuilder::createFunctionBody): + (JSC::ASTBuilder::createGetterOrSetterProperty): + (JSC::ASTBuilder::createArgumentsList): + (JSC::ASTBuilder::createPropertyList): + (JSC::ASTBuilder::createFuncDeclStatement): + (JSC::ASTBuilder::createBlockStatement): + (JSC::ASTBuilder::createExprStatement): + (JSC::ASTBuilder::createIfStatement): + (JSC::ASTBuilder::createForLoop): + (JSC::ASTBuilder::createForInLoop): + (JSC::ASTBuilder::createEmptyStatement): + (JSC::ASTBuilder::createVarStatement): + (JSC::ASTBuilder::createReturnStatement): + (JSC::ASTBuilder::createBreakStatement): + (JSC::ASTBuilder::createContinueStatement): + (JSC::ASTBuilder::createTryStatement): + (JSC::ASTBuilder::createSwitchStatement): + (JSC::ASTBuilder::createWhileStatement): + (JSC::ASTBuilder::createDoWhileStatement): + (JSC::ASTBuilder::createLabelStatement): + (JSC::ASTBuilder::createWithStatement): + (JSC::ASTBuilder::createThrowStatement): + (JSC::ASTBuilder::createDebugger): + (JSC::ASTBuilder::createConstStatement): + (JSC::ASTBuilder::appendConstDecl): + (JSC::ASTBuilder::combineCommaNodes): + (JSC::ASTBuilder::appendBinaryOperation): + (JSC::ASTBuilder::createAssignment): + (JSC::ASTBuilder::createNumber): + (JSC::ASTBuilder::makeTypeOfNode): + (JSC::ASTBuilder::makeDeleteNode): + (JSC::ASTBuilder::makeNegateNode): + (JSC::ASTBuilder::makeBitwiseNotNode): + (JSC::ASTBuilder::makeMultNode): + (JSC::ASTBuilder::makeDivNode): + (JSC::ASTBuilder::makeModNode): + (JSC::ASTBuilder::makeAddNode): + (JSC::ASTBuilder::makeSubNode): + (JSC::ASTBuilder::makeLeftShiftNode): + (JSC::ASTBuilder::makeRightShiftNode): + (JSC::ASTBuilder::makeURightShiftNode): + (JSC::ASTBuilder::makeBitOrNode): + (JSC::ASTBuilder::makeBitAndNode): + (JSC::ASTBuilder::makeBitXOrNode): + (JSC::ASTBuilder::makeFunctionCallNode): + (JSC::ASTBuilder::makeBinaryNode): + (JSC::ASTBuilder::makeAssignNode): + (JSC::ASTBuilder::makePrefixNode): + (JSC::ASTBuilder::makePostfixNode): + * parser/Lexer.cpp: + (JSC::::setCode): + (JSC::::internalShift): + (JSC::::shift): + (JSC::::lex): + * parser/Lexer.h: + (Lexer): + (JSC::Lexer::currentColumnNumber): + (JSC::::lexExpectIdentifier): + * parser/NodeConstructors.h: + (JSC::Node::Node): + (JSC::ExpressionNode::ExpressionNode): + (JSC::StatementNode::StatementNode): + (JSC::NullNode::NullNode): + (JSC::BooleanNode::BooleanNode): + (JSC::NumberNode::NumberNode): + (JSC::StringNode::StringNode): + (JSC::RegExpNode::RegExpNode): + (JSC::ThisNode::ThisNode): + (JSC::ResolveNode::ResolveNode): + (JSC::ArrayNode::ArrayNode): + (JSC::PropertyListNode::PropertyListNode): + (JSC::ObjectLiteralNode::ObjectLiteralNode): + (JSC::BracketAccessorNode::BracketAccessorNode): + (JSC::DotAccessorNode::DotAccessorNode): + (JSC::ArgumentListNode::ArgumentListNode): + (JSC::NewExprNode::NewExprNode): + (JSC::EvalFunctionCallNode::EvalFunctionCallNode): + (JSC::FunctionCallValueNode::FunctionCallValueNode): + (JSC::FunctionCallResolveNode::FunctionCallResolveNode): + (JSC::FunctionCallBracketNode::FunctionCallBracketNode): + (JSC::FunctionCallDotNode::FunctionCallDotNode): + (JSC::CallFunctionCallDotNode::CallFunctionCallDotNode): + (JSC::ApplyFunctionCallDotNode::ApplyFunctionCallDotNode): + (JSC::PrePostResolveNode::PrePostResolveNode): + (JSC::PostfixResolveNode::PostfixResolveNode): + (JSC::PostfixBracketNode::PostfixBracketNode): + (JSC::PostfixDotNode::PostfixDotNode): + (JSC::PostfixErrorNode::PostfixErrorNode): + (JSC::DeleteResolveNode::DeleteResolveNode): + (JSC::DeleteBracketNode::DeleteBracketNode): + (JSC::DeleteDotNode::DeleteDotNode): + (JSC::DeleteValueNode::DeleteValueNode): + (JSC::VoidNode::VoidNode): + (JSC::TypeOfResolveNode::TypeOfResolveNode): + (JSC::TypeOfValueNode::TypeOfValueNode): + (JSC::PrefixResolveNode::PrefixResolveNode): + (JSC::PrefixBracketNode::PrefixBracketNode): + (JSC::PrefixDotNode::PrefixDotNode): + (JSC::PrefixErrorNode::PrefixErrorNode): + (JSC::UnaryOpNode::UnaryOpNode): + (JSC::UnaryPlusNode::UnaryPlusNode): + (JSC::NegateNode::NegateNode): + (JSC::BitwiseNotNode::BitwiseNotNode): + (JSC::LogicalNotNode::LogicalNotNode): + (JSC::BinaryOpNode::BinaryOpNode): + (JSC::MultNode::MultNode): + (JSC::DivNode::DivNode): + (JSC::ModNode::ModNode): + (JSC::AddNode::AddNode): + (JSC::SubNode::SubNode): + (JSC::LeftShiftNode::LeftShiftNode): + (JSC::RightShiftNode::RightShiftNode): + (JSC::UnsignedRightShiftNode::UnsignedRightShiftNode): + (JSC::LessNode::LessNode): + (JSC::GreaterNode::GreaterNode): + (JSC::LessEqNode::LessEqNode): + (JSC::GreaterEqNode::GreaterEqNode): + (JSC::ThrowableBinaryOpNode::ThrowableBinaryOpNode): + (JSC::InstanceOfNode::InstanceOfNode): + (JSC::InNode::InNode): + (JSC::EqualNode::EqualNode): + (JSC::NotEqualNode::NotEqualNode): + (JSC::StrictEqualNode::StrictEqualNode): + (JSC::NotStrictEqualNode::NotStrictEqualNode): + (JSC::BitAndNode::BitAndNode): + (JSC::BitOrNode::BitOrNode): + (JSC::BitXOrNode::BitXOrNode): + (JSC::LogicalOpNode::LogicalOpNode): + (JSC::ConditionalNode::ConditionalNode): + (JSC::ReadModifyResolveNode::ReadModifyResolveNode): + (JSC::AssignResolveNode::AssignResolveNode): + (JSC::ReadModifyBracketNode::ReadModifyBracketNode): + (JSC::AssignBracketNode::AssignBracketNode): + (JSC::AssignDotNode::AssignDotNode): + (JSC::ReadModifyDotNode::ReadModifyDotNode): + (JSC::AssignErrorNode::AssignErrorNode): + (JSC::CommaNode::CommaNode): + (JSC::ConstStatementNode::ConstStatementNode): + (JSC::EmptyStatementNode::EmptyStatementNode): + (JSC::DebuggerStatementNode::DebuggerStatementNode): + (JSC::ExprStatementNode::ExprStatementNode): + (JSC::VarStatementNode::VarStatementNode): + (JSC::IfNode::IfNode): + (JSC::IfElseNode::IfElseNode): + (JSC::DoWhileNode::DoWhileNode): + (JSC::WhileNode::WhileNode): + (JSC::ForNode::ForNode): + (JSC::ContinueNode::ContinueNode): + (JSC::BreakNode::BreakNode): + (JSC::ReturnNode::ReturnNode): + (JSC::WithNode::WithNode): + (JSC::LabelNode::LabelNode): + (JSC::ThrowNode::ThrowNode): + (JSC::TryNode::TryNode): + (JSC::FuncExprNode::FuncExprNode): + (JSC::FuncDeclNode::FuncDeclNode): + (JSC::SwitchNode::SwitchNode): + (JSC::ConstDeclNode::ConstDeclNode): + (JSC::BlockNode::BlockNode): + (JSC::ForInNode::ForInNode): + * parser/Nodes.cpp: + (JSC::StatementNode::setLoc): + (JSC): + (JSC::ScopeNode::ScopeNode): + (JSC::ProgramNode::ProgramNode): + (JSC::ProgramNode::create): + (JSC::EvalNode::EvalNode): + (JSC::EvalNode::create): + (JSC::FunctionBodyNode::FunctionBodyNode): + (JSC::FunctionBodyNode::create): + * parser/Nodes.h: + (Node): + (JSC::Node::columnNo): + (ExpressionNode): + (StatementNode): + (JSC::StatementNode::column): + (NullNode): + (BooleanNode): + (NumberNode): + (StringNode): + (RegExpNode): + (ThisNode): + (ResolveNode): + (ArrayNode): + (PropertyListNode): + (ObjectLiteralNode): + (BracketAccessorNode): + (DotAccessorNode): + (ArgumentListNode): + (NewExprNode): + (EvalFunctionCallNode): + (FunctionCallValueNode): + (FunctionCallResolveNode): + (FunctionCallBracketNode): + (FunctionCallDotNode): + (CallFunctionCallDotNode): + (ApplyFunctionCallDotNode): + (PrePostResolveNode): + (PostfixResolveNode): + (PostfixBracketNode): + (PostfixDotNode): + (PostfixErrorNode): + (DeleteResolveNode): + (DeleteBracketNode): + (DeleteDotNode): + (DeleteValueNode): + (VoidNode): + (TypeOfResolveNode): + (TypeOfValueNode): + (PrefixResolveNode): + (PrefixBracketNode): + (PrefixDotNode): + (PrefixErrorNode): + (UnaryOpNode): + (UnaryPlusNode): + (NegateNode): + (BitwiseNotNode): + (LogicalNotNode): + (BinaryOpNode): + (MultNode): + (DivNode): + (ModNode): + (AddNode): + (SubNode): + (LeftShiftNode): + (RightShiftNode): + (UnsignedRightShiftNode): + (LessNode): + (GreaterNode): + (LessEqNode): + (GreaterEqNode): + (ThrowableBinaryOpNode): + (InstanceOfNode): + (InNode): + (EqualNode): + (NotEqualNode): + (StrictEqualNode): + (NotStrictEqualNode): + (BitAndNode): + (BitOrNode): + (BitXOrNode): + (LogicalOpNode): + (ConditionalNode): + (ReadModifyResolveNode): + (AssignResolveNode): + (ReadModifyBracketNode): + (AssignBracketNode): + (AssignDotNode): + (ReadModifyDotNode): + (AssignErrorNode): + (CommaNode): + (ConstDeclNode): + (ConstStatementNode): + (BlockNode): + (EmptyStatementNode): + (DebuggerStatementNode): + (ExprStatementNode): + (VarStatementNode): + (IfNode): + (IfElseNode): + (DoWhileNode): + (WhileNode): + (ForNode): + (ForInNode): + (ContinueNode): + (BreakNode): + (ReturnNode): + (WithNode): + (LabelNode): + (ThrowNode): + (TryNode): + (ScopeNode): + (ProgramNode): + (EvalNode): + (FunctionBodyNode): + (FuncExprNode): + (FuncDeclNode): + (SwitchNode): + * parser/Parser.cpp: + (JSC::::parseSourceElements): + (JSC::::parseVarDeclaration): + (JSC::::parseConstDeclaration): + (JSC::::parseDoWhileStatement): + (JSC::::parseWhileStatement): + (JSC::::parseVarDeclarationList): + (JSC::::parseConstDeclarationList): + (JSC::::parseForStatement): + (JSC::::parseBreakStatement): + (JSC::::parseContinueStatement): + (JSC::::parseReturnStatement): + (JSC::::parseThrowStatement): + (JSC::::parseWithStatement): + (JSC::::parseSwitchStatement): + (JSC::::parseTryStatement): + (JSC::::parseDebuggerStatement): + (JSC::::parseBlockStatement): + (JSC::::parseStatement): + (JSC::::parseFunctionBody): + (JSC::::parseFunctionInfo): + (JSC::::parseFunctionDeclaration): + (JSC::::parseExpressionOrLabelStatement): + (JSC::::parseExpressionStatement): + (JSC::::parseIfStatement): + (JSC::::parseExpression): + (JSC::::parseAssignmentExpression): + (JSC::::parseConditionalExpression): + (JSC::::parseBinaryExpression): + (JSC::::parseProperty): + (JSC::::parseObjectLiteral): + (JSC::::parseStrictObjectLiteral): + (JSC::::parseArrayLiteral): + (JSC::::parsePrimaryExpression): + (JSC::::parseArguments): + (JSC::::parseMemberExpression): + (JSC::::parseUnaryExpression): + * parser/Parser.h: + (JSC::Parser::next): + (JSC::Parser::nextExpectIdentifier): + (JSC::Parser::tokenStart): + (JSC::Parser::tokenLine): + (JSC::Parser::tokenEnd): + (JSC::Parser::tokenLocation): + (Parser): + (JSC::Parser::getTokenName): + (JSC::::parse): + * parser/ParserTokens.h: + (JSC::JSTokenLocation::JSTokenLocation): + (JSTokenLocation): + (JSToken): + * parser/SourceProviderCacheItem.h: + (JSC::SourceProviderCacheItem::closeBraceToken): + * parser/SyntaxChecker.h: + (JSC::SyntaxChecker::makeFunctionCallNode): + (JSC::SyntaxChecker::createCommaExpr): + (JSC::SyntaxChecker::makeAssignNode): + (JSC::SyntaxChecker::makePrefixNode): + (JSC::SyntaxChecker::makePostfixNode): + (JSC::SyntaxChecker::makeTypeOfNode): + (JSC::SyntaxChecker::makeDeleteNode): + (JSC::SyntaxChecker::makeNegateNode): + (JSC::SyntaxChecker::makeBitwiseNotNode): + (JSC::SyntaxChecker::createLogicalNot): + (JSC::SyntaxChecker::createUnaryPlus): + (JSC::SyntaxChecker::createVoid): + (JSC::SyntaxChecker::thisExpr): + (JSC::SyntaxChecker::createResolve): + (JSC::SyntaxChecker::createObjectLiteral): + (JSC::SyntaxChecker::createArray): + (JSC::SyntaxChecker::createNumberExpr): + (JSC::SyntaxChecker::createString): + (JSC::SyntaxChecker::createBoolean): + (JSC::SyntaxChecker::createNull): + (JSC::SyntaxChecker::createBracketAccess): + (JSC::SyntaxChecker::createDotAccess): + (JSC::SyntaxChecker::createRegExp): + (JSC::SyntaxChecker::createNewExpr): + (JSC::SyntaxChecker::createConditionalExpr): + (JSC::SyntaxChecker::createAssignResolve): + (JSC::SyntaxChecker::createFunctionExpr): + (JSC::SyntaxChecker::createFunctionBody): + (JSC::SyntaxChecker::createArgumentsList): + (JSC::SyntaxChecker::createPropertyList): + (JSC::SyntaxChecker::createFuncDeclStatement): + (JSC::SyntaxChecker::createBlockStatement): + (JSC::SyntaxChecker::createExprStatement): + (JSC::SyntaxChecker::createIfStatement): + (JSC::SyntaxChecker::createForLoop): + (JSC::SyntaxChecker::createForInLoop): + (JSC::SyntaxChecker::createEmptyStatement): + (JSC::SyntaxChecker::createVarStatement): + (JSC::SyntaxChecker::createReturnStatement): + (JSC::SyntaxChecker::createBreakStatement): + (JSC::SyntaxChecker::createContinueStatement): + (JSC::SyntaxChecker::createTryStatement): + (JSC::SyntaxChecker::createSwitchStatement): + (JSC::SyntaxChecker::createWhileStatement): + (JSC::SyntaxChecker::createWithStatement): + (JSC::SyntaxChecker::createDoWhileStatement): + (JSC::SyntaxChecker::createLabelStatement): + (JSC::SyntaxChecker::createThrowStatement): + (JSC::SyntaxChecker::createDebugger): + (JSC::SyntaxChecker::createConstStatement): + (JSC::SyntaxChecker::appendConstDecl): + (JSC::SyntaxChecker::createGetterOrSetterProperty): + (JSC::SyntaxChecker::combineCommaNodes): + (JSC::SyntaxChecker::operatorStackPop): + +2012-08-01 Filip Pizlo <fpizlo@apple.com> + + DFG should hoist structure checks + https://bugs.webkit.org/show_bug.cgi?id=92696 + + Reviewed by Gavin Barraclough. + + This hoists structure checks in the same way that we would hoist array checks, but with added + complexity to cope with the fact that the structure of an object may change. This is handled + by performing a side effects analysis over the region in which the respective variable is + live. If a structure clobbering side effect may happen then we either hoist the structure + checks and fall back on structure transition watchpoints (if the watchpoint set is still + valid), or we avoid hoisting altogether. + + Doing this required teaching the CFA that we may have an expectation that an object has a + particular structure even after structure clobbering happens, in the sense that structure + proofs that were cobbered can be revived using watchpoints. CFA must know about this so that + OSR entry may know about it, since we cannot allow entry to happen if the variable has a + clobbered structure proof, will have a watchpoint to revive the proof, and the variable in + the baseline JIT has a completely unrelated structure. + + This is mostly performance neutral. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * bytecode/ValueRecovery.h: + (JSC::ValueRecovery::isSet): + (JSC::ValueRecovery::operator!): + (ValueRecovery): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + (JSC::DFG::AbstractState::clobberWorld): + (DFG): + (JSC::DFG::AbstractState::clobberCapturedVars): + * dfg/DFGAbstractState.h: + (AbstractState): + * dfg/DFGAbstractValue.h: + (JSC::DFG::AbstractValue::clear): + (JSC::DFG::AbstractValue::isClear): + (JSC::DFG::AbstractValue::makeTop): + (JSC::DFG::AbstractValue::isTop): + (JSC::DFG::AbstractValue::set): + (JSC::DFG::AbstractValue::operator==): + (JSC::DFG::AbstractValue::merge): + (JSC::DFG::AbstractValue::filter): + (JSC::DFG::AbstractValue::validate): + (JSC::DFG::AbstractValue::validateForEntry): + (AbstractValue): + (JSC::DFG::AbstractValue::checkConsistency): + (JSC::DFG::AbstractValue::dump): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::setLocal): + (JSC::DFG::ByteCodeParser::getArgument): + (JSC::DFG::ByteCodeParser::setArgument): + (JSC::DFG::ByteCodeParser::parseBlock): + (JSC::DFG::ByteCodeParser::fixVariableAccessSpeculations): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::checkStructureLoadElimination): + (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination): + (JSC::DFG::CSEPhase::putStructureStoreElimination): + (JSC::DFG::CSEPhase::getLocalLoadElimination): + (JSC::DFG::CSEPhase::performNodeCSE): + * dfg/DFGDriver.cpp: + (JSC::DFG::compile): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + * dfg/DFGGraph.h: + (JSC::DFG::Graph::vote): + (Graph): + * dfg/DFGNode.h: + (JSC::DFG::Node::convertToStructureTransitionWatchpoint): + (Node): + (JSC::DFG::Node::hasStructureSet): + * dfg/DFGNodeType.h: + (DFG): + * dfg/DFGOSREntry.cpp: + (JSC::DFG::prepareOSREntry): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + (PredictionPropagationPhase): + (JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting): + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + (JSC::DFG::SpeculativeJIT::forwardSpeculationCheck): + (JSC::DFG::SpeculativeJIT::speculationCheckWithConditionalDirection): + (JSC::DFG::SpeculativeJIT::terminateSpeculativeExecutionWithConditionalDirection): + (JSC::DFG::SpeculateCellOperand::SpeculateCellOperand): + (JSC::DFG::SpeculateCellOperand::gpr): + (SpeculateCellOperand): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::fillSpeculateCell): + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::fillSpeculateCell): + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGStructureCheckHoistingPhase.cpp: Added. + (DFG): + (StructureCheckHoistingPhase): + (JSC::DFG::StructureCheckHoistingPhase::StructureCheckHoistingPhase): + (JSC::DFG::StructureCheckHoistingPhase::run): + (JSC::DFG::StructureCheckHoistingPhase::noticeStructureCheck): + (JSC::DFG::StructureCheckHoistingPhase::noticeClobber): + (JSC::DFG::StructureCheckHoistingPhase::clobber): + (CheckData): + (JSC::DFG::StructureCheckHoistingPhase::CheckData::CheckData): + (JSC::DFG::performStructureCheckHoisting): + * dfg/DFGStructureCheckHoistingPhase.h: Added. + (DFG): + * dfg/DFGVariableAccessData.h: + (VariableAccessData): + (JSC::DFG::VariableAccessData::VariableAccessData): + (JSC::DFG::VariableAccessData::mergeStructureCheckHoistingFailed): + (JSC::DFG::VariableAccessData::structureCheckHoistingFailed): + (JSC::DFG::VariableAccessData::clearVotes): + (JSC::DFG::VariableAccessData::vote): + (JSC::DFG::VariableAccessData::voteRatio): + (JSC::DFG::VariableAccessData::shouldUseDoubleFormatAccordingToVote): + * runtime/Options.h: + (JSC): + +2012-08-01 Filip Pizlo <fpizlo@apple.com> + + DFG should distinguish between PutByVal's that clobber the world and ones that don't + https://bugs.webkit.org/show_bug.cgi?id=92923 + + Reviewed by Mark Hahnenberg. + + This is performance-neutral. I also confirmed that it's neutral if we make the + clobbering variant (PutByValSafe) clobber all knowledge of what is an array, + which should feed nicely into work on removing uses of ClassInfo. + + * bytecode/DFGExitProfile.h: + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::parseBlock): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::getByValLoadElimination): + (JSC::DFG::CSEPhase::checkStructureLoadElimination): + (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination): + (JSC::DFG::CSEPhase::getByOffsetLoadElimination): + (JSC::DFG::CSEPhase::putByOffsetStoreElimination): + (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination): + (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination): + (JSC::DFG::CSEPhase::performNodeCSE): + * dfg/DFGFixupPhase.cpp: + (JSC::DFG::FixupPhase::fixupNode): + * dfg/DFGGraph.h: + (JSC::DFG::Graph::byValIsPure): + (JSC::DFG::Graph::clobbersWorld): + * dfg/DFGNodeType.h: + (DFG): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-08-01 Jian Li <jianli@chromium.org> + + Add new CSS property "-webkit-widget-region" to expose dashboard region support for other port + https://bugs.webkit.org/show_bug.cgi?id=90298 + + Reviewed by Adam Barth. + + * Configurations/FeatureDefines.xcconfig: Add ENABLE_WIDGET_REGION define. + +2012-08-01 Patrick Gansterer <paroga@webkit.org> + + Replace WTF::getCurrentLocalTime() with GregorianDateTime::setToCurrentLocalTime() + https://bugs.webkit.org/show_bug.cgi?id=92286 + + Reviewed by Geoffrey Garen. + + Add a method to GregorianDateTime to set its values to the current locale time. + Replacing all occurrences of getCurrentLocalTime with the new function allows + us to remove getCurrentLocalTime in a next step. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-08-01 Mark Hahnenberg <mhahnenberg@apple.com> + + C++ code should get ClassInfo from the Structure + https://bugs.webkit.org/show_bug.cgi?id=92892 + + Reviewed by Geoffrey Garen. + + In our march to remove ClassInfo from our JSCell object headers, we can switch + C++ code over to grabbing the ClassInfo from the Structure since it is finally + safe to do so now that Structure access is safe during finalization/destruction. + The remaining JIT code changes can be done in a separate patch. + + * heap/MarkedBlock.cpp: + (JSC::MarkedBlock::callDestructor): We don't want to clear the Structure any more + since the Structure should still be valid at this point. + * heap/WeakSetInlines.h: + (JSC::WeakBlock::finalize): Ditto. + * runtime/JSCell.h: + (JSC): + * runtime/Structure.h: + (JSC::JSCell::classInfo): Move JSCell's classInfo() to Structure.h so it can be + inline. Use a different method of getting the JSCell's Structure based on + whether we're in GC_VALIDATION mode or not, since always using get() will cause + infinite recursion in GC_VALIDATION mode. + (JSC): + +2012-07-31 Mark Hahnenberg <mhahnenberg@apple.com> + + MarkedBlock::sweep() should sweep another block if it can't sweep a Structure block + https://bugs.webkit.org/show_bug.cgi?id=92819 + + Reviewed by Geoffrey Garen. + + If we are forced to allocate a new block for Structures because we are unable to safely + sweep our pre-existing Structure blocks, we should sweep another random block so that we + can start sweeping Structure blocks sooner. + + * heap/IncrementalSweeper.cpp: + (JSC::IncrementalSweeper::doSweep): Change to use sweepNextBlock. + (JSC): + (JSC::IncrementalSweeper::sweepNextBlock): + * heap/IncrementalSweeper.h: + (IncrementalSweeper): + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::tryAllocateHelper): When we can't safely sweep + our Structure blocks, call sweepNextBlock instead. + +2012-07-31 Sam Weinig <sam@webkit.org> + + Fix the Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-07-31 Geoffrey Garen <ggaren@apple.com> + + Maybe fix the GCC build. + + * heap/HeapBlock.h: + (HeapBlock): Accommodate incorrect parsing in GCC. + +2012-07-31 Sam Weinig <sam@webkit.org> + + Stop masking 8 bits off of the visited link hash. We need all the bits! + https://bugs.webkit.org/show_bug.cgi?id=92799 + + Reviewed by Anders Carlsson. + + * runtime/Identifier.cpp: + (JSC::IdentifierCStringTranslator::hash): + (JSC::IdentifierLCharFromUCharTranslator::hash): + * runtime/Identifier.h: + (JSC::IdentifierCharBufferTranslator::hash): + Update for new function names. + +2012-07-31 Geoffrey Garen <ggaren@apple.com> + + Maybe break the Windows build. + + Reviewed by Anders Carlsson. + + Formally objected to by Sam Weinig. + + * heap/HeapBlock.h: + (HeapBlock): Try to slightly improve this because we don't want Windows to control our lives. + +2012-07-30 Mark Hahnenberg <mhahnenberg@apple.com> + + Structures should be swept after all other objects + https://bugs.webkit.org/show_bug.cgi?id=92679 + + Reviewed by Filip Pizlo. + + In order to get rid of ClassInfo from our objects, we need to be able to safely get the + ClassInfo during the destruction of objects. We'd like to get the ClassInfo out of the + Structure, but currently it is not safe to do so because the order of destruction of objects + is not guaranteed to sweep objects before their corresponding Structure. We can fix this by + sweeping Structures after everything else. + + * heap/Heap.cpp: + (JSC::Heap::isSafeToSweepStructures): Add a function that checks if it is safe to sweep Structures. + If the Heap's IncrementalSweeper member is null, that means we're shutting down this VM and it is + safe to sweep structures since we'll always do Structures last anyways due to the ordering of + MarkedSpace::forEachBlock. + (JSC): + (JSC::Heap::didStartVMShutdown): Add this intermediate function to the Heap that ~JSGlobalData now + calls rather than calling the two HeapTimer objects individually. This allows the Heap to null out + these pointers after it has invalidated them to prevent accidental use-after-free in the sweep() + calls during lastChanceToFinalize(). + * heap/Heap.h: + (Heap): + * heap/HeapTimer.h: + (HeapTimer): + * heap/IncrementalSweeper.cpp: + (JSC::IncrementalSweeper::structuresCanBeSwept): Determines if it is currently safe to sweep Structures. + This decision is based on whether we have gotten to the end of the vector of blocks that need sweeping + the first time. + (JSC): + (JSC::IncrementalSweeper::doSweep): We add a second pass over the vector to sweep Structures after we + make our first pass. We now null out the slots as we sweep them so that we can quickly find the + Structures during the second pass. + (JSC::IncrementalSweeper::startSweeping): Initialize our new Structure sweeping index. + (JSC::IncrementalSweeper::willFinishSweeping): Callback that is called by MarkedSpace::sweep to notify + the IncrementalSweeper that we are going to sweep all of the remaining blocks in the Heap so it can + assume that everything is taken care of in the correct order. Since MarkedSpace::forEachBlock + iterates over the Structure blocks after all other blocks, the ordering property for sweeping Structures holds. + (JSC::IncrementalSweeper::IncrementalSweeper): Initialize Structure sweeping index. + * heap/IncrementalSweeper.h: Add declarations for new stuff. + (IncrementalSweeper): + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::tryAllocateHelper): We now check if the current block only contains structures and + if so and it isn't safe to sweep Structures according to the Heap, we just return early instead of doing + the normal lazy sweep. If this proves to be too much of a waste in the future we can add an extra clause that + will sweep some number of other blocks in place of the current block to mitigate the cost of the floating + Structure garbage. + (JSC::MarkedAllocator::addBlock): + * heap/MarkedAllocator.h: + (JSC::MarkedAllocator::zapFreeList): When we zap the free list in the MarkedAllocator, the current block is no + longer valid to allocate from, so we set the current block to null. + * heap/MarkedBlock.cpp: + (JSC::MarkedBlock::sweepHelper): Added a couple assertions to make sure that we weren't trying to sweep Structures + at an unsafe time. + * heap/MarkedSpace.cpp: + (JSC::MarkedSpace::sweep): Notify the IncrementalSweeper that the MarkedSpace will finish all currently remaining sweeping. + (JSC): + * heap/MarkedSpace.h: + (JSC): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::~JSGlobalData): Call the new Heap::didStartVMShutdown. + +2012-07-31 Geoffrey Garen <ggaren@apple.com> + + Fix all the other builds I just broke. Maybe fix the Windows build. + + * heap/HeapBlock.h: + (HeapBlock): WTF? + +2012-07-31 Geoffrey Garen <ggaren@apple.com> + + Maybe fix the Windows build. + + * heap/HeapBlock.h: + (HeapBlock): WTF? + +2012-07-31 Geoffrey Garen <ggaren@apple.com> + + Maybe fix the Windows build. + + * heap/HeapBlock.h: + (HeapBlock): WTF? + +2012-07-31 Geoffrey Garen <ggaren@apple.com> + + Removed some public data and casting from the Heap + https://bugs.webkit.org/show_bug.cgi?id=92777 + + Reviewed by Oliver Hunt. + + * heap/BlockAllocator.cpp: + (JSC::BlockAllocator::releaseFreeBlocks): + (JSC::BlockAllocator::blockFreeingThreadMain): Use the DeadBlock class + since HeapBlock is a template, and not a class, now. Call destroy() + instead of monkeying around with DeadBlock's internal data because + encapsulation is good. + + * heap/BlockAllocator.h: + (DeadBlock): Added a class to represent a dead block, since HeapBlock is + a template now, and can't be instantiated directly. + + (JSC::DeadBlock::DeadBlock): + (JSC::DeadBlock::create): + (BlockAllocator): + (JSC::BlockAllocator::allocate): + (JSC::BlockAllocator::deallocate): Use the DeadBlock class because + encapsulation is good. + + * heap/CopiedBlock.h: + (CopiedBlock::destroy): No need for a destroy() function, since we + inherit one now. + + (JSC::CopiedBlock::CopiedBlock): + (JSC::CopiedBlock::payloadEnd): + (JSC::CopiedBlock::capacity): Updated for some encapsulation inside + HeapBlock. + + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::~CopiedSpace): + (JSC::CopiedSpace::doneCopying): + (JSC::CopiedSpace::size): + (JSC::CopiedSpace::capacity): + (JSC::isBlockListPagedOut): Removed a bunch of casting. This is no longer + necessary, now that our list and its nodes have the right type. + + * heap/CopiedSpace.h: Use the right type in our data structures because + it improves clarity. + + * heap/CopiedSpaceInlineMethods.h: + (JSC::CopiedSpace::startedCopying): Use swap to avoid duplicating it. + + * heap/HeapBlock.h: + (HeapBlock): Made this a class template so we can return the right type + in linked list operations. Made our data private because encapsulation + is good. + + (JSC::HeapBlock::destroy): Since we know our type, we can also eliminate + duplicate destroy() functions in our subclasses. + + (JSC::HeapBlock::allocation): Added an accessor so we can hide our data. + By using const, this accessor prevents clients from accidentally deleting + our allocation. + + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::isPagedOut): + (JSC::MarkedAllocator::tryAllocateHelper): + (JSC::MarkedAllocator::removeBlock): Removed a bunch of casting. This is + no longer necessary, now that our list and its nodes have the right type. + + * heap/MarkedAllocator.h: + (MarkedAllocator): + (JSC::MarkedAllocator::reset): + (JSC::MarkedAllocator::forEachBlock): Use the right type, do less casting. + + * heap/MarkedBlock.cpp: + (JSC::MarkedBlock::destroy): Removed this function because our parent + class provides it for us now. + + (JSC::MarkedBlock::MarkedBlock): + * heap/MarkedBlock.h: + (MarkedBlock): + (JSC::MarkedBlock::capacity): Updated for encapsulation. + +2012-07-31 Filip Pizlo <fpizlo@apple.com> + + DFG OSR exit profiling has unusual oversights + https://bugs.webkit.org/show_bug.cgi?id=92728 + + Reviewed by Geoffrey Garen. + + * dfg/DFGOSRExit.cpp: + (JSC::DFG::OSRExit::considerAddingAsFrequentExitSiteSlow): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::speculationWatchpoint): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-07-31 Chao-ying Fu <fu@mips.com> + + Add MIPS add32 function + https://bugs.webkit.org/show_bug.cgi?id=91522 + + Reviewed by Oliver Hunt. + + Add isCompactPtrAlignedAddressOffset. + Add a new version of add32 that accepts AbsoluteAddress as inputs. + + * assembler/MacroAssemblerMIPS.h: + (JSC::MacroAssemblerMIPS::isCompactPtrAlignedAddressOffset): New. + (MacroAssemblerMIPS): + (JSC::MacroAssemblerMIPS::add32): Support AbsoluteAddress as inputs. + +2012-07-30 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r124123. + http://trac.webkit.org/changeset/124123 + https://bugs.webkit.org/show_bug.cgi?id=92700 + + ASSERT crashes terminate webkit Layout tests (Requested by + msaboff on #webkit). + + * heap/Heap.cpp: + * heap/Heap.h: + (Heap): + * heap/IncrementalSweeper.cpp: + (JSC::IncrementalSweeper::doSweep): + (JSC::IncrementalSweeper::startSweeping): + (JSC::IncrementalSweeper::IncrementalSweeper): + (JSC): + * heap/IncrementalSweeper.h: + (IncrementalSweeper): + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::tryAllocateHelper): + (JSC::MarkedAllocator::addBlock): + * heap/MarkedAllocator.h: + (JSC::MarkedAllocator::zapFreeList): + * heap/MarkedBlock.cpp: + (JSC::MarkedBlock::sweepHelper): + * heap/MarkedSpace.cpp: + * heap/MarkedSpace.h: + (JSC::MarkedSpace::sweep): + (JSC): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::~JSGlobalData): + +2012-07-30 Mark Hahnenberg <mhahnenberg@apple.com> + + Structures should be swept after all other objects + https://bugs.webkit.org/show_bug.cgi?id=92679 + + Reviewed by Filip Pizlo. + + In order to get rid of ClassInfo from our objects, we need to be able to safely get the + ClassInfo during the destruction of objects. We'd like to get the ClassInfo out of the + Structure, but currently it is not safe to do so because the order of destruction of objects + is not guaranteed to sweep objects before their corresponding Structure. We can fix this by + sweeping Structures after everything else. + + * heap/Heap.cpp: + (JSC::Heap::isSafeToSweepStructures): Add a function that checks if it is safe to sweep Structures. + If the Heap's IncrementalSweeper member is null, that means we're shutting down this VM and it is + safe to sweep structures since we'll always do Structures last anyways due to the ordering of + MarkedSpace::forEachBlock. + (JSC): + (JSC::Heap::didStartVMShutdown): Add this intermediate function to the Heap that ~JSGlobalData now + calls rather than calling the two HeapTimer objects individually. This allows the Heap to null out + these pointers after it has invalidated them to prevent accidental use-after-free in the sweep() + calls during lastChanceToFinalize(). + * heap/Heap.h: + (Heap): + * heap/HeapTimer.h: + (HeapTimer): + * heap/IncrementalSweeper.cpp: + (JSC::IncrementalSweeper::structuresCanBeSwept): Determines if it is currently safe to sweep Structures. + This decision is based on whether we have gotten to the end of the vector of blocks that need sweeping + the first time. + (JSC): + (JSC::IncrementalSweeper::doSweep): We add a second pass over the vector to sweep Structures after we + make our first pass. We now null out the slots as we sweep them so that we can quickly find the + Structures during the second pass. + (JSC::IncrementalSweeper::startSweeping): Initialize our new Structure sweeping index. + (JSC::IncrementalSweeper::willFinishSweeping): Callback that is called by MarkedSpace::sweep to notify + the IncrementalSweeper that we are going to sweep all of the remaining blocks in the Heap so it can + assume that everything is taken care of in the correct order. Since MarkedSpace::forEachBlock + iterates over the Structure blocks after all other blocks, the ordering property for sweeping Structures holds. + (JSC::IncrementalSweeper::IncrementalSweeper): Initialize Structure sweeping index. + * heap/IncrementalSweeper.h: Add declarations for new stuff. + (IncrementalSweeper): + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::tryAllocateHelper): We now check if the current block only contains structures and + if so and it isn't safe to sweep Structures according to the Heap, we just return early instead of doing + the normal lazy sweep. If this proves to be too much of a waste in the future we can add an extra clause that + will sweep some number of other blocks in place of the current block to mitigate the cost of the floating + Structure garbage. + (JSC::MarkedAllocator::addBlock): + * heap/MarkedAllocator.h: + (JSC::MarkedAllocator::zapFreeList): When we zap the free list in the MarkedAllocator, the current block is no + longer valid to allocate from, so we set the current block to null. + * heap/MarkedBlock.cpp: + (JSC::MarkedBlock::sweepHelper): Added a couple assertions to make sure that we weren't trying to sweep Structures + at an unsafe time. + * heap/MarkedSpace.cpp: + (JSC::MarkedSpace::sweep): Notify the IncrementalSweeper that the MarkedSpace will finish all currently remaining sweeping. + (JSC): + * heap/MarkedSpace.h: + (JSC): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::~JSGlobalData): Call the new Heap::didStartVMShutdown. 2012-07-29 Filip Pizlo <fpizlo@apple.com> diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig index b5f24899f..40d95cb9c 100644 --- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -39,6 +39,7 @@ ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING; ENABLE_CSP_NEXT = ; ENABLE_CSS_EXCLUSIONS = ENABLE_CSS_EXCLUSIONS; ENABLE_CSS_FILTERS = ENABLE_CSS_FILTERS; +ENABLE_CSS_HIERARCHIES = ; ENABLE_CSS_IMAGE_ORIENTATION = ; ENABLE_CSS_IMAGE_RESOLUTION = ; ENABLE_CSS_REGIONS = ENABLE_CSS_REGIONS; @@ -133,7 +134,9 @@ ENABLE_WEBGL = ENABLE_WEBGL; ENABLE_WEB_AUDIO = ENABLE_WEB_AUDIO; ENABLE_WEB_SOCKETS = ENABLE_WEB_SOCKETS; ENABLE_WEB_TIMING = ; +ENABLE_WIDGET_REGION = $(ENABLE_WIDGET_REGION_$(REAL_PLATFORM_NAME)); +ENABLE_WIDGET_REGION_macosx = ENABLE_WIDGET_REGION; ENABLE_WORKERS = ENABLE_WORKERS; ENABLE_XSLT = ENABLE_XSLT; -FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_EXCLUSIONS) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SHADERS) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_STICKY_POSITION) $(ENABLE_CSS_VARIABLES) $(ENABLE_CSS3_FLEXBOX) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIALOG_ELEMENT) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_IFRAME_SEAMLESS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_ELEMENT) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_UNDO_MANAGER) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT); +FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_EXCLUSIONS) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_HIERARCHIES) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SHADERS) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_STICKY_POSITION) $(ENABLE_CSS_VARIABLES) $(ENABLE_CSS3_FLEXBOX) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIALOG_ELEMENT) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_IFRAME_SEAMLESS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_ELEMENT) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_UNDO_MANAGER) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WIDGET_REGION) $(ENABLE_WORKERS) $(ENABLE_XSLT); diff --git a/Source/JavaScriptCore/Configurations/Version.xcconfig b/Source/JavaScriptCore/Configurations/Version.xcconfig index daf808e05..b619d3602 100644 --- a/Source/JavaScriptCore/Configurations/Version.xcconfig +++ b/Source/JavaScriptCore/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 537; -MINOR_VERSION = 3; +MINOR_VERSION = 6; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am index e21ad80d7..ab8b110c2 100644 --- a/Source/JavaScriptCore/GNUmakefile.list.am +++ b/Source/JavaScriptCore/GNUmakefile.list.am @@ -227,6 +227,8 @@ javascriptcore_sources += \ Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp \ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp \ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h \ + Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp \ + Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h \ Source/JavaScriptCore/dfg/DFGThunks.cpp \ Source/JavaScriptCore/dfg/DFGThunks.h \ Source/JavaScriptCore/dfg/DFGValueRecoveryOverride.h \ @@ -262,6 +264,7 @@ javascriptcore_sources += \ Source/JavaScriptCore/heap/IncrementalSweeper.h \ Source/JavaScriptCore/heap/IncrementalSweeper.cpp \ Source/JavaScriptCore/heap/SlotVisitor.h \ + Source/JavaScriptCore/heap/SlotVisitorInlineMethods.h \ Source/JavaScriptCore/heap/HandleStack.cpp \ Source/JavaScriptCore/heap/HandleStack.h \ Source/JavaScriptCore/heap/HandleTypes.h \ diff --git a/Source/JavaScriptCore/JavaScriptCore.pri b/Source/JavaScriptCore/JavaScriptCore.pri index f6580c51f..fad36c974 100644 --- a/Source/JavaScriptCore/JavaScriptCore.pri +++ b/Source/JavaScriptCore/JavaScriptCore.pri @@ -32,9 +32,7 @@ INCLUDEPATH += \ $$SOURCE_DIR/ForwardingHeaders \ $$JAVASCRIPTCORE_GENERATED_SOURCES_DIR -win32-* { - LIBS += -lwinmm -} +win32-*: LIBS += -lwinmm wince* { INCLUDEPATH += $$QT.core.sources/../3rdparty/ce-compat diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index 5f27859d8..8032ed178 100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -81,7 +81,7 @@ EXPORTS ?byteCompile@Yarr@JSC@@YA?AV?$PassOwnPtr@UBytecodePattern@Yarr@JSC@@@WTF@@AAUYarrPattern@12@PAVBumpPointerAllocator@4@@Z ?byteSize@SourceProviderCache@JSC@@QBEIXZ ?calculateDSTOffset@WTF@@YANNN@Z - ?calculateStringHashAndLengthFromUTF8@Unicode@WTF@@YAIPBD0AAI1@Z + ?calculateStringHashAndLengthFromUTF8MaskingTop8Bits@Unicode@WTF@@YAIPBD0AAI1@Z ?calculateUTCOffset@WTF@@YAHXZ ?calculatedFunctionName@DebuggerCallFrame@JSC@@QBE?AVUString@2@XZ ?call@JSC@@YA?AVJSValue@1@PAVExecState@1@V21@W4CallType@1@ABTCallData@1@1ABVArgList@1@@Z @@ -201,7 +201,6 @@ EXPORTS ?getCallData@JSCell@JSC@@SA?AW4CallType@2@PAV12@AATCallData@2@@Z ?getCallableObjectSlow@JSC@@YAPAVJSCell@1@PAV21@@Z ?getConstructData@JSCell@JSC@@SA?AW4ConstructType@2@PAV12@AATConstructData@2@@Z - ?getCurrentLocalTime@WTF@@YAXPAUtm@@@Z ?getObject@JSCell@JSC@@QAEPAVJSObject@2@XZ ?getOwnPropertyDescriptor@JSGlobalObject@JSC@@SA_NPAVJSObject@2@PAVExecState@2@VPropertyName@2@AAVPropertyDescriptor@2@@Z ?getOwnPropertyDescriptor@JSObject@JSC@@SA_NPAV12@PAVExecState@2@VPropertyName@2@AAVPropertyDescriptor@2@@Z @@ -315,6 +314,7 @@ EXPORTS ?setOrderLowerFirst@Collator@WTF@@QAEX_N@Z ?setPrototype@JSObject@JSC@@QAEXAAVJSGlobalData@2@VJSValue@2@@Z ?setSetter@PropertyDescriptor@JSC@@QAEXVJSValue@2@@Z + ?setToCurrentLocalTime@GregorianDateTime@WTF@@QAEXXZ ?setUndefined@PropertyDescriptor@JSC@@QAEXXZ ?setUnwrappedObject@JSGlobalThis@JSC@@IAEXAAVJSGlobalData@2@PAVJSGlobalObject@2@@Z ?setUpStaticFunctionSlot@JSC@@YA_NPAVExecState@1@PBVHashEntry@1@PAVJSObject@1@VPropertyName@1@AAVPropertySlot@1@@Z @@ -352,8 +352,8 @@ EXPORTS ?toObject@JSCell@JSC@@QBEPAVJSObject@2@PAVExecState@2@PAVJSGlobalObject@2@@Z ?toObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@PAVJSGlobalObject@2@@Z ?toString@JSObject@JSC@@QBEPAVJSString@2@PAVExecState@2@@Z - ?toStringDecimal@DecimalNumber@WTF@@QBEIPA_WI@Z - ?toStringExponential@DecimalNumber@WTF@@QBEIPA_WI@Z + ?toStringDecimal@DecimalNumber@WTF@@QBEIPAEI@Z + ?toStringExponential@DecimalNumber@WTF@@QBEIPAEI@Z ?toStringSlowCase@JSValue@JSC@@ABEPAVJSString@2@PAVExecState@2@@Z ?toThisObject@JSObject@JSC@@SAPAV12@PAVJSCell@2@PAVExecState@2@@Z ?toThisObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@@Z diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 6caa07e6e..add311969 100644 --- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -138,6 +138,8 @@ 0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016E143FCD2F0068B77C /* DFGAbstractState.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */; }; + 0F63943F15C75F19006A597C /* DFGStructureCheckHoistingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0F63944015C75F1D006A597C /* DFGStructureCheckHoistingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */; }; 0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F766D2815A8CC1E008F363E /* JITStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F766D2615A8CC1B008F363E /* JITStubRoutine.cpp */; }; @@ -885,6 +887,8 @@ 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractValue.h; path = dfg/DFGAbstractValue.h; sourceTree = "<group>"; }; 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBasicBlock.h; path = dfg/DFGBasicBlock.h; sourceTree = "<group>"; }; 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; }; + 0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStructureCheckHoistingPhase.cpp; path = dfg/DFGStructureCheckHoistingPhase.cpp; sourceTree = "<group>"; }; + 0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureCheckHoistingPhase.h; path = dfg/DFGStructureCheckHoistingPhase.h; sourceTree = "<group>"; }; 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdjacencyList.h; path = dfg/DFGAdjacencyList.h; sourceTree = "<group>"; }; 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdge.h; path = dfg/DFGEdge.h; sourceTree = "<group>"; }; 0F766D1C15A5028D008F363E /* JITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubRoutine.h; sourceTree = "<group>"; }; @@ -2321,6 +2325,8 @@ 86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */, 86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */, 86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */, + 0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */, + 0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */, 0FC0979F146B28C700CF2442 /* DFGThunks.cpp */, 0FC097A0146B28C700CF2442 /* DFGThunks.h */, 0F2BDC3F1522801700CD8910 /* DFGValueRecoveryOverride.h */, @@ -2860,6 +2866,7 @@ 0F766D3915AE4A1F008F363E /* StructureStubClearingWatchpoint.h in Headers */, 0F766D4415B2A3C0008F363E /* DFGRegisterSet.h in Headers */, 0F766D4615B3701F008F363E /* DFGScratchRegisterAllocator.h in Headers */, + 0F63943F15C75F19006A597C /* DFGStructureCheckHoistingPhase.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3457,6 +3464,7 @@ 0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */, 0F766D3415AE2538008F363E /* JumpReplacementWatchpoint.cpp in Sources */, 0F766D3815AE4A1C008F363E /* StructureStubClearingWatchpoint.cpp in Sources */, + 0F63944015C75F1D006A597C /* DFGStructureCheckHoistingPhase.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri index 035656f0c..3d0e41df4 100644 --- a/Source/JavaScriptCore/Target.pri +++ b/Source/JavaScriptCore/Target.pri @@ -26,10 +26,6 @@ CONFIG += staticlib } } -wince* { - SOURCES += $$QT.core.sources/../3rdparty/ce-compat/ce_time.c -} - include(yarr/yarr.pri) INSTALLDEPS += all @@ -126,6 +122,7 @@ SOURCES += \ dfg/DFGSpeculativeJIT.cpp \ dfg/DFGSpeculativeJIT32_64.cpp \ dfg/DFGSpeculativeJIT64.cpp \ + dfg/DFGStructureCheckHoistingPhase.cpp \ dfg/DFGThunks.cpp \ dfg/DFGValueSource.cpp \ dfg/DFGVariableEvent.cpp \ diff --git a/Source/JavaScriptCore/assembler/ARMAssembler.cpp b/Source/JavaScriptCore/assembler/ARMAssembler.cpp index 362fcc630..533640ea8 100644 --- a/Source/JavaScriptCore/assembler/ARMAssembler.cpp +++ b/Source/JavaScriptCore/assembler/ARMAssembler.cpp @@ -46,7 +46,7 @@ void ARMAssembler::patchConstantPoolLoad(void* loadAddr, void* constPoolAddr) ASSERT(diff <= 0xfff); *ldr = (*ldr & ~0xfff) | diff; } else - *ldr = (*ldr & ~(0xfff | ARMAssembler::DT_UP)) | sizeof(ARMWord); + *ldr = (*ldr & ~(0xfff | ARMAssembler::DataTransferUp)) | sizeof(ARMWord); } // Handle immediates @@ -56,7 +56,7 @@ ARMWord ARMAssembler::getOp2(ARMWord imm) int rol; if (imm <= 0xff) - return OP2_IMM | imm; + return Op2Immediate | imm; if ((imm & 0xff000000) == 0) { imm <<= 8; @@ -83,9 +83,9 @@ ARMWord ARMAssembler::getOp2(ARMWord imm) } if ((imm & 0x00ffffff) == 0) - return OP2_IMM | (imm >> 24) | (rol << 8); + return Op2Immediate | (imm >> 24) | (rol << 8); - return INVALID_IMM; + return InvalidImmediate; } int ARMAssembler::genInt(int reg, ARMWord imm, bool positive) @@ -129,10 +129,10 @@ int ARMAssembler::genInt(int reg, ARMWord imm, bool positive) ASSERT((imm & 0xff) == 0); if ((imm & 0xff000000) == 0) { - imm1 = OP2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8); - imm2 = OP2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8); + imm1 = Op2Immediate | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8); + imm2 = Op2Immediate | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8); } else if (imm & 0xc0000000) { - imm1 = OP2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8); + imm1 = Op2Immediate | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8); imm <<= 8; rol += 4; @@ -152,7 +152,7 @@ int ARMAssembler::genInt(int reg, ARMWord imm, bool positive) } if ((imm & 0x00ffffff) == 0) - imm2 = OP2_IMM | (imm >> 24) | ((rol & 0xf) << 8); + imm2 = Op2Immediate | (imm >> 24) | ((rol & 0xf) << 8); else return 0; } else { @@ -166,7 +166,7 @@ int ARMAssembler::genInt(int reg, ARMWord imm, bool positive) rol += 1; } - imm1 = OP2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8); + imm1 = Op2Immediate | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8); imm <<= 8; rol += 4; @@ -181,7 +181,7 @@ int ARMAssembler::genInt(int reg, ARMWord imm, bool positive) } if ((imm & 0x00ffffff) == 0) - imm2 = OP2_IMM | (imm >> 24) | ((rol & 0xf) << 8); + imm2 = Op2Immediate | (imm >> 24) | ((rol & 0xf) << 8); else return 0; } @@ -203,13 +203,13 @@ ARMWord ARMAssembler::getImm(ARMWord imm, int tmpReg, bool invert) // Do it by 1 instruction tmp = getOp2(imm); - if (tmp != INVALID_IMM) + if (tmp != InvalidImmediate) return tmp; tmp = getOp2(~imm); - if (tmp != INVALID_IMM) { + if (tmp != InvalidImmediate) { if (invert) - return tmp | OP2_INV_IMM; + return tmp | Op2InvertedImmediate; mvn_r(tmpReg, tmp); return tmpReg; } @@ -223,13 +223,13 @@ void ARMAssembler::moveImm(ARMWord imm, int dest) // Do it by 1 instruction tmp = getOp2(imm); - if (tmp != INVALID_IMM) { + if (tmp != InvalidImmediate) { mov_r(dest, tmp); return; } tmp = getOp2(~imm); - if (tmp != INVALID_IMM) { + if (tmp != InvalidImmediate) { mvn_r(dest, tmp); return; } @@ -241,7 +241,7 @@ ARMWord ARMAssembler::encodeComplexImm(ARMWord imm, int dest) { #if WTF_ARM_ARCH_AT_LEAST(7) ARMWord tmp = getImm16Op2(imm); - if (tmp != INVALID_IMM) { + if (tmp != InvalidImmediate) { movw_r(dest, tmp); return dest; } @@ -268,7 +268,7 @@ void ARMAssembler::dataTransfer32(DataTransferTypeA transferType, RegisterID src if (offset <= 0xfff) dtr_u(transferType, srcDst, base, offset); else if (offset <= 0xfffff) { - add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8)); + add_r(ARMRegisters::S0, base, Op2Immediate | (offset >> 12) | (10 << 8)); dtr_u(transferType, srcDst, ARMRegisters::S0, (offset & 0xfff)); } else { moveImm(offset, ARMRegisters::S0); @@ -278,7 +278,7 @@ void ARMAssembler::dataTransfer32(DataTransferTypeA transferType, RegisterID src if (offset >= -0xfff) dtr_d(transferType, srcDst, base, -offset); else if (offset >= -0xfffff) { - sub_r(ARMRegisters::S0, base, OP2_IMM | (-offset >> 12) | (10 << 8)); + sub_r(ARMRegisters::S0, base, Op2Immediate | (-offset >> 12) | (10 << 8)); dtr_d(transferType, srcDst, ARMRegisters::S0, (-offset & 0xfff)); } else { moveImm(offset, ARMRegisters::S0); @@ -307,7 +307,7 @@ void ARMAssembler::dataTransfer16(DataTransferTypeB transferType, RegisterID src if (offset <= 0xff) dtrh_u(transferType, srcDst, base, getOp2Half(offset)); else if (offset <= 0xffff) { - add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 8) | (12 << 8)); + add_r(ARMRegisters::S0, base, Op2Immediate | (offset >> 8) | (12 << 8)); dtrh_u(transferType, srcDst, ARMRegisters::S0, getOp2Half(offset & 0xff)); } else { moveImm(offset, ARMRegisters::S0); @@ -317,7 +317,7 @@ void ARMAssembler::dataTransfer16(DataTransferTypeB transferType, RegisterID src if (offset >= -0xff) dtrh_d(transferType, srcDst, base, getOp2Half(-offset)); else if (offset >= -0xffff) { - sub_r(ARMRegisters::S0, base, OP2_IMM | (-offset >> 8) | (12 << 8)); + sub_r(ARMRegisters::S0, base, Op2Immediate | (-offset >> 8) | (12 << 8)); dtrh_d(transferType, srcDst, ARMRegisters::S0, getOp2Half(-offset & 0xff)); } else { moveImm(offset, ARMRegisters::S0); @@ -346,7 +346,7 @@ void ARMAssembler::dataTransferFloat(DataTransferTypeFloat transferType, FPRegis return; } if (offset <= 0x3ffff && offset >= 0) { - add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 10) | (11 << 8)); + add_r(ARMRegisters::S0, base, Op2Immediate | (offset >> 10) | (11 << 8)); fdtr_u(transferType, srcDst, ARMRegisters::S0, (offset >> 2) & 0xff); return; } @@ -357,7 +357,7 @@ void ARMAssembler::dataTransferFloat(DataTransferTypeFloat transferType, FPRegis return; } if (offset <= 0x3ffff && offset >= 0) { - sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 10) | (11 << 8)); + sub_r(ARMRegisters::S0, base, Op2Immediate | (offset >> 10) | (11 << 8)); fdtr_d(transferType, srcDst, ARMRegisters::S0, (offset >> 2) & 0xff); return; } @@ -392,10 +392,10 @@ PassRefPtr<ExecutableMemoryHandle> ARMAssembler::executableCopy(JSGlobalData& gl ARMWord* addr = getLdrImmAddress(ldrAddr); if (*addr != InvalidBranchTarget) { if (!(iter->m_offset & 1)) { - intptr_t difference = reinterpret_cast_ptr<ARMWord*>(data + *addr) - (ldrAddr + DefaultPrefetching); + intptr_t difference = reinterpret_cast_ptr<ARMWord*>(data + *addr) - (ldrAddr + DefaultPrefetchOffset); - if ((difference <= BOFFSET_MAX && difference >= BOFFSET_MIN)) { - *ldrAddr = B | getConditionalField(*ldrAddr) | (difference & BRANCH_MASK); + if ((difference <= MaximumBranchOffsetDistance && difference >= MinimumBranchOffsetDistance)) { + *ldrAddr = B | getConditionalField(*ldrAddr) | (difference & BranchOffsetMask); continue; } } diff --git a/Source/JavaScriptCore/assembler/ARMAssembler.h b/Source/JavaScriptCore/assembler/ARMAssembler.h index 87aed853e..ac918f31e 100644 --- a/Source/JavaScriptCore/assembler/ARMAssembler.h +++ b/Source/JavaScriptCore/assembler/ARMAssembler.h @@ -179,52 +179,50 @@ namespace JSC { }; enum { - OP2_IMM = (1 << 25), - OP2_IMM_HALF = (1 << 22), - OP2_INV_IMM = (1 << 26), - SET_CC = (1 << 20), - OP2_OFSREG = (1 << 25), + Op2Immediate = (1 << 25), + ImmediateForHalfWordTransfer = (1 << 22), + Op2InvertedImmediate = (1 << 26), + SetConditionalCodes = (1 << 20), + Op2IsRegisterArgument = (1 << 25), // Data transfer flags. - DT_UP = (1 << 23), - DT_WB = (1 << 21), - DT_PRE = (1 << 24), - DT_LOAD = (1 << 20), - DT_BYTE = (1 << 22), + DataTransferUp = (1 << 23), + DataTransferWriteBack = (1 << 21), + DataTransferPostUpdate = (1 << 24), + DataTransferLoad = (1 << 20), + ByteDataTransfer = (1 << 22), }; enum DataTransferTypeA { - LoadUint32 = 0x05000000 | DT_LOAD, - LoadUint8 = 0x05400000 | DT_LOAD, + LoadUint32 = 0x05000000 | DataTransferLoad, + LoadUint8 = 0x05400000 | DataTransferLoad, StoreUint32 = 0x05000000, StoreUint8 = 0x05400000, }; enum DataTransferTypeB { - LoadUint16 = 0x010000b0 | DT_LOAD, - LoadInt16 = 0x010000f0 | DT_LOAD, - LoadInt8 = 0x010000d0 | DT_LOAD, + LoadUint16 = 0x010000b0 | DataTransferLoad, + LoadInt16 = 0x010000f0 | DataTransferLoad, + LoadInt8 = 0x010000d0 | DataTransferLoad, StoreUint16 = 0x010000b0, }; enum DataTransferTypeFloat { - LoadFloat = 0x0d000a00 | DT_LOAD, - LoadDouble = 0x0d000b00 | DT_LOAD, + LoadFloat = 0x0d000a00 | DataTransferLoad, + LoadDouble = 0x0d000b00 | DataTransferLoad, StoreFloat = 0x0d000a00, StoreDouble = 0x0d000b00, }; // Masks of ARM instructions enum { - BRANCH_MASK = 0x00ffffff, - NONARM = 0xf0000000, - SDT_MASK = 0x0c000000, - SDT_OFFSET_MASK = 0xfff, + BranchOffsetMask = 0x00ffffff, + ConditionalFieldMask = 0xf0000000, + DataTransferOffsetMask = 0xfff, }; enum { - BOFFSET_MIN = -0x00800000, - BOFFSET_MAX = 0x007fffff, - SDT = 0x04000000, + MinimumBranchOffsetDistance = -0x00800000, + MaximumBranchOffsetDistance = 0x007fffff, }; enum { @@ -233,19 +231,28 @@ namespace JSC { padForAlign32 = 0xe12fff7f // 'bkpt 0xffff' instruction. }; - static const ARMWord INVALID_IMM = 0xf0000000; + static const ARMWord InvalidImmediate = 0xf0000000; static const ARMWord InvalidBranchTarget = 0xffffffff; - static const int DefaultPrefetching = 2; + static const int DefaultPrefetchOffset = 2; + + static const ARMWord BlxInstructionMask = 0x012fff30; + static const ARMWord LdrOrAddInstructionMask = 0x0ff00000; + static const ARMWord LdrPcImmediateInstructionMask = 0x0f7f0000; + + static const ARMWord AddImmediateInstruction = 0x02800000; + static const ARMWord BlxInstruction = 0x012fff30; + static const ARMWord LdrImmediateInstruction = 0x05900000; + static const ARMWord LdrPcImmediateInstruction = 0x051f0000; // Instruction formating - void emitInst(ARMWord op, int rd, int rn, ARMWord op2) + void emitInstruction(ARMWord op, int rd, int rn, ARMWord op2) { - ASSERT(((op2 & ~OP2_IMM) <= 0xfff) || (((op2 & ~OP2_IMM_HALF) <= 0xfff))); + ASSERT(((op2 & ~Op2Immediate) <= 0xfff) || (((op2 & ~ImmediateForHalfWordTransfer) <= 0xfff))); m_buffer.putInt(op | RN(rn) | RD(rd) | op2); } - void emitDoublePrecisionInst(ARMWord op, int dd, int dn, int dm) + void emitDoublePrecisionInstruction(ARMWord op, int dd, int dn, int dm) { ASSERT((dd >= 0 && dd <= 31) && (dn >= 0 && dn <= 31) && (dm >= 0 && dm <= 31)); m_buffer.putInt(op | ((dd & 0xf) << 12) | ((dd & 0x10) << (22 - 4)) @@ -253,7 +260,7 @@ namespace JSC { | (dm & 0xf) | ((dm & 0x10) << (5 - 4))); } - void emitSinglePrecisionInst(ARMWord op, int sd, int sn, int sm) + void emitSinglePrecisionInstruction(ARMWord op, int sd, int sn, int sm) { ASSERT((sd >= 0 && sd <= 31) && (sn >= 0 && sn <= 31) && (sm >= 0 && sm <= 31)); m_buffer.putInt(op | ((sd >> 1) << 12) | ((sd & 0x1) << 22) @@ -263,292 +270,292 @@ namespace JSC { void and_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | AND, rd, rn, op2); + emitInstruction(toARMWord(cc) | AND, rd, rn, op2); } void ands_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | AND | SET_CC, rd, rn, op2); + emitInstruction(toARMWord(cc) | AND | SetConditionalCodes, rd, rn, op2); } void eor_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | EOR, rd, rn, op2); + emitInstruction(toARMWord(cc) | EOR, rd, rn, op2); } void eors_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | EOR | SET_CC, rd, rn, op2); + emitInstruction(toARMWord(cc) | EOR | SetConditionalCodes, rd, rn, op2); } void sub_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | SUB, rd, rn, op2); + emitInstruction(toARMWord(cc) | SUB, rd, rn, op2); } void subs_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | SUB | SET_CC, rd, rn, op2); + emitInstruction(toARMWord(cc) | SUB | SetConditionalCodes, rd, rn, op2); } void rsb_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | RSB, rd, rn, op2); + emitInstruction(toARMWord(cc) | RSB, rd, rn, op2); } void rsbs_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | RSB | SET_CC, rd, rn, op2); + emitInstruction(toARMWord(cc) | RSB | SetConditionalCodes, rd, rn, op2); } void add_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | ADD, rd, rn, op2); + emitInstruction(toARMWord(cc) | ADD, rd, rn, op2); } void adds_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | ADD | SET_CC, rd, rn, op2); + emitInstruction(toARMWord(cc) | ADD | SetConditionalCodes, rd, rn, op2); } void adc_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | ADC, rd, rn, op2); + emitInstruction(toARMWord(cc) | ADC, rd, rn, op2); } void adcs_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | ADC | SET_CC, rd, rn, op2); + emitInstruction(toARMWord(cc) | ADC | SetConditionalCodes, rd, rn, op2); } void sbc_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | SBC, rd, rn, op2); + emitInstruction(toARMWord(cc) | SBC, rd, rn, op2); } void sbcs_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | SBC | SET_CC, rd, rn, op2); + emitInstruction(toARMWord(cc) | SBC | SetConditionalCodes, rd, rn, op2); } void rsc_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | RSC, rd, rn, op2); + emitInstruction(toARMWord(cc) | RSC, rd, rn, op2); } void rscs_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | RSC | SET_CC, rd, rn, op2); + emitInstruction(toARMWord(cc) | RSC | SetConditionalCodes, rd, rn, op2); } void tst_r(int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | TST | SET_CC, 0, rn, op2); + emitInstruction(toARMWord(cc) | TST | SetConditionalCodes, 0, rn, op2); } void teq_r(int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | TEQ | SET_CC, 0, rn, op2); + emitInstruction(toARMWord(cc) | TEQ | SetConditionalCodes, 0, rn, op2); } void cmp_r(int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2); + emitInstruction(toARMWord(cc) | CMP | SetConditionalCodes, 0, rn, op2); } void cmn_r(int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | CMN | SET_CC, 0, rn, op2); + emitInstruction(toARMWord(cc) | CMN | SetConditionalCodes, 0, rn, op2); } void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2); + emitInstruction(toARMWord(cc) | ORR, rd, rn, op2); } void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | ORR | SET_CC, rd, rn, op2); + emitInstruction(toARMWord(cc) | ORR | SetConditionalCodes, rd, rn, op2); } void mov_r(int rd, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | MOV, rd, ARMRegisters::r0, op2); + emitInstruction(toARMWord(cc) | MOV, rd, ARMRegisters::r0, op2); } #if WTF_ARM_ARCH_AT_LEAST(7) void movw_r(int rd, ARMWord op2, Condition cc = AL) { ASSERT((op2 | 0xf0fff) == 0xf0fff); - m_buffer.putInt(static_cast<ARMWord>(cc) | MOVW | RD(rd) | op2); + m_buffer.putInt(toARMWord(cc) | MOVW | RD(rd) | op2); } void movt_r(int rd, ARMWord op2, Condition cc = AL) { ASSERT((op2 | 0xf0fff) == 0xf0fff); - m_buffer.putInt(static_cast<ARMWord>(cc) | MOVT | RD(rd) | op2); + m_buffer.putInt(toARMWord(cc) | MOVT | RD(rd) | op2); } #endif void movs_r(int rd, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | MOV | SET_CC, rd, ARMRegisters::r0, op2); + emitInstruction(toARMWord(cc) | MOV | SetConditionalCodes, rd, ARMRegisters::r0, op2); } void bic_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | BIC, rd, rn, op2); + emitInstruction(toARMWord(cc) | BIC, rd, rn, op2); } void bics_r(int rd, int rn, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | BIC | SET_CC, rd, rn, op2); + emitInstruction(toARMWord(cc) | BIC | SetConditionalCodes, rd, rn, op2); } void mvn_r(int rd, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | MVN, rd, ARMRegisters::r0, op2); + emitInstruction(toARMWord(cc) | MVN, rd, ARMRegisters::r0, op2); } void mvns_r(int rd, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | MVN | SET_CC, rd, ARMRegisters::r0, op2); + emitInstruction(toARMWord(cc) | MVN | SetConditionalCodes, rd, ARMRegisters::r0, op2); } void mul_r(int rd, int rn, int rm, Condition cc = AL) { - m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | RN(rd) | RS(rn) | RM(rm)); + m_buffer.putInt(toARMWord(cc) | MUL | RN(rd) | RS(rn) | RM(rm)); } void muls_r(int rd, int rn, int rm, Condition cc = AL) { - m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | SET_CC | RN(rd) | RS(rn) | RM(rm)); + m_buffer.putInt(toARMWord(cc) | MUL | SetConditionalCodes | RN(rd) | RS(rn) | RM(rm)); } void mull_r(int rdhi, int rdlo, int rn, int rm, Condition cc = AL) { - m_buffer.putInt(static_cast<ARMWord>(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm)); + m_buffer.putInt(toARMWord(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm)); } void vmov_f64_r(int dd, int dm, Condition cc = AL) { - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VMOV_F64, dd, 0, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VMOV_F64, dd, 0, dm); } void vadd_f64_r(int dd, int dn, int dm, Condition cc = AL) { - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VADD_F64, dd, dn, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VADD_F64, dd, dn, dm); } void vdiv_f64_r(int dd, int dn, int dm, Condition cc = AL) { - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VDIV_F64, dd, dn, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VDIV_F64, dd, dn, dm); } void vsub_f64_r(int dd, int dn, int dm, Condition cc = AL) { - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VSUB_F64, dd, dn, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VSUB_F64, dd, dn, dm); } void vmul_f64_r(int dd, int dn, int dm, Condition cc = AL) { - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VMUL_F64, dd, dn, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VMUL_F64, dd, dn, dm); } void vcmp_f64_r(int dd, int dm, Condition cc = AL) { - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCMP_F64, dd, 0, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VCMP_F64, dd, 0, dm); } void vsqrt_f64_r(int dd, int dm, Condition cc = AL) { - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VSQRT_F64, dd, 0, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VSQRT_F64, dd, 0, dm); } void vabs_f64_r(int dd, int dm, Condition cc = AL) { - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VABS_F64, dd, 0, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VABS_F64, dd, 0, dm); } void vneg_f64_r(int dd, int dm, Condition cc = AL) { - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VNEG_F64, dd, 0, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VNEG_F64, dd, 0, dm); } void ldr_imm(int rd, ARMWord imm, Condition cc = AL) { - m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | LoadUint32 | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm, true); + m_buffer.putIntWithConstantInt(toARMWord(cc) | LoadUint32 | DataTransferUp | RN(ARMRegisters::pc) | RD(rd), imm, true); } void ldr_un_imm(int rd, ARMWord imm, Condition cc = AL) { - m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | LoadUint32 | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm); + m_buffer.putIntWithConstantInt(toARMWord(cc) | LoadUint32 | DataTransferUp | RN(ARMRegisters::pc) | RD(rd), imm); } void dtr_u(DataTransferTypeA transferType, int rd, int rb, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | transferType | DT_UP, rd, rb, op2); + emitInstruction(toARMWord(cc) | transferType | DataTransferUp, rd, rb, op2); } void dtr_ur(DataTransferTypeA transferType, int rd, int rb, int rm, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | transferType | DT_UP | OP2_OFSREG, rd, rb, rm); + emitInstruction(toARMWord(cc) | transferType | DataTransferUp | Op2IsRegisterArgument, rd, rb, rm); } void dtr_d(DataTransferTypeA transferType, int rd, int rb, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | transferType, rd, rb, op2); + emitInstruction(toARMWord(cc) | transferType, rd, rb, op2); } void dtr_dr(DataTransferTypeA transferType, int rd, int rb, int rm, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | transferType | OP2_OFSREG, rd, rb, rm); + emitInstruction(toARMWord(cc) | transferType | Op2IsRegisterArgument, rd, rb, rm); } void dtrh_u(DataTransferTypeB transferType, int rd, int rb, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | transferType | DT_UP, rd, rb, op2); + emitInstruction(toARMWord(cc) | transferType | DataTransferUp, rd, rb, op2); } void dtrh_ur(DataTransferTypeB transferType, int rd, int rn, int rm, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | transferType | DT_UP, rd, rn, rm); + emitInstruction(toARMWord(cc) | transferType | DataTransferUp, rd, rn, rm); } void dtrh_d(DataTransferTypeB transferType, int rd, int rb, ARMWord op2, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | transferType, rd, rb, op2); + emitInstruction(toARMWord(cc) | transferType, rd, rb, op2); } void dtrh_dr(DataTransferTypeB transferType, int rd, int rn, int rm, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | transferType, rd, rn, rm); + emitInstruction(toARMWord(cc) | transferType, rd, rn, rm); } void fdtr_u(DataTransferTypeFloat type, int rd, int rb, ARMWord op2, Condition cc = AL) { ASSERT(op2 <= 0xff && rd <= 15); /* Only d0-d15 and s0, s2, s4 ... s30 are supported. */ - m_buffer.putInt(static_cast<ARMWord>(cc) | DT_UP | type | (rd << 12) | RN(rb) | op2); + m_buffer.putInt(toARMWord(cc) | DataTransferUp | type | (rd << 12) | RN(rb) | op2); } void fdtr_d(DataTransferTypeFloat type, int rd, int rb, ARMWord op2, Condition cc = AL) { ASSERT(op2 <= 0xff && rd <= 15); /* Only d0-d15 and s0, s2, s4 ... s30 are supported. */ - m_buffer.putInt(static_cast<ARMWord>(cc) | type | (rd << 12) | RN(rb) | op2); + m_buffer.putInt(toARMWord(cc) | type | (rd << 12) | RN(rb) | op2); } void push_r(int reg, Condition cc = AL) { ASSERT(ARMWord(reg) <= 0xf); - m_buffer.putInt(static_cast<ARMWord>(cc) | StoreUint32 | DT_WB | RN(ARMRegisters::sp) | RD(reg) | 0x4); + m_buffer.putInt(toARMWord(cc) | StoreUint32 | DataTransferWriteBack | RN(ARMRegisters::sp) | RD(reg) | 0x4); } void pop_r(int reg, Condition cc = AL) { ASSERT(ARMWord(reg) <= 0xf); - m_buffer.putInt(static_cast<ARMWord>(cc) | (LoadUint32 ^ DT_PRE) | DT_UP | RN(ARMRegisters::sp) | RD(reg) | 0x4); + m_buffer.putInt(toARMWord(cc) | (LoadUint32 ^ DataTransferPostUpdate) | DataTransferUp | RN(ARMRegisters::sp) | RD(reg) | 0x4); } inline void poke_r(int reg, Condition cc = AL) @@ -564,65 +571,65 @@ namespace JSC { void vmov_vfp64_r(int sm, int rt, int rt2, Condition cc = AL) { ASSERT(rt != rt2); - m_buffer.putInt(static_cast<ARMWord>(cc) | VMOV_VFP64 | RN(rt2) | RD(rt) | (sm & 0xf) | ((sm & 0x10) << (5 - 4))); + m_buffer.putInt(toARMWord(cc) | VMOV_VFP64 | RN(rt2) | RD(rt) | (sm & 0xf) | ((sm & 0x10) << (5 - 4))); } void vmov_arm64_r(int rt, int rt2, int sm, Condition cc = AL) { ASSERT(rt != rt2); - m_buffer.putInt(static_cast<ARMWord>(cc) | VMOV_ARM64 | RN(rt2) | RD(rt) | (sm & 0xf) | ((sm & 0x10) << (5 - 4))); + m_buffer.putInt(toARMWord(cc) | VMOV_ARM64 | RN(rt2) | RD(rt) | (sm & 0xf) | ((sm & 0x10) << (5 - 4))); } void vmov_vfp32_r(int sn, int rt, Condition cc = AL) { ASSERT(rt <= 15); - emitSinglePrecisionInst(static_cast<ARMWord>(cc) | VMOV_VFP32, rt << 1, sn, 0); + emitSinglePrecisionInstruction(toARMWord(cc) | VMOV_VFP32, rt << 1, sn, 0); } void vmov_arm32_r(int rt, int sn, Condition cc = AL) { ASSERT(rt <= 15); - emitSinglePrecisionInst(static_cast<ARMWord>(cc) | VMOV_ARM32, rt << 1, sn, 0); + emitSinglePrecisionInstruction(toARMWord(cc) | VMOV_ARM32, rt << 1, sn, 0); } void vcvt_f64_s32_r(int dd, int sm, Condition cc = AL) { ASSERT(!(sm & 0x1)); // sm must be divisible by 2 - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_F64_S32, dd, 0, (sm >> 1)); + emitDoublePrecisionInstruction(toARMWord(cc) | VCVT_F64_S32, dd, 0, (sm >> 1)); } void vcvt_s32_f64_r(int sd, int dm, Condition cc = AL) { ASSERT(!(sd & 0x1)); // sd must be divisible by 2 - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_S32_F64, (sd >> 1), 0, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VCVT_S32_F64, (sd >> 1), 0, dm); } void vcvt_u32_f64_r(int sd, int dm, Condition cc = AL) { ASSERT(!(sd & 0x1)); // sd must be divisible by 2 - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_U32_F64, (sd >> 1), 0, dm); + emitDoublePrecisionInstruction(toARMWord(cc) | VCVT_U32_F64, (sd >> 1), 0, dm); } void vcvt_f64_f32_r(int dd, int sm, Condition cc = AL) { ASSERT(dd <= 15 && sm <= 15); - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_F64_F32, dd, 0, sm); + emitDoublePrecisionInstruction(toARMWord(cc) | VCVT_F64_F32, dd, 0, sm); } void vcvt_f32_f64_r(int dd, int sm, Condition cc = AL) { ASSERT(dd <= 15 && sm <= 15); - emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_F32_F64, dd, 0, sm); + emitDoublePrecisionInstruction(toARMWord(cc) | VCVT_F32_F64, dd, 0, sm); } void vmrs_apsr(Condition cc = AL) { - m_buffer.putInt(static_cast<ARMWord>(cc) | VMRS_APSR); + m_buffer.putInt(toARMWord(cc) | VMRS_APSR); } void clz_r(int rd, int rm, Condition cc = AL) { - m_buffer.putInt(static_cast<ARMWord>(cc) | CLZ | RD(rd) | RM(rm)); + m_buffer.putInt(toARMWord(cc) | CLZ | RD(rd) | RM(rm)); } void bkpt(ARMWord value) @@ -637,12 +644,12 @@ namespace JSC { void bx(int rm, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | BX, 0, 0, RM(rm)); + emitInstruction(toARMWord(cc) | BX, 0, 0, RM(rm)); } AssemblerLabel blx(int rm, Condition cc = AL) { - emitInst(static_cast<ARMWord>(cc) | BLX, 0, 0, RM(rm)); + emitInstruction(toARMWord(cc) | BLX, 0, 0, RM(rm)); return m_buffer.label(); } @@ -773,28 +780,28 @@ namespace JSC { static ARMWord* getLdrImmAddress(ARMWord* insn) { // Check for call - if ((*insn & 0x0f7f0000) != 0x051f0000) { + if ((*insn & LdrPcImmediateInstructionMask) != LdrPcImmediateInstruction) { // Must be BLX - ASSERT((*insn & 0x012fff30) == 0x012fff30); + ASSERT((*insn & BlxInstructionMask) == BlxInstruction); insn--; } // Must be an ldr ..., [pc +/- imm] - ASSERT((*insn & 0x0f7f0000) == 0x051f0000); + ASSERT((*insn & LdrPcImmediateInstructionMask) == LdrPcImmediateInstruction); - ARMWord addr = reinterpret_cast<ARMWord>(insn) + DefaultPrefetching * sizeof(ARMWord); - if (*insn & DT_UP) - return reinterpret_cast<ARMWord*>(addr + (*insn & SDT_OFFSET_MASK)); - return reinterpret_cast<ARMWord*>(addr - (*insn & SDT_OFFSET_MASK)); + ARMWord addr = reinterpret_cast<ARMWord>(insn) + DefaultPrefetchOffset * sizeof(ARMWord); + if (*insn & DataTransferUp) + return reinterpret_cast<ARMWord*>(addr + (*insn & DataTransferOffsetMask)); + return reinterpret_cast<ARMWord*>(addr - (*insn & DataTransferOffsetMask)); } static ARMWord* getLdrImmAddressOnPool(ARMWord* insn, uint32_t* constPool) { // Must be an ldr ..., [pc +/- imm] - ASSERT((*insn & 0x0f7f0000) == 0x051f0000); + ASSERT((*insn & LdrPcImmediateInstructionMask) == LdrPcImmediateInstruction); if (*insn & 0x1) - return reinterpret_cast<ARMWord*>(constPool + ((*insn & SDT_OFFSET_MASK) >> 1)); + return reinterpret_cast<ARMWord*>(constPool + ((*insn & DataTransferOffsetMask) >> 1)); return getLdrImmAddress(insn); } @@ -808,8 +815,8 @@ namespace JSC { static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value) { value = (value << 1) + 1; - ASSERT(!(value & ~0xfff)); - return (load & ~0xfff) | value; + ASSERT(!(value & ~DataTransferOffsetMask)); + return (load & ~DataTransferOffsetMask) | value; } static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr); @@ -839,7 +846,7 @@ namespace JSC { ARMWord* instruction = reinterpret_cast<ARMWord*>(where); ASSERT((*instruction & 0x0f700000) == LoadUint32); if (value >= 0) - *instruction = (*instruction & 0xff7ff000) | DT_UP | value; + *instruction = (*instruction & 0xff7ff000) | DataTransferUp | value; else *instruction = (*instruction & 0xff7ff000) | -value; cacheFlush(instruction, sizeof(ARMWord)); @@ -860,7 +867,7 @@ namespace JSC { { ARMWord* insn = reinterpret_cast<ARMWord*>(getAbsoluteJumpAddress(m_buffer.data(), from.m_offset)); ARMWord* addr = getLdrImmAddressOnPool(insn, m_buffer.poolAddress()); - *addr = static_cast<ARMWord>(to.m_offset); + *addr = toARMWord(to.m_offset); } static void linkJump(void* code, AssemblerLabel from, void* to) @@ -891,13 +898,13 @@ namespace JSC { static void replaceWithJump(void* instructionStart, void* to) { ARMWord* instruction = reinterpret_cast<ARMWord*>(instructionStart) - 1; - intptr_t difference = reinterpret_cast<intptr_t>(to) - (reinterpret_cast<intptr_t>(instruction) + DefaultPrefetching * sizeof(ARMWord)); + intptr_t difference = reinterpret_cast<intptr_t>(to) - (reinterpret_cast<intptr_t>(instruction) + DefaultPrefetchOffset * sizeof(ARMWord)); if (!(difference & 1)) { difference >>= 2; - if ((difference <= BOFFSET_MAX && difference >= BOFFSET_MIN)) { + if ((difference <= MaximumBranchOffsetDistance && difference >= MinimumBranchOffsetDistance)) { // Direct branch. - instruction[0] = B | AL | (difference & BRANCH_MASK); + instruction[0] = B | AL | (difference & BranchOffsetMask); cacheFlush(instruction, sizeof(ARMWord)); return; } @@ -919,9 +926,9 @@ namespace JSC { ARMWord* instruction = reinterpret_cast<ARMWord*>(instructionStart); cacheFlush(instruction, sizeof(ARMWord)); - ASSERT((*instruction & 0x0ff00000) == 0x02800000 || (*instruction & 0x0ff00000) == 0x05900000); - if ((*instruction & 0x0ff00000) == 0x02800000) { - *instruction = (*instruction & 0xf00fffff) | 0x05900000; + ASSERT((*instruction & LdrOrAddInstructionMask) == AddImmediateInstruction || (*instruction & LdrOrAddInstructionMask) == LdrImmediateInstruction); + if ((*instruction & LdrOrAddInstructionMask) == AddImmediateInstruction) { + *instruction = (*instruction & ~LdrOrAddInstructionMask) | LdrImmediateInstruction; cacheFlush(instruction, sizeof(ARMWord)); } } @@ -931,9 +938,9 @@ namespace JSC { ARMWord* instruction = reinterpret_cast<ARMWord*>(instructionStart); cacheFlush(instruction, sizeof(ARMWord)); - ASSERT((*instruction & 0x0ff00000) == 0x02800000 || (*instruction & 0x0ff00000) == 0x05900000); - if ((*instruction & 0x0ff00000) == 0x05900000) { - *instruction = (*instruction & 0xf00fffff) | 0x02800000; + ASSERT((*instruction & LdrOrAddInstructionMask) == AddImmediateInstruction || (*instruction & LdrOrAddInstructionMask) == LdrImmediateInstruction); + if ((*instruction & LdrOrAddInstructionMask) == LdrImmediateInstruction) { + *instruction = (*instruction & ~LdrOrAddInstructionMask) | AddImmediateInstruction; cacheFlush(instruction, sizeof(ARMWord)); } } @@ -965,13 +972,13 @@ namespace JSC { static ARMWord getOp2Byte(ARMWord imm) { ASSERT(imm <= 0xff); - return OP2_IMM | imm; + return Op2Immediate | imm; } static ARMWord getOp2Half(ARMWord imm) { ASSERT(imm <= 0xff); - return OP2_IMM_HALF | (imm & 0x0f) | ((imm & 0xf0) << 4); + return ImmediateForHalfWordTransfer | (imm & 0x0f) | ((imm & 0xf0) << 4); } #if WTF_ARM_ARCH_AT_LEAST(7) @@ -979,7 +986,7 @@ namespace JSC { { if (imm <= 0xffff) return (imm & 0xf000) << 4 | (imm & 0xfff); - return INVALID_IMM; + return InvalidImmediate; } #endif ARMWord getImm(ARMWord imm, int tmpReg, bool invert = false); @@ -1000,8 +1007,8 @@ namespace JSC { static ARMWord placeConstantPoolBarrier(int offset) { offset = (offset - sizeof(ARMWord)) >> 2; - ASSERT((offset <= BOFFSET_MAX && offset >= BOFFSET_MIN)); - return AL | B | (offset & BRANCH_MASK); + ASSERT((offset <= MaximumBranchOffsetDistance && offset >= MinimumBranchOffsetDistance)); + return AL | B | (offset & BranchOffsetMask); } #if OS(LINUX) && COMPILER(RVCT) @@ -1067,7 +1074,17 @@ namespace JSC { static ARMWord getConditionalField(ARMWord i) { - return i & 0xf0000000; + return i & ConditionalFieldMask; + } + + static ARMWord toARMWord(Condition cc) + { + return static_cast<ARMWord>(cc); + } + + static ARMWord toARMWord(uint32_t u) + { + return static_cast<ARMWord>(u); } int genInt(int reg, ARMWord imm, bool positive); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp b/Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp index 3408c1230..a251a4376 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp @@ -87,7 +87,7 @@ void MacroAssemblerARM::load32WithUnalignedHalfWords(BaseIndex address, Register m_assembler.moveImm(address.offset, ARMRegisters::S0); m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, op2); m_assembler.dtrh_ur(ARMAssembler::LoadUint16, dest, address.base, ARMRegisters::S0); - m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::OP2_IMM | 0x2); + m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::Op2Immediate | 0x2); m_assembler.dtrh_ur(ARMAssembler::LoadUint16, ARMRegisters::S0, address.base, ARMRegisters::S0); } m_assembler.orr_r(dest, dest, m_assembler.lsl(ARMRegisters::S0, 16)); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h index 530f62b86..85d0ffbcc 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -137,8 +137,8 @@ public: void and32(TrustedImm32 imm, RegisterID dest) { ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true); - if (w & ARMAssembler::OP2_INV_IMM) - m_assembler.bics_r(dest, dest, w & ~ARMAssembler::OP2_INV_IMM); + if (w & ARMAssembler::Op2InvertedImmediate) + m_assembler.bics_r(dest, dest, w & ~ARMAssembler::Op2InvertedImmediate); else m_assembler.ands_r(dest, dest, w); } @@ -146,8 +146,8 @@ public: void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) { ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true); - if (w & ARMAssembler::OP2_INV_IMM) - m_assembler.bics_r(dest, src, w & ~ARMAssembler::OP2_INV_IMM); + if (w & ARMAssembler::Op2InvertedImmediate) + m_assembler.bics_r(dest, src, w & ~ARMAssembler::Op2InvertedImmediate); else m_assembler.ands_r(dest, src, w); } @@ -555,8 +555,8 @@ public: Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right, int useConstantPool = 0) { - ARMWord tmp = (right.m_value == 0x80000000) ? ARMAssembler::INVALID_IMM : m_assembler.getOp2(-right.m_value); - if (tmp != ARMAssembler::INVALID_IMM) + ARMWord tmp = (right.m_value == 0x80000000) ? ARMAssembler::InvalidImmediate : m_assembler.getOp2(-right.m_value); + if (tmp != ARMAssembler::InvalidImmediate) m_assembler.cmn_r(left, tmp); else m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0)); @@ -617,8 +617,8 @@ public: { ASSERT((cond == Zero) || (cond == NonZero)); ARMWord w = m_assembler.getImm(mask.m_value, ARMRegisters::S0, true); - if (w & ARMAssembler::OP2_INV_IMM) - m_assembler.bics_r(ARMRegisters::S0, reg, w & ~ARMAssembler::OP2_INV_IMM); + if (w & ARMAssembler::Op2InvertedImmediate) + m_assembler.bics_r(ARMRegisters::S0, reg, w & ~ARMAssembler::Op2InvertedImmediate); else m_assembler.tst_r(reg, w); return Jump(m_assembler.jmp(ARMCondition(cond))); @@ -1152,7 +1152,7 @@ public: m_assembler.bic_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(1)); ARMWord w = ARMAssembler::getOp2(0x80000000); - ASSERT(w != ARMAssembler::INVALID_IMM); + ASSERT(w != ARMAssembler::InvalidImmediate); m_assembler.cmp_r(ARMRegisters::S0, w); return Jump(m_assembler.jmp(branchType == BranchIfTruncateFailed ? ARMAssembler::EQ : ARMAssembler::NE)); } diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h index bc280acec..8b3ce9f03 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h @@ -43,6 +43,11 @@ public: { } + static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value) + { + return value >= -2147483647 - 1 && value <= 2147483647; + } + static const Scale ScalePtr = TimesFour; // For storing immediate number @@ -189,6 +194,12 @@ public: add32(dataTempRegister, dest); } + void add32(AbsoluteAddress src, RegisterID dest) + { + load32(src.m_ptr, dataTempRegister); + add32(dataTempRegister, dest); + } + void add32(RegisterID src, Address dest) { if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) { diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index 5374a537a..0e2a98bc5 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -1525,7 +1525,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int debugHookID = (++it)->u.operand; int firstLine = (++it)->u.operand; int lastLine = (++it)->u.operand; - dataLog("[%4d] debug\t\t %s, %d, %d", location, debugHookName(debugHookID), firstLine, lastLine); + int column = (++it)->u.operand; + dataLog("[%4d] debug\t\t %s, %d, %d, %d", location, debugHookName(debugHookID), firstLine, lastLine, column); dumpBytecodeCommentAndNewLine(location); break; } diff --git a/Source/JavaScriptCore/bytecode/DFGExitProfile.h b/Source/JavaScriptCore/bytecode/DFGExitProfile.h index d751ce654..e0aeba2bd 100644 --- a/Source/JavaScriptCore/bytecode/DFGExitProfile.h +++ b/Source/JavaScriptCore/bytecode/DFGExitProfile.h @@ -38,6 +38,7 @@ enum ExitKind { BadCache, // We exited because an inline cache was wrong. Overflow, // We exited because of overflow. NegativeZero, // We exited because we encountered negative zero. + OutOfBounds, // We had an out-of-bounds access to an array. InadequateCoverage, // We exited because we ended up in code that didn't have profiling coverage. ArgumentsEscaped, // We exited because arguments escaped but we didn't expect them to. Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME. diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h index 14cefb9d9..4308e79df 100644 --- a/Source/JavaScriptCore/bytecode/Opcode.h +++ b/Source/JavaScriptCore/bytecode/Opcode.h @@ -194,7 +194,7 @@ namespace JSC { macro(op_throw, 2) \ macro(op_throw_reference_error, 2) \ \ - macro(op_debug, 4) \ + macro(op_debug, 5) \ macro(op_profile_will_call, 2) \ macro(op_profile_did_call, 2) \ \ diff --git a/Source/JavaScriptCore/bytecode/SpeculatedType.cpp b/Source/JavaScriptCore/bytecode/SpeculatedType.cpp index 02d0f7e77..399ab29c8 100644 --- a/Source/JavaScriptCore/bytecode/SpeculatedType.cpp +++ b/Source/JavaScriptCore/bytecode/SpeculatedType.cpp @@ -226,9 +226,6 @@ SpeculatedType speculationFromClassInfo(const ClassInfo* classInfo) if (classInfo == &JSArray::s_info) return SpecArray; - if (classInfo == &JSString::s_info) - return SpecString; - if (classInfo == &Arguments::s_info) return SpecArguments; // Cannot distinguish between MyArguments and ForeignArguments at this stage. That happens in the flow analysis. @@ -269,6 +266,8 @@ SpeculatedType speculationFromClassInfo(const ClassInfo* classInfo) SpeculatedType speculationFromStructure(Structure* structure) { + if (structure->typeInfo().type() == StringType) + return SpecString; return speculationFromClassInfo(structure->classInfo()); } diff --git a/Source/JavaScriptCore/bytecode/SpeculatedType.h b/Source/JavaScriptCore/bytecode/SpeculatedType.h index 91fb4fe4d..4ecc53776 100644 --- a/Source/JavaScriptCore/bytecode/SpeculatedType.h +++ b/Source/JavaScriptCore/bytecode/SpeculatedType.h @@ -243,6 +243,11 @@ inline bool isOtherSpeculation(SpeculatedType value) return value == SpecOther; } +inline bool isOtherOrEmptySpeculation(SpeculatedType value) +{ + return !value || value == SpecOther; +} + inline bool isEmptySpeculation(SpeculatedType value) { return value == SpecEmpty; diff --git a/Source/JavaScriptCore/bytecode/ValueRecovery.h b/Source/JavaScriptCore/bytecode/ValueRecovery.h index ebca661d0..1be5201ea 100644 --- a/Source/JavaScriptCore/bytecode/ValueRecovery.h +++ b/Source/JavaScriptCore/bytecode/ValueRecovery.h @@ -76,6 +76,9 @@ public: { } + bool isSet() const { return m_technique != DontKnow; } + bool operator!() const { return !isSet(); } + static ValueRecovery alreadyInRegisterFile() { ValueRecovery result; diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 33f282c66..14a69b530 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -1249,7 +1249,7 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property) if (!currentScope->isVariableObject()) { flags |= ResolveResult::DynamicFlag; break; - } + } JSSymbolTableObject* currentVariableObject = jsCast<JSSymbolTableObject*>(currentScope); SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl()); @@ -2083,7 +2083,7 @@ void BytecodeGenerator::emitPopScope() m_dynamicScopeDepth--; } -void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine) +void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine, int column) { #if ENABLE(DEBUG_WITH_BREAKPOINT) if (debugHookID != DidReachBreakpoint) @@ -2096,6 +2096,7 @@ void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, in instructions().append(debugHookID); instructions().append(firstLine); instructions().append(lastLine); + instructions().append(column); } void BytecodeGenerator::pushFinallyContext(StatementNode* finallyBlock) diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h index 52fd7e83c..490991fa7 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -506,7 +506,7 @@ namespace JSC { RegisterID* emitPushScope(RegisterID* scope); void emitPopScope(); - void emitDebugHook(DebugHookID, int firstLine, int lastLine); + void emitDebugHook(DebugHookID, int firstLine, int lastLine, int column); int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; } bool hasFinaliser() { return m_finallyDepth != 0; } diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp index d243e8ce0..249f822e2 100644 --- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -202,18 +202,21 @@ bool ArrayNode::isSimpleArray() const return true; } -ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData, int lineNumber) const +ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData, int lineNumber, int columnNumber) const { ASSERT(!m_elision && !m_optional); ElementNode* ptr = m_element; if (!ptr) return 0; - ArgumentListNode* head = new (globalData) ArgumentListNode(lineNumber, ptr->value()); + JSTokenLocation location; + location.line = lineNumber; + location.column = columnNumber; + ArgumentListNode* head = new (globalData) ArgumentListNode(location, ptr->value()); ArgumentListNode* tail = head; ptr = ptr->next(); for (; ptr; ptr = ptr->next()) { ASSERT(!ptr->elision()); - tail = new (globalData) ArgumentListNode(lineNumber, tail, ptr->value()); + tail = new (globalData) ArgumentListNode(location, tail, ptr->value()); } return head; } @@ -536,7 +539,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, if (m_args->m_listNode->m_next) { ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray()); ASSERT(!m_args->m_listNode->m_next->m_next); - m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.globalData(), 0); + m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.globalData(), 0, 0); RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); CallArguments callArguments(generator, m_args); generator.emitNode(callArguments.thisRegister(), oldList->m_expr); @@ -1385,7 +1388,7 @@ RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); return generator.emitNode(m_next); } @@ -1428,7 +1431,7 @@ RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); return dst; } @@ -1436,7 +1439,7 @@ RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, Regis RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine()); + generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine(), column()); return dst; } @@ -1445,7 +1448,7 @@ RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, Re RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { ASSERT(m_expr); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); return generator.emitNode(dst, m_expr); } @@ -1454,7 +1457,7 @@ RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, Regist RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { ASSERT(m_expr); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); return generator.emitNode(m_expr); } @@ -1462,7 +1465,7 @@ RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, Registe RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); RefPtr<Label> afterThen = generator.newLabel(); @@ -1486,7 +1489,7 @@ RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); RefPtr<Label> beforeElse = generator.newLabel(); RefPtr<Label> afterElse = generator.newLabel(); @@ -1522,12 +1525,12 @@ RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* RefPtr<Label> topOfLoop = generator.newLabel(); generator.emitLabel(topOfLoop.get()); generator.emitLoopHint(); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); - + generator.emitDebugHook(WillExecuteStatement, lastLine(), lastLine(), column()); + RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); - generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); + generator.emitDebugHook(WillExecuteStatement, lastLine(), lastLine(), column()); if (m_expr->hasConditionContextCodegen()) generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false); else { @@ -1546,7 +1549,7 @@ RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); RefPtr<Label> topOfLoop = generator.newLabel(); - generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); + generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), m_expr->columnNo()); if (m_expr->hasConditionContextCodegen()) generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), true); else { @@ -1560,7 +1563,7 @@ RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); - generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); if (m_expr->hasConditionContextCodegen()) generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false); @@ -1581,7 +1584,7 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); if (m_expr1) generator.emitNode(generator.ignoredResult(), m_expr1); @@ -1602,7 +1605,7 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); if (m_expr3) generator.emitNode(generator.ignoredResult(), m_expr3); @@ -1629,7 +1632,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds if (!m_lexpr->isLocation()) return emitThrowReferenceError(generator, "Left side of for-in statement is not a reference."); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); if (m_init) generator.emitNode(generator.ignoredResult(), m_init); @@ -1692,7 +1695,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitLabel(scope->continueTarget()); generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get()); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); generator.emitLabel(scope->breakTarget()); return dst; } @@ -1702,7 +1705,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds // ECMA 12.7 RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); LabelScope* scope = generator.continueTarget(m_ident); ASSERT(scope); @@ -1716,7 +1719,7 @@ RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* // ECMA 12.8 RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); LabelScope* scope = generator.breakTarget(m_ident); ASSERT(scope); @@ -1729,7 +1732,7 @@ RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); ASSERT(generator.codeType() == FunctionCode); if (dst == generator.ignoredResult()) @@ -1745,7 +1748,7 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d generator.emitJumpScopes(l0.get(), 0); generator.emitLabel(l0.get()); } - generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); + generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine(), column()); return generator.emitReturn(r0); } @@ -1753,7 +1756,7 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); RefPtr<RegisterID> scope = generator.newTemporary(); generator.emitNode(scope.get(), m_expr); // scope must be protected until popped @@ -1918,7 +1921,7 @@ RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, Re RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch); @@ -1933,7 +1936,7 @@ RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); ASSERT(!generator.breakTarget(m_name)); @@ -1948,7 +1951,7 @@ RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); if (dst == generator.ignoredResult()) dst = 0; @@ -1965,7 +1968,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) // NOTE: The catch and finally blocks must be labeled explicitly, so the // optimizer knows they may be jumped to from anywhere. - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); RefPtr<Label> tryStartLabel = generator.newLabel(); if (m_finallyBlock) @@ -2022,13 +2025,13 @@ inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, Regi RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine(), column()); RefPtr<RegisterID> dstRegister = generator.newTemporary(); generator.emitLoad(dstRegister.get(), jsUndefined()); emitStatementsBytecode(generator, dstRegister.get()); - generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); + generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine(), column()); generator.emitEnd(dstRegister.get()); return 0; } @@ -2037,13 +2040,13 @@ RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine(), column()); RefPtr<RegisterID> dstRegister = generator.newTemporary(); generator.emitLoad(dstRegister.get(), jsUndefined()); emitStatementsBytecode(generator, dstRegister.get()); - generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); + generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine(), column()); generator.emitEnd(dstRegister.get()); return 0; } @@ -2052,7 +2055,7 @@ RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); + generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine(), column()); emitStatementsBytecode(generator, generator.ignoredResult()); StatementNode* singleStatement = this->singleStatement(); @@ -2068,7 +2071,7 @@ RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, Registe // If there is no return we must automatically insert one. if (!returnNode) { RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined()); - generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); + generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine(), column()); generator.emitReturn(r0); return 0; } diff --git a/Source/JavaScriptCore/debugger/Debugger.h b/Source/JavaScriptCore/debugger/Debugger.h index a23732918..bc743677e 100644 --- a/Source/JavaScriptCore/debugger/Debugger.h +++ b/Source/JavaScriptCore/debugger/Debugger.h @@ -42,14 +42,16 @@ namespace JSC { virtual void detach(JSGlobalObject*); virtual void sourceParsed(ExecState*, SourceProvider*, int errorLineNumber, const UString& errorMessage) = 0; - virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber, bool hasHandler) = 0; - virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; - virtual void callEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; - virtual void returnEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; - virtual void willExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; - virtual void didExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; - virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; + virtual void exception(const DebuggerCallFrame&, intptr_t, int, int, bool) = 0; + virtual void atStatement(const DebuggerCallFrame&, intptr_t, int, int) = 0; + virtual void callEvent(const DebuggerCallFrame&, intptr_t, int, int) = 0; + virtual void returnEvent(const DebuggerCallFrame&, intptr_t, int, int) = 0; + + virtual void willExecuteProgram(const DebuggerCallFrame&, intptr_t, int, int) = 0; + virtual void didExecuteProgram(const DebuggerCallFrame&, intptr_t, int, int) = 0; + virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t, int, int) = 0; + void recompileAllJSFunctions(JSGlobalData*); diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp index 01996f132..4f02ee793 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp @@ -950,7 +950,8 @@ bool AbstractState::execute(unsigned indexInBlock) } case PutByVal: - case PutByValAlias: { + case PutByValAlias: + case PutByValSafe: { node.setCanExit(true); Edge child1 = m_graph.varArgChild(node, 0); @@ -966,7 +967,7 @@ bool AbstractState::execute(unsigned indexInBlock) || m_graph[child1].shouldSpeculateArguments() #endif ) { - ASSERT(node.op() == PutByVal); + ASSERT(node.op() == PutByVal || node.op() == PutByValSafe); clobberWorld(node.codeOrigin, indexInBlock); forNode(nodeIndex).makeTop(); break; @@ -1055,7 +1056,7 @@ bool AbstractState::execute(unsigned indexInBlock) ASSERT(m_graph[child1].shouldSpeculateArray()); forNode(child1).filter(SpecArray); forNode(child2).filter(SpecInt32); - if (node.op() == PutByVal) + if (node.op() == PutByValSafe) clobberWorld(node.codeOrigin, indexInBlock); break; } @@ -1335,7 +1336,7 @@ bool AbstractState::execute(unsigned indexInBlock) case PutScopedVar: node.setCanExit(false); - clobberStructures(indexInBlock); + clobberCapturedVars(node.codeOrigin); break; case GetById: @@ -1415,7 +1416,8 @@ bool AbstractState::execute(unsigned indexInBlock) forNode(nodeIndex).set(SpecInt32); break; - case CheckStructure: { + case CheckStructure: + case ForwardCheckStructure: { // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes). AbstractValue& value = forNode(node.child1()); node.setCanExit( @@ -1431,6 +1433,7 @@ bool AbstractState::execute(unsigned indexInBlock) AbstractValue& value = forNode(node.child1()); ASSERT(value.isClear() || isCellSpeculation(value.m_type)); // Value could be clear if we've proven must-exit due to a speculation statically known to be bad. value.filter(node.structure()); + m_haveStructures = true; node.setCanExit(true); break; } @@ -1609,6 +1612,12 @@ bool AbstractState::execute(unsigned indexInBlock) inline void AbstractState::clobberWorld(const CodeOrigin& codeOrigin, unsigned indexInBlock) { + clobberCapturedVars(codeOrigin); + clobberStructures(indexInBlock); +} + +inline void AbstractState::clobberCapturedVars(const CodeOrigin& codeOrigin) +{ if (codeOrigin.inlineCallFrame) { const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars; for (size_t i = capturedVars.size(); i--;) { @@ -1624,7 +1633,6 @@ inline void AbstractState::clobberWorld(const CodeOrigin& codeOrigin, unsigned i for (size_t i = m_variables.numberOfArguments(); i--;) m_variables.argument(i).makeTop(); } - clobberStructures(indexInBlock); } inline void AbstractState::clobberStructures(unsigned indexInBlock) diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h index 95cadecbb..d2bc1a551 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.h +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h @@ -217,6 +217,7 @@ public: private: void clobberWorld(const CodeOrigin&, unsigned indexInBlock); + void clobberCapturedVars(const CodeOrigin&); void clobberStructures(unsigned indexInBlock); bool mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex); diff --git a/Source/JavaScriptCore/dfg/DFGAbstractValue.h b/Source/JavaScriptCore/dfg/DFGAbstractValue.h index f81af4ecf..402fd0fcd 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractValue.h +++ b/Source/JavaScriptCore/dfg/DFGAbstractValue.h @@ -317,13 +317,14 @@ struct AbstractValue { { m_type = SpecNone; m_structure.clear(); + m_unclobberedStructure.clear(); m_value = JSValue(); checkConsistency(); } bool isClear() const { - bool result = m_type == SpecNone && m_structure.isClear(); + bool result = m_type == SpecNone && m_structure.isClear() && m_unclobberedStructure.isClear(); if (result) ASSERT(!m_value); return result; @@ -333,6 +334,7 @@ struct AbstractValue { { m_type = SpecTop; m_structure.makeTop(); + m_unclobberedStructure.makeTop(); m_value = JSValue(); checkConsistency(); } @@ -353,7 +355,7 @@ struct AbstractValue { bool isTop() const { - return m_type == SpecTop && m_structure.isTop(); + return m_type == SpecTop && m_structure.isTop() && m_unclobberedStructure.isTop(); } bool valueIsTop() const @@ -383,8 +385,11 @@ struct AbstractValue { // it may change in the future - for example between when we compile // the code and when we run it. m_structure.makeTop(); - } else + m_unclobberedStructure.makeTop(); // FIXME: Consider not clobbering this. + } else { m_structure.clear(); + m_unclobberedStructure.clear(); + } m_type = speculationFromValue(value); m_value = value; @@ -397,6 +402,9 @@ struct AbstractValue { m_structure.clear(); m_structure.add(structure); + m_unclobberedStructure.clear(); + m_unclobberedStructure.add(structure); + m_type = speculationFromStructure(structure); m_value = JSValue(); @@ -405,10 +413,13 @@ struct AbstractValue { void set(SpeculatedType type) { - if (type & SpecCell) + if (type & SpecCell) { m_structure.makeTop(); - else + m_unclobberedStructure.makeTop(); + } else { m_structure.clear(); + m_unclobberedStructure.clear(); + } m_type = type; m_value = JSValue(); checkConsistency(); @@ -418,6 +429,7 @@ struct AbstractValue { { return m_type == other.m_type && m_structure == other.m_structure + && m_unclobberedStructure == other.m_unclobberedStructure && m_value == other.m_value; } bool operator!=(const AbstractValue& other) const @@ -437,6 +449,7 @@ struct AbstractValue { } else { result |= mergeSpeculation(m_type, other.m_type); result |= m_structure.addAll(other.m_structure); + result |= m_unclobberedStructure.addAll(other.m_unclobberedStructure); if (m_value != other.m_value) { result |= !!m_value; m_value = JSValue(); @@ -451,8 +464,10 @@ struct AbstractValue { { mergeSpeculation(m_type, type); - if (type & SpecCell) + if (type & SpecCell) { m_structure.makeTop(); + m_unclobberedStructure.makeTop(); + } m_value = JSValue(); checkConsistency(); @@ -462,6 +477,7 @@ struct AbstractValue { { m_type &= other.speculationFromStructures(); m_structure.filter(other); + m_unclobberedStructure.filter(other); // It's possible that prior to the above two statements we had (Foo, TOP), where // Foo is a SpeculatedType that is disjoint with the passed StructureSet. In that @@ -469,6 +485,7 @@ struct AbstractValue { // sure that new information gleaned from the SpeculatedType needs to be fed back // into the information gleaned from the StructureSet. m_structure.filter(m_type); + m_unclobberedStructure.filter(m_type); if (!!m_value && !validateIgnoringValue(m_value)) clear(); @@ -487,6 +504,7 @@ struct AbstractValue { // to ensure that the structure filtering does the right thing is to filter on // the new type (None) rather than the one passed (Array). m_structure.filter(m_type); + m_unclobberedStructure.filter(m_type); if (!!m_value && !validateIgnoringValue(m_value)) clear(); @@ -523,8 +541,8 @@ struct AbstractValue { if (isTop()) return true; - if (!!m_value) - return m_value == value; + if (!!m_value && m_value != value) + return false; if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type) return false; @@ -545,10 +563,39 @@ struct AbstractValue { return true; } + bool validateForEntry(JSValue value) const + { + if (isTop()) + return true; + + if (!!m_value && m_value != value) + return false; + + if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type) + return false; + + if (value.isEmpty()) { + ASSERT(m_type & SpecEmpty); + return true; + } + + if (m_unclobberedStructure.isTop()) + return true; + + if (!!value && value.isCell()) { + ASSERT(m_type & SpecCell); + return m_unclobberedStructure.contains(value.asCell()->structure()); + } + + return true; + } + void checkConsistency() const { - if (!(m_type & SpecCell)) + if (!(m_type & SpecCell)) { ASSERT(m_structure.isClear()); + ASSERT(m_unclobberedStructure.isClear()); + } if (isClear()) ASSERT(!m_value); @@ -566,12 +613,15 @@ struct AbstractValue { { fprintf(out, "(%s, ", speculationToString(m_type)); m_structure.dump(out); + dataLog(", "); + m_unclobberedStructure.dump(out); if (!!m_value) fprintf(out, ", %s", m_value.description()); fprintf(out, ")"); } StructureAbstractValue m_structure; + StructureAbstractValue m_unclobberedStructure; SpeculatedType m_type; JSValue m_value; }; diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index e4e94e90b..b7f48aa4b 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -257,6 +257,8 @@ private: } VariableAccessData* variableAccessData = newVariableAccessData(operand, isCaptured); + variableAccessData->mergeStructureCheckHoistingFailed( + m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)); NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value); m_currentBlock->variablesAtTail.local(operand) = nodeIndex; } @@ -299,7 +301,8 @@ private: // We're getting an argument in the first basic block; link // the GetLocal to the SetArgument. ASSERT(nodePtr->local() == static_cast<VirtualRegister>(operand)); - nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex)); + VariableAccessData* variable = nodePtr->variableAccessData(); + nodeIndex = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variable), nodeIndex)); m_currentBlock->variablesAtTail.argument(argument) = nodeIndex; return nodeIndex; } @@ -340,6 +343,8 @@ private: flushDirect(operand); VariableAccessData* variableAccessData = newVariableAccessData(operand, isCaptured); + variableAccessData->mergeStructureCheckHoistingFailed( + m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)); NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value); m_currentBlock->variablesAtTail.argument(argument) = nodeIndex; } @@ -1723,7 +1728,11 @@ bool ByteCodeParser::parseBlock(unsigned limit) if (m_currentBlock == m_graph.m_blocks[0].get() && !m_inlineStackTop->m_inlineCallFrame) { m_graph.m_arguments.resize(m_numArguments); for (unsigned argument = 0; argument < m_numArguments; ++argument) { - NodeIndex setArgument = addToGraph(SetArgument, OpInfo(newVariableAccessData(argumentToOperand(argument), m_codeBlock->argumentIsCaptured(argument)))); + VariableAccessData* variable = newVariableAccessData( + argumentToOperand(argument), m_codeBlock->argumentIsCaptured(argument)); + variable->mergeStructureCheckHoistingFailed( + m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)); + NodeIndex setArgument = addToGraph(SetArgument, OpInfo(variable)); m_graph.m_arguments[argument] = setArgument; m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, setArgument); m_currentBlock->variablesAtTail.setArgumentFirstTime(argument, setArgument); @@ -2152,10 +2161,14 @@ bool ByteCodeParser::parseBlock(unsigned limit) NodeIndex property = get(currentInstruction[2].u.operand); NodeIndex value = get(currentInstruction[3].u.operand); + bool makeSafe = + m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex) + || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, OutOfBounds); + addVarArgChild(base); addVarArgChild(property); addVarArgChild(value); - addToGraph(Node::VarArg, PutByVal, OpInfo(0), OpInfo(0)); + addToGraph(Node::VarArg, makeSafe ? PutByValSafe : PutByVal, OpInfo(0), OpInfo(0)); NEXT_OPCODE(op_put_by_val); } @@ -2222,7 +2235,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) } case op_get_by_id: case op_get_by_id_out_of_line: { - SpeculatedType prediction = getPredictionWithoutOSRExit(); + SpeculatedType prediction = getPrediction(); NodeIndex base = get(currentInstruction[2].u.operand); unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand]; @@ -3010,6 +3023,7 @@ void ByteCodeParser::fixVariableAccessSpeculations() VariableAccessData* data = &m_graph.m_variableAccessData[i]; data->find()->predict(data->nonUnifiedPrediction()); data->find()->mergeIsCaptured(data->isCaptured()); + data->find()->mergeStructureCheckHoistingFailed(data->structureCheckHoistingFailed()); } } diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp index 4532214ee..e9b1e0d8b 100644 --- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp @@ -284,7 +284,8 @@ private: return index; break; case PutByVal: - case PutByValAlias: { + case PutByValAlias: + case PutByValSafe: { if (!m_graph.byValIsPure(node)) return NoNode; if (m_graph.varArgChild(node, 0) == child1 && canonicalize(m_graph.varArgChild(node, 1)) == canonicalize(child2)) @@ -337,6 +338,7 @@ private: Node& node = m_graph[index]; switch (node.op()) { case CheckStructure: + case ForwardCheckStructure: if (node.child1() == child1 && structureSet.isSupersetOf(node.structureSet())) return true; @@ -362,6 +364,7 @@ private: case PutByVal: case PutByValAlias: + case PutByValSafe: if (m_graph.byValIsPure(node)) { // If PutByVal speculates that it's accessing an array with an // integer index, then it's impossible for it to cause a structure @@ -389,6 +392,7 @@ private: Node& node = m_graph[index]; switch (node.op()) { case CheckStructure: + case ForwardCheckStructure: if (node.child1() == child1 && node.structureSet().containsOnly(structure)) return true; @@ -404,6 +408,7 @@ private: case PutByVal: case PutByValAlias: + case PutByValSafe: if (m_graph.byValIsPure(node)) { // If PutByVal speculates that it's accessing an array with an // integer index, then it's impossible for it to cause a structure @@ -437,6 +442,7 @@ private: break; switch (node.op()) { case CheckStructure: + case ForwardCheckStructure: return NoNode; case PhantomPutStructure: @@ -507,6 +513,7 @@ private: case PutByVal: case PutByValAlias: + case PutByValSafe: if (m_graph.byValIsPure(node)) { // If PutByVal speculates that it's accessing an array with an // integer index, then it's impossible for it to cause a structure @@ -551,6 +558,7 @@ private: case PutByVal: case PutByValAlias: case GetByVal: + case PutByValSafe: if (m_graph.byValIsPure(node)) { // If PutByVal speculates that it's accessing an array with an // integer index, then it's impossible for it to cause a structure @@ -603,6 +611,7 @@ private: case PutByVal: case PutByValAlias: + case PutByValSafe: if (m_graph.byValIsPure(node)) { // If PutByVal speculates that it's accessing an array with an // integer index, then it's impossible for it to cause a structure @@ -643,15 +652,6 @@ private: // change the property storage pointer. break; - case PutByValAlias: - // PutByValAlias can't change the indexed storage pointer - break; - - case PutByVal: - if (isFixedIndexedStorageObjectSpeculation(m_graph[m_graph.varArgChild(node, 0)].prediction()) && m_graph.byValIsPure(node)) - break; - return NoNode; - default: if (m_graph.clobbersWorld(index)) return NoNode; @@ -673,7 +673,7 @@ private: return NoNode; } - NodeIndex getLocalLoadElimination(VirtualRegister local, NodeIndex& relevantLocalOp) + NodeIndex getLocalLoadElimination(VirtualRegister local, NodeIndex& relevantLocalOp, bool careAboutClobbering) { relevantLocalOp = NoNode; @@ -703,7 +703,7 @@ private: break; default: - if (m_graph.clobbersWorld(index)) + if (careAboutClobbering && m_graph.clobbersWorld(index)) return NoNode; break; } @@ -944,13 +944,15 @@ private: case GetLocal: { VariableAccessData* variableAccessData = node.variableAccessData(); - if (!variableAccessData->isCaptured()) + if (m_fixpointState == FixpointNotConverged && !variableAccessData->isCaptured()) break; NodeIndex relevantLocalOp; - NodeIndex possibleReplacement = getLocalLoadElimination(variableAccessData->local(), relevantLocalOp); - ASSERT(relevantLocalOp == NoNode - || m_graph[relevantLocalOp].op() == GetLocalUnlinked - || m_graph[relevantLocalOp].variableAccessData() == variableAccessData); + NodeIndex possibleReplacement = getLocalLoadElimination(variableAccessData->local(), relevantLocalOp, variableAccessData->isCaptured()); + if (relevantLocalOp == NoNode) + break; + if (m_graph[relevantLocalOp].op() != GetLocalUnlinked + && m_graph[relevantLocalOp].variableAccessData() != variableAccessData) + break; NodeIndex phiIndex = node.child1().index(); if (!setReplacement(possibleReplacement)) break; @@ -980,7 +982,7 @@ private: case GetLocalUnlinked: { NodeIndex relevantLocalOpIgnored; - m_changed |= setReplacement(getLocalLoadElimination(node.unlinkedLocal(), relevantLocalOpIgnored)); + m_changed |= setReplacement(getLocalLoadElimination(node.unlinkedLocal(), relevantLocalOpIgnored, true)); break; } @@ -1093,7 +1095,8 @@ private: setReplacement(getByValLoadElimination(node.child1().index(), node.child2().index())); break; - case PutByVal: { + case PutByVal: + case PutByValSafe: { Edge child1 = m_graph.varArgChild(node, 0); Edge child2 = m_graph.varArgChild(node, 1); if (isActionableMutableArraySpeculation(m_graph[child1].prediction()) @@ -1108,6 +1111,7 @@ private: } case CheckStructure: + case ForwardCheckStructure: if (checkStructureLoadElimination(node.structureSet(), node.child1().index())) eliminate(); break; diff --git a/Source/JavaScriptCore/dfg/DFGDriver.cpp b/Source/JavaScriptCore/dfg/DFGDriver.cpp index f160b6d35..ddad4f864 100644 --- a/Source/JavaScriptCore/dfg/DFGDriver.cpp +++ b/Source/JavaScriptCore/dfg/DFGDriver.cpp @@ -38,6 +38,7 @@ #include "DFGJITCompiler.h" #include "DFGPredictionPropagationPhase.h" #include "DFGRedundantPhiEliminationPhase.h" +#include "DFGStructureCheckHoistingPhase.h" #include "DFGValidate.h" #include "DFGVirtualRegisterAllocationPhase.h" #include "Options.h" @@ -101,7 +102,10 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo dfg.resetExitStates(); performFixup(dfg); } + bool shouldRedoCFA = performStructureCheckHoisting(dfg); performCSE(dfg, FixpointConverged); + if (shouldRedoCFA) + performCFA(dfg); #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("DFG optimization fixpoint converged in %u iterations.\n", cnt); #endif diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp index a1954d7e0..4e3cd5782 100644 --- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp @@ -314,7 +314,8 @@ private: break; } - case PutByVal: { + case PutByVal: + case PutByValSafe: { Edge child1 = m_graph.varArgChild(node, 0); Edge child2 = m_graph.varArgChild(node, 1); Edge child3 = m_graph.varArgChild(node, 2); diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp index c7a4d94d2..9ae0648b8 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.cpp +++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp @@ -207,7 +207,7 @@ void Graph::dump(const char* prefix, NodeIndex nodeIndex) hasPrinted = !!node.child1(); } - if (node.flags()) { + if (strlen(nodeFlagsAsString(node.flags()))) { dataLog("%s%s", hasPrinted ? ", " : "", nodeFlagsAsString(node.flags())); hasPrinted = true; } @@ -287,13 +287,15 @@ void Graph::dump(const char* prefix, NodeIndex nodeIndex) dataLog("%sF:#%u", hasPrinted ? ", " : "", node.notTakenBlockIndex()); hasPrinted = true; } + dataLog("%sbc#%u", hasPrinted ? ", " : "", node.codeOrigin.bytecodeIndex); + hasPrinted = true; (void)hasPrinted; dataLog(")"); if (!skipped) { if (node.hasVariableAccessData()) - dataLog(" predicting %s, double ratio %lf%s", speculationToString(node.variableAccessData()->prediction()), node.variableAccessData()->doubleVoteRatio(), node.variableAccessData()->shouldUseDoubleFormat() ? ", forcing double" : ""); + dataLog(" predicting %s%s", speculationToString(node.variableAccessData()->prediction()), node.variableAccessData()->shouldUseDoubleFormat() ? ", forcing double" : ""); else if (node.hasHeapPrediction()) dataLog(" predicting %s", speculationToString(node.getHeapPrediction())); } diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h index 3e6539353..fdb78cf9b 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.h +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -479,6 +479,15 @@ public: SpeculatedType prediction = at(varArgChild(node, 0)).prediction(); if (!isActionableMutableArraySpeculation(prediction)) return false; + return true; + } + + case PutByValSafe: { + if (!at(varArgChild(node, 1)).shouldSpeculateInteger()) + return false; + SpeculatedType prediction = at(varArgChild(node, 0)).prediction(); + if (!isActionableMutableArraySpeculation(prediction)) + return false; if (isArraySpeculation(prediction)) return false; return true; @@ -524,6 +533,7 @@ public: return !isPredictedNumerical(node); case GetByVal: case PutByVal: + case PutByValSafe: case PutByValAlias: return !byValIsPure(node); default: @@ -568,6 +578,42 @@ public: return node.children.child(index); } + void vote(Edge edge, unsigned ballot) + { + switch (at(edge).op()) { + case ValueToInt32: + case UInt32ToNumber: + edge = at(edge).child1(); + break; + default: + break; + } + + if (at(edge).op() == GetLocal) + at(edge).variableAccessData()->vote(ballot); + } + + void vote(Node& node, unsigned ballot) + { + if (node.flags() & NodeHasVarArgs) { + for (unsigned childIdx = node.firstChild(); + childIdx < node.firstChild() + node.numChildren(); + childIdx++) + vote(m_varArgChildren[childIdx], ballot); + return; + } + + if (!node.child1()) + return; + vote(node.child1(), ballot); + if (!node.child2()) + return; + vote(node.child2(), ballot); + if (!node.child3()) + return; + vote(node.child3(), ballot); + } + JSGlobalData& m_globalData; CodeBlock* m_codeBlock; CodeBlock* m_profiledBlock; diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h index e72bd5e36..60cdd4b50 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.h +++ b/Source/JavaScriptCore/dfg/DFGNode.h @@ -245,6 +245,13 @@ struct Node { children.reset(); } + void convertToStructureTransitionWatchpoint() + { + ASSERT(m_op == CheckStructure); + m_opInfo = bitwise_cast<uintptr_t>(structureSet().singletonStructure()); + m_op = StructureTransitionWatchpoint; + } + JSCell* weakConstant() { ASSERT(op() == WeakJSConstant); @@ -651,7 +658,13 @@ struct Node { bool hasStructureSet() { - return op() == CheckStructure; + switch (op()) { + case CheckStructure: + case ForwardCheckStructure: + return true; + default: + return false; + } } StructureSet& structureSet() diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h index 0ca0039b9..7657663a9 100644 --- a/Source/JavaScriptCore/dfg/DFGNodeType.h +++ b/Source/JavaScriptCore/dfg/DFGNodeType.h @@ -113,12 +113,14 @@ namespace JSC { namespace DFG { /* opcodes use VarArgs beause they may have up to 4 children. */\ macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \ macro(PutByVal, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \ + macro(PutByValSafe, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \ macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \ macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ macro(PutById, NodeMustGenerate | NodeClobbersWorld) \ macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \ macro(CheckStructure, NodeMustGenerate) \ + macro(ForwardCheckStructure, NodeMustGenerate) \ /* Transition watchpoints are a contract between the party setting the watchpoint */\ /* and the runtime system, where the party promises that the child object once had */\ /* the structure being watched, and the runtime system in turn promises that the */\ diff --git a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp b/Source/JavaScriptCore/dfg/DFGOSREntry.cpp index 9a7bc96cc..97061bfb2 100644 --- a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSREntry.cpp @@ -99,7 +99,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn else value = exec->argument(argument - 1); - if (!entry->m_expectedValues.argument(argument).validate(value)) { + if (!entry->m_expectedValues.argument(argument).validateForEntry(value)) { #if ENABLE(JIT_VERBOSE_OSR) dataLog(" OSR failed because argument %zu is %s, expected ", argument, value.description()); entry->m_expectedValues.argument(argument).dump(WTF::dataFile()); @@ -119,7 +119,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn } continue; } - if (!entry->m_expectedValues.local(local).validate(exec->registers()[local].jsValue())) { + if (!entry->m_expectedValues.local(local).validateForEntry(exec->registers()[local].jsValue())) { #if ENABLE(JIT_VERBOSE_OSR) dataLog(" OSR failed because variable %zu is %s, expected ", local, exec->registers()[local].jsValue().description()); entry->m_expectedValues.local(local).dump(WTF::dataFile()); diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp index e9b02b2e3..b3701722e 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp @@ -64,7 +64,7 @@ bool OSRExit::considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, Code } else exitSite = FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind); - return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOrigin, profiledCodeBlock)->addFrequentExitSite(exitSite); + return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOriginForExitProfile, profiledCodeBlock)->addFrequentExitSite(exitSite); } } } // namespace JSC::DFG diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 94479d6d0..882e1cd02 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -423,12 +423,15 @@ EncodedJSValue DFG_OPERATION operationGetByIdBuildListWithReturnAddress(ExecStat JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue baseValue = JSValue::decode(base); PropertySlot slot(baseValue); JSValue result = baseValue.get(exec, *propertyName, slot); - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); - dfgBuildGetByIDList(exec, baseValue, *propertyName, slot, stubInfo); + if (accessType == static_cast<AccessType>(stubInfo.accessType)) + dfgBuildGetByIDList(exec, baseValue, *propertyName, slot, stubInfo); return JSValue::encode(result); } @@ -439,12 +442,15 @@ EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildListWithReturnAddress(Exe JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue baseValue = JSValue::decode(base); PropertySlot slot(baseValue); JSValue result = baseValue.get(exec, *propertyName, slot); - - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); - dfgBuildGetByIDProtoList(exec, baseValue, *propertyName, slot, stubInfo); + + if (accessType == static_cast<AccessType>(stubInfo.accessType)) + dfgBuildGetByIDProtoList(exec, baseValue, *propertyName, slot, stubInfo); return JSValue::encode(result); } @@ -455,15 +461,19 @@ EncodedJSValue DFG_OPERATION operationGetByIdOptimizeWithReturnAddress(ExecState JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue baseValue = JSValue::decode(base); PropertySlot slot(baseValue); JSValue result = baseValue.get(exec, *propertyName, slot); - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); - if (stubInfo.seen) - dfgRepatchGetByID(exec, baseValue, *propertyName, slot, stubInfo); - else - stubInfo.seen = true; + if (accessType == static_cast<AccessType>(stubInfo.accessType)) { + if (stubInfo.seen) + dfgRepatchGetByID(exec, baseValue, *propertyName, slot, stubInfo); + else + stubInfo.seen = true; + } return JSValue::encode(result); } @@ -645,13 +655,18 @@ void DFG_OPERATION operationPutByIdStrictOptimizeWithReturnAddress(ExecState* ex JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue value = JSValue::decode(encodedValue); JSValue baseValue(base); PutPropertySlot slot(true); baseValue.put(exec, *propertyName, value, slot); - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + if (accessType != static_cast<AccessType>(stubInfo.accessType)) + return; + if (stubInfo.seen) dfgRepatchPutByID(exec, baseValue, *propertyName, slot, stubInfo, NotDirect); else @@ -664,13 +679,18 @@ void DFG_OPERATION operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState* JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue value = JSValue::decode(encodedValue); JSValue baseValue(base); PutPropertySlot slot(false); baseValue.put(exec, *propertyName, value, slot); - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + if (accessType != static_cast<AccessType>(stubInfo.accessType)) + return; + if (stubInfo.seen) dfgRepatchPutByID(exec, baseValue, *propertyName, slot, stubInfo, NotDirect); else @@ -683,13 +703,18 @@ void DFG_OPERATION operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecSta JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue value = JSValue::decode(encodedValue); PutPropertySlot slot(true); ASSERT(base->isObject()); asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot); - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + if (accessType != static_cast<AccessType>(stubInfo.accessType)) + return; + if (stubInfo.seen) dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct); else @@ -702,13 +727,18 @@ void DFG_OPERATION operationPutByIdDirectNonStrictOptimizeWithReturnAddress(Exec JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue value = JSValue::decode(encodedValue); PutPropertySlot slot(false); ASSERT(base->isObject()); asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot); - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + if (accessType != static_cast<AccessType>(stubInfo.accessType)) + return; + if (stubInfo.seen) dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct); else @@ -721,13 +751,18 @@ void DFG_OPERATION operationPutByIdStrictBuildListWithReturnAddress(ExecState* e JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue value = JSValue::decode(encodedValue); JSValue baseValue(base); PutPropertySlot slot(true); baseValue.put(exec, *propertyName, value, slot); - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + if (accessType != static_cast<AccessType>(stubInfo.accessType)) + return; + dfgBuildPutByIdList(exec, baseValue, *propertyName, slot, stubInfo, NotDirect); } @@ -737,13 +772,18 @@ void DFG_OPERATION operationPutByIdNonStrictBuildListWithReturnAddress(ExecState JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue value = JSValue::decode(encodedValue); JSValue baseValue(base); PutPropertySlot slot(false); baseValue.put(exec, *propertyName, value, slot); - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + if (accessType != static_cast<AccessType>(stubInfo.accessType)) + return; + dfgBuildPutByIdList(exec, baseValue, *propertyName, slot, stubInfo, NotDirect); } @@ -753,13 +793,18 @@ void DFG_OPERATION operationPutByIdDirectStrictBuildListWithReturnAddress(ExecSt JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue value = JSValue::decode(encodedValue); PutPropertySlot slot(true); ASSERT(base->isObject()); asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot); - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + if (accessType != static_cast<AccessType>(stubInfo.accessType)) + return; + dfgBuildPutByIdList(exec, base, *propertyName, slot, stubInfo, Direct); } @@ -769,13 +814,18 @@ void DFG_OPERATION operationPutByIdDirectNonStrictBuildListWithReturnAddress(Exe JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue value = JSValue::decode(encodedValue); PutPropertySlot slot(false); ASSERT(base->isObject()); asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot); - StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); + if (accessType != static_cast<AccessType>(stubInfo.accessType)) + return; + dfgBuildPutByIdList(exec, base, *propertyName, slot, stubInfo, Direct); } diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp index 2e4f8094c..94f69abc2 100644 --- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp @@ -637,6 +637,7 @@ private: } case PutByVal: + case PutByValSafe: changed |= m_graph[m_graph.varArgChild(node, 0)].mergeFlags(NodeUsedAsValue); changed |= m_graph[m_graph.varArgChild(node, 1)].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt); changed |= m_graph[m_graph.varArgChild(node, 2)].mergeFlags(NodeUsedAsValue); @@ -672,6 +673,7 @@ private: case ForceOSRExit: case SetArgument: case CheckStructure: + case ForwardCheckStructure: case StructureTransitionWatchpoint: case CheckFunction: case PutStructure: @@ -746,42 +748,6 @@ private: propagate(m_graph[m_compileIndex]); } - void vote(Edge nodeUse, VariableAccessData::Ballot ballot) - { - switch (m_graph[nodeUse].op()) { - case ValueToInt32: - case UInt32ToNumber: - nodeUse = m_graph[nodeUse].child1(); - break; - default: - break; - } - - if (m_graph[nodeUse].op() == GetLocal) - m_graph[nodeUse].variableAccessData()->vote(ballot); - } - - void vote(Node& node, VariableAccessData::Ballot ballot) - { - if (node.flags() & NodeHasVarArgs) { - for (unsigned childIdx = node.firstChild(); - childIdx < node.firstChild() + node.numChildren(); - childIdx++) - vote(m_graph.m_varArgChildren[childIdx], ballot); - return; - } - - if (!node.child1()) - return; - vote(node.child1(), ballot); - if (!node.child2()) - return; - vote(node.child2(), ballot); - if (!node.child3()) - return; - vote(node.child3(), ballot); - } - void doRoundOfDoubleVoting() { #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) @@ -798,16 +764,16 @@ private: SpeculatedType left = m_graph[node.child1()].prediction(); SpeculatedType right = m_graph[node.child2()].prediction(); - VariableAccessData::Ballot ballot; + DoubleBallot ballot; if (isNumberSpeculation(left) && isNumberSpeculation(right) && !m_graph.addShouldSpeculateInteger(node)) - ballot = VariableAccessData::VoteDouble; + ballot = VoteDouble; else - ballot = VariableAccessData::VoteValue; + ballot = VoteValue; - vote(node.child1(), ballot); - vote(node.child2(), ballot); + m_graph.vote(node.child1(), ballot); + m_graph.vote(node.child2(), ballot); break; } @@ -815,16 +781,16 @@ private: SpeculatedType left = m_graph[node.child1()].prediction(); SpeculatedType right = m_graph[node.child2()].prediction(); - VariableAccessData::Ballot ballot; + DoubleBallot ballot; if (isNumberSpeculation(left) && isNumberSpeculation(right) && !m_graph.mulShouldSpeculateInteger(node)) - ballot = VariableAccessData::VoteDouble; + ballot = VoteDouble; else - ballot = VariableAccessData::VoteValue; + ballot = VoteValue; - vote(node.child1(), ballot); - vote(node.child2(), ballot); + m_graph.vote(node.child1(), ballot); + m_graph.vote(node.child2(), ballot); break; } @@ -835,46 +801,46 @@ private: SpeculatedType left = m_graph[node.child1()].prediction(); SpeculatedType right = m_graph[node.child2()].prediction(); - VariableAccessData::Ballot ballot; + DoubleBallot ballot; if (isNumberSpeculation(left) && isNumberSpeculation(right) && !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()]) && node.canSpeculateInteger())) - ballot = VariableAccessData::VoteDouble; + ballot = VoteDouble; else - ballot = VariableAccessData::VoteValue; + ballot = VoteValue; - vote(node.child1(), ballot); - vote(node.child2(), ballot); + m_graph.vote(node.child1(), ballot); + m_graph.vote(node.child2(), ballot); break; } case ArithAbs: - VariableAccessData::Ballot ballot; + DoubleBallot ballot; if (!(m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger())) - ballot = VariableAccessData::VoteDouble; + ballot = VoteDouble; else - ballot = VariableAccessData::VoteValue; + ballot = VoteValue; - vote(node.child1(), ballot); + m_graph.vote(node.child1(), ballot); break; case ArithSqrt: - vote(node.child1(), VariableAccessData::VoteDouble); + m_graph.vote(node.child1(), VoteDouble); break; case SetLocal: { SpeculatedType prediction = m_graph[node.child1()].prediction(); if (isDoubleSpeculation(prediction)) - node.variableAccessData()->vote(VariableAccessData::VoteDouble); + node.variableAccessData()->vote(VoteDouble); else if (!isNumberSpeculation(prediction) || isInt32Speculation(prediction)) - node.variableAccessData()->vote(VariableAccessData::VoteValue); + node.variableAccessData()->vote(VoteValue); break; } default: - vote(node, VariableAccessData::VoteValue); + m_graph.vote(node, VoteValue); break; } } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index 179ad45fa..f17e2d7e4 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -56,6 +56,163 @@ SpeculativeJIT::~SpeculativeJIT() WTF::deleteAllValues(m_slowPathGenerators); } +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail) +{ + if (!m_compileOkay) + return; + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_stream->size())); +} + +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail); +} + +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps(); + for (unsigned i = 0; i < jumpVector.size(); ++i) + speculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i]); +} + +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::JumpList& jumpsToFail) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail); +} + +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) +{ + if (!m_compileOkay) + return; + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + m_jit.codeBlock()->appendSpeculationRecovery(recovery); + m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_stream->size(), m_jit.codeBlock()->numberOfSpeculationRecoveries())); +} + +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery); +} + +JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex) +{ + if (!m_compileOkay) + return 0; + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + OSRExit& exit = m_jit.codeBlock()->osrExit( + m_jit.codeBlock()->appendOSRExit( + OSRExit(kind, jsValueSource, + m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), + JITCompiler::Jump(), this, m_stream->size()))); + exit.m_watchpointIndex = m_jit.codeBlock()->appendWatchpoint( + JumpReplacementWatchpoint(m_jit.watchpointLabel())); + return &m_jit.codeBlock()->watchpoint(exit.m_watchpointIndex); +} + +JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind) +{ + return speculationWatchpoint(kind, JSValueSource(), NoNode); +} + +void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail); + +#if !ASSERT_DISABLED + if (!valueRecovery) { + // Check that the preceding node was a SetLocal with the same code origin. + Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(m_indexInBlock - 1)); + ASSERT(setLocal->op() == SetLocal); + ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin); + } +#endif + + unsigned setLocalIndexInBlock = m_indexInBlock + 1; + + Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock)); + bool hadInt32ToDouble = false; + + if (setLocal->op() == Int32ToDouble) { + setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock)); + hadInt32ToDouble = true; + } + if (setLocal->op() == Flush || setLocal->op() == Phantom) + setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock)); + + if (!!valueRecovery) { + if (hadInt32ToDouble) + ASSERT(at(setLocal->child1()).child1() == m_compileIndex); + else + ASSERT(setLocal->child1() == m_compileIndex); + } + ASSERT(setLocal->op() == SetLocal); + ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin); + + Node* nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1)); + ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin); + + OSRExit& exit = m_jit.codeBlock()->lastOSRExit(); + exit.m_codeOrigin = nextNode->codeOrigin; + + if (!valueRecovery) + return; + exit.m_lastSetOperand = setLocal->local(); + exit.m_valueRecoveryOverride = adoptRef( + new ValueRecoveryOverride(setLocal->local(), valueRecovery)); +} + +void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps(); + for (unsigned i = 0; i < jumpVector.size(); ++i) + forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i], valueRecovery); +} + +void SpeculativeJIT::speculationCheckWithConditionalDirection(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, bool isForward) +{ + if (isForward) + forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpToFail); + else + speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail); +} + +void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); +#if DFG_ENABLE(DEBUG_VERBOSE) + dataLog("SpeculativeJIT was terminated.\n"); +#endif + if (!m_compileOkay) + return; + speculationCheck(kind, jsValueRegs, nodeIndex, m_jit.jump()); + m_compileOkay = false; +} + +void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.index()); +} + +void SpeculativeJIT::terminateSpeculativeExecutionWithConditionalDirection(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex, bool isForward) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); +#if DFG_ENABLE(DEBUG_VERBOSE) + dataLog("SpeculativeJIT was terminated.\n"); +#endif + if (!m_compileOkay) + return; + speculationCheckWithConditionalDirection(kind, jsValueRegs, nodeIndex, m_jit.jump(), isForward); + m_compileOkay = false; +} + void SpeculativeJIT::addSlowPathGenerator(PassOwnPtr<SlowPathGenerator> slowPathGenerator) { m_slowPathGenerators.append(slowPathGenerator.leakPtr()); @@ -2902,7 +3059,7 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node) ASSERT_NOT_REACHED(); } else if (at(node.child1()).prediction() == SpecString) { if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info))); + speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h index f43323afd..96f2fec0a 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h @@ -306,7 +306,7 @@ public: GPRReg fillSpeculateInt(NodeIndex, DataFormat& returnFormat); GPRReg fillSpeculateIntStrict(NodeIndex); FPRReg fillSpeculateDouble(NodeIndex); - GPRReg fillSpeculateCell(NodeIndex); + GPRReg fillSpeculateCell(NodeIndex, bool isForwardSpeculation = false); GPRReg fillSpeculateBoolean(NodeIndex); GeneratedOperandType checkGeneratedTypeForToInt32(NodeIndex); @@ -2163,130 +2163,33 @@ public: #endif // Add a speculation check without additional recovery. - void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail) - { - if (!m_compileOkay) - return; - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); - m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_stream->size())); - } - void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail) - { - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); - speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail); - } + void speculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail); + void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail); // Add a set of speculation checks without additional recovery. - void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail) - { - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); - Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps(); - for (unsigned i = 0; i < jumpVector.size(); ++i) - speculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i]); - } - void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::JumpList& jumpsToFail) - { - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); - speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail); - } + void speculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::JumpList& jumpsToFail); + void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::JumpList& jumpsToFail); // Add a speculation check with additional recovery. - void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) - { - if (!m_compileOkay) - return; - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); - m_jit.codeBlock()->appendSpeculationRecovery(recovery); - m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_stream->size(), m_jit.codeBlock()->numberOfSpeculationRecoveries())); - } - void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) - { - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); - speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery); - } + void speculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&); + void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&); // Use this like you would use speculationCheck(), except that you don't pass it a jump // (because you don't have to execute a branch; that's kind of the whole point), and you // must register the returned Watchpoint with something relevant. In general, this should // be used with extreme care. Use speculationCheck() unless you've got an amazing reason // not to. - JumpReplacementWatchpoint* speculationWatchpoint(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex) - { - if (!m_compileOkay) - return 0; - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); - OSRExit& exit = m_jit.codeBlock()->osrExit( - m_jit.codeBlock()->appendOSRExit( - OSRExit(kind, jsValueSource, - m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), - JITCompiler::Jump(), this, m_stream->size()))); - exit.m_watchpointIndex = m_jit.codeBlock()->appendWatchpoint( - JumpReplacementWatchpoint(m_jit.watchpointLabel())); - return &m_jit.codeBlock()->watchpoint(exit.m_watchpointIndex); - } + JumpReplacementWatchpoint* speculationWatchpoint(ExitKind, JSValueSource, NodeIndex); // The default for speculation watchpoints is that they're uncounted, because the // act of firing a watchpoint invalidates it. So, future recompilations will not // attempt to set this watchpoint again. - JumpReplacementWatchpoint* speculationWatchpoint() - { - return speculationWatchpoint(UncountableWatchpoint, JSValueSource(), NoNode); - } - void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery) - { - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); - speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail); - - unsigned setLocalIndexInBlock = m_indexInBlock + 1; - - Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock)); - bool hadInt32ToDouble = false; - - if (setLocal->op() == Int32ToDouble) { - setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock)); - hadInt32ToDouble = true; - } - if (setLocal->op() == Flush || setLocal->op() == Phantom) - setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock)); - - if (hadInt32ToDouble) - ASSERT(at(setLocal->child1()).child1() == m_compileIndex); - else - ASSERT(setLocal->child1() == m_compileIndex); - ASSERT(setLocal->op() == SetLocal); - ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin); - - Node* nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1)); - ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin); - - OSRExit& exit = m_jit.codeBlock()->lastOSRExit(); - exit.m_codeOrigin = nextNode->codeOrigin; - exit.m_lastSetOperand = setLocal->local(); - - exit.m_valueRecoveryOverride = adoptRef( - new ValueRecoveryOverride(setLocal->local(), valueRecovery)); - } - void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery) - { - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); - Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps(); - for (unsigned i = 0; i < jumpVector.size(); ++i) - forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i], valueRecovery); - } - + JumpReplacementWatchpoint* speculationWatchpoint(ExitKind = UncountableWatchpoint); + // Note: not specifying the valueRecovery argument (leaving it as ValueRecovery()) implies + // that you've ensured that there exists a MovHint prior to your use of forwardSpeculationCheck(). + void forwardSpeculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& = ValueRecovery()); + void forwardSpeculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& = ValueRecovery()); + void speculationCheckWithConditionalDirection(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail, bool isForward); // Called when we statically determine that a speculation will fail. - void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex) - { - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); -#if DFG_ENABLE(DEBUG_VERBOSE) - dataLog("SpeculativeJIT was terminated.\n"); -#endif - if (!m_compileOkay) - return; - speculationCheck(kind, jsValueRegs, nodeIndex, m_jit.jump()); - m_compileOkay = false; - } - void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse) - { - ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); - terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.index()); - } + void terminateSpeculativeExecution(ExitKind, JSValueRegs, NodeIndex); + void terminateSpeculativeExecution(ExitKind, JSValueRegs, Edge); + void terminateSpeculativeExecutionWithConditionalDirection(ExitKind, JSValueRegs, NodeIndex, bool isForward); template<bool strict> GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat); @@ -2912,10 +2815,11 @@ private: class SpeculateCellOperand { public: - explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge use) + explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge use, bool isForwardSpeculation = false) : m_jit(jit) , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) + , m_isForwardSpeculation(isForwardSpeculation) { ASSERT(m_jit); ASSERT(use.useKind() != DoubleUse); @@ -2937,7 +2841,7 @@ public: GPRReg gpr() { if (m_gprOrInvalid == InvalidGPRReg) - m_gprOrInvalid = m_jit->fillSpeculateCell(index()); + m_gprOrInvalid = m_jit->fillSpeculateCell(index(), m_isForwardSpeculation); return m_gprOrInvalid; } @@ -2950,6 +2854,7 @@ private: SpeculativeJIT* m_jit; NodeIndex m_index; GPRReg m_gprOrInvalid; + bool m_isForwardSpeculation; }; class SpeculateBooleanOperand { diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index 6209da485..bf3503d6d 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -1284,13 +1284,13 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex) } } -GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex) +GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex, bool isForwardSpeculation) { #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("SpecCell@%d ", nodeIndex); #endif if (isKnownNotCell(nodeIndex)) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecutionWithConditionalDirection(Uncountable, JSValueRegs(), NoNode, isForwardSpeculation); return allocate(); } @@ -1314,7 +1314,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex) ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell); if (!isCellSpeculation(type)) - speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag))); + speculationCheckWithConditionalDirection(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)), isForwardSpeculation); GPRReg gpr = allocate(); m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr); m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); @@ -1335,7 +1335,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex) m_gprs.lock(tagGPR); m_gprs.lock(payloadGPR); if (!isCellSpeculation(type)) - speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag))); + speculationCheckWithConditionalDirection(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag)), isForwardSpeculation); m_gprs.unlock(tagGPR); m_gprs.release(tagGPR); m_gprs.release(payloadGPR); @@ -2483,7 +2483,8 @@ void SpeculativeJIT::compile(Node& node) break; } - case PutByVal: { + case PutByVal: + case PutByValSafe: { Edge child1 = m_jit.graph().varArgChild(node, 0); Edge child2 = m_jit.graph().varArgChild(node, 1); Edge child3 = m_jit.graph().varArgChild(node, 2); @@ -2599,12 +2600,14 @@ void SpeculativeJIT::compile(Node& node) if (!isArraySpeculation(m_state.forNode(child1).m_type)) speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); + MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())); + if (node.op() == PutByVal) + speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds); + base.use(); property.use(); value.use(); - MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())); - // Get the array storage. GPRReg storageReg = scratchReg; m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); @@ -2626,12 +2629,14 @@ void SpeculativeJIT::compile(Node& node) m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - addSlowPathGenerator( - slowPathCall( - beyondArrayBounds, this, - m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, - NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg)); - + if (node.op() == PutByValSafe) { + addSlowPathGenerator( + slowPathCall( + beyondArrayBounds, this, + m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, + NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg)); + } + noResult(m_compileIndex, UseChildrenCalledExplicitly); break; } @@ -2990,7 +2995,7 @@ void SpeculativeJIT::compile(Node& node) m_jit.move(op1PayloadGPR, resultPayloadGPR); } else { MacroAssembler::Jump alreadyPrimitive = m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag)); - MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1PayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)); + MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1PayloadGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())); alreadyPrimitive.link(&m_jit); m_jit.move(op1TagGPR, resultTagGPR); @@ -3174,7 +3179,7 @@ void SpeculativeJIT::compile(Node& node) GPRReg thisValueGPR = thisValue.gpr(); if (!isObjectSpeculation(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info))); + speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); GPRTemporary result(this, thisValue); GPRReg resultGPR = result.gpr(); @@ -3418,7 +3423,7 @@ void SpeculativeJIT::compile(Node& node) GPRReg resultGPR = result.gpr(); if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info))); + speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR); @@ -3470,7 +3475,8 @@ void SpeculativeJIT::compile(Node& node) break; } - case CheckStructure: { + case CheckStructure: + case ForwardCheckStructure: { AbstractValue& value = m_state.forNode(node.child1()); if (value.m_structure.isSubsetOf(node.structureSet()) && isCellSpeculation(value.m_type)) { @@ -3478,13 +3484,19 @@ void SpeculativeJIT::compile(Node& node) break; } - SpeculateCellOperand base(this, node.child1()); + SpeculateCellOperand base(this, node.child1(), node.op() == ForwardCheckStructure); ASSERT(node.structureSet().size()); - if (node.structureSet().size() == 1) - speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(base.gpr(), JSCell::structureOffset()), node.structureSet()[0])); - else { + if (node.structureSet().size() == 1) { + speculationCheckWithConditionalDirection( + BadCache, JSValueRegs(), NoNode, + m_jit.branchWeakPtr( + JITCompiler::NotEqual, + JITCompiler::Address(base.gpr(), JSCell::structureOffset()), + node.structureSet()[0]), + node.op() == ForwardCheckStructure); + } else { GPRTemporary structure(this); m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr()); @@ -3494,7 +3506,11 @@ void SpeculativeJIT::compile(Node& node) for (size_t i = 0; i < node.structureSet().size() - 1; ++i) done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node.structureSet()[i])); - speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, structure.gpr(), node.structureSet().last())); + speculationCheckWithConditionalDirection( + BadCache, JSValueRegs(), NoNode, + m_jit.branchWeakPtr( + JITCompiler::NotEqual, structure.gpr(), node.structureSet().last()), + node.op() == ForwardCheckStructure); done.link(&m_jit); } @@ -3505,7 +3521,7 @@ void SpeculativeJIT::compile(Node& node) case StructureTransitionWatchpoint: { m_jit.addWeakReference(node.structure()); - node.structure()->addTransitionWatchpoint(speculationWatchpoint()); + node.structure()->addTransitionWatchpoint(speculationWatchpoint(BadCache)); #if !ASSERT_DISABLED SpeculateCellOperand op1(this, node.child1()); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index 39f4a0740..5541113f2 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -1326,7 +1326,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex) } } -GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex) +GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex, bool isForwardSpeculation) { #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("SpecCell@%d ", nodeIndex); @@ -1339,7 +1339,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex) switch (info.registerFormat()) { case DataFormatNone: { if (info.spillFormat() == DataFormatInteger || info.spillFormat() == DataFormatDouble) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecutionWithConditionalDirection(Uncountable, JSValueRegs(), NoNode, isForwardSpeculation); return allocate(); } @@ -1353,7 +1353,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex) info.fillJSValue(*m_stream, gpr, DataFormatJSCell); return gpr; } - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecutionWithConditionalDirection(Uncountable, JSValueRegs(), NoNode, isForwardSpeculation); return gpr; } ASSERT(info.spillFormat() & DataFormatJS); @@ -1362,7 +1362,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex) info.fillJSValue(*m_stream, gpr, DataFormatJS); if (!isCellSpeculation(type)) - speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister)); + speculationCheckWithConditionalDirection(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister), isForwardSpeculation); info.fillJSValue(*m_stream, gpr, DataFormatJSCell); return gpr; } @@ -1378,7 +1378,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex) GPRReg gpr = info.gpr(); m_gprs.lock(gpr); if (!isCellSpeculation(type)) - speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister)); + speculationCheckWithConditionalDirection(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister), isForwardSpeculation); info.fillJSValue(*m_stream, gpr, DataFormatJSCell); return gpr; } @@ -1389,7 +1389,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex) case DataFormatDouble: case DataFormatJSBoolean: case DataFormatBoolean: { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecutionWithConditionalDirection(Uncountable, JSValueRegs(), NoNode, isForwardSpeculation); return allocate(); } @@ -1578,7 +1578,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality( // We know that within this branch, rightChild must not be a cell. Check if that is enough to // prove that it is either null or undefined. - if (!isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) { + if (!isOtherOrEmptySpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) { m_jit.move(op2GPR, resultGPR); m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR); @@ -1649,7 +1649,7 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality( // We know that within this branch, rightChild must not be a cell. Check if that is enough to // prove that it is either null or undefined. - if (isOtherSpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) + if (isOtherOrEmptySpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) rightNotCell.link(&m_jit); else { jump(notTaken, ForceJump); @@ -2508,7 +2508,8 @@ void SpeculativeJIT::compile(Node& node) break; } - case PutByVal: { + case PutByVal: + case PutByValSafe: { Edge child1 = m_jit.graph().varArgChild(node, 0); Edge child2 = m_jit.graph().varArgChild(node, 1); Edge child3 = m_jit.graph().varArgChild(node, 2); @@ -2675,13 +2676,15 @@ void SpeculativeJIT::compile(Node& node) // If we have predicted the base to be type array, we can skip the check. if (!isArraySpeculation(m_state.forNode(child1).m_type)) speculationCheck(BadType, JSValueRegs(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); + + MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())); + if (node.op() == PutByVal) + speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds); base.use(); property.use(); value.use(); - MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())); - // Get the array storage. GPRReg storageReg = scratchReg; m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); @@ -2702,11 +2705,13 @@ void SpeculativeJIT::compile(Node& node) // Store the value to the array. m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); - addSlowPathGenerator( - slowPathCall( - beyondArrayBounds, this, - m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, - NoResult, baseReg, propertyReg, valueReg)); + if (node.op() == PutByValSafe) { + addSlowPathGenerator( + slowPathCall( + beyondArrayBounds, this, + m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, + NoResult, baseReg, propertyReg, valueReg)); + } noResult(m_compileIndex, UseChildrenCalledExplicitly); break; @@ -3043,7 +3048,7 @@ void SpeculativeJIT::compile(Node& node) m_jit.move(op1GPR, resultGPR); else { MacroAssembler::Jump alreadyPrimitive = m_jit.branchTestPtr(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister); - MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)); + MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())); alreadyPrimitive.link(&m_jit); m_jit.move(op1GPR, resultGPR); @@ -3208,7 +3213,7 @@ void SpeculativeJIT::compile(Node& node) GPRReg resultGPR = result.gpr(); if (!isObjectSpeculation(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info))); + speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); m_jit.move(thisValueGPR, resultGPR); @@ -3435,7 +3440,7 @@ void SpeculativeJIT::compile(Node& node) GPRReg resultGPR = result.gpr(); if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info))); + speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR); @@ -3485,7 +3490,8 @@ void SpeculativeJIT::compile(Node& node) noResult(m_compileIndex); break; } - case CheckStructure: { + case CheckStructure: + case ForwardCheckStructure: { AbstractValue& value = m_state.forNode(node.child1()); if (value.m_structure.isSubsetOf(node.structureSet()) && isCellSpeculation(value.m_type)) { @@ -3493,13 +3499,19 @@ void SpeculativeJIT::compile(Node& node) break; } - SpeculateCellOperand base(this, node.child1()); + SpeculateCellOperand base(this, node.child1(), node.op() == ForwardCheckStructure); ASSERT(node.structureSet().size()); - if (node.structureSet().size() == 1) - speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(base.gpr(), JSCell::structureOffset()), node.structureSet()[0])); - else { + if (node.structureSet().size() == 1) { + speculationCheckWithConditionalDirection( + BadCache, JSValueRegs(), NoNode, + m_jit.branchWeakPtr( + JITCompiler::NotEqual, + JITCompiler::Address(base.gpr(), JSCell::structureOffset()), + node.structureSet()[0]), + node.op() == ForwardCheckStructure); + } else { GPRTemporary structure(this); m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr()); @@ -3509,7 +3521,11 @@ void SpeculativeJIT::compile(Node& node) for (size_t i = 0; i < node.structureSet().size() - 1; ++i) done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node.structureSet()[i])); - speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, structure.gpr(), node.structureSet().last())); + speculationCheckWithConditionalDirection( + BadCache, JSValueRegs(), NoNode, + m_jit.branchWeakPtr( + JITCompiler::NotEqual, structure.gpr(), node.structureSet().last()), + node.op() == ForwardCheckStructure); done.link(&m_jit); } @@ -3520,7 +3536,7 @@ void SpeculativeJIT::compile(Node& node) case StructureTransitionWatchpoint: { m_jit.addWeakReference(node.structure()); - node.structure()->addTransitionWatchpoint(speculationWatchpoint()); + node.structure()->addTransitionWatchpoint(speculationWatchpoint(BadCache)); #if !ASSERT_DISABLED SpeculateCellOperand op1(this, node.child1()); diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp new file mode 100644 index 000000000..e86c57dff --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp @@ -0,0 +1,490 @@ +/* + * 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. + */ + +#include "config.h" +#include "DFGStructureCheckHoistingPhase.h" + +#if ENABLE(DFG_JIT) + +#include "DFGBasicBlock.h" +#include "DFGGraph.h" +#include "DFGInsertionSet.h" +#include "DFGPhase.h" +#include <wtf/HashMap.h> + +namespace JSC { namespace DFG { + +enum CheckBallot { VoteOther, VoteStructureCheck }; + +class StructureCheckHoistingPhase : public Phase { +public: + StructureCheckHoistingPhase(Graph& graph) + : Phase(graph, "structure check hoisting") + { + } + + bool run() + { + for (unsigned i = m_graph.m_variableAccessData.size(); i--;) { + VariableAccessData* variable = &m_graph.m_variableAccessData[i]; + if (!variable->isRoot()) + continue; + variable->clearVotes(); + } + + // Identify the set of variables that are always subject to the same structure + // checks. For now, only consider monomorphic structure checks (one structure). + + for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { + BasicBlock* block = m_graph.m_blocks[blockIndex].get(); + if (!block) + continue; + for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) { + NodeIndex nodeIndex = block->at(indexInBlock); + Node& node = m_graph[nodeIndex]; + if (!node.shouldGenerate()) + continue; + switch (node.op()) { + case CheckStructure: { + Node& child = m_graph[node.child1()]; + if (child.op() != GetLocal) + break; + VariableAccessData* variable = child.variableAccessData(); + variable->vote(VoteStructureCheck); + if (variable->isCaptured() || variable->structureCheckHoistingFailed()) + break; + if (!isCellSpeculation(variable->prediction())) + break; + noticeStructureCheck(variable, node.structureSet()); + break; + } + + case ForwardCheckStructure: + // We currently rely on the fact that we're the only ones who would + // insert this node. + ASSERT_NOT_REACHED(); + break; + + case GetByOffset: + case PutByOffset: + case PutStructure: + case StructureTransitionWatchpoint: + case AllocatePropertyStorage: + case ReallocatePropertyStorage: + case GetPropertyStorage: + // Don't count these uses. + break; + + default: + m_graph.vote(node, VoteOther); + break; + } + } + } + + // Disable structure hoisting on variables that appear to mostly be used in + // contexts where it doesn't make sense. + + for (unsigned i = m_graph.m_variableAccessData.size(); i--;) { + VariableAccessData* variable = &m_graph.m_variableAccessData[i]; + if (!variable->isRoot()) + continue; + if (variable->voteRatio() >= Options::structureCheckVoteRatioForHoisting()) + continue; + HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable); + if (iter == m_map.end()) + continue; +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + dataLog("Zeroing the structure to hoist for %s because the ratio is %lf.\n", + m_graph.nameOfVariableAccessData(variable), variable->voteRatio()); +#endif + iter->second.m_structure = 0; + } + + // Identify the set of variables that are live across a structure clobber. + + Operands<VariableAccessData*> live( + m_graph.m_blocks[0]->variablesAtTail.numberOfArguments(), + m_graph.m_blocks[0]->variablesAtTail.numberOfLocals()); + for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { + BasicBlock* block = m_graph.m_blocks[blockIndex].get(); + if (!block) + continue; + ASSERT(live.numberOfArguments() == block->variablesAtTail.numberOfArguments()); + ASSERT(live.numberOfLocals() == block->variablesAtTail.numberOfLocals()); + for (unsigned i = live.size(); i--;) { + NodeIndex indexAtTail = block->variablesAtTail[i]; + VariableAccessData* variable; + if (indexAtTail == NoNode) + variable = 0; + else + variable = m_graph[indexAtTail].variableAccessData(); + live[i] = variable; + } + for (unsigned indexInBlock = block->size(); indexInBlock--;) { + NodeIndex nodeIndex = block->at(indexInBlock); + Node& node = m_graph[nodeIndex]; + if (!node.shouldGenerate()) + continue; + switch (node.op()) { + case GetLocal: + case Flush: + // This is a birth. + live.operand(node.local()) = node.variableAccessData(); + break; + + case SetLocal: + case SetArgument: + ASSERT(live.operand(node.local())); // Must be live. + ASSERT(live.operand(node.local()) == node.variableAccessData()); // Must have the variable we expected. + // This is a death. + live.operand(node.local()) = 0; + break; + + // Use the CFA's notion of what clobbers the world. + case ValueAdd: + if (m_graph.addShouldSpeculateInteger(node)) + break; + if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) + break; + clobber(live); + break; + + case CompareLess: + case CompareLessEq: + case CompareGreater: + case CompareGreaterEq: + case CompareEq: { + Node& left = m_graph[node.child1()]; + Node& right = m_graph[node.child2()]; + if (Node::shouldSpeculateInteger(left, right)) + break; + if (Node::shouldSpeculateNumber(left, right)) + break; + if (node.op() == CompareEq) { + if ((m_graph.isConstant(node.child1().index()) + && m_graph.valueOfJSConstant(node.child1().index()).isNull()) + || (m_graph.isConstant(node.child2().index()) + && m_graph.valueOfJSConstant(node.child2().index()).isNull())) + break; + + if (Node::shouldSpeculateFinalObject(left, right)) + break; + if (Node::shouldSpeculateArray(left, right)) + break; + if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther()) + break; + if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther()) + break; + if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther()) + break; + if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther()) + break; + } + clobber(live); + break; + } + + case GetByVal: + if (!node.prediction() || !m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction()) + break; + if (!isActionableArraySpeculation(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) + clobber(live); + break; + + case PutByVal: + case PutByValAlias: { + Edge child1 = m_graph.varArgChild(node, 0); + Edge child2 = m_graph.varArgChild(node, 1); + + if (!m_graph[child1].prediction() || !m_graph[child2].prediction()) + break; + if (!m_graph[child2].shouldSpeculateInteger() || !isActionableMutableArraySpeculation(m_graph[child1].prediction())) { + clobber(live); + break; + } + if (node.op() == PutByValAlias) + break; + if (m_graph[child1].shouldSpeculateArguments()) + break; + if (m_graph[child1].shouldSpeculateInt8Array()) + break; + if (m_graph[child1].shouldSpeculateInt16Array()) + break; + if (m_graph[child1].shouldSpeculateInt32Array()) + break; + if (m_graph[child1].shouldSpeculateUint8Array()) + break; + if (m_graph[child1].shouldSpeculateUint8ClampedArray()) + break; + if (m_graph[child1].shouldSpeculateUint16Array()) + break; + if (m_graph[child1].shouldSpeculateUint32Array()) + break; + if (m_graph[child1].shouldSpeculateFloat32Array()) + break; + if (m_graph[child1].shouldSpeculateFloat64Array()) + break; + clobber(live); + break; + } + + case GetMyArgumentsLengthSafe: + case GetMyArgumentByValSafe: + case GetById: + case GetByIdFlush: + case PutStructure: + case PhantomPutStructure: + case PutById: + case PutByIdDirect: + case Call: + case Construct: + case Resolve: + case ResolveBase: + case ResolveBaseStrictPut: + case ResolveGlobal: + clobber(live); + break; + + default: + ASSERT(node.op() != Phi); + break; + } + } + } + + bool changed = false; + +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + for (HashMap<VariableAccessData*, CheckData>::iterator it = m_map.begin(); + it != m_map.end(); ++it) { + if (!it->second.m_structure) { + dataLog("Not hoisting checks for %s because of heuristics.\n", m_graph.nameOfVariableAccessData(it->first)); + continue; + } + if (it->second.m_isClobbered && !it->second.m_structure->transitionWatchpointSetIsStillValid()) { + dataLog("Not hoisting checks for %s because the structure is clobbered and has an invalid watchpoint set.\n", m_graph.nameOfVariableAccessData(it->first)); + continue; + } + dataLog("Hoisting checks for %s\n", m_graph.nameOfVariableAccessData(it->first)); + } +#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + + // Make changes: + // 1) If a variable's live range does not span a clobber, then inject structure + // checks before the SetLocal. + // 2) If a variable's live range spans a clobber but is watchpointable, then + // inject structure checks before the SetLocal and replace all other structure + // checks on that variable with structure transition watchpoints. + + InsertionSet<NodeIndex> insertionSet; + for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { + BasicBlock* block = m_graph.m_blocks[blockIndex].get(); + if (!block) + continue; + for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) { + NodeIndex nodeIndex = block->at(indexInBlock); + Node& node = m_graph[nodeIndex]; + // Be careful not to use 'node' after appending to the graph. In those switch + // cases where we need to append, we first carefully extract everything we need + // from the node, before doing any appending. + if (!node.shouldGenerate()) + continue; + switch (node.op()) { + case SetArgument: { + ASSERT(!blockIndex); + // Insert a GetLocal and a CheckStructure immediately following this + // SetArgument, if the variable was a candidate for structure hoisting. + // If the basic block previously only had the SetArgument as its + // variable-at-tail, then replace it with this GetLocal. + VariableAccessData* variable = node.variableAccessData(); + HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable); + if (iter == m_map.end()) + break; + if (!iter->second.m_structure) + break; + if (iter->second.m_isClobbered && !iter->second.m_structure->transitionWatchpointSetIsStillValid()) + break; + + node.ref(); + + CodeOrigin codeOrigin = node.codeOrigin; + + Node getLocal(GetLocal, codeOrigin, OpInfo(variable), nodeIndex); + getLocal.predict(variable->prediction()); + getLocal.ref(); + NodeIndex getLocalIndex = m_graph.size(); + m_graph.append(getLocal); + insertionSet.append(indexInBlock + 1, getLocalIndex); + + Node checkStructure(CheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->second.m_structure)), getLocalIndex); + checkStructure.ref(); + NodeIndex checkStructureIndex = m_graph.size(); + m_graph.append(checkStructure); + insertionSet.append(indexInBlock + 1, checkStructureIndex); + + if (block->variablesAtTail.operand(variable->local()) == nodeIndex) + block->variablesAtTail.operand(variable->local()) = getLocalIndex; + + changed = true; + break; + } + + case SetLocal: { + VariableAccessData* variable = node.variableAccessData(); + HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable); + if (iter == m_map.end()) + break; + if (!iter->second.m_structure) + break; + if (iter->second.m_isClobbered && !iter->second.m_structure->transitionWatchpointSetIsStillValid()) + break; + + // First insert a dead SetLocal to tell OSR that the child's value should + // be dropped into this bytecode variable if the CheckStructure decides + // to exit. + + CodeOrigin codeOrigin = node.codeOrigin; + NodeIndex child1 = node.child1().index(); + + Node setLocal(SetLocal, codeOrigin, OpInfo(variable), child1); + NodeIndex setLocalIndex = m_graph.size(); + m_graph.append(setLocal); + insertionSet.append(indexInBlock, setLocalIndex); + m_graph[child1].ref(); + // Use a ForwardCheckStructure to indicate that we should exit to the + // next bytecode instruction rather than reexecuting the current one. + Node checkStructure(ForwardCheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->second.m_structure)), child1); + checkStructure.ref(); + NodeIndex checkStructureIndex = m_graph.size(); + m_graph.append(checkStructure); + insertionSet.append(indexInBlock, checkStructureIndex); + changed = true; + break; + } + + case CheckStructure: { + Node& child = m_graph[node.child1()]; + if (child.op() != GetLocal) + break; + HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(child.variableAccessData()); + if (iter == m_map.end()) + break; + if (!iter->second.m_structure) + break; + if (!iter->second.m_isClobbered) { + node.setOpAndDefaultFlags(Phantom); + ASSERT(node.refCount() == 1); + break; + } + if (!iter->second.m_structure->transitionWatchpointSetIsStillValid()) + break; + ASSERT(iter->second.m_structure == node.structureSet().singletonStructure()); + node.convertToStructureTransitionWatchpoint(); + changed = true; + break; + } + + default: + break; + } + } + insertionSet.execute(*block); + } + + return changed; + } + +private: + void noticeStructureCheck(VariableAccessData* variable, Structure* structure) + { + HashMap<VariableAccessData*, CheckData>::AddResult result = + m_map.add(variable, CheckData(structure, false)); + if (result.isNewEntry) + return; + if (result.iterator->second.m_structure == structure) + return; + result.iterator->second.m_structure = 0; + } + + void noticeStructureCheck(VariableAccessData* variable, const StructureSet& set) + { + if (set.size() != 1) { + noticeStructureCheck(variable, 0); + return; + } + noticeStructureCheck(variable, set.singletonStructure()); + } + + void noticeClobber(VariableAccessData* variable) + { + HashMap<VariableAccessData*, CheckData>::iterator iter = + m_map.find(variable); + if (iter == m_map.end()) + return; + iter->second.m_isClobbered = true; + } + + void clobber(const Operands<VariableAccessData*>& live) + { + for (size_t i = live.size(); i--;) { + VariableAccessData* variable = live[i]; + if (!variable) + continue; + noticeClobber(variable); + } + } + + struct CheckData { + Structure* m_structure; + bool m_isClobbered; + + CheckData() + : m_structure(0) + , m_isClobbered(false) + { + } + + CheckData(Structure* structure, bool isClobbered) + : m_structure(structure) + , m_isClobbered(isClobbered) + { + } + }; + + HashMap<VariableAccessData*, CheckData> m_map; +}; + +bool performStructureCheckHoisting(Graph& graph) +{ + SamplingRegion samplingRegion("DFG Structure Check Hoisting Phase"); + return runPhase<StructureCheckHoistingPhase>(graph); +} + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + + diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h new file mode 100644 index 000000000..1e6462a92 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h @@ -0,0 +1,50 @@ +/* + * 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 DFGStructureCheckHoistingPhase_h +#define DFGStructureCheckHoistingPhase_h + +#include <wtf/Platform.h> + +#if ENABLE(DFG_JIT) + +namespace JSC { namespace DFG { + +class Graph; + +// Hoists CheckStructure on variables to assignments to those variables, if either of +// the following is true: +// A) The structure's transition watchpoint set is valid. +// B) The span of code within which the variable is live has no effects that might +// clobber the structure. + +bool performStructureCheckHoisting(Graph&); + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGStructureCheckHoistingPhase_h + diff --git a/Source/JavaScriptCore/dfg/DFGVariableAccessData.h b/Source/JavaScriptCore/dfg/DFGVariableAccessData.h index e734e6387..6d8e89799 100644 --- a/Source/JavaScriptCore/dfg/DFGVariableAccessData.h +++ b/Source/JavaScriptCore/dfg/DFGVariableAccessData.h @@ -37,10 +37,10 @@ namespace JSC { namespace DFG { +enum DoubleBallot { VoteValue, VoteDouble }; + class VariableAccessData : public UnionFind<VariableAccessData> { public: - enum Ballot { VoteValue, VoteDouble }; - VariableAccessData() : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min())) , m_prediction(SpecNone) @@ -49,6 +49,7 @@ public: , m_doubleFormatState(EmptyDoubleFormatState) , m_isCaptured(false) , m_isArgumentsAlias(false) + , m_structureCheckHoistingFailed(false) { clearVotes(); } @@ -61,6 +62,7 @@ public: , m_doubleFormatState(EmptyDoubleFormatState) , m_isCaptured(isCaptured) , m_isArgumentsAlias(false) + , m_structureCheckHoistingFailed(false) { clearVotes(); } @@ -90,6 +92,20 @@ public: return m_isCaptured; } + bool mergeStructureCheckHoistingFailed(bool failed) + { + bool newFailed = m_structureCheckHoistingFailed | failed; + if (newFailed == m_structureCheckHoistingFailed) + return false; + m_structureCheckHoistingFailed = newFailed; + return true; + } + + bool structureCheckHoistingFailed() + { + return m_structureCheckHoistingFailed; + } + bool mergeIsArgumentsAlias(bool isArgumentsAlias) { bool newIsArgumentsAlias = m_isArgumentsAlias | isArgumentsAlias; @@ -136,20 +152,20 @@ public: void clearVotes() { ASSERT(find() == this); - m_votes[VoteValue] = 0; - m_votes[VoteDouble] = 0; + m_votes[0] = 0; + m_votes[1] = 0; } - void vote(Ballot ballot) + void vote(unsigned ballot) { - ASSERT(static_cast<unsigned>(ballot) < 2); + ASSERT(ballot < 2); m_votes[ballot]++; } - double doubleVoteRatio() + double voteRatio() { ASSERT(find() == this); - return static_cast<double>(m_votes[VoteDouble]) / m_votes[VoteValue]; + return static_cast<double>(m_votes[1]) / m_votes[0]; } bool shouldUseDoubleFormatAccordingToVote() @@ -176,7 +192,7 @@ public: // If the variable has been voted to become a double, then make it a // double. - if (doubleVoteRatio() >= Options::doubleVoteRatioForDoubleFormat()) + if (voteRatio() >= Options::doubleVoteRatioForDoubleFormat()) return true; return false; @@ -250,11 +266,12 @@ private: SpeculatedType m_argumentAwarePrediction; NodeFlags m_flags; - float m_votes[2]; + float m_votes[2]; // Used primarily for double voting but may be reused for other purposes. DoubleFormatState m_doubleFormatState; bool m_isCaptured; bool m_isArgumentsAlias; + bool m_structureCheckHoistingFailed; }; } } // namespace JSC::DFG diff --git a/Source/JavaScriptCore/heap/BlockAllocator.cpp b/Source/JavaScriptCore/heap/BlockAllocator.cpp index fc4f8a4c6..690fd83c4 100644 --- a/Source/JavaScriptCore/heap/BlockAllocator.cpp +++ b/Source/JavaScriptCore/heap/BlockAllocator.cpp @@ -55,7 +55,7 @@ BlockAllocator::~BlockAllocator() void BlockAllocator::releaseFreeBlocks() { while (true) { - HeapBlock* block; + DeadBlock* block; { SpinLockHolder locker(&m_freeBlockLock); if (!m_numberOfFreeBlocks) @@ -70,7 +70,7 @@ void BlockAllocator::releaseFreeBlocks() if (!block) break; - block->m_allocation.deallocate(); + DeadBlock::destroy(block).deallocate(); } } @@ -121,7 +121,7 @@ void BlockAllocator::blockFreeingThreadMain() size_t desiredNumberOfFreeBlocks = currentNumberOfFreeBlocks / 2; while (!m_blockFreeingThreadShouldQuit) { - HeapBlock* block; + DeadBlock* block; { SpinLockHolder locker(&m_freeBlockLock); if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks) @@ -136,7 +136,7 @@ void BlockAllocator::blockFreeingThreadMain() if (!block) break; - block->m_allocation.deallocate(); + DeadBlock::destroy(block).deallocate(); } } } diff --git a/Source/JavaScriptCore/heap/BlockAllocator.h b/Source/JavaScriptCore/heap/BlockAllocator.h index 7a99d2edd..042e65d92 100644 --- a/Source/JavaScriptCore/heap/BlockAllocator.h +++ b/Source/JavaScriptCore/heap/BlockAllocator.h @@ -38,6 +38,24 @@ namespace JSC { // Simple allocator to reduce VM cost by holding onto blocks of memory for // short periods of time and then freeing them on a secondary thread. +class DeadBlock : public HeapBlock<DeadBlock> { +public: + static DeadBlock* create(const PageAllocationAligned&); + +private: + DeadBlock(const PageAllocationAligned&); +}; + +inline DeadBlock::DeadBlock(const PageAllocationAligned& allocation) + : HeapBlock<DeadBlock>(allocation) +{ +} + +inline DeadBlock* DeadBlock::create(const PageAllocationAligned& allocation) +{ + return new(NotNull, allocation.base()) DeadBlock(allocation); +} + class BlockAllocator { public: BlockAllocator(); @@ -55,7 +73,7 @@ private: void releaseFreeBlocks(); - DoublyLinkedList<HeapBlock> m_freeBlocks; + DoublyLinkedList<DeadBlock> m_freeBlocks; size_t m_numberOfFreeBlocks; bool m_isCurrentlyAllocating; bool m_blockFreeingThreadShouldQuit; @@ -73,12 +91,12 @@ inline PageAllocationAligned BlockAllocator::allocate() if (m_numberOfFreeBlocks) { ASSERT(!m_freeBlocks.isEmpty()); m_numberOfFreeBlocks--; - return m_freeBlocks.removeHead()->m_allocation; + return DeadBlock::destroy(m_freeBlocks.removeHead()); } } ASSERT(m_freeBlocks.isEmpty()); - PageAllocationAligned allocation = PageAllocationAligned::allocate(HeapBlock::s_blockSize, HeapBlock::s_blockSize, OSAllocator::JSGCHeapPages); + PageAllocationAligned allocation = PageAllocationAligned::allocate(DeadBlock::s_blockSize, DeadBlock::s_blockSize, OSAllocator::JSGCHeapPages); if (!static_cast<bool>(allocation)) CRASH(); return allocation; @@ -87,8 +105,7 @@ inline PageAllocationAligned BlockAllocator::allocate() inline void BlockAllocator::deallocate(PageAllocationAligned allocation) { SpinLockHolder locker(&m_freeBlockLock); - HeapBlock* heapBlock = new(NotNull, allocation.base()) HeapBlock(allocation); - m_freeBlocks.push(heapBlock); + m_freeBlocks.push(DeadBlock::create(allocation)); m_numberOfFreeBlocks++; } diff --git a/Source/JavaScriptCore/heap/CopiedBlock.h b/Source/JavaScriptCore/heap/CopiedBlock.h index 6717a6835..ad5dbb46b 100644 --- a/Source/JavaScriptCore/heap/CopiedBlock.h +++ b/Source/JavaScriptCore/heap/CopiedBlock.h @@ -34,13 +34,12 @@ namespace JSC { class CopiedSpace; -class CopiedBlock : public HeapBlock { +class CopiedBlock : public HeapBlock<CopiedBlock> { friend class CopiedSpace; friend class CopiedAllocator; public: static CopiedBlock* create(const PageAllocationAligned&); static CopiedBlock* createNoZeroFill(const PageAllocationAligned&); - static PageAllocationAligned destroy(CopiedBlock*); // The payload is the region of the block that is usable for allocations. char* payload(); @@ -93,17 +92,8 @@ inline void CopiedBlock::zeroFillWilderness() #endif } -inline PageAllocationAligned CopiedBlock::destroy(CopiedBlock* block) -{ - PageAllocationAligned allocation; - swap(allocation, block->m_allocation); - - block->~CopiedBlock(); - return allocation; -} - inline CopiedBlock::CopiedBlock(const PageAllocationAligned& allocation) - : HeapBlock(allocation) + : HeapBlock<CopiedBlock>(allocation) , m_remaining(payloadCapacity()) , m_isPinned(false) { @@ -117,7 +107,7 @@ inline char* CopiedBlock::payload() inline char* CopiedBlock::payloadEnd() { - return reinterpret_cast<char*>(this) + m_allocation.size(); + return reinterpret_cast<char*>(this) + allocation().size(); } inline size_t CopiedBlock::payloadCapacity() @@ -162,7 +152,7 @@ inline size_t CopiedBlock::size() inline size_t CopiedBlock::capacity() { - return m_allocation.size(); + return allocation().size(); } } // namespace JSC diff --git a/Source/JavaScriptCore/heap/CopiedSpace.cpp b/Source/JavaScriptCore/heap/CopiedSpace.cpp index 147dfa4b3..bf87a305c 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.cpp +++ b/Source/JavaScriptCore/heap/CopiedSpace.cpp @@ -44,13 +44,13 @@ CopiedSpace::CopiedSpace(Heap* heap) CopiedSpace::~CopiedSpace() { while (!m_toSpace->isEmpty()) - m_heap->blockAllocator().deallocate(CopiedBlock::destroy(static_cast<CopiedBlock*>(m_toSpace->removeHead()))); + m_heap->blockAllocator().deallocate(CopiedBlock::destroy(m_toSpace->removeHead())); while (!m_fromSpace->isEmpty()) - m_heap->blockAllocator().deallocate(CopiedBlock::destroy(static_cast<CopiedBlock*>(m_fromSpace->removeHead()))); + m_heap->blockAllocator().deallocate(CopiedBlock::destroy(m_fromSpace->removeHead())); while (!m_oversizeBlocks.isEmpty()) - CopiedBlock::destroy(static_cast<CopiedBlock*>(m_oversizeBlocks.removeHead())).deallocate(); + CopiedBlock::destroy(m_oversizeBlocks.removeHead()).deallocate(); } void CopiedSpace::init() @@ -193,7 +193,7 @@ void CopiedSpace::doneCopying() ASSERT(m_inCopyingPhase); m_inCopyingPhase = false; while (!m_fromSpace->isEmpty()) { - CopiedBlock* block = static_cast<CopiedBlock*>(m_fromSpace->removeHead()); + CopiedBlock* block = m_fromSpace->removeHead(); if (block->m_isPinned) { block->m_isPinned = false; // We don't add the block to the blockSet because it was never removed. @@ -207,9 +207,9 @@ void CopiedSpace::doneCopying() m_heap->blockAllocator().deallocate(CopiedBlock::destroy(block)); } - CopiedBlock* curr = static_cast<CopiedBlock*>(m_oversizeBlocks.head()); + CopiedBlock* curr = m_oversizeBlocks.head(); while (curr) { - CopiedBlock* next = static_cast<CopiedBlock*>(curr->next()); + CopiedBlock* next = curr->next(); if (!curr->m_isPinned) { m_oversizeBlocks.remove(curr); m_blockSet.remove(curr); @@ -224,20 +224,20 @@ void CopiedSpace::doneCopying() if (!m_toSpace->head()) allocateBlock(); else - m_allocator.setCurrentBlock(static_cast<CopiedBlock*>(m_toSpace->head())); + m_allocator.setCurrentBlock(m_toSpace->head()); } size_t CopiedSpace::size() { size_t calculatedSize = 0; - for (CopiedBlock* block = static_cast<CopiedBlock*>(m_toSpace->head()); block; block = static_cast<CopiedBlock*>(block->next())) + for (CopiedBlock* block = m_toSpace->head(); block; block = block->next()) calculatedSize += block->size(); - for (CopiedBlock* block = static_cast<CopiedBlock*>(m_fromSpace->head()); block; block = static_cast<CopiedBlock*>(block->next())) + for (CopiedBlock* block = m_fromSpace->head(); block; block = block->next()) calculatedSize += block->size(); - for (CopiedBlock* block = static_cast<CopiedBlock*>(m_oversizeBlocks.head()); block; block = static_cast<CopiedBlock*>(block->next())) + for (CopiedBlock* block = m_oversizeBlocks.head(); block; block = block->next()) calculatedSize += block->size(); return calculatedSize; @@ -247,22 +247,22 @@ size_t CopiedSpace::capacity() { size_t calculatedCapacity = 0; - for (CopiedBlock* block = static_cast<CopiedBlock*>(m_toSpace->head()); block; block = static_cast<CopiedBlock*>(block->next())) + for (CopiedBlock* block = m_toSpace->head(); block; block = block->next()) calculatedCapacity += block->capacity(); - for (CopiedBlock* block = static_cast<CopiedBlock*>(m_fromSpace->head()); block; block = static_cast<CopiedBlock*>(block->next())) + for (CopiedBlock* block = m_fromSpace->head(); block; block = block->next()) calculatedCapacity += block->capacity(); - for (CopiedBlock* block = static_cast<CopiedBlock*>(m_oversizeBlocks.head()); block; block = static_cast<CopiedBlock*>(block->next())) + for (CopiedBlock* block = m_oversizeBlocks.head(); block; block = block->next()) calculatedCapacity += block->capacity(); return calculatedCapacity; } -static bool isBlockListPagedOut(double deadline, DoublyLinkedList<HeapBlock>* list) +static bool isBlockListPagedOut(double deadline, DoublyLinkedList<CopiedBlock>* list) { unsigned itersSinceLastTimeCheck = 0; - HeapBlock* current = list->head(); + CopiedBlock* current = list->head(); while (current) { current = current->next(); ++itersSinceLastTimeCheck; diff --git a/Source/JavaScriptCore/heap/CopiedSpace.h b/Source/JavaScriptCore/heap/CopiedSpace.h index be3a331e8..ec394ca8f 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.h +++ b/Source/JavaScriptCore/heap/CopiedSpace.h @@ -44,7 +44,6 @@ namespace JSC { class Heap; class CopiedBlock; -class HeapBlock; class CopiedSpace { friend class SlotVisitor; @@ -101,12 +100,12 @@ private: SpinLock m_toSpaceLock; - DoublyLinkedList<HeapBlock>* m_toSpace; - DoublyLinkedList<HeapBlock>* m_fromSpace; + DoublyLinkedList<CopiedBlock>* m_toSpace; + DoublyLinkedList<CopiedBlock>* m_fromSpace; - DoublyLinkedList<HeapBlock> m_blocks1; - DoublyLinkedList<HeapBlock> m_blocks2; - DoublyLinkedList<HeapBlock> m_oversizeBlocks; + DoublyLinkedList<CopiedBlock> m_blocks1; + DoublyLinkedList<CopiedBlock> m_blocks2; + DoublyLinkedList<CopiedBlock> m_oversizeBlocks; bool m_inCopyingPhase; @@ -116,7 +115,7 @@ private: static const size_t s_maxAllocationSize = 32 * KB; static const size_t s_initialBlockNum = 16; - static const size_t s_blockMask = ~(HeapBlock::s_blockSize - 1); + static const size_t s_blockMask = ~(CopiedBlock::s_blockSize - 1); }; } // namespace JSC diff --git a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h index e2af41ad8..790a302de 100644 --- a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h +++ b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h @@ -95,9 +95,7 @@ inline void CopiedSpace::pinIfNecessary(void* opaquePointer) inline void CopiedSpace::startedCopying() { - DoublyLinkedList<HeapBlock>* temp = m_fromSpace; - m_fromSpace = m_toSpace; - m_toSpace = temp; + std::swap(m_fromSpace, m_toSpace); m_blockFilter.reset(); m_allocator.resetCurrentBlock(); diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp index 377132765..669178804 100644 --- a/Source/JavaScriptCore/heap/Heap.cpp +++ b/Source/JavaScriptCore/heap/Heap.cpp @@ -830,4 +830,18 @@ void Heap::addCompiledCode(ExecutableBase* executable) m_compiledCode.append(executable); } +bool Heap::isSafeToSweepStructures() +{ + return !m_sweeper || m_sweeper->structuresCanBeSwept(); +} + +void Heap::didStartVMShutdown() +{ + m_activityCallback->didStartVMShutdown(); + m_activityCallback = 0; + m_sweeper->didStartVMShutdown(); + m_sweeper = 0; + lastChanceToFinalize(); +} + } // namespace JSC diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h index 595e937ce..f3474f2ea 100644 --- a/Source/JavaScriptCore/heap/Heap.h +++ b/Source/JavaScriptCore/heap/Heap.h @@ -168,6 +168,8 @@ namespace JSC { void didAbandon(size_t); bool isPagedOut(double deadline); + bool isSafeToSweepStructures(); + void didStartVMShutdown(); private: friend class CodeBlock; diff --git a/Source/JavaScriptCore/heap/HeapBlock.h b/Source/JavaScriptCore/heap/HeapBlock.h index 3cd3c6322..a63b7ebe1 100644 --- a/Source/JavaScriptCore/heap/HeapBlock.h +++ b/Source/JavaScriptCore/heap/HeapBlock.h @@ -34,22 +34,42 @@ namespace JSC { enum AllocationEffort { AllocationCanFail, AllocationMustSucceed }; -class HeapBlock : public DoublyLinkedListNode<HeapBlock> { +#if COMPILER(GCC) +#define CLASS_IF_GCC class +#else +#define CLASS_IF_GCC +#endif + +template<typename T> +class HeapBlock : public DoublyLinkedListNode<T> { + friend CLASS_IF_GCC DoublyLinkedListNode<T>; public: + static const size_t s_blockSize = 64 * KB; + + static PageAllocationAligned destroy(HeapBlock* block) + { + static_cast<T*>(block)->~T(); + + PageAllocationAligned allocation; + std::swap(allocation, block->m_allocation); + return allocation; + } + HeapBlock(const PageAllocationAligned& allocation) - : DoublyLinkedListNode<HeapBlock>() + : DoublyLinkedListNode<T>() + , m_allocation(allocation) , m_prev(0) , m_next(0) - , m_allocation(allocation) { ASSERT(m_allocation); } - HeapBlock* m_prev; - HeapBlock* m_next; + const PageAllocationAligned allocation() const { return m_allocation; } + +private: PageAllocationAligned m_allocation; - - static const size_t s_blockSize = 64 * KB; + T* m_prev; + T* m_next; }; } // namespace JSC diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp index 49222c545..f284d8b57 100644 --- a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp +++ b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp @@ -51,6 +51,7 @@ void IncrementalSweeper::doWork() IncrementalSweeper::IncrementalSweeper(Heap* heap, CFRunLoopRef runLoop) : HeapTimer(heap->globalData(), runLoop) , m_currentBlockToSweepIndex(0) + , m_structuresCanBeSwept(false) { } @@ -72,12 +73,7 @@ void IncrementalSweeper::cancelTimer() void IncrementalSweeper::doSweep(double sweepBeginTime) { while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) { - MarkedBlock* block = m_blocksToSweep[m_currentBlockToSweepIndex++]; - if (!block->needsSweeping()) - continue; - - block->sweep(); - m_globalData->heap.objectSpace().freeOrShrinkBlock(block); + sweepNextBlock(); CFTimeInterval elapsedTime = WTF::monotonicallyIncreasingTime() - sweepBeginTime; if (elapsedTime < sweepTimeSlice) @@ -91,17 +87,48 @@ void IncrementalSweeper::doSweep(double sweepBeginTime) cancelTimer(); } +void IncrementalSweeper::sweepNextBlock() +{ + while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) { + MarkedBlock* block = m_blocksToSweep[m_currentBlockToSweepIndex++]; + if (block->onlyContainsStructures()) + m_structuresCanBeSwept = true; + else + ASSERT(!m_structuresCanBeSwept); + + if (!block->needsSweeping()) + continue; + + block->sweep(); + m_globalData->heap.objectSpace().freeOrShrinkBlock(block); + return; + } +} + void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>& blockSnapshot) { - WTF::copyToVector(blockSnapshot, m_blocksToSweep); + m_blocksToSweep.resize(blockSnapshot.size()); + CopyFunctor functor(m_blocksToSweep); + m_globalData->heap.objectSpace().forEachBlock(functor); m_currentBlockToSweepIndex = 0; + m_structuresCanBeSwept = false; scheduleTimer(); } +void IncrementalSweeper::willFinishSweeping() +{ + m_currentBlockToSweepIndex = 0; + m_structuresCanBeSwept = true; + m_blocksToSweep.clear(); + if (m_globalData) + cancelTimer(); +} + #else IncrementalSweeper::IncrementalSweeper(JSGlobalData* globalData) : HeapTimer(globalData) + , m_structuresCanBeSwept(false) { } @@ -116,8 +143,23 @@ IncrementalSweeper* IncrementalSweeper::create(Heap* heap) void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>&) { + m_structuresCanBeSwept = false; } - + +void IncrementalSweeper::willFinishSweeping() +{ + m_structuresCanBeSwept = true; +} + +void IncrementalSweeper::sweepNextBlock() +{ +} + #endif +bool IncrementalSweeper::structuresCanBeSwept() +{ + return m_structuresCanBeSwept; +} + } // namespace JSC diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.h b/Source/JavaScriptCore/heap/IncrementalSweeper.h index eedfa7f6f..c8005b071 100644 --- a/Source/JavaScriptCore/heap/IncrementalSweeper.h +++ b/Source/JavaScriptCore/heap/IncrementalSweeper.h @@ -36,12 +36,28 @@ namespace JSC { class Heap; - + +struct CopyFunctor : public MarkedBlock::VoidFunctor { + CopyFunctor(Vector<MarkedBlock*>& blocks) + : m_index(0) + , m_blocks(blocks) + { + } + + void operator()(MarkedBlock* block) { m_blocks[m_index++] = block; } + + size_t m_index; + Vector<MarkedBlock*>& m_blocks; +}; + class IncrementalSweeper : public HeapTimer { public: static IncrementalSweeper* create(Heap*); void startSweeping(const HashSet<MarkedBlock*>& blockSnapshot); virtual void doWork(); + void sweepNextBlock(); + bool structuresCanBeSwept(); + void willFinishSweeping(); private: #if USE(CF) @@ -58,6 +74,7 @@ private: IncrementalSweeper(JSGlobalData*); #endif + bool m_structuresCanBeSwept; }; } // namespace JSC diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.cpp b/Source/JavaScriptCore/heap/MachineStackMarker.cpp index 8e0c57b6a..537a34e48 100644 --- a/Source/JavaScriptCore/heap/MachineStackMarker.cpp +++ b/Source/JavaScriptCore/heap/MachineStackMarker.cpp @@ -142,7 +142,7 @@ MachineThreads::MachineThreads(Heap* heap) MachineThreads::~MachineThreads() { if (m_threadSpecific) - ThreadSpecificKeyDelete(m_threadSpecific); + threadSpecificKeyDelete(m_threadSpecific); MutexLocker registeredThreadsLock(m_registeredThreadsMutex); for (Thread* t = m_registeredThreads; t;) { @@ -179,17 +179,17 @@ void MachineThreads::makeUsableFromMultipleThreads() if (m_threadSpecific) return; - ThreadSpecificKeyCreate(&m_threadSpecific, removeThread); + threadSpecificKeyCreate(&m_threadSpecific, removeThread); } void MachineThreads::addCurrentThread() { ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread()); - if (!m_threadSpecific || ThreadSpecificGet(m_threadSpecific)) + if (!m_threadSpecific || threadSpecificGet(m_threadSpecific)) return; - ThreadSpecificSet(m_threadSpecific, this); + threadSpecificSet(m_threadSpecific, this); Thread* thread = new Thread(getCurrentPlatformThread(), wtfThreadData().stack().origin()); MutexLocker lock(m_registeredThreadsMutex); diff --git a/Source/JavaScriptCore/heap/MarkedAllocator.cpp b/Source/JavaScriptCore/heap/MarkedAllocator.cpp index 465e3a72a..20b556969 100644 --- a/Source/JavaScriptCore/heap/MarkedAllocator.cpp +++ b/Source/JavaScriptCore/heap/MarkedAllocator.cpp @@ -3,6 +3,7 @@ #include "GCActivityCallback.h" #include "Heap.h" +#include "IncrementalSweeper.h" #include "JSGlobalData.h" #include <wtf/CurrentTime.h> @@ -11,7 +12,7 @@ namespace JSC { bool MarkedAllocator::isPagedOut(double deadline) { unsigned itersSinceLastTimeCheck = 0; - HeapBlock* block = m_blockList.head(); + MarkedBlock* block = m_blockList.head(); while (block) { block = block->next(); ++itersSinceLastTimeCheck; @@ -29,7 +30,18 @@ bool MarkedAllocator::isPagedOut(double deadline) inline void* MarkedAllocator::tryAllocateHelper() { if (!m_freeList.head) { - for (MarkedBlock*& block = m_blocksToSweep; block; block = static_cast<MarkedBlock*>(block->next())) { + if (m_onlyContainsStructures && !m_heap->isSafeToSweepStructures()) { + if (m_currentBlock) { + m_currentBlock->didConsumeFreeList(); + m_currentBlock = 0; + } + // We sweep another random block here so that we can make progress + // toward being able to sweep Structures. + m_heap->sweeper()->sweepNextBlock(); + return 0; + } + + for (MarkedBlock*& block = m_blocksToSweep; block; block = block->next()) { m_freeList = block->sweep(MarkedBlock::SweepToFreeList); if (m_freeList.head) { m_currentBlock = block; @@ -104,7 +116,6 @@ MarkedBlock* MarkedAllocator::allocateBlock() void MarkedAllocator::addBlock(MarkedBlock* block) { ASSERT(!m_currentBlock); - ASSERT(!m_blocksToSweep); ASSERT(!m_freeList.head); m_blockList.append(block); @@ -115,11 +126,11 @@ void MarkedAllocator::addBlock(MarkedBlock* block) void MarkedAllocator::removeBlock(MarkedBlock* block) { if (m_currentBlock == block) { - m_currentBlock = static_cast<MarkedBlock*>(m_currentBlock->next()); + m_currentBlock = m_currentBlock->next(); m_freeList = MarkedBlock::FreeList(); } if (m_blocksToSweep == block) - m_blocksToSweep = static_cast<MarkedBlock*>(m_blocksToSweep->next()); + m_blocksToSweep = m_blocksToSweep->next(); m_blockList.remove(block); } diff --git a/Source/JavaScriptCore/heap/MarkedAllocator.h b/Source/JavaScriptCore/heap/MarkedAllocator.h index 47bae9451..c1c431194 100644 --- a/Source/JavaScriptCore/heap/MarkedAllocator.h +++ b/Source/JavaScriptCore/heap/MarkedAllocator.h @@ -47,7 +47,7 @@ private: MarkedBlock::FreeList m_freeList; MarkedBlock* m_currentBlock; MarkedBlock* m_blocksToSweep; - DoublyLinkedList<HeapBlock> m_blockList; + DoublyLinkedList<MarkedBlock> m_blockList; size_t m_cellSize; bool m_cellsNeedDestruction; bool m_onlyContainsStructures; @@ -90,7 +90,7 @@ inline void MarkedAllocator::reset() { m_currentBlock = 0; m_freeList = MarkedBlock::FreeList(); - m_blocksToSweep = static_cast<MarkedBlock*>(m_blockList.head()); + m_blocksToSweep = m_blockList.head(); } inline void MarkedAllocator::zapFreeList() @@ -101,15 +101,16 @@ inline void MarkedAllocator::zapFreeList() } m_currentBlock->zapFreeList(m_freeList); + m_currentBlock = 0; m_freeList = MarkedBlock::FreeList(); } template <typename Functor> inline void MarkedAllocator::forEachBlock(Functor& functor) { - HeapBlock* next; - for (HeapBlock* block = m_blockList.head(); block; block = next) { + MarkedBlock* next; + for (MarkedBlock* block = m_blockList.head(); block; block = next) { next = block->next(); - functor(static_cast<MarkedBlock*>(block)); + functor(block); } } diff --git a/Source/JavaScriptCore/heap/MarkedBlock.cpp b/Source/JavaScriptCore/heap/MarkedBlock.cpp index 8ede87927..95ea2f414 100644 --- a/Source/JavaScriptCore/heap/MarkedBlock.cpp +++ b/Source/JavaScriptCore/heap/MarkedBlock.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "MarkedBlock.h" +#include "IncrementalSweeper.h" #include "JSCell.h" #include "JSObject.h" #include "ScopeChain.h" @@ -37,17 +38,8 @@ MarkedBlock* MarkedBlock::create(const PageAllocationAligned& allocation, Heap* return new (NotNull, allocation.base()) MarkedBlock(allocation, heap, cellSize, cellsNeedDestruction, onlyContainsStructures); } -PageAllocationAligned MarkedBlock::destroy(MarkedBlock* block) -{ - PageAllocationAligned allocation; - swap(allocation, block->m_allocation); - - block->~MarkedBlock(); - return allocation; -} - MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, Heap* heap, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures) - : HeapBlock(allocation) + : HeapBlock<MarkedBlock>(allocation) , m_atomsPerCell((cellSize + atomSize - 1) / atomSize) , m_endAtom(atomsPerBlock - m_atomsPerCell + 1) , m_cellsNeedDestruction(cellsNeedDestruction) @@ -69,10 +61,6 @@ inline void MarkedBlock::callDestructor(JSCell* cell) m_heap->m_destroyedTypeCounts.countVPtr(vptr); #endif -#if !ASSERT_DISABLED || ENABLE(GC_VALIDATION) - cell->clearStructure(); -#endif - cell->methodTable()->destroy(cell); cell->zap(); } @@ -140,10 +128,12 @@ MarkedBlock::FreeList MarkedBlock::sweepHelper(SweepMode sweepMode) ASSERT_NOT_REACHED(); return FreeList(); case Marked: + ASSERT(!m_onlyContainsStructures || heap()->isSafeToSweepStructures()); return sweepMode == SweepToFreeList ? specializedSweep<Marked, SweepToFreeList, destructorCallNeeded>() : specializedSweep<Marked, SweepOnly, destructorCallNeeded>(); case Zapped: + ASSERT(!m_onlyContainsStructures || heap()->isSafeToSweepStructures()); return sweepMode == SweepToFreeList ? specializedSweep<Zapped, SweepToFreeList, destructorCallNeeded>() : specializedSweep<Zapped, SweepOnly, destructorCallNeeded>(); diff --git a/Source/JavaScriptCore/heap/MarkedBlock.h b/Source/JavaScriptCore/heap/MarkedBlock.h index ff7840632..ab2abd753 100644 --- a/Source/JavaScriptCore/heap/MarkedBlock.h +++ b/Source/JavaScriptCore/heap/MarkedBlock.h @@ -67,8 +67,7 @@ namespace JSC { // size is equal to the difference between the cell size and the object // size. - class MarkedBlock : public HeapBlock { - friend class WTF::DoublyLinkedListNode<MarkedBlock>; + class MarkedBlock : public HeapBlock<MarkedBlock> { public: // Ensure natural alignment for native types whilst recognizing that the smallest // object the heap will commonly allocate is four words. @@ -114,7 +113,6 @@ namespace JSC { }; static MarkedBlock* create(const PageAllocationAligned&, Heap*, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures); - static PageAllocationAligned destroy(MarkedBlock*); static bool isAtomAligned(const void*); static MarkedBlock* blockFor(const void*); @@ -336,7 +334,7 @@ namespace JSC { inline size_t MarkedBlock::capacity() { - return m_allocation.size(); + return allocation().size(); } inline size_t MarkedBlock::atomNumber(const void* p) diff --git a/Source/JavaScriptCore/heap/MarkedSpace.cpp b/Source/JavaScriptCore/heap/MarkedSpace.cpp index a9e9ef64d..cd6be001c 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.cpp +++ b/Source/JavaScriptCore/heap/MarkedSpace.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "MarkedSpace.h" +#include "IncrementalSweeper.h" #include "JSGlobalObject.h" #include "JSLock.h" #include "JSObject.h" @@ -108,6 +109,12 @@ void MarkedSpace::lastChanceToFinalize() forEachBlock<LastChanceToFinalize>(); } +void MarkedSpace::sweep() +{ + m_heap->sweeper()->willFinishSweeping(); + forEachBlock<Sweep>(); +} + void MarkedSpace::resetAllocators() { for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) { diff --git a/Source/JavaScriptCore/heap/MarkedSpace.h b/Source/JavaScriptCore/heap/MarkedSpace.h index d2a0688f1..d5dae3584 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.h +++ b/Source/JavaScriptCore/heap/MarkedSpace.h @@ -235,11 +235,6 @@ inline void MarkedSpace::clearMarks() forEachBlock<ClearMarks>(); } -inline void MarkedSpace::sweep() -{ - forEachBlock<Sweep>(); -} - inline size_t MarkedSpace::objectCount() { return forEachBlock<MarkCount>(); diff --git a/Source/JavaScriptCore/heap/WeakSetInlines.h b/Source/JavaScriptCore/heap/WeakSetInlines.h index c1c87b380..76337fda7 100644 --- a/Source/JavaScriptCore/heap/WeakSetInlines.h +++ b/Source/JavaScriptCore/heap/WeakSetInlines.h @@ -49,9 +49,6 @@ inline void WeakBlock::finalize(WeakImpl* weakImpl) WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner(); if (!weakHandleOwner) return; -#if !ASSERT_DISABLED || ENABLE(GC_VALIDATION) - weakImpl->jsValue().asCell()->clearStructure(); -#endif weakHandleOwner->finalize(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(weakImpl->jsValue())), weakImpl->context()); } diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index 3edb8589e..51f22bedd 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -730,9 +730,9 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) { DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); if (callFrame->callee()) - debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine()); + debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine(), 0); else - debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine()); + debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine(), 0); } // If this call frame created an activation or an 'arguments' object, tear it off. @@ -1055,7 +1055,7 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) { DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset); - debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), hasHandler); + debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), 0, hasHandler); } // Calculate an exception handler vPC, unwinding call frames as necessary. @@ -1643,7 +1643,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue return checkedReturn(result); } -NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine) +NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine, int column) { Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); if (!debugger) @@ -1651,22 +1651,22 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook switch (debugHookID) { case DidEnterCallFrame: - debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine); + debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column); return; case WillLeaveCallFrame: - debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine); + debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column); return; case WillExecuteStatement: - debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine); + debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column); return; case WillExecuteProgram: - debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine); + debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column); return; case DidExecuteProgram: - debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine); + debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column); return; case DidReachBreakpoint: - debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine); + debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column); return; } } @@ -5245,7 +5245,7 @@ skip_id_custom_self: NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_debug) { - /* debug debugHookID(n) firstLine(n) lastLine(n) + /* debug debugHookID(n) firstLine(n) lastLine(n) column(n) Notifies the debugger of the current state of execution. This opcode is only generated while the debugger is attached. @@ -5253,8 +5253,10 @@ skip_id_custom_self: int debugHookID = vPC[1].u.operand; int firstLine = vPC[2].u.operand; int lastLine = vPC[3].u.operand; + int column = vPC[4].u.operand; - debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); + + debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column); vPC += OPCODE_LENGTH(op_debug); NEXT_INSTRUCTION(); diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h index 8663bf8ec..f4ccd995c 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.h +++ b/Source/JavaScriptCore/interpreter/Interpreter.h @@ -240,7 +240,7 @@ namespace JSC { SamplingTool* sampler() { return m_sampler.get(); } NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset); - NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine); + NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine, int column); static const UString getTraceLine(CallFrame*, StackFrameCodeType, const UString&, int); JS_EXPORT_PRIVATE static void getStackTrace(JSGlobalData*, Vector<StackFrame>& results); static void addStackTraceIfNecessary(CallFrame*, JSObject* error); diff --git a/Source/JavaScriptCore/jit/JITInlineMethods.h b/Source/JavaScriptCore/jit/JITInlineMethods.h index 32bc1837d..e68ecbe78 100644 --- a/Source/JavaScriptCore/jit/JITInlineMethods.h +++ b/Source/JavaScriptCore/jit/JITInlineMethods.h @@ -84,7 +84,7 @@ ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHea ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures) { - failures.append(branchPtr(NotEqual, Address(src, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + failures.append(branchPtr(NotEqual, Address(src, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get()))); failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), TrustedImm32(1))); loadPtr(MacroAssembler::Address(src, ThunkHelpers::jsStringValueOffset()), dst); failures.append(branchTest32(Zero, dst)); diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp index c0af6f9e9..0d24961b8 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp @@ -50,7 +50,7 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl // Check eax is a string Jump string_failureCases1 = emitJumpIfNotJSCell(regT0); - Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)); + Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(globalData->stringStructure.get())); // Checks out okay! - get the length from the Ustring. load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_length)), regT0); @@ -647,7 +647,7 @@ void JIT::emit_op_to_primitive(Instruction* currentInstruction) emitGetVirtualRegister(src, regT0); Jump isImm = emitJumpIfNotJSCell(regT0); - addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get()))); isImm.link(this); if (dst != src) @@ -1158,6 +1158,7 @@ void JIT::emit_op_debug(Instruction* currentInstruction) stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand)); stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand)); stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[4].u.operand)); stubCall.call(); #endif } @@ -1260,7 +1261,7 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction) loadPtr(Address(regT1, JSCell::structureOffset()), regT0); emitValueProfilingSite(); } - addSlowCase(branchPtr(Equal, Address(regT1, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + addSlowCase(branchPtr(Equal, Address(regT1, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get()))); } void JIT::emit_op_create_this(Instruction* currentInstruction) diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp index 095ea57d3..eec9df36f 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp @@ -48,7 +48,7 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl // regT0 holds payload, regT1 holds tag Jump string_failureCases1 = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); - Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)); + Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(globalData->stringStructure.get())); // Checks out okay! - get the length from the Ustring. load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_length)), regT2); @@ -732,7 +732,7 @@ void JIT::emit_op_to_primitive(Instruction* currentInstruction) emitLoad(src, regT1, regT0); Jump isImm = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); - addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get()))); isImm.link(this); if (dst != src) @@ -1008,8 +1008,8 @@ void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>: genericCase.append(getSlowCase(iter)); // tags not equal linkSlowCase(iter); // tags equal and JSCell - genericCase.append(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); - genericCase.append(branchPtr(NotEqual, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + genericCase.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get()))); + genericCase.append(branchPtr(NotEqual, Address(regT2, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get()))); // String case. JITStubCall stubCallEqStrings(this, cti_op_eq_strings); @@ -1056,8 +1056,8 @@ void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry> genericCase.append(getSlowCase(iter)); // tags not equal linkSlowCase(iter); // tags equal and JSCell - genericCase.append(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); - genericCase.append(branchPtr(NotEqual, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + genericCase.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get()))); + genericCase.append(branchPtr(NotEqual, Address(regT2, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get()))); // String case. JITStubCall stubCallEqStrings(this, cti_op_eq_strings); @@ -1093,8 +1093,8 @@ void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqTy // Jump to a slow case if both are strings. Jump notCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); - Jump firstNotString = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)); - addSlowCase(branchPtr(Equal, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + Jump firstNotString = branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get())); + addSlowCase(branchPtr(Equal, Address(regT2, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get()))); notCell.link(this); firstNotString.link(this); @@ -1478,6 +1478,7 @@ void JIT::emit_op_debug(Instruction* currentInstruction) stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); + stubCall.addArgument(Imm32(currentInstruction[4].u.operand)); stubCall.call(); #endif } @@ -1556,7 +1557,7 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction) move(regT3, regT1); emitValueProfilingSite(); } - addSlowCase(branchPtr(Equal, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + addSlowCase(branchPtr(Equal, Address(regT2, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get()))); } void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp index 86078fbc3..dfb2dc8ec 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -56,7 +56,7 @@ JIT::CodeRef JIT::stringGetByValStubGenerator(JSGlobalData* globalData) { JSInterfaceJIT jit; JumpList failures; - failures.append(jit.branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + failures.append(jit.branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(globalData->stringStructure.get()))); // Load string length to regT2, and start the process of loading the data pointer into regT0 jit.load32(Address(regT0, ThunkHelpers::jsStringLengthOffset()), regT2); @@ -132,7 +132,7 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas linkSlowCaseIfNotJSCell(iter, base); // base cell check Jump nonCell = jump(); linkSlowCase(iter); // base array check - Jump notString = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)); + Jump notString = branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get())); emitNakedCall(CodeLocationLabel(m_globalData->getCTIStub(stringGetByValStubGenerator).code())); Jump failed = branchTestPtr(Zero, regT0); emitPutVirtualRegister(dst, regT0); diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp index 365ecd20a..b506f4ecb 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp @@ -161,7 +161,7 @@ JIT::CodeRef JIT::stringGetByValStubGenerator(JSGlobalData* globalData) { JSInterfaceJIT jit; JumpList failures; - failures.append(jit.branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + failures.append(jit.branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(globalData->stringStructure.get()))); // Load string length to regT1, and start the process of loading the data pointer into regT0 jit.load32(Address(regT0, ThunkHelpers::jsStringLengthOffset()), regT1); @@ -234,7 +234,7 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas Jump nonCell = jump(); linkSlowCase(iter); // base array check - Jump notString = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)); + Jump notString = branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(m_globalData->stringStructure.get())); emitNakedCall(m_globalData->getCTIStub(stringGetByValStubGenerator).code()); Jump failed = branchTestPtr(Zero, regT0); emitStore(dst, regT1, regT0); diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp index 0f03a0a4a..8b8546994 100644 --- a/Source/JavaScriptCore/jit/JITStubs.cpp +++ b/Source/JavaScriptCore/jit/JITStubs.cpp @@ -1430,15 +1430,19 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id) CallFrame* callFrame = stackFrame.callFrame; Identifier& ident = stackFrame.args[1].identifier(); + CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); + StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + AccessType accessType = static_cast<AccessType>(stubInfo->accessType); + PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot); - CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); - StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); - if (!stubInfo->seenOnce()) - stubInfo->setSeen(); - else - JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false); + if (accessType == static_cast<AccessType>(stubInfo->accessType)) { + if (!stubInfo->seenOnce()) + stubInfo->setSeen(); + else + JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false); + } CHECK_FOR_EXCEPTION_AT_END(); } @@ -1449,18 +1453,22 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct) CallFrame* callFrame = stackFrame.callFrame; Identifier& ident = stackFrame.args[1].identifier(); + CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); + StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + AccessType accessType = static_cast<AccessType>(stubInfo->accessType); + PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); JSValue baseValue = stackFrame.args[0].jsValue(); ASSERT(baseValue.isObject()); asObject(baseValue)->putDirect(callFrame->globalData(), ident, stackFrame.args[2].jsValue(), slot); - CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); - StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); - if (!stubInfo->seenOnce()) - stubInfo->setSeen(); - else - JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true); + if (accessType == static_cast<AccessType>(stubInfo->accessType)) { + if (!stubInfo->seenOnce()) + stubInfo->setSeen(); + else + JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true); + } CHECK_FOR_EXCEPTION_AT_END(); } @@ -1521,14 +1529,18 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check) CallFrame* callFrame = stackFrame.callFrame; Identifier& ident = stackFrame.args[1].identifier(); + CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); + MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS); + StructureStubInfo& stubInfo = codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue baseValue = stackFrame.args[0].jsValue(); PropertySlot slot(baseValue); JSValue result = baseValue.get(callFrame, ident, slot); CHECK_FOR_EXCEPTION(); - - CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); - MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS); - StructureStubInfo& stubInfo = codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + + if (accessType != static_cast<AccessType>(stubInfo.accessType)) + return JSValue::encode(result); if (!methodCallLinkInfo.seenOnce()) { methodCallLinkInfo.setSeen(); @@ -1595,14 +1607,18 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_update) CallFrame* callFrame = stackFrame.callFrame; Identifier& ident = stackFrame.args[1].identifier(); + CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); + MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS); + StructureStubInfo& stubInfo = codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + AccessType accessType = static_cast<AccessType>(stubInfo.accessType); + JSValue baseValue = stackFrame.args[0].jsValue(); PropertySlot slot(baseValue); JSValue result = baseValue.get(callFrame, ident, slot); CHECK_FOR_EXCEPTION(); - - CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); - MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS); - StructureStubInfo& stubInfo = codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + + if (accessType != static_cast<AccessType>(stubInfo.accessType)) + return JSValue::encode(result); ASSERT(methodCallLinkInfo.seenOnce()); @@ -1684,12 +1700,17 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id) CallFrame* callFrame = stackFrame.callFrame; Identifier& ident = stackFrame.args[1].identifier(); + CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); + StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + AccessType accessType = static_cast<AccessType>(stubInfo->accessType); + JSValue baseValue = stackFrame.args[0].jsValue(); PropertySlot slot(baseValue); JSValue result = baseValue.get(callFrame, ident, slot); + + if (accessType != static_cast<AccessType>(stubInfo->accessType)) + return JSValue::encode(result); - CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); - StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); if (!stubInfo->seenOnce()) stubInfo->setSeen(); else @@ -1706,9 +1727,16 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail) CallFrame* callFrame = stackFrame.callFrame; Identifier& ident = stackFrame.args[1].identifier(); + CodeBlock* codeBlock = callFrame->codeBlock(); + StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + AccessType accessType = static_cast<AccessType>(stubInfo->accessType); + JSValue baseValue = stackFrame.args[0].jsValue(); PropertySlot slot(baseValue); JSValue result = baseValue.get(callFrame, ident, slot); + + if (accessType != static_cast<AccessType>(stubInfo->accessType)) + return JSValue::encode(result); CHECK_FOR_EXCEPTION(); @@ -1717,9 +1745,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail) && !baseValue.asCell()->structure()->isUncacheableDictionary() && slot.slotBase() == baseValue) { - CodeBlock* codeBlock = callFrame->codeBlock(); - StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); - ASSERT(slot.slotBase().isObject()); PolymorphicAccessStructureList* polymorphicStructureList; @@ -1813,20 +1838,26 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) CallFrame* callFrame = stackFrame.callFrame; const Identifier& propertyName = stackFrame.args[1].identifier(); + CodeBlock* codeBlock = callFrame->codeBlock(); + StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); + AccessType accessType = static_cast<AccessType>(stubInfo->accessType); + JSValue baseValue = stackFrame.args[0].jsValue(); PropertySlot slot(baseValue); JSValue result = baseValue.get(callFrame, propertyName, slot); CHECK_FOR_EXCEPTION(); - if (!baseValue.isCell() || !slot.isCacheable() || baseValue.asCell()->structure()->isDictionary() || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) { + if (accessType != static_cast<AccessType>(stubInfo->accessType) + || !baseValue.isCell() + || !slot.isCacheable() + || baseValue.asCell()->structure()->isDictionary() + || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) { ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); return JSValue::encode(result); } Structure* structure = baseValue.asCell()->structure(); - CodeBlock* codeBlock = callFrame->codeBlock(); - StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); ASSERT(slot.slotBase().isObject()); JSObject* slotBaseObject = asObject(slot.slotBase()); @@ -3403,8 +3434,9 @@ DEFINE_STUB_FUNCTION(void, op_debug) int debugHookID = stackFrame.args[0].int32(); int firstLine = stackFrame.args[1].int32(); int lastLine = stackFrame.args[2].int32(); + int column = stackFrame.args[3].int32(); - stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); + stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column); } DEFINE_STUB_FUNCTION(void*, vm_throw) diff --git a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h index e17b45d94..0fe606476 100644 --- a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h +++ b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h @@ -55,10 +55,10 @@ namespace JSC { m_failures.append(emitLoadJSCell(src, dst)); } - void loadJSStringArgument(int argument, RegisterID dst) + void loadJSStringArgument(JSGlobalData& globalData, int argument, RegisterID dst) { loadCellArgument(argument, dst); - m_failures.append(branchPtr(NotEqual, Address(dst, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info))); + m_failures.append(branchPtr(NotEqual, Address(dst, JSCell::structureOffset()), TrustedImmPtr(globalData.stringStructure.get()))); } void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget) diff --git a/Source/JavaScriptCore/jit/ThunkGenerators.cpp b/Source/JavaScriptCore/jit/ThunkGenerators.cpp index c6431c22d..cbfc1eb0f 100644 --- a/Source/JavaScriptCore/jit/ThunkGenerators.cpp +++ b/Source/JavaScriptCore/jit/ThunkGenerators.cpp @@ -35,10 +35,10 @@ namespace JSC { -static void stringCharLoad(SpecializedThunkJIT& jit) +static void stringCharLoad(SpecializedThunkJIT& jit, JSGlobalData* globalData) { // load string - jit.loadJSStringArgument(SpecializedThunkJIT::ThisArgument, SpecializedThunkJIT::regT0); + jit.loadJSStringArgument(*globalData, SpecializedThunkJIT::ThisArgument, SpecializedThunkJIT::regT0); // Load string length to regT2, and start the process of loading the data pointer into regT0 jit.load32(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::jsStringLengthOffset()), SpecializedThunkJIT::regT2); @@ -76,7 +76,7 @@ static void charToString(SpecializedThunkJIT& jit, JSGlobalData* globalData, Mac MacroAssemblerCodeRef charCodeAtThunkGenerator(JSGlobalData* globalData) { SpecializedThunkJIT jit(1); - stringCharLoad(jit); + stringCharLoad(jit, globalData); jit.returnInt32(SpecializedThunkJIT::regT0); return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "charCodeAt"); } @@ -84,7 +84,7 @@ MacroAssemblerCodeRef charCodeAtThunkGenerator(JSGlobalData* globalData) MacroAssemblerCodeRef charAtThunkGenerator(JSGlobalData* globalData) { SpecializedThunkJIT jit(1); - stringCharLoad(jit); + stringCharLoad(jit, globalData); charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1); jit.returnJSCell(SpecializedThunkJIT::regT0); return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall(), "charAt"); diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp index d2d743e0a..58bf1bdeb 100644 --- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp +++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp @@ -1601,8 +1601,9 @@ LLINT_SLOW_PATH_DECL(slow_path_debug) int debugHookID = pc[1].u.operand; int firstLine = pc[2].u.operand; int lastLine = pc[3].u.operand; - - globalData.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); + int column = pc[4].u.operand; + + globalData.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column); LLINT_END(); } diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm index 2ae3e0cb2..10a5aaeab 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm @@ -760,7 +760,7 @@ _llint_op_profile_did_call: _llint_op_debug: traceExecution() callSlowPath(_llint_slow_path_debug) - dispatch(4) + dispatch(5) _llint_native_call_trampoline: diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h index d4c170617..0a71f1294 100644 --- a/Source/JavaScriptCore/parser/ASTBuilder.h +++ b/Source/JavaScriptCore/parser/ASTBuilder.h @@ -112,8 +112,8 @@ public: static const int DontBuildKeywords = 0; static const int DontBuildStrings = 0; - ExpressionNode* makeBinaryNode(int lineNumber, int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>); - ExpressionNode* makeFunctionCallNode(int lineNumber, ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end); + ExpressionNode* makeBinaryNode(const JSTokenLocation&, int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>); + ExpressionNode* makeFunctionCallNode(const JSTokenLocation&, ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end); JSC::SourceElements* createSourceElements() { return new (m_globalData) JSC::SourceElements(); } @@ -124,168 +124,168 @@ public: void appendToComma(CommaNode* commaNode, ExpressionNode* expr) { commaNode->append(expr); } - CommaNode* createCommaExpr(int lineNumber, ExpressionNode* lhs, ExpressionNode* rhs) { return new (m_globalData) CommaNode(lineNumber, lhs, rhs); } - - ExpressionNode* makeAssignNode(int lineNumber, ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, int start, int divot, int end); - ExpressionNode* makePrefixNode(int lineNumber, ExpressionNode*, Operator, int start, int divot, int end); - ExpressionNode* makePostfixNode(int lineNumber, ExpressionNode*, Operator, int start, int divot, int end); - ExpressionNode* makeTypeOfNode(int lineNumber, ExpressionNode*); - ExpressionNode* makeDeleteNode(int lineNumber, ExpressionNode*, int start, int divot, int end); - ExpressionNode* makeNegateNode(int lineNumber, ExpressionNode*); - ExpressionNode* makeBitwiseNotNode(int lineNumber, ExpressionNode*); - ExpressionNode* makeMultNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* makeDivNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* makeModNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* makeAddNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* makeSubNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* makeBitXOrNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* makeBitAndNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* makeBitOrNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* makeLeftShiftNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* makeRightShiftNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* makeURightShiftNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - - ExpressionNode* createLogicalNot(int lineNumber, ExpressionNode* expr) { return new (m_globalData) LogicalNotNode(lineNumber, expr); } - ExpressionNode* createUnaryPlus(int lineNumber, ExpressionNode* expr) { return new (m_globalData) UnaryPlusNode(lineNumber, expr); } - ExpressionNode* createVoid(int lineNumber, ExpressionNode* expr) + CommaNode* createCommaExpr(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* rhs) { return new (m_globalData) CommaNode(location, lhs, rhs); } + + ExpressionNode* makeAssignNode(const JSTokenLocation&, ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, int start, int divot, int end); + ExpressionNode* makePrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, int start, int divot, int end); + ExpressionNode* makePostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, int start, int divot, int end); + ExpressionNode* makeTypeOfNode(const JSTokenLocation&, ExpressionNode*); + ExpressionNode* makeDeleteNode(const JSTokenLocation&, ExpressionNode*, int start, int divot, int end); + ExpressionNode* makeNegateNode(const JSTokenLocation&, ExpressionNode*); + ExpressionNode* makeBitwiseNotNode(const JSTokenLocation&, ExpressionNode*); + ExpressionNode* makeMultNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + ExpressionNode* makeDivNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + ExpressionNode* makeModNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + ExpressionNode* makeAddNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + ExpressionNode* makeSubNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + ExpressionNode* makeBitXOrNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + ExpressionNode* makeBitAndNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + ExpressionNode* makeBitOrNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + ExpressionNode* makeLeftShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + ExpressionNode* makeRightShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + ExpressionNode* makeURightShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); + + ExpressionNode* createLogicalNot(const JSTokenLocation& location, ExpressionNode* expr) { return new (m_globalData) LogicalNotNode(location, expr); } + ExpressionNode* createUnaryPlus(const JSTokenLocation& location, ExpressionNode* expr) { return new (m_globalData) UnaryPlusNode(location, expr); } + ExpressionNode* createVoid(const JSTokenLocation& location, ExpressionNode* expr) { incConstants(); - return new (m_globalData) VoidNode(lineNumber, expr); + return new (m_globalData) VoidNode(location, expr); } - ExpressionNode* thisExpr(int lineNumber) + ExpressionNode* thisExpr(const JSTokenLocation& location) { usesThis(); - return new (m_globalData) ThisNode(lineNumber); + return new (m_globalData) ThisNode(location); } - ExpressionNode* createResolve(int lineNumber, const Identifier* ident, int start) + ExpressionNode* createResolve(const JSTokenLocation& location, const Identifier* ident, int start) { if (m_globalData->propertyNames->arguments == *ident) usesArguments(); - return new (m_globalData) ResolveNode(lineNumber, *ident, start); + return new (m_globalData) ResolveNode(location, *ident, start); } - ExpressionNode* createObjectLiteral(int lineNumber) { return new (m_globalData) ObjectLiteralNode(lineNumber); } - ExpressionNode* createObjectLiteral(int lineNumber, PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(lineNumber, properties); } + ExpressionNode* createObjectLiteral(const JSTokenLocation& location) { return new (m_globalData) ObjectLiteralNode(location); } + ExpressionNode* createObjectLiteral(const JSTokenLocation& location, PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(location, properties); } - ExpressionNode* createArray(int lineNumber, int elisions) + ExpressionNode* createArray(const JSTokenLocation& location, int elisions) { if (elisions) incConstants(); - return new (m_globalData) ArrayNode(lineNumber, elisions); + return new (m_globalData) ArrayNode(location, elisions); } - ExpressionNode* createArray(int lineNumber, ElementNode* elems) { return new (m_globalData) ArrayNode(lineNumber, elems); } - ExpressionNode* createArray(int lineNumber, int elisions, ElementNode* elems) + ExpressionNode* createArray(const JSTokenLocation& location, ElementNode* elems) { return new (m_globalData) ArrayNode(location, elems); } + ExpressionNode* createArray(const JSTokenLocation& location, int elisions, ElementNode* elems) { if (elisions) incConstants(); - return new (m_globalData) ArrayNode(lineNumber, elisions, elems); + return new (m_globalData) ArrayNode(location, elisions, elems); } - ExpressionNode* createNumberExpr(int lineNumber, double d) + ExpressionNode* createNumberExpr(const JSTokenLocation& location, double d) { incConstants(); - return new (m_globalData) NumberNode(lineNumber, d); + return new (m_globalData) NumberNode(location, d); } - ExpressionNode* createString(int lineNumber, const Identifier* string) + ExpressionNode* createString(const JSTokenLocation& location, const Identifier* string) { incConstants(); - return new (m_globalData) StringNode(lineNumber, *string); + return new (m_globalData) StringNode(location, *string); } - ExpressionNode* createBoolean(int lineNumber, bool b) + ExpressionNode* createBoolean(const JSTokenLocation& location, bool b) { incConstants(); - return new (m_globalData) BooleanNode(lineNumber, b); + return new (m_globalData) BooleanNode(location, b); } - ExpressionNode* createNull(int lineNumber) + ExpressionNode* createNull(const JSTokenLocation& location) { incConstants(); - return new (m_globalData) NullNode(lineNumber); + return new (m_globalData) NullNode(location); } - ExpressionNode* createBracketAccess(int lineNumber, ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, int start, int divot, int end) + ExpressionNode* createBracketAccess(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, int start, int divot, int end) { - BracketAccessorNode* node = new (m_globalData) BracketAccessorNode(lineNumber, base, property, propertyHasAssignments); + BracketAccessorNode* node = new (m_globalData) BracketAccessorNode(location, base, property, propertyHasAssignments); setExceptionLocation(node, start, divot, end); return node; } - ExpressionNode* createDotAccess(int lineNumber, ExpressionNode* base, const Identifier* property, int start, int divot, int end) + ExpressionNode* createDotAccess(const JSTokenLocation& location, ExpressionNode* base, const Identifier* property, int start, int divot, int end) { - DotAccessorNode* node = new (m_globalData) DotAccessorNode(lineNumber, base, *property); + DotAccessorNode* node = new (m_globalData) DotAccessorNode(location, base, *property); setExceptionLocation(node, start, divot, end); return node; } - ExpressionNode* createRegExp(int lineNumber, const Identifier& pattern, const Identifier& flags, int start) + ExpressionNode* createRegExp(const JSTokenLocation& location, const Identifier& pattern, const Identifier& flags, int start) { if (Yarr::checkSyntax(pattern.ustring())) return 0; - RegExpNode* node = new (m_globalData) RegExpNode(lineNumber, pattern, flags); + RegExpNode* node = new (m_globalData) RegExpNode(location, pattern, flags); int size = pattern.length() + 2; // + 2 for the two /'s setExceptionLocation(node, start, start + size, start + size); return node; } - ExpressionNode* createNewExpr(int lineNumber, ExpressionNode* expr, ArgumentsNode* arguments, int start, int divot, int end) + ExpressionNode* createNewExpr(const JSTokenLocation& location, ExpressionNode* expr, ArgumentsNode* arguments, int start, int divot, int end) { - NewExprNode* node = new (m_globalData) NewExprNode(lineNumber, expr, arguments); + NewExprNode* node = new (m_globalData) NewExprNode(location, expr, arguments); setExceptionLocation(node, start, divot, end); return node; } - ExpressionNode* createNewExpr(int lineNumber, ExpressionNode* expr, int start, int end) + ExpressionNode* createNewExpr(const JSTokenLocation& location, ExpressionNode* expr, int start, int end) { - NewExprNode* node = new (m_globalData) NewExprNode(lineNumber, expr); + NewExprNode* node = new (m_globalData) NewExprNode(location, expr); setExceptionLocation(node, start, end, end); return node; } - ExpressionNode* createConditionalExpr(int lineNumber, ExpressionNode* condition, ExpressionNode* lhs, ExpressionNode* rhs) + ExpressionNode* createConditionalExpr(const JSTokenLocation& location, ExpressionNode* condition, ExpressionNode* lhs, ExpressionNode* rhs) { - return new (m_globalData) ConditionalNode(lineNumber, condition, lhs, rhs); + return new (m_globalData) ConditionalNode(location, condition, lhs, rhs); } - ExpressionNode* createAssignResolve(int lineNumber, const Identifier& ident, ExpressionNode* rhs, int start, int divot, int end) + ExpressionNode* createAssignResolve(const JSTokenLocation& location, const Identifier& ident, ExpressionNode* rhs, int start, int divot, int end) { if (rhs->isFuncExprNode()) static_cast<FuncExprNode*>(rhs)->body()->setInferredName(ident); - AssignResolveNode* node = new (m_globalData) AssignResolveNode(lineNumber, ident, rhs); + AssignResolveNode* node = new (m_globalData) AssignResolveNode(location, ident, rhs); setExceptionLocation(node, start, divot, end); return node; } - ExpressionNode* createFunctionExpr(int lineNumber, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) + ExpressionNode* createFunctionExpr(const JSTokenLocation& location, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) { - FuncExprNode* result = new (m_globalData) FuncExprNode(lineNumber, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters); - body->setLoc(bodyStartLine, bodyEndLine); + FuncExprNode* result = new (m_globalData) FuncExprNode(location, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters); + body->setLoc(bodyStartLine, bodyEndLine, location.column); return result; } - FunctionBodyNode* createFunctionBody(int lineNumber, bool inStrictContext) + FunctionBodyNode* createFunctionBody(const JSTokenLocation& location, bool inStrictContext) { - return FunctionBodyNode::create(m_globalData, lineNumber, inStrictContext); + return FunctionBodyNode::create(m_globalData, location, inStrictContext); } - template <bool> PropertyNode* createGetterOrSetterProperty(int lineNumber, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) + template <bool> PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) { ASSERT(name); - body->setLoc(bodyStartLine, bodyEndLine); + body->setLoc(bodyStartLine, bodyEndLine, location.column); body->setInferredName(*name); - return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(lineNumber, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type); + return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(location, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type); } - template <bool> PropertyNode* createGetterOrSetterProperty(JSGlobalData*, int lineNumber, PropertyNode::Type type, double name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) + template <bool> PropertyNode* createGetterOrSetterProperty(JSGlobalData*, const JSTokenLocation& location, PropertyNode::Type type, double name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) { - body->setLoc(bodyStartLine, bodyEndLine); - return new (m_globalData) PropertyNode(m_globalData, name, new (m_globalData) FuncExprNode(lineNumber, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type); + body->setLoc(bodyStartLine, bodyEndLine, location.column); + return new (m_globalData) PropertyNode(m_globalData, name, new (m_globalData) FuncExprNode(location, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type); } ArgumentsNode* createArguments() { return new (m_globalData) ArgumentsNode(); } ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_globalData) ArgumentsNode(args); } - ArgumentListNode* createArgumentsList(int lineNumber, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(lineNumber, arg); } - ArgumentListNode* createArgumentsList(int lineNumber, ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(lineNumber, args, arg); } + ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(location, arg); } + ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(location, args, arg); } template <bool> PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { @@ -294,8 +294,8 @@ public: return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); } template <bool> PropertyNode* createProperty(JSGlobalData*, double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); } - PropertyListNode* createPropertyList(int lineNumber, PropertyNode* property) { return new (m_globalData) PropertyListNode(lineNumber, property); } - PropertyListNode* createPropertyList(int lineNumber, PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(lineNumber, property, tail); } + PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property) { return new (m_globalData) PropertyListNode(location, property); } + PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(location, property, tail); } ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(elisions, expr); } ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(elems, elisions, expr); } @@ -309,191 +309,191 @@ public: void setUsesArguments(FunctionBodyNode* node) { node->setUsesArguments(); } - StatementNode* createFuncDeclStatement(int lineNumber, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) + StatementNode* createFuncDeclStatement(const JSTokenLocation& location, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) { - FuncDeclNode* decl = new (m_globalData) FuncDeclNode(lineNumber, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters); + FuncDeclNode* decl = new (m_globalData) FuncDeclNode(location, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters); if (*name == m_globalData->propertyNames->arguments) usesArguments(); m_scope.m_funcDeclarations->data.append(decl->body()); - body->setLoc(bodyStartLine, bodyEndLine); + body->setLoc(bodyStartLine, bodyEndLine, location.column); return decl; } - StatementNode* createBlockStatement(int lineNumber, JSC::SourceElements* elements, int startLine, int endLine) + StatementNode* createBlockStatement(const JSTokenLocation& location, JSC::SourceElements* elements, int startLine, int endLine) { - BlockNode* block = new (m_globalData) BlockNode(lineNumber, elements); - block->setLoc(startLine, endLine); + BlockNode* block = new (m_globalData) BlockNode(location, elements); + block->setLoc(startLine, endLine, location.column); return block; } - StatementNode* createExprStatement(int lineNumber, ExpressionNode* expr, int start, int end) + StatementNode* createExprStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end) { - ExprStatementNode* result = new (m_globalData) ExprStatementNode(lineNumber, expr); - result->setLoc(start, end); + ExprStatementNode* result = new (m_globalData) ExprStatementNode(location, expr); + result->setLoc(start, end, location.column); return result; } - StatementNode* createIfStatement(int lineNumber, ExpressionNode* condition, StatementNode* trueBlock, int start, int end) + StatementNode* createIfStatement(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* trueBlock, int start, int end) { - IfNode* result = new (m_globalData) IfNode(lineNumber, condition, trueBlock); - result->setLoc(start, end); + IfNode* result = new (m_globalData) IfNode(location, condition, trueBlock); + result->setLoc(start, end, location.column); return result; } - StatementNode* createIfStatement(int lineNumber, ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end) + StatementNode* createIfStatement(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end) { - IfNode* result = new (m_globalData) IfElseNode(lineNumber, condition, trueBlock, falseBlock); - result->setLoc(start, end); + IfNode* result = new (m_globalData) IfElseNode(location, condition, trueBlock, falseBlock); + result->setLoc(start, end, location.column); return result; } - StatementNode* createForLoop(int lineNumber, ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, int start, int end) + StatementNode* createForLoop(const JSTokenLocation& location, ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, int start, int end) { - ForNode* result = new (m_globalData) ForNode(lineNumber, initializer, condition, iter, statements); + ForNode* result = new (m_globalData) ForNode(location, initializer, condition, iter, statements); result->setLoc(start, end); return result; } - StatementNode* createForInLoop(int lineNumber, const Identifier* ident, ExpressionNode* initializer, ExpressionNode* iter, StatementNode* statements, int start, int divot, int end, int initStart, int initEnd, int startLine, int endLine) + StatementNode* createForInLoop(const JSTokenLocation& location, const Identifier* ident, ExpressionNode* initializer, ExpressionNode* iter, StatementNode* statements, int start, int divot, int end, int initStart, int initEnd, int startLine, int endLine) { - ForInNode* result = new (m_globalData) ForInNode(m_globalData, lineNumber, *ident, initializer, iter, statements, initStart, initStart - start, initEnd - initStart); - result->setLoc(startLine, endLine); + ForInNode* result = new (m_globalData) ForInNode(m_globalData, location, *ident, initializer, iter, statements, initStart, initStart - start, initEnd - initStart); + result->setLoc(startLine, endLine, location.column); setExceptionLocation(result, start, divot + 1, end); return result; } - StatementNode* createForInLoop(int lineNumber, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, int eStart, int eDivot, int eEnd, int start, int end) + StatementNode* createForInLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, int eStart, int eDivot, int eEnd, int start, int end) { - ForInNode* result = new (m_globalData) ForInNode(lineNumber, lhs, iter, statements); - result->setLoc(start, end); + ForInNode* result = new (m_globalData) ForInNode(location, lhs, iter, statements); + result->setLoc(start, end, location.column); setExceptionLocation(result, eStart, eDivot, eEnd); return result; } - StatementNode* createEmptyStatement(int lineNumber) { return new (m_globalData) EmptyStatementNode(lineNumber); } + StatementNode* createEmptyStatement(const JSTokenLocation& location) { return new (m_globalData) EmptyStatementNode(location); } - StatementNode* createVarStatement(int lineNumber, ExpressionNode* expr, int start, int end) + StatementNode* createVarStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end) { StatementNode* result; if (!expr) - result = new (m_globalData) EmptyStatementNode(lineNumber); + result = new (m_globalData) EmptyStatementNode(location); else - result = new (m_globalData) VarStatementNode(lineNumber, expr); - result->setLoc(start, end); + result = new (m_globalData) VarStatementNode(location, expr); + result->setLoc(start, end, location.column); return result; } - StatementNode* createReturnStatement(int lineNumber, ExpressionNode* expression, int eStart, int eEnd, int startLine, int endLine) + StatementNode* createReturnStatement(const JSTokenLocation& location, ExpressionNode* expression, int eStart, int eEnd, int startLine, int endLine) { - ReturnNode* result = new (m_globalData) ReturnNode(lineNumber, expression); + ReturnNode* result = new (m_globalData) ReturnNode(location, expression); setExceptionLocation(result, eStart, eEnd, eEnd); - result->setLoc(startLine, endLine); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createBreakStatement(int lineNumber, int eStart, int eEnd, int startLine, int endLine) + StatementNode* createBreakStatement(const JSTokenLocation& location, int eStart, int eEnd, int startLine, int endLine) { - BreakNode* result = new (m_globalData) BreakNode(m_globalData, lineNumber); + BreakNode* result = new (m_globalData) BreakNode(m_globalData, location); setExceptionLocation(result, eStart, eEnd, eEnd); - result->setLoc(startLine, endLine); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createBreakStatement(int lineNumber, const Identifier* ident, int eStart, int eEnd, int startLine, int endLine) + StatementNode* createBreakStatement(const JSTokenLocation& location, const Identifier* ident, int eStart, int eEnd, int startLine, int endLine) { - BreakNode* result = new (m_globalData) BreakNode(lineNumber, *ident); + BreakNode* result = new (m_globalData) BreakNode(location, *ident); setExceptionLocation(result, eStart, eEnd, eEnd); - result->setLoc(startLine, endLine); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createContinueStatement(int lineNumber, int eStart, int eEnd, int startLine, int endLine) + StatementNode* createContinueStatement(const JSTokenLocation& location, int eStart, int eEnd, int startLine, int endLine) { - ContinueNode* result = new (m_globalData) ContinueNode(m_globalData, lineNumber); + ContinueNode* result = new (m_globalData) ContinueNode(m_globalData, location); setExceptionLocation(result, eStart, eEnd, eEnd); - result->setLoc(startLine, endLine); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createContinueStatement(int lineNumber, const Identifier* ident, int eStart, int eEnd, int startLine, int endLine) + StatementNode* createContinueStatement(const JSTokenLocation& location, const Identifier* ident, int eStart, int eEnd, int startLine, int endLine) { - ContinueNode* result = new (m_globalData) ContinueNode(lineNumber, *ident); + ContinueNode* result = new (m_globalData) ContinueNode(location, *ident); setExceptionLocation(result, eStart, eEnd, eEnd); - result->setLoc(startLine, endLine); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createTryStatement(int lineNumber, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine) + StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine) { - TryNode* result = new (m_globalData) TryNode(lineNumber, tryBlock, *ident, catchBlock, finallyBlock); + TryNode* result = new (m_globalData) TryNode(location, tryBlock, *ident, catchBlock, finallyBlock); if (catchBlock) usesCatch(); - result->setLoc(startLine, endLine); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createSwitchStatement(int lineNumber, ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine) + StatementNode* createSwitchStatement(const JSTokenLocation& location, ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine) { CaseBlockNode* cases = new (m_globalData) CaseBlockNode(firstClauses, defaultClause, secondClauses); - SwitchNode* result = new (m_globalData) SwitchNode(lineNumber, expr, cases); - result->setLoc(startLine, endLine); + SwitchNode* result = new (m_globalData) SwitchNode(location, expr, cases); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createWhileStatement(int lineNumber, ExpressionNode* expr, StatementNode* statement, int startLine, int endLine) + StatementNode* createWhileStatement(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, int startLine, int endLine) { - WhileNode* result = new (m_globalData) WhileNode(lineNumber, expr, statement); - result->setLoc(startLine, endLine); + WhileNode* result = new (m_globalData) WhileNode(location, expr, statement); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createDoWhileStatement(int lineNumber, StatementNode* statement, ExpressionNode* expr, int startLine, int endLine) + StatementNode* createDoWhileStatement(const JSTokenLocation& location, StatementNode* statement, ExpressionNode* expr, int startLine, int endLine) { - DoWhileNode* result = new (m_globalData) DoWhileNode(lineNumber, statement, expr); - result->setLoc(startLine, endLine); + DoWhileNode* result = new (m_globalData) DoWhileNode(location, statement, expr); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createLabelStatement(int lineNumber, const Identifier* ident, StatementNode* statement, int start, int end) + StatementNode* createLabelStatement(const JSTokenLocation& location, const Identifier* ident, StatementNode* statement, int start, int end) { - LabelNode* result = new (m_globalData) LabelNode(lineNumber, *ident, statement); + LabelNode* result = new (m_globalData) LabelNode(location, *ident, statement); setExceptionLocation(result, start, end, end); return result; } - StatementNode* createWithStatement(int lineNumber, ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine) + StatementNode* createWithStatement(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine) { usesWith(); - WithNode* result = new (m_globalData) WithNode(lineNumber, expr, statement, end, end - start); - result->setLoc(startLine, endLine); + WithNode* result = new (m_globalData) WithNode(location, expr, statement, end, end - start); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createThrowStatement(int lineNumber, ExpressionNode* expr, int start, int end, int startLine, int endLine) + StatementNode* createThrowStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end, int startLine, int endLine) { - ThrowNode* result = new (m_globalData) ThrowNode(lineNumber, expr); - result->setLoc(startLine, endLine); + ThrowNode* result = new (m_globalData) ThrowNode(location, expr); + result->setLoc(startLine, endLine, location.column); setExceptionLocation(result, start, end, end); return result; } - StatementNode* createDebugger(int lineNumber, int startLine, int endLine) + StatementNode* createDebugger(const JSTokenLocation& location, int startLine, int endLine) { - DebuggerStatementNode* result = new (m_globalData) DebuggerStatementNode(lineNumber); - result->setLoc(startLine, endLine); + DebuggerStatementNode* result = new (m_globalData) DebuggerStatementNode(location); + result->setLoc(startLine, endLine, location.column); return result; } - StatementNode* createConstStatement(int lineNumber, ConstDeclNode* decls, int startLine, int endLine) + StatementNode* createConstStatement(const JSTokenLocation& location, ConstDeclNode* decls, int startLine, int endLine) { - ConstStatementNode* result = new (m_globalData) ConstStatementNode(lineNumber, decls); - result->setLoc(startLine, endLine); + ConstStatementNode* result = new (m_globalData) ConstStatementNode(location, decls); + result->setLoc(startLine, endLine, location.column); return result; } - ConstDeclNode* appendConstDecl(int lineNumber, ConstDeclNode* tail, const Identifier* name, ExpressionNode* initializer) + ConstDeclNode* appendConstDecl(const JSTokenLocation& location, ConstDeclNode* tail, const Identifier* name, ExpressionNode* initializer) { - ConstDeclNode* result = new (m_globalData) ConstDeclNode(lineNumber, *name, initializer); + ConstDeclNode* result = new (m_globalData) ConstDeclNode(location, *name, initializer); if (tail) tail->m_next = result; return result; @@ -511,7 +511,7 @@ public: m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs)); } - ExpressionNode* combineCommaNodes(int lineNumber, ExpressionNode* list, ExpressionNode* init) + ExpressionNode* combineCommaNodes(const JSTokenLocation& location, ExpressionNode* list, ExpressionNode* init) { if (!list) return init; @@ -519,7 +519,7 @@ public: static_cast<CommaNode*>(list)->append(init); return list; } - return new (m_globalData) CommaNode(lineNumber, list, init); + return new (m_globalData) CommaNode(location, list, init); } int evalCount() const { return m_evalCount; } @@ -547,10 +547,10 @@ public: ASSERT(operandStackDepth >= 0); m_binaryOperandStack.resize(m_binaryOperandStack.size() - amount); } - void appendBinaryOperation(int lineNumber, int& operandStackDepth, int&, const BinaryOperand& lhs, const BinaryOperand& rhs) + void appendBinaryOperation(const JSTokenLocation& location, int& operandStackDepth, int&, const BinaryOperand& lhs, const BinaryOperand& rhs) { operandStackDepth++; - m_binaryOperandStack.append(std::make_pair(makeBinaryNode(lineNumber, m_binaryOperatorStack.last().first, lhs, rhs), BinaryOpInfo(lhs.second, rhs.second))); + m_binaryOperandStack.append(std::make_pair(makeBinaryNode(location, m_binaryOperatorStack.last().first, lhs, rhs), BinaryOpInfo(lhs.second, rhs.second))); } void operatorStackAppend(int& operatorStackDepth, int op, int precedence) { @@ -592,9 +592,9 @@ public: m_assignmentInfoStack.append(AssignmentInfo(node, start, divot, assignmentCount, op)); } - ExpressionNode* createAssignment(int lineNumber, int& assignmentStackDepth, ExpressionNode* rhs, int initialAssignmentCount, int currentAssignmentCount, int lastTokenEnd) + ExpressionNode* createAssignment(const JSTokenLocation& location, int& assignmentStackDepth, ExpressionNode* rhs, int initialAssignmentCount, int currentAssignmentCount, int lastTokenEnd) { - ExpressionNode* result = makeAssignNode(lineNumber, m_assignmentInfoStack.last().m_node, m_assignmentInfoStack.last().m_op, rhs, m_assignmentInfoStack.last().m_initAssignments != initialAssignmentCount, m_assignmentInfoStack.last().m_initAssignments != currentAssignmentCount, m_assignmentInfoStack.last().m_start, m_assignmentInfoStack.last().m_divot + 1, lastTokenEnd); + ExpressionNode* result = makeAssignNode(location, m_assignmentInfoStack.last().m_node, m_assignmentInfoStack.last().m_op, rhs, m_assignmentInfoStack.last().m_initAssignments != initialAssignmentCount, m_assignmentInfoStack.last().m_initAssignments != currentAssignmentCount, m_assignmentInfoStack.last().m_start, m_assignmentInfoStack.last().m_divot + 1, lastTokenEnd); m_assignmentInfoStack.removeLast(); assignmentStackDepth--; return result; @@ -635,9 +635,9 @@ private: m_evalCount++; m_scope.m_features |= EvalFeature; } - ExpressionNode* createNumber(int lineNumber, double d) + ExpressionNode* createNumber(const JSTokenLocation& location, double d) { - return new (m_globalData) NumberNode(lineNumber, d); + return new (m_globalData) NumberNode(location, d); } JSGlobalData* m_globalData; @@ -650,33 +650,33 @@ private: int m_evalCount; }; -ExpressionNode* ASTBuilder::makeTypeOfNode(int lineNumber, ExpressionNode* expr) +ExpressionNode* ASTBuilder::makeTypeOfNode(const JSTokenLocation& location, ExpressionNode* expr) { if (expr->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(expr); - return new (m_globalData) TypeOfResolveNode(lineNumber, resolve->identifier()); + return new (m_globalData) TypeOfResolveNode(location, resolve->identifier()); } - return new (m_globalData) TypeOfValueNode(lineNumber, expr); + return new (m_globalData) TypeOfValueNode(location, expr); } -ExpressionNode* ASTBuilder::makeDeleteNode(int lineNumber, ExpressionNode* expr, int start, int divot, int end) +ExpressionNode* ASTBuilder::makeDeleteNode(const JSTokenLocation& location, ExpressionNode* expr, int start, int divot, int end) { if (!expr->isLocation()) - return new (m_globalData) DeleteValueNode(lineNumber, expr); + return new (m_globalData) DeleteValueNode(location, expr); if (expr->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(expr); - return new (m_globalData) DeleteResolveNode(lineNumber, resolve->identifier(), divot, divot - start, end - divot); + return new (m_globalData) DeleteResolveNode(location, resolve->identifier(), divot, divot - start, end - divot); } if (expr->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); - return new (m_globalData) DeleteBracketNode(lineNumber, bracket->base(), bracket->subscript(), divot, divot - start, end - divot); + return new (m_globalData) DeleteBracketNode(location, bracket->base(), bracket->subscript(), divot, divot - start, end - divot); } ASSERT(expr->isDotAccessorNode()); DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); - return new (m_globalData) DeleteDotNode(lineNumber, dot->base(), dot->identifier(), divot, divot - start, end - divot); + return new (m_globalData) DeleteDotNode(location, dot->base(), dot->identifier(), divot, divot - start, end - divot); } -ExpressionNode* ASTBuilder::makeNegateNode(int lineNumber, ExpressionNode* n) +ExpressionNode* ASTBuilder::makeNegateNode(const JSTokenLocation& location, ExpressionNode* n) { if (n->isNumber()) { NumberNode* numberNode = static_cast<NumberNode*>(n); @@ -684,128 +684,128 @@ ExpressionNode* ASTBuilder::makeNegateNode(int lineNumber, ExpressionNode* n) return numberNode; } - return new (m_globalData) NegateNode(lineNumber, n); + return new (m_globalData) NegateNode(location, n); } -ExpressionNode* ASTBuilder::makeBitwiseNotNode(int lineNumber, ExpressionNode* expr) +ExpressionNode* ASTBuilder::makeBitwiseNotNode(const JSTokenLocation& location, ExpressionNode* expr) { if (expr->isNumber()) - return createNumber(lineNumber, ~toInt32(static_cast<NumberNode*>(expr)->value())); - return new (m_globalData) BitwiseNotNode(lineNumber, expr); + return createNumber(location, ~toInt32(static_cast<NumberNode*>(expr)->value())); + return new (m_globalData) BitwiseNotNode(location, expr); } -ExpressionNode* ASTBuilder::makeMultNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeMultNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { expr1 = expr1->stripUnaryPlus(); expr2 = expr2->stripUnaryPlus(); if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value()); + return createNumber(location, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value()); if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1) - return new (m_globalData) UnaryPlusNode(lineNumber, expr2); + return new (m_globalData) UnaryPlusNode(location, expr2); if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1) - return new (m_globalData) UnaryPlusNode(lineNumber, expr1); + return new (m_globalData) UnaryPlusNode(location, expr1); - return new (m_globalData) MultNode(lineNumber, expr1, expr2, rightHasAssignments); + return new (m_globalData) MultNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeDivNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeDivNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { expr1 = expr1->stripUnaryPlus(); expr2 = expr2->stripUnaryPlus(); if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value()); - return new (m_globalData) DivNode(lineNumber, expr1, expr2, rightHasAssignments); + return createNumber(location, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value()); + return new (m_globalData) DivNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeModNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeModNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { expr1 = expr1->stripUnaryPlus(); expr2 = expr2->stripUnaryPlus(); if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, fmod(static_cast<NumberNode*>(expr1)->value(), static_cast<NumberNode*>(expr2)->value())); - return new (m_globalData) ModNode(lineNumber, expr1, expr2, rightHasAssignments); + return createNumber(location, fmod(static_cast<NumberNode*>(expr1)->value(), static_cast<NumberNode*>(expr2)->value())); + return new (m_globalData) ModNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeAddNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeAddNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value()); - return new (m_globalData) AddNode(lineNumber, expr1, expr2, rightHasAssignments); + return createNumber(location, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value()); + return new (m_globalData) AddNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeSubNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeSubNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { expr1 = expr1->stripUnaryPlus(); expr2 = expr2->stripUnaryPlus(); if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value()); - return new (m_globalData) SubNode(lineNumber, expr1, expr2, rightHasAssignments); + return createNumber(location, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value()); + return new (m_globalData) SubNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeLeftShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeLeftShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); - return new (m_globalData) LeftShiftNode(lineNumber, expr1, expr2, rightHasAssignments); + return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); + return new (m_globalData) LeftShiftNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeRightShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeRightShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); - return new (m_globalData) RightShiftNode(lineNumber, expr1, expr2, rightHasAssignments); + return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); + return new (m_globalData) RightShiftNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeURightShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeURightShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, toUInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); - return new (m_globalData) UnsignedRightShiftNode(lineNumber, expr1, expr2, rightHasAssignments); + return createNumber(location, toUInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); + return new (m_globalData) UnsignedRightShiftNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeBitOrNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeBitOrNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, toInt32(static_cast<NumberNode*>(expr1)->value()) | toInt32(static_cast<NumberNode*>(expr2)->value())); - return new (m_globalData) BitOrNode(lineNumber, expr1, expr2, rightHasAssignments); + return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) | toInt32(static_cast<NumberNode*>(expr2)->value())); + return new (m_globalData) BitOrNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeBitAndNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeBitAndNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, toInt32(static_cast<NumberNode*>(expr1)->value()) & toInt32(static_cast<NumberNode*>(expr2)->value())); - return new (m_globalData) BitAndNode(lineNumber, expr1, expr2, rightHasAssignments); + return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) & toInt32(static_cast<NumberNode*>(expr2)->value())); + return new (m_globalData) BitAndNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeBitXOrNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) +ExpressionNode* ASTBuilder::makeBitXOrNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) - return createNumber(lineNumber, toInt32(static_cast<NumberNode*>(expr1)->value()) ^ toInt32(static_cast<NumberNode*>(expr2)->value())); - return new (m_globalData) BitXOrNode(lineNumber, expr1, expr2, rightHasAssignments); + return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) ^ toInt32(static_cast<NumberNode*>(expr2)->value())); + return new (m_globalData) BitXOrNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeFunctionCallNode(int lineNumber, ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end) +ExpressionNode* ASTBuilder::makeFunctionCallNode(const JSTokenLocation& location, ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end) { if (!func->isLocation()) - return new (m_globalData) FunctionCallValueNode(lineNumber, func, args, divot, divot - start, end - divot); + return new (m_globalData) FunctionCallValueNode(location, func, args, divot, divot - start, end - divot); if (func->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(func); const Identifier& identifier = resolve->identifier(); if (identifier == m_globalData->propertyNames->eval) { usesEval(); - return new (m_globalData) EvalFunctionCallNode(lineNumber, args, divot, divot - start, end - divot); + return new (m_globalData) EvalFunctionCallNode(location, args, divot, divot - start, end - divot); } - return new (m_globalData) FunctionCallResolveNode(lineNumber, identifier, args, divot, divot - start, end - divot); + return new (m_globalData) FunctionCallResolveNode(location, identifier, args, divot, divot - start, end - divot); } if (func->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func); - FunctionCallBracketNode* node = new (m_globalData) FunctionCallBracketNode(lineNumber, bracket->base(), bracket->subscript(), args, divot, divot - start, end - divot); + FunctionCallBracketNode* node = new (m_globalData) FunctionCallBracketNode(location, bracket->base(), bracket->subscript(), args, divot, divot - start, end - divot); node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); return node; } @@ -813,118 +813,118 @@ ExpressionNode* ASTBuilder::makeFunctionCallNode(int lineNumber, ExpressionNode* DotAccessorNode* dot = static_cast<DotAccessorNode*>(func); FunctionCallDotNode* node; if (dot->identifier() == m_globalData->propertyNames->call) - node = new (m_globalData) CallFunctionCallDotNode(lineNumber, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); + node = new (m_globalData) CallFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); else if (dot->identifier() == m_globalData->propertyNames->apply) - node = new (m_globalData) ApplyFunctionCallDotNode(lineNumber, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); + node = new (m_globalData) ApplyFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); else - node = new (m_globalData) FunctionCallDotNode(lineNumber, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); + node = new (m_globalData) FunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); node->setSubexpressionInfo(dot->divot(), dot->endOffset()); return node; } -ExpressionNode* ASTBuilder::makeBinaryNode(int lineNumber, int token, pair<ExpressionNode*, BinaryOpInfo> lhs, pair<ExpressionNode*, BinaryOpInfo> rhs) +ExpressionNode* ASTBuilder::makeBinaryNode(const JSTokenLocation& location, int token, pair<ExpressionNode*, BinaryOpInfo> lhs, pair<ExpressionNode*, BinaryOpInfo> rhs) { switch (token) { case OR: - return new (m_globalData) LogicalOpNode(lineNumber, lhs.first, rhs.first, OpLogicalOr); + return new (m_globalData) LogicalOpNode(location, lhs.first, rhs.first, OpLogicalOr); case AND: - return new (m_globalData) LogicalOpNode(lineNumber, lhs.first, rhs.first, OpLogicalAnd); + return new (m_globalData) LogicalOpNode(location, lhs.first, rhs.first, OpLogicalAnd); case BITOR: - return makeBitOrNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeBitOrNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case BITXOR: - return makeBitXOrNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeBitXOrNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case BITAND: - return makeBitAndNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeBitAndNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case EQEQ: - return new (m_globalData) EqualNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_globalData) EqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case NE: - return new (m_globalData) NotEqualNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_globalData) NotEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case STREQ: - return new (m_globalData) StrictEqualNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_globalData) StrictEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case STRNEQ: - return new (m_globalData) NotStrictEqualNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_globalData) NotStrictEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case LT: - return new (m_globalData) LessNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_globalData) LessNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case GT: - return new (m_globalData) GreaterNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_globalData) GreaterNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case LE: - return new (m_globalData) LessEqNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_globalData) LessEqNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case GE: - return new (m_globalData) GreaterEqNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_globalData) GreaterEqNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case INSTANCEOF: { - InstanceOfNode* node = new (m_globalData) InstanceOfNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + InstanceOfNode* node = new (m_globalData) InstanceOfNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end); return node; } case INTOKEN: { - InNode* node = new (m_globalData) InNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + InNode* node = new (m_globalData) InNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end); return node; } case LSHIFT: - return makeLeftShiftNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeLeftShiftNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case RSHIFT: - return makeRightShiftNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeRightShiftNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case URSHIFT: - return makeURightShiftNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeURightShiftNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case PLUS: - return makeAddNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeAddNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case MINUS: - return makeSubNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeSubNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case TIMES: - return makeMultNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeMultNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case DIVIDE: - return makeDivNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeDivNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case MOD: - return makeModNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment); + return makeModNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); } CRASH(); return 0; } -ExpressionNode* ASTBuilder::makeAssignNode(int lineNumber, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end) +ExpressionNode* ASTBuilder::makeAssignNode(const JSTokenLocation& location, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end) { if (!loc->isLocation()) - return new (m_globalData) AssignErrorNode(lineNumber, divot, divot - start, end - divot); + return new (m_globalData) AssignErrorNode(location, divot, divot - start, end - divot); if (loc->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(loc); if (op == OpEqual) { if (expr->isFuncExprNode()) static_cast<FuncExprNode*>(expr)->body()->setInferredName(resolve->identifier()); - AssignResolveNode* node = new (m_globalData) AssignResolveNode(lineNumber, resolve->identifier(), expr); + AssignResolveNode* node = new (m_globalData) AssignResolveNode(location, resolve->identifier(), expr); setExceptionLocation(node, start, divot, end); return node; } - return new (m_globalData) ReadModifyResolveNode(lineNumber, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); + return new (m_globalData) ReadModifyResolveNode(location, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); } if (loc->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc); if (op == OpEqual) - return new (m_globalData) AssignBracketNode(lineNumber, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot()); - ReadModifyBracketNode* node = new (m_globalData) ReadModifyBracketNode(lineNumber, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot); + return new (m_globalData) AssignBracketNode(location, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot()); + ReadModifyBracketNode* node = new (m_globalData) ReadModifyBracketNode(location, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot); node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); return node; } @@ -933,55 +933,55 @@ ExpressionNode* ASTBuilder::makeAssignNode(int lineNumber, ExpressionNode* loc, if (op == OpEqual) { if (expr->isFuncExprNode()) static_cast<FuncExprNode*>(expr)->body()->setInferredName(dot->identifier()); - return new (m_globalData) AssignDotNode(lineNumber, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot()); + return new (m_globalData) AssignDotNode(location, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot()); } - ReadModifyDotNode* node = new (m_globalData) ReadModifyDotNode(lineNumber, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); + ReadModifyDotNode* node = new (m_globalData) ReadModifyDotNode(location, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); node->setSubexpressionInfo(dot->divot(), dot->endOffset()); return node; } -ExpressionNode* ASTBuilder::makePrefixNode(int lineNumber, ExpressionNode* expr, Operator op, int start, int divot, int end) +ExpressionNode* ASTBuilder::makePrefixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator op, int start, int divot, int end) { if (!expr->isLocation()) - return new (m_globalData) PrefixErrorNode(lineNumber, op, divot, divot - start, end - divot); + return new (m_globalData) PrefixErrorNode(location, op, divot, divot - start, end - divot); if (expr->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(expr); - return new (m_globalData) PrefixResolveNode(lineNumber, resolve->identifier(), op, divot, divot - start, end - divot); + return new (m_globalData) PrefixResolveNode(location, resolve->identifier(), op, divot, divot - start, end - divot); } if (expr->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); - PrefixBracketNode* node = new (m_globalData) PrefixBracketNode(lineNumber, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot); + PrefixBracketNode* node = new (m_globalData) PrefixBracketNode(location, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot); node->setSubexpressionInfo(bracket->divot(), bracket->startOffset()); return node; } ASSERT(expr->isDotAccessorNode()); DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); - PrefixDotNode* node = new (m_globalData) PrefixDotNode(lineNumber, dot->base(), dot->identifier(), op, divot, divot - start, end - divot); + PrefixDotNode* node = new (m_globalData) PrefixDotNode(location, dot->base(), dot->identifier(), op, divot, divot - start, end - divot); node->setSubexpressionInfo(dot->divot(), dot->startOffset()); return node; } -ExpressionNode* ASTBuilder::makePostfixNode(int lineNumber, ExpressionNode* expr, Operator op, int start, int divot, int end) +ExpressionNode* ASTBuilder::makePostfixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator op, int start, int divot, int end) { if (!expr->isLocation()) - return new (m_globalData) PostfixErrorNode(lineNumber, op, divot, divot - start, end - divot); + return new (m_globalData) PostfixErrorNode(location, op, divot, divot - start, end - divot); if (expr->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(expr); - return new (m_globalData) PostfixResolveNode(lineNumber, resolve->identifier(), op, divot, divot - start, end - divot); + return new (m_globalData) PostfixResolveNode(location, resolve->identifier(), op, divot, divot - start, end - divot); } if (expr->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); - PostfixBracketNode* node = new (m_globalData) PostfixBracketNode(lineNumber, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot); + PostfixBracketNode* node = new (m_globalData) PostfixBracketNode(location, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot); node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); return node; } ASSERT(expr->isDotAccessorNode()); DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); - PostfixDotNode* node = new (m_globalData) PostfixDotNode(lineNumber, dot->base(), dot->identifier(), op, divot, divot - start, end - divot); + PostfixDotNode* node = new (m_globalData) PostfixDotNode(location, dot->base(), dot->identifier(), op, divot, divot - start, end - divot); node->setSubexpressionInfo(dot->divot(), dot->endOffset()); return node; } diff --git a/Source/JavaScriptCore/parser/Lexer.cpp b/Source/JavaScriptCore/parser/Lexer.cpp index 3b020f4f2..2a8a8dc9e 100644 --- a/Source/JavaScriptCore/parser/Lexer.cpp +++ b/Source/JavaScriptCore/parser/Lexer.cpp @@ -417,6 +417,7 @@ void Lexer<T>::setCode(const SourceCode& source, ParserArena* arena) m_codeEnd = m_codeStart + source.endOffset(); m_error = false; m_atLineStart = true; + m_columnNumber = 0; m_lexErrorMessage = UString(); m_buffer8.reserveInitialCapacity(initialReadBufferCapacity); @@ -433,6 +434,7 @@ template <typename T> template <int shiftAmount> ALWAYS_INLINE void Lexer<T>::internalShift() { m_code += shiftAmount; + m_columnNumber += shiftAmount; m_current = *m_code; } @@ -444,6 +446,7 @@ ALWAYS_INLINE void Lexer<T>::shift() ++m_code; if (LIKELY(m_code < m_codeEnd)) m_current = *m_code; + ++m_columnNumber; } template <typename T> @@ -1183,7 +1186,7 @@ bool Lexer<T>::nextTokenIsColon() } template <typename T> -JSTokenType Lexer<T>::lex(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsigned lexerFlags, bool strictMode) +JSTokenType Lexer<T>::lex(JSTokenData* tokenData, JSTokenLocation* tokenLocation, unsigned lexerFlags, bool strictMode) { ASSERT(!m_error); ASSERT(m_buffer8.isEmpty()); @@ -1199,7 +1202,8 @@ start: if (atEnd()) return EOFTOK; - tokenInfo->startOffset = currentOffset(); + tokenLocation->startOffset = currentOffset(); + tokenLocation->column = m_columnNumber; CharacterType type; if (LIKELY(isLatin1(m_current))) @@ -1522,6 +1526,7 @@ inNumberAfterDecimalPoint: shiftLineTerminator(); m_atLineStart = true; m_terminator = true; + m_columnNumber = 0; goto start; case CharacterInvalid: m_lexErrorMessage = invalidCharacterMessage(); @@ -1544,6 +1549,7 @@ inSingleLineComment: shiftLineTerminator(); m_atLineStart = true; m_terminator = true; + m_columnNumber = 0; if (!lastTokenWasRestrKeyword()) goto start; @@ -1551,15 +1557,15 @@ inSingleLineComment: // Fall through into returnToken. returnToken: - tokenInfo->line = m_lineNumber; - tokenInfo->endOffset = currentOffset(); + tokenLocation->line = m_lineNumber; + tokenLocation->endOffset = currentOffset(); m_lastToken = token; return token; returnError: m_error = true; - tokenInfo->line = m_lineNumber; - tokenInfo->endOffset = currentOffset(); + tokenLocation->line = m_lineNumber; + tokenLocation->endOffset = currentOffset(); return ERRORTOK; } diff --git a/Source/JavaScriptCore/parser/Lexer.h b/Source/JavaScriptCore/parser/Lexer.h index 41f1f8553..1ac832a2c 100644 --- a/Source/JavaScriptCore/parser/Lexer.h +++ b/Source/JavaScriptCore/parser/Lexer.h @@ -87,9 +87,10 @@ public: void setIsReparsing() { m_isReparsing = true; } bool isReparsing() const { return m_isReparsing; } - JSTokenType lex(JSTokenData*, JSTokenInfo*, unsigned, bool strictMode); + JSTokenType lex(JSTokenData*, JSTokenLocation*, unsigned, bool strictMode); bool nextTokenIsColon(); int lineNumber() const { return m_lineNumber; } + int currentColumnNumber() const { return m_columnNumber; } void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; } int lastLineNumber() const { return m_lastLineNumber; } bool prevTerminator() const { return m_terminator; } @@ -120,7 +121,7 @@ public: SourceProvider* sourceProvider() const { return m_source->provider(); } - JSTokenType lexExpectIdentifier(JSTokenData*, JSTokenInfo*, unsigned, bool strictMode); + JSTokenType lexExpectIdentifier(JSTokenData*, JSTokenLocation*, unsigned, bool strictMode); private: void record8(int); @@ -166,6 +167,7 @@ private: int m_lineNumber; int m_lastLineNumber; + int m_columnNumber; Vector<LChar> m_buffer8; Vector<UChar> m_buffer16; @@ -257,7 +259,7 @@ ALWAYS_INLINE const Identifier* Lexer<T>::makeIdentifierLCharFromUChar(const UCh } template <typename T> -ALWAYS_INLINE JSTokenType Lexer<T>::lexExpectIdentifier(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsigned lexerFlags, bool strictMode) +ALWAYS_INLINE JSTokenType Lexer<T>::lexExpectIdentifier(JSTokenData* tokenData, JSTokenLocation* tokenLocation, unsigned lexerFlags, bool strictMode) { ASSERT((lexerFlags & LexerFlagsIgnoreReservedWords)); const T* start = m_code; @@ -285,20 +287,22 @@ ALWAYS_INLINE JSTokenType Lexer<T>::lexExpectIdentifier(JSTokenData* tokenData, m_current = 0; m_code = ptr; + m_columnNumber = m_columnNumber + (m_code - start); // Create the identifier if needed if (lexerFlags & LexexFlagsDontBuildKeywords) tokenData->ident = 0; else tokenData->ident = makeIdentifier(start, ptr - start); - tokenInfo->line = m_lineNumber; - tokenInfo->startOffset = start - m_codeStart; - tokenInfo->endOffset = currentOffset(); + tokenLocation->line = m_lineNumber; + tokenLocation->startOffset = start - m_codeStart; + tokenLocation->endOffset = currentOffset(); + tokenLocation->column = m_columnNumber; m_lastToken = IDENT; return IDENT; slowCase: - return lex(tokenData, tokenInfo, lexerFlags, strictMode); + return lex(tokenData, tokenLocation, lexerFlags, strictMode); } } // namespace JSC diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h index be50eeafe..43d1e17c6 100644 --- a/Source/JavaScriptCore/parser/NodeConstructors.h +++ b/Source/JavaScriptCore/parser/NodeConstructors.h @@ -42,60 +42,61 @@ namespace JSC { globalData->parserArena->derefWithArena(adoptRef(this)); } - inline Node::Node(int lineNumber) - : m_lineNumber(lineNumber) + inline Node::Node(const JSTokenLocation& location) + : m_lineNumber(location.line) + , m_columnNumber(location.column) { } - inline ExpressionNode::ExpressionNode(int lineNumber, ResultType resultType) - : Node(lineNumber) + inline ExpressionNode::ExpressionNode(const JSTokenLocation& location, ResultType resultType) + : Node(location) , m_resultType(resultType) { } - inline StatementNode::StatementNode(int lineNumber) - : Node(lineNumber) + inline StatementNode::StatementNode(const JSTokenLocation& location) + : Node(location) , m_lastLine(-1) { } - inline NullNode::NullNode(int lineNumber) - : ExpressionNode(lineNumber, ResultType::nullType()) + inline NullNode::NullNode(const JSTokenLocation& location) + : ExpressionNode(location, ResultType::nullType()) { } - inline BooleanNode::BooleanNode(int lineNumber, bool value) - : ExpressionNode(lineNumber, ResultType::booleanType()) + inline BooleanNode::BooleanNode(const JSTokenLocation& location, bool value) + : ExpressionNode(location, ResultType::booleanType()) , m_value(value) { } - inline NumberNode::NumberNode(int lineNumber, double value) - : ExpressionNode(lineNumber, ResultType::numberType()) + inline NumberNode::NumberNode(const JSTokenLocation& location, double value) + : ExpressionNode(location, ResultType::numberType()) , m_value(value) { } - inline StringNode::StringNode(int lineNumber, const Identifier& value) - : ExpressionNode(lineNumber, ResultType::stringType()) + inline StringNode::StringNode(const JSTokenLocation& location, const Identifier& value) + : ExpressionNode(location, ResultType::stringType()) , m_value(value) { } - inline RegExpNode::RegExpNode(int lineNumber, const Identifier& pattern, const Identifier& flags) - : ExpressionNode(lineNumber) + inline RegExpNode::RegExpNode(const JSTokenLocation& location, const Identifier& pattern, const Identifier& flags) + : ExpressionNode(location) , m_pattern(pattern) , m_flags(flags) { } - inline ThisNode::ThisNode(int lineNumber) - : ExpressionNode(lineNumber) + inline ThisNode::ThisNode(const JSTokenLocation& location) + : ExpressionNode(location) { } - inline ResolveNode::ResolveNode(int lineNumber, const Identifier& ident, int startOffset) - : ExpressionNode(lineNumber) + inline ResolveNode::ResolveNode(const JSTokenLocation& location, const Identifier& ident, int startOffset) + : ExpressionNode(location) , m_ident(ident) , m_startOffset(startOffset) { @@ -116,24 +117,24 @@ namespace JSC { l->m_next = this; } - inline ArrayNode::ArrayNode(int lineNumber, int elision) - : ExpressionNode(lineNumber) + inline ArrayNode::ArrayNode(const JSTokenLocation& location, int elision) + : ExpressionNode(location) , m_element(0) , m_elision(elision) , m_optional(true) { } - inline ArrayNode::ArrayNode(int lineNumber, ElementNode* element) - : ExpressionNode(lineNumber) + inline ArrayNode::ArrayNode(const JSTokenLocation& location, ElementNode* element) + : ExpressionNode(location) , m_element(element) , m_elision(0) , m_optional(false) { } - inline ArrayNode::ArrayNode(int lineNumber, int elision, ElementNode* element) - : ExpressionNode(lineNumber) + inline ArrayNode::ArrayNode(const JSTokenLocation& location, int elision, ElementNode* element) + : ExpressionNode(location) , m_element(element) , m_elision(elision) , m_optional(true) @@ -154,57 +155,57 @@ namespace JSC { { } - inline PropertyListNode::PropertyListNode(int lineNumber, PropertyNode* node) - : Node(lineNumber) + inline PropertyListNode::PropertyListNode(const JSTokenLocation& location, PropertyNode* node) + : Node(location) , m_node(node) , m_next(0) { } - inline PropertyListNode::PropertyListNode(int lineNumber, PropertyNode* node, PropertyListNode* list) - : Node(lineNumber) + inline PropertyListNode::PropertyListNode(const JSTokenLocation& location, PropertyNode* node, PropertyListNode* list) + : Node(location) , m_node(node) , m_next(0) { list->m_next = this; } - inline ObjectLiteralNode::ObjectLiteralNode(int lineNumber) - : ExpressionNode(lineNumber) + inline ObjectLiteralNode::ObjectLiteralNode(const JSTokenLocation& location) + : ExpressionNode(location) , m_list(0) { } - inline ObjectLiteralNode::ObjectLiteralNode(int lineNumber, PropertyListNode* list) - : ExpressionNode(lineNumber) + inline ObjectLiteralNode::ObjectLiteralNode(const JSTokenLocation& location, PropertyListNode* list) + : ExpressionNode(location) , m_list(list) { } - inline BracketAccessorNode::BracketAccessorNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments) - : ExpressionNode(lineNumber) + inline BracketAccessorNode::BracketAccessorNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments) + : ExpressionNode(location) , m_base(base) , m_subscript(subscript) , m_subscriptHasAssignments(subscriptHasAssignments) { } - inline DotAccessorNode::DotAccessorNode(int lineNumber, ExpressionNode* base, const Identifier& ident) - : ExpressionNode(lineNumber) + inline DotAccessorNode::DotAccessorNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident) + : ExpressionNode(location) , m_base(base) , m_ident(ident) { } - inline ArgumentListNode::ArgumentListNode(int lineNumber, ExpressionNode* expr) - : Node(lineNumber) + inline ArgumentListNode::ArgumentListNode(const JSTokenLocation& location, ExpressionNode* expr) + : Node(location) , m_next(0) , m_expr(expr) { } - inline ArgumentListNode::ArgumentListNode(int lineNumber, ArgumentListNode* listNode, ExpressionNode* expr) - : Node(lineNumber) + inline ArgumentListNode::ArgumentListNode(const JSTokenLocation& location, ArgumentListNode* listNode, ExpressionNode* expr) + : Node(location) , m_next(0) , m_expr(expr) { @@ -221,45 +222,45 @@ namespace JSC { { } - inline NewExprNode::NewExprNode(int lineNumber, ExpressionNode* expr) - : ExpressionNode(lineNumber) + inline NewExprNode::NewExprNode(const JSTokenLocation& location, ExpressionNode* expr) + : ExpressionNode(location) , m_expr(expr) , m_args(0) { } - inline NewExprNode::NewExprNode(int lineNumber, ExpressionNode* expr, ArgumentsNode* args) - : ExpressionNode(lineNumber) + inline NewExprNode::NewExprNode(const JSTokenLocation& location, ExpressionNode* expr, ArgumentsNode* args) + : ExpressionNode(location) , m_expr(expr) , m_args(args) { } - inline EvalFunctionCallNode::EvalFunctionCallNode(int lineNumber, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline EvalFunctionCallNode::EvalFunctionCallNode(const JSTokenLocation& location, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) , m_args(args) { } - inline FunctionCallValueNode::FunctionCallValueNode(int lineNumber, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline FunctionCallValueNode::FunctionCallValueNode(const JSTokenLocation& location, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) , m_expr(expr) , m_args(args) { } - inline FunctionCallResolveNode::FunctionCallResolveNode(int lineNumber, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline FunctionCallResolveNode::FunctionCallResolveNode(const JSTokenLocation& location, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) , m_ident(ident) , m_args(args) { } - inline FunctionCallBracketNode::FunctionCallBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline FunctionCallBracketNode::FunctionCallBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableSubExpressionData(divot, startOffset, endOffset) , m_base(base) , m_subscript(subscript) @@ -267,8 +268,8 @@ namespace JSC { { } - inline FunctionCallDotNode::FunctionCallDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline FunctionCallDotNode::FunctionCallDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableSubExpressionData(divot, startOffset, endOffset) , m_base(base) , m_ident(ident) @@ -276,31 +277,31 @@ namespace JSC { { } - inline CallFunctionCallDotNode::CallFunctionCallDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) - : FunctionCallDotNode(lineNumber, base, ident, args, divot, startOffset, endOffset) + inline CallFunctionCallDotNode::CallFunctionCallDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : FunctionCallDotNode(location, base, ident, args, divot, startOffset, endOffset) { } - inline ApplyFunctionCallDotNode::ApplyFunctionCallDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) - : FunctionCallDotNode(lineNumber, base, ident, args, divot, startOffset, endOffset) + inline ApplyFunctionCallDotNode::ApplyFunctionCallDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : FunctionCallDotNode(location, base, ident, args, divot, startOffset, endOffset) { } - inline PrePostResolveNode::PrePostResolveNode(int lineNumber, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber, ResultType::numberType()) // could be reusable for pre? + inline PrePostResolveNode::PrePostResolveNode(const JSTokenLocation& location, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location, ResultType::numberType()) // could be reusable for pre? , ThrowableExpressionData(divot, startOffset, endOffset) , m_ident(ident) { } - inline PostfixResolveNode::PostfixResolveNode(int lineNumber, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) - : PrePostResolveNode(lineNumber, ident, divot, startOffset, endOffset) + inline PostfixResolveNode::PostfixResolveNode(const JSTokenLocation& location, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : PrePostResolveNode(location, ident, divot, startOffset, endOffset) , m_operator(oper) { } - inline PostfixBracketNode::PostfixBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline PostfixBracketNode::PostfixBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableSubExpressionData(divot, startOffset, endOffset) , m_base(base) , m_subscript(subscript) @@ -308,8 +309,8 @@ namespace JSC { { } - inline PostfixDotNode::PostfixDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline PostfixDotNode::PostfixDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableSubExpressionData(divot, startOffset, endOffset) , m_base(base) , m_ident(ident) @@ -317,68 +318,68 @@ namespace JSC { { } - inline PostfixErrorNode::PostfixErrorNode(int lineNumber, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline PostfixErrorNode::PostfixErrorNode(const JSTokenLocation& location, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableSubExpressionData(divot, startOffset, endOffset) , m_operator(oper) { } - inline DeleteResolveNode::DeleteResolveNode(int lineNumber, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline DeleteResolveNode::DeleteResolveNode(const JSTokenLocation& location, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) , m_ident(ident) { } - inline DeleteBracketNode::DeleteBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline DeleteBracketNode::DeleteBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) , m_base(base) , m_subscript(subscript) { } - inline DeleteDotNode::DeleteDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline DeleteDotNode::DeleteDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) , m_base(base) , m_ident(ident) { } - inline DeleteValueNode::DeleteValueNode(int lineNumber, ExpressionNode* expr) - : ExpressionNode(lineNumber) + inline DeleteValueNode::DeleteValueNode(const JSTokenLocation& location, ExpressionNode* expr) + : ExpressionNode(location) , m_expr(expr) { } - inline VoidNode::VoidNode(int lineNumber, ExpressionNode* expr) - : ExpressionNode(lineNumber) + inline VoidNode::VoidNode(const JSTokenLocation& location, ExpressionNode* expr) + : ExpressionNode(location) , m_expr(expr) { } - inline TypeOfResolveNode::TypeOfResolveNode(int lineNumber, const Identifier& ident) - : ExpressionNode(lineNumber, ResultType::stringType()) + inline TypeOfResolveNode::TypeOfResolveNode(const JSTokenLocation& location, const Identifier& ident) + : ExpressionNode(location, ResultType::stringType()) , m_ident(ident) { } - inline TypeOfValueNode::TypeOfValueNode(int lineNumber, ExpressionNode* expr) - : ExpressionNode(lineNumber, ResultType::stringType()) + inline TypeOfValueNode::TypeOfValueNode(const JSTokenLocation& location, ExpressionNode* expr) + : ExpressionNode(location, ResultType::stringType()) , m_expr(expr) { } - inline PrefixResolveNode::PrefixResolveNode(int lineNumber, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) - : PrePostResolveNode(lineNumber, ident, divot, startOffset, endOffset) + inline PrefixResolveNode::PrefixResolveNode(const JSTokenLocation& location, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : PrePostResolveNode(location, ident, divot, startOffset, endOffset) , m_operator(oper) { } - inline PrefixBracketNode::PrefixBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline PrefixBracketNode::PrefixBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) , m_base(base) , m_subscript(subscript) @@ -386,8 +387,8 @@ namespace JSC { { } - inline PrefixDotNode::PrefixDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline PrefixDotNode::PrefixDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) , m_base(base) , m_ident(ident) @@ -395,43 +396,43 @@ namespace JSC { { } - inline PrefixErrorNode::PrefixErrorNode(int lineNumber, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline PrefixErrorNode::PrefixErrorNode(const JSTokenLocation& location, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) , m_operator(oper) { } - inline UnaryOpNode::UnaryOpNode(int lineNumber, ResultType type, ExpressionNode* expr, OpcodeID opcodeID) - : ExpressionNode(lineNumber, type) + inline UnaryOpNode::UnaryOpNode(const JSTokenLocation& location, ResultType type, ExpressionNode* expr, OpcodeID opcodeID) + : ExpressionNode(location, type) , m_expr(expr) , m_opcodeID(opcodeID) { } - inline UnaryPlusNode::UnaryPlusNode(int lineNumber, ExpressionNode* expr) - : UnaryOpNode(lineNumber, ResultType::numberType(), expr, op_to_jsnumber) + inline UnaryPlusNode::UnaryPlusNode(const JSTokenLocation& location, ExpressionNode* expr) + : UnaryOpNode(location, ResultType::numberType(), expr, op_to_jsnumber) { } - inline NegateNode::NegateNode(int lineNumber, ExpressionNode* expr) - : UnaryOpNode(lineNumber, ResultType::numberType(), expr, op_negate) + inline NegateNode::NegateNode(const JSTokenLocation& location, ExpressionNode* expr) + : UnaryOpNode(location, ResultType::numberType(), expr, op_negate) { } - inline BitwiseNotNode::BitwiseNotNode(int lineNumber, ExpressionNode* expr) - : ExpressionNode(lineNumber, ResultType::forBitOp()) + inline BitwiseNotNode::BitwiseNotNode(const JSTokenLocation& location, ExpressionNode* expr) + : ExpressionNode(location, ResultType::forBitOp()) , m_expr(expr) { } - inline LogicalNotNode::LogicalNotNode(int lineNumber, ExpressionNode* expr) - : UnaryOpNode(lineNumber, ResultType::booleanType(), expr, op_not) + inline LogicalNotNode::LogicalNotNode(const JSTokenLocation& location, ExpressionNode* expr) + : UnaryOpNode(location, ResultType::booleanType(), expr, op_not) { } - inline BinaryOpNode::BinaryOpNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) - : ExpressionNode(lineNumber) + inline BinaryOpNode::BinaryOpNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) + : ExpressionNode(location) , m_expr1(expr1) , m_expr2(expr2) , m_opcodeID(opcodeID) @@ -439,8 +440,8 @@ namespace JSC { { } - inline BinaryOpNode::BinaryOpNode(int lineNumber, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) - : ExpressionNode(lineNumber, type) + inline BinaryOpNode::BinaryOpNode(const JSTokenLocation& location, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) + : ExpressionNode(location, type) , m_expr1(expr1) , m_expr2(expr2) , m_opcodeID(opcodeID) @@ -448,140 +449,140 @@ namespace JSC { { } - inline MultNode::MultNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_mul, rightHasAssignments) + inline MultNode::MultNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_mul, rightHasAssignments) { } - inline DivNode::DivNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_div, rightHasAssignments) + inline DivNode::DivNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_div, rightHasAssignments) { } - inline ModNode::ModNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_mod, rightHasAssignments) + inline ModNode::ModNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_mod, rightHasAssignments) { } - inline AddNode::AddNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_add, rightHasAssignments) + inline AddNode::AddNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_add, rightHasAssignments) { } - inline SubNode::SubNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_sub, rightHasAssignments) + inline SubNode::SubNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_sub, rightHasAssignments) { } - inline LeftShiftNode::LeftShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::forBitOp(), expr1, expr2, op_lshift, rightHasAssignments) + inline LeftShiftNode::LeftShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::forBitOp(), expr1, expr2, op_lshift, rightHasAssignments) { } - inline RightShiftNode::RightShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::forBitOp(), expr1, expr2, op_rshift, rightHasAssignments) + inline RightShiftNode::RightShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::forBitOp(), expr1, expr2, op_rshift, rightHasAssignments) { } - inline UnsignedRightShiftNode::UnsignedRightShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_urshift, rightHasAssignments) + inline UnsignedRightShiftNode::UnsignedRightShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_urshift, rightHasAssignments) { } - inline LessNode::LessNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_less, rightHasAssignments) + inline LessNode::LessNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::booleanType(), expr1, expr2, op_less, rightHasAssignments) { } - inline GreaterNode::GreaterNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_greater, rightHasAssignments) + inline GreaterNode::GreaterNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::booleanType(), expr1, expr2, op_greater, rightHasAssignments) { } - inline LessEqNode::LessEqNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_lesseq, rightHasAssignments) + inline LessEqNode::LessEqNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::booleanType(), expr1, expr2, op_lesseq, rightHasAssignments) { } - inline GreaterEqNode::GreaterEqNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_greatereq, rightHasAssignments) + inline GreaterEqNode::GreaterEqNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::booleanType(), expr1, expr2, op_greatereq, rightHasAssignments) { } - inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(int lineNumber, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) - : BinaryOpNode(lineNumber, type, expr1, expr2, opcodeID, rightHasAssignments) + inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(const JSTokenLocation& location, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) + : BinaryOpNode(location, type, expr1, expr2, opcodeID, rightHasAssignments) { } - inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) - : BinaryOpNode(lineNumber, expr1, expr2, opcodeID, rightHasAssignments) + inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) + : BinaryOpNode(location, expr1, expr2, opcodeID, rightHasAssignments) { } - inline InstanceOfNode::InstanceOfNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : ThrowableBinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_instanceof, rightHasAssignments) + inline InstanceOfNode::InstanceOfNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : ThrowableBinaryOpNode(location, ResultType::booleanType(), expr1, expr2, op_instanceof, rightHasAssignments) { } - inline InNode::InNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : ThrowableBinaryOpNode(lineNumber, expr1, expr2, op_in, rightHasAssignments) + inline InNode::InNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : ThrowableBinaryOpNode(location, expr1, expr2, op_in, rightHasAssignments) { } - inline EqualNode::EqualNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_eq, rightHasAssignments) + inline EqualNode::EqualNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::booleanType(), expr1, expr2, op_eq, rightHasAssignments) { } - inline NotEqualNode::NotEqualNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_neq, rightHasAssignments) + inline NotEqualNode::NotEqualNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::booleanType(), expr1, expr2, op_neq, rightHasAssignments) { } - inline StrictEqualNode::StrictEqualNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_stricteq, rightHasAssignments) + inline StrictEqualNode::StrictEqualNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::booleanType(), expr1, expr2, op_stricteq, rightHasAssignments) { } - inline NotStrictEqualNode::NotStrictEqualNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_nstricteq, rightHasAssignments) + inline NotStrictEqualNode::NotStrictEqualNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::booleanType(), expr1, expr2, op_nstricteq, rightHasAssignments) { } - inline BitAndNode::BitAndNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::forBitOp(), expr1, expr2, op_bitand, rightHasAssignments) + inline BitAndNode::BitAndNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::forBitOp(), expr1, expr2, op_bitand, rightHasAssignments) { } - inline BitOrNode::BitOrNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::forBitOp(), expr1, expr2, op_bitor, rightHasAssignments) + inline BitOrNode::BitOrNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::forBitOp(), expr1, expr2, op_bitor, rightHasAssignments) { } - inline BitXOrNode::BitXOrNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::forBitOp(), expr1, expr2, op_bitxor, rightHasAssignments) + inline BitXOrNode::BitXOrNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(location, ResultType::forBitOp(), expr1, expr2, op_bitxor, rightHasAssignments) { } - inline LogicalOpNode::LogicalOpNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper) - : ExpressionNode(lineNumber, ResultType::booleanType()) + inline LogicalOpNode::LogicalOpNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper) + : ExpressionNode(location, ResultType::booleanType()) , m_expr1(expr1) , m_expr2(expr2) , m_operator(oper) { } - inline ConditionalNode::ConditionalNode(int lineNumber, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2) - : ExpressionNode(lineNumber) + inline ConditionalNode::ConditionalNode(const JSTokenLocation& location, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2) + : ExpressionNode(location) , m_logical(logical) , m_expr1(expr1) , m_expr2(expr2) { } - inline ReadModifyResolveNode::ReadModifyResolveNode(int lineNumber, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline ReadModifyResolveNode::ReadModifyResolveNode(const JSTokenLocation& location, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) , m_ident(ident) , m_right(right) @@ -590,15 +591,15 @@ namespace JSC { { } - inline AssignResolveNode::AssignResolveNode(int lineNumber, const Identifier& ident, ExpressionNode* right) - : ExpressionNode(lineNumber) + inline AssignResolveNode::AssignResolveNode(const JSTokenLocation& location, const Identifier& ident, ExpressionNode* right) + : ExpressionNode(location) , m_ident(ident) , m_right(right) { } - inline ReadModifyBracketNode::ReadModifyBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline ReadModifyBracketNode::ReadModifyBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableSubExpressionData(divot, startOffset, endOffset) , m_base(base) , m_subscript(subscript) @@ -609,8 +610,8 @@ namespace JSC { { } - inline AssignBracketNode::AssignBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline AssignBracketNode::AssignBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) , m_base(base) , m_subscript(subscript) @@ -620,8 +621,8 @@ namespace JSC { { } - inline AssignDotNode::AssignDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline AssignDotNode::AssignDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) , m_base(base) , m_ident(ident) @@ -630,8 +631,8 @@ namespace JSC { { } - inline ReadModifyDotNode::ReadModifyDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline ReadModifyDotNode::ReadModifyDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableSubExpressionData(divot, startOffset, endOffset) , m_base(base) , m_ident(ident) @@ -641,21 +642,21 @@ namespace JSC { { } - inline AssignErrorNode::AssignErrorNode(int lineNumber, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(lineNumber) + inline AssignErrorNode::AssignErrorNode(const JSTokenLocation& location, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(location) , ThrowableExpressionData(divot, startOffset, endOffset) { } - inline CommaNode::CommaNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2) - : ExpressionNode(lineNumber) + inline CommaNode::CommaNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2) + : ExpressionNode(location) { m_expressions.append(expr1); m_expressions.append(expr2); } - inline ConstStatementNode::ConstStatementNode(int lineNumber, ConstDeclNode* next) - : StatementNode(lineNumber) + inline ConstStatementNode::ConstStatementNode(const JSTokenLocation& location, ConstDeclNode* next) + : StatementNode(location) , m_next(next) { } @@ -664,57 +665,57 @@ namespace JSC { { } - inline EmptyStatementNode::EmptyStatementNode(int lineNumber) - : StatementNode(lineNumber) + inline EmptyStatementNode::EmptyStatementNode(const JSTokenLocation& location) + : StatementNode(location) { } - inline DebuggerStatementNode::DebuggerStatementNode(int lineNumber) - : StatementNode(lineNumber) + inline DebuggerStatementNode::DebuggerStatementNode(const JSTokenLocation& location) + : StatementNode(location) { } - inline ExprStatementNode::ExprStatementNode(int lineNumber, ExpressionNode* expr) - : StatementNode(lineNumber) + inline ExprStatementNode::ExprStatementNode(const JSTokenLocation& location, ExpressionNode* expr) + : StatementNode(location) , m_expr(expr) { } - inline VarStatementNode::VarStatementNode(int lineNumber, ExpressionNode* expr) - : StatementNode(lineNumber) + inline VarStatementNode::VarStatementNode(const JSTokenLocation& location, ExpressionNode* expr) + : StatementNode(location) , m_expr(expr) { } - inline IfNode::IfNode(int lineNumber, ExpressionNode* condition, StatementNode* ifBlock) - : StatementNode(lineNumber) + inline IfNode::IfNode(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* ifBlock) + : StatementNode(location) , m_condition(condition) , m_ifBlock(ifBlock) { } - inline IfElseNode::IfElseNode(int lineNumber, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) - : IfNode(lineNumber, condition, ifBlock) + inline IfElseNode::IfElseNode(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) + : IfNode(location, condition, ifBlock) , m_elseBlock(elseBlock) { } - inline DoWhileNode::DoWhileNode(int lineNumber, StatementNode* statement, ExpressionNode* expr) - : StatementNode(lineNumber) + inline DoWhileNode::DoWhileNode(const JSTokenLocation& location, StatementNode* statement, ExpressionNode* expr) + : StatementNode(location) , m_statement(statement) , m_expr(expr) { } - inline WhileNode::WhileNode(int lineNumber, ExpressionNode* expr, StatementNode* statement) - : StatementNode(lineNumber) + inline WhileNode::WhileNode(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement) + : StatementNode(location) , m_expr(expr) , m_statement(statement) { } - inline ForNode::ForNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement) - : StatementNode(lineNumber) + inline ForNode::ForNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement) + : StatementNode(location) , m_expr1(expr1) , m_expr2(expr2) , m_expr3(expr3) @@ -723,38 +724,38 @@ namespace JSC { ASSERT(statement); } - inline ContinueNode::ContinueNode(JSGlobalData* globalData, int lineNumber) - : StatementNode(lineNumber) + inline ContinueNode::ContinueNode(JSGlobalData* globalData, const JSTokenLocation& location) + : StatementNode(location) , m_ident(globalData->propertyNames->nullIdentifier) { } - inline ContinueNode::ContinueNode(int lineNumber, const Identifier& ident) - : StatementNode(lineNumber) + inline ContinueNode::ContinueNode(const JSTokenLocation& location, const Identifier& ident) + : StatementNode(location) , m_ident(ident) { } - inline BreakNode::BreakNode(JSGlobalData* globalData, int lineNumber) - : StatementNode(lineNumber) + inline BreakNode::BreakNode(JSGlobalData* globalData, const JSTokenLocation& location) + : StatementNode(location) , m_ident(globalData->propertyNames->nullIdentifier) { } - inline BreakNode::BreakNode(int lineNumber, const Identifier& ident) - : StatementNode(lineNumber) + inline BreakNode::BreakNode(const JSTokenLocation& location, const Identifier& ident) + : StatementNode(location) , m_ident(ident) { } - inline ReturnNode::ReturnNode(int lineNumber, ExpressionNode* value) - : StatementNode(lineNumber) + inline ReturnNode::ReturnNode(const JSTokenLocation& location, ExpressionNode* value) + : StatementNode(location) , m_value(value) { } - inline WithNode::WithNode(int lineNumber, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength) - : StatementNode(lineNumber) + inline WithNode::WithNode(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength) + : StatementNode(location) , m_expr(expr) , m_statement(statement) , m_divot(divot) @@ -762,21 +763,21 @@ namespace JSC { { } - inline LabelNode::LabelNode(int lineNumber, const Identifier& name, StatementNode* statement) - : StatementNode(lineNumber) + inline LabelNode::LabelNode(const JSTokenLocation& location, const Identifier& name, StatementNode* statement) + : StatementNode(location) , m_name(name) , m_statement(statement) { } - inline ThrowNode::ThrowNode(int lineNumber, ExpressionNode* expr) - : StatementNode(lineNumber) + inline ThrowNode::ThrowNode(const JSTokenLocation& location, ExpressionNode* expr) + : StatementNode(location) , m_expr(expr) { } - inline TryNode::TryNode(int lineNumber, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock) - : StatementNode(lineNumber) + inline TryNode::TryNode(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock) + : StatementNode(location) , m_tryBlock(tryBlock) , m_exceptionIdent(exceptionIdent) , m_catchBlock(catchBlock) @@ -797,15 +798,15 @@ namespace JSC { l->m_next = this; } - inline FuncExprNode::FuncExprNode(int lineNumber, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter) - : ExpressionNode(lineNumber) + inline FuncExprNode::FuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter) + : ExpressionNode(location) , m_body(body) { m_body->finishParsing(source, parameter, ident); } - inline FuncDeclNode::FuncDeclNode(int lineNumber, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter) - : StatementNode(lineNumber) + inline FuncDeclNode::FuncDeclNode(const JSTokenLocation& location, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter) + : StatementNode(location) , m_body(body) { m_body->finishParsing(source, parameter, ident); @@ -837,29 +838,29 @@ namespace JSC { { } - inline SwitchNode::SwitchNode(int lineNumber, ExpressionNode* expr, CaseBlockNode* block) - : StatementNode(lineNumber) + inline SwitchNode::SwitchNode(const JSTokenLocation& location, ExpressionNode* expr, CaseBlockNode* block) + : StatementNode(location) , m_expr(expr) , m_block(block) { } - inline ConstDeclNode::ConstDeclNode(int lineNumber, const Identifier& ident, ExpressionNode* init) - : ExpressionNode(lineNumber) + inline ConstDeclNode::ConstDeclNode(const JSTokenLocation& location, const Identifier& ident, ExpressionNode* init) + : ExpressionNode(location) , m_ident(ident) , m_next(0) , m_init(init) { } - inline BlockNode::BlockNode(int lineNumber, SourceElements* statements) - : StatementNode(lineNumber) + inline BlockNode::BlockNode(const JSTokenLocation& location, SourceElements* statements) + : StatementNode(location) , m_statements(statements) { } - inline ForInNode::ForInNode(int lineNumber, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement) - : StatementNode(lineNumber) + inline ForInNode::ForInNode(const JSTokenLocation& location, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement) + : StatementNode(location) , m_init(0) , m_lexpr(l) , m_expr(expr) @@ -868,16 +869,16 @@ namespace JSC { { } - inline ForInNode::ForInNode(JSGlobalData* globalData, int lineNumber, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset) - : StatementNode(lineNumber) + inline ForInNode::ForInNode(JSGlobalData* globalData, const JSTokenLocation& location, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset) + : StatementNode(location) , m_init(0) - , m_lexpr(new (globalData) ResolveNode(lineNumber, ident, divot - startOffset)) + , m_lexpr(new (globalData) ResolveNode(location, ident, divot - startOffset)) , m_expr(expr) , m_statement(statement) , m_identIsVarDecl(true) { if (in) { - AssignResolveNode* node = new (globalData) AssignResolveNode(lineNumber, ident, in); + AssignResolveNode* node = new (globalData) AssignResolveNode(location, ident, in); node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot); m_init = node; } diff --git a/Source/JavaScriptCore/parser/Nodes.cpp b/Source/JavaScriptCore/parser/Nodes.cpp index c32e4c73a..0172359c7 100644 --- a/Source/JavaScriptCore/parser/Nodes.cpp +++ b/Source/JavaScriptCore/parser/Nodes.cpp @@ -52,10 +52,18 @@ namespace JSC { // ------------------------------ StatementNode -------------------------------- +void StatementNode::setLoc(int firstLine, int lastLine, int column) +{ + m_lineNumber = firstLine; + m_lastLine = lastLine; + m_columnNumber = column; +} + void StatementNode::setLoc(int firstLine, int lastLine) { m_lineNumber = firstLine; m_lastLine = lastLine; + m_columnNumber = 0; } // ------------------------------ SourceElements -------------------------------- @@ -75,8 +83,8 @@ StatementNode* SourceElements::singleStatement() const // ------------------------------ ScopeNode ----------------------------- -ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext) - : StatementNode(lineNumber) +ScopeNode::ScopeNode(JSGlobalData* globalData, const JSTokenLocation& location, bool inStrictContext) + : StatementNode(location) , ParserArenaRefCounted(globalData) , m_features(inStrictContext ? StrictModeFeature : NoFeatures) , m_numConstants(0) @@ -84,8 +92,8 @@ ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, bool inStrictCont { } -ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants) - : StatementNode(lineNumber) +ScopeNode::ScopeNode(JSGlobalData* globalData, const JSTokenLocation& location, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants) + : StatementNode(location) , ParserArenaRefCounted(globalData) , m_features(features) , m_source(source) @@ -107,14 +115,14 @@ StatementNode* ScopeNode::singleStatement() const // ------------------------------ ProgramNode ----------------------------- -inline ProgramNode::ProgramNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) - : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, features, numConstants) +inline ProgramNode::ProgramNode(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) + : ScopeNode(globalData, location, source, children, varStack, funcStack, capturedVariables, features, numConstants) { } -PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) { - RefPtr<ProgramNode> node = new ProgramNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants); + RefPtr<ProgramNode> node = new ProgramNode(globalData, location, children, varStack, funcStack, capturedVariables, source, features, numConstants); ASSERT(node->m_arena.last() == node); node->m_arena.removeLast(); @@ -125,14 +133,14 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNu // ------------------------------ EvalNode ----------------------------- -inline EvalNode::EvalNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) - : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, features, numConstants) +inline EvalNode::EvalNode(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) + : ScopeNode(globalData, location, source, children, varStack, funcStack, capturedVariables, features, numConstants) { } -PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) { - RefPtr<EvalNode> node = new EvalNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants); + RefPtr<EvalNode> node = new EvalNode(globalData, location, children, varStack, funcStack, capturedVariables, source, features, numConstants); ASSERT(node->m_arena.last() == node); node->m_arena.removeLast(); @@ -149,13 +157,13 @@ FunctionParameters::FunctionParameters(ParameterNode* firstParameter) append(parameter->ident()); } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext) - : ScopeNode(globalData, lineNumber, inStrictContext) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, const JSTokenLocation& location, bool inStrictContext) + : ScopeNode(globalData, location, inStrictContext) { } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) - : ScopeNode(globalData, lineNumber, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) + : ScopeNode(globalData, location, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants) { } @@ -172,14 +180,14 @@ void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, m_ident = ident; } -FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, bool inStrictContext) +FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, const JSTokenLocation& location, bool inStrictContext) { - return new FunctionBodyNode(globalData, lineNumber, inStrictContext); + return new FunctionBodyNode(globalData, location, inStrictContext); } -PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) +PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) { - RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants); + RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, location, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants); ASSERT(node->m_arena.last() == node); node->m_arena.removeLast(); diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h index 5b15be44c..ed1a85aaf 100644 --- a/Source/JavaScriptCore/parser/Nodes.h +++ b/Source/JavaScriptCore/parser/Nodes.h @@ -130,7 +130,7 @@ namespace JSC { class Node : public ParserArenaFreeable { protected: - Node(int); + Node(const JSTokenLocation&); public: virtual ~Node() { } @@ -139,13 +139,16 @@ namespace JSC { int lineNo() const { return m_lineNumber; } + int columnNo() const { return m_columnNumber; } + protected: int m_lineNumber; + int m_columnNumber; }; class ExpressionNode : public Node { protected: - ExpressionNode(int, ResultType = ResultType::unknownType()); + ExpressionNode(const JSTokenLocation&, ResultType = ResultType::unknownType()); public: virtual bool isNumber() const { return false; } @@ -175,12 +178,14 @@ namespace JSC { class StatementNode : public Node { protected: - StatementNode(int); + StatementNode(const JSTokenLocation&); public: JS_EXPORT_PRIVATE void setLoc(int firstLine, int lastLine); + void setLoc(int firstLine, int lastLine, int column); int firstLine() const { return lineNo(); } int lastLine() const { return m_lastLine; } + int column() const { return columnNo();} virtual bool isEmptyStatement() const { return false; } virtual bool isReturnNode() const { return false; } @@ -194,7 +199,7 @@ namespace JSC { class NullNode : public ExpressionNode { public: - NullNode(int); + NullNode(const JSTokenLocation&); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -204,7 +209,7 @@ namespace JSC { class BooleanNode : public ExpressionNode { public: - BooleanNode(int, bool value); + BooleanNode(const JSTokenLocation&, bool value); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -216,7 +221,7 @@ namespace JSC { class NumberNode : public ExpressionNode { public: - NumberNode(int, double value); + NumberNode(const JSTokenLocation&, double value); double value() const { return m_value; } void setValue(double value) { m_value = value; } @@ -232,7 +237,7 @@ namespace JSC { class StringNode : public ExpressionNode { public: - StringNode(int, const Identifier&); + StringNode(const JSTokenLocation&, const Identifier&); const Identifier& value() { return m_value; } @@ -342,7 +347,7 @@ namespace JSC { class RegExpNode : public ExpressionNode, public ThrowableExpressionData { public: - RegExpNode(int, const Identifier& pattern, const Identifier& flags); + RegExpNode(const JSTokenLocation&, const Identifier& pattern, const Identifier& flags); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -353,7 +358,7 @@ namespace JSC { class ThisNode : public ExpressionNode { public: - ThisNode(int); + ThisNode(const JSTokenLocation&); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -361,7 +366,7 @@ namespace JSC { class ResolveNode : public ExpressionNode { public: - ResolveNode(int, const Identifier&, int startOffset); + ResolveNode(const JSTokenLocation&, const Identifier&, int startOffset); const Identifier& identifier() const { return m_ident; } @@ -393,11 +398,11 @@ namespace JSC { class ArrayNode : public ExpressionNode { public: - ArrayNode(int, int elision); - ArrayNode(int, ElementNode*); - ArrayNode(int, int elision, ElementNode*); + ArrayNode(const JSTokenLocation&, int elision); + ArrayNode(const JSTokenLocation&, ElementNode*); + ArrayNode(const JSTokenLocation&, int elision, ElementNode*); - ArgumentListNode* toArgumentList(JSGlobalData*, int) const; + ArgumentListNode* toArgumentList(JSGlobalData*, int, int) const; private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -428,8 +433,8 @@ namespace JSC { class PropertyListNode : public Node { public: - PropertyListNode(int, PropertyNode*); - PropertyListNode(int, PropertyNode*, PropertyListNode*); + PropertyListNode(const JSTokenLocation&, PropertyNode*); + PropertyListNode(const JSTokenLocation&, PropertyNode*, PropertyListNode*); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -440,8 +445,8 @@ namespace JSC { class ObjectLiteralNode : public ExpressionNode { public: - ObjectLiteralNode(int); - ObjectLiteralNode(int, PropertyListNode*); + ObjectLiteralNode(const JSTokenLocation&); + ObjectLiteralNode(const JSTokenLocation&, PropertyListNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -451,7 +456,7 @@ namespace JSC { class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData { public: - BracketAccessorNode(int, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments); + BracketAccessorNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments); ExpressionNode* base() const { return m_base; } ExpressionNode* subscript() const { return m_subscript; } @@ -469,7 +474,7 @@ namespace JSC { class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData { public: - DotAccessorNode(int, ExpressionNode* base, const Identifier&); + DotAccessorNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&); ExpressionNode* base() const { return m_base; } const Identifier& identifier() const { return m_ident; } @@ -486,8 +491,8 @@ namespace JSC { class ArgumentListNode : public Node { public: - ArgumentListNode(int, ExpressionNode*); - ArgumentListNode(int, ArgumentListNode*, ExpressionNode*); + ArgumentListNode(const JSTokenLocation&, ExpressionNode*); + ArgumentListNode(const JSTokenLocation&, ArgumentListNode*, ExpressionNode*); ArgumentListNode* m_next; ExpressionNode* m_expr; @@ -506,8 +511,8 @@ namespace JSC { class NewExprNode : public ExpressionNode, public ThrowableExpressionData { public: - NewExprNode(int, ExpressionNode*); - NewExprNode(int, ExpressionNode*, ArgumentsNode*); + NewExprNode(const JSTokenLocation&, ExpressionNode*); + NewExprNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -518,7 +523,7 @@ namespace JSC { class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData { public: - EvalFunctionCallNode(int, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + EvalFunctionCallNode(const JSTokenLocation&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -528,7 +533,7 @@ namespace JSC { class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallValueNode(int, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallValueNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -539,7 +544,7 @@ namespace JSC { class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallResolveNode(int, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallResolveNode(const JSTokenLocation&, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -550,7 +555,7 @@ namespace JSC { class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -562,7 +567,7 @@ namespace JSC { class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallDotNode(int, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -575,7 +580,7 @@ namespace JSC { class CallFunctionCallDotNode : public FunctionCallDotNode { public: - CallFunctionCallDotNode(int, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + CallFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -583,7 +588,7 @@ namespace JSC { class ApplyFunctionCallDotNode : public FunctionCallDotNode { public: - ApplyFunctionCallDotNode(int, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + ApplyFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -591,7 +596,7 @@ namespace JSC { class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - PrePostResolveNode(int, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + PrePostResolveNode(const JSTokenLocation&, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); protected: const Identifier& m_ident; @@ -599,7 +604,7 @@ namespace JSC { class PostfixResolveNode : public PrePostResolveNode { public: - PostfixResolveNode(int, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PostfixResolveNode(const JSTokenLocation&, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -609,7 +614,7 @@ namespace JSC { class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - PostfixBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PostfixBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -621,7 +626,7 @@ namespace JSC { class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - PostfixDotNode(int, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PostfixDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -633,7 +638,7 @@ namespace JSC { class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData { public: - PostfixErrorNode(int, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PostfixErrorNode(const JSTokenLocation&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -643,7 +648,7 @@ namespace JSC { class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteResolveNode(int, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + DeleteResolveNode(const JSTokenLocation&, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -653,7 +658,7 @@ namespace JSC { class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset); + DeleteBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -664,7 +669,7 @@ namespace JSC { class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteDotNode(int, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + DeleteDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -675,7 +680,7 @@ namespace JSC { class DeleteValueNode : public ExpressionNode { public: - DeleteValueNode(int, ExpressionNode*); + DeleteValueNode(const JSTokenLocation&, ExpressionNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -685,7 +690,7 @@ namespace JSC { class VoidNode : public ExpressionNode { public: - VoidNode(int, ExpressionNode*); + VoidNode(const JSTokenLocation&, ExpressionNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -695,7 +700,7 @@ namespace JSC { class TypeOfResolveNode : public ExpressionNode { public: - TypeOfResolveNode(int, const Identifier&); + TypeOfResolveNode(const JSTokenLocation&, const Identifier&); const Identifier& identifier() const { return m_ident; } @@ -707,7 +712,7 @@ namespace JSC { class TypeOfValueNode : public ExpressionNode { public: - TypeOfValueNode(int, ExpressionNode*); + TypeOfValueNode(const JSTokenLocation&, ExpressionNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -717,7 +722,7 @@ namespace JSC { class PrefixResolveNode : public PrePostResolveNode { public: - PrefixResolveNode(int, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PrefixResolveNode(const JSTokenLocation&, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -727,7 +732,7 @@ namespace JSC { class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { public: - PrefixBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PrefixBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -739,7 +744,7 @@ namespace JSC { class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { public: - PrefixDotNode(int, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PrefixDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -751,7 +756,7 @@ namespace JSC { class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData { public: - PrefixErrorNode(int, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PrefixErrorNode(const JSTokenLocation&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -761,7 +766,7 @@ namespace JSC { class UnaryOpNode : public ExpressionNode { public: - UnaryOpNode(int, ResultType, ExpressionNode*, OpcodeID); + UnaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode*, OpcodeID); protected: ExpressionNode* expr() { return m_expr; } @@ -778,7 +783,7 @@ namespace JSC { class UnaryPlusNode : public UnaryOpNode { public: - UnaryPlusNode(int, ExpressionNode*); + UnaryPlusNode(const JSTokenLocation&, ExpressionNode*); private: virtual ExpressionNode* stripUnaryPlus() { return expr(); } @@ -786,12 +791,12 @@ namespace JSC { class NegateNode : public UnaryOpNode { public: - NegateNode(int, ExpressionNode*); + NegateNode(const JSTokenLocation&, ExpressionNode*); }; class BitwiseNotNode : public ExpressionNode { public: - BitwiseNotNode(int, ExpressionNode*); + BitwiseNotNode(const JSTokenLocation&, ExpressionNode*); protected: ExpressionNode* expr() { return m_expr; } @@ -805,7 +810,7 @@ namespace JSC { class LogicalNotNode : public UnaryOpNode { public: - LogicalNotNode(int, ExpressionNode*); + LogicalNotNode(const JSTokenLocation&, ExpressionNode*); private: void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); } @@ -813,8 +818,8 @@ namespace JSC { class BinaryOpNode : public ExpressionNode { public: - BinaryOpNode(int, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); - BinaryOpNode(int, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + BinaryOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + BinaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); @@ -838,72 +843,72 @@ namespace JSC { class MultNode : public BinaryOpNode { public: - MultNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + MultNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class DivNode : public BinaryOpNode { public: - DivNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + DivNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class ModNode : public BinaryOpNode { public: - ModNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + ModNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class AddNode : public BinaryOpNode { public: - AddNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + AddNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); virtual bool isAdd() const { return true; } }; class SubNode : public BinaryOpNode { public: - SubNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + SubNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); virtual bool isSubtract() const { return true; } }; class LeftShiftNode : public BinaryOpNode { public: - LeftShiftNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + LeftShiftNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class RightShiftNode : public BinaryOpNode { public: - RightShiftNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + RightShiftNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class UnsignedRightShiftNode : public BinaryOpNode { public: - UnsignedRightShiftNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + UnsignedRightShiftNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class LessNode : public BinaryOpNode { public: - LessNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + LessNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class GreaterNode : public BinaryOpNode { public: - GreaterNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + GreaterNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class LessEqNode : public BinaryOpNode { public: - LessEqNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + LessEqNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class GreaterEqNode : public BinaryOpNode { public: - GreaterEqNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + GreaterEqNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData { public: - ThrowableBinaryOpNode(int, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); - ThrowableBinaryOpNode(int, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + ThrowableBinaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + ThrowableBinaryOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -911,7 +916,7 @@ namespace JSC { class InstanceOfNode : public ThrowableBinaryOpNode { public: - InstanceOfNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + InstanceOfNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -919,12 +924,12 @@ namespace JSC { class InNode : public ThrowableBinaryOpNode { public: - InNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + InNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class EqualNode : public BinaryOpNode { public: - EqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + EqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -932,12 +937,12 @@ namespace JSC { class NotEqualNode : public BinaryOpNode { public: - NotEqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + NotEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class StrictEqualNode : public BinaryOpNode { public: - StrictEqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + StrictEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -945,28 +950,28 @@ namespace JSC { class NotStrictEqualNode : public BinaryOpNode { public: - NotStrictEqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + NotStrictEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitAndNode : public BinaryOpNode { public: - BitAndNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + BitAndNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitOrNode : public BinaryOpNode { public: - BitOrNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + BitOrNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitXOrNode : public BinaryOpNode { public: - BitXOrNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + BitXOrNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; // m_expr1 && m_expr2, m_expr1 || m_expr2 class LogicalOpNode : public ExpressionNode { public: - LogicalOpNode(int, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); + LogicalOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -981,7 +986,7 @@ namespace JSC { // The ternary operator, "m_logical ? m_expr1 : m_expr2" class ConditionalNode : public ExpressionNode { public: - ConditionalNode(int, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2); + ConditionalNode(const JSTokenLocation&, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -993,7 +998,7 @@ namespace JSC { class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - ReadModifyResolveNode(int, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + ReadModifyResolveNode(const JSTokenLocation&, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1006,7 +1011,7 @@ namespace JSC { class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignResolveNode(int, const Identifier&, ExpressionNode* right); + AssignResolveNode(const JSTokenLocation&, const Identifier&, ExpressionNode* right); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1017,7 +1022,7 @@ namespace JSC { class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + ReadModifyBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1032,7 +1037,7 @@ namespace JSC { class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + AssignBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1046,7 +1051,7 @@ namespace JSC { class AssignDotNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignDotNode(int, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + AssignDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1059,7 +1064,7 @@ namespace JSC { class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyDotNode(int, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + ReadModifyDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1073,7 +1078,7 @@ namespace JSC { class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignErrorNode(int, unsigned divot, unsigned startOffset, unsigned endOffset); + AssignErrorNode(const JSTokenLocation&, unsigned divot, unsigned startOffset, unsigned endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1083,7 +1088,7 @@ namespace JSC { class CommaNode : public ExpressionNode, public ParserArenaDeletable { public: - CommaNode(int, ExpressionNode* expr1, ExpressionNode* expr2); + CommaNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2); using ParserArenaDeletable::operator new; @@ -1098,7 +1103,7 @@ namespace JSC { class ConstDeclNode : public ExpressionNode { public: - ConstDeclNode(int, const Identifier&, ExpressionNode*); + ConstDeclNode(const JSTokenLocation&, const Identifier&, ExpressionNode*); bool hasInitializer() const { return m_init; } const Identifier& ident() { return m_ident; } @@ -1118,7 +1123,7 @@ namespace JSC { class ConstStatementNode : public StatementNode { public: - ConstStatementNode(int, ConstDeclNode* next); + ConstStatementNode(const JSTokenLocation&, ConstDeclNode* next); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1143,7 +1148,7 @@ namespace JSC { class BlockNode : public StatementNode { public: - BlockNode(int, SourceElements* = 0); + BlockNode(const JSTokenLocation&, SourceElements* = 0); StatementNode* singleStatement() const; StatementNode* lastStatement() const; @@ -1158,7 +1163,7 @@ namespace JSC { class EmptyStatementNode : public StatementNode { public: - EmptyStatementNode(int); + EmptyStatementNode(const JSTokenLocation&); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1168,7 +1173,7 @@ namespace JSC { class DebuggerStatementNode : public StatementNode { public: - DebuggerStatementNode(int); + DebuggerStatementNode(const JSTokenLocation&); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1176,7 +1181,7 @@ namespace JSC { class ExprStatementNode : public StatementNode { public: - ExprStatementNode(int, ExpressionNode*); + ExprStatementNode(const JSTokenLocation&, ExpressionNode*); ExpressionNode* expr() const { return m_expr; } @@ -1190,8 +1195,7 @@ namespace JSC { class VarStatementNode : public StatementNode { public: - VarStatementNode(int, ExpressionNode*); - + VarStatementNode(const JSTokenLocation&, ExpressionNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1200,7 +1204,7 @@ namespace JSC { class IfNode : public StatementNode { public: - IfNode(int, ExpressionNode* condition, StatementNode* ifBlock); + IfNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock); protected: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1211,7 +1215,7 @@ namespace JSC { class IfElseNode : public IfNode { public: - IfElseNode(int, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); + IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1221,7 +1225,7 @@ namespace JSC { class DoWhileNode : public StatementNode { public: - DoWhileNode(int, StatementNode*, ExpressionNode*); + DoWhileNode(const JSTokenLocation&, StatementNode*, ExpressionNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1232,7 +1236,7 @@ namespace JSC { class WhileNode : public StatementNode { public: - WhileNode(int, ExpressionNode*, StatementNode*); + WhileNode(const JSTokenLocation&, ExpressionNode*, StatementNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1243,7 +1247,7 @@ namespace JSC { class ForNode : public StatementNode { public: - ForNode(int, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*); + ForNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1256,8 +1260,8 @@ namespace JSC { class ForInNode : public StatementNode, public ThrowableExpressionData { public: - ForInNode(int, ExpressionNode*, ExpressionNode*, StatementNode*); - ForInNode(JSGlobalData*, int, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset); + ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); + ForInNode(JSGlobalData*, const JSTokenLocation&, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1271,8 +1275,8 @@ namespace JSC { class ContinueNode : public StatementNode, public ThrowableExpressionData { public: - ContinueNode(JSGlobalData*, int); - ContinueNode(int, const Identifier&); + ContinueNode(JSGlobalData*, const JSTokenLocation&); + ContinueNode(const JSTokenLocation&, const Identifier&); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1282,8 +1286,8 @@ namespace JSC { class BreakNode : public StatementNode, public ThrowableExpressionData { public: - BreakNode(JSGlobalData*, int); - BreakNode(int, const Identifier&); + BreakNode(JSGlobalData*, const JSTokenLocation&); + BreakNode(const JSTokenLocation&, const Identifier&); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1293,7 +1297,7 @@ namespace JSC { class ReturnNode : public StatementNode, public ThrowableExpressionData { public: - ReturnNode(int, ExpressionNode* value); + ReturnNode(const JSTokenLocation&, ExpressionNode* value); ExpressionNode* value() { return m_value; } @@ -1307,7 +1311,7 @@ namespace JSC { class WithNode : public StatementNode { public: - WithNode(int, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength); + WithNode(const JSTokenLocation&, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1320,7 +1324,7 @@ namespace JSC { class LabelNode : public StatementNode, public ThrowableExpressionData { public: - LabelNode(int, const Identifier& name, StatementNode*); + LabelNode(const JSTokenLocation&, const Identifier& name, StatementNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1331,7 +1335,7 @@ namespace JSC { class ThrowNode : public StatementNode, public ThrowableExpressionData { public: - ThrowNode(int, ExpressionNode*); + ThrowNode(const JSTokenLocation&, ExpressionNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1341,7 +1345,7 @@ namespace JSC { class TryNode : public StatementNode { public: - TryNode(int, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock); + TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1370,8 +1374,8 @@ namespace JSC { typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNode(JSGlobalData*, int, bool inStrictContext); - ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); + ScopeNode(JSGlobalData*, const JSTokenLocation&, bool inStrictContext); + ScopeNode(JSGlobalData*, const JSTokenLocation&, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); using ParserArenaRefCounted::operator new; @@ -1433,12 +1437,12 @@ namespace JSC { class ProgramNode : public ScopeNode { public: static const bool isFunctionNode = false; - static PassRefPtr<ProgramNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<ProgramNode> create(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); static const bool scopeIsFunction = false; private: - ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + ProgramNode(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; @@ -1446,12 +1450,12 @@ namespace JSC { class EvalNode : public ScopeNode { public: static const bool isFunctionNode = false; - static PassRefPtr<EvalNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<EvalNode> create(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); static const bool scopeIsFunction = false; private: - EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + EvalNode(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; @@ -1468,8 +1472,8 @@ namespace JSC { class FunctionBodyNode : public ScopeNode { public: static const bool isFunctionNode = true; - static FunctionBodyNode* create(JSGlobalData*, int, bool isStrictMode); - static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static FunctionBodyNode* create(JSGlobalData*, const JSTokenLocation&, bool isStrictMode); + static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); FunctionParameters* parameters() const { return m_parameters.get(); } size_t parameterCount() const { return m_parameters->size(); } @@ -1486,8 +1490,8 @@ namespace JSC { static const bool scopeIsFunction = true; private: - FunctionBodyNode(JSGlobalData*, int, bool inStrictContext); - FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + FunctionBodyNode(JSGlobalData*, const JSTokenLocation&, bool inStrictContext); + FunctionBodyNode(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); Identifier m_ident; Identifier m_inferredName; @@ -1496,7 +1500,7 @@ namespace JSC { class FuncExprNode : public ExpressionNode { public: - FuncExprNode(int, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); + FuncExprNode(const JSTokenLocation&, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); FunctionBodyNode* body() { return m_body; } @@ -1510,7 +1514,7 @@ namespace JSC { class FuncDeclNode : public StatementNode { public: - FuncDeclNode(int, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); + FuncDeclNode(const JSTokenLocation&, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); FunctionBodyNode* body() { return m_body; } @@ -1561,7 +1565,7 @@ namespace JSC { class SwitchNode : public StatementNode { public: - SwitchNode(int, ExpressionNode*, CaseBlockNode*); + SwitchNode(const JSTokenLocation&, ExpressionNode*, CaseBlockNode*); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp index 558f50e5f..4fd671fb7 100644 --- a/Source/JavaScriptCore/parser/Parser.cpp +++ b/Source/JavaScriptCore/parser/Parser.cpp @@ -138,7 +138,7 @@ template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser< bool seenNonDirective = false; const Identifier* directive = 0; unsigned directiveLiteralLength = 0; - unsigned startOffset = m_token.m_info.startOffset; + unsigned startOffset = m_token.m_location.startOffset; unsigned oldLastLineNumber = m_lexer->lastLineNumber(); unsigned oldLineNumber = m_lexer->lineNumber(); bool hasSetStrict = false; @@ -172,6 +172,7 @@ template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context) { ASSERT(match(VAR)); + JSTokenLocation location(tokenLocation()); int start = tokenLine(); int end = 0; int scratch; @@ -182,20 +183,21 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaratio failIfTrue(m_error); failIfFalse(autoSemiColon()); - return context.createVarStatement(m_lexer->lastLineNumber(), varDecls, start, end); + return context.createVarStatement(location, varDecls, start, end); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context) { ASSERT(match(CONSTTOKEN)); + JSTokenLocation location(tokenLocation()); int start = tokenLine(); int end = 0; TreeConstDeclList constDecls = parseConstDeclarationList(context); failIfTrue(m_error); failIfFalse(autoSemiColon()); - return context.createConstStatement(m_lexer->lastLineNumber(), constDecls, start, end); + return context.createConstStatement(location, constDecls, start, end); } template <typename LexerType> @@ -210,6 +212,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatem endLoop(); failIfFalse(statement); int endLine = tokenLine(); + JSTokenLocation location(tokenLocation()); consumeOrFail(WHILE); consumeOrFail(OPENPAREN); TreeExpression expr = parseExpression(context); @@ -217,13 +220,14 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatem consumeOrFail(CLOSEPAREN); if (match(SEMICOLON)) next(); // Always performs automatic semicolon insertion. - return context.createDoWhileStatement(m_lexer->lastLineNumber(), statement, expr, startLine, endLine); + return context.createDoWhileStatement(location, statement, expr, startLine, endLine); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context) { ASSERT(match(WHILE)); + JSTokenLocation location(tokenLocation()); int startLine = tokenLine(); next(); consumeOrFail(OPENPAREN); @@ -236,7 +240,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatemen TreeStatement statement = parseStatement(context, unused); endLoop(); failIfFalse(statement); - return context.createWhileStatement(m_lexer->lastLineNumber(), expr, statement, startLine, endLine); + return context.createWhileStatement(location, expr, statement, startLine, endLine); } template <typename LexerType> @@ -245,6 +249,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarati TreeExpression varDecls = 0; do { declarations++; + JSTokenLocation location(tokenLocation()); next(); matchOrFail(IDENT); @@ -265,11 +270,11 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarati lastInitializer = initializer; failIfFalse(initializer); - TreeExpression node = context.createAssignResolve(m_lexer->lastLineNumber(), *name, initializer, varStart, varDivot, lastTokenEnd()); + TreeExpression node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEnd()); if (!varDecls) varDecls = node; else - varDecls = context.combineCommaNodes(m_lexer->lastLineNumber(), varDecls, node); + varDecls = context.combineCommaNodes(location, varDecls, node); } } while (match(COMMA)); return varDecls; @@ -282,6 +287,7 @@ template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDecl TreeConstDeclList constDecls = 0; TreeConstDeclList tail = 0; do { + JSTokenLocation location(tokenLocation()); next(); matchOrFail(IDENT); const Identifier* name = m_token.m_data.ident; @@ -294,7 +300,7 @@ template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDecl next(TreeBuilder::DontBuildStrings); // consume '=' initializer = parseAssignmentExpression(context); } - tail = context.appendConstDecl(m_lexer->lastLineNumber(), tail, name, initializer); + tail = context.appendConstDecl(location, tail, name, initializer); if (!constDecls) constDecls = tail; } while (match(COMMA)); @@ -305,6 +311,7 @@ template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context) { ASSERT(match(FOR)); + JSTokenLocation location(tokenLocation()); int startLine = tokenLine(); next(); consumeOrFail(OPENPAREN); @@ -352,7 +359,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement( endLoop(); failIfFalse(statement); - return context.createForInLoop(m_lexer->lastLineNumber(), forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine); + return context.createForInLoop(location, forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine); } if (!match(SEMICOLON)) { @@ -388,7 +395,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement( TreeStatement statement = parseStatement(context, unused); endLoop(); failIfFalse(statement); - return context.createForLoop(m_lexer->lastLineNumber(), decls, condition, increment, statement, startLine, endLine); + return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine); } // For-in loop @@ -405,13 +412,14 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement( endLoop(); failIfFalse(statement); - return context.createForInLoop(m_lexer->lastLineNumber(), decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine); + return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context) { ASSERT(match(BREAK)); + JSTokenLocation location(tokenLocation()); int startCol = tokenStart(); int endCol = tokenEnd(); int startLine = tokenLine(); @@ -420,7 +428,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatemen if (autoSemiColon()) { failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement"); - return context.createBreakStatement(m_lexer->lastLineNumber(), startCol, endCol, startLine, endLine); + return context.createBreakStatement(location, startCol, endCol, startLine, endLine); } matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; @@ -429,13 +437,14 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatemen endLine = tokenLine(); next(); failIfFalse(autoSemiColon()); - return context.createBreakStatement(m_lexer->lastLineNumber(), ident, startCol, endCol, startLine, endLine); + return context.createBreakStatement(location, ident, startCol, endCol, startLine, endLine); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context) { ASSERT(match(CONTINUE)); + JSTokenLocation location(tokenLocation()); int startCol = tokenStart(); int endCol = tokenEnd(); int startLine = tokenLine(); @@ -444,7 +453,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueState if (autoSemiColon()) { failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement"); - return context.createContinueStatement(m_lexer->lastLineNumber(), startCol, endCol, startLine, endLine); + return context.createContinueStatement(location, startCol, endCol, startLine, endLine); } matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; @@ -455,13 +464,14 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueState endLine = tokenLine(); next(); failIfFalse(autoSemiColon()); - return context.createContinueStatement(m_lexer->lastLineNumber(), ident, startCol, endCol, startLine, endLine); + return context.createContinueStatement(location, ident, startCol, endCol, startLine, endLine); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context) { ASSERT(match(RETURN)); + JSTokenLocation location(tokenLocation()); failIfFalse(currentScope()->isFunction()); int startLine = tokenLine(); int endLine = startLine; @@ -474,20 +484,21 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStateme if (match(SEMICOLON)) endLine = tokenLine(); if (autoSemiColon()) - return context.createReturnStatement(m_lexer->lastLineNumber(), 0, start, end, startLine, endLine); + return context.createReturnStatement(location, 0, start, end, startLine, endLine); TreeExpression expr = parseExpression(context); failIfFalse(expr); end = lastTokenEnd(); if (match(SEMICOLON)) endLine = tokenLine(); failIfFalse(autoSemiColon()); - return context.createReturnStatement(m_lexer->lastLineNumber(), expr, start, end, startLine, endLine); + return context.createReturnStatement(location, expr, start, end, startLine, endLine); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context) { ASSERT(match(THROW)); + JSTokenLocation location(tokenLocation()); int eStart = tokenStart(); int startLine = tokenLine(); next(); @@ -500,13 +511,14 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatemen int endLine = tokenLine(); failIfFalse(autoSemiColon()); - return context.createThrowStatement(m_lexer->lastLineNumber(), expr, eStart, eEnd, startLine, endLine); + return context.createThrowStatement(location, expr, eStart, eEnd, startLine, endLine); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context) { ASSERT(match(WITH)); + JSTokenLocation location(tokenLocation()); failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode"); currentScope()->setNeedsFullActivation(); int startLine = tokenLine(); @@ -523,13 +535,14 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement TreeStatement statement = parseStatement(context, unused); failIfFalse(statement); - return context.createWithStatement(m_lexer->lastLineNumber(), expr, statement, start, end, startLine, endLine); + return context.createWithStatement(location, expr, statement, start, end, startLine, endLine); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context) { ASSERT(match(SWITCH)); + JSTokenLocation location(tokenLocation()); int startLine = tokenLine(); next(); consumeOrFail(OPENPAREN); @@ -550,7 +563,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStateme endSwitch(); consumeOrFail(CLOSEBRACE); - return context.createSwitchStatement(m_lexer->lastLineNumber(), expr, firstClauses, defaultClause, secondClauses, startLine, endLine); + return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine); } @@ -598,6 +611,7 @@ template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context) { ASSERT(match(TRY)); + JSTokenLocation location(tokenLocation()); TreeStatement tryBlock = 0; const Identifier* ident = &m_globalData->propertyNames->nullIdentifier; TreeStatement catchBlock = 0; @@ -634,37 +648,39 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement( failIfFalse(finallyBlock); } failIfFalse(catchBlock || finallyBlock); - return context.createTryStatement(m_lexer->lastLineNumber(), tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine); + return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context) { ASSERT(match(DEBUGGER)); + JSTokenLocation location(tokenLocation()); int startLine = tokenLine(); int endLine = startLine; next(); if (match(SEMICOLON)) startLine = tokenLine(); failIfFalse(autoSemiColon()); - return context.createDebugger(m_lexer->lastLineNumber(), startLine, endLine); + return context.createDebugger(location, startLine, endLine); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context) { ASSERT(match(OPENBRACE)); + JSTokenLocation location(tokenLocation()); int start = tokenLine(); next(); if (match(CLOSEBRACE)) { next(); - return context.createBlockStatement(m_lexer->lastLineNumber(), 0, start, m_lastLine); + return context.createBlockStatement(location, 0, start, m_lastLine); } TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context); failIfFalse(subtree); matchOrFail(CLOSEBRACE); next(); - return context.createBlockStatement(m_lexer->lastLineNumber(), subtree, start, m_lastLine); + return context.createBlockStatement(location, subtree, start, m_lastLine); } template <typename LexerType> @@ -685,9 +701,11 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(Tre case FUNCTION: failIfFalseIfStrictWithMessage(m_statementDepth == 1, "Functions cannot be declared in a nested block in strict mode"); return parseFunctionDeclaration(context); - case SEMICOLON: + case SEMICOLON: { + JSTokenLocation location(tokenLocation()); next(); - return context.createEmptyStatement(m_lexer->lastLineNumber()); + return context.createEmptyStatement(location); + } case IF: return parseIfStatement(context); case DO: @@ -723,7 +741,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(Tre case STRING: directive = m_token.m_data.ident; if (directiveLiteralLength) - *directiveLiteralLength = m_token.m_info.endOffset - m_token.m_info.startOffset; + *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset; nonTrivialExpressionCount = m_nonTrivialExpressionCount; default: TreeStatement exprStatement = parseExpressionStatement(context); @@ -756,12 +774,12 @@ template <typename LexerType> template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context) { if (match(CLOSEBRACE)) - return context.createFunctionBody(m_lexer->lastLineNumber(), strictMode()); + return context.createFunctionBody(tokenLocation(), strictMode()); DepthManager statementDepth(&m_statementDepth); m_statementDepth = 0; typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<JSGlobalData*>(m_globalData), m_lexer.get()); failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder)); - return context.createFunctionBody(m_lexer->lastLineNumber(), strictMode()); + return context.createFunctionBody(tokenLocation(), strictMode()); } template <typename LexerType> @@ -786,20 +804,21 @@ template <FunctionRequirements requirements, bool nameIsInContainingScope, class openBracePos = m_token.m_data.intValue; bodyStartLine = tokenLine(); + JSTokenLocation location(tokenLocation()); // If we know about this function already, we can use the cached info and skip the parser to the end of the function. if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) { // If we're in a strict context, the cached function info must say it was strict too. ASSERT(!strictMode() || cachedInfo->strictMode); - body = context.createFunctionBody(m_lexer->lastLineNumber(), cachedInfo->strictMode); + body = context.createFunctionBody(location, cachedInfo->strictMode); functionScope->restoreFunctionInfo(cachedInfo); failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); closeBracePos = cachedInfo->closeBracePos; m_token = cachedInfo->closeBraceToken(); - m_lexer->setOffset(m_token.m_info.endOffset); - m_lexer->setLineNumber(m_token.m_info.line); + m_lexer->setOffset(m_token.m_location.endOffset); + m_lexer->setLineNumber(m_token.m_location.line); next(); return true; @@ -821,7 +840,7 @@ template <FunctionRequirements requirements, bool nameIsInContainingScope, class OwnPtr<SourceProviderCacheItem> newInfo; int functionLength = closeBracePos - openBracePos; if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) { - newInfo = adoptPtr(new SourceProviderCacheItem(m_token.m_info.line, closeBracePos)); + newInfo = adoptPtr(new SourceProviderCacheItem(m_token.m_location.line, closeBracePos)); functionScope->saveFunctionInfo(newInfo.get()); } @@ -841,6 +860,7 @@ template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context) { ASSERT(match(FUNCTION)); + JSTokenLocation location(tokenLocation()); next(); const Identifier* name = 0; TreeFormalParameterList parameters = 0; @@ -851,7 +871,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDecla failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); failIfFalse(name); failIfFalseIfStrict(declareVariable(name)); - return context.createFuncDeclStatement(m_lexer->lastLineNumber(), name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + return context.createFuncDeclStatement(location, name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } struct LabelInfo { @@ -875,10 +895,11 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrL * special case that looks for a colon as the next character in the input. */ Vector<LabelInfo> labels; - + JSTokenLocation location; do { int start = tokenStart(); int startLine = tokenLine(); + location = tokenLocation(); if (!nextTokenIsColon()) { // If we hit this path we're making a expression statement, which // by definition can't make use of continue/break so we can just @@ -886,7 +907,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrL TreeExpression expression = parseExpression(context); failIfFalse(expression); failIfFalse(autoSemiColon()); - return context.createExprStatement(m_lexer->lastLineNumber(), expression, startLine, m_lastLine); + return context.createExprStatement(location, expression, startLine, m_lastLine); } const Identifier* ident = m_token.m_data.ident; int end = tokenEnd(); @@ -925,7 +946,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrL failIfFalse(statement); for (size_t i = 0; i < labels.size(); i++) { const LabelInfo& info = labels[labels.size() - i - 1]; - statement = context.createLabelStatement(m_lexer->lastLineNumber(), info.m_ident, statement, info.m_start, info.m_end); + statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end); } return statement; } @@ -934,39 +955,42 @@ template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context) { int startLine = tokenLine(); + JSTokenLocation location(tokenLocation()); TreeExpression expression = parseExpression(context); failIfFalse(expression); failIfFalse(autoSemiColon()); - return context.createExprStatement(m_lexer->lastLineNumber(), expression, startLine, m_lastLine); + return context.createExprStatement(location, expression, startLine, m_lastLine); } template <typename LexerType> template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context) { ASSERT(match(IF)); - + JSTokenLocation ifLocation(tokenLocation()); int start = tokenLine(); next(); - + consumeOrFail(OPENPAREN); - + TreeExpression condition = parseExpression(context); failIfFalse(condition); int end = tokenLine(); consumeOrFail(CLOSEPAREN); - + const Identifier* unused = 0; TreeStatement trueBlock = parseStatement(context, unused); failIfFalse(trueBlock); - + if (!match(ELSE)) - return context.createIfStatement(m_lexer->lastLineNumber(), condition, trueBlock, start, end); - + return context.createIfStatement(ifLocation, condition, trueBlock, start, end); + Vector<TreeExpression> exprStack; Vector<pair<int, int> > posStack; + Vector<JSTokenLocation> tokenLocationStack; Vector<TreeStatement> statementStack; bool trailingElse = false; do { + JSTokenLocation tempLocation = tokenLocation(); next(); if (!match(IF)) { const Identifier* unused = 0; @@ -978,21 +1002,22 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(T } int innerStart = tokenLine(); next(); - + consumeOrFail(OPENPAREN); - + TreeExpression innerCondition = parseExpression(context); failIfFalse(innerCondition); int innerEnd = tokenLine(); consumeOrFail(CLOSEPAREN); const Identifier* unused = 0; TreeStatement innerTrueBlock = parseStatement(context, unused); - failIfFalse(innerTrueBlock); + failIfFalse(innerTrueBlock); + tokenLocationStack.append(tempLocation); exprStack.append(innerCondition); posStack.append(make_pair(innerStart, innerEnd)); statementStack.append(innerTrueBlock); } while (match(ELSE)); - + if (!trailingElse) { TreeExpression condition = exprStack.last(); exprStack.removeLast(); @@ -1000,9 +1025,11 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(T statementStack.removeLast(); pair<int, int> pos = posStack.last(); posStack.removeLast(); - statementStack.append(context.createIfStatement(m_lexer->lastLineNumber(), condition, trueBlock, pos.first, pos.second)); + JSTokenLocation elseLocation = tokenLocationStack.last(); + tokenLocationStack.removeLast(); + statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, pos.first, pos.second)); } - + while (!exprStack.isEmpty()) { TreeExpression condition = exprStack.last(); exprStack.removeLast(); @@ -1012,16 +1039,19 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(T statementStack.removeLast(); pair<int, int> pos = posStack.last(); posStack.removeLast(); - statementStack.append(context.createIfStatement(m_lexer->lastLineNumber(), condition, trueBlock, falseBlock, pos.first, pos.second)); + JSTokenLocation elseLocation = tokenLocationStack.last(); + tokenLocationStack.removeLast(); + statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second)); } - - return context.createIfStatement(m_lexer->lastLineNumber(), condition, trueBlock, statementStack.last(), start, end); + + return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end); } template <typename LexerType> template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context) { failIfStackOverflow(); + JSTokenLocation location(tokenLocation()); TreeExpression node = parseAssignmentExpression(context); failIfFalse(node); if (!match(COMMA)) @@ -1031,7 +1061,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(T m_nonLHSCount++; TreeExpression right = parseAssignmentExpression(context); failIfFalse(right); - typename TreeBuilder::Comma commaNode = context.createCommaExpr(m_lexer->lastLineNumber(), node, right); + typename TreeBuilder::Comma commaNode = context.createCommaExpr(location, node, right); while (match(COMMA)) { next(TreeBuilder::DontBuildStrings); right = parseAssignmentExpression(context); @@ -1046,6 +1076,7 @@ template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmen { failIfStackOverflow(); int start = tokenStart(); + JSTokenLocation location(tokenLocation()); int initialAssignmentCount = m_assignmentCount; int initialNonLHSCount = m_nonLHSCount; TreeExpression lhs = parseConditionalExpression(context); @@ -1098,7 +1129,7 @@ end: return lhs; while (assignmentStack) - lhs = context.createAssignment(m_lexer->lastLineNumber(), assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd()); + lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd()); return lhs; } @@ -1106,6 +1137,7 @@ end: template <typename LexerType> template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context) { + JSTokenLocation location(tokenLocation()); TreeExpression cond = parseBinaryExpression(context); failIfFalse(cond); if (!match(QUESTION)) @@ -1118,7 +1150,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalE TreeExpression rhs = parseAssignmentExpression(context); failIfFalse(rhs); - return context.createConditionalExpr(m_lexer->lastLineNumber(), cond, lhs, rhs); + return context.createConditionalExpr(location, cond, lhs, rhs); } ALWAYS_INLINE static bool isUnaryOp(JSTokenType token) @@ -1141,6 +1173,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpres int operandStackDepth = 0; int operatorStackDepth = 0; typename TreeBuilder::BinaryExprContext binaryExprContext(context); + JSTokenLocation location(tokenLocation()); while (true) { int exprStart = tokenStart(); int initialAssignments = m_assignmentCount; @@ -1162,7 +1195,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpres typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1); typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2); context.shrinkOperandStackBy(operandStackDepth, 2); - context.appendBinaryOperation(m_lexer->lastLineNumber(), operandStackDepth, operatorStackDepth, lhs, rhs); + context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs); context.operatorStackPop(operatorStackDepth); } context.operatorStackAppend(operatorStackDepth, operatorToken, precedence); @@ -1173,7 +1206,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpres typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1); typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2); context.shrinkOperandStackBy(operandStackDepth, 2); - context.appendBinaryOperation(m_lexer->lastLineNumber(), operandStackDepth, operatorStackDepth, lhs, rhs); + context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs); context.operatorStackPop(operatorStackDepth); } return context.popOperandStack(operandStackDepth); @@ -1222,11 +1255,12 @@ template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::pars numericPropertyName = m_token.m_data.doubleValue; else fail(); + JSTokenLocation location(tokenLocation()); next(); failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine))); if (stringPropertyName) - return context.template createGetterOrSetterProperty<complete>(m_lexer->lastLineNumber(), type, stringPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); - return context.template createGetterOrSetterProperty<complete>(const_cast<JSGlobalData*>(m_globalData), m_lexer->lastLineNumber(), type, numericPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + return context.template createGetterOrSetterProperty<complete>(location, type, stringPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + return context.template createGetterOrSetterProperty<complete>(const_cast<JSGlobalData*>(m_globalData), location, type, numericPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } case NUMBER: { double propertyName = m_token.m_data.doubleValue; @@ -1249,12 +1283,13 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLitera unsigned oldLastLineNumber = m_lexer->lastLineNumber(); unsigned oldLineNumber = m_lexer->lineNumber(); consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings); - + JSTokenLocation location(tokenLocation()); + int oldNonLHSCount = m_nonLHSCount; if (match(CLOSEBRACE)) { next(); - return context.createObjectLiteral(m_lexer->lastLineNumber()); + return context.createObjectLiteral(location); } TreeProperty property = parseProperty<false>(context); @@ -1266,13 +1301,14 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLitera m_lexer->setLineNumber(oldLineNumber); return parseStrictObjectLiteral(context); } - TreePropertyList propertyList = context.createPropertyList(m_lexer->lastLineNumber(), property); + TreePropertyList propertyList = context.createPropertyList(location, property); TreePropertyList tail = propertyList; while (match(COMMA)) { next(TreeBuilder::DontBuildStrings); // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 if (match(CLOSEBRACE)) break; + JSTokenLocation propertyLocation(tokenLocation()); property = parseProperty<false>(context); failIfFalse(property); if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) { @@ -1282,14 +1318,15 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLitera m_lexer->setLineNumber(oldLineNumber); return parseStrictObjectLiteral(context); } - tail = context.createPropertyList(m_lexer->lastLineNumber(), property, tail); + tail = context.createPropertyList(propertyLocation, property, tail); } - + + location = tokenLocation(); consumeOrFail(CLOSEBRACE); m_nonLHSCount = oldNonLHSCount; - return context.createObjectLiteral(m_lexer->lastLineNumber(), propertyList); + return context.createObjectLiteral(location, propertyList); } template <typename LexerType> @@ -1299,9 +1336,10 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObject int oldNonLHSCount = m_nonLHSCount; + JSTokenLocation location(tokenLocation()); if (match(CLOSEBRACE)) { next(); - return context.createObjectLiteral(m_lexer->lastLineNumber()); + return context.createObjectLiteral(location); } TreeProperty property = parseProperty<true>(context); @@ -1313,13 +1351,14 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObject if (!m_syntaxAlreadyValidated) objectValidator.add(context.getName(property).impl(), context.getType(property)); - TreePropertyList propertyList = context.createPropertyList(m_lexer->lastLineNumber(), property); + TreePropertyList propertyList = context.createPropertyList(location, property); TreePropertyList tail = propertyList; while (match(COMMA)) { next(); // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 if (match(CLOSEBRACE)) break; + JSTokenLocation propertyLocation(tokenLocation()); property = parseProperty<true>(context); failIfFalse(property); if (!m_syntaxAlreadyValidated) { @@ -1331,14 +1370,15 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObject propertyEntry.iterator->second |= context.getType(property); } } - tail = context.createPropertyList(m_lexer->lastLineNumber(), property, tail); + tail = context.createPropertyList(propertyLocation, property, tail); } - + + location = tokenLocation(); consumeOrFail(CLOSEBRACE); m_nonLHSCount = oldNonLHSCount; - return context.createObjectLiteral(m_lexer->lastLineNumber(), propertyList); + return context.createObjectLiteral(location, propertyList); } template <typename LexerType> @@ -1354,8 +1394,9 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral elisions++; } if (match(CLOSEBRACKET)) { + JSTokenLocation location(tokenLocation()); next(TreeBuilder::DontBuildStrings); - return context.createArray(m_lexer->lastLineNumber(), elisions); + return context.createArray(location, elisions); } TreeExpression elem = parseAssignmentExpression(context); @@ -1373,19 +1414,21 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral } if (match(CLOSEBRACKET)) { + JSTokenLocation location(tokenLocation()); next(TreeBuilder::DontBuildStrings); - return context.createArray(m_lexer->lastLineNumber(), elisions, elementList); + return context.createArray(location, elisions, elementList); } TreeExpression elem = parseAssignmentExpression(context); failIfFalse(elem); tail = context.createElementList(tail, elisions, elem); } - + + JSTokenLocation location(tokenLocation()); consumeOrFail(CLOSEBRACKET); m_nonLHSCount = oldNonLHSCount; - return context.createArray(m_lexer->lastLineNumber(), elementList); + return context.createArray(location, elementList); } template <typename LexerType> @@ -1409,38 +1452,45 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre return result; } case THISTOKEN: { + JSTokenLocation location(tokenLocation()); next(); - return context.thisExpr(m_lexer->lastLineNumber()); + return context.thisExpr(location); } case IDENT: { int start = tokenStart(); const Identifier* ident = m_token.m_data.ident; + JSTokenLocation location(tokenLocation()); next(); currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident); m_lastIdentifier = ident; - return context.createResolve(m_lexer->lastLineNumber(), ident, start); + return context.createResolve(location, ident, start); } case STRING: { const Identifier* ident = m_token.m_data.ident; + JSTokenLocation location(tokenLocation()); next(); - return context.createString(m_lexer->lastLineNumber(), ident); + return context.createString(location, ident); } case NUMBER: { double d = m_token.m_data.doubleValue; + JSTokenLocation location(tokenLocation()); next(); - return context.createNumberExpr(m_lexer->lastLineNumber(), d); + return context.createNumberExpr(location, d); } case NULLTOKEN: { + JSTokenLocation location(tokenLocation()); next(); - return context.createNull(m_lexer->lastLineNumber()); + return context.createNull(location); } case TRUETOKEN: { + JSTokenLocation location(tokenLocation()); next(); - return context.createBoolean(m_lexer->lastLineNumber(), true); + return context.createBoolean(location, true); } case FALSETOKEN: { + JSTokenLocation location(tokenLocation()); next(); - return context.createBoolean(m_lexer->lastLineNumber(), false); + return context.createBoolean(location, false); } case DIVEQUAL: case DIVIDE: { @@ -1453,8 +1503,9 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre failIfFalse(m_lexer->scanRegExp(pattern, flags)); int start = tokenStart(); + JSTokenLocation location(tokenLocation()); next(); - TreeExpression re = context.createRegExp(m_lexer->lastLineNumber(), *pattern, *flags, start); + TreeExpression re = context.createRegExp(location, *pattern, *flags, start); if (!re) { const char* yarrErrorMsg = Yarr::checkSyntax(pattern->ustring()); ASSERT(!m_errorMessage.isNull()); @@ -1471,6 +1522,7 @@ template <typename LexerType> template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context) { consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings); + JSTokenLocation location(tokenLocation()); if (match(CLOSEPAREN)) { next(TreeBuilder::DontBuildStrings); return context.createArguments(); @@ -1478,13 +1530,14 @@ template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(Tre TreeExpression firstArg = parseAssignmentExpression(context); failIfFalse(firstArg); - TreeArgumentsList argList = context.createArgumentsList(m_lexer->lastLineNumber(), firstArg); + TreeArgumentsList argList = context.createArgumentsList(location, firstArg); TreeArgumentsList tail = argList; while (match(COMMA)) { + JSTokenLocation argumentLocation(tokenLocation()); next(TreeBuilder::DontBuildStrings); TreeExpression arg = parseAssignmentExpression(context); failIfFalse(arg); - tail = context.createArgumentsList(m_lexer->lastLineNumber(), tail, arg); + tail = context.createArgumentsList(argumentLocation, tail, arg); } consumeOrFail(CLOSEPAREN); return context.createArguments(argList); @@ -1497,6 +1550,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres int start = tokenStart(); int expressionStart = start; int newCount = 0; + JSTokenLocation location; while (match(NEW)) { next(); newCount++; @@ -1509,14 +1563,16 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres int openBracePos = 0; int closeBracePos = 0; int bodyStartLine = 0; + location = tokenLocation(); next(); failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); - base = context.createFunctionExpr(m_lexer->lastLineNumber(), name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + base = context.createFunctionExpr(location, name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } else base = parsePrimaryExpression(context); failIfFalse(base); while (true) { + location = tokenLocation(); switch (m_token.m_type) { case OPENBRACKET: { m_nonTrivialExpressionCount++; @@ -1526,7 +1582,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres int initialAssignments = m_assignmentCount; TreeExpression property = parseExpression(context); failIfFalse(property); - base = context.createBracketAccess(m_lexer->lastLineNumber(), base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd()); + base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd()); consumeOrFail(CLOSEBRACKET); m_nonLHSCount = nonLHSCount; break; @@ -1539,12 +1595,12 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres int exprEnd = lastTokenEnd(); TreeArguments arguments = parseArguments(context); failIfFalse(arguments); - base = context.createNewExpr(m_lexer->lastLineNumber(), base, arguments, start, exprEnd, lastTokenEnd()); + base = context.createNewExpr(location, base, arguments, start, exprEnd, lastTokenEnd()); } else { int expressionEnd = lastTokenEnd(); TreeArguments arguments = parseArguments(context); failIfFalse(arguments); - base = context.makeFunctionCallNode(m_lexer->lastLineNumber(), base, arguments, expressionStart, expressionEnd, lastTokenEnd()); + base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEnd()); } m_nonLHSCount = nonLHSCount; break; @@ -1554,7 +1610,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres int expressionEnd = lastTokenEnd(); nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords); matchOrFail(IDENT); - base = context.createDotAccess(m_lexer->lastLineNumber(), base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd()); + base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd()); next(); break; } @@ -1564,7 +1620,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres } endMemberExpression: while (newCount--) - base = context.createNewExpr(m_lexer->lastLineNumber(), base, start, lastTokenEnd()); + base = context.createNewExpr(location, base, start, lastTokenEnd()); return base; } @@ -1602,6 +1658,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress m_nonTrivialExpressionCount++; } int subExprStart = tokenStart(); + JSTokenLocation location(tokenLocation()); TreeExpression expr = parseMemberExpression(context); failIfFalse(expr); bool isEvalOrArguments = false; @@ -1614,7 +1671,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress case PLUSPLUS: m_nonTrivialExpressionCount++; m_nonLHSCount++; - expr = context.makePostfixNode(m_lexer->lastLineNumber(), expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd()); + expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd()); m_assignmentCount++; failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode"); failIfTrueIfStrict(requiresLExpr); @@ -1623,7 +1680,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress case MINUSMINUS: m_nonTrivialExpressionCount++; m_nonLHSCount++; - expr = context.makePostfixNode(m_lexer->lastLineNumber(), expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd()); + expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd()); m_assignmentCount++; failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode"); failIfTrueIfStrict(requiresLExpr); @@ -1637,40 +1694,42 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode())) return expr; - + + location = tokenLocation(); + location.line = m_lexer->lastLineNumber(); while (tokenStackDepth) { switch (context.unaryTokenStackLastType(tokenStackDepth)) { case EXCLAMATION: - expr = context.createLogicalNot(m_lexer->lastLineNumber(), expr); + expr = context.createLogicalNot(location, expr); break; case TILDE: - expr = context.makeBitwiseNotNode(m_lexer->lastLineNumber(), expr); + expr = context.makeBitwiseNotNode(location, expr); break; case MINUS: - expr = context.makeNegateNode(m_lexer->lastLineNumber(), expr); + expr = context.makeNegateNode(location, expr); break; case PLUS: - expr = context.createUnaryPlus(m_lexer->lastLineNumber(), expr); + expr = context.createUnaryPlus(location, expr); break; case PLUSPLUS: case AUTOPLUSPLUS: - expr = context.makePrefixNode(m_lexer->lastLineNumber(), expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end); + expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end); m_assignmentCount++; break; case MINUSMINUS: case AUTOMINUSMINUS: - expr = context.makePrefixNode(m_lexer->lastLineNumber(), expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end); + expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end); m_assignmentCount++; break; case TYPEOF: - expr = context.makeTypeOfNode(m_lexer->lastLineNumber(), expr); + expr = context.makeTypeOfNode(location, expr); break; case VOIDTOKEN: - expr = context.createVoid(m_lexer->lastLineNumber(), expr); + expr = context.createVoid(location, expr); break; case DELETETOKEN: failIfTrueIfStrictWithNameAndMessage(context.isResolve(expr), "Cannot delete unqualified property", m_lastIdentifier->impl(), "in strict mode"); - expr = context.makeDeleteNode(m_lexer->lastLineNumber(), expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end); + expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end); break; default: // If we get here something has gone horribly horribly wrong diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h index c2a11d665..79a95b696 100644 --- a/Source/JavaScriptCore/parser/Parser.h +++ b/Source/JavaScriptCore/parser/Parser.h @@ -502,18 +502,18 @@ private: ALWAYS_INLINE void next(unsigned lexerFlags = 0) { - m_lastLine = m_token.m_info.line; - m_lastTokenEnd = m_token.m_info.endOffset; + m_lastLine = m_token.m_location.line; + m_lastTokenEnd = m_token.m_location.endOffset; m_lexer->setLastLineNumber(m_lastLine); - m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info, lexerFlags, strictMode()); + m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_location, lexerFlags, strictMode()); } ALWAYS_INLINE void nextExpectIdentifier(unsigned lexerFlags = 0) { - m_lastLine = m_token.m_info.line; - m_lastTokenEnd = m_token.m_info.endOffset; + m_lastLine = m_token.m_location.line; + m_lastTokenEnd = m_token.m_location.endOffset; m_lexer->setLastLineNumber(m_lastLine); - m_token.m_type = m_lexer->lexExpectIdentifier(&m_token.m_data, &m_token.m_info, lexerFlags, strictMode()); + m_token.m_type = m_lexer->lexExpectIdentifier(&m_token.m_data, &m_token.m_location, lexerFlags, strictMode()); } ALWAYS_INLINE bool nextTokenIsColon() @@ -541,20 +541,25 @@ private: ALWAYS_INLINE int tokenStart() { - return m_token.m_info.startOffset; + return m_token.m_location.startOffset; } ALWAYS_INLINE int tokenLine() { - return m_token.m_info.line; + return m_token.m_location.line; } ALWAYS_INLINE int tokenEnd() { - return m_token.m_info.endOffset; + return m_token.m_location.endOffset; } - const char* getTokenName(JSTokenType tok) + ALWAYS_INLINE const JSTokenLocation& tokenLocation() + { + return m_token.m_location; + } + + const char* getTokenName(JSTokenType tok) { switch (tok) { case NULLTOKEN: @@ -1003,8 +1008,11 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj RefPtr<ParsedNode> result; if (m_sourceElements) { + JSTokenLocation location; + location.line = m_lexer->lastLineNumber(); + location.column = m_lexer->currentColumnNumber(); result = ParsedNode::create(&lexicalGlobalObject->globalData(), - m_lexer->lastLineNumber(), + location, m_sourceElements, m_varDeclarations ? &m_varDeclarations->data : 0, m_funcDeclarations ? &m_funcDeclarations->data : 0, @@ -1012,7 +1020,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj *m_source, m_features, m_numConstants); - result->setLoc(m_source->firstLine(), m_lastLine); + result->setLoc(m_source->firstLine(), m_lastLine, m_lexer->currentColumnNumber()); } else if (lexicalGlobalObject) { // We can never see a syntax error when reparsing a function, since we should have // reported the error when parsing the containing program or eval code. So if we're diff --git a/Source/JavaScriptCore/parser/ParserTokens.h b/Source/JavaScriptCore/parser/ParserTokens.h index a1ea751ac..6e6cec114 100644 --- a/Source/JavaScriptCore/parser/ParserTokens.h +++ b/Source/JavaScriptCore/parser/ParserTokens.h @@ -140,17 +140,25 @@ union JSTokenData { const Identifier* ident; }; -struct JSTokenInfo { - JSTokenInfo() : line(0) { } +struct JSTokenLocation { + JSTokenLocation() : line(0), column(0) { } + JSTokenLocation(const JSTokenLocation& location) + { + line = location.line; + startOffset = location.startOffset; + endOffset = location.endOffset; + column = location.column; + } int line; int startOffset; int endOffset; + int column; }; struct JSToken { JSTokenType m_type; JSTokenData m_data; - JSTokenInfo m_info; + JSTokenLocation m_location; }; enum JSParserStrictness { JSParseNormal, JSParseStrict }; diff --git a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h index 3662367a0..bfd35648e 100644 --- a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h +++ b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h @@ -53,9 +53,9 @@ public: JSToken token; token.m_type = CLOSEBRACE; token.m_data.intValue = closeBracePos; - token.m_info.startOffset = closeBracePos; - token.m_info.endOffset = closeBracePos + 1; - token.m_info.line = closeBraceLine; + token.m_location.startOffset = closeBracePos; + token.m_location.endOffset = closeBracePos + 1; + token.m_location.line = closeBraceLine; return token; } diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h index fe3ce714f..7d44ef3c6 100644 --- a/Source/JavaScriptCore/parser/SyntaxChecker.h +++ b/Source/JavaScriptCore/parser/SyntaxChecker.h @@ -119,42 +119,42 @@ public: static const unsigned DontBuildStrings = LexerFlagsDontBuildStrings; int createSourceElements() { return 1; } - ExpressionType makeFunctionCallNode(int, int, int, int, int, int) { return CallExpr; } + ExpressionType makeFunctionCallNode(const JSTokenLocation&, int, int, int, int, int) { return CallExpr; } void appendToComma(ExpressionType& base, ExpressionType right) { base = right; } - ExpressionType createCommaExpr(int, ExpressionType, ExpressionType right) { return right; } - ExpressionType makeAssignNode(int, ExpressionType, Operator, ExpressionType, bool, bool, int, int, int) { return AssignmentExpr; } - ExpressionType makePrefixNode(int, ExpressionType, Operator, int, int, int) { return PreExpr; } - ExpressionType makePostfixNode(int, ExpressionType, Operator, int, int, int) { return PostExpr; } - ExpressionType makeTypeOfNode(int, ExpressionType) { return TypeofExpr; } - ExpressionType makeDeleteNode(int, ExpressionType, int, int, int) { return DeleteExpr; } - ExpressionType makeNegateNode(int, ExpressionType) { return UnaryExpr; } - ExpressionType makeBitwiseNotNode(int, ExpressionType) { return UnaryExpr; } - ExpressionType createLogicalNot(int, ExpressionType) { return UnaryExpr; } - ExpressionType createUnaryPlus(int, ExpressionType) { return UnaryExpr; } - ExpressionType createVoid(int, ExpressionType) { return UnaryExpr; } - ExpressionType thisExpr(int) { return ThisExpr; } - ExpressionType createResolve(int, const Identifier*, int) { return ResolveExpr; } - ExpressionType createObjectLiteral(int) { return ObjectLiteralExpr; } - ExpressionType createObjectLiteral(int, int) { return ObjectLiteralExpr; } - ExpressionType createArray(int, int) { return ArrayLiteralExpr; } - ExpressionType createArray(int, int, int) { return ArrayLiteralExpr; } - ExpressionType createNumberExpr(int, double) { return NumberExpr; } - ExpressionType createString(int, const Identifier*) { return StringExpr; } - ExpressionType createBoolean(int, bool) { return BoolExpr; } - ExpressionType createNull(int) { return NullExpr; } - ExpressionType createBracketAccess(int, ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; } - ExpressionType createDotAccess(int, ExpressionType, const Identifier*, int, int, int) { return DotExpr; } - ExpressionType createRegExp(int, const Identifier& pattern, const Identifier&, int) { return Yarr::checkSyntax(pattern.ustring()) ? 0 : RegExpExpr; } - ExpressionType createNewExpr(int, ExpressionType, int, int, int, int) { return NewExpr; } - ExpressionType createNewExpr(int, ExpressionType, int, int) { return NewExpr; } - ExpressionType createConditionalExpr(int, ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; } - ExpressionType createAssignResolve(int, const Identifier&, ExpressionType, int, int, int) { return AssignmentExpr; } - ExpressionType createFunctionExpr(int, const Identifier*, int, int, int, int, int, int) { return FunctionExpr; } - int createFunctionBody(int, bool) { return 1; } + ExpressionType createCommaExpr(const JSTokenLocation&, ExpressionType, ExpressionType right) { return right; } + ExpressionType makeAssignNode(const JSTokenLocation&, ExpressionType, Operator, ExpressionType, bool, bool, int, int, int) { return AssignmentExpr; } + ExpressionType makePrefixNode(const JSTokenLocation&, ExpressionType, Operator, int, int, int) { return PreExpr; } + ExpressionType makePostfixNode(const JSTokenLocation&, ExpressionType, Operator, int, int, int) { return PostExpr; } + ExpressionType makeTypeOfNode(const JSTokenLocation&, ExpressionType) { return TypeofExpr; } + ExpressionType makeDeleteNode(const JSTokenLocation&, ExpressionType, int, int, int) { return DeleteExpr; } + ExpressionType makeNegateNode(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } + ExpressionType makeBitwiseNotNode(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } + ExpressionType createLogicalNot(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } + ExpressionType createUnaryPlus(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } + ExpressionType createVoid(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } + ExpressionType thisExpr(const JSTokenLocation&) { return ThisExpr; } + ExpressionType createResolve(const JSTokenLocation&, const Identifier*, int) { return ResolveExpr; } + ExpressionType createObjectLiteral(const JSTokenLocation&) { return ObjectLiteralExpr; } + ExpressionType createObjectLiteral(const JSTokenLocation&, int) { return ObjectLiteralExpr; } + ExpressionType createArray(const JSTokenLocation&, int) { return ArrayLiteralExpr; } + ExpressionType createArray(const JSTokenLocation&, int, int) { return ArrayLiteralExpr; } + ExpressionType createNumberExpr(const JSTokenLocation&, double) { return NumberExpr; } + ExpressionType createString(const JSTokenLocation&, const Identifier*) { return StringExpr; } + ExpressionType createBoolean(const JSTokenLocation&, bool) { return BoolExpr; } + ExpressionType createNull(const JSTokenLocation&) { return NullExpr; } + ExpressionType createBracketAccess(const JSTokenLocation&, ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; } + ExpressionType createDotAccess(const JSTokenLocation&, ExpressionType, const Identifier*, int, int, int) { return DotExpr; } + ExpressionType createRegExp(const JSTokenLocation&, const Identifier& pattern, const Identifier&, int) { return Yarr::checkSyntax(pattern.ustring()) ? 0 : RegExpExpr; } + ExpressionType createNewExpr(const JSTokenLocation&, ExpressionType, int, int, int, int) { return NewExpr; } + ExpressionType createNewExpr(const JSTokenLocation&, ExpressionType, int, int) { return NewExpr; } + ExpressionType createConditionalExpr(const JSTokenLocation&, ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; } + ExpressionType createAssignResolve(const JSTokenLocation&, const Identifier&, ExpressionType, int, int, int) { return AssignmentExpr; } + ExpressionType createFunctionExpr(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int) { return FunctionExpr; } + int createFunctionBody(const JSTokenLocation&, bool) { return 1; } int createArguments() { return 1; } int createArguments(int) { return 1; } - int createArgumentsList(int, int) { return 1; } - int createArgumentsList(int, int, int) { return 1; } + int createArgumentsList(const JSTokenLocation&, int) { return 1; } + int createArgumentsList(const JSTokenLocation&, int, int) { return 1; } template <bool complete> Property createProperty(const Identifier* name, int, PropertyNode::Type type) { if (!complete) @@ -168,8 +168,8 @@ public: return Property(type); return Property(&globalData->parserArena->identifierArena().makeNumericIdentifier(globalData, name), type); } - int createPropertyList(int, Property) { return 1; } - int createPropertyList(int, Property, int) { return 1; } + int createPropertyList(const JSTokenLocation&, Property) { return 1; } + int createPropertyList(const JSTokenLocation&, Property, int) { return 1; } int createElementList(int, int) { return 1; } int createElementList(int, int, int) { return 1; } int createFormalParameterList(const Identifier&) { return 1; } @@ -178,39 +178,39 @@ public: int createClauseList(int) { return 1; } int createClauseList(int, int) { return 1; } void setUsesArguments(int) { } - int createFuncDeclStatement(int, const Identifier*, int, int, int, int, int, int) { return 1; } - int createBlockStatement(int, int, int, int) { return 1; } - int createExprStatement(int, int, int, int) { return 1; } - int createIfStatement(int, int, int, int, int) { return 1; } - int createIfStatement(int, int, int, int, int, int) { return 1; } - int createForLoop(int, int, int, int, int, int, int) { return 1; } - int createForInLoop(int, const Identifier*, int, int, int, int, int, int, int, int, int, int) { return 1; } - int createForInLoop(int, int, int, int, int, int, int, int, int) { return 1; } - int createEmptyStatement(int) { return 1; } - int createVarStatement(int, int, int, int) { return 1; } - int createReturnStatement(int, int, int, int, int, int) { return 1; } - int createBreakStatement(int, int, int, int, int) { return 1; } - int createBreakStatement(int, const Identifier*, int, int, int, int) { return 1; } - int createContinueStatement(int, int, int, int, int) { return 1; } - int createContinueStatement(int, const Identifier*, int, int, int, int) { return 1; } - int createTryStatement(int, int, const Identifier*, int, int, int, int) { return 1; } - int createSwitchStatement(int, int, int, int, int, int, int) { return 1; } - int createWhileStatement(int, int, int, int, int) { return 1; } - int createWithStatement(int, int, int, int, int, int, int) { return 1; } - int createDoWhileStatement(int, int, int, int, int) { return 1; } - int createLabelStatement(int, const Identifier*, int, int, int) { return 1; } - int createThrowStatement(int, int, int, int, int, int) { return 1; } - int createDebugger(int, int, int) { return 1; } - int createConstStatement(int, int, int, int) { return 1; } - int appendConstDecl(int, int, const Identifier*, int) { return 1; } - template <bool strict> Property createGetterOrSetterProperty(int, PropertyNode::Type type, const Identifier* name, int, int, int, int, int, int) + int createFuncDeclStatement(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int) { return 1; } + int createBlockStatement(const JSTokenLocation&, int, int, int) { return 1; } + int createExprStatement(const JSTokenLocation&, int, int, int) { return 1; } + int createIfStatement(const JSTokenLocation&, int, int, int, int) { return 1; } + int createIfStatement(const JSTokenLocation&, int, int, int, int, int) { return 1; } + int createForLoop(const JSTokenLocation&, int, int, int, int, int, int) { return 1; } + int createForInLoop(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int, int, int, int, int) { return 1; } + int createForInLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int) { return 1; } + int createEmptyStatement(const JSTokenLocation&) { return 1; } + int createVarStatement(const JSTokenLocation&, int, int, int) { return 1; } + int createReturnStatement(const JSTokenLocation&, int, int, int, int, int) { return 1; } + int createBreakStatement(const JSTokenLocation&, int, int, int, int) { return 1; } + int createBreakStatement(const JSTokenLocation&, const Identifier*, int, int, int, int) { return 1; } + int createContinueStatement(const JSTokenLocation&, int, int, int, int) { return 1; } + int createContinueStatement(const JSTokenLocation&, const Identifier*, int, int, int, int) { return 1; } + int createTryStatement(const JSTokenLocation&, int, const Identifier*, int, int, int, int) { return 1; } + int createSwitchStatement(const JSTokenLocation&, int, int, int, int, int, int) { return 1; } + int createWhileStatement(const JSTokenLocation&, int, int, int, int) { return 1; } + int createWithStatement(const JSTokenLocation&, int, int, int, int, int, int) { return 1; } + int createDoWhileStatement(const JSTokenLocation&, int, int, int, int) { return 1; } + int createLabelStatement(const JSTokenLocation&, const Identifier*, int, int, int) { return 1; } + int createThrowStatement(const JSTokenLocation&, int, int, int, int, int) { return 1; } + int createDebugger(const JSTokenLocation&, int, int) { return 1; } + int createConstStatement(const JSTokenLocation&, int, int, int) { return 1; } + int appendConstDecl(const JSTokenLocation&, int, const Identifier*, int) { return 1; } + template <bool strict> Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, const Identifier* name, int, int, int, int, int, int) { ASSERT(name); if (!strict) return Property(type); return Property(name, type); } - template <bool strict> Property createGetterOrSetterProperty(JSGlobalData* globalData, int, PropertyNode::Type type, double name, int, int, int, int, int, int) + template <bool strict> Property createGetterOrSetterProperty(JSGlobalData* globalData, const JSTokenLocation&, PropertyNode::Type type, double name, int, int, int, int, int, int) { if (!strict) return Property(type); @@ -219,7 +219,7 @@ public: void appendStatement(int, int) { } void addVar(const Identifier*, bool) { } - int combineCommaNodes(int, int, int) { return 1; } + int combineCommaNodes(const JSTokenLocation&, int, int) { return 1; } int evalCount() const { return 0; } void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool) { @@ -235,7 +235,7 @@ public: bool operatorStackHasHigherPrecedence(int&, int) { return true; } BinaryOperand getFromOperandStack(int) { return m_topBinaryExpr; } void shrinkOperandStackBy(int& operandStackDepth, int amount) { operandStackDepth -= amount; } - void appendBinaryOperation(int, int& operandStackDepth, int&, BinaryOperand, BinaryOperand) { operandStackDepth++; } + void appendBinaryOperation(const JSTokenLocation&, int& operandStackDepth, int&, BinaryOperand, BinaryOperand) { operandStackDepth++; } void operatorStackAppend(int& operatorStackDepth, int, int) { operatorStackDepth++; } int popOperandStack(int&) { int res = m_topBinaryExpr; m_topBinaryExpr = 0; return res; } @@ -245,7 +245,7 @@ public: void unaryTokenStackRemoveLast(int& stackDepth) { stackDepth = 0; } void assignmentStackAppend(int, int, int, int, int, Operator) { } - int createAssignment(int, int, int, int, int, int) { ASSERT_NOT_REACHED(); return 1; } + int createAssignment(const JSTokenLocation&, int, int, int, int, int) { ASSERT_NOT_REACHED(); return 1; } const Identifier& getName(const Property& property) const { ASSERT(property.name); return *property.name; } PropertyNode::Type getType(const Property& property) const { return property.type; } bool isResolve(ExpressionType expr) const { return expr == ResolveExpr || expr == ResolveEvalExpr; } diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.cpp b/Source/JavaScriptCore/runtime/CommonIdentifiers.cpp index 82beda336..e929d7a49 100644 --- a/Source/JavaScriptCore/runtime/CommonIdentifiers.cpp +++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2007, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007, 2009, 2012 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,14 +23,12 @@ namespace JSC { -static const char* const nullCString = 0; - #define INITIALIZE_PROPERTY_NAME(name) , name(globalData, #name) #define INITIALIZE_KEYWORD(name) , name##Keyword(globalData, #name) CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData) - : nullIdentifier(globalData, nullCString) - , emptyIdentifier(globalData, "") + : nullIdentifier() + , emptyIdentifier(Identifier::EmptyIdentifier) , underscoreProto(globalData, "__proto__") , thisIdentifier(globalData, "this") , useStrictIdentifier(globalData, "use strict") diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp index 5984bbf97..e4f89dd37 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.cpp +++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp @@ -168,11 +168,7 @@ static EncodedJSValue JSC_HOST_CALL callDate(ExecState* exec) { GregorianDateTime ts; msToGregorianDateTime(exec, currentTimeMS(), false, ts); - DateConversionBuffer date; - DateConversionBuffer time; - formatDate(ts, date); - formatTime(ts, time); - return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time)); + return JSValue::encode(jsNontrivialString(exec, formatDateTime(ts, DateTimeFormatDateAndTime, false))); } CallType DateConstructor::getCallData(JSCell*, CallData& callData) diff --git a/Source/JavaScriptCore/runtime/DateConversion.cpp b/Source/JavaScriptCore/runtime/DateConversion.cpp index 706ffe9a2..47839817f 100644 --- a/Source/JavaScriptCore/runtime/DateConversion.cpp +++ b/Source/JavaScriptCore/runtime/DateConversion.cpp @@ -1,95 +1,127 @@ /* - * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com> * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. + * 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. * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Alternatively, the contents of this file may be used under the terms - * of either the Mozilla Public License Version 1.1, found at - * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public - * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html - * (the "GPL"), in which case the provisions of the MPL or the GPL are - * applicable instead of those above. If you wish to allow use of your - * version of this file only under the terms of one of those two - * licenses (the MPL or the GPL) and not to allow others to use your - * version of this file under the LGPL, indicate your decision by - * deletingthe provisions above and replace them with the notice and - * other provisions required by the MPL or the GPL, as the case may be. - * If you do not delete the provisions above, a recipient may use your - * version of this file under any of the LGPL, the MPL or the GPL. + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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. */ #include "config.h" #include "DateConversion.h" -#include "CallFrame.h" -#include "JSDateMath.h" -#include "JSObject.h" -#include "ScopeChain.h" #include "UString.h" -#include <wtf/StringExtras.h> -#include <wtf/text/CString.h> +#include <wtf/Assertions.h> +#include <wtf/DateMath.h> +#include <wtf/text/StringBuilder.h> + +#if OS(WINDOWS) +#include <windows.h> +#endif using namespace WTF; namespace JSC { -void formatDate(const GregorianDateTime &t, DateConversionBuffer& buffer) +template<int width> +static inline void appendNumber(StringBuilder& builder, int value) { - snprintf(buffer, DateConversionBufferSize, "%s %s %02d %04d", - weekdayName[(t.weekDay() + 6) % 7], - monthName[t.month()], t.monthDay(), t.year()); + int fillingZerosCount = width; + if (value < 0) { + builder.append('-'); + value = -value; + --fillingZerosCount; + } + String valueString = String::number(value); + fillingZerosCount -= valueString.length(); + for (int i = 0; i < fillingZerosCount; ++i) + builder.append('0'); + builder.append(valueString); } -void formatDateUTCVariant(const GregorianDateTime &t, DateConversionBuffer& buffer) +template<> +void appendNumber<2>(StringBuilder& builder, int value) { - snprintf(buffer, DateConversionBufferSize, "%s, %02d %s %04d", - weekdayName[(t.weekDay() + 6) % 7], - t.monthDay(), monthName[t.month()], t.year()); + ASSERT(0 <= value && value <= 99); + builder.append(static_cast<char>('0' + value / 10)); + builder.append(static_cast<char>('0' + value % 10)); } -void formatTime(const GregorianDateTime &t, DateConversionBuffer& buffer) +UString formatDateTime(const GregorianDateTime& t, DateTimeFormat format, bool asUTCVariant) { - int offset = abs(t.utcOffset()); - char timeZoneName[70]; - struct tm gtm = t; - strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m); - - if (timeZoneName[0]) { - snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT%c%02d%02d (%s)", - t.hour(), t.minute(), t.second(), - t.utcOffset() < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, timeZoneName); - } else { - snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT%c%02d%02d", - t.hour(), t.minute(), t.second(), - t.utcOffset() < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60); + bool appendDate = format & DateTimeFormatDate; + bool appendTime = format & DateTimeFormatTime; + + StringBuilder builder; + + if (appendDate) { + builder.append(weekdayName[(t.weekDay() + 6) % 7]); + + if (asUTCVariant) { + builder.append(", "); + appendNumber<2>(builder, t.monthDay()); + builder.append(' '); + builder.append(monthName[t.month()]); + } else { + builder.append(' '); + builder.append(monthName[t.month()]); + builder.append(' '); + appendNumber<2>(builder, t.monthDay()); + } + builder.append(' '); + appendNumber<4>(builder, t.year()); } -} -void formatTimeUTC(const GregorianDateTime &t, DateConversionBuffer& buffer) -{ - snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT", t.hour(), t.minute(), t.second()); + if (appendDate && appendTime) + builder.append(' '); + + if (appendTime) { + appendNumber<2>(builder, t.hour()); + builder.append(':'); + appendNumber<2>(builder, t.minute()); + builder.append(':'); + appendNumber<2>(builder, t.second()); + builder.append(" GMT"); + + if (!asUTCVariant) { + int offset = abs(t.utcOffset()) / 60; + builder.append(t.utcOffset() < 0 ? '-' : '+'); + appendNumber<2>(builder, offset / 60); + appendNumber<2>(builder, offset % 60); + +#if OS(WINDOWS) + TIME_ZONE_INFORMATION timeZoneInformation; + GetTimeZoneInformation(&timeZoneInformation); + const WCHAR* timeZoneName = t.isDST() ? timeZoneInformation.DaylightName : timeZoneInformation.StandardName; +#else + struct tm gtm = t; + char timeZoneName[70]; + strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m); +#endif + if (timeZoneName[0]) { + builder.append(" ("); + builder.append(timeZoneName); + builder.append(')'); + } + } + } + + return builder.toString().impl(); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/DateConversion.h b/Source/JavaScriptCore/runtime/DateConversion.h index 0b078cd34..fd1a7eb35 100644 --- a/Source/JavaScriptCore/runtime/DateConversion.h +++ b/Source/JavaScriptCore/runtime/DateConversion.h @@ -1,42 +1,25 @@ /* - * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * + * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com> + * + * 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 AND ITS CONTRIBUTORS "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 OR ITS 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 DateConversion_h @@ -46,15 +29,15 @@ namespace JSC { -class ExecState; +class UString; -static const unsigned DateConversionBufferSize = 100; -typedef char DateConversionBuffer[DateConversionBufferSize]; +enum DateTimeFormat { + DateTimeFormatDate = 1, + DateTimeFormatTime = 2, + DateTimeFormatDateAndTime = DateTimeFormatDate | DateTimeFormatTime +}; -void formatDate(const GregorianDateTime&, DateConversionBuffer&); -void formatDateUTCVariant(const GregorianDateTime&, DateConversionBuffer&); -void formatTime(const GregorianDateTime&, DateConversionBuffer&); -void formatTimeUTC(const GregorianDateTime&, DateConversionBuffer&); +UString formatDateTime(const GregorianDateTime&, DateTimeFormat, bool asUTCVariant); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp index 7cbab0497..363eec03a 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.cpp +++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp @@ -340,6 +340,23 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, doubl #endif // !PLATFORM(MAC) && !PLATFORM(IOS) +static EncodedJSValue formateDateInstance(ExecState* exec, DateTimeFormat format, bool asUTCVariant) +{ + JSValue thisValue = exec->hostThisValue(); + if (!thisValue.inherits(&DateInstance::s_info)) + return throwVMTypeError(exec); + + DateInstance* thisDateObj = asDateInstance(thisValue); + + const GregorianDateTime* gregorianDateTime = asUTCVariant + ? thisDateObj->gregorianDateTimeUTC(exec) + : thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return JSValue::encode(jsNontrivialString(exec, "Invalid Date")); + + return JSValue::encode(jsNontrivialString(exec, formatDateTime(*gregorianDateTime, format, asUTCVariant))); +} + // Converts a list of arguments sent to a Date member function into milliseconds, updating // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately. // @@ -513,38 +530,14 @@ bool DatePrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, EncodedJSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); - if (!thisValue.inherits(&DateInstance::s_info)) - return throwVMTypeError(exec); - - DateInstance* thisDateObj = asDateInstance(thisValue); - - const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); - if (!gregorianDateTime) - return JSValue::encode(jsNontrivialString(exec, "Invalid Date")); - DateConversionBuffer date; - DateConversionBuffer time; - formatDate(*gregorianDateTime, date); - formatTime(*gregorianDateTime, time); - return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time)); + const bool asUTCVariant = false; + return formateDateInstance(exec, DateTimeFormatDateAndTime, asUTCVariant); } EncodedJSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); - if (!thisValue.inherits(&DateInstance::s_info)) - return throwVMTypeError(exec); - - DateInstance* thisDateObj = asDateInstance(thisValue); - - const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); - if (!gregorianDateTime) - return JSValue::encode(jsNontrivialString(exec, "Invalid Date")); - DateConversionBuffer date; - DateConversionBuffer time; - formatDateUTCVariant(*gregorianDateTime, date); - formatTimeUTC(*gregorianDateTime, time); - return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time)); + const bool asUTCVariant = true; + return formateDateInstance(exec, DateTimeFormatDateAndTime, asUTCVariant); } EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec) @@ -577,34 +570,14 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec) EncodedJSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); - if (!thisValue.inherits(&DateInstance::s_info)) - return throwVMTypeError(exec); - - DateInstance* thisDateObj = asDateInstance(thisValue); - - const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); - if (!gregorianDateTime) - return JSValue::encode(jsNontrivialString(exec, "Invalid Date")); - DateConversionBuffer date; - formatDate(*gregorianDateTime, date); - return JSValue::encode(jsNontrivialString(exec, date)); + const bool asUTCVariant = false; + return formateDateInstance(exec, DateTimeFormatDate, asUTCVariant); } EncodedJSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); - if (!thisValue.inherits(&DateInstance::s_info)) - return throwVMTypeError(exec); - - DateInstance* thisDateObj = asDateInstance(thisValue); - - const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); - if (!gregorianDateTime) - return JSValue::encode(jsNontrivialString(exec, "Invalid Date")); - DateConversionBuffer time; - formatTime(*gregorianDateTime, time); - return JSValue::encode(jsNontrivialString(exec, time)); + const bool asUTCVariant = false; + return formateDateInstance(exec, DateTimeFormatTime, asUTCVariant); } EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec) @@ -676,20 +649,8 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec) EncodedJSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); - if (!thisValue.inherits(&DateInstance::s_info)) - return throwVMTypeError(exec); - - DateInstance* thisDateObj = asDateInstance(thisValue); - - const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); - if (!gregorianDateTime) - return JSValue::encode(jsNontrivialString(exec, "Invalid Date")); - DateConversionBuffer date; - DateConversionBuffer time; - formatDateUTCVariant(*gregorianDateTime, date); - formatTimeUTC(*gregorianDateTime, time); - return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time)); + const bool asUTCVariant = true; + return formateDateInstance(exec, DateTimeFormatDateAndTime, asUTCVariant); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp index c052c61ba..35b992567 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp @@ -25,8 +25,6 @@ namespace JSC { -static const size_t bytesWorthGC = 4 * 1024 * 1024; - DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap) : GCActivityCallback(heap->globalData()) { @@ -40,7 +38,7 @@ void DefaultGCActivityCallback::doWork() void DefaultGCActivityCallback::didAllocate(size_t bytesAllocated) { - if (bytesAllocated < bytesWorthGC || m_timer.started()) + if (m_timer.started()) return; // Try using ~5% CPU time. diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp index 20770928c..0fc54f3c6 100644 --- a/Source/JavaScriptCore/runtime/Identifier.cpp +++ b/Source/JavaScriptCore/runtime/Identifier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2012 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -46,10 +46,10 @@ void deleteIdentifierTable(IdentifierTable* table) delete table; } -struct IdentifierCStringTranslator { +struct IdentifierASCIIStringTranslator { static unsigned hash(const LChar* c) { - return StringHasher::computeHash<LChar>(c); + return StringHasher::computeHashAndMaskTop8Bits<LChar>(c); } static bool equal(StringImpl* r, const LChar* s) @@ -60,19 +60,15 @@ struct IdentifierCStringTranslator { static void translate(StringImpl*& location, const LChar* c, unsigned hash) { size_t length = strlen(reinterpret_cast<const char*>(c)); - LChar* d; - StringImpl* r = StringImpl::createUninitialized(length, d).leakRef(); - for (size_t i = 0; i != length; i++) - d[i] = c[i]; - r->setHash(hash); - location = r; + location = StringImpl::createFromLiteral(reinterpret_cast<const char*>(c), length).leakRef(); + location->setHash(hash); } }; struct IdentifierLCharFromUCharTranslator { static unsigned hash(const CharBuffer<UChar>& buf) { - return StringHasher::computeHash<UChar>(buf.s, buf.length); + return StringHasher::computeHashAndMaskTop8Bits<UChar>(buf.s, buf.length); } static bool equal(StringImpl* str, const CharBuffer<UChar>& buf) @@ -96,10 +92,8 @@ struct IdentifierLCharFromUCharTranslator { PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c) { - if (!c) - return 0; - if (!c[0]) - return StringImpl::empty(); + ASSERT(c); + ASSERT(c[0]); if (!c[1]) return add(globalData, globalData->smallStrings.singleCharacterStringRep(c[0])); @@ -110,7 +104,7 @@ PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c) if (iter != literalIdentifierTable.end()) return iter->second; - HashSet<StringImpl*>::AddResult addResult = identifierTable.add<const LChar*, IdentifierCStringTranslator>(reinterpret_cast<const LChar*>(c)); + HashSet<StringImpl*>::AddResult addResult = identifierTable.add<const LChar*, IdentifierASCIIStringTranslator>(reinterpret_cast<const LChar*>(c)); // If the string is newly-translated, then we need to adopt it. // The boolean in the pair tells us if that is so. diff --git a/Source/JavaScriptCore/runtime/Identifier.h b/Source/JavaScriptCore/runtime/Identifier.h index 7b7907983..196fdca23 100644 --- a/Source/JavaScriptCore/runtime/Identifier.h +++ b/Source/JavaScriptCore/runtime/Identifier.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -35,12 +35,18 @@ namespace JSC { friend class Structure; public: Identifier() { } + enum EmptyIdentifierFlag { EmptyIdentifier }; + Identifier(EmptyIdentifierFlag) : m_string(StringImpl::empty()) { } - Identifier(ExecState* exec, const char* s) : m_string(add(exec, s)) { } // Only to be used with string literals. - Identifier(ExecState* exec, StringImpl* rep) : m_string(add(exec, rep)) { } + // Only to be used with string literals. + template<unsigned charactersCount> + Identifier(ExecState* exec, const char (&characters)[charactersCount]) : m_string(add(exec, characters)) { } + template<unsigned charactersCount> + Identifier(JSGlobalData* globalData, const char (&characters)[charactersCount]) : m_string(add(globalData, characters)) { } + + Identifier(ExecState* exec, StringImpl* rep) : m_string(add(exec, rep)) { } Identifier(ExecState* exec, const UString& s) : m_string(add(exec, s.impl())) { } - Identifier(JSGlobalData* globalData, const char* s) : m_string(add(globalData, s)) { } // Only to be used with string literals. Identifier(JSGlobalData* globalData, const LChar* s, int length) : m_string(add(globalData, s, length)) { } Identifier(JSGlobalData* globalData, const UChar* s, int length) : m_string(add(globalData, s, length)) { } Identifier(JSGlobalData* globalData, StringImpl* rep) : m_string(add(globalData, rep)) { } @@ -80,8 +86,9 @@ namespace JSC { static bool equal(const StringImpl*, const UChar*, unsigned length); static bool equal(const StringImpl* a, const StringImpl* b) { return ::equal(a, b); } - JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(ExecState*, const char*); // Only to be used with string literals. - static PassRefPtr<StringImpl> add(JSGlobalData*, const char*); // Only to be used with string literals. + // Only to be used with string literals. + static PassRefPtr<StringImpl> add(JSGlobalData*, const char*); + JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(ExecState*, const char*); private: UString m_string; @@ -143,7 +150,7 @@ namespace JSC { struct IdentifierCharBufferTranslator { static unsigned hash(const CharBuffer<T>& buf) { - return StringHasher::computeHash<T>(buf.s, buf.length); + return StringHasher::computeHashAndMaskTop8Bits<T>(buf.s, buf.length); } static bool equal(StringImpl* str, const CharBuffer<T>& buf) diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index cdd409706..90e531cec 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -192,11 +192,6 @@ namespace JSC { return m_structure.get(); } - inline const ClassInfo* JSCell::classInfo() const - { - return m_classInfo; - } - inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor) { MARK_LOG_PARENT(visitor, cell); diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index dd05005c7..2d6d1e54f 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -223,9 +223,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread JSGlobalData::~JSGlobalData() { ASSERT(!m_apiLock.currentThreadIsHoldingLock()); - heap.activityCallback()->didStartVMShutdown(); - heap.sweeper()->didStartVMShutdown(); - heap.lastChanceToFinalize(); + heap.didStartVMShutdown(); delete interpreter; #ifndef NDEBUG diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h index 0a55bda6b..ab3f34bb6 100644 --- a/Source/JavaScriptCore/runtime/Options.h +++ b/Source/JavaScriptCore/runtime/Options.h @@ -109,6 +109,7 @@ namespace JSC { v(double, desiredProfileFullnessRate, 0.35) \ \ v(double, doubleVoteRatioForDoubleFormat, 2) \ + v(double, structureCheckVoteRatioForHoisting, 1) \ \ v(unsigned, minimumNumberOfScansBetweenRebalance, 100) \ v(unsigned, gcMarkStackSegmentSize, pageSize()) \ diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index 8e41781e2..ee0b573d9 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -602,6 +602,15 @@ namespace JSC { ASSERT(m_structure || !globalData.structureStructure); } + inline const ClassInfo* JSCell::classInfo() const + { +#if ENABLE(GC_VALIDATION) + return m_structure.unvalidatedGet()->classInfo(); +#else + return m_structure->classInfo(); +#endif + } + } // namespace JSC #endif // Structure_h diff --git a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp index 8f3d1a578..56d6d4b71 100644 --- a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp +++ b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp @@ -80,6 +80,11 @@ static inline unsigned getCPUTime() GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime); return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000; +#elif OS(QNX) + struct timespec time; + if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time)) + CRASH(); + return time.tv_sec * 1000.0 + time.tv_nsec / 1.0e6; #else // FIXME: We should return the time the current thread has spent executing. |