Commit 5930185c authored by oliver@apple.com's avatar oliver@apple.com

2010-10-01 Oliver Hunt <oliver@apple.com>

        Reviewed by Gavin Barraclough.

        [ES5] Implement strict mode
        https://bugs.webkit.org/show_bug.cgi?id=10701

        Initial strict mode implementation.  This is the simplest
        implementation that could possibly work and adds (hopefully)
        all of the restrictions required by strict mode.  There are
        a number of inefficiencies, especially in the handling of
        arguments and eval as smart implementations would make this
        patch more complicated.

        The SyntaxChecker AST builder has become somewhat more complex
        as strict mode does require more parse tree information to
        validate the syntax.

        Summary of major changes to the parser:
            * We track when we enter strict mode (this may come as a surprise)
            * Strict mode actually requires a degree of AST knowledge to validate
              so the SyntaxChecker now produces values that can be used to distinguish
              "node" types.
            * We now track variables that are written to.  We do this to
              statically identify writes to global properties that don't exist
              and abort at that point.  This should actually make it possible
              to optimise some other cases in the future but for now it's
              purely for validity checking.  Currently writes are only tracked
              in strict mode code.
            * Labels are now tracked as it is now a syntax error to jump to a label
              that does not exist (or to use break, continue, or return in a context
              where they would be invalid).

        Runtime changes:
            * In order to get correct hanlding of the Arguments object all
              strict mode functions that reference arguments create and tearoff
              the arguments object on entry.  This is not strictly necessary
              but was the least work necessary to get the correct behaviour.
            * PutPropertySlot now tracks whether it is being used for a strict
              mode write, and if so Object::put will throw when a write can't be
              completed.
            * StrictEvalActivation was added as an "activation" object for strict
              mode eval (so that strict eval does not introduce new variables into
              the containing scope).

        * CMakeLists.txt:
        * GNUmakefile.am:
        * JavaScriptCore.exp:
        * JavaScriptCore.pro:
        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
        * JavaScriptCore.xcodeproj/project.pbxproj:
        * bytecode/CodeBlock.cpp:
        (JSC::CodeBlock::dump):
        (JSC::CodeBlock::CodeBlock):
        (JSC::CodeBlock::reparseForExceptionInfoIfNecessary):
        * bytecode/CodeBlock.h:
        (JSC::CodeBlock::isStrictMode):
        * bytecode/EvalCodeCache.h:
        (JSC::EvalCodeCache::get):
        * bytecode/Opcode.h:
        * bytecompiler/BytecodeGenerator.cpp:
        (JSC::BytecodeGenerator::BytecodeGenerator):
        (JSC::BytecodeGenerator::createArgumentsIfNecessary):
        (JSC::BytecodeGenerator::emitReturn):
        * bytecompiler/BytecodeGenerator.h:
        (JSC::BytecodeGenerator::isStrictMode):
        (JSC::BytecodeGenerator::makeFunction):
        * debugger/Debugger.cpp:
        (JSC::evaluateInGlobalCallFrame):
        * debugger/DebuggerCallFrame.cpp:
        (JSC::DebuggerCallFrame::evaluate):
        * interpreter/Interpreter.cpp:
        (JSC::Interpreter::callEval):
        (JSC::Interpreter::unwindCallFrame):
        (JSC::Interpreter::execute):
        (JSC::Interpreter::privateExecute):
        * jit/JIT.cpp:
        (JSC::JIT::privateCompileMainPass):
        (JSC::JIT::privateCompileSlowCases):
        * jit/JIT.h:
        * jit/JITOpcodes.cpp:
        (JSC::JIT::emit_op_get_pnames):
        (JSC::JIT::emit_op_convert_this_strict):
        (JSC::JIT::emitSlow_op_convert_this_strict):
        * jit/JITOpcodes32_64.cpp:
        (JSC::JIT::emit_op_get_pnames):
        * jit/JITStubs.cpp:
        (JSC::DEFINE_STUB_FUNCTION):
        * jit/JITStubs.h:
        * parser/ASTBuilder.h:
        (JSC::ASTBuilder::createFunctionBody):
        (JSC::ASTBuilder::isResolve):
        * parser/JSParser.cpp:
        (JSC::JSParser::next):
        (JSC::JSParser::startLoop):
        (JSC::JSParser::endLoop):
        (JSC::JSParser::startSwitch):
        (JSC::JSParser::endSwitch):
        (JSC::JSParser::setStrictMode):
        (JSC::JSParser::strictMode):
        (JSC::JSParser::isValidStrictMode):
        (JSC::JSParser::declareParameter):
        (JSC::JSParser::breakIsValid):
        (JSC::JSParser::pushLabel):
        (JSC::JSParser::popLabel):
        (JSC::JSParser::hasLabel):
        (JSC::JSParser::DepthManager::DepthManager):
        (JSC::JSParser::DepthManager::~DepthManager):
        (JSC::JSParser::Scope::Scope):
        (JSC::JSParser::Scope::startSwitch):
        (JSC::JSParser::Scope::endSwitch):
        (JSC::JSParser::Scope::startLoop):
        (JSC::JSParser::Scope::endLoop):
        (JSC::JSParser::Scope::inLoop):
        (JSC::JSParser::Scope::breakIsValid):
        (JSC::JSParser::Scope::pushLabel):
        (JSC::JSParser::Scope::popLabel):
        (JSC::JSParser::Scope::hasLabel):
        (JSC::JSParser::Scope::isFunction):
        (JSC::JSParser::Scope::declareVariable):
        (JSC::JSParser::Scope::declareWrite):
        (JSC::JSParser::Scope::deleteProperty):
        (JSC::JSParser::Scope::declareParameter):
        (JSC::JSParser::Scope::setNeedsFullActivation):
        (JSC::JSParser::Scope::collectFreeVariables):
        (JSC::JSParser::Scope::getUncapturedWrittenVariables):
        (JSC::JSParser::Scope::getDeletedVariables):
        (JSC::JSParser::Scope::setStrictMode):
        (JSC::JSParser::Scope::strictMode):
        (JSC::JSParser::Scope::isValidStrictMode):
        (JSC::JSParser::pushScope):
        (JSC::JSParser::popScope):
        (JSC::JSParser::declareVariable):
        (JSC::JSParser::declareWrite):
        (JSC::JSParser::deleteProperty):
        (JSC::jsParse):
        (JSC::JSParser::JSParser):
        (JSC::JSParser::parseProgram):
        (JSC::JSParser::parseSourceElements):
        (JSC::JSParser::parseDoWhileStatement):
        (JSC::JSParser::parseWhileStatement):
        (JSC::JSParser::parseVarDeclarationList):
        (JSC::JSParser::parseConstDeclarationList):
        (JSC::JSParser::parseForStatement):
        (JSC::JSParser::parseBreakStatement):
        (JSC::JSParser::parseContinueStatement):
        (JSC::JSParser::parseReturnStatement):
        (JSC::JSParser::parseWithStatement):
        (JSC::JSParser::parseSwitchStatement):
        (JSC::JSParser::parseSwitchClauses):
        (JSC::JSParser::parseSwitchDefaultClause):
        (JSC::JSParser::parseTryStatement):
        (JSC::JSParser::parseBlockStatement):
        (JSC::JSParser::parseStatement):
        (JSC::JSParser::parseFormalParameters):
        (JSC::JSParser::parseFunctionBody):
        (JSC::JSParser::parseFunctionInfo):
        (JSC::JSParser::parseFunctionDeclaration):
        (JSC::JSParser::parseExpressionOrLabelStatement):
        (JSC::JSParser::parseIfStatement):
        (JSC::JSParser::parseExpression):
        (JSC::JSParser::parseAssignmentExpression):
        (JSC::JSParser::parseConditionalExpression):
        (JSC::JSParser::parseBinaryExpression):
        (JSC::JSParser::parseStrictObjectLiteral):
        (JSC::JSParser::parsePrimaryExpression):
        (JSC::JSParser::parseMemberExpression):
        (JSC::JSParser::parseUnaryExpression):
        * parser/JSParser.h:
        * parser/Lexer.cpp:
        (JSC::Lexer::parseString):
        (JSC::Lexer::lex):
        * parser/Lexer.h:
        (JSC::Lexer::isReparsing):
        * parser/Nodes.cpp:
        (JSC::ScopeNode::ScopeNode):
        (JSC::FunctionBodyNode::FunctionBodyNode):
        (JSC::FunctionBodyNode::create):
        * parser/Nodes.h:
        (JSC::ScopeNode::isStrictMode):
        * parser/Parser.cpp:
        (JSC::Parser::parse):
        * parser/Parser.h:
        (JSC::Parser::parse):
        * parser/SyntaxChecker.h:
        (JSC::SyntaxChecker::SyntaxChecker):
        (JSC::SyntaxChecker::makeFunctionCallNode):
        (JSC::SyntaxChecker::appendToComma):
        (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::createRegex):
        (JSC::SyntaxChecker::createNewExpr):
        (JSC::SyntaxChecker::createConditionalExpr):
        (JSC::SyntaxChecker::createAssignResolve):
        (JSC::SyntaxChecker::createFunctionExpr):
        (JSC::SyntaxChecker::createFunctionBody):
        (JSC::SyntaxChecker::appendBinaryExpressionInfo):
        (JSC::SyntaxChecker::operatorStackPop):
        * runtime/Arguments.cpp:
        (JSC::Arguments::createStrictModeCallerIfNecessary):
        (JSC::Arguments::createStrictModeCalleeIfNecessary):
        (JSC::Arguments::getOwnPropertySlot):
        (JSC::Arguments::getOwnPropertyDescriptor):
        (JSC::Arguments::put):
        (JSC::Arguments::deleteProperty):
        * runtime/Arguments.h:
        (JSC::Arguments::Arguments):
        * runtime/CommonIdentifiers.cpp:
        (JSC::CommonIdentifiers::CommonIdentifiers):
        * runtime/CommonIdentifiers.h:
        * runtime/Error.cpp:
        (JSC::StrictModeTypeErrorFunction::StrictModeTypeErrorFunction):
        (JSC::StrictModeTypeErrorFunction::constructThrowTypeError):
        (JSC::StrictModeTypeErrorFunction::getConstructData):
        (JSC::StrictModeTypeErrorFunction::callThrowTypeError):
        (JSC::StrictModeTypeErrorFunction::getCallData):
        (JSC::createTypeErrorFunction):
        * runtime/Error.h:
        * runtime/Executable.cpp:
        (JSC::EvalExecutable::EvalExecutable):
        (JSC::ProgramExecutable::ProgramExecutable):
        (JSC::FunctionExecutable::FunctionExecutable):
        (JSC::EvalExecutable::compileInternal):
        (JSC::ProgramExecutable::checkSyntax):
        (JSC::ProgramExecutable::compileInternal):
        (JSC::FunctionExecutable::compileForCallInternal):
        (JSC::FunctionExecutable::compileForConstructInternal):
        (JSC::FunctionExecutable::reparseExceptionInfo):
        (JSC::EvalExecutable::reparseExceptionInfo):
        (JSC::FunctionExecutable::fromGlobalCode):
        (JSC::ProgramExecutable::reparseExceptionInfo):
        * runtime/Executable.h:
        (JSC::ScriptExecutable::ScriptExecutable):
        (JSC::ScriptExecutable::isStrictMode):
        (JSC::EvalExecutable::create):
        (JSC::FunctionExecutable::create):
        * runtime/JSActivation.cpp:
        (JSC::JSActivation::toStrictThisObject):
        * runtime/JSActivation.h:
        * runtime/JSFunction.cpp:
        (JSC::createDescriptorForThrowingProperty):
        (JSC::JSFunction::getOwnPropertySlot):
        (JSC::JSFunction::getOwnPropertyDescriptor):
        (JSC::JSFunction::put):
        * runtime/JSGlobalData.cpp:
        (JSC::JSGlobalData::JSGlobalData):
        * runtime/JSGlobalData.h:
        * runtime/JSGlobalObject.cpp:
        (JSC::JSGlobalObject::reset):
        * runtime/JSGlobalObject.h:
        (JSC::JSGlobalObject::internalFunctionStructure):
        * runtime/JSGlobalObjectFunctions.cpp:
        (JSC::globalFuncEval):
        * runtime/JSObject.cpp:
        (JSC::JSObject::put):
        (JSC::JSObject::toStrictThisObject):
        (JSC::throwTypeError):
        * runtime/JSObject.h:
        (JSC::JSObject::isStrictModeFunction):
        (JSC::JSObject::putDirectInternal):
        (JSC::JSObject::putDirect):
        (JSC::JSValue::putDirect):
        (JSC::JSValue::toStrictThisObject):
        * runtime/JSStaticScopeObject.cpp:
        (JSC::JSStaticScopeObject::toStrictThisObject):
        * runtime/JSStaticScopeObject.h:
        * runtime/JSValue.h:
        * runtime/JSZombie.h:
        (JSC::JSZombie::toStrictThisObject):
        * runtime/PutPropertySlot.h:
        (JSC::PutPropertySlot::PutPropertySlot):
        (JSC::PutPropertySlot::isStrictMode):
        * runtime/StrictEvalActivation.cpp: Added.
        (JSC::StrictEvalActivation::StrictEvalActivation):
        (JSC::StrictEvalActivation::deleteProperty):
        (JSC::StrictEvalActivation::toThisObject):
        (JSC::StrictEvalActivation::toStrictThisObject):
        * runtime/StrictEvalActivation.h: Added.
2010-10-01  Oliver Hunt  <oliver@apple.com>

        Reviewed by Gavin Barraclough.

        [ES5] Implement strict mode
        https://bugs.webkit.org/show_bug.cgi?id=10701

        Tests for the many different behaviours we get in strict mode.

        * fast/js/basic-strict-mode-expected.txt: Added.
        * fast/js/basic-strict-mode.html: Added.
        * fast/js/script-tests/basic-strict-mode.js: Added.
        (testThis):
        (testGlobalAccess):
2010-10-01  Oliver Hunt  <oliver@apple.com>

        Reviewed by Gavin Barraclough.

        [ES5] Implement strict mode
        https://bugs.webkit.org/show_bug.cgi?id=10701

        Test: fast/js/basic-strict-mode.html

        Override toStrictThisObject on the domwindow so that
        it correctly provides the shell object when used as this
        in a strict mode function.

        * bindings/js/JSDOMWindowBase.cpp:
        (WebCore::JSDOMWindowBase::toStrictThisObject):
        * bindings/js/JSDOMWindowBase.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@69516 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 35f4ae58
......@@ -157,6 +157,7 @@ SET(JavaScriptCore_SOURCES
runtime/RopeImpl.cpp
runtime/ScopeChain.cpp
runtime/SmallStrings.cpp
runtime/StrictEvalActivation.cpp
runtime/StringConstructor.cpp
runtime/StringObject.cpp
runtime/StringPrototype.cpp
......
2010-10-01 Oliver Hunt <oliver@apple.com>
Reviewed by Gavin Barraclough.
[ES5] Implement strict mode
https://bugs.webkit.org/show_bug.cgi?id=10701
Initial strict mode implementation. This is the simplest
implementation that could possibly work and adds (hopefully)
all of the restrictions required by strict mode. There are
a number of inefficiencies, especially in the handling of
arguments and eval as smart implementations would make this
patch more complicated.
The SyntaxChecker AST builder has become somewhat more complex
as strict mode does require more parse tree information to
validate the syntax.
Summary of major changes to the parser:
* We track when we enter strict mode (this may come as a surprise)
* Strict mode actually requires a degree of AST knowledge to validate
so the SyntaxChecker now produces values that can be used to distinguish
"node" types.
* We now track variables that are written to. We do this to
statically identify writes to global properties that don't exist
and abort at that point. This should actually make it possible
to optimise some other cases in the future but for now it's
purely for validity checking. Currently writes are only tracked
in strict mode code.
* Labels are now tracked as it is now a syntax error to jump to a label
that does not exist (or to use break, continue, or return in a context
where they would be invalid).
Runtime changes:
* In order to get correct hanlding of the Arguments object all
strict mode functions that reference arguments create and tearoff
the arguments object on entry. This is not strictly necessary
but was the least work necessary to get the correct behaviour.
* PutPropertySlot now tracks whether it is being used for a strict
mode write, and if so Object::put will throw when a write can't be
completed.
* StrictEvalActivation was added as an "activation" object for strict
mode eval (so that strict eval does not introduce new variables into
the containing scope).
* CMakeLists.txt:
* GNUmakefile.am:
* JavaScriptCore.exp:
* JavaScriptCore.pro:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dump):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::reparseForExceptionInfoIfNecessary):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::isStrictMode):
* bytecode/EvalCodeCache.h:
(JSC::EvalCodeCache::get):
* bytecode/Opcode.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::createArgumentsIfNecessary):
(JSC::BytecodeGenerator::emitReturn):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::isStrictMode):
(JSC::BytecodeGenerator::makeFunction):
* debugger/Debugger.cpp:
(JSC::evaluateInGlobalCallFrame):
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::evaluate):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::callEval):
(JSC::Interpreter::unwindCallFrame):
(JSC::Interpreter::execute):
(JSC::Interpreter::privateExecute):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_get_pnames):
(JSC::JIT::emit_op_convert_this_strict):
(JSC::JIT::emitSlow_op_convert_this_strict):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_get_pnames):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* jit/JITStubs.h:
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createFunctionBody):
(JSC::ASTBuilder::isResolve):
* parser/JSParser.cpp:
(JSC::JSParser::next):
(JSC::JSParser::startLoop):
(JSC::JSParser::endLoop):
(JSC::JSParser::startSwitch):
(JSC::JSParser::endSwitch):
(JSC::JSParser::setStrictMode):
(JSC::JSParser::strictMode):
(JSC::JSParser::isValidStrictMode):
(JSC::JSParser::declareParameter):
(JSC::JSParser::breakIsValid):
(JSC::JSParser::pushLabel):
(JSC::JSParser::popLabel):
(JSC::JSParser::hasLabel):
(JSC::JSParser::DepthManager::DepthManager):
(JSC::JSParser::DepthManager::~DepthManager):
(JSC::JSParser::Scope::Scope):
(JSC::JSParser::Scope::startSwitch):
(JSC::JSParser::Scope::endSwitch):
(JSC::JSParser::Scope::startLoop):
(JSC::JSParser::Scope::endLoop):
(JSC::JSParser::Scope::inLoop):
(JSC::JSParser::Scope::breakIsValid):
(JSC::JSParser::Scope::pushLabel):
(JSC::JSParser::Scope::popLabel):
(JSC::JSParser::Scope::hasLabel):
(JSC::JSParser::Scope::isFunction):
(JSC::JSParser::Scope::declareVariable):
(JSC::JSParser::Scope::declareWrite):
(JSC::JSParser::Scope::deleteProperty):
(JSC::JSParser::Scope::declareParameter):
(JSC::JSParser::Scope::setNeedsFullActivation):
(JSC::JSParser::Scope::collectFreeVariables):
(JSC::JSParser::Scope::getUncapturedWrittenVariables):
(JSC::JSParser::Scope::getDeletedVariables):
(JSC::JSParser::Scope::setStrictMode):
(JSC::JSParser::Scope::strictMode):
(JSC::JSParser::Scope::isValidStrictMode):
(JSC::JSParser::pushScope):
(JSC::JSParser::popScope):
(JSC::JSParser::declareVariable):
(JSC::JSParser::declareWrite):
(JSC::JSParser::deleteProperty):
(JSC::jsParse):
(JSC::JSParser::JSParser):
(JSC::JSParser::parseProgram):
(JSC::JSParser::parseSourceElements):
(JSC::JSParser::parseDoWhileStatement):
(JSC::JSParser::parseWhileStatement):
(JSC::JSParser::parseVarDeclarationList):
(JSC::JSParser::parseConstDeclarationList):
(JSC::JSParser::parseForStatement):
(JSC::JSParser::parseBreakStatement):
(JSC::JSParser::parseContinueStatement):
(JSC::JSParser::parseReturnStatement):
(JSC::JSParser::parseWithStatement):
(JSC::JSParser::parseSwitchStatement):
(JSC::JSParser::parseSwitchClauses):
(JSC::JSParser::parseSwitchDefaultClause):
(JSC::JSParser::parseTryStatement):
(JSC::JSParser::parseBlockStatement):
(JSC::JSParser::parseStatement):
(JSC::JSParser::parseFormalParameters):
(JSC::JSParser::parseFunctionBody):
(JSC::JSParser::parseFunctionInfo):
(JSC::JSParser::parseFunctionDeclaration):
(JSC::JSParser::parseExpressionOrLabelStatement):
(JSC::JSParser::parseIfStatement):
(JSC::JSParser::parseExpression):
(JSC::JSParser::parseAssignmentExpression):
(JSC::JSParser::parseConditionalExpression):
(JSC::JSParser::parseBinaryExpression):
(JSC::JSParser::parseStrictObjectLiteral):
(JSC::JSParser::parsePrimaryExpression):
(JSC::JSParser::parseMemberExpression):
(JSC::JSParser::parseUnaryExpression):
* parser/JSParser.h:
* parser/Lexer.cpp:
(JSC::Lexer::parseString):
(JSC::Lexer::lex):
* parser/Lexer.h:
(JSC::Lexer::isReparsing):
* parser/Nodes.cpp:
(JSC::ScopeNode::ScopeNode):
(JSC::FunctionBodyNode::FunctionBodyNode):
(JSC::FunctionBodyNode::create):
* parser/Nodes.h:
(JSC::ScopeNode::isStrictMode):
* parser/Parser.cpp:
(JSC::Parser::parse):
* parser/Parser.h:
(JSC::Parser::parse):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::SyntaxChecker):
(JSC::SyntaxChecker::makeFunctionCallNode):
(JSC::SyntaxChecker::appendToComma):
(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::createRegex):
(JSC::SyntaxChecker::createNewExpr):
(JSC::SyntaxChecker::createConditionalExpr):
(JSC::SyntaxChecker::createAssignResolve):
(JSC::SyntaxChecker::createFunctionExpr):
(JSC::SyntaxChecker::createFunctionBody):
(JSC::SyntaxChecker::appendBinaryExpressionInfo):
(JSC::SyntaxChecker::operatorStackPop):
* runtime/Arguments.cpp:
(JSC::Arguments::createStrictModeCallerIfNecessary):
(JSC::Arguments::createStrictModeCalleeIfNecessary):
(JSC::Arguments::getOwnPropertySlot):
(JSC::Arguments::getOwnPropertyDescriptor):
(JSC::Arguments::put):
(JSC::Arguments::deleteProperty):
* runtime/Arguments.h:
(JSC::Arguments::Arguments):
* runtime/CommonIdentifiers.cpp:
(JSC::CommonIdentifiers::CommonIdentifiers):
* runtime/CommonIdentifiers.h:
* runtime/Error.cpp:
(JSC::StrictModeTypeErrorFunction::StrictModeTypeErrorFunction):
(JSC::StrictModeTypeErrorFunction::constructThrowTypeError):
(JSC::StrictModeTypeErrorFunction::getConstructData):
(JSC::StrictModeTypeErrorFunction::callThrowTypeError):
(JSC::StrictModeTypeErrorFunction::getCallData):
(JSC::createTypeErrorFunction):
* runtime/Error.h:
* runtime/Executable.cpp:
(JSC::EvalExecutable::EvalExecutable):
(JSC::ProgramExecutable::ProgramExecutable):
(JSC::FunctionExecutable::FunctionExecutable):
(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::checkSyntax):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::compileForCallInternal):
(JSC::FunctionExecutable::compileForConstructInternal):
(JSC::FunctionExecutable::reparseExceptionInfo):
(JSC::EvalExecutable::reparseExceptionInfo):
(JSC::FunctionExecutable::fromGlobalCode):
(JSC::ProgramExecutable::reparseExceptionInfo):
* runtime/Executable.h:
(JSC::ScriptExecutable::ScriptExecutable):
(JSC::ScriptExecutable::isStrictMode):
(JSC::EvalExecutable::create):
(JSC::FunctionExecutable::create):
* runtime/JSActivation.cpp:
(JSC::JSActivation::toStrictThisObject):
* runtime/JSActivation.h:
* runtime/JSFunction.cpp:
(JSC::createDescriptorForThrowingProperty):
(JSC::JSFunction::getOwnPropertySlot):
(JSC::JSFunction::getOwnPropertyDescriptor):
(JSC::JSFunction::put):
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::internalFunctionStructure):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncEval):
* runtime/JSObject.cpp:
(JSC::JSObject::put):
(JSC::JSObject::toStrictThisObject):
(JSC::throwTypeError):
* runtime/JSObject.h:
(JSC::JSObject::isStrictModeFunction):
(JSC::JSObject::putDirectInternal):
(JSC::JSObject::putDirect):
(JSC::JSValue::putDirect):
(JSC::JSValue::toStrictThisObject):
* runtime/JSStaticScopeObject.cpp:
(JSC::JSStaticScopeObject::toStrictThisObject):
* runtime/JSStaticScopeObject.h:
* runtime/JSValue.h:
* runtime/JSZombie.h:
(JSC::JSZombie::toStrictThisObject):
* runtime/PutPropertySlot.h:
(JSC::PutPropertySlot::PutPropertySlot):
(JSC::PutPropertySlot::isStrictMode):
* runtime/StrictEvalActivation.cpp: Added.
(JSC::StrictEvalActivation::StrictEvalActivation):
(JSC::StrictEvalActivation::deleteProperty):
(JSC::StrictEvalActivation::toThisObject):
(JSC::StrictEvalActivation::toStrictThisObject):
* runtime/StrictEvalActivation.h: Added.
2010-10-10 Patrick Gansterer <paroga@webkit.org>
Unreviewed.
......
......@@ -388,6 +388,8 @@ javascriptcore_sources += \
JavaScriptCore/runtime/ScopeChainMark.h \
JavaScriptCore/runtime/SmallStrings.cpp \
JavaScriptCore/runtime/SmallStrings.h \
JavaScriptCore/runtime/StrictEvalActivation.cpp\
JavaScriptCore/runtime/StrictEvalActivation.h\
JavaScriptCore/runtime/StringBuilder.h \
JavaScriptCore/runtime/StringConcatenate.h \
JavaScriptCore/runtime/StringConstructor.cpp \
......
......@@ -531,6 +531,7 @@ __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
__ZNK3JSC8JSObject18toStrictThisObjectEPNS_9ExecStateE
__ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
......
......@@ -197,6 +197,7 @@ SOURCES += \
runtime/RopeImpl.cpp \
runtime/ScopeChain.cpp \
runtime/SmallStrings.cpp \
runtime/StrictEvalActivation.cpp \
runtime/StringConstructor.cpp \
runtime/StringObject.cpp \
runtime/StringPrototype.cpp \
......
......@@ -1172,6 +1172,14 @@
RelativePath="..\..\runtime\SmallStrings.h"
>
</File>
<File
RelativePath="..\..\runtime\StrictEvalActivation.cpp"
>
</File>
<File
RelativePath="..\..\runtime\StrictEvalActivation.h"
>
</File>
<File
RelativePath="..\..\runtime\StringConstructor.cpp"
>
......
......@@ -318,6 +318,8 @@
A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; };
A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */; };
A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */ = {isa = PBXBuildFile; fileRef = A730B6101250068F009D25B1 /* StrictEvalActivation.h */; };
A730B6131250068F009D25B1 /* StrictEvalActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */; };
A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386551118697B400540279 /* SpecializedThunkJIT.h */; };
A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7386552118697B400540279 /* ThunkGenerators.cpp */; };
A7386556118697B400540279 /* ThunkGenerators.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386553118697B400540279 /* ThunkGenerators.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -951,6 +953,8 @@
A72701B30DADE94900E548D7 /* ExceptionHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionHelpers.h; sourceTree = "<group>"; };
A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = "<group>"; };
A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = "<group>"; };
A730B6101250068F009D25B1 /* StrictEvalActivation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StrictEvalActivation.h; sourceTree = "<group>"; };
A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StrictEvalActivation.cpp; sourceTree = "<group>"; };
A7386551118697B400540279 /* SpecializedThunkJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpecializedThunkJIT.h; sourceTree = "<group>"; };
A7386552118697B400540279 /* ThunkGenerators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThunkGenerators.cpp; sourceTree = "<group>"; };
A7386553118697B400540279 /* ThunkGenerators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThunkGenerators.h; sourceTree = "<group>"; };
......@@ -1814,6 +1818,8 @@
14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */,
1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
A730B6101250068F009D25B1 /* StrictEvalActivation.h */,
A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */,
);
path = runtime;
sourceTree = "<group>";
......@@ -2314,6 +2320,7 @@
9714AF5F122F32070092D9F5 /* ParsedURL.h in Headers */,
9714AF60122F32070092D9F5 /* URLString.h in Headers */,
90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */,
A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -2407,7 +2414,6 @@
isa = PBXProject;
buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */;
compatibilityVersion = "Xcode 2.4";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
......@@ -2769,6 +2775,7 @@
9714AF46122F28850092D9F5 /* URLSegments.cpp in Sources */,
9714AF5E122F32070092D9F5 /* ParsedURL.cpp in Sources */,
90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */,
A730B6131250068F009D25B1 /* StrictEvalActivation.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -517,6 +517,11 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
printf("[%4d] convert_this %s\n", location, registerName(exec, r0).data());
break;
}
case op_convert_this_strict: {
int r0 = (++it)->u.operand;
printf("[%4d] convert_this_strict %s\n", location, registerName(exec, r0).data());
break;
}
case op_new_object: {
int r0 = (++it)->u.operand;
printf("[%4d] new_object\t %s\n", location, registerName(exec, r0).data());
......@@ -1371,6 +1376,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo
, m_needsFullScopeChain(ownerExecutable->needsActivation())
, m_usesEval(ownerExecutable->usesEval())
, m_isNumericCompareFunction(false)
, m_isStrictMode(ownerExecutable->isStrictMode())
, m_codeType(codeType)
, m_source(sourceProvider)
, m_sourceOffset(sourceOffset)
......@@ -1557,7 +1563,7 @@ bool CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
scopeChain = scopeChain->next;
}
m_exceptionInfo = m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this);
m_exceptionInfo = m_ownerExecutable->reparseExceptionInfo(scopeChain, this);
return m_exceptionInfo;
}
......
......@@ -297,6 +297,8 @@ namespace JSC {
void printStructure(const char* name, const Instruction*, int operand) const;
#endif
bool isStrictMode() const { return m_isStrictMode; }
inline bool isKnownNotImmediate(int index)
{
if (index == m_thisRegister)
......@@ -564,6 +566,7 @@ namespace JSC {
bool m_needsFullScopeChain;
bool m_usesEval;
bool m_isNumericCompareFunction;
bool m_isStrictMode;
CodeType m_codeType;
......
......@@ -43,20 +43,20 @@ namespace JSC {
class EvalCodeCache {
public:
PassRefPtr<EvalExecutable> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
PassRefPtr<EvalExecutable> get(ExecState* exec, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
{
RefPtr<EvalExecutable> evalExecutable;
if (evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
evalExecutable = m_cacheMap.get(evalSource.impl());
if (!evalExecutable) {
evalExecutable = EvalExecutable::create(exec, makeSource(evalSource));
evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext);
exceptionValue = evalExecutable->compile(exec, scopeChain);
if (exceptionValue)
return 0;
if (evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
m_cacheMap.set(evalSource.impl(), evalExecutable);
}
......
......@@ -45,6 +45,7 @@ namespace JSC {
macro(op_create_this, 3) \
macro(op_get_callee, 2) \
macro(op_convert_this, 2) \
macro(op_convert_this_strict, 2) \
\
macro(op_new_object, 2) \
macro(op_new_array, 4) \
......
......@@ -343,6 +343,11 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
emitInitLazyRegister(argumentsRegister);
emitInitLazyRegister(unmodifiedArgumentsRegister);
if (m_codeBlock->isStrictMode()) {
emitOpcode(op_create_arguments);
instructions().append(argumentsRegister->index());
}
// The debugger currently retrieves the arguments object from an activation rather than pulling
// it from a call frame. In the long-term it should stop doing that (<rdar://problem/6911886>),
......@@ -442,7 +447,10 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
instructions().append(m_thisRegister.index());
instructions().append(funcProto->index());
} else if (functionBody->usesThis() || m_shouldEmitDebugHooks) {
emitOpcode(op_convert_this);
if (codeBlock->isStrictMode())
emitOpcode(op_convert_this_strict);
else
emitOpcode(op_convert_this);
instructions().append(m_thisRegister.index());
}
}
......@@ -1557,6 +1565,12 @@ void BytecodeGenerator::createArgumentsIfNecessary()
return;
ASSERT(m_codeBlock->usesArguments());
// If we're in strict mode we tear off the arguments on function
// entry, so there's no need to check if we need to create them
// now
if (m_codeBlock->isStrictMode())
return;
emitOpcode(op_create_arguments);
instructions().append(m_codeBlock->argumentsRegister());
}
......@@ -1674,7 +1688,8 @@ RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
emitOpcode(op_tear_off_activation);
instructions().append(m_activationRegister->index());
instructions().append(m_codeBlock->argumentsRegister());
} else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1) { // If there are no named parameters, there's nothing to tear off, since extra / unnamed parameters get copied to the arguments object at construct time.
} else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1
&& !m_codeBlock->isStrictMode()) { // If there are no named parameters, there's nothing to tear off, since extra / unnamed parameters get copied to the arguments object at construct time.
emitOpcode(op_tear_off_arguments);
instructions().append(m_codeBlock->argumentsRegister());
}
......
......@@ -419,6 +419,8 @@ namespace JSC {
}
bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
private:
void emitOpcode(OpcodeID);
......@@ -499,12 +501,12 @@ namespace JSC {
PassRefPtr<FunctionExecutable> makeFunction(ExecState* exec, FunctionBodyNode* body)
{
return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
}
PassRefPtr<FunctionExecutable> makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
{
return FunctionExecutable::create(globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
return FunctionExecutable::create(globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
}
RegisterID* emitInitLazyRegister(RegisterID*);
......
......@@ -101,7 +101,7 @@ JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSG
{
CallFrame* globalCallFrame = globalObject->globalExec();
RefPtr<EvalExecutable> eval = EvalExecutable::create(globalCallFrame, makeSource(script));
RefPtr<EvalExecutable> eval = EvalExecutable::create(globalCallFrame, makeSource(script), false);
JSObject* error = eval->compile(globalCallFrame, globalCallFrame->scopeChain());
if (error)
return error;
......
......@@ -88,7 +88,7 @@ JSValue DebuggerCallFrame::evaluate(const UString& script, JSValue& exception) c
if (!m_callFrame->codeBlock())
return JSValue();
RefPtr<EvalExecutable> eval = EvalExecutable::create(m_callFrame, makeSource(script));
RefPtr<EvalExecutable> eval = EvalExecutable::create(m_callFrame, makeSource(script), m_callFrame->codeBlock()->isStrictMode());
JSObject* error = eval->compile(m_callFrame, m_callFrame->scopeChain());
if (error)
return error;
......
......@@ -59,6 +59,7 @@
#include "RegExpPrototype.h"
#include "Register.h"
#include "SamplingTool.h"
#include "StrictEvalActivation.h"
#include <limits.h>
#include <stdio.h>
#include <wtf/Threading.h>
......@@ -389,14 +390,18 @@ NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* r
UString programSource = asString(program)->value(callFrame);
if (callFrame->hadException())
return JSValue();
LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
if (JSValue parsedObject = preparser.tryLiteralParse())
return parsedObject;
CodeBlock* codeBlock = callFrame->codeBlock();
if (!codeBlock->isStrictMode()) {
// FIXME: We can use the preparser in strict mode, we just need additional logic
// to prevent duplicates.
LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
if (JSValue parsedObject = preparser.tryLiteralParse())
return parsedObject;
}
ScopeChainNode* scopeChain = callFrame->scopeChain();
CodeBlock* codeBlock = callFrame->codeBlock();