diff options
author | Ben Murdoch <benm@google.com> | 2010-10-22 13:02:20 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-10-26 15:21:41 +0100 |
commit | a94275402997c11dd2e778633dacf4b7e630a35d (patch) | |
tree | e66f56c67e3b01f22c9c23cd932271ee9ac558ed /JavaScriptCore | |
parent | 09e26c78506587b3f5d930d7bc72a23287ffbec0 (diff) | |
download | external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.zip external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.gz external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.bz2 |
Merge WebKit at r70209: Initial merge by Git
Change-Id: Id23a68efa36e9d1126bcce0b137872db00892c8e
Diffstat (limited to 'JavaScriptCore')
164 files changed, 6103 insertions, 2170 deletions
diff --git a/JavaScriptCore/Android.mk b/JavaScriptCore/Android.mk index 959fbc4..c690477 100644 --- a/JavaScriptCore/Android.mk +++ b/JavaScriptCore/Android.mk @@ -166,6 +166,7 @@ LOCAL_SRC_FILES := \ wtf/ByteArray.cpp \ wtf/CurrentTime.cpp \ wtf/DateMath.cpp \ + wtf/DecimalNumber.cpp \ wtf/FastMalloc.cpp \ wtf/HashTable.cpp \ wtf/MD5.cpp \ @@ -185,6 +186,7 @@ LOCAL_SRC_FILES := \ \ wtf/text/AtomicString.cpp \ wtf/text/CString.cpp \ + wtf/text/StringBuilder.cpp \ wtf/text/StringImpl.cpp \ wtf/text/StringStatics.cpp \ wtf/text/WTFString.cpp \ diff --git a/JavaScriptCore/Android.v8.wtf.mk b/JavaScriptCore/Android.v8.wtf.mk index 16554b1..a9c8a3b 100644 --- a/JavaScriptCore/Android.v8.wtf.mk +++ b/JavaScriptCore/Android.v8.wtf.mk @@ -36,6 +36,7 @@ LOCAL_SRC_FILES := \ wtf/ByteArray.cpp \ wtf/CurrentTime.cpp \ wtf/DateMath.cpp \ + wtf/DecimalNumber.cpp \ wtf/FastMalloc.cpp \ wtf/HashTable.cpp \ wtf/MD5.cpp \ @@ -55,6 +56,7 @@ LOCAL_SRC_FILES := \ \ wtf/text/AtomicString.cpp \ wtf/text/CString.cpp \ + wtf/text/StringBuidler.cpp \ wtf/text/StringImpl.cpp \ wtf/text/StringStatics.cpp \ wtf/text/WTFString.cpp \ diff --git a/JavaScriptCore/CMakeLists.txt b/JavaScriptCore/CMakeLists.txt index 89c9ef1..90067a4 100644 --- a/JavaScriptCore/CMakeLists.txt +++ b/JavaScriptCore/CMakeLists.txt @@ -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 @@ -254,7 +255,7 @@ SOURCE_GROUP(yarr "yarr/") SOURCE_GROUP(wtf "wtf/") ADD_SUBDIRECTORY(wtf) -ADD_SUBDIRECTORY(jsc) +ADD_SUBDIRECTORY(shell) WEBKIT_WRAP_SOURCELIST(${JavaScriptCore_SOURCES}) INCLUDE_DIRECTORIES(${JavaScriptCore_INCLUDE_DIRECTORIES}) diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index bbdf703..95bf475 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,1734 @@ +2010-10-20 Simon Fraser <simon.fraser@apple.com> + + Fix the EFL build. + + * wtf/CMakeLists.txt: + +2010-10-20 Simon Fraser <simon.fraser@apple.com> + + Fix Windows build: export needed symbols. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-10-19 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Gavin Barraclough. + + https://bugs.webkit.org/show_bug.cgi?id=47851 + + Add methods to DecimalNumber to return the buffer length + required for decimal and exponential output. + + Make some of the DecimalNumber code non-inline (no + effect on Sunspider), adding DecimalNumber.cpp to various + build systems. + + Make some DecimalNumber methods 'const'. + + * Android.mk: + * Android.v8.wtf.mk: + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/NumberPrototype.cpp: + (JSC::numberProtoFuncToExponential): + (JSC::numberProtoFuncToFixed): + (JSC::numberProtoFuncToPrecision): + * wtf/DecimalNumber.cpp: Added. + (WTF::DecimalNumber::bufferLengthForStringDecimal): + (WTF::DecimalNumber::bufferLengthForStringExponential): + (WTF::DecimalNumber::toStringDecimal): + (WTF::DecimalNumber::toStringExponential): + * wtf/DecimalNumber.h: + (WTF::DecimalNumber::sign): + (WTF::DecimalNumber::exponent): + (WTF::DecimalNumber::significand): + (WTF::DecimalNumber::precision): + * wtf/dtoa.cpp: + (WTF::dtoa): + * wtf/dtoa.h: + * wtf/wtf.pri: + +2010-10-20 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r70165. + http://trac.webkit.org/changeset/70165 + https://bugs.webkit.org/show_bug.cgi?id=48007 + + It broke tests on Qt bot (Requested by Ossy on #webkit). + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/text/TextPosition.h: Removed. + +2010-10-20 Brian Weinstein <bweinstein@apple.com> + + Reviewed by Adam Roben. + + Fix the Windows build after r70165. Move the copying of JavaScript headers from JavaScriptCore's post-build + step to JavaScriptCoreGenerated, so the copying is done even when a cpp file in JavaScriptCore is changed. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make: + +2010-10-20 Dumitru Daniliuc <dumi@chromium.org> + + Unreviewed, fixing the Win build. + + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + +2010-10-20 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=41948 + REGRESSION(r60392): Registerfile can be unwound too far following an exception + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): Walk the stack to calculate the high + water mark currently in use. It's not safe to assume that the current + CallFrame's high water mark is the highest high water mark because + calls do not always set up at the end of a CallFrame. A large caller + CallFrame can encompass a small callee CallFrame. + +2010-10-20 Peter Rybin <peter.rybin@gmail.com> + + Reviewed by Adam Barth. + + HTML parser should provide script column position within HTML document to JavaScript engine + https://bugs.webkit.org/show_bug.cgi?id=45271 + + Adds TextPosition* classes -- a structure that stores line/column/generation + level coordinates inside text document. Adds *BasedNumber classes -- typesafe int + wrappers that emphasize whether int number is used as zero-based or + one-based. + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/text/TextPosition.h: Added. + (WTF::TextPosition::TextPosition): + (WTF::TextPosition::minimumPosition): + (WTF::TextPosition::belowRangePosition): + (WTF::ZeroBasedNumber::fromZeroBasedInt): + (WTF::ZeroBasedNumber::ZeroBasedNumber): + (WTF::ZeroBasedNumber::zeroBasedInt): + (WTF::ZeroBasedNumber::base): + (WTF::ZeroBasedNumber::belowBase): + (WTF::OneBasedNumber::fromOneBasedInt): + (WTF::OneBasedNumber::OneBasedNumber): + (WTF::OneBasedNumber::oneBasedInt): + (WTF::OneBasedNumber::convertAsZeroBasedInt): + (WTF::OneBasedNumber::convertToZeroBased): + (WTF::OneBasedNumber::base): + (WTF::OneBasedNumber::belowBase): + (WTF::toZeroBasedTextPosition): + (WTF::toOneBasedTextPosition): + (WTF::ZeroBasedNumber::convertToOneBased): + +2010-10-19 Kwang Yul Seo <skyul@company100.net> + + Reviewed by David Kilzer. + + [BREWMP] Turn off JIT for simulator build + https://bugs.webkit.org/show_bug.cgi?id=47937 + + We don't need to test x86 JIT. + + * wtf/Platform.h: + +2010-10-19 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Remove support for JSVALUE32 from JSC + https://bugs.webkit.org/show_bug.cgi?id=47948 + + Remove all the code for supporting JSVALUE32 from JSC. + + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_lshift): + (JSC::JIT::emitSlow_op_lshift): + (JSC::JIT::emit_op_rshift): + (JSC::JIT::emitSlow_op_rshift): + (JSC::JIT::emit_op_urshift): + (JSC::JIT::emitSlow_op_urshift): + (JSC::JIT::emit_op_jnless): + (JSC::JIT::emitSlow_op_jnless): + (JSC::JIT::emit_op_jless): + (JSC::JIT::emitSlow_op_jless): + (JSC::JIT::emit_op_jlesseq): + (JSC::JIT::emitSlow_op_jlesseq): + (JSC::JIT::emit_op_bitand): + (JSC::JIT::emit_op_post_inc): + (JSC::JIT::emit_op_post_dec): + (JSC::JIT::emit_op_pre_inc): + (JSC::JIT::emit_op_pre_dec): + (JSC::JIT::emit_op_mod): + (JSC::JIT::emitSlow_op_mod): + * jit/JITCall.cpp: + * jit/JITInlineMethods.h: + (JSC::JIT::emitGetFromCallFrameHeaderPtr): + (JSC::JIT::emitGetFromCallFrameHeader32): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_loop_if_lesseq): + (JSC::JIT::emit_op_bitnot): + (JSC::JIT::emit_op_next_pname): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::emit_op_get_by_val): + (JSC::JIT::emit_op_put_by_val): + * jit/JITStubs.h: + * jit/JSInterfaceJIT.h: + * jit/SpecializedThunkJIT.h: + (JSC::SpecializedThunkJIT::returnDouble): + (JSC::SpecializedThunkJIT::tagReturnAsInt32): + * jit/ThunkGenerators.cpp: + (JSC::sqrtThunkGenerator): + (JSC::powThunkGenerator): + * runtime/Collector.cpp: + (JSC::isPossibleCell): + (JSC::typeName): + * runtime/JSCell.h: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: + * runtime/JSGlobalObject.h: + (JSC::Structure::prototypeForLookup): + * runtime/JSImmediate.h: + (JSC::reinterpretIntptrToDouble): + (JSC::JSImmediate::isIntegerNumber): + (JSC::JSImmediate::isDouble): + (JSC::JSImmediate::areBothImmediateIntegerNumbers): + (JSC::JSImmediate::makeDouble): + (JSC::JSImmediate::doubleValue): + (JSC::JSImmediate::toBoolean): + (JSC::JSImmediate::fromNumberOutsideIntegerRange): + (JSC::JSImmediate::from): + (JSC::JSImmediate::toDouble): + (JSC::JSFastMath::rightShiftImmediateNumbers): + * runtime/JSNumberCell.cpp: + * runtime/JSNumberCell.h: + * runtime/JSObject.h: + (JSC::JSObject::JSObject): + * runtime/JSValue.h: + * runtime/NumberObject.h: + * wtf/Platform.h: + +2010-10-19 Csaba Osztrogonác <ossy@webkit.org> + + Reviewed by Geoffrey Garen. + + BytecodeGenerator::m_lastOpcodePosition must be initialized in all constructors + https://bugs.webkit.org/show_bug.cgi?id=47920 + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): Add missing member initialization. + +2010-10-19 Kwang Yul Seo <skyul@company100.net> + + Reviewed by David Kilzer. + + RVCT fails to compile DateMath.cpp due to overloaded function pow + https://bugs.webkit.org/show_bug.cgi?id=47844 + + Choose std::pow(double, double) among multiple overloaded pow functions + to fix build for RVCT. + + * wtf/DateMath.cpp: + (WTF::parseES5DateFromNullTerminatedCharacters): + +2010-10-19 Patrick Gansterer <paroga@webkit.org> + + Reviewed by David Kilzer. + + Use UChar instead of wchar_t in UnicodeWinCE + https://bugs.webkit.org/show_bug.cgi?id=47904 + + Make UnicodeWinCE more portable, so we can use it for other ports too. + + * wtf/unicode/wince/UnicodeWinCE.cpp: + (WTF::Unicode::toLower): + (WTF::Unicode::toUpper): + (WTF::Unicode::foldCase): + (WTF::Unicode::isPrintableChar): + (WTF::Unicode::isSpace): + (WTF::Unicode::isLetter): + (WTF::Unicode::isUpper): + (WTF::Unicode::isLower): + (WTF::Unicode::isDigit): + (WTF::Unicode::isPunct): + (WTF::Unicode::isAlphanumeric): + (WTF::Unicode::toTitleCase): + (WTF::Unicode::mirroredChar): + (WTF::Unicode::digitValue): + * wtf/unicode/wince/UnicodeWinCE.h: + (WTF::Unicode::isSeparatorSpace): + (WTF::Unicode::isHighSurrogate): + (WTF::Unicode::isLowSurrogate): + (WTF::Unicode::umemcasecmp): + (WTF::Unicode::surrogateToUcs4): + +2010-10-19 Patrick Gansterer <paroga@webkit.org> + + Reviewed by Andreas Kling. + + Fix style of UnicodeWinCE + https://bugs.webkit.org/show_bug.cgi?id=47818 + + * wtf/unicode/wince/UnicodeWinCE.cpp: + (WTF::Unicode::toLower): + (WTF::Unicode::toUpper): + * wtf/unicode/wince/UnicodeWinCE.h: + +2010-10-18 Xan Lopez <xlopez@igalia.com> + + Reviewed by Martin Robinson. + + * GNUmakefile.am: add missing file. + +2010-10-18 Oliver Hunt <oliver@apple.com> + + Reviewed by Sam Weinig. + + Strict mode: Functions created with the function constructor don't implement strict mode semantics + https://bugs.webkit.org/show_bug.cgi?id=47860 + + When creating the FunctionExecutable for a new function the function constructor + was always passing false for whether or not a function was strict, rather than + using the information from the freshly parsed function itself. + + * runtime/Executable.cpp: + (JSC::FunctionExecutable::fromGlobalCode): + +2010-10-18 Oliver Hunt <oliver@apple.com> + + Reviewed by Darin Adler. + + Strict mode: |this| should be undefined if it is not explicitly provided + https://bugs.webkit.org/show_bug.cgi?id=47833 + + To make strict mode behave correctly we want to pass undefined instead of null + as the default this value. This has no impact on behaviour outside of strict + mode as both values are replaced with the global object if necessary. + + * bytecompiler/NodesCodegen.cpp: + (JSC::FunctionCallValueNode::emitBytecode): + (JSC::FunctionCallResolveNode::emitBytecode): + (JSC::CallFunctionCallDotNode::emitBytecode): + (JSC::ApplyFunctionCallDotNode::emitBytecode): + + +2010-10-18 Darin Adler <darin@apple.com> + + Reviewed by Anders Carlsson. + + Make a nullptr that works with OwnPtr and RefPtr + https://bugs.webkit.org/show_bug.cgi?id=47756 + + * JavaScriptCore.xcodeproj/project.pbxproj: Added NullPtr.h. + + * wtf/NullPtr.h: Added. + + * wtf/OwnArrayPtr.h: Add an overload of = taking nullptr. + * wtf/OwnPtr.h: Ditto. + * wtf/PassOwnArrayPtr.h: Ditto. + * wtf/PassOwnPtr.h: Ditto. + * wtf/PassRefPtr.h: Ditto. + * wtf/RefPtr.h: Ditto. + * wtf/RetainPtr.h: Ditto. + +2010-10-18 Oliver Hunt <oliver@apple.com> + + Reviewed by Sam Weinig. + + Strict mode: JIT doesn't check for |this| being an immediate before dereferencing + https://bugs.webkit.org/show_bug.cgi?id=47826 + + There's no guarantee that |this| will be a cell in a strict mode function, so + don't claim that it is. + + * bytecode/CodeBlock.h: + (JSC::CodeBlock::isKnownNotImmediate): + +2010-10-18 Zoltan Herczeg <zherczeg@webkit.org> + + Reviewed by Oliver Hunt. + + if (0) throw "x" ; else { } throws parse error after r69906 + https://bugs.webkit.org/show_bug.cgi?id=47807 + + r69906 introduced a bug: the semicolon is not parsed after a throw + expression anymore. Thus, the semicolon terminates the "if" parsing + in the example above, and the else token results a parse error. + + * parser/JSParser.cpp: + (JSC::JSParser::parseThrowStatement): + +2010-10-18 Peter Varga <pvarga@inf.u-szeged.hu> + + Reviewed by Andreas Kling. + + Remove some unnecessary lines of code from Parser.cpp + https://bugs.webkit.org/show_bug.cgi?id=47816 + + * parser/Parser.cpp: + +2010-10-18 Xan Lopez <xlopez@igalia.com> + + Reviewed by Csaba Osztrogonác. + + Build broken with JIT disabled + https://bugs.webkit.org/show_bug.cgi?id=47801 + + This is a regression caused by r69940. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::resolveBase): + +2010-10-18 Zoltan Horvath <zoltan@webkit.org> + + Reviewed by Darin Adler. + + Change FastAllocBase implementation into a macro + https://bugs.webkit.org/show_bug.cgi?id=42998 + + It was investigated in bug #33896 that inheriting classes from FastAllocBase + can result in objects getting larger which leads to memory regressions. + Using a macro instead of inheriting classes from FastAllocBase would solve the issue. + + * wtf/FastAllocBase.h: Add a WTF_MAKE_FAST_ALLOCATED macro + +2010-10-17 Oliver Hunt <oliver@apple.com> + + Reviewed by Sam Weinig. + + Strict mode: arguments is not valid as the base expression for pre- or post-fix expressions + https://bugs.webkit.org/show_bug.cgi?id=47791 + + Simple fix, check for arguments in addition to eval. + + * parser/JSParser.cpp: + (JSC::JSParser::parseUnaryExpression): + +2010-10-17 Oliver Hunt <oliver@apple.com> + + Reviewed by Sam Weinig. + + Strict mode: Assignment that would create a global should be a late ReferenceError, not a syntax failure + https://bugs.webkit.org/show_bug.cgi?id=47788 + + Fixing this required a couple of changes: + * resolve_base now has a flag to indicate whether it is being used for a put in strict mode. + this allows us to throw an exception when we're doing a completely generic resolve for + assignment, and that assignment would create a new global. + * There is a new opcode 'op_ensure_property_exists' that is used to determine whether + the property being assigned to already exists on the global object. This currently + has no caching, but such caching could be added relatively trivially. It is only used + in the case where we know that a property will be placed on the global object, and + we cannot verify that the property already exists. + + In the jit we plant a call to cti_op_resolve_base_strict_put in the effected case rather + than making op_resolve_base have an additional runtime branch. + + There's also a new helper function to create the exception for the invalid assignment. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + * bytecode/Opcode.h: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitResolveBase): + (JSC::BytecodeGenerator::emitResolveBaseForPut): + * bytecompiler/BytecodeGenerator.h: + * bytecompiler/NodesCodegen.cpp: + (JSC::AssignResolveNode::emitBytecode): + (JSC::ForInNode::emitBytecode): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::resolveBase): + (JSC::Interpreter::privateExecute): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JIT.h: + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_resolve_base): + (JSC::JIT::emit_op_ensure_property_exists): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_resolve_base): + (JSC::JIT::emit_op_ensure_property_exists): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * jit/JITStubs.h: + * parser/JSParser.cpp: + (JSC::JSParser::parseProgram): + * runtime/ExceptionHelpers.cpp: + (JSC::createErrorForInvalidGlobalAssignment): + * runtime/ExceptionHelpers.h: + * runtime/Operations.h: + (JSC::resolveBase): + +2010-10-17 Simon Fraser <simon.fraser@apple.com> + + First part of fix for Windows build failure. Will wait for the + next set of link errors to determine the mangled forms for dtoaRoundSF + and dtoaRoundDP. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-10-17 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Nikolas Zimmermann. + + Very large and small numbers fail to round-trip through CSS + https://bugs.webkit.org/show_bug.cgi?id=20674 + + New exports required to use DecimalNumber in WebCore. + + * JavaScriptCore.exp: + * JavaScriptCore.xcodeproj/project.pbxproj: + +2010-10-16 Kyusun Kim <maniagoon@company100.net> + + Reviewed by Alexey Proskuryakov. + + Add using declarations for currentTimeMS() and parseDateFromNullTerminatedCharacters() + https://bugs.webkit.org/show_bug.cgi?id=47758 + + * wtf/CurrentTime.h: + * wtf/DateMath.h: + +2010-10-16 Patrick Gansterer <paroga@webkit.org> + + Reviewed by Adam Barth. + + Rename StringHasherFunctions.h to StringHasher.h + https://bugs.webkit.org/show_bug.cgi?id=47200 + + Now StringHasherFunctions.h only contains the StringHasher class, so rename it to the correct name. + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/StringHashFunctions.h: Removed. + * wtf/StringHasher.h: Copied from JavaScriptCore/wtf/StringHashFunctions.h. + * wtf/text/StringHash.h: + * wtf/text/StringImpl.h: + +2010-10-15 Oliver Hunt <oliver@apple.com> + + Reviewed by Sam Weinig. + + Automatic Semicolon Insertion incorrectly inserts semicolon after break, continue, and return followed by a newline + https://bugs.webkit.org/show_bug.cgi?id=47762 + + The old YACC parser depended on the lexer for some classes of semicolon insertion. + The new parser handles ASI entirely on its own so when the lexer inserts a semicolon + on its own the net result is a spurious semicolon in the input stream. This can result + in incorrect parsing in some cases: + + if (0) + break + ;else {} + + Would result in a parse failure as the output from the lexer is essentially + + if (0) + break + ;;else + + So the second semicolon is interpreted as a empty statement, which terminates the if, + making the else an error. + + + * parser/JSParser.cpp: + (JSC::JSParser::parseThrowStatement): + Parsing of throw statement was wrong, and only worked due to the weird behaviour + in the lexer + * parser/Lexer.cpp: + (JSC::Lexer::lex): + Remove bogus semicolon insertion from the newline handling + +2010-10-15 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Dirk Schulze. + + Replace some String::format() usages by StringConcatenate in WebKit + https://bugs.webkit.org/show_bug.cgi?id=47714 + + * wtf/text/StringConcatenate.h: Add UChar specific StringTypeAdapter, to accept single UChars in makeString(). + +2010-10-15 Ilya Tikhonovsky <loislo@chromium.org> + + Unreviewed build fix for Debug Leopard which is failng to compile after r69842. + + * yarr/RegexInterpreter.cpp: + (JSC::Yarr::ByteCompiler::emitDisjunction): + +2010-10-15 Peter Varga <pvarga@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + The parenthetical assertion checking isn't working in some cases with YARR + Interpreter + https://bugs.webkit.org/show_bug.cgi?id=46893 + + Calculate the countToCheck value of a TypeParentheticalAssertion by + subtracting the number of characters which follows + a TypeParentheticalAssertion term with the number of characters which should + be matched by terms which are contained + in the TypeParentheticalAssertion term (minimumSize). + + * yarr/RegexInterpreter.cpp: + (JSC::Yarr::ByteCompiler::emitDisjunction): + +2010-10-14 Nathan Vander Wilt <nate@andyet.net> + + Reviewed by Darin Adler. + + Added parser for ECMAScript 5 standard date format, so Date.parse can handle RFC 3339 timestamps: https://bugs.webkit.org/show_bug.cgi?id=44632 + + * runtime/DateConversion.cpp: + (JSC::parseDate): + * wtf/DateMath.cpp: + (WTF::ymdhmsToSeconds): + (WTF::parseES5DateFromNullTerminatedCharacters): + * wtf/DateMath.h: + +2010-10-14 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Gavin Barraclough. + + Replace lots of String::format() usages by StringConcatenate + https://bugs.webkit.org/show_bug.cgi?id=47664 + + Add StringTypeAdapter<char> to accept single characters for makeString(). + + * wtf/text/StringConcatenate.h: + (WTF::makeString): + +2010-10-14 David Goodwin <david_goodwin@apple.com> + + Reviewed by Darin Adler. + + need way to measure size of JITed ARM code + https://bugs.webkit.org/show_bug.cgi?id=47121 + + * assembler/LinkBuffer.h: + (JSC::LinkBuffer::linkCode): + (JSC::LinkBuffer::dumpLinkStats): + (JSC::LinkBuffer::dumpCode): + +2010-10-14 Peter Varga <pvarga@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + The backreference checking isn't working in some cases with YARR Interpreter + https://bugs.webkit.org/show_bug.cgi?id=46904 + + The Interpreter::matchBackReference() function returns true without matching + when a backreference points to the same parentheses where it is. + + * yarr/RegexInterpreter.cpp: + (JSC::Yarr::Interpreter::matchBackReference): + +2010-10-14 No'am Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Andreas Kling. + + [Qt] Text breaking is slow: enable ICU as an opt-in + https://bugs.webkit.org/show_bug.cgi?id=40332 + + Added a config flag that enables ICU as an opt-in instead of the Qt specific code. + Because of the inclusion of ICU headers, some explicit casting was necessary in UnicodeQt4.h + + * JavaScriptCore.pri: + * wtf/unicode/qt4/UnicodeQt4.h: + (WTF::Unicode::toLower): + (WTF::Unicode::toUpper): + (WTF::Unicode::toTitleCase): + (WTF::Unicode::foldCase): + (WTF::Unicode::isPrintableChar): + (WTF::Unicode::isSeparatorSpace): + (WTF::Unicode::isPunct): + (WTF::Unicode::isLower): + (WTF::Unicode::mirroredChar): + (WTF::Unicode::combiningClass): + (WTF::Unicode::direction): + (WTF::Unicode::category): + +2010-10-14 Anton Faern <anton@bladehawke.com> + + Reviewed by Csaba Osztrogonác. + + https://bugs.webkit.org/show_bug.cgi?id=47658 + NetBSD was not included in the WTF_PLATFORM_FOO to WTF_OS_FOO + change. This means that OS(NETBSD) is also undefined. + + * wtf/Platform.h: s/_PLATFORM_/_OS_/ for NetBSD + +2010-10-13 David Goodwin <david_goodwin@apple.com> + + Reviewed by Oliver Hunt. + + ARMv7 JIT should generated conditional branches when possible + https://bugs.webkit.org/show_bug.cgi?id=47384 + + Use different jump padding sizes for conditional and unconditional + jumps (12 bytes and 10 bytes respectively). This allows the JIT to + include the IT instruction as part of the conditional jump sequence + which in turn allows it to optimize away the IT using an ARMv7 + conditional branch instruction. Use 2-byte B(T1) and 4-byte B(T3) for + conditional branches when displacement is in range. Also use IT/B(T4) + for conditional branch when displacement does not fit in B(T3). + + For unconditional jump, instruction selection options are: + B(T2), B(T4), MOVW/MOVT/BX. For conditional jump, instruction selection + options are: B(T1), B(T3), IT/B(T4), ITTT/MOVW/MOVT/BX. + + * assembler/ARMv7Assembler.cpp: + * assembler/ARMv7Assembler.h: + (JSC::ARMv7Assembler::JmpSrc::JmpSrc): + (JSC::ARMv7Assembler::ifThenElse): + (JSC::ARMv7Assembler::jumpSizeDelta): + (JSC::ARMv7Assembler::canCompact): + (JSC::ARMv7Assembler::computeJumpType): + (JSC::ARMv7Assembler::link): + (JSC::ARMv7Assembler::canBeJumpT1): + (JSC::ARMv7Assembler::canBeJumpT3): + (JSC::ARMv7Assembler::canBeJumpT4): + (JSC::ARMv7Assembler::linkJumpT1): + (JSC::ARMv7Assembler::linkJumpT3): + (JSC::ARMv7Assembler::linkJumpT4): + (JSC::ARMv7Assembler::linkConditionalJumpT4): + (JSC::ARMv7Assembler::linkBX): + (JSC::ARMv7Assembler::linkConditionalBX): + (JSC::ARMv7Assembler::linkJumpAbsolute): + * assembler/LinkBuffer.h: + (JSC::LinkBuffer::linkCode): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::canCompact): + (JSC::MacroAssemblerARMv7::computeJumpType): + (JSC::MacroAssemblerARMv7::jumpSizeDelta): + (JSC::MacroAssemblerARMv7::jump): + (JSC::MacroAssemblerARMv7::nearCall): + (JSC::MacroAssemblerARMv7::call): + (JSC::MacroAssemblerARMv7::ret): + (JSC::MacroAssemblerARMv7::tailRecursiveCall): + (JSC::MacroAssemblerARMv7::makeJump): + (JSC::MacroAssemblerARMv7::makeBranch): + +2010-10-13 Fridrich Strba <fridrich.strba@bluewin.ch> + + Reviewed by Darin Adler. + + Don't depend on Windows on sched_yield and sched.h + https://bugs.webkit.org/show_bug.cgi?id=45543 + + sched.h is part of pthreads and sched_yield is implemented + in pthreads-win32 as Sleep(0). This patch avoids a gratuitous + dependency on pthreads-win32 in this file. + + * wtf/TCSpinLock.h: + (TCMalloc_SlowLock): + +2010-10-13 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Kent Tamura. + + [BREWMP] Port unicode + https://bugs.webkit.org/show_bug.cgi?id=45716 + + Brew MP port uses only the subset of ICU library to reduce the binary size. + Follow the WinCE's implementation. + + * wtf/Platform.h: + * wtf/unicode/Unicode.h: + * wtf/unicode/brew/UnicodeBrew.cpp: Added. + (WTF::Unicode::toLower): + (WTF::Unicode::toUpper): + (WTF::Unicode::foldCase): + (WTF::Unicode::isPrintableChar): + (WTF::Unicode::isUpper): + (WTF::Unicode::isLower): + (WTF::Unicode::isDigit): + (WTF::Unicode::isPunct): + (WTF::Unicode::isAlphanumeric): + (WTF::Unicode::toTitleCase): + (WTF::Unicode::direction): + (WTF::Unicode::category): + (WTF::Unicode::decompositionType): + (WTF::Unicode::combiningClass): + (WTF::Unicode::mirroredChar): + (WTF::Unicode::digitValue): + (WTF::Unicode::isSpace): + (WTF::Unicode::isLetter): + * wtf/unicode/brew/UnicodeBrew.h: Added. + (WTF::Unicode::isArabicChar): + (WTF::Unicode::isSeparatorSpace): + (WTF::Unicode::hasLineBreakingPropertyComplexContext): + (WTF::Unicode::hasLineBreakingPropertyComplexContextOrIdeographic): + (WTF::Unicode::umemcasecmp): + +2010-10-13 Gavin Barraclough <barraclough@apple.com> + + Windows build fix. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-10-13 Adam Barth <abarth@webkit.org> + + Reviewed by Maciej Stachowiak. + + [WTFURL] Add URLQueryCanonicalizer + https://bugs.webkit.org/show_bug.cgi?id=45088 + + This class canonicalizes the query component of URLs. The main tricky + bit there is the convertCharset function, which I've moved to a + templated dependency. There'll likely be more about that in future + patches. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/url/src/URLEscape.cpp: Added. + * wtf/url/src/URLEscape.h: Added. + (WTF::appendEscapedCharacter): + * wtf/url/src/URLQueryCanonicalizer.h: Added. + (WTF::URLQueryCanonicalizer::canonicalize): + (WTF::URLQueryCanonicalizer::isAllASCII): + (WTF::URLQueryCanonicalizer::appendRaw8BitQueryString): + (WTF::URLQueryCanonicalizer::convertToQueryEncoding): + +2010-10-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 43987 - Downloading using XHR is much slower than before + Change StringBuilder to use overcapacity in a StringImpl, rather than a Vector. + Fundamentally this should be the same (copies current contents to expand capacity, + rather than using a rope), but this approach allows the intermadiate state of the + String to be inspected in the buffer without copying to resolve. + + * runtime/JSONObject.cpp: + (JSC::Stringifier::appendQuotedString): + (JSC::Stringifier::Holder::appendNextProperty): + Renamed StringBuilder::size() -> length() (to match other String types). + + * runtime/UStringBuilder.h: + (JSC::UStringBuilder::append): + (JSC::UStringBuilder::toUString): + Update for changes in parent class, can just 'using' the append methods. + + * wtf/text/StringBuilder.cpp: Added. + (WTF::StringBuilder::reifyString): + (WTF::StringBuilder::resize): + (WTF::StringBuilder::reserveCapacity): + (WTF::StringBuilder::allocateBuffer): + (WTF::StringBuilder::appendUninitialized): + (WTF::StringBuilder::append): + (WTF::StringBuilder::shrinkToFit): + * wtf/text/StringBuilder.h: + (WTF::StringBuilder::StringBuilder): + (WTF::StringBuilder::append): + (WTF::StringBuilder::toString): + (WTF::StringBuilder::toStringPreserveCapacity): + (WTF::StringBuilder::length): + (WTF::StringBuilder::isEmpty): + (WTF::StringBuilder::operator[]): + (WTF::StringBuilder::clear): + Class updated to use overcapacity in a StringImpl, rather than a Vector. + + * Android.mk: + * Android.v8.wtf.mk: + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/CMakeLists.txt: + * wtf/wtf.pri: + +2010-10-13 Adam Roben <aroben@apple.com> + + Export tryFastRealloc for WebKit2's benefit + + Rubber-stamped by Anders Carlsson. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Added + tryFastRealloc. Removed RegExpObject::info, which is now exported via + JS_EXPORTDATA. + +2010-10-13 Adam Barth <abarth@webkit.org> + + Reviewed by Maciej Stachowiak. + + [WTFURL] Add a mechanism for classifying types of characters + https://bugs.webkit.org/show_bug.cgi?id=45085 + + Various characters have different escaping rules depending on where + they are in URLs. This patch adds a table containing that information. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/url/src/URLCharacterTypes.cpp: Added. + * wtf/url/src/URLCharacterTypes.h: Added. + (WTF::URLCharacterTypes::isQueryChar): + (WTF::URLCharacterTypes::isIPv4Char): + (WTF::URLCharacterTypes::isHexChar): + (WTF::URLCharacterTypes::isCharOfType): + +2010-10-13 Xan Lopez <xlopez@igalia.com> + + Reviewed by Csaba Osztrogonác. + + Missing parameters for bytecode dump of next_pname + https://bugs.webkit.org/show_bug.cgi?id=47590 + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): add missing parameters to the dump. + +2010-10-13 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Dirk Schulze. + + Add wtf/text/StringConcatenate + https://bugs.webkit.org/show_bug.cgi?id=47584 + + Move runtime/StringConcatenate.h to wtf/text, make it work for Strings too. + Add a special runtime/UStringConcatenate.h class that inherits from StringConcatenate, and extends it for use with UString. + Exactly the same design that has been followed while refactoring StringBuilder. + + The UString variants can all be removed as soon as WTF::String & JSC::UString converge. + + * GNUmakefile.am: Add wtf/text/StringConcatenate.h and runtime/UStringConcatenate.h. + * JavaScriptCore.gypi: Ditto. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Ditto. + * JavaScriptCore.vcproj/WTF/WTF.vcproj: Ditto. + * JavaScriptCore.xcodeproj/project.pbxproj: Ditto. + * bytecode/CodeBlock.cpp: s/makeString/makeUString/ + (JSC::escapeQuotes): + (JSC::valueToSourceString): + (JSC::constantName): + (JSC::idName): + (JSC::CodeBlock::registerName): + (JSC::regexpToSourceString): + (JSC::regexpName): + * bytecompiler/NodesCodegen.cpp: Ditto. + (JSC::substitute): + * profiler/Profiler.cpp: Ditto. + (JSC::Profiler::createCallIdentifier): + * runtime/ExceptionHelpers.cpp: Ditto. + (JSC::createUndefinedVariableError): + (JSC::createErrorMessage): + (JSC::createInvalidParamError): + * runtime/FunctionConstructor.cpp: Ditto. + (JSC::constructFunction): + * runtime/FunctionPrototype.cpp: Ditto. + (JSC::insertSemicolonIfNeeded): + * runtime/JSONObject.cpp: Ditto. + (JSC::Stringifier::indent): + * runtime/JSStringBuilder.h: + (JSC::jsMakeNontrivialString): + * runtime/RegExpConstructor.cpp: Ditto. + (JSC::constructRegExp): + * runtime/RegExpObject.cpp: Ditto. + (JSC::RegExpObject::match): + * runtime/RegExpPrototype.cpp: Ditto. + (JSC::regExpProtoFuncCompile): + * runtime/StringConcatenate.h: Removed. + * runtime/UStringConcatenate.h: Added. Only contains the StringTypeAdapter<JSC::UString> code and the makeUString variants, the rest lives in wtf/text/StringConcatenate.h + (JSC::makeUString): + * wtf/text/StringConcatenate.h: Copied from runtime/StringConcatenate.h. + (WTF::makeString): + +2010-10-12 Gavin Barraclough <barraclough@apple.com> + + Windows build fix. + + * wtf/text/StringBuilder.h: + (WTF::StringBuilder::length): + +2010-10-12 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Gavin Barraclough. + + Unify JSC::StringBuilder & WebCore::StringBuilder + https://bugs.webkit.org/show_bug.cgi?id=47538 + + Move runtime/StringBuilder.h to wtf/text/StringBuilder.h. Rename build() to toString() and return a WTF::String(). + Move the append(const JSC::UString&) method into runtime/UStringBuilder.h. + UStringBuilder inherits from StringBuilder.h and adds append(const JSC::UString&) and UString toUString() functionality. + + No new code, just move code around. + + * GNUmakefile.am: Add wtf/text/StringBuilder.h / runtime/UStringBuilder.h. Remove runtime/StringBuilder.h. + * JavaScriptCore.gypi: Ditto. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Ditto. + * JavaScriptCore.vcproj/WTF/WTF.vcproj: Ditto. + * JavaScriptCore.xcodeproj/project.pbxproj: Ditto. + * runtime/Executable.cpp: + (JSC::FunctionExecutable::paramString): Use UStringBuilder, instead of StringBuilder. Rename build() -> toUString(). + * runtime/FunctionConstructor.cpp: + (JSC::constructFunction): Ditto. + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncUnescape): Ditto. + * runtime/JSONObject.cpp: + (JSC::Stringifier::stringify): Ditto. + (JSC::Stringifier::appendQuotedString): Ditto. + (JSC::Stringifier::appendStringifiedValue): Ditto. + (JSC::Stringifier::startNewLine): Ditto. + (JSC::Stringifier::Holder::appendNextProperty): Ditto. + * runtime/LiteralParser.cpp: + (JSC::LiteralParser::Lexer::lexString): Ditto. + * runtime/NumberPrototype.cpp: Remove unneeded JSStringBuilder.h / StringBuilder.h include. + * runtime/StringBuilder.h: Removed. + * runtime/UStringBuilder.h: Added. Inherits from WTF::StringBuilder, extending it by two methods. + (JSC::UStringBuilder::append): append(const JSC::UString&) + (JSC::UStringBuilder::toUString): + * wtf/text/StringBuilder.h: Copied from runtime/StringBuilder.h. Move JSC::UString parts into runtime/UStringBuilder.h + (WTF::StringBuilder::append): Renamed m_buffer to buffer everywhere. + (WTF::StringBuilder::isEmpty): Ditto (+ constify method). + (WTF::StringBuilder::reserveCapacity): Ditto. + (WTF::StringBuilder::resize): Ditto. + (WTF::StringBuilder::size): Ditto. + (WTF::StringBuilder::operator[]): Ditto. + (WTF::StringBuilder::toString): Ditto (+ renamed from build()). Returns a String, not an UString. The old build() method is now named toUString() and lives in UStringBuilder. + +2010-10-12 Michael Saboff <msaboff@apple.com> + + Reviewed by Oliver Hunt. + + Cleaned up the processing of replacements after regular expression + processing, especially the case where there wasn't a match. + Changed to use empty strings instead of computing a zero length sub + string. + https://bugs.webkit.org/show_bug.cgi?id=47506 + + * runtime/StringPrototype.cpp: + (JSC::jsSpliceSubstringsWithSeparators): + (JSC::stringProtoFuncReplace): + +2010-10-11 Patrick Gansterer <paroga@webkit.org> + + Unreviewed. + + Clang build fix after r69472. + https://bugs.webkit.org/show_bug.cgi?id=46523 + + * wtf/text/StringHash.h: + +2010-10-11 Oliver Hunt <oliver@apple.com> + + Undo last minute change to 32bit build. + + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_convert_this_strict): + +2010-10-11 Brian Weinstein <bweinstein@apple.com> + + Build fix for Windows. Add a necessary export from r69516. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-10-11 Oliver Hunt <oliver@apple.com> + + Fix interpreter build -- was broken by incorrect merge. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + +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. + + Windows build fix after r69472. + + * wtf/text/StringHash.h: + (WTF::CaseFoldingHash::hash): + +2010-10-10 Patrick Gansterer <paroga@webkit.org> + + Reviewed by Adam Barth. + + Use WTF::StringHasher in WTF::CaseFoldingHash + https://bugs.webkit.org/show_bug.cgi?id=46523 + + * wtf/text/StringHash.h: + (WTF::CaseFoldingHash::foldCase): + (WTF::CaseFoldingHash::hash): + +2010-10-09 Pratik Solanki <psolanki@apple.com> + + Reviewed by Xan Lopez. + + https://bugs.webkit.org/show_bug.cgi?id=47445 + Remove unused function WTFThreadData::initializeIdentifierTable() + + * wtf/WTFThreadData.h: + +2010-10-08 Michael Saboff <msaboff@apple.com> + + Reviewed by Darin Adler. + + Added check to start of subexpression being positive before using + subexpression in replacement. + https://bugs.webkit.org/show_bug.cgi?id=47324 + + * runtime/StringPrototype.cpp: + (JSC::substituteBackreferencesSlow): + +2010-10-08 Chris Evans <cevans@google.com> + + Reviewed by David Levin. + + https://bugs.webkit.org/show_bug.cgi?id=47393 + + Use unsigned consistently to check for max StringImpl length. + Add a few integer overflow checks. + Uses the existing paradigm of CRASH() when we can't reasonably handle a crazily large request. + + * wtf/text/WTFString.cpp: + * wtf/text/StringImpl.h: + * wtf/text/StringImpl.cpp: + Better use of size_t vs. unsigned; check for integer overflows. + +2010-10-07 David Goodwin <david_goodwin@apple.com> + + Reviewed by Oliver Hunt. + + ARM JIT generates undefined operations due to partially uninitialized ShiftTypeAndAmount + https://bugs.webkit.org/show_bug.cgi?id=47356 + + * assembler/ARMv7Assembler.h: + +2010-10-06 Chris Evans <cevans@google.com> + + Reviewed by David Levin. + + https://bugs.webkit.org/show_bug.cgi?id=47248 + + Use size_t consistently in CString, to prevent theoretical trouble + with > 4GB strings on 64-bit platforms. + + * wtf/text/CString.h: + * wtf/text/CString.cpp: + Use size_t for string lengths. + * wtf/MD5.cpp: + (WTF::expectMD5): use suitable format string + cast for size_t. + * JavaScriptCore.exp: + Update symbol name. + +2010-10-06 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Start cleaning up Arguments.h + https://bugs.webkit.org/show_bug.cgi?id=47304 + + * wtf/TypeTraits.h: + * wtf/TypeTraits.cpp: + Add RemoveReference type trait. + +2010-10-06 Rafael Antognolli <antognolli@profusion.mobi> + + Unreviewed build fix. + + [EFL] Build fix for glib support. + https://bugs.webkit.org/show_bug.cgi?id=47221 + + If compiling with GLib support enabled, we also need to link wtf against + glib library. + + * wtf/CMakeListsEfl.txt: + +2010-10-05 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Gavin Barraclough. + + [BREWMP] Port ExecutableAllocator::cacheFlush to enable ARM JIT + https://bugs.webkit.org/show_bug.cgi?id=47117 + + Use IMemCache1 to flush data cache and invalidate instruction cache. + + * jit/ExecutableAllocator.h: + (JSC::ExecutableAllocator::cacheFlush): + +2010-10-05 Leandro Pereira <leandro@profusion.mobi> + + Unreviewed. Build fix. + + Moved "jsc" directory to "shell", so that the name does not clash with the + JavaScriptCore shell in some build systems. + http://webkit.org/b/47049 + + * CMakeLists.txt: Changed reference from "jsc" to "shell". + * jsc: Removed. + * jsc/CMakeLists.txt: Removed. + * jsc/CMakeListsEfl.txt: Removed. + * shell: Copied from JavaScriptCore/jsc. + +2010-10-05 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Kent Tamura. + + [BREWMP] Use PlatformRefPtr in randomNumber + https://bugs.webkit.org/show_bug.cgi?id=46989 + + Use PlatformRefPtr to free memory automatically. + + * wtf/RandomNumber.cpp: + (WTF::randomNumber): + +2010-10-05 Oliver Hunt <oliver@apple.com> + + Reviewed by Darin Adler. + + REGRESSION(r68338): JavaScript error on PowerPC only (crashes on Interpreter built for x86_64) + https://bugs.webkit.org/show_bug.cgi?id=46690 + + Use the correct register value when initialising the arguments + object in the interpreter. This is covered by existing tests. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + +2010-10-04 David Goodwin <david_goodwin@apple.com> + + Reviewed by Oliver Hunt. + + ARMv7 JIT should take advantage of 2-byte branches to reduce code size + https://bugs.webkit.org/show_bug.cgi?id=47007 + + * assembler/ARMv7Assembler.cpp: + * assembler/ARMv7Assembler.h: + (JSC::ARMv7Assembler::computeJumpType): + (JSC::ARMv7Assembler::link): + (JSC::ARMv7Assembler::canBeJumpT2): + (JSC::ARMv7Assembler::canBeJumpT4): + (JSC::ARMv7Assembler::linkBX): + (JSC::ARMv7Assembler::linkJumpT4): + (JSC::ARMv7Assembler::linkJumpT2): + (JSC::ARMv7Assembler::linkJumpAbsolute): + +2010-10-04 Gyuyoung Kim <gyuyoung.kim@samsung.com> + + Reviewed by Antonio Gomes. + + [EFL] Use fast malloc for WebKit EFL + https://bugs.webkit.org/show_bug.cgi?id=46691 + + Use fast malloc for WebKit EFL because the fast malloc is to allocate + memory quickly. + + * wtf/CMakeListsEfl.txt: + +2010-10-04 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + Lazily create activation objects + https://bugs.webkit.org/show_bug.cgi?id=47107 + + Make it possible to lazily create the activation object + for a function that needs one. This allows us to reduce + the overhead of entering a function that may require + an activation in some cases, but not always. + + This does make exception handling a little more complex as + it's now necessary to verify that a callframes activation + has been created, and create it if not, in all of the + paths used in exception handling. + + We also need to add logic to check for the existence of + the activation in the scoped_var opcodes, as well as + op_ret, op_ret_object_or_this and op_tearoff_activation + so that we can avoid creating an activation unnecesarily + on function exit. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): + (JSC::CodeBlock::createActivation): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::setActivationRegister): + (JSC::CodeBlock::activationRegister): + * bytecode/Opcode.h: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): + (JSC::BytecodeGenerator::emitNewFunctionInternal): + (JSC::BytecodeGenerator::emitNewFunctionExpression): + (JSC::BytecodeGenerator::createActivationIfNecessary): + * bytecompiler/BytecodeGenerator.h: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::resolveSkip): + (JSC::Interpreter::resolveGlobalDynamic): + (JSC::Interpreter::resolveBase): + (JSC::Interpreter::unwindCallFrame): + (JSC::Interpreter::throwException): + (JSC::Interpreter::privateExecute): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JIT.h: + * jit/JITCall32_64.cpp: + (JSC::JIT::emit_op_ret): + (JSC::JIT::emit_op_ret_object_or_this): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_end): + (JSC::JIT::emit_op_get_scoped_var): + (JSC::JIT::emit_op_put_scoped_var): + (JSC::JIT::emit_op_tear_off_activation): + (JSC::JIT::emit_op_ret): + (JSC::JIT::emit_op_ret_object_or_this): + (JSC::JIT::emit_op_create_activation): + (JSC::JIT::emit_op_resolve_global_dynamic): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_get_scoped_var): + (JSC::JIT::emit_op_put_scoped_var): + (JSC::JIT::emit_op_tear_off_activation): + (JSC::JIT::emit_op_create_activation): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + +2010-10-04 Adam Barth <abarth@webkit.org> + + Reviewed by Sam Weinig. + + Remove ENABLE_SANDBOX + https://bugs.webkit.org/show_bug.cgi?id=47032 + + * Configurations/FeatureDefines.xcconfig: + +2010-10-01 Pratik Solanki <psolanki@apple.com> + + Reviewed by Geoffrey Garen. + Specify ALWAYS_INLINE at function declaration not function definition + https://bugs.webkit.org/show_bug.cgi?id=46960 + + For functions defined with ALWAYS_INLINE, add the attribute to the declaration as well. + + * bytecompiler/BytecodeGenerator.h: + * wtf/FastMalloc.cpp: + +2010-10-01 Kwang Yul Seo <skyul@company100.net> + + Unreviewed. + + [BREWMP] Change Collector BLOCK_SIZE to 64KB + https://bugs.webkit.org/show_bug.cgi?id=46436 + + Lower BLOCK_SIZE to 64KB because Brew MP runs on low end devices. + + * runtime/Collector.h: + +2010-10-01 Viatcheslav Ostapenko <ostapenko.viatcheslav@nokia.com> + + Reviewed by Andreas Kling. + + [Qt] Stack overflow on symbian platform. + https://bugs.webkit.org/show_bug.cgi?id=40598 + + Move big allocation in arrayProtoFuncToString from stack to heap. + JSC::arrayProtoFuncToString function can be called recursivly and + 1K allocation on stack cahse stack overflow. + Can be useful for other platforms with limited stack size. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + +2010-09-30 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Kent Tamura. + + [BREWMP] Add a factory function which returns an instance wrapped in PlatformRefPtr. + https://bugs.webkit.org/show_bug.cgi?id=46373 + + A Brew MP instance has reference count 1 when it is created, so call adoptPlatformRef + to wrap the instance in PlatformRefPtr. + + * wtf/brew/ShellBrew.h: + (WTF::createRefPtrInstance): + +2010-09-30 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Kent Tamura. + + [BREWMP] Port PlatformRefPtr + https://bugs.webkit.org/show_bug.cgi?id=46370 + + Implement refPlatformPtr and derefPlatformPtr to use PlatformRefPtr in Brew MP. + + * wtf/brew/RefPtrBrew.h: Added. + (WTF::refPlatformPtr): + (WTF::derefPlatformPtr): + +2010-09-29 Sam Weinig <sam@webkit.org> + + Reviewed by Darin Adler. + + Add additional checks to StringBuffer. + <rdar://problem/7756381> + + * wtf/text/StringBuffer.h: + (WTF::StringBuffer::StringBuffer): + (WTF::StringBuffer::resize): + +2010-09-30 Chris Marrin <cmarrin@apple.com> + + Reviewed by Simon Fraser. + + Make 2D accelerated canvas rendering build on Mac + https://bugs.webkit.org/show_bug.cgi?id=46007 + + Added ACCELERATED_2D_CANVAS to FeatureDefines + + * Configurations/FeatureDefines.xcconfig: + +2010-09-30 Kevin Ollivier <kevino@theolliviers.com> + + [wx] wxMSW build fix. Make sure we copy the compiler flags and remove exception handling from + the copy so as not to alter global settings. + + * wscript: + +2010-09-30 Peter Varga <pvarga@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + The case-insensitivity backreference checking isn't working with YARR + Interpreter + https://bugs.webkit.org/show_bug.cgi?id=46882 + + Add ignorecase checking to the Interpreter::tryConsumeBackReference() function. + + * yarr/RegexInterpreter.cpp: + (JSC::Yarr::Interpreter::tryConsumeBackReference): + +2010-09-30 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Andreas Kling. + + [BREWMP] Leave initializeRandomNumberGenerator empty. + https://bugs.webkit.org/show_bug.cgi?id=46851 + + On Brew MP, AEECLSID_RANDOM initializes itself. + + * wtf/RandomNumberSeed.h: + (WTF::initializeRandomNumberGenerator): + +2010-09-30 Gabor Loki <loki@webkit.org> + + Reviewed by Csaba Osztrogonác. + + Remove unnecessary cacheFlush calls from Thumb-2 + https://bugs.webkit.org/show_bug.cgi?id=46702 + + * assembler/ARMv7Assembler.h: + (JSC::ARMv7Assembler::relinkCall): + (JSC::ARMv7Assembler::repatchInt32): + (JSC::ARMv7Assembler::repatchPointer): + 2010-09-29 Patrick Gansterer <paroga@webkit.org> Unreviewed. diff --git a/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/JavaScriptCore/Configurations/FeatureDefines.xcconfig index 2ed3a8e..4c698ce 100644 --- a/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -33,6 +33,11 @@ ENABLE_LINK_PREFETCH = ; +ENABLE_ACCELERATED_2D_CANVAS = $(ENABLE_ACCELERATED_2D_CANVAS_$(REAL_PLATFORM_NAME)); +ENABLE_ACCELERATED_2D_CANVAS_macosx = $(ENABLE_ACCELERATED_2D_CANVAS_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +ENABLE_ACCELERATED_2D_CANVAS_macosx_1060 = ; +ENABLE_ACCELERATED_2D_CANVAS_macosx_1070 = ; + ENABLE_3D_CANVAS = $(ENABLE_3D_CANVAS_$(REAL_PLATFORM_NAME)); ENABLE_3D_CANVAS_macosx = $(ENABLE_3D_CANVAS_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR)); ENABLE_3D_CANVAS_macosx_1060 = ENABLE_3D_CANVAS; @@ -88,9 +93,6 @@ ENABLE_PROGRESS_TAG = ENABLE_PROGRESS_TAG; ENABLE_RUBY = $(ENABLE_RUBY_$(REAL_PLATFORM_NAME)); ENABLE_RUBY_macosx = ENABLE_RUBY; -ENABLE_SANDBOX = $(ENABLE_SANDBOX_$(REAL_PLATFORM_NAME)); -ENABLE_SANDBOX_macosx = ENABLE_SANDBOX; - ENABLE_SHARED_WORKERS = $(ENABLE_SHARED_WORKERS_$(REAL_PLATFORM_NAME)); ENABLE_SHARED_WORKERS_macosx = ENABLE_SHARED_WORKERS; @@ -119,4 +121,4 @@ ENABLE_XHTMLMP = ; ENABLE_XPATH = ENABLE_XPATH; ENABLE_XSLT = ENABLE_XSLT; -FEATURE_DEFINES = $(ENABLE_LINK_PREFETCH) $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_FILE_SYSTEM) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_IMAGE_RESIZER) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_METER_TAG) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_PROGRESS_TAG) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT); +FEATURE_DEFINES = $(ENABLE_LINK_PREFETCH) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_FILE_SYSTEM) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_IMAGE_RESIZER) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_METER_TAG) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_PROGRESS_TAG) $(ENABLE_RUBY) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT); diff --git a/JavaScriptCore/Configurations/Version.xcconfig b/JavaScriptCore/Configurations/Version.xcconfig index f688ea8..35ae251 100644 --- a/JavaScriptCore/Configurations/Version.xcconfig +++ b/JavaScriptCore/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 534; -MINOR_VERSION = 10; +MINOR_VERSION = 11; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am index 88d1761..c507f5d 100644 --- a/JavaScriptCore/GNUmakefile.am +++ b/JavaScriptCore/GNUmakefile.am @@ -388,8 +388,8 @@ javascriptcore_sources += \ JavaScriptCore/runtime/ScopeChainMark.h \ JavaScriptCore/runtime/SmallStrings.cpp \ JavaScriptCore/runtime/SmallStrings.h \ - JavaScriptCore/runtime/StringBuilder.h \ - JavaScriptCore/runtime/StringConcatenate.h \ + JavaScriptCore/runtime/StrictEvalActivation.cpp \ + JavaScriptCore/runtime/StrictEvalActivation.h \ JavaScriptCore/runtime/StringConstructor.cpp \ JavaScriptCore/runtime/StringConstructor.h \ JavaScriptCore/runtime/StringObject.cpp \ @@ -409,6 +409,8 @@ javascriptcore_sources += \ JavaScriptCore/runtime/Tracing.h \ JavaScriptCore/runtime/UString.cpp \ JavaScriptCore/runtime/UString.h \ + JavaScriptCore/runtime/UStringBuilder.h \ + JavaScriptCore/runtime/UStringConcatenate.h \ JavaScriptCore/runtime/WeakGCMap.h \ JavaScriptCore/runtime/WeakGCPtr.h \ JavaScriptCore/runtime/WeakRandom.h \ @@ -428,6 +430,7 @@ javascriptcore_sources += \ JavaScriptCore/wtf/DateMath.cpp \ JavaScriptCore/wtf/DateMath.h \ JavaScriptCore/wtf/DecimalNumber.h \ + JavaScriptCore/wtf/DecimalNumber.cpp \ JavaScriptCore/wtf/Deque.h \ JavaScriptCore/wtf/DisallowCType.h \ JavaScriptCore/wtf/dtoa.cpp \ @@ -466,6 +469,7 @@ javascriptcore_sources += \ JavaScriptCore/wtf/NonCopyingSort.h \ JavaScriptCore/wtf/Noncopyable.h \ JavaScriptCore/wtf/NotFound.h \ + JavaScriptCore/wtf/NullPtr.h \ JavaScriptCore/wtf/OwnArrayPtr.h \ JavaScriptCore/wtf/OwnFastMallocPtr.h \ JavaScriptCore/wtf/OwnArrayPtrCommon.h \ @@ -493,7 +497,7 @@ javascriptcore_sources += \ JavaScriptCore/wtf/StaticConstructors.h \ JavaScriptCore/wtf/StdLibExtras.h \ JavaScriptCore/wtf/StringExtras.h \ - JavaScriptCore/wtf/StringHashFunctions.h \ + JavaScriptCore/wtf/StringHasher.h \ JavaScriptCore/wtf/TCPackedCache.h \ JavaScriptCore/wtf/TCPageMap.h \ JavaScriptCore/wtf/TCSpinLock.h \ @@ -506,6 +510,9 @@ javascriptcore_sources += \ JavaScriptCore/wtf/text/CString.cpp \ JavaScriptCore/wtf/text/CString.h \ JavaScriptCore/wtf/text/StringBuffer.h \ + JavaScriptCore/wtf/text/StringBuilder.cpp \ + JavaScriptCore/wtf/text/StringBuilder.h \ + JavaScriptCore/wtf/text/StringConcatenate.h \ JavaScriptCore/wtf/text/StringHash.h \ JavaScriptCore/wtf/text/StringImplBase.h \ JavaScriptCore/wtf/text/StringImpl.cpp \ diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp index ff3d9b3..6ef8ead 100644 --- a/JavaScriptCore/JavaScriptCore.exp +++ b/JavaScriptCore/JavaScriptCore.exp @@ -132,6 +132,8 @@ __ZN3JSC12JSGlobalData14sharedInstanceEv __ZN3JSC12JSGlobalData15dumpRegExpTraceEv __ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE __ZN3JSC12JSGlobalDataD1Ev +__ZN3JSC12RegExpObject4infoE +__ZN3JSC12RegExpObjectC1EPNS_14JSGlobalObjectEN3WTF17NonNullPassRefPtrINS_9StructureEEENS4_INS_6RegExpEEE __ZN3JSC12SamplingTool5setupEv __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE __ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh @@ -150,7 +152,6 @@ __ZN3JSC13SamplingFlags4stopEv __ZN3JSC13SamplingFlags5startEv __ZN3JSC13SamplingFlags7s_flagsE __ZN3JSC13StatementNode6setLocEii -__ZN3JSC14heapStatisticsEPNS_12JSGlobalDataE __ZN3JSC14JSGlobalObject10globalExecEv __ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj __ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj @@ -165,6 +166,7 @@ __ZN3JSC14SamplingThread4stopEv __ZN3JSC14SamplingThread5startEj __ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE __ZN3JSC14TimeoutChecker5resetEv +__ZN3JSC14heapStatisticsEPNS_12JSGlobalDataE __ZN3JSC14throwTypeErrorEPNS_9ExecStateE __ZN3JSC15JSWrapperObject12markChildrenERNS_9MarkStackE __ZN3JSC15createTypeErrorEPNS_9ExecStateERKNS_7UStringE @@ -239,6 +241,8 @@ __ZN3JSC6JSLock4lockENS_14JSLockBehaviorE __ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE __ZN3JSC6JSLock9lockCountEv __ZN3JSC6JSLockC1EPNS_9ExecStateE +__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringES5_ +__ZN3JSC6RegExpD1Ev __ZN3JSC7JSArray12markChildrenERNS_9MarkStackE __ZN3JSC7JSArray15setSubclassDataEPv __ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE @@ -372,6 +376,11 @@ __ZN3WTF12createThreadEPFPvS0_ES0_PKc __ZN3WTF12detachThreadEj __ZN3WTF12isMainThreadEv __ZN3WTF12randomNumberEv +__ZN3WTF13StringBuilder11reifyStringEv +__ZN3WTF13StringBuilder11shrinkToFitEv +__ZN3WTF13StringBuilder6appendEPKcj +__ZN3WTF13StringBuilder6appendEPKtj +__ZN3WTF13StringBuilder6resizeEj __ZN3WTF13WTFThreadData10staticDataE __ZN3WTF13WTFThreadDataC1Ev __ZN3WTF13WTFThreadDataD1Ev @@ -458,7 +467,7 @@ __ZN3WTF6strtodEPKcPPc __ZN3WTF7CString11mutableDataEv __ZN3WTF7CString16newUninitializedEmRPc __ZN3WTF7CStringC1EPKc -__ZN3WTF7CStringC1EPKcj +__ZN3WTF7CStringC1EPKcm __ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b __ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b __ZN3WTF7xmlAtomE @@ -484,8 +493,6 @@ __ZNK3JSC10JSFunction23isHostFunctionNonInlineEv __ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_10JSFunctionE __ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE __ZNK3JSC12PropertySlot14functionGetterEPNS_9ExecStateE -__ZN3JSC12RegExpObject4infoE -__ZN3JSC12RegExpObjectC1EPNS_14JSGlobalObjectEN3WTF17NonNullPassRefPtrINS_9StructureEEENS4_INS_6RegExpEEE __ZNK3JSC14JSGlobalObject14isDynamicScopeERb __ZNK3JSC16InternalFunction9classInfoEv __ZNK3JSC16JSVariableObject16isVariableObjectEv @@ -516,8 +523,6 @@ __ZNK3JSC6JSCell9getStringEPNS_9ExecStateE __ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE __ZNK3JSC6JSCell9getUInt32ERj __ZNK3JSC6JSCell9toBooleanEPNS_9ExecStateE -__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringES5_ -__ZN3JSC6RegExpD1Ev __ZNK3JSC7ArgList8getSliceEiRS0_ __ZNK3JSC7JSArray12subclassDataEv __ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateE @@ -531,6 +536,7 @@ __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj __ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE __ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE +__ZNK3JSC8JSObject18toStrictThisObjectEPNS_9ExecStateE __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE __ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE __ZNK3JSC8JSObject8toStringEPNS_9ExecStateE @@ -539,7 +545,12 @@ __ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE __ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE __ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE __ZNK3JSC9HashTable11deleteTableEv +__ZN3WTF11dtoaRoundSFEPcdiRbRiRj +__ZN3WTF11dtoaRoundDPEPcdiRbRiRj +__ZN3WTF4dtoaEPcdRbRiRj __ZNK3WTF12AtomicString5lowerEv +__ZNK3WTF13DecimalNumber15toStringDecimalEPtj +__ZNK3WTF13DecimalNumber28bufferLengthForStringDecimalEv __ZNK3WTF6String11toIntStrictEPbi __ZNK3WTF6String12toUIntStrictEPbi __ZNK3WTF6String13toInt64StrictEPbi diff --git a/JavaScriptCore/JavaScriptCore.gypi b/JavaScriptCore/JavaScriptCore.gypi index 462960d..6252d07 100644 --- a/JavaScriptCore/JavaScriptCore.gypi +++ b/JavaScriptCore/JavaScriptCore.gypi @@ -346,6 +346,8 @@ 'runtime/Tracing.h', 'runtime/UString.cpp', 'runtime/UString.h', + 'runtime/UStringBuilder.h', + 'runtime/UStringConcatenate.h', 'runtime/WeakRandom.h', 'wtf/AlwaysInline.h', 'wtf/ASCIICType.h', @@ -363,6 +365,7 @@ 'wtf/CurrentTime.h', 'wtf/DateMath.cpp', 'wtf/DateMath.h', + 'wtf/DecimalNumber.cpp', 'wtf/Deque.h', 'wtf/DisallowCType.h', 'wtf/dtoa.cpp', @@ -422,7 +425,7 @@ 'wtf/StaticConstructors.h', 'wtf/StdLibExtras.h', 'wtf/StringExtras.h', - 'wtf/StringHashFunctions.h', + 'wtf/StringHasher.h', 'wtf/TCPackedCache.h', 'wtf/qt/MainThreadQt.cpp', 'wtf/qt/StringQt.cpp', @@ -450,6 +453,10 @@ 'wtf/text/AtomicStringImpl.h', 'wtf/text/CString.cpp', 'wtf/text/CString.h', + 'wtf/text/StringBuffer.h', + 'wtf/text/StringBuilder.cpp', + 'wtf/text/StringBuilder.h', + 'wtf/text/StringConcatenate.h', 'wtf/text/StringHash.h', 'wtf/text/StringImpl.cpp', 'wtf/text/StringImpl.h', diff --git a/JavaScriptCore/JavaScriptCore.pri b/JavaScriptCore/JavaScriptCore.pri index 57b1ce8..847576d 100644 --- a/JavaScriptCore/JavaScriptCore.pri +++ b/JavaScriptCore/JavaScriptCore.pri @@ -54,6 +54,12 @@ win32-*: DEFINES += _HAS_TR1=0 DEFINES += BUILDING_QT__ BUILDING_JavaScriptCore BUILDING_WTF +# CONFIG += text_breaking_with_icu + +contains (CONFIG, text_breaking_with_icu) { + DEFINES += WTF_USE_QT_ICU_TEXT_BREAKING=1 +} + wince* { INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/ce-compat INCLUDEPATH += $$PWD/../JavaScriptCore/os-win32 diff --git a/JavaScriptCore/JavaScriptCore.pro b/JavaScriptCore/JavaScriptCore.pro index f463f41..f83bf4c 100644 --- a/JavaScriptCore/JavaScriptCore.pro +++ b/JavaScriptCore/JavaScriptCore.pro @@ -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 \ diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index ba564f0..779b0bc 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -41,7 +41,6 @@ EXPORTS ??8JSC@@YA_NABVUString@0@0@Z ??8WTF@@YA_NABVCString@0@0@Z ?NaN@JSC@@3NB - ?utf8@UString@JSC@@QBE?AVCString@WTF@@_N@Z ?add@Identifier@JSC@@SA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVExecState@2@PBD@Z ?add@PropertyNameArray@JSC@@QAEXPAVStringImpl@WTF@@@Z ?addBytes@MD5@WTF@@QAEXPBEI@Z @@ -53,9 +52,12 @@ EXPORTS ?allocate@Heap@JSC@@QAEPAXI@Z ?allocatePropertyStorage@JSObject@JSC@@QAEXII@Z ?allocateStack@MarkStack@JSC@@CAPAXI@Z + ?append@StringBuilder@WTF@@QAEXPBDI@Z + ?append@StringBuilder@WTF@@QAEXPB_WI@Z ?ascii@UString@JSC@@QBE?AVCString@WTF@@XZ ?attach@Debugger@JSC@@QAEXPAVJSGlobalObject@2@@Z ?broadcast@ThreadCondition@WTF@@QAEXXZ + ?bufferLengthForStringDecimal@DecimalNumber@WTF@@QBEIXZ ?calculatedFunctionName@DebuggerCallFrame@JSC@@QBE?AVUString@2@XZ ?call@JSC@@YA?AVJSValue@1@PAVExecState@1@V21@W4CallType@1@ABTCallData@1@1ABVArgList@1@@Z ?callOnMainThread@WTF@@YAXP6AXPAX@Z0@Z @@ -130,6 +132,7 @@ EXPORTS ?detach@Debugger@JSC@@UAEXPAVJSGlobalObject@2@@Z ?detachThread@WTF@@YAXI@Z ?didTimeOut@TimeoutChecker@JSC@@QAE_NPAVExecState@2@@Z + ?dtoa@WTF@@YAXQADNAA_NAAHAAI@Z ?dumpSampleData@JSGlobalData@JSC@@QAEXPAVExecState@2@@Z ?empty@StringImpl@WTF@@SAPAV12@XZ ?enumerable@PropertyDescriptor@JSC@@QBE_NXZ @@ -149,10 +152,6 @@ EXPORTS ?free@WeakGCHandlePool@JSC@@QAEXPAVWeakGCHandle@2@@Z ?from@Identifier@JSC@@SA?AV12@PAVExecState@2@H@Z ?from@Identifier@JSC@@SA?AV12@PAVExecState@2@I@Z - ?number@UString@JSC@@SA?AV12@H@Z - ?number@UString@JSC@@SA?AV12@I@Z - ?number@UString@JSC@@SA?AV12@N@Z - ?numberToString@WTF@@YAINQA_W@Z ?functionGetter@PropertySlot@JSC@@ABE?AVJSValue@2@PAVExecState@2@@Z ?functionName@DebuggerCallFrame@JSC@@QBEPBVUString@2@XZ ?get@Structure@JSC@@QAEIPBVStringImpl@WTF@@AAIAAPAVJSCell@2@@Z @@ -193,7 +192,6 @@ EXPORTS ?hasTransition@Structure@JSC@@QAE_NPAVStringImpl@WTF@@I@Z ?heap@Heap@JSC@@SAPAV12@VJSValue@2@@Z ?increment@RefCountedLeakCounter@WTF@@QAEXXZ - ?info@RegExpObject@JSC@@2UClassInfo@2@B ?init@AtomicString@WTF@@SAXXZ ?init@JSGlobalObject@JSC@@AAEXPAVJSObject@2@@Z ?initializeMainThread@WTF@@YAXXZ @@ -230,6 +228,10 @@ EXPORTS ?name@JSFunction@JSC@@QAEABVUString@2@PAVExecState@2@@Z ?newUninitialized@CString@WTF@@SA?AV12@IAAPAD@Z ?nonInlineNaN@JSC@@YANXZ + ?number@UString@JSC@@SA?AV12@H@Z + ?number@UString@JSC@@SA?AV12@I@Z + ?number@UString@JSC@@SA?AV12@N@Z + ?numberToString@WTF@@YAINQA_W@Z ?objectCount@Heap@JSC@@QBEIXZ ?objectProtoFuncToString@JSC@@YI_JPAVExecState@1@@Z ?parseDateFromNullTerminatedCharacters@WTF@@YANPBD@Z @@ -257,10 +259,12 @@ EXPORTS ?randomNumber@WTF@@YANXZ ?recompileAllJSFunctions@Debugger@JSC@@QAEXPAVJSGlobalData@2@@Z ?recordExtraCost@Heap@JSC@@AAEXI@Z + ?reifyString@StringBuilder@WTF@@AAEXXZ ?releaseStack@MarkStack@JSC@@CAXPAXI@Z ?reset@ParserArena@JSC@@QAEXXZ ?reset@TimeoutChecker@JSC@@QAEXXZ ?resetDateCache@JSGlobalData@JSC@@QAEXXZ + ?resize@StringBuilder@WTF@@QAEXI@Z ?resolveRope@JSString@JSC@@ABEXPAVExecState@2@@Z ?restoreAll@Profile@JSC@@QAEXXZ ?retrieveCaller@Interpreter@JSC@@QBE?AVJSValue@2@PAVExecState@2@PAVJSFunction@2@@Z @@ -280,6 +284,7 @@ EXPORTS ?setUpStaticFunctionSlot@JSC@@YAXPAVExecState@1@PBVHashEntry@1@PAVJSObject@1@ABVIdentifier@1@AAVPropertySlot@1@@Z ?setWritable@PropertyDescriptor@JSC@@QAEX_N@Z ?setter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ + ?shrinkToFit@StringBuilder@WTF@@QAEXXZ ?signal@ThreadCondition@WTF@@QAEXXZ ?size@Heap@JSC@@QBEIXZ ?slowAppend@MarkedArgumentBuffer@JSC@@AAEXVJSValue@2@@Z @@ -315,6 +320,8 @@ EXPORTS ?toObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@@Z ?toPrimitive@JSCell@JSC@@UBE?AVJSValue@2@PAVExecState@2@W4PreferredPrimitiveType@2@@Z ?toPrimitive@JSString@JSC@@EBE?AVJSValue@2@PAVExecState@2@W4PreferredPrimitiveType@2@@Z + ?toStrictThisObject@JSObject@JSC@@UBE?AVJSValue@2@PAVExecState@2@@Z + ?toStringDecimal@DecimalNumber@WTF@@QBEIPA_WI@Z ?toString@JSCell@JSC@@UBE?AVUString@2@PAVExecState@2@@Z ?toString@JSObject@JSC@@UBE?AVUString@2@PAVExecState@2@@Z ?toString@JSString@JSC@@EBE?AVUString@2@PAVExecState@2@@Z @@ -325,6 +332,7 @@ EXPORTS ?toUInt32@Identifier@JSC@@SAIABVUString@2@AA_N@Z ?tryFastCalloc@WTF@@YA?AUTryMallocReturnValue@1@II@Z ?tryFastMalloc@WTF@@YA?AUTryMallocReturnValue@1@I@Z + ?tryFastRealloc@WTF@@YA?AUTryMallocReturnValue@1@PAXI@Z ?tryLock@Mutex@WTF@@QAE_NXZ ?type@DebuggerCallFrame@JSC@@QBE?AW4Type@12@XZ ?unlock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z @@ -332,6 +340,7 @@ EXPORTS ?unlockAtomicallyInitializedStaticMutex@WTF@@YAXXZ ?unprotect@Heap@JSC@@QAE_NVJSValue@2@@Z ?unwrappedObject@JSObject@JSC@@UAEPAV12@XZ + ?utf8@UString@JSC@@QBE?AVCString@WTF@@_N@Z ?wait@ThreadCondition@WTF@@QAEXAAVMutex@2@@Z ?waitForThreadCompletion@WTF@@YAHIPAPAX@Z ?writable@PropertyDescriptor@JSC@@QBE_NXZ diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index 83d34e3..4823286 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -1173,6 +1173,14 @@ >
</File>
<File
+ RelativePath="..\..\runtime\StrictEvalActivation.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\runtime\StrictEvalActivation.h"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\StringConstructor.cpp"
>
</File>
@@ -1245,6 +1253,14 @@ >
</File>
<File
+ RelativePath="..\..\runtime\UStringBuilder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\runtime\UStringConcatenate.h"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\UStringImpl.h"
>
</File>
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops index c92196e..6929c8a 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops @@ -19,7 +19,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\AtomicString.cpp" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\StringImpl.cpp" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\WTFString.cpp" "$(WebKitOutputDir)\include\private\JavaScriptCore"


mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
<Tool
Name="VCPreBuildEventTool"
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make index 098ff08..d1e5d46 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make @@ -21,6 +21,32 @@ all: xcopy /y /d "..\..\API\JSRetainPtr.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\OpaqueJSString.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\WebKitAvailability.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" + + -mkdir 2>NUL "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + + xcopy /y /d "..\..\wtf\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\wtf\text\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\wtf\unicode\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\wtf\unicode\icu\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\parser\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\runtime\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\bytecode\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\interpreter\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\assembler\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\jit\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\debugger\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\profiler\*.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\create_hash_table" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\pcre\pcre.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\wtf\text\AtomicString.cpp" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\wtf\text\StringBuilder.cpp" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\wtf\text\StringImpl.cpp" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + xcopy /y /d "..\..\wtf\text\WTFString.cpp" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + + + -mkdir 2>NUL "$(WEBKITOUTPUTDIR)\bin\JavaScriptCore.resources" + xcopy /y /d "..\JavaScriptCore.resources\*" "$(WEBKITOUTPUTDIR)\bin\JavaScriptCore.resources" + -del "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore\stdbool.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore\stdint.h" -del "$(WEBKITOUTPUTDIR)\buildfailed" @@ -28,3 +54,5 @@ clean: -del "$(WEBKITOUTPUTDIR)\buildfailed" -del /s /q "$(WEBKITOUTPUTDIR)\include\JavaScriptCore\JavaScriptCore" -del /s /q "$(WEBKITOUTPUTDIR)\obj\JavaScriptCore\DerivedSources" + -del /s /q "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore" + -del /s /q "$(WEBKITOUTPUTDIR)\bin\JavaScriptCore.resources" diff --git a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj index 42a91eb..3a53070 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj @@ -309,6 +309,14 @@ >
</File>
<File
+ RelativePath="..\..\wtf\DecimalNumber.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\DecimalNumber.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\FastAllocBase.h"
>
</File>
@@ -609,6 +617,22 @@ >
</File>
<File
+ RelativePath="..\..\wtf\text\StringBuffer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\StringBuilder.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\StringBuilder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\StringConcatenate.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\text\StringHash.h"
>
</File>
@@ -620,6 +644,10 @@ RelativePath="..\..\wtf\text\StringImpl.h"
>
</File>
+ <File
+ RelativePath="..\..\wtf\text\TextPosition.h"
+ >
+ </File>
<File
RelativePath="..\..\wtf\text\WTFString.cpp"
>
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj index 0f3e145..029a4b0 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj @@ -334,6 +334,10 @@ >
</File>
<File
+ RelativePath="$(WebKitOutputDir)\include\private\JavaScriptCore\StringBuilder.cpp"
+ >
+ </File>
+ <File
RelativePath="$(WebKitOutputDir)\include\private\JavaScriptCore\StringImpl.cpp"
>
</File>
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 675d26d..d134a73 100644 --- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -36,14 +36,18 @@ /* Begin PBXBuildFile section */ 06D358B30DAADAA4003B174E /* MainThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06D358A20DAAD9C4003B174E /* MainThread.cpp */; }; 06D358B40DAADAAA003B174E /* MainThreadMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 06D358A10DAAD9C4003B174E /* MainThreadMac.mm */; }; + 081469491264378500DFF935 /* StringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 081469481264375E00DFF935 /* StringBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; }; 088FA5BB0EF76D4300578E6F /* RandomNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 088FA5B90EF76D4300578E6F /* RandomNumber.cpp */; }; 088FA5BC0EF76D4300578E6F /* RandomNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 088FA5BA0EF76D4300578E6F /* RandomNumber.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 08CABBA61265AB3900B206CE /* StringConcatenate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0896C29E1265AB0900B1CDD3 /* StringConcatenate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 08DDA5C11264631700751732 /* UStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 08DDA5BB12645F1D00751732 /* UStringBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; }; 08E279E90EF83B10007DB523 /* RandomNumberSeed.h in Headers */ = {isa = PBXBuildFile; fileRef = 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */; }; 0B330C270F38C62300692DE3 /* TypeTraits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0B330C260F38C62300692DE3 /* TypeTraits.cpp */; }; 0B4D7E630F319AC800AD7E58 /* TypeTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0BDFFAE00FC6192900D69EF4 /* CrossThreadRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BDFFAD40FC6171000D69EF4 /* CrossThreadRefCounted.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0BDFFAE10FC6193100D69EF4 /* OwnFastMallocPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BDFFAD10FC616EC00D69EF4 /* OwnFastMallocPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */; }; + 0F29479C126E698C00B3ABF5 /* DecimalNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F29479B126E698C00B3ABF5 /* DecimalNumber.cpp */; }; 14035DB110DBFB2A00FFFFE7 /* WeakGCPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; 140566C4107EC255005DBC8D /* JSAPIValueWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC0894D50FAFBA2D00001865 /* JSAPIValueWrapper.cpp */; }; 140566D1107EC267005DBC8D /* JSStaticScopeObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7E42C190E3938830065A544 /* JSStaticScopeObject.cpp */; }; @@ -182,7 +186,7 @@ 5D53726F0E1C54880021E549 /* Tracing.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D53726E0E1C54880021E549 /* Tracing.h */; }; 5D5D8AB60E0D0A7200F9C692 /* jsc in Copy Into Framework */ = {isa = PBXBuildFile; fileRef = 932F5BE10822A1C700736975 /* jsc */; }; 5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; }; - 5D63E9AD10F2BD6E00FC8AE9 /* StringHashFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D63E9AC10F2BD6E00FC8AE9 /* StringHashFunctions.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5D63E9AD10F2BD6E00FC8AE9 /* StringHasher.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D63E9AC10F2BD6E00FC8AE9 /* StringHasher.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5D6A566B0F05995500266145 /* Threading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5D6A566A0F05995500266145 /* Threading.cpp */; }; 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */ = {isa = PBXBuildFile; fileRef = F692A8540255597D01FF60F7 /* create_hash_table */; settings = {ATTRIBUTES = (); }; }; 6507D29E0E871E5E00D7D896 /* JSTypeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 6507D2970E871E4A00D7D896 /* JSTypeInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -201,8 +205,9 @@ 8626BECF11928E3900782FAB /* StringStatics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8626BECE11928E3900782FAB /* StringStatics.cpp */; }; 8627E5EB11F1281900A313B5 /* PageAllocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8627E5E911F1281900A313B5 /* PageAllocation.cpp */; }; 8627E5EC11F1281900A313B5 /* PageAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8627E5EA11F1281900A313B5 /* PageAllocation.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 862AF4B612239C7B0024E5B8 /* DecimalNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 862AF4B512239C7B0024E5B8 /* DecimalNumber.h */; }; + 862AF4B612239C7B0024E5B8 /* DecimalNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 862AF4B512239C7B0024E5B8 /* DecimalNumber.h */; settings = {ATTRIBUTES = (Private, ); }; }; 863B23E00FC6118900703AA4 /* MacroAssemblerCodeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 86438FC41265503E00E0DFCA /* StringBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86438FC31265503E00E0DFCA /* StringBuilder.cpp */; }; 86565742115BE3DA00291F40 /* CString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86565740115BE3DA00291F40 /* CString.cpp */; }; 86565743115BE3DA00291F40 /* CString.h in Headers */ = {isa = PBXBuildFile; fileRef = 86565741115BE3DA00291F40 /* CString.h */; settings = {ATTRIBUTES = (Private, ); }; }; 865F408810E7D56300947361 /* APIShims.h in Headers */ = {isa = PBXBuildFile; fileRef = 865F408710E7D56300947361 /* APIShims.h */; }; @@ -217,13 +222,11 @@ 868BFA18117CF19900B908B1 /* WTFString.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA16117CF19900B908B1 /* WTFString.h */; settings = {ATTRIBUTES = (Private, ); }; }; 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA5F117D048200B908B1 /* StaticConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; }; 8690231512092D5C00630AF9 /* PageReservation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8690231412092D5C00630AF9 /* PageReservation.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 8698B86910D44D9400D8D01B /* StringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 8698B86810D44D9400D8D01B /* StringBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; }; 869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */ = {isa = PBXBuildFile; fileRef = 869EBCB60E8C6D4A008722CC /* ResultType.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */; }; 86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */; }; 86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */; }; - 86B6DA0212132B9A000D316F /* StringConcatenate.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B6DA0112132B9A000D316F /* StringConcatenate.h */; }; 86B99AB8117E391E00DF5A90 /* RopeImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86B99AB6117E391E00DF5A90 /* RopeImpl.cpp */; }; 86B99AB9117E391E00DF5A90 /* RopeImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AB7117E391E00DF5A90 /* RopeImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE1117E578100DF5A90 /* StringBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -275,6 +278,7 @@ 932F5BEA0822A1C700736975 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; }; 933040040E6A749400786E6A /* SmallStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 93303FEA0E6A72C000786E6A /* SmallStrings.h */; settings = {ATTRIBUTES = (Private, ); }; }; 9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93303FE80E6A72B500786E6A /* SmallStrings.cpp */; }; + 933F5CDC1269229B0049191E /* NullPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 933F5CDB126922690049191E /* NullPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; 937013480CA97E0E00FA14D3 /* pcre_ucp_searchfuncs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 937013470CA97E0E00FA14D3 /* pcre_ucp_searchfuncs.cpp */; settings = {COMPILER_FLAGS = "-Wno-sign-compare"; }; }; 93E26BD408B1514100F85226 /* pcre_xclass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93E26BD308B1514100F85226 /* pcre_xclass.cpp */; }; 9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 952C63AC0E4777D600C13936 /* JSProfilerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -310,6 +314,8 @@ 9714AF5F122F32070092D9F5 /* ParsedURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 9714AF58122F31F50092D9F5 /* ParsedURL.h */; }; 9714AF60122F32070092D9F5 /* URLString.h in Headers */ = {isa = PBXBuildFile; fileRef = 9714AF59122F31F50092D9F5 /* URLString.h */; }; 971EDEA61169E0D3005E4262 /* Terminator.h in Headers */ = {isa = PBXBuildFile; fileRef = 97F6903A1169DF7F00A6BB46 /* Terminator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 972A485F12661E0800F4514F /* URLCharacterTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 972A485D12661E0800F4514F /* URLCharacterTypes.cpp */; }; + 972A48771266256F00F4514F /* URLEscape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 972A48741266256F00F4514F /* URLEscape.cpp */; }; A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1712B3A11C7B212007A5315 /* RegExpCache.cpp */; }; A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B3E11C7B228007A5315 /* RegExpCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B4011C7B235007A5315 /* RegExpKey.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -318,6 +324,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, ); }; }; @@ -627,14 +635,19 @@ 06D358A10DAAD9C4003B174E /* MainThreadMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MainThreadMac.mm; sourceTree = "<group>"; }; 06D358A20DAAD9C4003B174E /* MainThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainThread.cpp; sourceTree = "<group>"; }; 06D358A30DAAD9C4003B174E /* MainThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainThread.h; sourceTree = "<group>"; }; + 081469481264375E00DFF935 /* StringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringBuilder.h; path = text/StringBuilder.h; sourceTree = "<group>"; }; 088FA5B90EF76D4300578E6F /* RandomNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RandomNumber.cpp; sourceTree = "<group>"; }; 088FA5BA0EF76D4300578E6F /* RandomNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomNumber.h; sourceTree = "<group>"; }; + 0896C29B1265AAF600B1CDD3 /* UStringConcatenate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UStringConcatenate.h; sourceTree = "<group>"; }; + 0896C29E1265AB0900B1CDD3 /* StringConcatenate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringConcatenate.h; path = text/StringConcatenate.h; sourceTree = "<group>"; }; + 08DDA5BB12645F1D00751732 /* UStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UStringBuilder.h; sourceTree = "<group>"; }; 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomNumberSeed.h; sourceTree = "<group>"; }; 0B330C260F38C62300692DE3 /* TypeTraits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeTraits.cpp; sourceTree = "<group>"; }; 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeTraits.h; sourceTree = "<group>"; }; 0BDFFAD10FC616EC00D69EF4 /* OwnFastMallocPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnFastMallocPtr.h; sourceTree = "<group>"; }; 0BDFFAD40FC6171000D69EF4 /* CrossThreadRefCounted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossThreadRefCounted.h; sourceTree = "<group>"; }; 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SizeLimits.cpp; sourceTree = "<group>"; }; + 0F29479B126E698C00B3ABF5 /* DecimalNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DecimalNumber.cpp; sourceTree = "<group>"; }; 14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCPtr.h; sourceTree = "<group>"; }; 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBasePrivate.h; sourceTree = "<group>"; }; 141211020A48780900480255 /* minidom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = minidom.c; path = tests/minidom.c; sourceTree = "<group>"; }; @@ -741,7 +754,7 @@ 5D53726E0E1C54880021E549 /* Tracing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Tracing.h; sourceTree = "<group>"; }; 5D53727D0E1C55EC0021E549 /* TracingDtrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TracingDtrace.h; sourceTree = "<group>"; }; 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.dylib; sourceTree = "<absolute>"; }; - 5D63E9AC10F2BD6E00FC8AE9 /* StringHashFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringHashFunctions.h; sourceTree = "<group>"; }; + 5D63E9AC10F2BD6E00FC8AE9 /* StringHasher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringHasher.h; sourceTree = "<group>"; }; 5D6A566A0F05995500266145 /* Threading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Threading.cpp; sourceTree = "<group>"; }; 5DA479650CFBCF56009328A0 /* TCPackedCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TCPackedCache.h; sourceTree = "<group>"; }; 5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MallocZoneSupport.h; sourceTree = "<group>"; }; @@ -803,6 +816,7 @@ 8627E5EA11F1281900A313B5 /* PageAllocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageAllocation.h; sourceTree = "<group>"; }; 862AF4B512239C7B0024E5B8 /* DecimalNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DecimalNumber.h; sourceTree = "<group>"; }; 863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerCodeRef.h; sourceTree = "<group>"; }; + 86438FC31265503E00E0DFCA /* StringBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringBuilder.cpp; path = text/StringBuilder.cpp; sourceTree = "<group>"; }; 86565740115BE3DA00291F40 /* CString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CString.cpp; path = text/CString.cpp; sourceTree = "<group>"; }; 86565741115BE3DA00291F40 /* CString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CString.h; path = text/CString.h; sourceTree = "<group>"; }; 865F408710E7D56300947361 /* APIShims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIShims.h; sourceTree = "<group>"; }; @@ -820,13 +834,11 @@ 868BFA16117CF19900B908B1 /* WTFString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WTFString.h; path = text/WTFString.h; sourceTree = "<group>"; }; 868BFA5F117D048200B908B1 /* StaticConstructors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticConstructors.h; sourceTree = "<group>"; }; 8690231412092D5C00630AF9 /* PageReservation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageReservation.h; sourceTree = "<group>"; }; - 8698B86810D44D9400D8D01B /* StringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringBuilder.h; sourceTree = "<group>"; }; 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedTranscendentalFunction.h; sourceTree = "<group>"; }; 869EBCB60E8C6D4A008722CC /* ResultType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultType.h; sourceTree = "<group>"; }; 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic.cpp; sourceTree = "<group>"; }; 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMv7Assembler.h; sourceTree = "<group>"; }; 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARMv7.h; sourceTree = "<group>"; }; - 86B6DA0112132B9A000D316F /* StringConcatenate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringConcatenate.h; sourceTree = "<group>"; }; 86B99AB6117E391E00DF5A90 /* RopeImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RopeImpl.cpp; sourceTree = "<group>"; }; 86B99AB7117E391E00DF5A90 /* RopeImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RopeImpl.h; sourceTree = "<group>"; }; 86B99AE1117E578100DF5A90 /* StringBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringBuffer.h; path = text/StringBuffer.h; sourceTree = "<group>"; }; @@ -882,6 +894,7 @@ 93303FEA0E6A72C000786E6A /* SmallStrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmallStrings.h; sourceTree = "<group>"; }; 933A349A038AE7C6008635CE /* Identifier.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Identifier.h; sourceTree = "<group>"; tabWidth = 8; }; 933A349D038AE80F008635CE /* Identifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Identifier.cpp; sourceTree = "<group>"; tabWidth = 8; }; + 933F5CDB126922690049191E /* NullPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NullPtr.h; sourceTree = "<group>"; }; 935AF46909E9D9DB00ACD1D8 /* Forward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Forward.h; sourceTree = "<group>"; }; 935AF46B09E9D9DB00ACD1D8 /* UnusedParam.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnusedParam.h; sourceTree = "<group>"; }; 937013470CA97E0E00FA14D3 /* pcre_ucp_searchfuncs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pcre_ucp_searchfuncs.cpp; sourceTree = "<group>"; }; @@ -939,6 +952,11 @@ 9714AF57122F31F50092D9F5 /* ParsedURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ParsedURL.cpp; path = url/api/ParsedURL.cpp; sourceTree = "<group>"; }; 9714AF58122F31F50092D9F5 /* ParsedURL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ParsedURL.h; path = url/api/ParsedURL.h; sourceTree = "<group>"; }; 9714AF59122F31F50092D9F5 /* URLString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = URLString.h; path = url/api/URLString.h; sourceTree = "<group>"; }; + 972A485D12661E0800F4514F /* URLCharacterTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = URLCharacterTypes.cpp; path = url/src/URLCharacterTypes.cpp; sourceTree = "<group>"; }; + 972A485E12661E0800F4514F /* URLCharacterTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = URLCharacterTypes.h; path = url/src/URLCharacterTypes.h; sourceTree = "<group>"; }; + 972A48741266256F00F4514F /* URLEscape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = URLEscape.cpp; path = url/src/URLEscape.cpp; sourceTree = "<group>"; }; + 972A48751266256F00F4514F /* URLEscape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = URLEscape.h; path = url/src/URLEscape.h; sourceTree = "<group>"; }; + 972A48761266256F00F4514F /* URLQueryCanonicalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = URLQueryCanonicalizer.h; path = url/src/URLQueryCanonicalizer.h; sourceTree = "<group>"; }; 97F6903A1169DF7F00A6BB46 /* Terminator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Terminator.h; sourceTree = "<group>"; }; A1712B3A11C7B212007A5315 /* RegExpCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpCache.cpp; sourceTree = "<group>"; }; A1712B3E11C7B228007A5315 /* RegExpCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpCache.h; sourceTree = "<group>"; }; @@ -951,6 +969,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>"; }; @@ -1470,6 +1490,7 @@ 41359CF40FDD89CB00206180 /* DateMath.cpp */, 41359CF50FDD89CB00206180 /* DateMath.h */, 862AF4B512239C7B0024E5B8 /* DecimalNumber.h */, + 0F29479B126E698C00B3ABF5 /* DecimalNumber.cpp */, 5186111D0CC824830081412B /* Deque.h */, 938C4F6B0CA06BCE00D9310A /* DisallowCType.h */, 651F6412039D5B5F0078395C /* dtoa.cpp */, @@ -1501,6 +1522,7 @@ 65E1A2F4122B880D00B26097 /* NonCopyingSort.h */, 9303F5690991190000AD71B8 /* Noncopyable.h */, C0A2723F0E509F1E00E96E15 /* NotFound.h */, + 933F5CDB126922690049191E /* NullPtr.h */, 9303F5A409911A5800AD71B8 /* OwnArrayPtr.h */, BCFBE697122561D200309E9D /* OwnArrayPtrCommon.h */, 0BDFFAD10FC616EC00D69EF4 /* OwnFastMallocPtr.h */, @@ -1528,7 +1550,7 @@ 868BFA5F117D048200B908B1 /* StaticConstructors.h */, FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */, E11D51750B2E798D0056C188 /* StringExtras.h */, - 5D63E9AC10F2BD6E00FC8AE9 /* StringHashFunctions.h */, + 5D63E9AC10F2BD6E00FC8AE9 /* StringHasher.h */, 5DA479650CFBCF56009328A0 /* TCPackedCache.h */, 6541BD6E08E80A17002CBEE7 /* TCPageMap.h */, 6541BD6F08E80A17002CBEE7 /* TCSpinLock.h */, @@ -1789,8 +1811,6 @@ 7E2C6C980D31C6B6002D44E2 /* ScopeChainMark.h */, 93303FE80E6A72B500786E6A /* SmallStrings.cpp */, 93303FEA0E6A72C000786E6A /* SmallStrings.h */, - 8698B86810D44D9400D8D01B /* StringBuilder.h */, - 86B6DA0112132B9A000D316F /* StringConcatenate.h */, BC18C3C00E16EE3300B34460 /* StringConstructor.cpp */, BC18C3C10E16EE3300B34460 /* StringConstructor.h */, BC18C3C20E16EE3300B34460 /* StringObject.cpp */, @@ -1811,9 +1831,13 @@ 5D53726E0E1C54880021E549 /* Tracing.h */, F692A8850255597D01FF60F7 /* UString.cpp */, F692A8860255597D01FF60F7 /* UString.h */, + 08DDA5BB12645F1D00751732 /* UStringBuilder.h */, + 0896C29B1265AAF600B1CDD3 /* UStringConcatenate.h */, 14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */, 14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */, 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */, + A730B6101250068F009D25B1 /* StrictEvalActivation.h */, + A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */, ); path = runtime; sourceTree = "<group>"; @@ -1828,6 +1852,9 @@ 86565740115BE3DA00291F40 /* CString.cpp */, 86565741115BE3DA00291F40 /* CString.h */, 86B99AE1117E578100DF5A90 /* StringBuffer.h */, + 86438FC31265503E00E0DFCA /* StringBuilder.cpp */, + 081469481264375E00DFF935 /* StringBuilder.h */, + 0896C29E1265AB0900B1CDD3 /* StringConcatenate.h */, 868BFA05117CEFD100B908B1 /* StringHash.h */, 868BFA06117CEFD100B908B1 /* StringImpl.cpp */, 868BFA07117CEFD100B908B1 /* StringImpl.h */, @@ -1944,8 +1971,13 @@ children = ( 9714AF31122F27E70092D9F5 /* RawURLBuffer.h */, 9714AF32122F27E70092D9F5 /* URLBuffer.h */, + 972A485D12661E0800F4514F /* URLCharacterTypes.cpp */, + 972A485E12661E0800F4514F /* URLCharacterTypes.h */, 9714AF33122F27E70092D9F5 /* URLComponent.h */, + 972A48741266256F00F4514F /* URLEscape.cpp */, + 972A48751266256F00F4514F /* URLEscape.h */, 9714AF34122F27E70092D9F5 /* URLParser.h */, + 972A48761266256F00F4514F /* URLQueryCanonicalizer.h */, 9714AF35122F27E70092D9F5 /* URLSegments.cpp */, 9714AF36122F27E70092D9F5 /* URLSegments.h */, ); @@ -2250,11 +2282,12 @@ 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */, FE1B447A0ECCD73B004F4DD1 /* StdLibExtras.h in Headers */, 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */, - 8698B86910D44D9400D8D01B /* StringBuilder.h in Headers */, + 081469491264378500DFF935 /* StringBuilder.h in Headers */, + 08CABBA61265AB3900B206CE /* StringConcatenate.h in Headers */, BC18C4660E16F5CD00B34460 /* StringConstructor.h in Headers */, BC18C4670E16F5CD00B34460 /* StringExtras.h in Headers */, 868BFA0D117CEFD100B908B1 /* StringHash.h in Headers */, - 5D63E9AD10F2BD6E00FC8AE9 /* StringHashFunctions.h in Headers */, + 5D63E9AD10F2BD6E00FC8AE9 /* StringHasher.h in Headers */, 868BFA0F117CEFD100B908B1 /* StringImpl.h in Headers */, 86B99AE4117E578100DF5A90 /* StringImplBase.h in Headers */, BC18C4680E16F5CD00B34460 /* StringObject.h in Headers */, @@ -2286,6 +2319,7 @@ BC18C4740E16F5CD00B34460 /* UnicodeIcu.h in Headers */, BC18C4750E16F5CD00B34460 /* UnusedParam.h in Headers */, BC18C4760E16F5CD00B34460 /* UString.h in Headers */, + 08DDA5C11264631700751732 /* UStringBuilder.h in Headers */, BC18C4770E16F5CD00B34460 /* UTF8.h in Headers */, E17FF771112131D200076A19 /* ValueCheck.h in Headers */, BC18C4780E16F5CD00B34460 /* Vector.h in Headers */, @@ -2302,7 +2336,6 @@ DD2724691208D1FF00F9ABE7 /* AlignedMemoryAllocator.h in Headers */, DDE82AD81209D955005C1756 /* GCHandle.h in Headers */, 86F38859121130CA007A7CE3 /* AtomicStringHash.h in Headers */, - 86B6DA0212132B9A000D316F /* StringConcatenate.h in Headers */, 862AF4B612239C7B0024E5B8 /* DecimalNumber.h in Headers */, BCFBE696122560E800309E9D /* PassOwnArrayPtr.h in Headers */, BCFBE698122561D200309E9D /* OwnArrayPtrCommon.h in Headers */, @@ -2314,6 +2347,8 @@ 9714AF5F122F32070092D9F5 /* ParsedURL.h in Headers */, 9714AF60122F32070092D9F5 /* URLString.h in Headers */, 90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */, + A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */, + 933F5CDC1269229B0049191E /* NullPtr.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2407,6 +2442,7 @@ isa = PBXProject; buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */; compatibilityVersion = "Xcode 2.4"; + developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( English, @@ -2768,6 +2804,9 @@ 9714AF46122F28850092D9F5 /* URLSegments.cpp in Sources */, 9714AF5E122F32070092D9F5 /* ParsedURL.cpp in Sources */, 90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */, + A730B6131250068F009D25B1 /* StrictEvalActivation.cpp in Sources */, + 86438FC41265503E00E0DFCA /* StringBuilder.cpp in Sources */, + 0F29479C126E698C00B3ABF5 /* DecimalNumber.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2777,6 +2816,8 @@ files = ( 932F5BDD0822A1C700736975 /* jsc.cpp in Sources */, DDE82AD31209D955005C1756 /* GCHandle.cpp in Sources */, + 972A485F12661E0800F4514F /* URLCharacterTypes.cpp in Sources */, + 972A48771266256F00F4514F /* URLEscape.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JavaScriptCore/assembler/ARMv7Assembler.cpp b/JavaScriptCore/assembler/ARMv7Assembler.cpp index 233a6f1..7aa1f10 100644 --- a/JavaScriptCore/assembler/ARMv7Assembler.cpp +++ b/JavaScriptCore/assembler/ARMv7Assembler.cpp @@ -31,7 +31,10 @@ namespace JSC { -const int ARMv7Assembler::JumpSizes[] = { 0xffffffff, 2 * sizeof(uint16_t), 2 * sizeof(uint16_t), 5 * sizeof(uint16_t) }; +const int ARMv7Assembler::JumpSizes[] = { 0xffffffff, sizeof(uint16_t), sizeof(uint16_t), + 2 * sizeof(uint16_t), 2 * sizeof(uint16_t), 3 * sizeof(uint16_t), 5 * sizeof(uint16_t), 6 * sizeof(uint16_t) }; +const int ARMv7Assembler::JumpPaddingSizes[] = { 0, 5 * sizeof(uint16_t), 6 * sizeof(uint16_t), + 5 * sizeof(uint16_t), 6 * sizeof(uint16_t) }; } diff --git a/JavaScriptCore/assembler/ARMv7Assembler.h b/JavaScriptCore/assembler/ARMv7Assembler.h index d960546..37b650b 100644 --- a/JavaScriptCore/assembler/ARMv7Assembler.h +++ b/JavaScriptCore/assembler/ARMv7Assembler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2010 University of Szeged * * Redistribution and use in source and binary forms, with or without @@ -440,7 +440,7 @@ private: }; struct { unsigned type : 2; - unsigned amount : 5; + unsigned amount : 6; }; } m_u; }; @@ -478,10 +478,11 @@ public: ConditionInvalid } Condition; - enum JumpType { JumpNoCondition, JumpCondition, JumpFullSize }; - enum JumpLinkType { LinkInvalid, LinkShortJump, LinkConditionalShortJump, LinkLongJump, JumpTypeCount }; - static const int JumpSizes[JumpTypeCount]; - enum { JumpPaddingSize = 5 * sizeof(uint16_t) }; + enum JumpType { JumpFixed, JumpNoCondition, JumpCondition, JumpNoConditionFixedSize, JumpConditionFixedSize, JumpTypeCount }; + enum JumpLinkType { LinkInvalid, LinkJumpT1, LinkJumpT2, LinkJumpT3, + LinkJumpT4, LinkConditionalJumpT4, LinkBX, LinkConditionalBX, JumpLinkTypeCount }; + static const int JumpSizes[JumpLinkTypeCount]; + static const int JumpPaddingSizes[JumpTypeCount]; class LinkRecord { public: LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition) @@ -502,8 +503,8 @@ public: private: intptr_t m_from : 31; intptr_t m_to : 31; - JumpType m_type : 2; - JumpLinkType m_linkType : 3; + JumpType m_type : 3; + JumpLinkType m_linkType : 4; Condition m_condition : 16; }; @@ -523,7 +524,7 @@ public: , m_condition(ConditionInvalid) , m_type(type) { - ASSERT(m_type != JumpCondition); + ASSERT(m_type == JumpFixed || m_type == JumpNoCondition || m_type == JumpNoConditionFixedSize); } JmpSrc(int offset, JumpType type, Condition condition) @@ -531,7 +532,7 @@ public: , m_condition(condition) , m_type(type) { - ASSERT(m_type == JumpCondition || m_type == JumpFullSize); + ASSERT(m_type == JumpFixed || m_type == JumpCondition || m_type == JumpConditionFixedSize); } int m_offset; @@ -628,6 +629,8 @@ private: } OpcodeID; typedef enum { + OP_B_T1 = 0xD000, + OP_B_T2 = 0xE000, OP_AND_reg_T2 = 0xEA00, OP_TST_reg_T2 = 0xEA10, OP_ORR_reg_T2 = 0xEA40, @@ -655,6 +658,7 @@ private: OP_VCVT_FPIVFP = 0xEEB0, OP_VMOV_IMM_T2 = 0xEEB0, OP_VMRS = 0xEEB0, + OP_B_T3a = 0xF000, OP_B_T4a = 0xF000, OP_AND_imm_T1 = 0xF000, OP_TST_imm = 0xF010, @@ -707,6 +711,7 @@ private: OP_VCVT_FPIVFPb = 0x0A40, OP_VSUB_T2b = 0x0A40, OP_NOP_T2b = 0x8000, + OP_B_T3b = 0x8000, OP_B_T4b = 0x9000, } OpcodeID2; @@ -743,7 +748,7 @@ private: | (ifThenElseConditionBit(condition, inst3if) << 2) | (ifThenElseConditionBit(condition, inst4if) << 1) | 1; - ASSERT((condition != ConditionAL) || (mask & (mask - 1))); + ASSERT((condition != ConditionAL) || !(mask & (mask - 1))); return (condition << 4) | mask; } uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if) @@ -751,21 +756,20 @@ private: int mask = (ifThenElseConditionBit(condition, inst2if) << 3) | (ifThenElseConditionBit(condition, inst3if) << 2) | 2; - ASSERT((condition != ConditionAL) || (mask & (mask - 1))); + ASSERT((condition != ConditionAL) || !(mask & (mask - 1))); return (condition << 4) | mask; } uint8_t ifThenElse(Condition condition, bool inst2if) { int mask = (ifThenElseConditionBit(condition, inst2if) << 3) | 4; - ASSERT((condition != ConditionAL) || (mask & (mask - 1))); + ASSERT((condition != ConditionAL) || !(mask & (mask - 1))); return (condition << 4) | mask; } uint8_t ifThenElse(Condition condition) { int mask = 8; - ASSERT((condition != ConditionAL) || (mask & (mask - 1))); return (condition << 4) | mask; } @@ -1662,7 +1666,7 @@ public: return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1]; } - int jumpSizeDelta(JumpLinkType jumpLinkType) { return JumpPaddingSize - JumpSizes[jumpLinkType]; } + int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JumpPaddingSizes[jumpType] - JumpSizes[jumpLinkType]; } // Assembler admin methods: @@ -1676,30 +1680,73 @@ public: return a.from() < b.from(); } - JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) + bool canCompact(JumpType jumpType) { - if (record.type() >= JumpFullSize) { - record.setLinkType(LinkLongJump); - return LinkLongJump; - } + // The following cannot be compacted: + // JumpFixed: represents custom jump sequence + // JumpNoConditionFixedSize: represents unconditional jump that must remain a fixed size + // JumpConditionFixedSize: represents conditional jump that must remain a fixed size + return (jumpType == JumpNoCondition) || (jumpType == JumpCondition); + } + + JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) + { + if (jumpType == JumpFixed) + return LinkInvalid; + + // for patchable jump we must leave space for the longest code sequence + if (jumpType == JumpNoConditionFixedSize) + return LinkBX; + if (jumpType == JumpConditionFixedSize) + return LinkConditionalBX; + + const int paddingSize = JumpPaddingSizes[jumpType]; bool mayTriggerErrata = false; - const uint16_t* shortJumpLocation = reinterpret_cast<const uint16_t*>(from - (JumpPaddingSize - JumpSizes[LinkShortJump])); - if (!canBeShortJump(shortJumpLocation, to, mayTriggerErrata)) { - record.setLinkType(LinkLongJump); - return LinkLongJump; - } - if (mayTriggerErrata) { - record.setLinkType(LinkLongJump); - return LinkLongJump; - } - if (record.type() == JumpCondition) { - record.setLinkType(LinkConditionalShortJump); - return LinkConditionalShortJump; + + if (jumpType == JumpCondition) { + // 2-byte conditional T1 + const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT1])); + if (canBeJumpT1(jumpT1Location, to)) + return LinkJumpT1; + // 4-byte conditional T3 + const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT3])); + if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) { + if (!mayTriggerErrata) + return LinkJumpT3; + } + // 4-byte conditional T4 with IT + const uint16_t* conditionalJumpT4Location = + reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkConditionalJumpT4])); + if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) { + if (!mayTriggerErrata) + return LinkConditionalJumpT4; + } + } else { + // 2-byte unconditional T2 + const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT2])); + if (canBeJumpT2(jumpT2Location, to)) + return LinkJumpT2; + // 4-byte unconditional T4 + const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT4])); + if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) { + if (!mayTriggerErrata) + return LinkJumpT4; + } + // use long jump sequence + return LinkBX; } - record.setLinkType(LinkShortJump); - return LinkShortJump; + + ASSERT(jumpType == JumpCondition); + return LinkConditionalBX; } - + + JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) + { + JumpLinkType linkType = computeJumpType(record.type(), from, to); + record.setLinkType(linkType); + return linkType; + } + void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset) { int32_t ptr = regionStart / sizeof(int32_t); @@ -1717,16 +1764,32 @@ public: void link(LinkRecord& record, uint8_t* from, uint8_t* to) { - uint16_t* itttLocation; - if (record.linkType() == LinkConditionalShortJump) { - itttLocation = reinterpret_cast<uint16_t*>(from - JumpSizes[LinkConditionalShortJump] - 2); - itttLocation[0] = ifThenElse(record.condition()) | OP_IT; + switch (record.linkType()) { + case LinkJumpT1: + linkJumpT1(record.condition(), reinterpret_cast<uint16_t*>(from), to); + break; + case LinkJumpT2: + linkJumpT2(reinterpret_cast<uint16_t*>(from), to); + break; + case LinkJumpT3: + linkJumpT3(record.condition(), reinterpret_cast<uint16_t*>(from), to); + break; + case LinkJumpT4: + linkJumpT4(reinterpret_cast<uint16_t*>(from), to); + break; + case LinkConditionalJumpT4: + linkConditionalJumpT4(record.condition(), reinterpret_cast<uint16_t*>(from), to); + break; + case LinkConditionalBX: + linkConditionalBX(record.condition(), reinterpret_cast<uint16_t*>(from), to); + break; + case LinkBX: + linkBX(reinterpret_cast<uint16_t*>(from), to); + break; + default: + ASSERT_NOT_REACHED(); + break; } - ASSERT(record.linkType() != LinkInvalid); - if (record.linkType() != LinkLongJump) - linkShortJump(reinterpret_cast<uint16_t*>(from), to); - else - linkLongJump(reinterpret_cast<uint16_t*>(from), to); } void* unlinkedCode() { return m_formatter.data(); } @@ -1792,8 +1855,6 @@ public: ASSERT(reinterpret_cast<intptr_t>(to) & 1); setPointer(reinterpret_cast<uint16_t*>(from) - 1, to); - - ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 4 * sizeof(uint16_t)); } static void repatchInt32(void* where, int32_t value) @@ -1801,8 +1862,6 @@ public: ASSERT(!(reinterpret_cast<intptr_t>(where) & 1)); setInt32(where, value); - - ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t)); } static void repatchPointer(void* where, void* value) @@ -1810,8 +1869,6 @@ public: ASSERT(!(reinterpret_cast<intptr_t>(where) & 1)); setPointer(where, value); - - ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t)); } static void repatchLoadPtrToLEA(void* where) @@ -1952,7 +2009,54 @@ private: return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b); } - static bool canBeShortJump(const uint16_t* instruction, const void* target, bool& mayTriggerErrata) + static bool canBeJumpT1(const uint16_t* instruction, const void* target) + { + ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); + ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); + + intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); + // It does not appear to be documented in the ARM ARM (big surprise), but + // for OP_B_T1 the branch displacement encoded in the instruction is 2 + // less than the actual displacement. + relative -= 2; + return ((relative << 23) >> 23) == relative; + } + + static bool canBeJumpT2(const uint16_t* instruction, const void* target) + { + ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); + ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); + + intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); + // It does not appear to be documented in the ARM ARM (big surprise), but + // for OP_B_T2 the branch displacement encoded in the instruction is 2 + // less than the actual displacement. + relative -= 2; + return ((relative << 20) >> 20) == relative; + } + + static bool canBeJumpT3(const uint16_t* instruction, const void* target, bool& mayTriggerErrata) + { + ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); + ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); + + intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); + // From Cortex-A8 errata: + // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and + // the target of the branch falls within the first region it is + // possible for the processor to incorrectly determine the branch + // instruction, and it is also possible in some cases for the processor + // to enter a deadlock state. + // The instruction is spanning two pages if it ends at an address ending 0x002 + bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002); + mayTriggerErrata = spansTwo4K; + // The target is in the first page if the jump branch back by [3..0x1002] bytes + bool targetInFirstPage = (relative >= -0x1002) && (relative < -2); + bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage; + return ((relative << 11) >> 11) == relative && !wouldTriggerA8Errata; + } + + static bool canBeJumpT4(const uint16_t* instruction, const void* target, bool& mayTriggerErrata) { ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); @@ -1972,50 +2076,127 @@ private: bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage; return ((relative << 7) >> 7) == relative && !wouldTriggerA8Errata; } - - static void linkLongJump(uint16_t* instruction, void* target) + + void linkJumpT1(Condition cond, uint16_t* instruction, void* target) { - linkJumpAbsolute(instruction, target); + // FIMXE: this should be up in the MacroAssembler layer. :-( + ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); + ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); + ASSERT(canBeJumpT1(instruction, target)); + + intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); + // It does not appear to be documented in the ARM ARM (big surprise), but + // for OP_B_T1 the branch displacement encoded in the instruction is 2 + // less than the actual displacement. + relative -= 2; + + // All branch offsets should be an even distance. + ASSERT(!(relative & 1)); + instruction[-1] = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1); } - static void linkShortJump(uint16_t* instruction, void* target) + static void linkJumpT2(uint16_t* instruction, void* target) { // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); + ASSERT(canBeJumpT2(instruction, target)); intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); + // It does not appear to be documented in the ARM ARM (big surprise), but + // for OP_B_T2 the branch displacement encoded in the instruction is 2 + // less than the actual displacement. + relative -= 2; + + // All branch offsets should be an even distance. + ASSERT(!(relative & 1)); + instruction[-1] = OP_B_T2 | ((relative & 0xffe) >> 1); + } + + void linkJumpT3(Condition cond, uint16_t* instruction, void* target) + { + // FIMXE: this should be up in the MacroAssembler layer. :-( + ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); + ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); bool scratch; UNUSED_PARAM(scratch); - ASSERT(canBeShortJump(instruction, target, scratch)); + ASSERT(canBeJumpT3(instruction, target, scratch)); + + intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); + + // All branch offsets should be an even distance. + ASSERT(!(relative & 1)); + instruction[-2] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12); + instruction[-1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1); + } + + static void linkJumpT4(uint16_t* instruction, void* target) + { + // FIMXE: this should be up in the MacroAssembler layer. :-( + ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); + ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); + bool scratch; + UNUSED_PARAM(scratch); + ASSERT(canBeJumpT4(instruction, target, scratch)); + + intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); // ARM encoding for the top two bits below the sign bit is 'peculiar'. if (relative >= 0) relative ^= 0xC00000; - + // All branch offsets should be an even distance. ASSERT(!(relative & 1)); instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); } - + + void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target) + { + // FIMXE: this should be up in the MacroAssembler layer. :-( + ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); + ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); + + instruction[-3] = ifThenElse(cond) | OP_IT; + linkJumpT4(instruction, target); + } + + static void linkBX(uint16_t* instruction, void* target) + { + // FIMXE: this should be up in the MacroAssembler layer. :-( + ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); + ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); + + const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; + ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1)); + ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16)); + instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); + instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); + instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); + instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); + instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); + } + + void linkConditionalBX(Condition cond, uint16_t* instruction, void* target) + { + // FIMXE: this should be up in the MacroAssembler layer. :-( + ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); + ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); + + linkBX(instruction, target); + instruction[-6] = ifThenElse(cond, true, true) | OP_IT; + } + static void linkJumpAbsolute(uint16_t* instruction, void* target) { // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); - + ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1)) - || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2))); - - intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); + || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2))); + bool scratch; - if (canBeShortJump(instruction, target, scratch)) { - // ARM encoding for the top two bits below the sign bit is 'peculiar'. - if (relative >= 0) - relative ^= 0xC00000; - - // All branch offsets should be an even distance. - ASSERT(!(relative & 1)); + if (canBeJumpT4(instruction, target, scratch)) { // There may be a better way to fix this, but right now put the NOPs first, since in the // case of an conditional branch this will be coming after an ITTT predicating *three* // instructions! Looking backwards to modify the ITTT to an IT is not easy, due to @@ -2024,8 +2205,7 @@ private: instruction[-5] = OP_NOP_T1; instruction[-4] = OP_NOP_T2a; instruction[-3] = OP_NOP_T2b; - instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); - instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); + linkJumpT4(instruction, target); } else { const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1)); @@ -2037,7 +2217,7 @@ private: instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); } } - + static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm) { return op | (imm.m_value.i << 10) | imm.m_value.imm4; diff --git a/JavaScriptCore/assembler/LinkBuffer.h b/JavaScriptCore/assembler/LinkBuffer.h index 408deb0..e1dca0b 100644 --- a/JavaScriptCore/assembler/LinkBuffer.h +++ b/JavaScriptCore/assembler/LinkBuffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,6 +28,9 @@ #if ENABLE(ASSEMBLER) +#define DUMP_LINK_STATISTICS 0 +#define DUMP_CODE 0 + #include <MacroAssembler.h> #include <wtf/Noncopyable.h> @@ -235,12 +238,14 @@ private: target = linkBase + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to()); JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], linkBase + writePtr, target); - - // Step back in the write stream - int32_t delta = m_assembler->jumpSizeDelta(jumpLinkType); - if (delta) { - writePtr -= delta; - m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr); + // Compact branch if we can... + if (m_assembler->canCompact(jumpsToLink[i].type())) { + // Step back in the write stream + int32_t delta = m_assembler->jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType); + if (delta) { + writePtr -= delta; + m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr); + } } jumpsToLink[i].setFrom(writePtr); } @@ -261,6 +266,13 @@ private: jumpsToLink.clear(); m_size = writePtr + m_assembler->size() - readPtr; m_executablePool->returnLastBytes(initialSize - m_size); + +#if DUMP_LINK_STATISTICS + dumpLinkStatistics(m_code, initialSize, m_size); +#endif +#if DUMP_CODE + dumpCode(m_code, m_size); +#endif #endif } @@ -275,6 +287,53 @@ private: ExecutableAllocator::cacheFlush(code(), m_size); } +#if DUMP_LINK_STATISTICS + static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize) + { + static unsigned linkCount = 0; + static unsigned totalInitialSize = 0; + static unsigned totalFinalSize = 0; + linkCount++; + totalInitialSize += initialSize; + totalFinalSize += finalSize; + printf("link %p: orig %u, compact %u (delta %u, %.2f%%)\n", + code, static_cast<unsigned>(initialSize), static_cast<unsigned>(finalSize), + static_cast<unsigned>(initialSize - finalSize), + 100.0 * (initialSize - finalSize) / initialSize); + printf("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n", + linkCount, totalInitialSize, totalFinalSize, totalInitialSize - totalFinalSize, + 100.0 * (totalInitialSize - totalFinalSize) / totalInitialSize); + } +#endif + +#if DUMP_CODE + static void dumpCode(void* code, size_t size) + { +#if CPU(ARM_THUMB2) + // Dump the generated code in an asm file format that can be assembled and then disassembled + // for debugging purposes. For example, save this output as jit.s: + // gcc -arch armv7 -c jit.s + // otool -tv jit.o + static unsigned codeCount = 0; + unsigned short* tcode = static_cast<unsigned short*>(code); + size_t tsize = size / sizeof(short); + char nameBuf[128]; + snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++); + printf("\t.syntax unified\n" + "\t.section\t__TEXT,__text,regular,pure_instructions\n" + "\t.globl\t%s\n" + "\t.align 2\n" + "\t.code 16\n" + "\t.thumb_func\t%s\n" + "# %p\n" + "%s:\n", nameBuf, nameBuf, code, nameBuf); + + for (unsigned i = 0; i < tsize; i++) + printf("\t.short\t0x%x\n", tcode[i]); +#endif + } +#endif + RefPtr<ExecutablePool> m_executablePool; size_t m_size; void* m_code; diff --git a/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/JavaScriptCore/assembler/MacroAssemblerARMv7.h index a1539f2..fe5d052 100644 --- a/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2010 University of Szeged * * Redistribution and use in source and binary forms, with or without @@ -46,6 +46,7 @@ class MacroAssemblerARMv7 : public AbstractMacroAssembler<ARMv7Assembler> { public: typedef ARMv7Assembler::LinkRecord LinkRecord; + typedef ARMv7Assembler::JumpType JumpType; typedef ARMv7Assembler::JumpLinkType JumpLinkType; MacroAssemblerARMv7() @@ -57,9 +58,11 @@ public: void endUninterruptedSequence() { m_inUninterruptedSequence = false; } Vector<LinkRecord>& jumpsToLink() { return m_assembler.jumpsToLink(); } void* unlinkedCode() { return m_assembler.unlinkedCode(); } + bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); } + JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(jumpType, from, to); } JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(record, from, to); } void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset) {return m_assembler.recordLinkOffsets(regionStart, regionEnd, offset); } - int jumpSizeDelta(JumpLinkType jumpLinkType) { return m_assembler.jumpSizeDelta(jumpLinkType); } + int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return m_assembler.jumpSizeDelta(jumpType, jumpLinkType); } void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return m_assembler.link(record, from, to); } struct ArmAddress { @@ -986,14 +989,14 @@ public: void jump(RegisterID target) { - m_assembler.bx(target, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpNoCondition); + m_assembler.bx(target, ARMv7Assembler::JumpFixed); } // Address is a memory location containing the address to jump to void jump(Address address) { load32(address, dataTempRegister); - m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpNoCondition); + m_assembler.bx(dataTempRegister, ARMv7Assembler::JumpFixed); } @@ -1082,29 +1085,29 @@ public: Call nearCall() { moveFixedWidthEncoding(Imm32(0), dataTempRegister); - return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::LinkableNear); + return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::LinkableNear); } Call call() { moveFixedWidthEncoding(Imm32(0), dataTempRegister); - return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::Linkable); + return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::Linkable); } Call call(RegisterID target) { - return Call(m_assembler.blx(target, ARMv7Assembler::JumpFullSize), Call::None); + return Call(m_assembler.blx(target, ARMv7Assembler::JumpFixed), Call::None); } Call call(Address address) { load32(address, dataTempRegister); - return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::None); + return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::None); } void ret() { - m_assembler.bx(linkRegister, ARMv7Assembler::JumpFullSize); + m_assembler.bx(linkRegister, ARMv7Assembler::JumpFixed); } void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest) @@ -1204,7 +1207,7 @@ public: { // Like a normal call, but don't link. moveFixedWidthEncoding(Imm32(0), dataTempRegister); - return Call(m_assembler.bx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::Linkable); + return Call(m_assembler.bx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::Linkable); } Call makeTailRecursiveCall(Jump oldJump) @@ -1228,14 +1231,14 @@ protected: ARMv7Assembler::JmpSrc makeJump() { moveFixedWidthEncoding(Imm32(0), dataTempRegister); - return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpNoCondition); + return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition); } ARMv7Assembler::JmpSrc makeBranch(ARMv7Assembler::Condition cond) { m_assembler.it(cond, true, true); moveFixedWidthEncoding(Imm32(0), dataTempRegister); - return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpCondition, cond); + return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond); } ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); } ARMv7Assembler::JmpSrc makeBranch(DoubleCondition cond) { return makeBranch(armV7Condition(cond)); } diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp index 6c0696e..55101d4 100644 --- a/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/JavaScriptCore/bytecode/CodeBlock.cpp @@ -34,10 +34,11 @@ #include "Debugger.h" #include "Interpreter.h" #include "JIT.h" +#include "JSActivation.h" #include "JSFunction.h" #include "JSStaticScopeObject.h" #include "JSValue.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" #include <stdio.h> #include <wtf/StringExtras.h> @@ -52,7 +53,7 @@ static UString escapeQuotes(const UString& str) UString result = str; size_t pos = 0; while ((pos = result.find('\"', pos)) != notFound) { - result = makeString(result.substringSharingImpl(0, pos), "\"\\\"\"", result.substringSharingImpl(pos + 1)); + result = makeUString(result.substringSharingImpl(0, pos), "\"\\\"\"", result.substringSharingImpl(pos + 1)); pos += 4; } return result; @@ -64,19 +65,19 @@ static UString valueToSourceString(ExecState* exec, JSValue val) return "0"; if (val.isString()) - return makeString("\"", escapeQuotes(val.toString(exec)), "\""); + return makeUString("\"", escapeQuotes(val.toString(exec)), "\""); return val.toString(exec); } static CString constantName(ExecState* exec, int k, JSValue value) { - return makeString(valueToSourceString(exec, value), "(@k", UString::number(k - FirstConstantRegisterIndex), ")").utf8(); + return makeUString(valueToSourceString(exec, value), "(@k", UString::number(k - FirstConstantRegisterIndex), ")").utf8(); } static CString idName(int id0, const Identifier& ident) { - return makeString(ident.ustring(), "(@id", UString::number(id0), ")").utf8(); + return makeUString(ident.ustring(), "(@id", UString::number(id0), ")").utf8(); } CString CodeBlock::registerName(ExecState* exec, int r) const @@ -87,7 +88,7 @@ CString CodeBlock::registerName(ExecState* exec, int r) const if (isConstantRegisterIndex(r)) return constantName(exec, r, getConstant(r)); - return makeString("r", UString::number(r)).utf8(); + return makeUString("r", UString::number(r)).utf8(); } static UString regexpToSourceString(RegExp* regExp) @@ -101,12 +102,12 @@ static UString regexpToSourceString(RegExp* regExp) if (regExp->multiline()) postfix[index] = 'm'; - return makeString("/", regExp->pattern(), postfix); + return makeUString("/", regExp->pattern(), postfix); } static CString regexpName(int re, RegExp* regexp) { - return makeString(regexpToSourceString(regexp), "(@re", UString::number(re), ")").utf8(); + return makeUString(regexpToSourceString(regexp), "(@re", UString::number(re), ")").utf8(); } static UString pointerToSourceString(void* p) @@ -485,9 +486,9 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& printf("[%4d] enter\n", location); break; } - case op_enter_with_activation: { + case op_create_activation: { int r0 = (++it)->u.operand; - printf("[%4d] enter_with_activation %s\n", location, registerName(exec, r0).data()); + printf("[%4d] create_activation %s\n", location, registerName(exec, r0).data()); break; } case op_create_arguments: { @@ -516,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()); @@ -722,9 +728,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int id0 = (++it)->u.operand; JSValue scope = JSValue((++it)->u.jsCell); ++it; - int depth = it[2].u.operand; + int depth = (++it)->u.operand; printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth); - it += 3; break; } case op_get_scoped_var: { @@ -756,7 +761,14 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_resolve_base: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] resolve_base\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + int isStrict = (++it)->u.operand; + printf("[%4d] resolve_base%s\t %s, %s\n", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + break; + } + case op_ensure_property_exists: { + int r0 = (++it)->u.operand; + int id0 = (++it)->u.operand; + printf("[%4d] ensure_property_exists\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); break; } case op_resolve_with_base: { @@ -1134,9 +1146,12 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_next_pname: { int dest = it[1].u.operand; - int iter = it[4].u.operand; - int offset = it[5].u.operand; - printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(exec, dest).data(), registerName(exec, iter).data(), offset, location + offset); + int base = it[2].u.operand; + int i = it[3].u.operand; + int size = it[4].u.operand; + int iter = it[5].u.operand; + int offset = it[6].u.operand; + printf("[%4d] next_pname\t %s, %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, dest).data(), registerName(exec, base).data(), registerName(exec, i).data(), registerName(exec, size).data(), registerName(exec, iter).data(), offset, location + offset); it += OPCODE_LENGTH(op_next_pname) - 1; break; } @@ -1371,6 +1386,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) @@ -1542,6 +1558,10 @@ bool CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame) ASSERT(!m_rareData || !m_rareData->m_exceptionHandlers.size()); ScopeChainNode* scopeChain = callFrame->scopeChain(); if (m_needsFullScopeChain) { + if (codeType() == FunctionCode && !callFrame->r(activationRegister()).jsValue()) { + createActivation(callFrame); + scopeChain = callFrame->scopeChain(); + } ScopeChain sc(scopeChain); int scopeDelta = sc.localDepth(); if (m_codeType == EvalCode) @@ -1553,7 +1573,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; } @@ -1765,4 +1785,14 @@ void CodeBlock::shrinkToFit() } } +void CodeBlock::createActivation(CallFrame* callFrame) +{ + ASSERT(codeType() == FunctionCode); + ASSERT(needsFullScopeChain()); + ASSERT(!callFrame->r(activationRegister()).jsValue()); + JSActivation* activation = new (callFrame) JSActivation(callFrame, static_cast<FunctionExecutable*>(ownerExecutable())); + callFrame->r(activationRegister()) = JSValue(activation); + callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation)); +} + } // namespace JSC diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h index cda4530..e4ebeb8 100644 --- a/JavaScriptCore/bytecode/CodeBlock.h +++ b/JavaScriptCore/bytecode/CodeBlock.h @@ -297,9 +297,11 @@ 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) + if (index == m_thisRegister && !m_isStrictMode) return true; if (isConstantRegisterIndex(index)) @@ -408,6 +410,15 @@ namespace JSC { ASSERT(usesArguments()); return m_argumentsRegister; } + void setActivationRegister(int activationRegister) + { + m_activationRegister = activationRegister; + } + int activationRegister() + { + ASSERT(needsFullScopeChain()); + return m_activationRegister; + } bool usesArguments() const { return m_argumentsRegister != -1; } CodeType codeType() const { return m_codeType; } @@ -420,6 +431,8 @@ namespace JSC { unsigned jumpTarget(int index) const { return m_jumpTargets[index]; } unsigned lastJumpTarget() const { return m_jumpTargets.last(); } + void createActivation(CallFrame*); + #if ENABLE(INTERPRETER) void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); } void addGlobalResolveInstruction(unsigned globalResolveInstruction) { m_globalResolveInstructions.append(globalResolveInstruction); } @@ -548,10 +561,12 @@ namespace JSC { int m_thisRegister; int m_argumentsRegister; + int m_activationRegister; bool m_needsFullScopeChain; bool m_usesEval; bool m_isNumericCompareFunction; + bool m_isStrictMode; CodeType m_codeType; diff --git a/JavaScriptCore/bytecode/EvalCodeCache.h b/JavaScriptCore/bytecode/EvalCodeCache.h index 7c4cb33..edd575f 100644 --- a/JavaScriptCore/bytecode/EvalCodeCache.h +++ b/JavaScriptCore/bytecode/EvalCodeCache.h @@ -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); } diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h index 03f6573..e1ef01e 100644 --- a/JavaScriptCore/bytecode/Opcode.h +++ b/JavaScriptCore/bytecode/Opcode.h @@ -39,12 +39,13 @@ namespace JSC { #define FOR_EACH_OPCODE_ID(macro) \ macro(op_enter, 1) \ - macro(op_enter_with_activation, 2) \ + macro(op_create_activation, 2) \ macro(op_init_lazy_reg, 2) \ macro(op_create_arguments, 2) \ 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) \ @@ -99,7 +100,8 @@ namespace JSC { macro(op_put_scoped_var, 4) \ macro(op_get_global_var, 3) \ macro(op_put_global_var, 3) \ - macro(op_resolve_base, 3) \ + macro(op_resolve_base, 4) \ + macro(op_ensure_property_exists, 3) \ macro(op_resolve_with_base, 4) \ macro(op_get_by_id, 8) \ macro(op_get_by_id_self, 8) \ diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 986709b..f34c38c 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -214,6 +214,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d , m_nextGlobalIndex(-1) , m_nextConstantOffset(0) , m_globalConstantIndex(0) + , m_hasCreatedActivation(true) , m_firstLazyFunction(0) , m_lastLazyFunction(0) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) @@ -306,10 +307,14 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug , m_codeType(FunctionCode) , m_nextConstantOffset(0) , m_globalConstantIndex(0) + , m_hasCreatedActivation(false) , m_firstLazyFunction(0) , m_lastLazyFunction(0) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) +#ifndef NDEBUG + , m_lastOpcodePosition(0) +#endif , m_emitNodeDepth(0) , m_usesExceptions(false) , m_regeneratingForExceptionInfo(false) @@ -319,13 +324,13 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug m_codeBlock->setNeedsFullScopeChain(true); codeBlock->setGlobalData(m_globalData); - + + emitOpcode(op_enter); if (m_codeBlock->needsFullScopeChain()) { m_activationRegister = addVar(); - emitOpcode(op_enter_with_activation); - instructions().append(m_activationRegister->index()); - } else - emitOpcode(op_enter); + emitInitLazyRegister(m_activationRegister); + m_codeBlock->setActivationRegister(m_activationRegister->index()); + } // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments' // object, if created. @@ -341,6 +346,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>), @@ -356,11 +366,17 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug // Captured variables and functions go first so that activations don't have // to step over the non-captured locals to mark them. + m_hasCreatedActivation = false; if (functionBody->hasCapturedVariables()) { for (size_t i = 0; i < functionStack.size(); ++i) { FunctionBodyNode* function = functionStack[i]; const Identifier& ident = function->ident(); if (functionBody->captures(ident)) { + if (!m_hasCreatedActivation) { + m_hasCreatedActivation = true; + emitOpcode(op_create_activation); + instructions().append(m_activationRegister->index()); + } m_functions.add(ident.impl()); emitNewFunction(addVar(ident, false), function); } @@ -371,7 +387,13 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug addVar(ident, varStack[i].second & DeclarationStacks::IsConstant); } } - bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables(); + bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !debugger; + if (!canLazilyCreateFunctions && !m_hasCreatedActivation) { + m_hasCreatedActivation = true; + emitOpcode(op_create_activation); + instructions().append(m_activationRegister->index()); + } + codeBlock->m_numCapturedVars = codeBlock->m_numVars; m_firstLazyFunction = codeBlock->m_numVars; for (size_t i = 0; i < functionStack.size(); ++i) { @@ -399,7 +421,6 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug if (debugger) codeBlock->m_numCapturedVars = codeBlock->m_numVars; - FunctionParameters& parameters = *functionBody->parameters(); size_t parameterCount = parameters.size(); @@ -429,7 +450,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()); } } @@ -448,10 +472,14 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge , m_codeType(EvalCode) , m_nextConstantOffset(0) , m_globalConstantIndex(0) + , m_hasCreatedActivation(true) , m_firstLazyFunction(0) , m_lastLazyFunction(0) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) +#ifndef NDEBUG + , m_lastOpcodePosition(0) +#endif , m_emitNodeDepth(0) , m_usesExceptions(false) , m_regeneratingForExceptionInfo(false) @@ -1249,6 +1277,7 @@ RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier emitOpcode(op_resolve_base); instructions().append(dst->index()); instructions().append(addConstant(property)); + instructions().append(false); return dst; } @@ -1256,6 +1285,32 @@ RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier return emitLoad(dst, JSValue(globalObject)); } +RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const Identifier& property) +{ + if (!m_codeBlock->isStrictMode()) + return emitResolveBase(dst, property); + size_t depth = 0; + int index = 0; + JSObject* globalObject = 0; + bool requiresDynamicChecks = false; + findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject); + if (!globalObject || requiresDynamicChecks) { + // We can't optimise at all :-( + emitOpcode(op_resolve_base); + instructions().append(dst->index()); + instructions().append(addConstant(property)); + instructions().append(true); + return dst; + } + + // Global object is the base + RefPtr<RegisterID> result = emitLoad(dst, JSValue(globalObject)); + emitOpcode(op_ensure_property_exists); + instructions().append(dst->index()); + instructions().append(addConstant(property)); + return result.get(); +} + RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property) { size_t depth = 0; @@ -1504,6 +1559,7 @@ RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBody RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck) { + createActivationIfNecessary(); emitOpcode(op_new_func); instructions().append(dst->index()); instructions().append(index); @@ -1523,7 +1579,8 @@ RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExp { FunctionBodyNode* function = n->body(); unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function)); - + + createActivationIfNecessary(); emitOpcode(op_new_func_exp); instructions().append(r0->index()); instructions().append(index); @@ -1541,10 +1598,26 @@ 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()); } +void BytecodeGenerator::createActivationIfNecessary() +{ + if (m_hasCreatedActivation) + return; + if (!m_codeBlock->needsFullScopeChain()) + return; + emitOpcode(op_create_activation); + instructions().append(m_activationRegister->index()); +} + RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset) { return emitCall(op_call_eval, dst, func, callArguments, divot, startOffset, endOffset); @@ -1648,7 +1721,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()); } diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h index 2afa0c4..d0e4a6b 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -329,6 +329,7 @@ namespace JSC { RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValue globalObject); RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property); + RegisterID* emitResolveBaseForPut(RegisterID* dst, const Identifier& property); RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property); void emitMethodCheck(); @@ -419,13 +420,15 @@ namespace JSC { } bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; } + + bool isStrictMode() const { return m_codeBlock->isStrictMode(); } private: void emitOpcode(OpcodeID); void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index); void retrieveLastUnaryOp(int& dstIndex, int& srcIndex); - void rewindBinaryOp(); - void rewindUnaryOp(); + ALWAYS_INLINE void rewindBinaryOp(); + ALWAYS_INLINE void rewindUnaryOp(); PassRefPtr<Label> emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope); @@ -499,12 +502,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*); @@ -518,6 +521,7 @@ namespace JSC { RegisterID* emitThrowExpressionTooDeepException(); void createArgumentsIfNecessary(); + void createActivationIfNecessary(); RegisterID* createLazyRegisterIfNecessary(RegisterID*); bool m_shouldEmitDebugHooks; @@ -558,6 +562,7 @@ namespace JSC { int m_globalVarStorageOffset; + bool m_hasCreatedActivation; int m_firstLazyFunction; int m_lastLazyFunction; HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int> > m_lazyFunctions; diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp index 2cc1a3f..449cae9 100644 --- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -42,7 +42,7 @@ #include "RegExpCache.h" #include "RegExpObject.h" #include "SamplingTool.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" #include <wtf/Assertions.h> #include <wtf/RefCountedLeakCounter.h> #include <wtf/Threading.h> @@ -80,7 +80,7 @@ static void substitute(UString& string, const UString& substring) { size_t position = string.find("%s"); ASSERT(position != notFound); - string = makeString(string.substringSharingImpl(0, position), substring, string.substringSharingImpl(position + 2)); + string = makeUString(string.substringSharingImpl(0, position), substring, string.substringSharingImpl(position + 2)); } RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, bool isReferenceError, const char* message) @@ -371,7 +371,7 @@ RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, Re { RefPtr<RegisterID> func = generator.emitNode(m_expr); CallArguments callArguments(generator, m_args); - generator.emitLoad(callArguments.thisRegister(), jsNull()); + generator.emitLoad(callArguments.thisRegister(), jsUndefined()); return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); } @@ -381,7 +381,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, { if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { CallArguments callArguments(generator, m_args); - generator.emitLoad(callArguments.thisRegister(), jsNull()); + generator.emitLoad(callArguments.thisRegister(), jsUndefined()); return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), local.get(), callArguments, divot(), startOffset(), endOffset()); } @@ -392,7 +392,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); CallArguments callArguments(generator, m_args); - generator.emitLoad(callArguments.thisRegister(), jsNull()); + generator.emitLoad(callArguments.thisRegister(), jsUndefined()); return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); } @@ -455,7 +455,7 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, } else { RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); CallArguments callArguments(generator, m_args); - generator.emitLoad(callArguments.thisRegister(), jsNull()); + generator.emitLoad(callArguments.thisRegister(), jsUndefined()); generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); generator.emitJump(end.get()); } @@ -513,7 +513,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, } else { RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); CallArguments callArguments(generator, m_args); - generator.emitLoad(callArguments.thisRegister(), jsNull()); + generator.emitLoad(callArguments.thisRegister(), jsUndefined()); generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); } } else { @@ -1231,7 +1231,7 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist return value; } - RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); + RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), m_ident); if (dst == generator.ignoredResult()) dst = 0; RegisterID* value = generator.emitNode(dst, m_right); @@ -1605,7 +1605,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds if (!propertyName) { propertyName = generator.newTemporary(); RefPtr<RegisterID> protect = propertyName; - RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident); + RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), ident); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutById(base, ident, propertyName); diff --git a/JavaScriptCore/debugger/Debugger.cpp b/JavaScriptCore/debugger/Debugger.cpp index cbcbd21..17dfdf7 100644 --- a/JavaScriptCore/debugger/Debugger.cpp +++ b/JavaScriptCore/debugger/Debugger.cpp @@ -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; diff --git a/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/JavaScriptCore/debugger/DebuggerCallFrame.cpp index 32f65dd..c98c7cc 100644 --- a/JavaScriptCore/debugger/DebuggerCallFrame.cpp +++ b/JavaScriptCore/debugger/DebuggerCallFrame.cpp @@ -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; diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp index 5943ece..632571d 100644 --- a/JavaScriptCore/interpreter/Interpreter.cpp +++ b/JavaScriptCore/interpreter/Interpreter.cpp @@ -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> @@ -127,6 +128,12 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP ScopeChainIterator iter = scopeChain->begin(); ScopeChainIterator end = scopeChain->end(); ASSERT(iter != end); + bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + if (callFrame->r(codeBlock->activationRegister()).jsValue()) + ++iter; + } while (skip--) { ++iter; ASSERT(iter != end); @@ -140,6 +147,7 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; + ASSERT(result); callFrame->r(dst) = JSValue(result); return true; } @@ -203,6 +211,12 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru ScopeChainIterator iter = scopeChain->begin(); ScopeChainIterator end = scopeChain->end(); ASSERT(iter != end); + bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + if (callFrame->r(codeBlock->activationRegister()).jsValue()) + ++iter; + } while (skip--) { JSObject* o = *iter; if (o->hasCustomProperties()) { @@ -214,6 +228,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; + ASSERT(result); callFrame->r(dst) = JSValue(result); return true; } @@ -230,6 +245,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru if (structure == globalObject->structure()) { callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset)); + ASSERT(callFrame->r(dst).jsValue()); return true; } @@ -243,6 +259,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru globalObject->structure()->ref(); vPC[3] = globalObject->structure(); vPC[4] = slot.cachedOffset(); + ASSERT(result); callFrame->r(dst) = JSValue(result); return true; } @@ -250,6 +267,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; + ASSERT(result); callFrame->r(dst) = JSValue(result); return true; } @@ -262,7 +280,14 @@ NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vP { int dst = vPC[1].u.operand; int property = vPC[2].u.operand; - callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain())); + bool isStrictPut = vPC[3].u.operand; + Identifier ident = callFrame->codeBlock()->identifier(property); + JSValue result = JSC::resolveBase(callFrame, ident, callFrame->scopeChain(), isStrictPut); + if (!result) { + callFrame->r(dst) = result; + ASSERT(callFrame->r(dst).jsValue()); + } else + callFrame->globalData().exception = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring()); } NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) @@ -371,14 +396,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(); - RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue); + RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue); JSValue result = jsUndefined(); if (eval) @@ -535,13 +564,19 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex // If this call frame created an activation or an 'arguments' object, tear it off. if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) { + if (!callFrame->r(oldCodeBlock->activationRegister()).jsValue()) { + oldCodeBlock->createActivation(callFrame); + scopeChain = callFrame->scopeChain(); + } while (!scopeChain->object->inherits(&JSActivation::info)) scopeChain = scopeChain->pop(); JSActivation* activation = asActivation(scopeChain->object); activation->copyRegisters(); - if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) - asArguments(arguments)->setActivation(activation); - } else if (oldCodeBlock->usesArguments()) { + if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) { + if (!oldCodeBlock->isStrictMode()) + asArguments(arguments)->setActivation(activation); + } + } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) { if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) asArguments(arguments)->copyRegisters(); } @@ -641,12 +676,23 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV } // Shrink the JS stack, in case stack overflow made it huge. - m_registerFile.shrink(callFrame->registers() + callFrame->codeBlock()->m_numCalleeRegisters); + Register* highWaterMark = callFrame->registers() + callFrame->codeBlock()->m_numCalleeRegisters; + for (CallFrame* callerFrame = callFrame->callerFrame()->removeHostCallFrameFlag(); callerFrame; callerFrame = callerFrame->callerFrame()->removeHostCallFrameFlag()) { + CodeBlock* codeBlock = callerFrame->codeBlock(); + if (!codeBlock) + continue; + Register* callerHighWaterMark = callerFrame->registers() + codeBlock->m_numCalleeRegisters; + highWaterMark = max(highWaterMark, callerHighWaterMark); + } + m_registerFile.shrink(highWaterMark); // Unwind the scope chain within the exception handler's call frame. ScopeChainNode* scopeChain = callFrame->scopeChain(); ScopeChain sc(scopeChain); - int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth; + int scopeDelta = 0; + if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode + || callFrame->r(codeBlock->activationRegister()).jsValue()) + scopeDelta = depth(codeBlock, sc) - handler->scopeDepth; ASSERT(scopeDelta >= 0); while (scopeDelta--) scopeChain = scopeChain->pop(); @@ -1036,7 +1082,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec } EvalCodeBlock* codeBlock = &eval->generatedBytecode(); - JSVariableObject* variableObject; + JSObject* variableObject; for (ScopeChainNode* node = scopeChain; ; node = node->next) { ASSERT(node); if (node->object->isVariableObject()) { @@ -1047,7 +1093,13 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec unsigned numVariables = codeBlock->numVariables(); int numFunctions = codeBlock->numberOfFunctionDecls(); + bool pushedScope = false; if (numVariables || numFunctions) { + if (codeBlock->isStrictMode()) { + variableObject = new (callFrame) StrictEvalActivation(callFrame); + scopeChain = scopeChain->push(variableObject); + pushedScope = true; + } // Scope for BatchedTransitionOptimizer BatchedTransitionOptimizer optimizer(variableObject); @@ -1070,6 +1122,8 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters; if (!m_registerFile.grow(newEnd)) { *exception = createStackOverflowError(callFrame); + if (pushedScope) + scopeChain->pop(); return jsNull(); } @@ -1112,6 +1166,8 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo()); m_registerFile.shrink(oldEnd); + if (pushedScope) + scopeChain->pop(); return result; } @@ -1518,6 +1574,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ int dst = vPC[1].u.operand; int src = vPC[2].u.operand; + callFrame->r(dst) = callFrame->r(src); vPC += OPCODE_LENGTH(op_mov); @@ -2327,6 +2384,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ScopeChainIterator iter = scopeChain->begin(); ScopeChainIterator end = scopeChain->end(); ASSERT(iter != end); + ASSERT(codeBlock == callFrame->codeBlock()); + bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + if (callFrame->r(codeBlock->activationRegister()).jsValue()) + ++iter; + } while (skip--) { ++iter; ASSERT(iter != end); @@ -2334,6 +2398,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT((*iter)->isVariableObject()); JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); callFrame->r(dst) = scope->registerAt(index); + ASSERT(callFrame->r(dst).jsValue()); vPC += OPCODE_LENGTH(op_get_scoped_var); NEXT_INSTRUCTION(); } @@ -2348,7 +2413,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ScopeChainNode* scopeChain = callFrame->scopeChain(); ScopeChainIterator iter = scopeChain->begin(); ScopeChainIterator end = scopeChain->end(); + ASSERT(codeBlock == callFrame->codeBlock()); ASSERT(iter != end); + bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + if (callFrame->r(codeBlock->activationRegister()).jsValue()) + ++iter; + } while (skip--) { ++iter; ASSERT(iter != end); @@ -2356,6 +2428,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT((*iter)->isVariableObject()); JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); + ASSERT(callFrame->r(value).jsValue()); scope->registerAt(index) = JSValue(callFrame->r(value).jsValue()); vPC += OPCODE_LENGTH(op_put_scoped_var); NEXT_INSTRUCTION(); @@ -2373,6 +2446,24 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi vPC += OPCODE_LENGTH(op_resolve_base); NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_ensure_property_exists) { + /* ensure_property_exists base(r) property(id) + + Throws an exception if property does not exist on base + */ + int base = vPC[1].u.operand; + int property = vPC[2].u.operand; + Identifier& ident = codeBlock->identifier(property); + + JSValue baseVal = callFrame->r(base).jsValue(); + JSObject* baseObject = asObject(baseVal); + PropertySlot slot(baseVal); + if (!baseObject->getPropertySlot(callFrame, ident, slot)) { + exceptionValue = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring()); + goto vm_throw; + } + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_resolve_with_base) { /* resolve_with_base baseDst(r) propDst(r) property(id) @@ -2922,7 +3013,7 @@ skip_id_custom_self: JSValue baseValue = callFrame->r(base).jsValue(); Identifier& ident = codeBlock->identifier(property); - PutPropertySlot slot; + PutPropertySlot slot(codeBlock->isStrictMode()); if (direct) { baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot); ASSERT(slot.base() == baseValue); @@ -3038,7 +3129,7 @@ skip_id_custom_self: JSValue baseValue = callFrame->r(base).jsValue(); Identifier& ident = codeBlock->identifier(property); - PutPropertySlot slot; + PutPropertySlot slot(codeBlock->isStrictMode()); if (direct) { baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot); ASSERT(slot.base() == baseValue); @@ -3063,9 +3154,13 @@ skip_id_custom_self: JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); Identifier& ident = codeBlock->identifier(property); - JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident)); + bool result = baseObj->deleteProperty(callFrame, ident); + if (!result && codeBlock->isStrictMode()) { + exceptionValue = createTypeError(callFrame, "Unable to delete property."); + goto vm_throw; + } CHECK_FOR_EXCEPTION(); - callFrame->r(dst) = result; + callFrame->r(dst) = jsBoolean(result); vPC += OPCODE_LENGTH(op_del_by_id); NEXT_INSTRUCTION(); } @@ -3131,8 +3226,8 @@ skip_id_custom_self: } if (!arguments) { Arguments* arguments = new (globalData) Arguments(callFrame); - callFrame->r(dst) = JSValue(arguments); - callFrame->r(unmodifiedArgumentsRegister(dst)) = JSValue(arguments); + callFrame->r(argumentsRegister) = JSValue(arguments); + callFrame->r(unmodifiedArgumentsRegister(argumentsRegister)) = JSValue(arguments); } // fallthrough } @@ -3218,7 +3313,7 @@ skip_id_custom_self: } else { Identifier property(callFrame, subscript.toString(callFrame)); if (!globalData->exception) { // Don't put to an object if toString threw an exception. - PutPropertySlot slot; + PutPropertySlot slot(codeBlock->isStrictMode()); baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot); } } @@ -3242,19 +3337,22 @@ skip_id_custom_self: JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw JSValue subscript = callFrame->r(property).jsValue(); - JSValue result; + bool result; uint32_t i; if (subscript.getUInt32(i)) - result = jsBoolean(baseObj->deleteProperty(callFrame, i)); + result = baseObj->deleteProperty(callFrame, i); else { CHECK_FOR_EXCEPTION(); Identifier property(callFrame, subscript.toString(callFrame)); CHECK_FOR_EXCEPTION(); - result = jsBoolean(baseObj->deleteProperty(callFrame, property)); + result = baseObj->deleteProperty(callFrame, property); + } + if (!result && codeBlock->isStrictMode()) { + exceptionValue = createTypeError(callFrame, "Unable to delete property."); + goto vm_throw; } - CHECK_FOR_EXCEPTION(); - callFrame->r(dst) = result; + callFrame->r(dst) = jsBoolean(result); vPC += OPCODE_LENGTH(op_del_by_val); NEXT_INSTRUCTION(); } @@ -3658,7 +3756,7 @@ skip_id_custom_self: int dst = vPC[1].u.operand; int func = vPC[2].u.operand; int shouldCheck = vPC[3].u.operand; - + ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue()); if (!shouldCheck || !callFrame->r(dst).jsValue()) callFrame->r(dst) = JSValue(codeBlock->functionDecl(func)->make(callFrame, callFrame->scopeChain())); @@ -3675,7 +3773,8 @@ skip_id_custom_self: */ int dst = vPC[1].u.operand; int funcIndex = vPC[2].u.operand; - + + ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue()); FunctionExecutable* function = codeBlock->functionExpr(funcIndex); JSFunction* func = function->make(callFrame, callFrame->scopeChain()); @@ -3711,7 +3810,8 @@ skip_id_custom_self: int func = vPC[1].u.operand; int argCount = vPC[2].u.operand; int registerOffset = vPC[3].u.operand; - + + ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue()); JSValue funcVal = callFrame->r(func).jsValue(); Register* newCallFrame = callFrame->registers() + registerOffset; @@ -3980,15 +4080,22 @@ skip_id_custom_self: This opcode appears before op_ret in functions that require full scope chains. */ - int src1 = vPC[1].u.operand; - int src2 = vPC[2].u.operand; + int activation = vPC[1].u.operand; + int arguments = vPC[2].u.operand; ASSERT(codeBlock->needsFullScopeChain()); - - JSActivation* activation = asActivation(callFrame->r(src1).jsValue()); - activation->copyRegisters(); - - if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src2)).jsValue()) - asArguments(arguments)->setActivation(activation); + JSValue activationValue = callFrame->r(activation).jsValue(); + if (activationValue) { + asActivation(activationValue)->copyRegisters(); + + if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) + asArguments(argumentsValue)->setActivation(asActivation(activationValue)); + } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) + asArguments(argumentsValue)->copyRegisters(); + + if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) { + if (!codeBlock->isStrictMode()) + asArguments(argumentsValue)->setActivation(asActivation(activationValue)); + } vPC += OPCODE_LENGTH(op_tear_off_activation); NEXT_INSTRUCTION(); @@ -4026,7 +4133,7 @@ skip_id_custom_self: int result = vPC[1].u.operand; - if (callFrame->codeBlock()->needsFullScopeChain()) + if (callFrame->codeBlock()->needsFullScopeChain() && callFrame->r(codeBlock->activationRegister()).jsValue()) callFrame->scopeChain()->deref(); JSValue returnValue = callFrame->r(result).jsValue(); @@ -4067,7 +4174,7 @@ skip_id_custom_self: int result = vPC[1].u.operand; - if (codeBlock->needsFullScopeChain()) + if (codeBlock->needsFullScopeChain() && callFrame->r(codeBlock->activationRegister()).jsValue()) callFrame->scopeChain()->deref(); JSValue returnValue = callFrame->r(result).jsValue(); @@ -4103,25 +4210,20 @@ skip_id_custom_self: vPC += OPCODE_LENGTH(op_enter); NEXT_INSTRUCTION(); } - DEFINE_OPCODE(op_enter_with_activation) { - /* enter_with_activation dst(r) - - Initializes local variables to undefined, creates an activation object, - places it in dst, and pushes it onto the scope chain. + DEFINE_OPCODE(op_create_activation) { + /* create_activation dst(r) - This opcode appears only at the beginning of a code block. + If the activation object for this callframe has not yet been created, + this creates it and writes it back to dst. */ - size_t i = 0; - for (size_t count = codeBlock->m_numVars; i < count; ++i) - callFrame->r(i) = jsUndefined(); - - int dst = vPC[1].u.operand; - JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable())); - callFrame->r(dst) = JSValue(activation); - callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation)); - - vPC += OPCODE_LENGTH(op_enter_with_activation); + int activationReg = vPC[1].u.operand; + if (!callFrame->r(activationReg).jsValue()) { + JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable())); + callFrame->r(activationReg) = JSValue(activation); + callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation)); + } + vPC += OPCODE_LENGTH(op_create_activation); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_get_callee) { @@ -4184,6 +4286,25 @@ skip_id_custom_self: vPC += OPCODE_LENGTH(op_convert_this); NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_convert_this_strict) { + /* convert_this_strict this(r) + + Takes the value in the 'this' register, and converts it to + its "this" form if (and only if) "this" is an object with a + custom this conversion + + This opcode should only be used at the beginning of a code + block. + */ + + int thisRegister = vPC[1].u.operand; + JSValue thisVal = callFrame->r(thisRegister).jsValue(); + if (thisVal.isObject() && thisVal.needsThisConversion()) + callFrame->r(thisRegister) = JSValue(thisVal.toStrictThisObject(callFrame)); + + vPC += OPCODE_LENGTH(op_convert_this_strict); + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_init_lazy_reg) { /* init_lazy_reg dst(r) diff --git a/JavaScriptCore/jit/ExecutableAllocator.h b/JavaScriptCore/jit/ExecutableAllocator.h index f145404..f362605 100644 --- a/JavaScriptCore/jit/ExecutableAllocator.h +++ b/JavaScriptCore/jit/ExecutableAllocator.h @@ -53,6 +53,12 @@ extern "C" __declspec(dllimport) void CacheRangeFlush(LPVOID pAddr, DWORD dwLength, DWORD dwFlags); #endif +#if PLATFORM(BREWMP) +#include <AEEIMemCache1.h> +#include <AEEMemCache1.bid> +#include <wtf/brew/RefPtrBrew.h> +#endif + #define JIT_ALLOCATOR_PAGE_SIZE (ExecutableAllocator::pageSize) #define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (ExecutableAllocator::pageSize * 4) @@ -294,6 +300,13 @@ public: { CacheRangeFlush(code, size, CACHE_SYNC_ALL); } +#elif PLATFORM(BREWMP) + static void cacheFlush(void* code, size_t size) + { + PlatformRefPtr<IMemCache1> memCache = createRefPtrInstance<IMemCache1>(AEECLSID_MemCache1); + IMemCache1_ClearCache(memCache.get(), reinterpret_cast<uint32>(code), size, MEMSPACE_CACHE_FLUSH, MEMSPACE_DATACACHE); + IMemCache1_ClearCache(memCache.get(), reinterpret_cast<uint32>(code), size, MEMSPACE_CACHE_INVALIDATE, MEMSPACE_INSTCACHE); + } #else #error "The cacheFlush support is missing on this platform." #endif diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp index a508d0c..0eabdf5 100644 --- a/JavaScriptCore/jit/JIT.cpp +++ b/JavaScriptCore/jit/JIT.cpp @@ -186,7 +186,7 @@ void JIT::privateCompileMainPass() sampleInstruction(currentInstruction); #endif -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) if (m_labels[m_bytecodeOffset].isUsed()) killLastResultRegister(); #endif @@ -195,9 +195,6 @@ void JIT::privateCompileMainPass() switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) { DEFINE_BINARY_OP(op_del_by_val) -#if USE(JSVALUE32) - DEFINE_BINARY_OP(op_div) -#endif DEFINE_BINARY_OP(op_in) DEFINE_BINARY_OP(op_less) DEFINE_BINARY_OP(op_lesseq) @@ -207,7 +204,7 @@ void JIT::privateCompileMainPass() DEFINE_UNARY_OP(op_is_object) DEFINE_UNARY_OP(op_is_string) DEFINE_UNARY_OP(op_is_undefined) -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) DEFINE_UNARY_OP(op_negate) #endif DEFINE_UNARY_OP(op_typeof) @@ -225,16 +222,15 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_get_callee) DEFINE_OP(op_create_this) DEFINE_OP(op_convert_this) + DEFINE_OP(op_convert_this_strict) DEFINE_OP(op_init_lazy_reg) DEFINE_OP(op_create_arguments) DEFINE_OP(op_debug) DEFINE_OP(op_del_by_id) -#if !USE(JSVALUE32) DEFINE_OP(op_div) -#endif DEFINE_OP(op_end) DEFINE_OP(op_enter) - DEFINE_OP(op_enter_with_activation) + DEFINE_OP(op_create_activation) DEFINE_OP(op_eq) DEFINE_OP(op_eq_null) DEFINE_OP(op_get_by_id) @@ -301,6 +297,7 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_put_setter) DEFINE_OP(op_resolve) DEFINE_OP(op_resolve_base) + DEFINE_OP(op_ensure_property_exists) DEFINE_OP(op_resolve_global) DEFINE_OP(op_resolve_global_dynamic) DEFINE_OP(op_resolve_skip) @@ -375,7 +372,7 @@ void JIT::privateCompileSlowCases() m_callLinkInfoIndex = 0; for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) { -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) killLastResultRegister(); #endif @@ -396,9 +393,8 @@ void JIT::privateCompileSlowCases() DEFINE_SLOWCASE_OP(op_call_varargs) DEFINE_SLOWCASE_OP(op_construct) DEFINE_SLOWCASE_OP(op_convert_this) -#if !USE(JSVALUE32) + DEFINE_SLOWCASE_OP(op_convert_this_strict) DEFINE_SLOWCASE_OP(op_div) -#endif DEFINE_SLOWCASE_OP(op_eq) DEFINE_SLOWCASE_OP(op_get_by_id) DEFINE_SLOWCASE_OP(op_get_arguments_length) @@ -596,7 +592,7 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) return patchBuffer.finalizeCode(); } -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) void JIT::emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst) { loadPtr(Address(variableObject, OBJECT_OFFSETOF(JSVariableObject, d)), dst); diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h index 6b2e70e..3ef0538 100644 --- a/JavaScriptCore/jit/JIT.h +++ b/JavaScriptCore/jit/JIT.h @@ -516,8 +516,7 @@ namespace JSC { Jump emitJumpIfNotJSCell(RegisterID); void emitJumpSlowCaseIfNotJSCell(RegisterID); void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg); -#if USE(JSVALUE64) -#else +#if USE(JSVALUE32_64) JIT::Jump emitJumpIfImmediateNumber(RegisterID reg) { return emitJumpIfImmediateInteger(reg); @@ -535,7 +534,7 @@ namespace JSC { void emitJumpSlowCaseIfNotImmediateNumber(RegisterID); void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID); -#if !USE(JSVALUE64) +#if USE(JSVALUE32_64) void emitFastArithDeTagImmediate(RegisterID); Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID); #endif @@ -738,13 +737,14 @@ namespace JSC { void emit_op_get_callee(Instruction*); void emit_op_create_this(Instruction*); void emit_op_convert_this(Instruction*); + void emit_op_convert_this_strict(Instruction*); void emit_op_create_arguments(Instruction*); void emit_op_debug(Instruction*); void emit_op_del_by_id(Instruction*); void emit_op_div(Instruction*); void emit_op_end(Instruction*); void emit_op_enter(Instruction*); - void emit_op_enter_with_activation(Instruction*); + void emit_op_create_activation(Instruction*); void emit_op_eq(Instruction*); void emit_op_eq_null(Instruction*); void emit_op_get_by_id(Instruction*); @@ -810,6 +810,7 @@ namespace JSC { void emit_op_put_setter(Instruction*); void emit_op_resolve(Instruction*); void emit_op_resolve_base(Instruction*); + void emit_op_ensure_property_exists(Instruction*); void emit_op_resolve_global(Instruction*, bool dynamic = false); void emit_op_resolve_global_dynamic(Instruction*); void emit_op_resolve_skip(Instruction*); @@ -845,6 +846,7 @@ namespace JSC { void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_convert_this(Instruction*, Vector<SlowCaseEntry>::iterator&); + void emitSlow_op_convert_this_strict(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&); diff --git a/JavaScriptCore/jit/JITArithmetic.cpp b/JavaScriptCore/jit/JITArithmetic.cpp index d75f8b5..d4fa12f 100644 --- a/JavaScriptCore/jit/JITArithmetic.cpp +++ b/JavaScriptCore/jit/JITArithmetic.cpp @@ -26,7 +26,7 @@ #include "config.h" #if ENABLE(JIT) -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) #include "JIT.h" #include "CodeBlock.h" @@ -60,10 +60,6 @@ void JIT::emit_op_lshift(Instruction* currentInstruction) emitFastArithImmToInt(regT0); emitFastArithImmToInt(regT2); lshift32(regT2, regT0); -#if USE(JSVALUE32) - addSlowCase(branchAdd32(Overflow, regT0, regT0)); - signExtend32ToPtr(regT0, regT0); -#endif emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(result); } @@ -74,20 +70,10 @@ void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEnt unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; -#if USE(JSVALUE64) UNUSED_PARAM(op1); UNUSED_PARAM(op2); linkSlowCase(iter); linkSlowCase(iter); -#else - // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded. - Jump notImm1 = getSlowCase(iter); - Jump notImm2 = getSlowCase(iter); - linkSlowCase(iter); - emitGetVirtualRegisters(op1, regT0, op2, regT2); - notImm1.link(this); - notImm2.link(this); -#endif JITStubCall stubCall(this, cti_op_lshift); stubCall.addArgument(regT0); stubCall.addArgument(regT2); @@ -110,20 +96,11 @@ void JIT::emit_op_rshift(Instruction* currentInstruction) emitGetVirtualRegisters(op1, regT0, op2, regT2); if (supportsFloatingPointTruncate()) { Jump lhsIsInt = emitJumpIfImmediateInteger(regT0); -#if USE(JSVALUE64) // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases addSlowCase(emitJumpIfNotImmediateNumber(regT0)); addPtr(tagTypeNumberRegister, regT0); movePtrToDouble(regT0, fpRegT0); addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0)); -#else - // supportsFloatingPoint() && !USE(JSVALUE64) => 5 SlowCases (of which 1 IfNotJSCell) - emitJumpSlowCaseIfNotJSCell(regT0, op1); - addSlowCase(checkStructure(regT0, m_globalData->numberStructure.get())); - loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); - addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0)); - addSlowCase(branchAdd32(Overflow, regT0, regT0)); -#endif lhsIsInt.link(this); emitJumpSlowCaseIfNotImmediateInteger(regT2); } else { @@ -133,15 +110,8 @@ void JIT::emit_op_rshift(Instruction* currentInstruction) } emitFastArithImmToInt(regT2); rshift32(regT2, regT0); -#if USE(JSVALUE32) - signExtend32ToPtr(regT0, regT0); -#endif } -#if USE(JSVALUE64) emitFastArithIntToImmNoCheck(regT0, regT0); -#else - orPtr(Imm32(JSImmediate::TagTypeNumber), regT0); -#endif emitPutVirtualRegister(result); } @@ -159,17 +129,9 @@ void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEnt stubCall.addArgument(op2, regT2); } else { if (supportsFloatingPointTruncate()) { -#if USE(JSVALUE64) - linkSlowCase(iter); - linkSlowCase(iter); - linkSlowCase(iter); -#else - linkSlowCaseIfNotJSCell(iter, op1); - linkSlowCase(iter); linkSlowCase(iter); linkSlowCase(iter); linkSlowCase(iter); -#endif // We're reloading op1 to regT0 as we can no longer guarantee that // we have not munged the operand. It may have already been shifted // correctly, but it still will not have been tagged. @@ -206,10 +168,6 @@ void JIT::emit_op_urshift(Instruction* currentInstruction) // as an immediate int. if (shift < 0 || !(shift & 31)) addSlowCase(branch32(LessThan, regT0, Imm32(0))); -#if USE(JSVALUE32) - addSlowCase(branchAdd32(Overflow, regT0, regT0)); - signExtend32ToPtr(regT0, regT0); -#endif emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(dst, regT0); return; @@ -222,10 +180,6 @@ void JIT::emit_op_urshift(Instruction* currentInstruction) emitFastArithImmToInt(regT1); urshift32(regT1, regT0); addSlowCase(branch32(LessThan, regT0, Imm32(0))); -#if USE(JSVALUE32) - addSlowCase(branchAdd32(Overflow, regT0, regT0)); - signExtend32ToPtr(regT0, regT0); -#endif emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(dst, regT0); } @@ -239,7 +193,6 @@ void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEn int shift = getConstantOperand(op2).asInt32(); // op1 = regT0 linkSlowCase(iter); // int32 check -#if USE(JSVALUE64) if (supportsFloatingPointTruncate()) { JumpList failures; failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double @@ -255,18 +208,13 @@ void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEn emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift)); failures.link(this); } -#endif // JSVALUE64 if (shift < 0 || !(shift & 31)) linkSlowCase(iter); // failed to box in hot path -#if USE(JSVALUE32) - linkSlowCase(iter); // Couldn't box result -#endif } else { // op1 = regT0 // op2 = regT1 if (!isOperandConstantImmediateInt(op1)) { linkSlowCase(iter); // int32 check -- op1 is not an int -#if USE(JSVALUE64) if (supportsFloatingPointTruncate()) { JumpList failures; failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double @@ -282,14 +230,10 @@ void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEn emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift)); failures.link(this); } -#endif } linkSlowCase(iter); // int32 check - op2 is not an int linkSlowCase(iter); // Can't represent unsigned result as an immediate -#if USE(JSVALUE32) - linkSlowCase(iter); // Couldn't box result -#endif } JITStubCall stubCall(this, cti_op_urshift); @@ -330,20 +274,12 @@ void JIT::emit_op_jnless(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) int32_t op2imm = getConstantOperandImmediateInt(op2); -#else - int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); -#endif addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target); } else if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1); -#if USE(JSVALUE64) int32_t op1imm = getConstantOperandImmediateInt(op1); -#else - int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); -#endif addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target); } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); @@ -381,18 +317,9 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt linkSlowCase(iter); if (supportsFloatingPoint()) { -#if USE(JSVALUE64) Jump fail1 = emitJumpIfNotImmediateNumber(regT0); addPtr(tagTypeNumberRegister, regT0); movePtrToDouble(regT0, fpRegT0); -#else - Jump fail1; - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1 = emitJumpIfNotJSCell(regT0); - - Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); - loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); -#endif int32_t op2imm = getConstantOperand(op2).asInt32();; @@ -403,13 +330,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); -#if USE(JSVALUE64) fail1.link(this); -#else - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1.link(this); - fail2.link(this); -#endif } JITStubCall stubCall(this, cti_op_jless); @@ -422,18 +343,9 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt linkSlowCase(iter); if (supportsFloatingPoint()) { -#if USE(JSVALUE64) Jump fail1 = emitJumpIfNotImmediateNumber(regT1); addPtr(tagTypeNumberRegister, regT1); movePtrToDouble(regT1, fpRegT1); -#else - Jump fail1; - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail1 = emitJumpIfNotJSCell(regT1); - - Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); - loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); -#endif int32_t op1imm = getConstantOperand(op1).asInt32();; @@ -444,13 +356,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); -#if USE(JSVALUE64) fail1.link(this); -#else - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail1.link(this); - fail2.link(this); -#endif } JITStubCall stubCall(this, cti_op_jless); @@ -463,7 +369,6 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt linkSlowCase(iter); if (supportsFloatingPoint()) { -#if USE(JSVALUE64) Jump fail1 = emitJumpIfNotImmediateNumber(regT0); Jump fail2 = emitJumpIfNotImmediateNumber(regT1); Jump fail3 = emitJumpIfImmediateInteger(regT1); @@ -471,37 +376,14 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt addPtr(tagTypeNumberRegister, regT1); movePtrToDouble(regT0, fpRegT0); movePtrToDouble(regT1, fpRegT1); -#else - Jump fail1; - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1 = emitJumpIfNotJSCell(regT0); - - Jump fail2; - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail2 = emitJumpIfNotJSCell(regT1); - - Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get()); - Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get()); - loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); - loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); -#endif emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); -#if USE(JSVALUE64) fail1.link(this); fail2.link(this); fail3.link(this); -#else - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1.link(this); - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail2.link(this); - fail3.link(this); - fail4.link(this); -#endif } linkSlowCase(iter); @@ -545,20 +427,12 @@ void JIT::emit_op_jless(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) int32_t op2imm = getConstantOperandImmediateInt(op2); -#else - int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); -#endif addJump(branch32(LessThan, regT0, Imm32(op2imm)), target); } else if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1); -#if USE(JSVALUE64) int32_t op1imm = getConstantOperandImmediateInt(op1); -#else - int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); -#endif addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target); } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); @@ -596,18 +470,9 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr linkSlowCase(iter); if (supportsFloatingPoint()) { -#if USE(JSVALUE64) Jump fail1 = emitJumpIfNotImmediateNumber(regT0); addPtr(tagTypeNumberRegister, regT0); movePtrToDouble(regT0, fpRegT0); -#else - Jump fail1; - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1 = emitJumpIfNotJSCell(regT0); - - Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); - loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); -#endif int32_t op2imm = getConstantOperand(op2).asInt32(); @@ -618,13 +483,7 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); -#if USE(JSVALUE64) fail1.link(this); -#else - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1.link(this); - fail2.link(this); -#endif } JITStubCall stubCall(this, cti_op_jless); @@ -637,18 +496,9 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr linkSlowCase(iter); if (supportsFloatingPoint()) { -#if USE(JSVALUE64) Jump fail1 = emitJumpIfNotImmediateNumber(regT1); addPtr(tagTypeNumberRegister, regT1); movePtrToDouble(regT1, fpRegT1); -#else - Jump fail1; - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail1 = emitJumpIfNotJSCell(regT1); - - Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); - loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); -#endif int32_t op1imm = getConstantOperand(op1).asInt32(); @@ -659,13 +509,7 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); -#if USE(JSVALUE64) fail1.link(this); -#else - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail1.link(this); - fail2.link(this); -#endif } JITStubCall stubCall(this, cti_op_jless); @@ -678,7 +522,6 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr linkSlowCase(iter); if (supportsFloatingPoint()) { -#if USE(JSVALUE64) Jump fail1 = emitJumpIfNotImmediateNumber(regT0); Jump fail2 = emitJumpIfNotImmediateNumber(regT1); Jump fail3 = emitJumpIfImmediateInteger(regT1); @@ -686,37 +529,14 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr addPtr(tagTypeNumberRegister, regT1); movePtrToDouble(regT0, fpRegT0); movePtrToDouble(regT1, fpRegT1); -#else - Jump fail1; - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1 = emitJumpIfNotJSCell(regT0); - - Jump fail2; - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail2 = emitJumpIfNotJSCell(regT1); - - Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get()); - Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get()); - loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); - loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); -#endif emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); -#if USE(JSVALUE64) fail1.link(this); fail2.link(this); fail3.link(this); -#else - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1.link(this); - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail2.link(this); - fail3.link(this); - fail4.link(this); -#endif } linkSlowCase(iter); @@ -760,20 +580,12 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert) if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) int32_t op2imm = getConstantOperandImmediateInt(op2); -#else - int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); -#endif addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(op2imm)), target); } else if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1); -#if USE(JSVALUE64) int32_t op1imm = getConstantOperandImmediateInt(op1); -#else - int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); -#endif addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT1, Imm32(op1imm)), target); } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); @@ -812,18 +624,9 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn linkSlowCase(iter); if (supportsFloatingPoint()) { -#if USE(JSVALUE64) Jump fail1 = emitJumpIfNotImmediateNumber(regT0); addPtr(tagTypeNumberRegister, regT0); movePtrToDouble(regT0, fpRegT0); -#else - Jump fail1; - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1 = emitJumpIfNotJSCell(regT0); - - Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); - loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); -#endif int32_t op2imm = getConstantOperand(op2).asInt32();; @@ -834,13 +637,7 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); -#if USE(JSVALUE64) fail1.link(this); -#else - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1.link(this); - fail2.link(this); -#endif } JITStubCall stubCall(this, cti_op_jlesseq); @@ -853,18 +650,9 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn linkSlowCase(iter); if (supportsFloatingPoint()) { -#if USE(JSVALUE64) Jump fail1 = emitJumpIfNotImmediateNumber(regT1); addPtr(tagTypeNumberRegister, regT1); movePtrToDouble(regT1, fpRegT1); -#else - Jump fail1; - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail1 = emitJumpIfNotJSCell(regT1); - - Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); - loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); -#endif int32_t op1imm = getConstantOperand(op1).asInt32();; @@ -875,13 +663,7 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); -#if USE(JSVALUE64) fail1.link(this); -#else - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail1.link(this); - fail2.link(this); -#endif } JITStubCall stubCall(this, cti_op_jlesseq); @@ -894,7 +676,6 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn linkSlowCase(iter); if (supportsFloatingPoint()) { -#if USE(JSVALUE64) Jump fail1 = emitJumpIfNotImmediateNumber(regT0); Jump fail2 = emitJumpIfNotImmediateNumber(regT1); Jump fail3 = emitJumpIfImmediateInteger(regT1); @@ -902,37 +683,14 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn addPtr(tagTypeNumberRegister, regT1); movePtrToDouble(regT0, fpRegT0); movePtrToDouble(regT1, fpRegT1); -#else - Jump fail1; - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1 = emitJumpIfNotJSCell(regT0); - - Jump fail2; - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail2 = emitJumpIfNotJSCell(regT1); - - Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get()); - Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get()); - loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); - loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); -#endif emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); -#if USE(JSVALUE64) fail1.link(this); fail2.link(this); fail3.link(this); -#else - if (!m_codeBlock->isKnownNotImmediate(op1)) - fail1.link(this); - if (!m_codeBlock->isKnownNotImmediate(op2)) - fail2.link(this); - fail3.link(this); - fail4.link(this); -#endif } linkSlowCase(iter); @@ -963,25 +721,17 @@ void JIT::emit_op_bitand(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) int32_t imm = getConstantOperandImmediateInt(op1); andPtr(Imm32(imm), regT0); if (imm >= 0) emitFastArithIntToImmNoCheck(regT0, regT0); -#else - andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), regT0); -#endif } else if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) int32_t imm = getConstantOperandImmediateInt(op2); andPtr(Imm32(imm), regT0); if (imm >= 0) emitFastArithIntToImmNoCheck(regT0, regT0); -#else - andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), regT0); -#endif } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); andPtr(regT1, regT0); @@ -1023,13 +773,8 @@ void JIT::emit_op_post_inc(Instruction* currentInstruction) emitGetVirtualRegister(srcDst, regT0); move(regT0, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) addSlowCase(branchAdd32(Overflow, Imm32(1), regT1)); emitFastArithIntToImmNoCheck(regT1, regT1); -#else - addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1)); - signExtend32ToPtr(regT1, regT1); -#endif emitPutVirtualRegister(srcDst, regT1); emitPutVirtualRegister(result); } @@ -1055,13 +800,8 @@ void JIT::emit_op_post_dec(Instruction* currentInstruction) emitGetVirtualRegister(srcDst, regT0); move(regT0, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) addSlowCase(branchSub32(Zero, Imm32(1), regT1)); emitFastArithIntToImmNoCheck(regT1, regT1); -#else - addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1)); - signExtend32ToPtr(regT1, regT1); -#endif emitPutVirtualRegister(srcDst, regT1); emitPutVirtualRegister(result); } @@ -1085,13 +825,8 @@ void JIT::emit_op_pre_inc(Instruction* currentInstruction) emitGetVirtualRegister(srcDst, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); emitFastArithIntToImmNoCheck(regT0, regT0); -#else - addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0)); - signExtend32ToPtr(regT0, regT0); -#endif emitPutVirtualRegister(srcDst); } @@ -1114,13 +849,8 @@ void JIT::emit_op_pre_dec(Instruction* currentInstruction) emitGetVirtualRegister(srcDst, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) addSlowCase(branchSub32(Zero, Imm32(1), regT0)); emitFastArithIntToImmNoCheck(regT0, regT0); -#else - addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0)); - signExtend32ToPtr(regT0, regT0); -#endif emitPutVirtualRegister(srcDst); } @@ -1158,22 +888,9 @@ void JIT::emit_op_mod(Instruction* currentInstruction) emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT2); -#if USE(JSVALUE64) addSlowCase(branchPtr(Equal, regT2, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0))))); m_assembler.cdq(); m_assembler.idivl_r(regT2); -#else - emitFastArithDeTagImmediate(regT0); - addSlowCase(emitFastArithDeTagImmediateJumpIfZero(regT2)); -#if CPU(X86) || CPU(X86_64) - m_assembler.cdq(); - m_assembler.idivl_r(regT2); - signExtend32ToPtr(regT1, regT1); -#elif CPU(MIPS) - m_assembler.div(regT0, regT2); - m_assembler.mfhi(regT1); -#endif -#endif emitFastArithReTagImmediate(regT1, regT0); emitPutVirtualRegister(result); } @@ -1182,19 +899,9 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry> { unsigned result = currentInstruction[1].u.operand; -#if USE(JSVALUE64) linkSlowCase(iter); linkSlowCase(iter); linkSlowCase(iter); -#else - Jump notImm1 = getSlowCase(iter); - Jump notImm2 = getSlowCase(iter); - linkSlowCase(iter); - emitFastArithReTagImmediate(regT0, regT0); - emitFastArithReTagImmediate(regT2, regT2); - notImm1.link(this); - notImm2.link(this); -#endif JITStubCall stubCall(this, cti_op_mod); stubCall.addArgument(regT0); stubCall.addArgument(regT2); @@ -1249,8 +956,6 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry> /* ------------------------------ END: OP_MOD ------------------------------ */ -#if USE(JSVALUE64) - /* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes) @@ -1543,310 +1248,9 @@ void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry> compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types, false, false); } -#else // USE(JSVALUE64) - -/* ------------------------------ BEGIN: !USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */ - -void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types) -{ - Structure* numberStructure = m_globalData->numberStructure.get(); - Jump wasJSNumberCell1; - Jump wasJSNumberCell2; - - emitGetVirtualRegisters(src1, regT0, src2, regT1); - - if (types.second().isReusable() && supportsFloatingPoint()) { - ASSERT(types.second().mightBeNumber()); - - // Check op2 is a number - Jump op2imm = emitJumpIfImmediateInteger(regT1); - if (!types.second().definitelyIsNumber()) { - emitJumpSlowCaseIfNotJSCell(regT1, src2); - addSlowCase(checkStructure(regT1, numberStructure)); - } - - // (1) In this case src2 is a reusable number cell. - // Slow case if src1 is not a number type. - Jump op1imm = emitJumpIfImmediateInteger(regT0); - if (!types.first().definitelyIsNumber()) { - emitJumpSlowCaseIfNotJSCell(regT0, src1); - addSlowCase(checkStructure(regT0, numberStructure)); - } - - // (1a) if we get here, src1 is also a number cell - loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); - Jump loadedDouble = jump(); - // (1b) if we get here, src1 is an immediate - op1imm.link(this); - emitFastArithImmToInt(regT0); - convertInt32ToDouble(regT0, fpRegT0); - // (1c) - loadedDouble.link(this); - if (opcodeID == op_add) - addDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); - else if (opcodeID == op_sub) - subDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); - else { - ASSERT(opcodeID == op_mul); - mulDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); - } - - // Store the result to the JSNumberCell and jump. - storeDouble(fpRegT0, Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value))); - move(regT1, regT0); - emitPutVirtualRegister(dst); - wasJSNumberCell2 = jump(); - - // (2) This handles cases where src2 is an immediate number. - // Two slow cases - either src1 isn't an immediate, or the subtract overflows. - op2imm.link(this); - emitJumpSlowCaseIfNotImmediateInteger(regT0); - } else if (types.first().isReusable() && supportsFloatingPoint()) { - ASSERT(types.first().mightBeNumber()); - - // Check op1 is a number - Jump op1imm = emitJumpIfImmediateInteger(regT0); - if (!types.first().definitelyIsNumber()) { - emitJumpSlowCaseIfNotJSCell(regT0, src1); - addSlowCase(checkStructure(regT0, numberStructure)); - } - - // (1) In this case src1 is a reusable number cell. - // Slow case if src2 is not a number type. - Jump op2imm = emitJumpIfImmediateInteger(regT1); - if (!types.second().definitelyIsNumber()) { - emitJumpSlowCaseIfNotJSCell(regT1, src2); - addSlowCase(checkStructure(regT1, numberStructure)); - } - - // (1a) if we get here, src2 is also a number cell - loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); - Jump loadedDouble = jump(); - // (1b) if we get here, src2 is an immediate - op2imm.link(this); - emitFastArithImmToInt(regT1); - convertInt32ToDouble(regT1, fpRegT1); - // (1c) - loadedDouble.link(this); - loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); - if (opcodeID == op_add) - addDouble(fpRegT1, fpRegT0); - else if (opcodeID == op_sub) - subDouble(fpRegT1, fpRegT0); - else { - ASSERT(opcodeID == op_mul); - mulDouble(fpRegT1, fpRegT0); - } - storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value))); - emitPutVirtualRegister(dst); - - // Store the result to the JSNumberCell and jump. - storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value))); - emitPutVirtualRegister(dst); - wasJSNumberCell1 = jump(); - - // (2) This handles cases where src1 is an immediate number. - // Two slow cases - either src2 isn't an immediate, or the subtract overflows. - op1imm.link(this); - emitJumpSlowCaseIfNotImmediateInteger(regT1); - } else - emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2); - - if (opcodeID == op_add) { - emitFastArithDeTagImmediate(regT0); - addSlowCase(branchAdd32(Overflow, regT1, regT0)); - } else if (opcodeID == op_sub) { - addSlowCase(branchSub32(Overflow, regT1, regT0)); - signExtend32ToPtr(regT0, regT0); - emitFastArithReTagImmediate(regT0, regT0); - } else { - ASSERT(opcodeID == op_mul); - // convert eax & edx from JSImmediates to ints, and check if either are zero - emitFastArithImmToInt(regT1); - Jump op1Zero = emitFastArithDeTagImmediateJumpIfZero(regT0); - Jump op2NonZero = branchTest32(NonZero, regT1); - op1Zero.link(this); - // if either input is zero, add the two together, and check if the result is < 0. - // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate. - move(regT0, regT2); - addSlowCase(branchAdd32(Signed, regT1, regT2)); - // Skip the above check if neither input is zero - op2NonZero.link(this); - addSlowCase(branchMul32(Overflow, regT1, regT0)); - signExtend32ToPtr(regT0, regT0); - emitFastArithReTagImmediate(regT0, regT0); - } - emitPutVirtualRegister(dst); - - if (types.second().isReusable() && supportsFloatingPoint()) - wasJSNumberCell2.link(this); - else if (types.first().isReusable() && supportsFloatingPoint()) - wasJSNumberCell1.link(this); -} - -void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types) -{ - linkSlowCase(iter); - if (types.second().isReusable() && supportsFloatingPoint()) { - if (!types.first().definitelyIsNumber()) { - linkSlowCaseIfNotJSCell(iter, src1); - linkSlowCase(iter); - } - if (!types.second().definitelyIsNumber()) { - linkSlowCaseIfNotJSCell(iter, src2); - linkSlowCase(iter); - } - } else if (types.first().isReusable() && supportsFloatingPoint()) { - if (!types.first().definitelyIsNumber()) { - linkSlowCaseIfNotJSCell(iter, src1); - linkSlowCase(iter); - } - if (!types.second().definitelyIsNumber()) { - linkSlowCaseIfNotJSCell(iter, src2); - linkSlowCase(iter); - } - } - linkSlowCase(iter); - - // additional entry point to handle -0 cases. - if (opcodeID == op_mul) - linkSlowCase(iter); - - JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul); - stubCall.addArgument(src1, regT2); - stubCall.addArgument(src2, regT2); - stubCall.call(dst); -} - -void JIT::emit_op_add(Instruction* currentInstruction) -{ - unsigned result = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - - if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { - JITStubCall stubCall(this, cti_op_add); - stubCall.addArgument(op1, regT2); - stubCall.addArgument(op2, regT2); - stubCall.call(result); - return; - } - - if (isOperandConstantImmediateInt(op1)) { - emitGetVirtualRegister(op2, regT0); - emitJumpSlowCaseIfNotImmediateInteger(regT0); - addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0)); - signExtend32ToPtr(regT0, regT0); - emitPutVirtualRegister(result); - } else if (isOperandConstantImmediateInt(op2)) { - emitGetVirtualRegister(op1, regT0); - emitJumpSlowCaseIfNotImmediateInteger(regT0); - addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0)); - signExtend32ToPtr(regT0, regT0); - emitPutVirtualRegister(result); - } else { - compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand)); - } -} - -void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned result = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) - return; - - if (isOperandConstantImmediateInt(op1)) { - Jump notImm = getSlowCase(iter); - linkSlowCase(iter); - sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0); - notImm.link(this); - JITStubCall stubCall(this, cti_op_add); - stubCall.addArgument(op1, regT2); - stubCall.addArgument(regT0); - stubCall.call(result); - } else if (isOperandConstantImmediateInt(op2)) { - Jump notImm = getSlowCase(iter); - linkSlowCase(iter); - sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0); - notImm.link(this); - JITStubCall stubCall(this, cti_op_add); - stubCall.addArgument(regT0); - stubCall.addArgument(op2, regT2); - stubCall.call(result); - } else { - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber()); - compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types); - } -} - -void JIT::emit_op_mul(Instruction* currentInstruction) -{ - unsigned result = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - // For now, only plant a fast int case if the constant operand is greater than zero. - int32_t value; - if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) { - emitGetVirtualRegister(op2, regT0); - emitJumpSlowCaseIfNotImmediateInteger(regT0); - emitFastArithDeTagImmediate(regT0); - addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0)); - signExtend32ToPtr(regT0, regT0); - emitFastArithReTagImmediate(regT0, regT0); - emitPutVirtualRegister(result); - } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) { - emitGetVirtualRegister(op1, regT0); - emitJumpSlowCaseIfNotImmediateInteger(regT0); - emitFastArithDeTagImmediate(regT0); - addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0)); - signExtend32ToPtr(regT0, regT0); - emitFastArithReTagImmediate(regT0, regT0); - emitPutVirtualRegister(result); - } else - compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand)); -} - -void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned result = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0)) - || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) { - linkSlowCase(iter); - linkSlowCase(iter); - // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0. - JITStubCall stubCall(this, cti_op_mul); - stubCall.addArgument(op1, regT2); - stubCall.addArgument(op2, regT2); - stubCall.call(result); - } else - compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand)); -} - -void JIT::emit_op_sub(Instruction* currentInstruction) -{ - compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand)); -} - -void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand)); -} - -#endif // USE(JSVALUE64) - /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */ } // namespace JSC -#endif // !USE(JSVALUE32_64) +#endif // USE(JSVALUE64) #endif // ENABLE(JIT) diff --git a/JavaScriptCore/jit/JITCall.cpp b/JavaScriptCore/jit/JITCall.cpp index 368eab9..fdd0d47 100644 --- a/JavaScriptCore/jit/JITCall.cpp +++ b/JavaScriptCore/jit/JITCall.cpp @@ -26,7 +26,7 @@ #include "config.h" #if ENABLE(JIT) -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) #include "JIT.h" #include "CodeBlock.h" @@ -257,5 +257,5 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>: } // namespace JSC -#endif // !USE(JSVALUE32_64) +#endif // USE(JSVALUE64) #endif // ENABLE(JIT) diff --git a/JavaScriptCore/jit/JITCall32_64.cpp b/JavaScriptCore/jit/JITCall32_64.cpp index e4005ae..daf5d2d 100644 --- a/JavaScriptCore/jit/JITCall32_64.cpp +++ b/JavaScriptCore/jit/JITCall32_64.cpp @@ -108,9 +108,11 @@ void JIT::emit_op_ret(Instruction* currentInstruction) unsigned dst = currentInstruction[1].u.operand; // We could JIT generate the deref, only calling out to C when the refcount hits zero. - if (m_codeBlock->needsFullScopeChain()) + if (m_codeBlock->needsFullScopeChain()) { + Jump activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag)); JITStubCall(this, cti_op_ret_scopeChain).call(); - + activationNotCreated.link(this); + } emitLoad(dst, regT1, regT0); emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2); emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); @@ -125,8 +127,11 @@ void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) unsigned thisReg = currentInstruction[2].u.operand; // We could JIT generate the deref, only calling out to C when the refcount hits zero. - if (m_codeBlock->needsFullScopeChain()) + if (m_codeBlock->needsFullScopeChain()) { + Jump activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag)); JITStubCall(this, cti_op_ret_scopeChain).call(); + activationNotCreated.link(this); + } emitLoad(result, regT1, regT0); Jump notJSCell = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); diff --git a/JavaScriptCore/jit/JITInlineMethods.h b/JavaScriptCore/jit/JITInlineMethods.h index e2e77db..0fe9929 100644 --- a/JavaScriptCore/jit/JITInlineMethods.h +++ b/JavaScriptCore/jit/JITInlineMethods.h @@ -63,7 +63,7 @@ ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, RegisterF ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) { loadPtr(Address(from, entry * sizeof(Register)), to); -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) killLastResultRegister(); #endif } @@ -81,7 +81,7 @@ ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) { load32(Address(from, entry * sizeof(Register)), to); -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) killLastResultRegister(); #endif } @@ -750,7 +750,7 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateNumber(RegisterID reg) addSlowCase(emitJumpIfNotImmediateNumber(reg)); } -#if !USE(JSVALUE64) +#if USE(JSVALUE32_64) ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg) { subPtr(Imm32(JSImmediate::TagTypeNumber), reg); diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp index c81932a..a468c18 100644 --- a/JavaScriptCore/jit/JITOpcodes.cpp +++ b/JavaScriptCore/jit/JITOpcodes.cpp @@ -39,7 +39,7 @@ namespace JSC { -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) #define RECORD_JUMP_TARGET(targetOffset) \ do { m_labels[m_bytecodeOffset + (targetOffset)].used(); } while (false) @@ -337,6 +337,7 @@ void JIT::emit_op_end(Instruction* currentInstruction) { if (m_codeBlock->needsFullScopeChain()) JITStubCall(this, cti_op_end).call(); + ASSERT(returnValueRegister != callFrameRegister); emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister); restoreReturnAddressBeforeReturn(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)))); @@ -360,11 +361,7 @@ void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) int32_t op2imm = getConstantOperandImmediateInt(op2); -#else - int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); -#endif addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target); } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); @@ -467,6 +464,15 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction) int skip = currentInstruction[3].u.operand; emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0); + bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + Jump activationNotCreated; + if (checkTopLevel) + activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister())); + loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0); + activationNotCreated.link(this); + } while (skip--) loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0); @@ -481,6 +487,15 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction) emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1); emitGetVirtualRegister(currentInstruction[3].u.operand, regT0); + bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + Jump activationNotCreated; + if (checkTopLevel) + activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister())); + loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1); + activationNotCreated.link(this); + } while (skip--) loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1); @@ -490,10 +505,16 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction) void JIT::emit_op_tear_off_activation(Instruction* currentInstruction) { + unsigned activation = currentInstruction[1].u.operand; + unsigned arguments = currentInstruction[2].u.operand; + Jump activationCreated = branchTestPtr(NonZero, addressFor(activation)); + Jump argumentsNotCreated = branchTestPtr(Zero, addressFor(arguments)); + activationCreated.link(this); JITStubCall stubCall(this, cti_op_tear_off_activation); - stubCall.addArgument(currentInstruction[1].u.operand, regT2); - stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand), regT2); + stubCall.addArgument(activation, regT2); + stubCall.addArgument(unmodifiedArgumentsRegister(arguments), regT2); stubCall.call(); + argumentsNotCreated.link(this); } void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction) @@ -510,9 +531,11 @@ void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction) void JIT::emit_op_ret(Instruction* currentInstruction) { // We could JIT generate the deref, only calling out to C when the refcount hits zero. - if (m_codeBlock->needsFullScopeChain()) + if (m_codeBlock->needsFullScopeChain()) { + Jump activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister())); JITStubCall(this, cti_op_ret_scopeChain).call(); - + activationNotCreated.link(this); + } ASSERT(callFrameRegister != regT1); ASSERT(regT1 != returnValueRegister); ASSERT(returnValueRegister != callFrameRegister); @@ -534,8 +557,11 @@ void JIT::emit_op_ret(Instruction* currentInstruction) void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) { // We could JIT generate the deref, only calling out to C when the refcount hits zero. - if (m_codeBlock->needsFullScopeChain()) + if (m_codeBlock->needsFullScopeChain()) { + Jump activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister())); JITStubCall(this, cti_op_ret_scopeChain).call(); + activationNotCreated.link(this); + } ASSERT(callFrameRegister != regT1); ASSERT(regT1 != returnValueRegister); @@ -614,7 +640,15 @@ void JIT::emit_op_strcat(Instruction* currentInstruction) void JIT::emit_op_resolve_base(Instruction* currentInstruction) { - JITStubCall stubCall(this, cti_op_resolve_base); + JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base); + stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.call(currentInstruction[1].u.operand); +} + +void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction) +{ + JITStubCall stubCall(this, cti_op_ensure_property_exists); + stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -772,12 +806,8 @@ void JIT::emit_op_bitnot(Instruction* currentInstruction) { emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) not32(regT0); emitFastArithIntToImmNoCheck(regT0, regT0); -#else - xorPtr(Imm32(~JSImmediate::TagTypeNumber), regT0); -#endif emitPutVirtualRegister(currentInstruction[1].u.operand); } @@ -865,7 +895,7 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction) emitGetVirtualRegister(base, regT0); if (!m_codeBlock->isKnownNotImmediate(base)) isNotObject.append(emitJumpIfNotJSCell(regT0)); - if (base != m_codeBlock->thisRegister()) { + if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) { loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); isNotObject.append(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); } @@ -913,11 +943,7 @@ void JIT::emit_op_next_pname(Instruction* currentInstruction) loadPtr(addressFor(it), regT1); loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2); -#if USE(JSVALUE64) loadPtr(BaseIndex(regT2, regT0, TimesEight), regT2); -#else - loadPtr(BaseIndex(regT2, regT0, TimesFour), regT2); -#endif emitPutVirtualRegister(dst, regT2); @@ -1185,16 +1211,14 @@ void JIT::emit_op_enter(Instruction*) } -void JIT::emit_op_enter_with_activation(Instruction* currentInstruction) +void JIT::emit_op_create_activation(Instruction* currentInstruction) { - // Even though CTI doesn't use them, we initialize our constant - // registers to zap stale pointers, to avoid unnecessarily prolonging - // object lifetime and increasing GC pressure. - size_t count = m_codeBlock->m_numVars; - for (size_t j = 0; j < count; ++j) - emitInitRegister(j); - + unsigned dst = currentInstruction[1].u.operand; + + Jump activationCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * dst)); JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand); + emitPutVirtualRegister(dst); + activationCreated.link(this); } void JIT::emit_op_create_arguments(Instruction* currentInstruction) @@ -1227,6 +1251,23 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction) addSlowCase(branchTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); } +void JIT::emit_op_convert_this_strict(Instruction* currentInstruction) +{ + emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); + Jump notNull = branchTestPtr(NonZero, regT0); + move(ImmPtr(JSValue::encode(jsNull())), regT0); + emitPutVirtualRegister(currentInstruction[1].u.operand, regT0); + Jump setThis = jump(); + notNull.link(this); + Jump isImmediate = emitJumpIfNotJSCell(regT0); + loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1); + Jump notAnObject = branch8(NotEqual, Address(regT3, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)); + addSlowCase(branchTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); + isImmediate.link(this); + notAnObject.link(this); + setThis.link(this); +} + void JIT::emit_op_get_callee(Instruction* currentInstruction) { unsigned result = currentInstruction[1].u.operand; @@ -1276,6 +1317,14 @@ void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowC stubCall.call(currentInstruction[1].u.operand); } +void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + linkSlowCase(iter); + JITStubCall stubCall(this, cti_op_convert_this_strict); + stubCall.addArgument(regT0); + stubCall.call(currentInstruction[1].u.operand); +} + void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { linkSlowCase(iter); @@ -1552,13 +1601,25 @@ void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vecto stubCall.call(dst); } -#endif // !USE(JSVALUE32_64) +#endif // USE(JSVALUE64) void JIT::emit_op_resolve_global_dynamic(Instruction* currentInstruction) { int skip = currentInstruction[5].u.operand; emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0); + + bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + Jump activationNotCreated; + if (checkTopLevel) + activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister())); + loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1); + addSlowCase(checkStructure(regT1, m_globalData->activationStructure.get())); + loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0); + activationNotCreated.link(this); + } while (skip--) { loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1); addSlowCase(checkStructure(regT1, m_globalData->activationStructure.get())); diff --git a/JavaScriptCore/jit/JITOpcodes32_64.cpp b/JavaScriptCore/jit/JITOpcodes32_64.cpp index ad3b558..c3b7ac2 100644 --- a/JavaScriptCore/jit/JITOpcodes32_64.cpp +++ b/JavaScriptCore/jit/JITOpcodes32_64.cpp @@ -610,6 +610,15 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction) int skip = currentInstruction[3].u.operand; emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2); + bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + Jump activationNotCreated; + if (checkTopLevel) + activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag)); + loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); + activationNotCreated.link(this); + } while (skip--) loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); @@ -631,6 +640,15 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction) emitLoad(value, regT1, regT0); emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2); + bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + Jump activationNotCreated; + if (checkTopLevel) + activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag)); + loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); + activationNotCreated.link(this); + } while (skip--) loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); @@ -644,10 +662,16 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction) void JIT::emit_op_tear_off_activation(Instruction* currentInstruction) { + unsigned activation = currentInstruction[1].u.operand; + unsigned arguments = currentInstruction[2].u.operand; + Jump activationCreated = branch32(NotEqual, tagFor(activation), Imm32(JSValue::EmptyValueTag)); + Jump argumentsNotCreated = branch32(Equal, tagFor(arguments), Imm32(JSValue::EmptyValueTag)); + activationCreated.link(this); JITStubCall stubCall(this, cti_op_tear_off_activation); stubCall.addArgument(currentInstruction[1].u.operand); stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand)); stubCall.call(); + argumentsNotCreated.link(this); } void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction) @@ -713,7 +737,15 @@ void JIT::emit_op_strcat(Instruction* currentInstruction) void JIT::emit_op_resolve_base(Instruction* currentInstruction) { - JITStubCall stubCall(this, cti_op_resolve_base); + JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base); + stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.call(currentInstruction[1].u.operand); +} + +void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction) +{ + JITStubCall stubCall(this, cti_op_ensure_property_exists); + stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -1215,7 +1247,7 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction) emitLoad(base, regT1, regT0); if (!m_codeBlock->isKnownNotImmediate(base)) isNotObject.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); - if (base != m_codeBlock->thisRegister()) { + if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) { loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); isNotObject.append(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); } @@ -1467,11 +1499,13 @@ void JIT::emit_op_enter(Instruction*) emitStore(i, jsUndefined()); } -void JIT::emit_op_enter_with_activation(Instruction* currentInstruction) +void JIT::emit_op_create_activation(Instruction* currentInstruction) { - emit_op_enter(currentInstruction); - - JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand); + unsigned activation = currentInstruction[1].u.operand; + + Jump activationCreated = branch32(NotEqual, tagFor(activation), Imm32(JSValue::EmptyValueTag)); + JITStubCall(this, cti_op_push_activation).call(activation); + activationCreated.link(this); } void JIT::emit_op_create_arguments(Instruction* currentInstruction) @@ -1528,6 +1562,26 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction) map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0); } +void JIT::emit_op_convert_this_strict(Instruction* currentInstruction) +{ + unsigned thisRegister = currentInstruction[1].u.operand; + + emitLoad(thisRegister, regT1, regT0); + + Jump notNull = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag)); + emitStore(thisRegister, jsNull()); + Jump setThis = jump(); + notNull.link(this); + Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); + loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + Jump notAnObject = branch8(NotEqual, Address(regT3, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)); + addSlowCase(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); + isImmediate.link(this); + notAnObject.link(this); + setThis.link(this); + map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this_strict), thisRegister, regT1, regT0); +} + void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { unsigned thisRegister = currentInstruction[1].u.operand; @@ -1540,6 +1594,17 @@ void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowC stubCall.call(thisRegister); } +void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned thisRegister = currentInstruction[1].u.operand; + + linkSlowCase(iter); + + JITStubCall stubCall(this, cti_op_convert_this_strict); + stubCall.addArgument(regT1, regT0); + stubCall.call(thisRegister); +} + void JIT::emit_op_profile_will_call(Instruction* currentInstruction) { peek(regT2, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*)); diff --git a/JavaScriptCore/jit/JITPropertyAccess.cpp b/JavaScriptCore/jit/JITPropertyAccess.cpp index 7c129a5..2edc860 100644 --- a/JavaScriptCore/jit/JITPropertyAccess.cpp +++ b/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -26,7 +26,7 @@ #include "config.h" #if ENABLE(JIT) -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) #include "JIT.h" #include "CodeBlock.h" @@ -89,7 +89,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction) emitGetVirtualRegisters(base, regT0, property, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1); -#if USE(JSVALUE64) + // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter. // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if // number was signed since m_vectorLength is always less than intmax (since the total allocation @@ -97,9 +97,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction) // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign // extending since it makes it easier to re-tag the value in the slow case. zeroExtend32ToPtr(regT1, regT1); -#else - emitFastArithImmToInt(regT1); -#endif + emitJumpSlowCaseIfNotJSCell(regT0, base); addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr))); @@ -204,12 +202,8 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction) emitGetVirtualRegisters(base, regT0, property, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1); -#if USE(JSVALUE64) // See comment in op_get_by_val. zeroExtend32ToPtr(regT1, regT1); -#else - emitFastArithImmToInt(regT1); -#endif emitJumpSlowCaseIfNotJSCell(regT0, base); addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr))); addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength)))); @@ -1103,5 +1097,5 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str } // namespace JSC -#endif // !USE(JSVALUE32_64) +#endif // USE(JSVALUE64) #endif // ENABLE(JIT) diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp index f1ec079..8340211 100644 --- a/JavaScriptCore/jit/JITStubs.cpp +++ b/JavaScriptCore/jit/JITStubs.cpp @@ -1065,7 +1065,9 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD return 0; \ } while (0) #define VM_THROW_EXCEPTION_AT_END() \ - returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS) + do {\ + returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\ + } while (0) #define CHECK_FOR_EXCEPTION() \ do { \ @@ -1301,6 +1303,18 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this) return JSValue::encode(result); } +DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this_strict) +{ + STUB_INIT_STACK_FRAME(stackFrame); + + JSValue v1 = stackFrame.args[0].jsValue(); + CallFrame* callFrame = stackFrame.callFrame; + + JSValue result = v1.toStrictThisObject(callFrame); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValue::encode(result); +} + DEFINE_STUB_FUNCTION(void, op_end) { STUB_INIT_STACK_FRAME(stackFrame); @@ -1404,7 +1418,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_generic) { STUB_INIT_STACK_FRAME(stackFrame); - PutPropertySlot slot; + PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode()); stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot); CHECK_FOR_EXCEPTION_AT_END(); } @@ -1413,7 +1427,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic) { STUB_INIT_STACK_FRAME(stackFrame); - PutPropertySlot slot; + PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode()); stackFrame.args[0].jsValue().putDirect(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot); CHECK_FOR_EXCEPTION_AT_END(); } @@ -1441,7 +1455,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id) CallFrame* callFrame = stackFrame.callFrame; Identifier& ident = stackFrame.args[1].identifier(); - PutPropertySlot slot; + PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot); CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); @@ -1460,7 +1474,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct) CallFrame* callFrame = stackFrame.callFrame; Identifier& ident = stackFrame.args[1].identifier(); - PutPropertySlot slot; + PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot); CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); @@ -1479,8 +1493,8 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_fail) CallFrame* callFrame = stackFrame.callFrame; Identifier& ident = stackFrame.args[1].identifier(); - - PutPropertySlot slot; + + PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot); CHECK_FOR_EXCEPTION_AT_END(); @@ -1493,7 +1507,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail) CallFrame* callFrame = stackFrame.callFrame; Identifier& ident = stackFrame.args[1].identifier(); - PutPropertySlot slot; + PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot); CHECK_FOR_EXCEPTION_AT_END(); @@ -1880,7 +1894,11 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id) JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame); - JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier())); + bool couldDelete = baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier()); + JSValue result = jsBoolean(couldDelete); + if (!couldDelete && callFrame->codeBlock()->isStrictMode()) + stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property."); + CHECK_FOR_EXCEPTION_AT_END(); return JSValue::encode(result); } @@ -1906,7 +1924,8 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul) DEFINE_STUB_FUNCTION(JSObject*, op_new_func) { STUB_INIT_STACK_FRAME(stackFrame); - + + ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->r(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue()); return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain()); } @@ -2213,10 +2232,18 @@ DEFINE_STUB_FUNCTION(void, op_tear_off_activation) STUB_INIT_STACK_FRAME(stackFrame); ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain()); + JSValue activationValue = stackFrame.args[0].jsValue(); + if (!activationValue) { + if (JSValue v = stackFrame.args[1].jsValue()) + asArguments(v)->copyRegisters(); + return; + } JSActivation* activation = asActivation(stackFrame.args[0].jsValue()); activation->copyRegisters(); - if (JSValue v = stackFrame.args[1].jsValue()) - asArguments(v)->setActivation(activation); + if (JSValue v = stackFrame.args[1].jsValue()) { + if (!stackFrame.callFrame->codeBlock()->isStrictMode()) + asArguments(v)->setActivation(activation); + } } DEFINE_STUB_FUNCTION(void, op_tear_off_arguments) @@ -2496,7 +2523,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val) } else { Identifier property(callFrame, subscript.toString(callFrame)); if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception. - PutPropertySlot slot; + PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); baseValue.put(callFrame, property, value, slot); } } @@ -2539,7 +2566,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array) } else { Identifier property(callFrame, subscript.toString(callFrame)); if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception. - PutPropertySlot slot; + PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); baseValue.put(callFrame, property, value, slot); } } @@ -2670,9 +2697,35 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base) { STUB_INIT_STACK_FRAME(stackFrame); - return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain())); + return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain(), false)); } +DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base_strict_put) +{ + STUB_INIT_STACK_FRAME(stackFrame); + JSValue base = JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain(), true); + if (!base) { + stackFrame.globalData->exception = createErrorForInvalidGlobalAssignment(stackFrame.callFrame, stackFrame.args[0].identifier().ustring()); + VM_THROW_EXCEPTION(); + } + return JSValue::encode(base); +} + +DEFINE_STUB_FUNCTION(EncodedJSValue, op_ensure_property_exists) +{ + STUB_INIT_STACK_FRAME(stackFrame); + JSValue base = stackFrame.callFrame->r(stackFrame.args[0].int32()).jsValue(); + JSObject* object = asObject(base); + PropertySlot slot(object); + ASSERT(stackFrame.callFrame->codeBlock()->isStrictMode()); + if (!object->getPropertySlot(stackFrame.callFrame, stackFrame.args[1].identifier(), slot)) { + stackFrame.globalData->exception = createErrorForInvalidGlobalAssignment(stackFrame.callFrame, stackFrame.args[1].identifier().ustring()); + VM_THROW_EXCEPTION(); + } + + return JSValue::encode(base); +} + DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip) { STUB_INIT_STACK_FRAME(stackFrame); @@ -2685,6 +2738,13 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip) ScopeChainIterator iter = scopeChain->begin(); ScopeChainIterator end = scopeChain->end(); ASSERT(iter != end); + CodeBlock* codeBlock = callFrame->codeBlock(); + bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + if (callFrame->r(codeBlock->activationRegister()).jsValue()) + ++iter; + } while (skip--) { ++iter; ASSERT(iter != end); @@ -2700,7 +2760,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip) } } while (++iter != end); - CodeBlock* codeBlock = callFrame->codeBlock(); unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS); stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); VM_THROW_EXCEPTION(); @@ -3049,6 +3108,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp) FunctionExecutable* function = stackFrame.args[0].function(); JSFunction* func = function->make(callFrame, callFrame->scopeChain()); + ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->r(callFrame->codeBlock()->activationRegister()).jsValue()); /* The Identifier in a FunctionExpression can be referenced from inside @@ -3155,6 +3215,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor) DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval) { STUB_INIT_STACK_FRAME(stackFrame); + ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->r(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue()); CallFrame* callFrame = stackFrame.callFrame; RegisterFile* registerFile = stackFrame.registerFile; @@ -3486,19 +3547,22 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val) JSObject* baseObj = baseValue.toObject(callFrame); // may throw JSValue subscript = stackFrame.args[1].jsValue(); - JSValue result; + bool result; uint32_t i; if (subscript.getUInt32(i)) - result = jsBoolean(baseObj->deleteProperty(callFrame, i)); + result = baseObj->deleteProperty(callFrame, i); else { CHECK_FOR_EXCEPTION(); Identifier property(callFrame, subscript.toString(callFrame)); CHECK_FOR_EXCEPTION(); - result = jsBoolean(baseObj->deleteProperty(callFrame, property)); + result = baseObj->deleteProperty(callFrame, property); } + if (!result && callFrame->codeBlock()->isStrictMode()) + stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property."); + CHECK_FOR_EXCEPTION_AT_END(); - return JSValue::encode(result); + return JSValue::encode(jsBoolean(result)); } DEFINE_STUB_FUNCTION(void, op_put_getter) diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h index 2b22e6d..b91a074 100644 --- a/JavaScriptCore/jit/JITStubs.h +++ b/JavaScriptCore/jit/JITStubs.h @@ -147,7 +147,7 @@ namespace JSC { struct JITStackFrame { JITStubArg reserved; // Unused JITStubArg args[6]; -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) void* padding; // Maintain 16-byte stack alignment. #endif @@ -296,6 +296,7 @@ extern "C" { EncodedJSValue JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_create_this(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_convert_this_strict(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_del_by_id(STUB_ARGS_DECLARATION); @@ -337,6 +338,8 @@ extern "C" { EncodedJSValue JIT_STUB cti_op_pre_inc(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_resolve(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_resolve_base(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_resolve_base_strict_put(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_ensure_property_exists(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_resolve_global(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_resolve_global_dynamic(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_resolve_skip(STUB_ARGS_DECLARATION); diff --git a/JavaScriptCore/jit/JSInterfaceJIT.h b/JavaScriptCore/jit/JSInterfaceJIT.h index 031bfa8..6453bab 100644 --- a/JavaScriptCore/jit/JSInterfaceJIT.h +++ b/JavaScriptCore/jit/JSInterfaceJIT.h @@ -166,7 +166,7 @@ namespace JSC { inline Address tagFor(unsigned index, RegisterID base = callFrameRegister); #endif -#if USE(JSVALUE32) || USE(JSVALUE64) +#if USE(JSVALUE64) Jump emitJumpIfImmediateNumber(RegisterID reg); Jump emitJumpIfNotImmediateNumber(RegisterID reg); void emitFastArithImmToInt(RegisterID reg); @@ -273,35 +273,7 @@ namespace JSC { #endif -#if USE(JSVALUE32) - inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID dst) - { - loadPtr(addressFor(virtualRegisterIndex), dst); - return branchTest32(NonZero, dst, Imm32(JSImmediate::TagMask)); - } - - inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst) - { - loadPtr(addressFor(virtualRegisterIndex), dst); - Jump result = branchTest32(Zero, dst, Imm32(JSImmediate::TagTypeNumber)); - rshift32(Imm32(JSImmediate::IntegerPayloadShift), dst); - return result; - } - - inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned, FPRegisterID, RegisterID) - { - ASSERT_NOT_REACHED(); - return jump(); - } - - ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID reg) - { - rshift32(Imm32(JSImmediate::IntegerPayloadShift), reg); - } - -#endif - -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(unsigned virtualRegisterIndex, RegisterID base) { ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex); diff --git a/JavaScriptCore/jit/SpecializedThunkJIT.h b/JavaScriptCore/jit/SpecializedThunkJIT.h index 57515fb..5c593d9 100644 --- a/JavaScriptCore/jit/SpecializedThunkJIT.h +++ b/JavaScriptCore/jit/SpecializedThunkJIT.h @@ -96,14 +96,10 @@ namespace JSC { #if USE(JSVALUE64) moveDoubleToPtr(src, regT0); subPtr(tagTypeNumberRegister, regT0); -#elif USE(JSVALUE32_64) +#else storeDouble(src, Address(stackPointerRegister, -(int)sizeof(double))); loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - sizeof(double)), regT1); loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - sizeof(double)), regT0); -#else - UNUSED_PARAM(src); - ASSERT_NOT_REACHED(); - m_failures.append(jump()); #endif loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister); ret(); @@ -144,13 +140,8 @@ namespace JSC { { #if USE(JSVALUE64) orPtr(tagTypeNumberRegister, regT0); -#elif USE(JSVALUE32_64) - move(Imm32(JSValue::Int32Tag), regT1); #else - signExtend32ToPtr(regT0, regT0); - // If we can't tag the result, give up and jump to the slow case - m_failures.append(branchAddPtr(Overflow, regT0, regT0)); - addPtr(Imm32(JSImmediate::TagTypeNumber), regT0); + move(Imm32(JSValue::Int32Tag), regT1); #endif } diff --git a/JavaScriptCore/jit/ThunkGenerators.cpp b/JavaScriptCore/jit/ThunkGenerators.cpp index 4c7a354..9b40f12 100644 --- a/JavaScriptCore/jit/ThunkGenerators.cpp +++ b/JavaScriptCore/jit/ThunkGenerators.cpp @@ -92,7 +92,6 @@ MacroAssemblerCodePtr fromCharCodeThunkGenerator(JSGlobalData* globalData, Execu MacroAssemblerCodePtr sqrtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) { -#if USE(JSVALUE64) || USE(JSVALUE32_64) SpecializedThunkJIT jit(1, globalData, pool); if (!jit.supportsFloatingPointSqrt()) return globalData->jitStubs->ctiNativeCall(); @@ -101,10 +100,6 @@ MacroAssemblerCodePtr sqrtThunkGenerator(JSGlobalData* globalData, ExecutablePoo jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0); jit.returnDouble(SpecializedThunkJIT::fpRegT0); return jit.finalize(globalData->jitStubs->ctiNativeCall()); -#else - UNUSED_PARAM(pool); - return globalData->jitStubs->ctiNativeCall(); -#endif } static const double oneConstant = 1.0; @@ -112,7 +107,6 @@ static const double negativeHalfConstant = -0.5; MacroAssemblerCodePtr powThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) { -#if USE(JSVALUE64) || USE(JSVALUE32_64) SpecializedThunkJIT jit(2, globalData, pool); if (!jit.supportsFloatingPoint()) return globalData->jitStubs->ctiNativeCall(); @@ -161,10 +155,6 @@ MacroAssemblerCodePtr powThunkGenerator(JSGlobalData* globalData, ExecutablePool jit.appendFailure(nonIntExponent); return jit.finalize(globalData->jitStubs->ctiNativeCall()); -#else - UNUSED_PARAM(pool); - return globalData->jitStubs->ctiNativeCall(); -#endif } } diff --git a/JavaScriptCore/parser/ASTBuilder.h b/JavaScriptCore/parser/ASTBuilder.h index 40023f8..9a68144 100644 --- a/JavaScriptCore/parser/ASTBuilder.h +++ b/JavaScriptCore/parser/ASTBuilder.h @@ -249,10 +249,10 @@ public: return result; } - FunctionBodyNode* createFunctionBody() + FunctionBodyNode* createFunctionBody(bool inStrictContext) { usesClosures(); - return FunctionBodyNode::create(m_globalData); + return FunctionBodyNode::create(m_globalData, inStrictContext); } template <bool> PropertyNode* createGetterOrSetterProperty(PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) @@ -578,6 +578,9 @@ public: const Identifier& getName(Property property) { return property->name(); } PropertyNode::Type getType(Property property) { return property->type(); } + + bool isResolve(ExpressionNode* expr) { return expr->isResolveNode(); } + private: struct Scope { Scope(JSGlobalData* globalData) diff --git a/JavaScriptCore/parser/JSParser.cpp b/JavaScriptCore/parser/JSParser.cpp index 0e526ac..0338210 100644 --- a/JavaScriptCore/parser/JSParser.cpp +++ b/JavaScriptCore/parser/JSParser.cpp @@ -29,6 +29,7 @@ using namespace JSC; +#include "CodeBlock.h" #include "JSGlobalData.h" #include "NodeInfo.h" #include "ASTBuilder.h" @@ -42,6 +43,8 @@ namespace JSC { #define fail() do { m_error = true; return 0; } while (0) #define failIfFalse(cond) do { if (!(cond)) fail(); } while (0) #define failIfTrue(cond) do { if ((cond)) fail(); } while (0) +#define failIfTrueIfStrict(cond) do { if ((cond) && strictMode()) fail(); } while (0) +#define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0) #define consumeOrFail(tokenType) do { if (!consume(tokenType)) fail(); } while (0) #define matchOrFail(tokenType) do { if (!match(tokenType)) fail(); } while (0) #define failIfStackOverflow() do { failIfFalse(canRecurse()); } while (0) @@ -67,8 +70,8 @@ static const ptrdiff_t kMaxParserStackUsage = 128 * sizeof(void*) * 1024; class JSParser { public: - JSParser(Lexer*, JSGlobalData*, FunctionParameters*, SourceProvider*); - bool parseProgram(); + JSParser(Lexer*, JSGlobalData*, FunctionParameters*, bool isStrictContext, bool isFunction, SourceProvider*); + bool parseProgram(JSGlobalObject*); private: struct AllowInOverride { AllowInOverride(JSParser* parser) @@ -90,7 +93,7 @@ private: m_lastLine = m_token.m_info.line; m_lastTokenEnd = m_token.m_info.endOffset; m_lexer->setLastLineNumber(m_lastLine); - m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info, lexType); + m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info, lexType, strictMode()); m_tokenCount++; } @@ -121,9 +124,23 @@ private: { return m_token.m_info.endOffset; } - - template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&); - template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&); + + void startLoop() { currentScope()->startLoop(); } + void endLoop() { currentScope()->endLoop(); } + void startSwitch() { currentScope()->startSwitch(); } + void endSwitch() { currentScope()->endSwitch(); } + void setStrictMode() { currentScope()->setStrictMode(); } + bool strictMode() { return currentScope()->strictMode(); } + bool isValidStrictMode() { return currentScope()->isValidStrictMode(); } + bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } + bool breakIsValid() { return currentScope()->breakIsValid(); } + void pushLabel(const Identifier* label) { currentScope()->pushLabel(label); } + void popLabel() { currentScope()->popLabel(); } + bool hasLabel(const Identifier* label) { return currentScope()->hasLabel(label); } + + enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode }; + template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&); + template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive); template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&); template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&); template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&); @@ -199,32 +216,118 @@ private: int m_assignmentCount; int m_nonLHSCount; bool m_syntaxAlreadyValidated; + int m_statementDepth; + int m_nonTrivialExpressionCount; + const Identifier* m_lastIdentifier; + + struct DepthManager { + DepthManager(int* depth) + : m_originalDepth(*depth) + , m_depth(depth) + { + } + + ~DepthManager() + { + *m_depth = m_originalDepth; + } + + private: + int m_originalDepth; + int* m_depth; + }; struct Scope { - Scope() - : m_usesEval(false) + Scope(JSGlobalData* globalData, bool isFunction, bool strictMode) + : m_globalData(globalData) + , m_usesEval(false) , m_needsFullActivation(false) , m_allowsNewDecls(true) + , m_strictMode(strictMode) + , m_isFunction(isFunction) + , m_isValidStrictMode(true) + , m_loopDepth(0) + , m_switchDepth(0) + , m_labels(0) + { + } + + void startSwitch() { m_switchDepth++; } + void endSwitch() { m_switchDepth--; } + void startLoop() { m_loopDepth++; } + void endLoop() { ASSERT(m_loopDepth); m_loopDepth--; } + bool inLoop() { return !!m_loopDepth; } + bool breakIsValid() { return m_loopDepth || m_switchDepth; } + + void pushLabel(const Identifier* label) + { + if (!m_labels) + m_labels = new LabelStack; + m_labels->append(label->impl()); + } + + void popLabel() { + ASSERT(m_labels); + ASSERT(m_labels->size()); + m_labels->removeLast(); } + + bool hasLabel(const Identifier* label) + { + if (!m_labels) + return false; + for (int i = m_labels->size(); i > 0; i--) { + if (m_labels->at(i - 1) == label->impl()) + return true; + } + return false; + } + + void setIsFunction() { m_isFunction = true; } + bool isFunction() { return m_isFunction; } - void declareVariable(const Identifier* ident) + bool declareVariable(const Identifier* ident) { + bool isValidStrictMode = m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident; + m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; m_declaredVariables.add(ident->ustring().impl()); + return isValidStrictMode; + } + + void declareWrite(const Identifier* ident) + { + ASSERT(m_strictMode); + m_writtenVariables.add(ident->impl()); + } + + bool deleteProperty(const Identifier* ident) + { + if (m_declaredVariables.contains(ident->impl())) + return false; + m_deletedVariables.add(ident->impl()); + return true; } void preventNewDecls() { m_allowsNewDecls = false; } bool allowsNewDecls() const { return m_allowsNewDecls; } + bool declareParameter(const Identifier* ident) + { + bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).second && m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident; + m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; + return isValidStrictMode; + } + void useVariable(const Identifier* ident, bool isEval) { m_usesEval |= isEval; m_usedVariables.add(ident->ustring().impl()); } - void needsFullActivation() { m_needsFullActivation = true; } + void setNeedsFullActivation() { m_needsFullActivation = true; } - void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) + bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) { if (nestedScope->m_usesEval) m_usesEval = true; @@ -236,6 +339,45 @@ private: if (shouldTrackClosedVariables) m_closedVariables.add(*ptr); } + if (nestedScope->m_writtenVariables.size()) { + IdentifierSet::iterator end = nestedScope->m_writtenVariables.end(); + for (IdentifierSet::iterator ptr = nestedScope->m_writtenVariables.begin(); ptr != end; ++ptr) { + if (nestedScope->m_declaredVariables.contains(*ptr)) + continue; + m_writtenVariables.add(*ptr); + } + } + if (nestedScope->m_deletedVariables.size()) { + IdentifierSet::iterator end = nestedScope->m_deletedVariables.end(); + for (IdentifierSet::iterator ptr = nestedScope->m_deletedVariables.begin(); ptr != end; ++ptr) { + if (nestedScope->m_declaredVariables.contains(*ptr)) + return false; + if (m_declaredVariables.contains(*ptr)) + return false; + m_deletedVariables.add(*ptr); + } + } + return true; + } + + void getUncapturedWrittenVariables(IdentifierSet& writtenVariables) + { + IdentifierSet::iterator end = m_writtenVariables.end(); + for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) { + if (!m_declaredVariables.contains(*ptr)) + writtenVariables.add(*ptr); + } + } + + bool getDeletedVariables(IdentifierSet& deletedVariables) + { + IdentifierSet::iterator end = m_deletedVariables.end(); + for (IdentifierSet::iterator ptr = m_deletedVariables.begin(); ptr != end; ++ptr) { + if (m_declaredVariables.contains(*ptr)) + return false; + } + deletedVariables.swap(m_deletedVariables); + return true; } void getCapturedVariables(IdentifierSet& capturedVariables) @@ -250,13 +392,27 @@ private: capturedVariables.add(*ptr); } } + void setStrictMode() { m_strictMode = true; } + bool strictMode() const { return m_strictMode; } + bool isValidStrictMode() const { return m_isValidStrictMode; } + private: - bool m_usesEval; - bool m_needsFullActivation; - bool m_allowsNewDecls; + JSGlobalData* m_globalData; + bool m_usesEval : 1; + bool m_needsFullActivation : 1; + bool m_allowsNewDecls : 1; + bool m_strictMode : 1; + bool m_isFunction : 1; + bool m_isValidStrictMode : 1; + int m_loopDepth; + int m_switchDepth; + typedef Vector<StringImpl*, 2> LabelStack; + LabelStack* m_labels; IdentifierSet m_declaredVariables; IdentifierSet m_usedVariables; IdentifierSet m_closedVariables; + IdentifierSet m_writtenVariables; + IdentifierSet m_deletedVariables; }; typedef Vector<Scope, 10> ScopeStack; @@ -281,19 +437,26 @@ private: ScopeRef pushScope() { - m_scopeStack.append(Scope()); + bool isFunction = false; + bool isStrict = false; + if (!m_scopeStack.isEmpty()) { + isStrict = m_scopeStack.last().strictMode(); + isFunction = m_scopeStack.last().isFunction(); + } + m_scopeStack.append(Scope(m_globalData, isFunction, isStrict)); return currentScope(); } - void popScope(ScopeRef scope, bool shouldTrackClosedVariables) + bool popScope(ScopeRef scope, bool shouldTrackClosedVariables) { ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1); ASSERT(m_scopeStack.size() > 1); - m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables); + bool result = m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables); m_scopeStack.removeLast(); + return result; } - void declareVariable(const Identifier* ident) + bool declareVariable(const Identifier* ident) { unsigned i = m_scopeStack.size() - 1; ASSERT(i < m_scopeStack.size()); @@ -301,19 +464,32 @@ private: i--; ASSERT(i < m_scopeStack.size()); } - m_scopeStack[i].declareVariable(ident); + return m_scopeStack[i].declareVariable(ident); + } + + void declareWrite(const Identifier* ident) + { + if (!m_syntaxAlreadyValidated) + m_scopeStack.last().declareWrite(ident); } + bool deleteProperty(const Identifier* ident) + { + if (!m_syntaxAlreadyValidated) + return m_scopeStack.last().deleteProperty(ident); + return true; + } + ScopeStack m_scopeStack; }; -int jsParse(JSGlobalData* globalData, FunctionParameters* parameters, const SourceCode* source) +int jsParse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source) { - JSParser parser(globalData->lexer, globalData, parameters, source->provider()); - return parser.parseProgram(); + JSParser parser(lexicalGlobalObject->globalData()->lexer, lexicalGlobalObject->globalData(), parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source->provider()); + return parser.parseProgram(lexicalGlobalObject); } -JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, SourceProvider* provider) +JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, bool inStrictContext, bool isFunction, SourceProvider* provider) : m_lexer(lexer) , m_endAddress(0) , m_error(false) @@ -325,28 +501,48 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* p , m_assignmentCount(0) , m_nonLHSCount(0) , m_syntaxAlreadyValidated(provider->isValid()) + , m_statementDepth(0) + , m_nonTrivialExpressionCount(0) + , m_lastIdentifier(0) { m_endAddress = wtfThreadData().approximatedStackStart() - kMaxParserStackUsage; - next(); - m_lexer->setLastLineNumber(tokenLine()); ScopeRef scope = pushScope(); + if (isFunction) + scope->setIsFunction(); + if (inStrictContext) + scope->setStrictMode(); if (parameters) { for (unsigned i = 0; i < parameters->size(); i++) - scope->declareVariable(¶meters->at(i)); + scope->declareParameter(¶meters->at(i)); } + next(); + m_lexer->setLastLineNumber(tokenLine()); } -bool JSParser::parseProgram() +bool JSParser::parseProgram(JSGlobalObject* lexicalGlobalObject) { ASTBuilder context(m_globalData, m_lexer); + if (m_lexer->isReparsing()) + m_statementDepth--; ScopeRef scope = currentScope(); - SourceElements* sourceElements = parseSourceElements<ASTBuilder>(context); + SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context); if (!sourceElements || !consume(EOFTOK)) return true; + if (!m_syntaxAlreadyValidated) { + IdentifierSet deletedVariables; + if (!scope->getDeletedVariables(deletedVariables)) + return true; + IdentifierSet::const_iterator end = deletedVariables.end(); + SymbolTable& globalEnvRecord = lexicalGlobalObject->symbolTable(); + for (IdentifierSet::const_iterator ptr = deletedVariables.begin(); ptr != end; ++ptr) { + if (!globalEnvRecord.get(*ptr).isNull()) + return true; + } + } IdentifierSet capturedVariables; scope->getCapturedVariables(capturedVariables); - m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features(), - m_lastLine, context.numConstants(), capturedVariables); + m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features() | (scope->strictMode() ? StrictModeFeature : 0), + m_lastLine, context.numConstants(), capturedVariables); return false; } @@ -355,11 +551,30 @@ bool JSParser::allowAutomaticSemicolon() return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator(); } -template <class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context) +template <JSParser::SourceElementsMode mode, class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context) { TreeSourceElements sourceElements = context.createSourceElements(); - while (TreeStatement statement = parseStatement(context)) + bool seenNonDirective = false; + const Identifier* directive = 0; + unsigned startOffset = m_token.m_info.startOffset; + bool hasSetStrict = false; + while (TreeStatement statement = parseStatement(context, directive)) { + if (mode == CheckForStrictMode && !seenNonDirective) { + if (directive) { + if (!hasSetStrict && m_globalData->propertyNames->useStrictIdentifier == *directive) { + setStrictMode(); + hasSetStrict = true; + failIfFalse(isValidStrictMode()); + m_lexer->setOffset(startOffset); + next(); + failIfTrue(m_error); + continue; + } + } else + seenNonDirective = true; + } context.appendStatement(sourceElements, statement); + } if (m_error) fail(); @@ -399,7 +614,10 @@ template <class TreeBuilder> TreeStatement JSParser::parseDoWhileStatement(TreeB ASSERT(match(DO)); int startLine = tokenLine(); next(); - TreeStatement statement = parseStatement(context); + const Identifier* unused = 0; + startLoop(); + TreeStatement statement = parseStatement(context, unused); + endLoop(); failIfFalse(statement); int endLine = tokenLine(); consumeOrFail(WHILE); @@ -422,7 +640,10 @@ template <class TreeBuilder> TreeStatement JSParser::parseWhileStatement(TreeBui failIfFalse(expr); int endLine = tokenLine(); consumeOrFail(CLOSEPAREN); - TreeStatement statement = parseStatement(context); + const Identifier* unused = 0; + startLoop(); + TreeStatement statement = parseStatement(context, unused); + endLoop(); failIfFalse(statement); return context.createWhileStatement(expr, statement, startLine, endLine); } @@ -441,7 +662,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(Tr lastIdent = name; next(); bool hasInitializer = match(EQUAL); - declareVariable(name); + failIfFalseIfStrict(declareVariable(name)); context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0); if (hasInitializer) { int varDivot = tokenStart() + 1; @@ -465,6 +686,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(Tr template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationList(TreeBuilder& context) { + failIfTrue(strictMode()); TreeConstDeclList constDecls = 0; TreeConstDeclList tail = 0; do { @@ -532,7 +754,10 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild int endLine = tokenLine(); consumeOrFail(CLOSEPAREN); - TreeStatement statement = parseStatement(context); + const Identifier* unused = 0; + startLoop(); + TreeStatement statement = parseStatement(context, unused); + endLoop(); failIfFalse(statement); return context.createForInLoop(forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine); @@ -566,7 +791,10 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild } int endLine = tokenLine(); consumeOrFail(CLOSEPAREN); - TreeStatement statement = parseStatement(context); + const Identifier* unused = 0; + startLoop(); + TreeStatement statement = parseStatement(context, unused); + endLoop(); failIfFalse(statement); return context.createForLoop(decls, condition, increment, statement, hasDeclaration, startLine, endLine); } @@ -579,7 +807,10 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild int exprEnd = lastTokenEnd(); int endLine = tokenLine(); consumeOrFail(CLOSEPAREN); - TreeStatement statement = parseStatement(context); + const Identifier* unused = 0; + startLoop(); + TreeStatement statement = parseStatement(context, unused); + endLoop(); failIfFalse(statement); return context.createForInLoop(decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine); @@ -594,10 +825,13 @@ template <class TreeBuilder> TreeStatement JSParser::parseBreakStatement(TreeBui int endLine = tokenLine(); next(); - if (autoSemiColon()) + if (autoSemiColon()) { + failIfFalseIfStrict(breakIsValid()); return context.createBreakStatement(startCol, endCol, startLine, endLine); + } matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; + failIfFalseIfStrict(hasLabel(ident)); endCol = tokenEnd(); endLine = tokenLine(); next(); @@ -614,10 +848,13 @@ template <class TreeBuilder> TreeStatement JSParser::parseContinueStatement(Tree int endLine = tokenLine(); next(); - if (autoSemiColon()) + if (autoSemiColon()) { + failIfFalseIfStrict(breakIsValid()); return context.createContinueStatement(startCol, endCol, startLine, endLine); + } matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; + failIfFalseIfStrict(hasLabel(ident)); endCol = tokenEnd(); endLine = tokenLine(); next(); @@ -628,6 +865,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseContinueStatement(Tree template <class TreeBuilder> TreeStatement JSParser::parseReturnStatement(TreeBuilder& context) { ASSERT(match(RETURN)); + failIfFalseIfStrict(currentScope()->isFunction()); int startLine = tokenLine(); int endLine = startLine; int start = tokenStart(); @@ -655,6 +893,8 @@ template <class TreeBuilder> TreeStatement JSParser::parseThrowStatement(TreeBui int eStart = tokenStart(); int startLine = tokenLine(); next(); + + failIfTrue(autoSemiColon()); TreeExpression expr = parseExpression(context); failIfFalse(expr); @@ -668,7 +908,8 @@ template <class TreeBuilder> TreeStatement JSParser::parseThrowStatement(TreeBui template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuilder& context) { ASSERT(match(WITH)); - currentScope()->needsFullActivation(); + failIfTrue(strictMode()); + currentScope()->setNeedsFullActivation(); int startLine = tokenLine(); next(); consumeOrFail(OPENPAREN); @@ -679,8 +920,8 @@ template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuil int endLine = tokenLine(); consumeOrFail(CLOSEPAREN); - - TreeStatement statement = parseStatement(context); + const Identifier* unused = 0; + TreeStatement statement = parseStatement(context, unused); failIfFalse(statement); return context.createWithStatement(expr, statement, start, end, startLine, endLine); @@ -697,7 +938,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseSwitchStatement(TreeBu int endLine = tokenLine(); consumeOrFail(CLOSEPAREN); consumeOrFail(OPENBRACE); - + startSwitch(); TreeClauseList firstClauses = parseSwitchClauses(context); failIfTrue(m_error); @@ -706,6 +947,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseSwitchStatement(TreeBu TreeClauseList secondClauses = parseSwitchClauses(context); failIfTrue(m_error); + endSwitch(); consumeOrFail(CLOSEBRACE); return context.createSwitchStatement(expr, firstClauses, defaultClause, secondClauses, startLine, endLine); @@ -720,7 +962,7 @@ template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBui TreeExpression condition = parseExpression(context); failIfFalse(condition); consumeOrFail(COLON); - TreeSourceElements statements = parseSourceElements(context); + TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context); failIfFalse(statements); TreeClause clause = context.createClause(condition, statements); TreeClauseList clauseList = context.createClauseList(clause); @@ -731,7 +973,7 @@ template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBui TreeExpression condition = parseExpression(context); failIfFalse(condition); consumeOrFail(COLON); - TreeSourceElements statements = parseSourceElements(context); + TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context); failIfFalse(statements); clause = context.createClause(condition, statements); tail = context.createClauseList(tail, clause); @@ -745,7 +987,7 @@ template <class TreeBuilder> TreeClause JSParser::parseSwitchDefaultClause(TreeB return 0; next(); consumeOrFail(COLON); - TreeSourceElements statements = parseSourceElements(context); + TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context); failIfFalse(statements); return context.createClause(0, statements); } @@ -767,14 +1009,14 @@ template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuild int lastLine = m_lastLine; if (match(CATCH)) { - currentScope()->needsFullActivation(); + currentScope()->setNeedsFullActivation(); next(); consumeOrFail(OPENPAREN); matchOrFail(IDENT); ident = m_token.m_data.ident; next(); ScopeRef catchScope = pushScope(); - catchScope->declareVariable(ident); + failIfFalseIfStrict(catchScope->declareVariable(ident)); catchScope->preventNewDecls(); consumeOrFail(CLOSEPAREN); matchOrFail(OPENBRACE); @@ -782,7 +1024,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuild catchBlock = parseBlockStatement(context); failIfFalse(catchBlock); catchHasEval = initialEvalCount != context.evalCount(); - popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo); + failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo)); } if (match(FINALLY)) { @@ -816,15 +1058,19 @@ template <class TreeBuilder> TreeStatement JSParser::parseBlockStatement(TreeBui next(); return context.createBlockStatement(0, start, m_lastLine); } - TreeSourceElements subtree = parseSourceElements(context); + TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context); failIfFalse(subtree); matchOrFail(CLOSEBRACE); next(); return context.createBlockStatement(subtree, start, m_lastLine); } -template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& context) +template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& context, const Identifier*& directive) { + DepthManager statementDepth(&m_statementDepth); + m_statementDepth++; + directive = 0; + int nonTrivialExpressionCount = 0; failIfStackOverflow(); switch (m_token.m_type) { case OPENBRACE: @@ -834,6 +1080,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& case CONSTTOKEN: return parseConstDeclaration(context); case FUNCTION: + failIfFalseIfStrict(m_statementDepth == 1); return parseFunctionDeclaration(context); case SEMICOLON: next(); @@ -870,8 +1117,14 @@ template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& return 0; case IDENT: return parseExpressionOrLabelStatement(context); + case STRING: + directive = m_token.m_data.ident; + nonTrivialExpressionCount = m_nonTrivialExpressionCount; default: - return parseExpressionStatement(context); + TreeStatement exprStatement = parseExpressionStatement(context); + if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount) + directive = 0; + return exprStatement; } } @@ -879,7 +1132,7 @@ template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParame { matchOrFail(IDENT); usesArguments = m_globalData->propertyNames->arguments == *m_token.m_data.ident; - declareVariable(m_token.m_data.ident); + failIfFalseIfStrict(declareParameter(m_token.m_data.ident)); TreeFormalParameterList list = context.createFormalParameterList(*m_token.m_data.ident); TreeFormalParameterList tail = list; next(); @@ -887,7 +1140,8 @@ template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParame next(); matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; - declareVariable(ident); + usesArguments |= m_globalData->propertyNames->arguments == *m_token.m_data.ident; + failIfFalseIfStrict(declareParameter(ident)); next(); usesArguments = usesArguments || m_globalData->propertyNames->arguments == *ident; tail = context.createFormalParameterList(tail, *ident); @@ -898,20 +1152,23 @@ template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParame template <class TreeBuilder> TreeFunctionBody JSParser::parseFunctionBody(TreeBuilder& context) { if (match(CLOSEBRACE)) - return context.createFunctionBody(); + return context.createFunctionBody(strictMode()); + DepthManager statementDepth(&m_statementDepth); + m_statementDepth = 0; typename TreeBuilder::FunctionBodyBuilder bodyBuilder(m_globalData, m_lexer); - failIfFalse(parseSourceElements(bodyBuilder)); - return context.createFunctionBody(); + failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder)); + return context.createFunctionBody(strictMode()); } template <JSParser::FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine) { ScopeRef functionScope = pushScope(); + functionScope->setIsFunction(); if (match(IDENT)) { name = m_token.m_data.ident; next(); if (!nameIsInContainingScope) - functionScope->declareVariable(name); + failIfFalseIfStrict(functionScope->declareVariable(name)); } else if (requirements == FunctionNeedsName) return false; consumeOrFail(OPENPAREN); @@ -931,7 +1188,11 @@ template <JSParser::FunctionRequirements requirements, bool nameIsInContainingSc failIfFalse(body); if (usesArguments) context.setUsesArguments(body); - popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo); + if (functionScope->strictMode() && name) { + failIfTrue(m_globalData->propertyNames->arguments == *name); + failIfTrue(m_globalData->propertyNames->eval == *name); + } + failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); matchOrFail(CLOSEBRACE); closeBracePos = m_token.m_data.intValue; next(); @@ -950,7 +1211,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseFunctionDeclaration(Tr int bodyStartLine = 0; failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); failIfFalse(name); - declareVariable(name); + failIfFalseIfStrict(declareVariable(name)); return context.createFuncDeclStatement(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } @@ -973,7 +1234,12 @@ template <class TreeBuilder> TreeStatement JSParser::parseExpressionOrLabelState failIfFalse(currentToken + 1 == m_tokenCount); int end = tokenEnd(); consumeOrFail(COLON); - TreeStatement statement = parseStatement(context); + const Identifier* unused = 0; + if (strictMode() && !m_syntaxAlreadyValidated) + pushLabel(ident); + TreeStatement statement = parseStatement(context, unused); + if (strictMode() && !m_syntaxAlreadyValidated) + popLabel(); failIfFalse(statement); return context.createLabelStatement(ident, statement, start, end); } @@ -1001,7 +1267,8 @@ template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilde int end = tokenLine(); consumeOrFail(CLOSEPAREN); - TreeStatement trueBlock = parseStatement(context); + const Identifier* unused = 0; + TreeStatement trueBlock = parseStatement(context, unused); failIfFalse(trueBlock); if (!match(ELSE)) @@ -1014,7 +1281,8 @@ template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilde do { next(); if (!match(IF)) { - TreeStatement block = parseStatement(context); + const Identifier* unused = 0; + TreeStatement block = parseStatement(context, unused); failIfFalse(block); statementStack.append(block); trailingElse = true; @@ -1029,8 +1297,8 @@ template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilde failIfFalse(innerCondition); int innerEnd = tokenLine(); consumeOrFail(CLOSEPAREN); - - TreeStatement innerTrueBlock = parseStatement(context); + const Identifier* unused = 0; + TreeStatement innerTrueBlock = parseStatement(context, unused); failIfFalse(innerTrueBlock); exprStack.append(innerCondition); posStack.append(make_pair(innerStart, innerEnd)); @@ -1070,6 +1338,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseExpression(TreeBuilde if (!match(COMMA)) return node; next(); + m_nonTrivialExpressionCount++; m_nonLHSCount++; TreeExpression right = parseAssignmentExpression(context); failIfFalse(right); @@ -1115,11 +1384,17 @@ template <typename TreeBuilder> TreeExpression JSParser::parseAssignmentExpressi default: goto end; } + m_nonTrivialExpressionCount++; hadAssignment = true; context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), m_assignmentCount, op); start = tokenStart(); m_assignmentCount++; next(); + if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) { + failIfTrueIfStrict(m_globalData->propertyNames->eval == *m_lastIdentifier); + declareWrite(m_lastIdentifier); + m_lastIdentifier = 0; + } lhs = parseConditionalExpression(context); failIfFalse(lhs); if (initialNonLHSCount != m_nonLHSCount) @@ -1144,6 +1419,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseConditionalExpression failIfFalse(cond); if (!match(QUESTION)) return cond; + m_nonTrivialExpressionCount++; m_nonLHSCount++; next(); TreeExpression lhs = parseAssignmentExpression(context); @@ -1181,6 +1457,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(Tree int precedence = isBinaryOperator(m_token.m_type); if (!precedence) break; + m_nonTrivialExpressionCount++; m_nonLHSCount++; int operatorToken = m_token.m_type; next(); @@ -1196,7 +1473,6 @@ template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(Tree } context.operatorStackAppend(operatorStackDepth, operatorToken, precedence); } - while (operatorStackDepth) { ASSERT(operandStackDepth > 1); @@ -1327,6 +1603,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseStrictObjectLiteral(T if (!m_syntaxAlreadyValidated) { std::pair<ObjectValidationMap::iterator, bool> propertyEntryIter = objectValidator.add(context.getName(property).impl(), context.getType(property)); if (!propertyEntryIter.second) { + failIfTrue(strictMode()); if ((context.getType(property) & propertyEntryIter.first->second) != PropertyNode::Constant) { // Can't have multiple getters or setters with the same name, nor can we define // a property as both an accessor and a constant value @@ -1389,6 +1666,8 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre { switch (m_token.m_type) { case OPENBRACE: + if (strictMode()) + return parseStrictObjectLiteral(context); return parseObjectLiteral(context); case OPENBRACKET: return parseArrayLiteral(context); @@ -1410,6 +1689,7 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre const Identifier* ident = m_token.m_data.ident; next(); currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident); + m_lastIdentifier = ident; return context.createResolve(ident, start); } case STRING: { @@ -1485,6 +1765,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree next(); newCount++; } + if (match(FUNCTION)) { const Identifier* name = &m_globalData->propertyNames->nullIdentifier; TreeFormalParameterList parameters = 0; @@ -1502,6 +1783,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree while (true) { switch (m_token.m_type) { case OPENBRACKET: { + m_nonTrivialExpressionCount++; int expressionEnd = lastTokenEnd(); next(); int nonLHSCount = m_nonLHSCount; @@ -1515,6 +1797,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree break; } case OPENPAREN: { + m_nonTrivialExpressionCount++; if (newCount) { newCount--; if (match(OPENPAREN)) { @@ -1535,6 +1818,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree break; } case DOT: { + m_nonTrivialExpressionCount++; int expressionEnd = lastTokenEnd(); next(Lexer::IgnoreReservedWords); matchOrFail(IDENT); @@ -1556,25 +1840,62 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB { AllowInOverride allowInOverride(this); int tokenStackDepth = 0; + bool modifiesExpr = false; + bool requiresLExpr = false; while (isUnaryOp(m_token.m_type)) { + if (strictMode()) { + switch (m_token.m_type) { + case PLUSPLUS: + case MINUSMINUS: + case AUTOPLUSPLUS: + case AUTOMINUSMINUS: + failIfTrue(requiresLExpr); + modifiesExpr = true; + requiresLExpr = true; + break; + case DELETETOKEN: + failIfTrue(requiresLExpr); + requiresLExpr = true; + break; + default: + failIfTrue(requiresLExpr); + break; + } + } m_nonLHSCount++; context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStart()); next(); + m_nonTrivialExpressionCount++; } int subExprStart = tokenStart(); TreeExpression expr = parseMemberExpression(context); failIfFalse(expr); + bool isEvalOrArguments = false; + if (strictMode() && !m_syntaxAlreadyValidated) { + if (context.isResolve(expr)) { + isEvalOrArguments = m_globalData->propertyNames->eval == *m_lastIdentifier; + if (!isEvalOrArguments && currentScope()->isFunction()) + isEvalOrArguments = m_globalData->propertyNames->arguments == *m_lastIdentifier; + } + } + failIfTrueIfStrict(isEvalOrArguments && modifiesExpr); switch (m_token.m_type) { case PLUSPLUS: + m_nonTrivialExpressionCount++; m_nonLHSCount++; expr = context.makePostfixNode(expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd()); m_assignmentCount++; + failIfTrueIfStrict(isEvalOrArguments); + failIfTrueIfStrict(requiresLExpr); next(); break; case MINUSMINUS: + m_nonTrivialExpressionCount++; m_nonLHSCount++; expr = context.makePostfixNode(expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd()); m_assignmentCount++; + failIfTrueIfStrict(isEvalOrArguments); + failIfTrueIfStrict(requiresLExpr); next(); break; default: @@ -1583,7 +1904,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB int end = lastTokenEnd(); - if (!TreeBuilder::CreatesAST) + if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode())) return expr; while (tokenStackDepth) { @@ -1617,6 +1938,8 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB expr = context.createVoid(expr); break; case DELETETOKEN: + if (strictMode() && context.isResolve(expr)) + failIfFalse(deleteProperty(m_lastIdentifier)); expr = context.makeDeleteNode(expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end); break; default: diff --git a/JavaScriptCore/parser/JSParser.h b/JavaScriptCore/parser/JSParser.h index ab18fab..64b18e7 100644 --- a/JavaScriptCore/parser/JSParser.h +++ b/JavaScriptCore/parser/JSParser.h @@ -28,9 +28,10 @@ namespace JSC { +class ExecState; class FunctionParameters; class Identifier; -class JSGlobalData; +class JSGlobalObject; class SourceCode; enum { @@ -155,6 +156,9 @@ struct JSToken { JSTokenInfo m_info; }; -int jsParse(JSGlobalData*, FunctionParameters*, const SourceCode*); +enum JSParserStrictness { JSParseNormal, JSParseStrict }; +enum JSParserMode { JSParseProgramCode, JSParseFunctionCode }; + +int jsParse(JSGlobalObject*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*); } #endif // JSParser_h diff --git a/JavaScriptCore/parser/Lexer.cpp b/JavaScriptCore/parser/Lexer.cpp index cc4321d..b443561 100644 --- a/JavaScriptCore/parser/Lexer.cpp +++ b/JavaScriptCore/parser/Lexer.cpp @@ -453,7 +453,7 @@ ALWAYS_INLINE JSTokenType Lexer::parseIdentifier(JSTokenData* lvalp, LexType lex return IDENT; } -ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp) +ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp, bool strictMode) { int stringQuoteCharacter = m_current; shift(); @@ -494,6 +494,8 @@ ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp) return false; } else if (isASCIIOctalDigit(m_current)) { // Octal character sequences + if (strictMode) + return false; int character1 = m_current; shift(); if (isASCIIOctalDigit(m_current)) { @@ -696,7 +698,7 @@ ALWAYS_INLINE bool Lexer::parseMultilineComment() } } -JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType lexType) +JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType lexType, bool strictMode) { ASSERT(!m_error); ASSERT(m_buffer8.isEmpty()); @@ -976,8 +978,11 @@ start: } else { record8('0'); if (isASCIIOctalDigit(m_current)) { - if (parseOctal(lvalp->doubleValue)) + if (parseOctal(lvalp->doubleValue)) { + if (strictMode) + goto returnError; token = NUMBER; + } } } // Fall through into CharacterNumber @@ -1006,7 +1011,7 @@ inNumberAfterDecimalPoint: m_delimited = false; break; case CharacterQuote: - if (UNLIKELY(!parseString(lvalp))) + if (UNLIKELY(!parseString(lvalp, strictMode))) goto returnError; shift(); m_delimited = false; @@ -1023,11 +1028,6 @@ inNumberAfterDecimalPoint: shiftLineTerminator(); m_atLineStart = true; m_terminator = true; - if (lastTokenWasRestrKeyword()) { - token = SEMICOLON; - m_delimited = true; - goto returnToken; - } goto start; case CharacterInvalid: goto returnError; diff --git a/JavaScriptCore/parser/Lexer.h b/JavaScriptCore/parser/Lexer.h index e6c1efd..4d2513d 100644 --- a/JavaScriptCore/parser/Lexer.h +++ b/JavaScriptCore/parser/Lexer.h @@ -48,10 +48,11 @@ namespace JSC { // Functions to set up parsing. void setCode(const SourceCode&, ParserArena&); void setIsReparsing() { m_isReparsing = true; } + bool isReparsing() const { return m_isReparsing; } // Functions for the parser itself. enum LexType { IdentifyReservedWords, IgnoreReservedWords }; - JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType); + JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType, bool strictMode); int lineNumber() const { return m_lineNumber; } void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; } int lastLineNumber() const { return m_lastLineNumber; } @@ -95,7 +96,7 @@ namespace JSC { ALWAYS_INLINE bool lastTokenWasRestrKeyword() const; ALWAYS_INLINE JSTokenType parseIdentifier(JSTokenData*, LexType); - ALWAYS_INLINE bool parseString(JSTokenData* lvalp); + ALWAYS_INLINE bool parseString(JSTokenData* lvalp, bool strictMode); ALWAYS_INLINE void parseHex(double& returnValue); ALWAYS_INLINE bool parseOctal(double& returnValue); ALWAYS_INLINE bool parseDecimal(double& returnValue); diff --git a/JavaScriptCore/parser/Nodes.cpp b/JavaScriptCore/parser/Nodes.cpp index 534e28a..34aa674 100644 --- a/JavaScriptCore/parser/Nodes.cpp +++ b/JavaScriptCore/parser/Nodes.cpp @@ -89,10 +89,10 @@ ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, Var // ------------------------------ ScopeNode ----------------------------- -ScopeNode::ScopeNode(JSGlobalData* globalData) +ScopeNode::ScopeNode(JSGlobalData* globalData, bool inStrictContext) : StatementNode(globalData) , ParserArenaRefCounted(globalData) - , m_features(NoFeatures) + , m_features(inStrictContext ? StrictModeFeature : NoFeatures) { } @@ -154,8 +154,8 @@ FunctionParameters::FunctionParameters(ParameterNode* firstParameter) append(parameter->ident()); } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData) - : ScopeNode(globalData) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, bool inStrictContext) + : ScopeNode(globalData, inStrictContext) { } @@ -177,9 +177,9 @@ void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, m_ident = ident; } -FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData) +FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, bool inStrictContext) { - return new FunctionBodyNode(globalData); + return new FunctionBodyNode(globalData, inStrictContext); } PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) diff --git a/JavaScriptCore/parser/Nodes.h b/JavaScriptCore/parser/Nodes.h index fa61cdc..f2a7c1e 100644 --- a/JavaScriptCore/parser/Nodes.h +++ b/JavaScriptCore/parser/Nodes.h @@ -57,6 +57,7 @@ namespace JSC { const CodeFeatures WithFeature = 1 << 4; const CodeFeatures CatchFeature = 1 << 5; const CodeFeatures ThisFeature = 1 << 6; + const CodeFeatures StrictModeFeature = 1 << 7; const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature; enum Operator { @@ -1393,7 +1394,7 @@ namespace JSC { typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNode(JSGlobalData*); + ScopeNode(JSGlobalData*, bool inStrictContext); ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); using ParserArenaRefCounted::operator new; @@ -1410,6 +1411,7 @@ namespace JSC { bool usesEval() const { return m_features & EvalFeature; } bool usesArguments() const { return m_features & ArgumentsFeature; } + bool isStrictMode() const { return m_features & StrictModeFeature; } void setUsesArguments() { m_features |= ArgumentsFeature; } bool usesThis() const { return m_features & ThisFeature; } bool needsActivationForMoreThanVariables() const { ASSERT(m_data); return m_features & (EvalFeature | WithFeature | CatchFeature); } @@ -1444,6 +1446,7 @@ namespace JSC { class ProgramNode : public ScopeNode { public: + static const bool isFunctionNode = false; static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); static const bool scopeIsFunction = false; @@ -1456,6 +1459,7 @@ namespace JSC { class EvalNode : public ScopeNode { public: + static const bool isFunctionNode = false; static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); static const bool scopeIsFunction = false; @@ -1476,7 +1480,8 @@ namespace JSC { class FunctionBodyNode : public ScopeNode { public: - static FunctionBodyNode* create(JSGlobalData*); + static const bool isFunctionNode = true; + static FunctionBodyNode* create(JSGlobalData*, bool isStrictMode); static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); FunctionParameters* parameters() const { return m_parameters.get(); } @@ -1492,7 +1497,7 @@ namespace JSC { static const bool scopeIsFunction = true; private: - FunctionBodyNode(JSGlobalData*); + FunctionBodyNode(JSGlobalData*, bool inStrictContext); FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); Identifier m_ident; diff --git a/JavaScriptCore/parser/Parser.cpp b/JavaScriptCore/parser/Parser.cpp index bd77742..5092357 100644 --- a/JavaScriptCore/parser/Parser.cpp +++ b/JavaScriptCore/parser/Parser.cpp @@ -26,12 +26,6 @@ #include "Debugger.h" #include "JSParser.h" #include "Lexer.h" -#include <wtf/HashSet.h> -#include <wtf/Vector.h> - -#ifndef yyparse -extern int jscyyparse(void*); -#endif #ifdef ANDROID_INSTRUMENT #include "TimeCounter.h" @@ -39,11 +33,15 @@ extern int jscyyparse(void*); namespace JSC { -void Parser::parse(JSGlobalData* globalData, FunctionParameters* parameters, int* errLine, UString* errMsg) +void Parser::parse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg) { +<<<<<<< HEAD #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::JavaScriptParseTimeCounter); #endif +======= + ASSERT(lexicalGlobalObject); +>>>>>>> webkit.org at r70209 m_sourceElements = 0; int defaultErrLine; @@ -57,10 +55,10 @@ void Parser::parse(JSGlobalData* globalData, FunctionParameters* parameters, int *errLine = -1; *errMsg = UString(); - Lexer& lexer = *globalData->lexer; + Lexer& lexer = *lexicalGlobalObject->globalData()->lexer; lexer.setCode(*m_source, m_arena); - int parseError = jsParse(globalData, parameters, m_source); + int parseError = jsParse(lexicalGlobalObject, parameters, strictness, mode, m_source); int lineNumber = lexer.lineNumber(); bool lexError = lexer.sawError(); lexer.clear(); diff --git a/JavaScriptCore/parser/Parser.h b/JavaScriptCore/parser/Parser.h index 9134de1..f5bbcb8 100644 --- a/JavaScriptCore/parser/Parser.h +++ b/JavaScriptCore/parser/Parser.h @@ -48,7 +48,7 @@ namespace JSC { class Parser : public Noncopyable { public: template <class ParsedNode> - PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, const SourceCode& source, FunctionParameters*, JSObject** exception); + PassRefPtr<ParsedNode> parse(JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, const SourceCode& source, FunctionParameters*, JSParserStrictness strictness, JSObject** exception); void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, @@ -57,7 +57,7 @@ namespace JSC { ParserArena& arena() { return m_arena; } private: - void parse(JSGlobalData*, FunctionParameters*, int* errLine, UString* errMsg); + void parse(JSGlobalObject* lexicalGlobalObject, FunctionParameters*, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg); // Used to determine type of error to report. bool isFunctionBodyNode(ScopeNode*) { return false; } @@ -75,20 +75,21 @@ namespace JSC { }; template <class ParsedNode> - PassRefPtr<ParsedNode> Parser::parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, FunctionParameters* parameters, JSObject** exception) + PassRefPtr<ParsedNode> Parser::parse(JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSObject** exception) { + ASSERT(lexicalGlobalObject); ASSERT(exception && !*exception); int errLine; UString errMsg; m_source = &source; if (ParsedNode::scopeIsFunction) - globalData->lexer->setIsReparsing(); - parse(globalData, parameters, &errLine, &errMsg); + lexicalGlobalObject->globalData()->lexer->setIsReparsing(); + parse(lexicalGlobalObject, parameters, strictness, ParsedNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, &errLine, &errMsg); RefPtr<ParsedNode> result; if (m_sourceElements) { - result = ParsedNode::create(globalData, + result = ParsedNode::create(lexicalGlobalObject->globalData(), m_sourceElements, m_varDeclarations ? &m_varDeclarations->data : 0, m_funcDeclarations ? &m_funcDeclarations->data : 0, @@ -107,7 +108,7 @@ namespace JSC { if (isFunctionBodyNode(static_cast<ParsedNode*>(0))) *exception = createStackOverflowError(lexicalGlobalObject); else - *exception = addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, source); + *exception = addErrorInfo(lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, source); } m_arena.reset(); diff --git a/JavaScriptCore/parser/SyntaxChecker.h b/JavaScriptCore/parser/SyntaxChecker.h index ce3ab61..f9093a7 100644 --- a/JavaScriptCore/parser/SyntaxChecker.h +++ b/JavaScriptCore/parser/SyntaxChecker.h @@ -30,15 +30,24 @@ namespace JSC { class SyntaxChecker { public: SyntaxChecker(JSGlobalData* , Lexer*) + : m_topBinaryExpr(0) { } typedef SyntaxChecker FunctionBodyBuilder; + enum { NoneExpr = 0, + ResolveEvalExpr, ResolveExpr, NumberExpr, StringExpr, + ThisExpr, NullExpr, BoolExpr, RegExpExpr, ObjectLiteralExpr, + FunctionExpr, BracketExpr, DotExpr, CallExpr, + NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr, + ConditionalExpr, AssignmentExpr, TypeofExpr, + DeleteExpr, ArrayLiteralExpr }; + typedef int ExpressionType; - typedef int Expression; + typedef ExpressionType Expression; typedef int SourceElements; typedef int Arguments; - typedef int Comma; + typedef ExpressionType Comma; struct Property { ALWAYS_INLINE Property(void* = 0) : type((PropertyNode::Type)0) @@ -73,38 +82,38 @@ public: static const bool NeedsFreeVariableInfo = false; int createSourceElements() { return 1; } - int makeFunctionCallNode(int, int, int, int, int) { return 1; } - void appendToComma(int, int) { } - int createCommaExpr(int, int) { return 1; } - int makeAssignNode(int, Operator, int, bool, bool, int, int, int) { return 1; } - int makePrefixNode(int, Operator, int, int, int) { return 1; } - int makePostfixNode(int, Operator, int, int, int) { return 1; } - int makeTypeOfNode(int) { return 1; } - int makeDeleteNode(int, int, int, int) { return 1; } - int makeNegateNode(int) { return 1; } - int makeBitwiseNotNode(int) { return 1; } - int createLogicalNot(int) { return 1; } - int createUnaryPlus(int) { return 1; } - int createVoid(int) { return 1; } - int thisExpr() { return 1; } - int createResolve(const Identifier*, int) { return 1; } - int createObjectLiteral() { return 1; } - int createObjectLiteral(int) { return 1; } - int createArray(int) { return 1; } - int createArray(int, int) { return 1; } - int createNumberExpr(double) { return 1; } - int createString(const Identifier*) { return 1; } - int createBoolean(bool) { return 1; } - int createNull() { return 1; } - int createBracketAccess(int, int, bool, int, int, int) { return 1; } - int createDotAccess(int, const Identifier&, int, int, int) { return 1; } - int createRegex(const Identifier&, const Identifier&, int) { return 1; } - int createNewExpr(int, int, int, int, int) { return 1; } - int createNewExpr(int, int, int) { return 1; } - int createConditionalExpr(int, int, int) { return 1; } - int createAssignResolve(const Identifier&, int, bool, int, int, int) { return 1; } - int createFunctionExpr(const Identifier*, int, int, int, int, int, int) { return 1; } - int createFunctionBody() { return 1; } + ExpressionType makeFunctionCallNode(int, int, int, int, int) { return CallExpr; } + void appendToComma(ExpressionType& base, ExpressionType right) { base = right; } + ExpressionType createCommaExpr(ExpressionType, ExpressionType right) { return right; } + ExpressionType makeAssignNode(ExpressionType, Operator, ExpressionType, bool, bool, int, int, int) { return AssignmentExpr; } + ExpressionType makePrefixNode(ExpressionType, Operator, int, int, int) { return PreExpr; } + ExpressionType makePostfixNode(ExpressionType, Operator, int, int, int) { return PostExpr; } + ExpressionType makeTypeOfNode(ExpressionType) { return TypeofExpr; } + ExpressionType makeDeleteNode(ExpressionType, int, int, int) { return DeleteExpr; } + ExpressionType makeNegateNode(ExpressionType) { return UnaryExpr; } + ExpressionType makeBitwiseNotNode(ExpressionType) { return UnaryExpr; } + ExpressionType createLogicalNot(ExpressionType) { return UnaryExpr; } + ExpressionType createUnaryPlus(ExpressionType) { return UnaryExpr; } + ExpressionType createVoid(ExpressionType) { return UnaryExpr; } + ExpressionType thisExpr() { return ThisExpr; } + ExpressionType createResolve(const Identifier*, int) { return ResolveExpr; } + ExpressionType createObjectLiteral() { return ObjectLiteralExpr; } + ExpressionType createObjectLiteral(int) { return ObjectLiteralExpr; } + ExpressionType createArray(int) { return ArrayLiteralExpr; } + ExpressionType createArray(int, int) { return ArrayLiteralExpr; } + ExpressionType createNumberExpr(double) { return NumberExpr; } + ExpressionType createString(const Identifier*) { return StringExpr; } + ExpressionType createBoolean(bool) { return BoolExpr; } + ExpressionType createNull() { return NullExpr; } + ExpressionType createBracketAccess(ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; } + ExpressionType createDotAccess(ExpressionType, const Identifier&, int, int, int) { return DotExpr; } + ExpressionType createRegex(const Identifier&, const Identifier&, int) { return RegExpExpr; } + ExpressionType createNewExpr(ExpressionType, int, int, int, int) { return NewExpr; } + ExpressionType createNewExpr(ExpressionType, int, int) { return NewExpr; } + ExpressionType createConditionalExpr(ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; } + ExpressionType createAssignResolve(const Identifier&, ExpressionType, bool, int, int, int) { return AssignmentExpr; } + ExpressionType createFunctionExpr(const Identifier*, int, int, int, int, int, int) { return FunctionExpr; } + int createFunctionBody(bool) { return 1; } int createArguments() { return 1; } int createArguments(int) { return 1; } int createArgumentsList(int) { return 1; } @@ -169,26 +178,38 @@ public: void addVar(const Identifier*, bool) { } int combineCommaNodes(int, int) { return 1; } int evalCount() const { return 0; } - void appendBinaryExpressionInfo(int& operandStackDepth, int, int, int, int, bool) { operandStackDepth++; } + void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool) + { + if (!m_topBinaryExpr) + m_topBinaryExpr = expr; + else + m_topBinaryExpr = BinaryExpr; + operandStackDepth++; + } // Logic to handle datastructures used during parsing of binary expressions void operatorStackPop(int& operatorStackDepth) { operatorStackDepth--; } bool operatorStackHasHigherPrecedence(int&, int) { return true; } - BinaryOperand getFromOperandStack(int) { return 1; } + BinaryOperand getFromOperandStack(int) { return m_topBinaryExpr; } void shrinkOperandStackBy(int& operandStackDepth, int amount) { operandStackDepth -= amount; } void appendBinaryOperation(int& operandStackDepth, int&, BinaryOperand, BinaryOperand) { operandStackDepth++; } void operatorStackAppend(int& operatorStackDepth, int, int) { operatorStackDepth++; } - int popOperandStack(int&) { return 1; } + int popOperandStack(int&) { int res = m_topBinaryExpr; m_topBinaryExpr = 0; return res; } - void appendUnaryToken(int&, int, int) { } - int unaryTokenStackLastType(int&) { ASSERT_NOT_REACHED(); return 1; } - int unaryTokenStackLastStart(int&) { ASSERT_NOT_REACHED(); return 1; } - void unaryTokenStackRemoveLast(int&) { } + void appendUnaryToken(int& stackDepth, int tok, int) { stackDepth = 1; m_topUnaryToken = tok; } + int unaryTokenStackLastType(int&) { return m_topUnaryToken; } + int unaryTokenStackLastStart(int&) { return 0; } + void unaryTokenStackRemoveLast(int& stackDepth) { stackDepth = 0; } void assignmentStackAppend(int, int, int, int, int, Operator) { } int createAssignment(int, int, int, int, int) { ASSERT_NOT_REACHED(); return 1; } const Identifier& getName(const Property& property) { ASSERT(property.name); return *property.name; } PropertyNode::Type getType(const Property& property) { return property.type; } + bool isResolve(ExpressionType expr) { return expr == ResolveExpr || expr == ResolveEvalExpr; } + +private: + int m_topBinaryExpr; + int m_topUnaryToken; }; } diff --git a/JavaScriptCore/profiler/Profiler.cpp b/JavaScriptCore/profiler/Profiler.cpp index 021ecff..78fe2f5 100644 --- a/JavaScriptCore/profiler/Profiler.cpp +++ b/JavaScriptCore/profiler/Profiler.cpp @@ -39,7 +39,7 @@ #include "Profile.h" #include "ProfileGenerator.h" #include "ProfileNode.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" #include <stdio.h> namespace JSC { @@ -152,7 +152,7 @@ CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionV return CallIdentifier(static_cast<JSFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber); if (asObject(functionValue)->inherits(&InternalFunction::info)) return CallIdentifier(static_cast<InternalFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber); - return CallIdentifier(makeString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber); + return CallIdentifier(makeUString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber); } CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSFunction* function) diff --git a/JavaScriptCore/runtime/Arguments.cpp b/JavaScriptCore/runtime/Arguments.cpp index 450dc7d..5c5e522 100644 --- a/JavaScriptCore/runtime/Arguments.cpp +++ b/JavaScriptCore/runtime/Arguments.cpp @@ -153,6 +153,30 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& sl return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::number(i)), slot); } + +void Arguments::createStrictModeCallerIfNecessary(ExecState* exec) +{ + if (d->overrodeCaller) + return; + + d->overrodeCaller = true; + PropertyDescriptor descriptor; + JSValue thrower = createTypeErrorFunction(exec, "Unable to access caller of strict mode function"); + descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter); + defineOwnProperty(exec, exec->propertyNames().caller, descriptor, false); +} + +void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec) +{ + if (d->overrodeCallee) + return; + + d->overrodeCallee = true; + PropertyDescriptor descriptor; + JSValue thrower = createTypeErrorFunction(exec, "Unable to access callee of strict mode function"); + descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter); + defineOwnProperty(exec, exec->propertyNames().callee, descriptor, false); +} bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { @@ -172,10 +196,16 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa } if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { - slot.setValue(d->callee); - return true; + if (!d->isStrictMode) { + slot.setValue(d->callee); + return true; + } + createStrictModeCalleeIfNecessary(exec); } + if (propertyName == exec->propertyNames().caller && d->isStrictMode) + createStrictModeCallerIfNecessary(exec); + return JSObject::getOwnPropertySlot(exec, propertyName, slot); } @@ -197,9 +227,15 @@ bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& prop } if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { - descriptor.setDescriptor(d->callee, DontEnum); - return true; + if (!d->isStrictMode) { + descriptor.setDescriptor(d->callee, DontEnum); + return true; + } + createStrictModeCalleeIfNecessary(exec); } + + if (propertyName == exec->propertyNames().caller && d->isStrictMode) + createStrictModeCallerIfNecessary(exec); return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); } @@ -249,11 +285,17 @@ void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue val } if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { - d->overrodeCallee = true; - putDirect(propertyName, value, DontEnum); - return; + if (!d->isStrictMode) { + d->overrodeCallee = true; + putDirect(propertyName, value, DontEnum); + return; + } + createStrictModeCalleeIfNecessary(exec); } + if (propertyName == exec->propertyNames().caller && d->isStrictMode) + createStrictModeCallerIfNecessary(exec); + JSObject::put(exec, propertyName, value, slot); } @@ -294,9 +336,15 @@ bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) } if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { - d->overrodeCallee = true; - return true; + if (!d->isStrictMode) { + d->overrodeCallee = true; + return true; + } + createStrictModeCalleeIfNecessary(exec); } + + if (propertyName == exec->propertyNames().caller && !d->isStrictMode) + createStrictModeCallerIfNecessary(exec); return JSObject::deleteProperty(exec, propertyName); } diff --git a/JavaScriptCore/runtime/Arguments.h b/JavaScriptCore/runtime/Arguments.h index 49c8b3b..715a2ac 100644 --- a/JavaScriptCore/runtime/Arguments.h +++ b/JavaScriptCore/runtime/Arguments.h @@ -50,6 +50,8 @@ namespace JSC { JSFunction* callee; bool overrodeLength : 1; bool overrodeCallee : 1; + bool overrodeCaller : 1; + bool isStrictMode : 1; }; @@ -105,6 +107,8 @@ namespace JSC { virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); + void createStrictModeCallerIfNecessary(ExecState*); + void createStrictModeCalleeIfNecessary(ExecState*); virtual const ClassInfo* classInfo() const { return &info; } @@ -172,6 +176,10 @@ namespace JSC { d->callee = callee; d->overrodeLength = false; d->overrodeCallee = false; + d->overrodeCaller = false; + d->isStrictMode = callFrame->codeBlock()->isStrictMode(); + if (d->isStrictMode) + copyRegisters(); } inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) @@ -201,6 +209,10 @@ namespace JSC { d->callee = asFunction(callFrame->callee()); d->overrodeLength = false; d->overrodeCallee = false; + d->overrodeCaller = false; + d->isStrictMode = callFrame->codeBlock()->isStrictMode(); + if (d->isStrictMode) + copyRegisters(); } inline void Arguments::copyRegisters() diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp index 28269ff..6002ebb 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -180,7 +180,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned totalSize = length ? length - 1 : 0; +#if OS(SYMBIAN) + // Symbian has very limited stack size available. + // This function could be called recursively and allocating 1K on stack here cause + // stack overflow on Symbian devices. + Vector<RefPtr<StringImpl> > strBuffer(length); +#else Vector<RefPtr<StringImpl>, 256> strBuffer(length); +#endif for (unsigned k = 0; k < length; k++) { JSValue element; if (isRealArray && thisObj->canGetIndex(k)) diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp index 93b91bb..f341646 100644 --- a/JavaScriptCore/runtime/Collector.cpp +++ b/JavaScriptCore/runtime/Collector.cpp @@ -642,19 +642,6 @@ inline bool isPointerAligned(void* p) // Cell size needs to be a power of two for isPossibleCell to be valid. COMPILE_ASSERT(sizeof(CollectorCell) % 2 == 0, Collector_cell_size_is_power_of_two); -#if USE(JSVALUE32) -static bool isHalfCellAligned(void *p) -{ - return (((intptr_t)(p) & (CELL_MASK >> 1)) == 0); -} - -static inline bool isPossibleCell(void* p) -{ - return isHalfCellAligned(p) && p; -} - -#else - static inline bool isCellAligned(void *p) { return (((intptr_t)(p) & CELL_MASK) == 0); @@ -664,7 +651,6 @@ static inline bool isPossibleCell(void* p) { return isCellAligned(p) && p; } -#endif // USE(JSVALUE32) void Heap::markConservatively(MarkStack& markStack, void* start, void* end) { @@ -1145,10 +1131,6 @@ static const char* typeName(JSCell* cell) { if (cell->isString()) return "string"; -#if USE(JSVALUE32) - if (cell->isNumber()) - return "number"; -#endif if (cell->isGetterSetter()) return "Getter-Setter"; if (cell->isAPIValueWrapper()) diff --git a/JavaScriptCore/runtime/Collector.h b/JavaScriptCore/runtime/Collector.h index 05d5c10..237c139 100644 --- a/JavaScriptCore/runtime/Collector.h +++ b/JavaScriptCore/runtime/Collector.h @@ -57,7 +57,7 @@ namespace JSC { class LiveObjectIterator; -#if OS(WINCE) || OS(SYMBIAN) +#if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP) const size_t BLOCK_SIZE = 64 * 1024; // 64k #else const size_t BLOCK_SIZE = 256 * 1024; // 256k diff --git a/JavaScriptCore/runtime/CommonIdentifiers.cpp b/JavaScriptCore/runtime/CommonIdentifiers.cpp index 3837817..1561102 100644 --- a/JavaScriptCore/runtime/CommonIdentifiers.cpp +++ b/JavaScriptCore/runtime/CommonIdentifiers.cpp @@ -32,6 +32,7 @@ CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData) , emptyIdentifier(globalData, "") , underscoreProto(globalData, "__proto__") , thisIdentifier(globalData, "this") + , useStrictIdentifier(globalData, "use strict") JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME) { } diff --git a/JavaScriptCore/runtime/CommonIdentifiers.h b/JavaScriptCore/runtime/CommonIdentifiers.h index de24f4a..1e22b6a 100644 --- a/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/JavaScriptCore/runtime/CommonIdentifiers.h @@ -94,6 +94,7 @@ namespace JSC { const Identifier emptyIdentifier; const Identifier underscoreProto; const Identifier thisIdentifier; + const Identifier useStrictIdentifier; #define JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL(name) const Identifier name; JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL) diff --git a/JavaScriptCore/runtime/DateConversion.cpp b/JavaScriptCore/runtime/DateConversion.cpp index 7eb82e4..d4b8232 100644 --- a/JavaScriptCore/runtime/DateConversion.cpp +++ b/JavaScriptCore/runtime/DateConversion.cpp @@ -57,7 +57,9 @@ double parseDate(ExecState* exec, const UString &date) { if (date == exec->globalData().cachedDateString) return exec->globalData().cachedDateStringValue; - double value = parseDateFromNullTerminatedCharacters(exec, date.utf8().data()); + double value = parseES5DateFromNullTerminatedCharacters(date.utf8().data()); + if (isnan(value)) + value = parseDateFromNullTerminatedCharacters(exec, date.utf8().data()); exec->globalData().cachedDateString = date; exec->globalData().cachedDateStringValue = value; return value; diff --git a/JavaScriptCore/runtime/Error.cpp b/JavaScriptCore/runtime/Error.cpp index a2be473..e35424b 100644 --- a/JavaScriptCore/runtime/Error.cpp +++ b/JavaScriptCore/runtime/Error.cpp @@ -195,4 +195,47 @@ JSObject* throwSyntaxError(ExecState* exec) return throwError(exec, createSyntaxError(exec, "Syntax error")); } +class StrictModeTypeErrorFunction : public InternalFunction { +public: + StrictModeTypeErrorFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const UString& message) + : InternalFunction(&exec->globalData(), globalObject, structure, exec->globalData().propertyNames->emptyIdentifier) + , m_message(message) + { + } + + static EncodedJSValue JSC_HOST_CALL constructThrowTypeError(ExecState* exec) + { + throwTypeError(exec, static_cast<StrictModeTypeErrorFunction*>(exec->callee())->m_message); + return JSValue::encode(jsNull()); + } + + ConstructType getConstructData(ConstructData& constructData) + { + constructData.native.function = constructThrowTypeError; + return ConstructTypeHost; + } + + static EncodedJSValue JSC_HOST_CALL callThrowTypeError(ExecState* exec) + { + throwTypeError(exec, static_cast<StrictModeTypeErrorFunction*>(exec->callee())->m_message); + return JSValue::encode(jsNull()); + } + + CallType getCallData(CallData& callData) + { + callData.native.function = callThrowTypeError; + return CallTypeHost; + } + +private: + UString m_message; +}; + +COMPILE_ASSERT(sizeof(StrictModeTypeErrorFunction) <= sizeof(CollectorCell), sizeof_StrictModeTypeErrorFunction_must_be_less_than_CollectorCell); + +JSValue createTypeErrorFunction(ExecState* exec, const UString& message) +{ + return new (exec) StrictModeTypeErrorFunction(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->internalFunctionStructure(), message); +} + } // namespace JSC diff --git a/JavaScriptCore/runtime/Error.h b/JavaScriptCore/runtime/Error.h index 1a0ece5..bfde7dc 100644 --- a/JavaScriptCore/runtime/Error.h +++ b/JavaScriptCore/runtime/Error.h @@ -73,6 +73,8 @@ namespace JSC { inline EncodedJSValue throwVMError(ExecState* exec, JSValue error) { return JSValue::encode(throwError(exec, error)); } inline EncodedJSValue throwVMTypeError(ExecState* exec) { return JSValue::encode(throwTypeError(exec)); } + JSValue createTypeErrorFunction(ExecState* exec, const UString& message); + } // namespace JSC #endif // Error_h diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp index 9a6fe5e..a1e28d1 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -36,7 +36,7 @@ #include "JSNotAnObject.h" #include "Interpreter.h" #include "Nodes.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" namespace JSC { @@ -90,7 +90,7 @@ JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, u int endOffset = 0; int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); - UString message(makeString("Can't find variable: ", ident.ustring())); + UString message(makeUString("Can't find variable: ", ident.ustring())); JSObject* exception = addErrorInfo(exec, createReferenceError(exec, message), line, codeBlock->ownerExecutable()->source(), divotPoint, startOffset, endOffset); return exception; } @@ -98,9 +98,9 @@ JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, u static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue value, UString error) { if (!expressionStop || expressionStart > codeBlock->source()->length()) - return makeString(value.toString(exec), " is ", error); + return makeUString(value.toString(exec), " is ", error); if (expressionStart < expressionStop) - return makeString("Result of expression '", codeBlock->source()->getRange(expressionStart, expressionStop), "' [", value.toString(exec), "] is ", error, "."); + return makeUString("Result of expression '", codeBlock->source()->getRange(expressionStart, expressionStop), "' [", value.toString(exec), "] is ", error, "."); // No range information, so give a few characters of context const UChar* data = codeBlock->source()->data(); @@ -117,7 +117,7 @@ static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, in stop++; while (stop > expressionStart && isStrWhiteSpace(data[stop])) stop--; - return makeString("Result of expression near '...", codeBlock->source()->getRange(start, stop), "...' [", value.toString(exec), "] is ", error, "."); + return makeUString("Result of expression near '...", codeBlock->source()->getRange(start, stop), "...' [", value.toString(exec), "] is ", error, "."); } JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock) @@ -126,7 +126,7 @@ JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value int endOffset = 0; int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); - UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, makeString("not a valid argument for '", op, "'")); + UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, makeUString("not a valid argument for '", op, "'")); JSObject* exception = addErrorInfo(exec, createTypeError(exec, errorMessage), line, codeBlock->ownerExecutable()->source(), divotPoint, startOffset, endOffset); return exception; } @@ -192,4 +192,9 @@ JSValue throwOutOfMemoryError(ExecState* exec) return throwError(exec, createError(exec, "Out of memory")); } +JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const UString& propertyName) +{ + return createReferenceError(exec, makeUString("Strict mode forbids implicit creation of global property '", propertyName, "'")); +} + } // namespace JSC diff --git a/JavaScriptCore/runtime/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h index 3e6de86..9b6f1f2 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.h +++ b/JavaScriptCore/runtime/ExceptionHelpers.h @@ -54,6 +54,7 @@ namespace JSC { JSValue createNotAFunctionError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*); JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*); JSValue throwOutOfMemoryError(ExecState*); + JSObject* createErrorForInvalidGlobalAssignment(ExecState*, const UString&); } // namespace JSC diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp index 871f3e2..2ad4b2d 100644 --- a/JavaScriptCore/runtime/Executable.cpp +++ b/JavaScriptCore/runtime/Executable.cpp @@ -30,7 +30,7 @@ #include "CodeBlock.h" #include "JIT.h" #include "Parser.h" -#include "StringBuilder.h" +#include "UStringBuilder.h" #include "Vector.h" namespace JSC { @@ -45,8 +45,8 @@ VPtrHackExecutable::~VPtrHackExecutable() { } -EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source) - : ScriptExecutable(exec, source) +EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext) + : ScriptExecutable(exec, source, inStrictContext) { } @@ -55,7 +55,7 @@ EvalExecutable::~EvalExecutable() } ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source) - : ScriptExecutable(exec, source) + : ScriptExecutable(exec, source, false) { } @@ -63,8 +63,8 @@ ProgramExecutable::~ProgramExecutable() { } -FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) - : ScriptExecutable(globalData, source) +FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine) + : ScriptExecutable(globalData, source, inStrictContext) , m_numCapturedVariables(0) , m_forceUsesArguments(forceUsesArguments) , m_parameters(parameters) @@ -75,8 +75,8 @@ FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifie m_lastLine = lastLine; } -FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) - : ScriptExecutable(exec, source) +FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine) + : ScriptExecutable(exec, source, inStrictContext) , m_numCapturedVariables(0) , m_forceUsesArguments(forceUsesArguments) , m_parameters(parameters) @@ -96,7 +96,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception); + RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!evalNode) { ASSERT(exception); return exception; @@ -131,7 +131,7 @@ JSObject* ProgramExecutable::checkSyntax(ExecState* exec) JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception); + RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, JSParseNormal, &exception); if (programNode) return 0; ASSERT(exception); @@ -145,7 +145,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception); + RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!programNode) { ASSERT(exception); return exception; @@ -178,7 +178,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain { JSObject* exception = 0; JSGlobalData* globalData = scopeChainNode->globalData; - RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), &exception); + RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!body) { ASSERT(exception); return exception; @@ -219,7 +219,7 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope { JSObject* exception = 0; JSGlobalData* globalData = scopeChainNode->globalData; - RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), &exception); + RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!body) { ASSERT(exception); return exception; @@ -264,12 +264,14 @@ void FunctionExecutable::markAggregate(MarkStack& markStack) m_codeBlockForConstruct->markAggregate(markStack); } -PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) +PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) { JSObject* exception = 0; - RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, 0, m_source, m_parameters.get(), &exception); + JSGlobalData* globalData = scopeChainNode->globalData; + RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(scopeChainNode->globalObject, 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!newFunctionBody) return PassOwnPtr<ExceptionInfo>(); + ASSERT(newFunctionBody->isStrictMode() == isStrictMode()); if (m_forceUsesArguments) newFunctionBody->setUsesArguments(); newFunctionBody->finishParsing(m_parameters, m_name); @@ -298,10 +300,12 @@ PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* return newCodeBlock->extractExceptionInfo(); } -PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) +PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) { JSObject* exception = 0; - RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, 0, m_source, 0, &exception); + JSGlobalData* globalData = scopeChainNode->globalData; + RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(scopeChainNode->globalObject, 0, 0, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception); + ASSERT(newEvalBody->isStrictMode() == isStrictMode()); if (!newEvalBody) return PassOwnPtr<ExceptionInfo>(); @@ -341,7 +345,7 @@ void FunctionExecutable::recompile(ExecState*) PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception) { JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, debugger, exec, source, 0, exception); + RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(lexicalGlobalObject, debugger, exec, source, 0, JSParseNormal, exception); if (!program) { ASSERT(*exception); return 0; @@ -357,22 +361,22 @@ PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifi FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); ASSERT(body); - return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine()); + return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine()); } UString FunctionExecutable::paramString() const { FunctionParameters& parameters = *m_parameters; - StringBuilder builder; + UStringBuilder builder; for (size_t pos = 0; pos < parameters.size(); ++pos) { if (!builder.isEmpty()) builder.append(", "); builder.append(parameters[pos].ustring()); } - return builder.build(); + return builder.toUString(); } -PassOwnPtr<ExceptionInfo> ProgramExecutable::reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) +PassOwnPtr<ExceptionInfo> ProgramExecutable::reparseExceptionInfo(ScopeChainNode*, CodeBlock*) { // CodeBlocks for program code are transient and therefore do not gain from from throwing out their exception information. return PassOwnPtr<ExceptionInfo>(); diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h index feab7ef..4c4ca56 100644 --- a/JavaScriptCore/runtime/Executable.h +++ b/JavaScriptCore/runtime/Executable.h @@ -138,10 +138,10 @@ namespace JSC { class ScriptExecutable : public ExecutableBase { public: - ScriptExecutable(JSGlobalData* globalData, const SourceCode& source) + ScriptExecutable(JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext) : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED) , m_source(source) - , m_features(0) + , m_features(isInStrictContext ? StrictModeFeature : 0) { #if ENABLE(CODEBLOCK_SAMPLING) relaxAdoptionRequirement(); @@ -152,10 +152,10 @@ namespace JSC { #endif } - ScriptExecutable(ExecState* exec, const SourceCode& source) + ScriptExecutable(ExecState* exec, const SourceCode& source, bool isInStrictContext) : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED) , m_source(source) - , m_features(0) + , m_features(isInStrictContext ? StrictModeFeature : 0) { #if ENABLE(CODEBLOCK_SAMPLING) relaxAdoptionRequirement(); @@ -175,8 +175,9 @@ namespace JSC { bool usesEval() const { return m_features & EvalFeature; } bool usesArguments() const { return m_features & ArgumentsFeature; } bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); } + bool isStrictMode() const { return m_features & StrictModeFeature; } - virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0; + virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*) = 0; protected: void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine) @@ -214,7 +215,7 @@ namespace JSC { return *m_evalCodeBlock; } - static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); } + static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return adoptRef(new EvalExecutable(exec, source, isInStrictContext)); } #if ENABLE(JIT) JITCode& generatedJITCode() @@ -224,11 +225,11 @@ namespace JSC { #endif private: - EvalExecutable(ExecState*, const SourceCode&); + EvalExecutable(ExecState*, const SourceCode&, bool); JSObject* compileInternal(ExecState*, ScopeChainNode*); - virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*); OwnPtr<EvalCodeBlock> m_evalCodeBlock; }; @@ -271,7 +272,7 @@ namespace JSC { JSObject* compileInternal(ExecState*, ScopeChainNode*); - virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*); OwnPtr<ProgramCodeBlock> m_programCodeBlock; }; @@ -279,14 +280,14 @@ namespace JSC { class FunctionExecutable : public ScriptExecutable { friend class JIT; public: - static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) + static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) { - return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, firstLine, lastLine)); + return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine)); } - static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) + static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) { - return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, firstLine, lastLine)); + return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine)); } ~FunctionExecutable(); @@ -358,13 +359,13 @@ namespace JSC { static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception); private: - FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, int firstLine, int lastLine); - FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, int firstLine, int lastLine); + FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine); + FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine); JSObject* compileForCallInternal(ExecState*, ScopeChainNode*); JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*); - virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*); unsigned m_numCapturedVariables : 31; bool m_forceUsesArguments : 1; diff --git a/JavaScriptCore/runtime/FunctionConstructor.cpp b/JavaScriptCore/runtime/FunctionConstructor.cpp index f72a273..9b59720 100644 --- a/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -30,8 +30,8 @@ #include "Lexer.h" #include "Nodes.h" #include "Parser.h" -#include "StringBuilder.h" -#include "StringConcatenate.h" +#include "UStringBuilder.h" +#include "UStringConcatenate.h" namespace JSC { @@ -81,9 +81,9 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi if (args.isEmpty()) program = "(function() { \n})"; else if (args.size() == 1) - program = makeString("(function() { ", args.at(0).toString(exec), "\n})"); + program = makeUString("(function() { ", args.at(0).toString(exec), "\n})"); else { - StringBuilder builder; + UStringBuilder builder; builder.append("(function("); builder.append(args.at(0).toString(exec)); for (size_t i = 1; i < args.size() - 1; i++) { @@ -93,7 +93,7 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi builder.append(") { "); builder.append(args.at(args.size() - 1).toString(exec)); builder.append("\n})"); - program = builder.build(); + program = builder.toUString(); } JSGlobalObject* globalObject = exec->lexicalGlobalObject(); diff --git a/JavaScriptCore/runtime/FunctionPrototype.cpp b/JavaScriptCore/runtime/FunctionPrototype.cpp index c740624..ef42cdc 100644 --- a/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -77,7 +77,7 @@ static inline void insertSemicolonIfNeeded(UString& functionBody) UChar ch = functionBody[i]; if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) { if (ch != ';' && ch != '}') - functionBody = makeString(functionBody.substringSharingImpl(0, i + 1), ";", functionBody.substringSharingImpl(i + 1, functionBody.length() - (i + 1))); + functionBody = makeUString(functionBody.substringSharingImpl(0, i + 1), ";", functionBody.substringSharingImpl(i + 1, functionBody.length() - (i + 1))); return; } } diff --git a/JavaScriptCore/runtime/JSActivation.cpp b/JavaScriptCore/runtime/JSActivation.cpp index d121518..795ad1f 100644 --- a/JavaScriptCore/runtime/JSActivation.cpp +++ b/JavaScriptCore/runtime/JSActivation.cpp @@ -186,6 +186,11 @@ JSObject* JSActivation::toThisObject(ExecState* exec) const return exec->globalThisValue(); } +JSValue JSActivation::toStrictThisObject(ExecState*) const +{ + return jsNull(); +} + bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const { requiresDynamicChecks = d()->functionExecutable->usesEval(); diff --git a/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h index 9ff9168..6dd6d70 100644 --- a/JavaScriptCore/runtime/JSActivation.h +++ b/JavaScriptCore/runtime/JSActivation.h @@ -60,6 +60,7 @@ namespace JSC { virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual JSObject* toThisObject(ExecState*) const; + virtual JSValue toStrictThisObject(ExecState*) const; void copyRegisters(); diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h index cfa1454..1a7f8b2 100644 --- a/JavaScriptCore/runtime/JSCell.h +++ b/JavaScriptCore/runtime/JSCell.h @@ -75,9 +75,6 @@ namespace JSC { } // Querying the type. -#if USE(JSVALUE32) - bool isNumber() const; -#endif bool isString() const; bool isObject() const; virtual bool isGetterSetter() const; @@ -156,13 +153,6 @@ namespace JSC { { } -#if USE(JSVALUE32) - inline bool JSCell::isNumber() const - { - return m_structure->typeInfo().type() == NumberType; - } -#endif - inline bool JSCell::isObject() const { return m_structure->typeInfo().type() == ObjectType; @@ -253,13 +243,13 @@ namespace JSC { return false; } -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) ALWAYS_INLINE JSCell* JSValue::asCell() const { ASSERT(isCell()); return m_ptr; } -#endif // !USE(JSVALUE32_64) +#endif // USE(JSVALUE64) inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const { diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp index 7eb9ba5..fdaa509 100644 --- a/JavaScriptCore/runtime/JSFunction.cpp +++ b/JavaScriptCore/runtime/JSFunction.cpp @@ -122,6 +122,15 @@ JSFunction::~JSFunction() } } +static const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function"; +static const char* StrictModeArgumentsAccessError = "Cannot access arguments property of a strict mode function"; + +static void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescriptor& descriptor, const char* message) +{ + JSValue thrower = createTypeErrorFunction(exec, message); + descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter); +} + const UString& JSFunction::name(ExecState* exec) { return asString(getDirect(exec->globalData().propertyNames->name))->tryGetValue(); @@ -209,6 +218,12 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN } if (propertyName == exec->propertyNames().arguments) { + if (jsExecutable()->isStrictMode()) { + throwTypeError(exec, "Can't access arguments object of a strict mode function"); + slot.setValue(jsNull()); + return true; + } + slot.setCacheableCustom(this, argumentsGetter); return true; } @@ -219,6 +234,11 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN } if (propertyName == exec->propertyNames().caller) { + if (jsExecutable()->isStrictMode()) { + throwTypeError(exec, StrictModeCallerAccessError); + slot.setValue(jsNull()); + return true; + } slot.setCacheableCustom(this, callerGetter); return true; } @@ -226,35 +246,41 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN return Base::getOwnPropertySlot(exec, propertyName, slot); } - bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) - { - if (isHostFunction()) - return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); - - if (propertyName == exec->propertyNames().prototype) { - PropertySlot slot; - getOwnPropertySlot(exec, propertyName, slot); - return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); - } - - if (propertyName == exec->propertyNames().arguments) { +bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + if (isHostFunction()) + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); + + if (propertyName == exec->propertyNames().prototype) { + PropertySlot slot; + getOwnPropertySlot(exec, propertyName, slot); + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); + } + + if (propertyName == exec->propertyNames().arguments) { + if (jsExecutable()->isStrictMode()) + createDescriptorForThrowingProperty(exec, descriptor, StrictModeArgumentsAccessError); + else descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete); - return true; - } - - if (propertyName == exec->propertyNames().length) { - descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); - return true; - } - - if (propertyName == exec->propertyNames().caller) { + return true; + } + + if (propertyName == exec->propertyNames().length) { + descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); + return true; + } + + if (propertyName == exec->propertyNames().caller) { + if (jsExecutable()->isStrictMode()) + createDescriptorForThrowingProperty(exec, descriptor, StrictModeCallerAccessError); + else descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete); - return true; - } - - return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); + return true; } + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + void JSFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { if (!isHostFunction() && (mode == IncludeDontEnumProperties)) { @@ -272,6 +298,16 @@ void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue va Base::put(exec, propertyName, value, slot); return; } + if (jsExecutable()->isStrictMode()) { + if (propertyName == exec->propertyNames().arguments) { + throwTypeError(exec, StrictModeArgumentsAccessError); + return; + } + if (propertyName == exec->propertyNames().caller) { + throwTypeError(exec, StrictModeCallerAccessError); + return; + } + } if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) return; Base::put(exec, propertyName, value, slot); diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp index 5eaa59b..1404ddf 100644 --- a/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/JavaScriptCore/runtime/JSGlobalData.cpp @@ -50,6 +50,7 @@ #include "Nodes.h" #include "Parser.h" #include "RegExpCache.h" +#include "StrictEvalActivation.h" #include <wtf/WTFThreadData.h> #if ENABLE(REGEXP_TRACING) #include "RegExp.h" @@ -124,6 +125,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull())) , terminatedExecutionErrorStructure(JSObject::createStructure(jsNull())) , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull())) + , strictEvalActivationStructure(StrictEvalActivation::createStructure(jsNull())) , stringStructure(JSString::createStructure(jsNull())) , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull())) , notAnObjectStructure(JSNotAnObject::createStructure(jsNull())) @@ -131,9 +133,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , getterSetterStructure(GetterSetter::createStructure(jsNull())) , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull())) , dummyMarkableCellStructure(JSCell::createDummyStructure()) -#if USE(JSVALUE32) - , numberStructure(JSNumberCell::createStructure(jsNull())) -#endif , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h index 8e2ed61..775d026 100644 --- a/JavaScriptCore/runtime/JSGlobalData.h +++ b/JavaScriptCore/runtime/JSGlobalData.h @@ -145,6 +145,7 @@ namespace JSC { RefPtr<Structure> interruptedExecutionErrorStructure; RefPtr<Structure> terminatedExecutionErrorStructure; RefPtr<Structure> staticScopeStructure; + RefPtr<Structure> strictEvalActivationStructure; RefPtr<Structure> stringStructure; RefPtr<Structure> notAnObjectErrorStubStructure; RefPtr<Structure> notAnObjectStructure; @@ -153,10 +154,6 @@ namespace JSC { RefPtr<Structure> apiWrapperStructure; RefPtr<Structure> dummyMarkableCellStructure; -#if USE(JSVALUE32) - RefPtr<Structure> numberStructure; -#endif - static void storeVPtrs(); static JS_EXPORTDATA void* jsArrayVPtr; static JS_EXPORTDATA void* jsByteArrayVPtr; diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp index 89c042a..903e573 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -204,6 +204,7 @@ void JSGlobalObject::reset(JSValue prototype) d()->functionPrototype = new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(jsNull())); // The real prototype will be set once ObjectPrototype is created. d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype); + d()->internalFunctionStructure = InternalFunction::createStructure(d()->functionPrototype); NativeFunctionWrapper* callFunction = 0; NativeFunctionWrapper* applyFunction = 0; d()->functionPrototype->addFunctionProperties(exec, this, d()->prototypeFunctionStructure.get(), &callFunction, &applyFunction); diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h index f5d2fb0..36fa70b 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.h +++ b/JavaScriptCore/runtime/JSGlobalObject.h @@ -148,6 +148,7 @@ namespace JSC { RefPtr<Structure> regExpMatchesArrayStructure; RefPtr<Structure> regExpStructure; RefPtr<Structure> stringObjectStructure; + RefPtr<Structure> internalFunctionStructure; SymbolTable symbolTable; unsigned profileGroup; @@ -243,6 +244,7 @@ namespace JSC { Structure* functionStructure() const { return d()->functionStructure.get(); } Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); } Structure* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); } + Structure* internalFunctionStructure() const { return d()->internalFunctionStructure.get(); } Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); } Structure* regExpStructure() const { return d()->regExpStructure.get(); } Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); } @@ -384,16 +386,8 @@ namespace JSC { if (typeInfo().type() == ObjectType) return m_prototype; -#if USE(JSVALUE32) - if (typeInfo().type() == StringType) - return exec->lexicalGlobalObject()->stringPrototype(); - - ASSERT(typeInfo().type() == NumberType); - return exec->lexicalGlobalObject()->numberPrototype(); -#else ASSERT(typeInfo().type() == StringType); return exec->lexicalGlobalObject()->stringPrototype(); -#endif } inline StructureChain* Structure::prototypeChain(ExecState* exec) const diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 1e20f7f..ed06fa5 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -35,7 +35,7 @@ #include "LiteralParser.h" #include "Nodes.h" #include "Parser.h" -#include "StringBuilder.h" +#include "UStringBuilder.h" #include "dtoa.h" #include <stdio.h> #include <stdlib.h> @@ -450,7 +450,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) if (JSValue parsedObject = preparser.tryLiteralParse()) return JSValue::encode(parsedObject); - RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s)); + RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s), false); JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node()); if (error) return throwVMError(exec, error); @@ -563,7 +563,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec) EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec) { - StringBuilder builder; + UStringBuilder builder; UString str = exec->argument(0).toString(exec); int k = 0; int len = str.length(); @@ -585,7 +585,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec) builder.append(*c); } - return JSValue::encode(jsString(exec, builder.build())); + return JSValue::encode(jsString(exec, builder.toUString())); } #ifndef NDEBUG diff --git a/JavaScriptCore/runtime/JSImmediate.h b/JavaScriptCore/runtime/JSImmediate.h index 9127b6a..ffa446e 100644 --- a/JavaScriptCore/runtime/JSImmediate.h +++ b/JavaScriptCore/runtime/JSImmediate.h @@ -22,7 +22,7 @@ #ifndef JSImmediate_h #define JSImmediate_h -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) #include <wtf/Assertions.h> #include <wtf/AlwaysInline.h> @@ -44,7 +44,6 @@ namespace JSC { class JSObject; class UString; -#if USE(JSVALUE64) inline intptr_t reinterpretDoubleToIntptr(double value) { return WTF::bitwise_cast<intptr_t>(value); @@ -54,7 +53,6 @@ namespace JSC { { return WTF::bitwise_cast<double>(value); } -#endif /* * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged @@ -159,16 +157,12 @@ namespace JSC { friend JSValue jsNumber(JSGlobalData* globalData, long long i); friend JSValue jsNumber(JSGlobalData* globalData, unsigned long long i); -#if USE(JSVALUE64) // If all bits in the mask are set, this indicates an integer number, // if any but not all are set this value is a double precision number. static const intptr_t TagTypeNumber = 0xffff000000000000ll; // This value is 2^48, used to encode doubles such that the encoded value will begin // with a 16-bit pattern within the range 0x0001..0xFFFE. static const intptr_t DoubleEncodeOffset = 0x1000000000000ll; -#elif USE(JSVALUE32) - static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit -#endif static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer static const intptr_t TagMask = TagTypeNumber | TagBitTypeOther; @@ -181,11 +175,7 @@ namespace JSC { static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined; static const intptr_t FullTagTypeNull = TagBitTypeOther; -#if USE(JSVALUE64) static const int32_t IntegerPayloadShift = 0; -#else - static const int32_t IntegerPayloadShift = 1; -#endif static const int32_t ExtendedPayloadShift = 4; static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift; @@ -204,19 +194,13 @@ namespace JSC { static ALWAYS_INLINE bool isIntegerNumber(JSValue v) { -#if USE(JSVALUE64) return (rawValue(v) & TagTypeNumber) == TagTypeNumber; -#else - return isNumber(v); -#endif } -#if USE(JSVALUE64) static ALWAYS_INLINE bool isDouble(JSValue v) { return isNumber(v) && !isIntegerNumber(v); } -#endif static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValue v) { @@ -260,11 +244,7 @@ namespace JSC { static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValue v1, JSValue v2) { -#if USE(JSVALUE64) return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber; -#else - return rawValue(v1) & rawValue(v2) & TagTypeNumber; -#endif } static double toDouble(JSValue); @@ -285,13 +265,8 @@ namespace JSC { static JSValue oneImmediate(); private: -#if USE(JSVALUE64) static const int minImmediateInt = ((-INT_MAX) - 1); static const int maxImmediateInt = INT_MAX; -#else - static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift; - static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift; -#endif static const unsigned maxImmediateUInt = maxImmediateInt; static ALWAYS_INLINE JSValue makeValue(intptr_t integer) @@ -302,21 +277,15 @@ namespace JSC { // With USE(JSVALUE64) we want the argument to be zero extended, so the // integer doesn't interfere with the tag bits in the upper word. In the default encoding, // if intptr_t id larger then int32_t we sign extend the value through the upper word. -#if USE(JSVALUE64) static ALWAYS_INLINE JSValue makeInt(uint32_t value) -#else - static ALWAYS_INLINE JSValue makeInt(int32_t value) -#endif { return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber); } -#if USE(JSVALUE64) static ALWAYS_INLINE JSValue makeDouble(double value) { return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset); } -#endif static ALWAYS_INLINE JSValue makeBool(bool b) { @@ -336,12 +305,10 @@ namespace JSC { template<typename T> static JSValue fromNumberOutsideIntegerRange(T); -#if USE(JSVALUE64) static ALWAYS_INLINE double doubleValue(JSValue v) { return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset); } -#endif static ALWAYS_INLINE int32_t intValue(JSValue v) { @@ -371,7 +338,6 @@ namespace JSC { ALWAYS_INLINE JSValue JSImmediate::zeroImmediate() { return makeInt(0); } ALWAYS_INLINE JSValue JSImmediate::oneImmediate() { return makeInt(1); } -#if USE(JSVALUE64) inline bool doubleToBoolean(double value) { return value < 0.0 || value > 0.0; @@ -383,13 +349,6 @@ namespace JSC { return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate() : doubleToBoolean(doubleValue(v)) : v == trueImmediate(); } -#else - ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v) - { - ASSERT(isImmediate(v)); - return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate(); - } -#endif ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue v) { @@ -398,19 +357,11 @@ namespace JSC { return intValue(v); } -#if USE(JSVALUE64) template<typename T> inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T value) { return makeDouble(static_cast<double>(value)); } -#else - template<typename T> - inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T) - { - return JSValue(); - } -#endif ALWAYS_INLINE JSValue JSImmediate::from(char i) { @@ -439,10 +390,6 @@ namespace JSC { ALWAYS_INLINE JSValue JSImmediate::from(int i) { -#if !USE(JSVALUE64) - if ((i < minImmediateInt) | (i > maxImmediateInt)) - return fromNumberOutsideIntegerRange(i); -#endif return makeInt(i); } @@ -505,14 +452,10 @@ namespace JSC { if (isIntegerNumber(v)) return intValue(v); -#if USE(JSVALUE64) if (isNumber(v)) { ASSERT(isDouble(v)); return doubleValue(v); } -#else - ASSERT(!isNumber(v)); -#endif if (rawValue(v) == FullTagTypeUndefined) return nonInlineNaN(); @@ -670,11 +613,7 @@ namespace JSC { static ALWAYS_INLINE JSValue rightShiftImmediateNumbers(JSValue val, JSValue shift) { ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift)); -#if USE(JSVALUE64) return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val)) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f))) | JSImmediate::TagTypeNumber); -#else - return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber); -#endif } static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v) @@ -718,6 +657,6 @@ namespace JSC { } // namespace JSC -#endif // !USE(JSVALUE32_64) +#endif // USE(JSVALUE64) #endif // JSImmediate_h diff --git a/JavaScriptCore/runtime/JSNumberCell.cpp b/JavaScriptCore/runtime/JSNumberCell.cpp index 77388e0..6fa6b2a 100644 --- a/JavaScriptCore/runtime/JSNumberCell.cpp +++ b/JavaScriptCore/runtime/JSNumberCell.cpp @@ -23,75 +23,6 @@ #include "config.h" #include "JSNumberCell.h" -#if USE(JSVALUE32) - -#include "NumberObject.h" -#include "UString.h" - -namespace JSC { - -JSValue JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const -{ - return const_cast<JSNumberCell*>(this); -} - -bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValue& value) -{ - number = m_value; - value = this; - return true; -} - -bool JSNumberCell::toBoolean(ExecState*) const -{ - return m_value < 0.0 || m_value > 0.0; // false for NaN -} - -double JSNumberCell::toNumber(ExecState*) const -{ - return m_value; -} - -UString JSNumberCell::toString(ExecState*) const -{ - return UString::number(m_value); -} - -JSObject* JSNumberCell::toObject(ExecState* exec) const -{ - return constructNumber(exec, const_cast<JSNumberCell*>(this)); -} - -JSObject* JSNumberCell::toThisObject(ExecState* exec) const -{ - return constructNumber(exec, const_cast<JSNumberCell*>(this)); -} - -bool JSNumberCell::getUInt32(uint32_t& uint32) const -{ - uint32 = static_cast<uint32_t>(m_value); - return uint32 == m_value; -} - -JSValue JSNumberCell::getJSNumber() -{ - return this; -} - -JSValue jsNumberCell(ExecState* exec, double d) -{ - return new (exec) JSNumberCell(exec, d); -} - -JSValue jsNumberCell(JSGlobalData* globalData, double d) -{ - return new (globalData) JSNumberCell(globalData, d); -} - -} // namespace JSC - -#else // USE(JSVALUE32) - // Keep our exported symbols lists happy. namespace JSC { @@ -105,4 +36,3 @@ JSValue jsNumberCell(ExecState*, double) } // namespace JSC -#endif // USE(JSVALUE32) diff --git a/JavaScriptCore/runtime/JSNumberCell.h b/JavaScriptCore/runtime/JSNumberCell.h index cdd2d8c..a25c531 100644 --- a/JavaScriptCore/runtime/JSNumberCell.h +++ b/JavaScriptCore/runtime/JSNumberCell.h @@ -35,167 +35,6 @@ namespace JSC { extern const double NaN; extern const double Inf; -#if USE(JSVALUE32) - JSValue jsNumberCell(ExecState*, double); - - class Identifier; - class JSCell; - class JSObject; - class JSString; - class PropertySlot; - - struct ClassInfo; - struct Instruction; - - class JSNumberCell : public JSCell { - friend class JIT; - friend JSValue jsNumberCell(JSGlobalData*, double); - friend JSValue jsNumberCell(ExecState*, double); - - public: - double value() const { return m_value; } - - virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); - virtual bool toBoolean(ExecState*) const; - virtual double toNumber(ExecState*) const; - virtual UString toString(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; - - virtual JSObject* toThisObject(ExecState*) const; - virtual JSValue getJSNumber(); - - void* operator new(size_t size, ExecState* exec) - { - return exec->heap()->allocateNumber(size); - } - - void* operator new(size_t size, JSGlobalData* globalData) - { - return globalData->heap.allocateNumber(size); - } - - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount); } - - private: - JSNumberCell(JSGlobalData* globalData, double value) - : JSCell(globalData->numberStructure.get()) - , m_value(value) - { - } - - JSNumberCell(ExecState* exec, double value) - : JSCell(exec->globalData().numberStructure.get()) - , m_value(value) - { - } - - virtual bool getUInt32(uint32_t&) const; - - double m_value; - }; - - JSValue jsNumberCell(JSGlobalData*, double); - - inline bool isNumberCell(JSValue v) - { - return v.isCell() && v.asCell()->isNumber(); - } - - inline JSNumberCell* asNumberCell(JSValue v) - { - ASSERT(isNumberCell(v)); - return static_cast<JSNumberCell*>(v.asCell()); - } - - ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState* exec, double d) - { - *this = jsNumberCell(exec, d); - } - - inline JSValue::JSValue(ExecState* exec, double d) - { - JSValue v = JSImmediate::from(d); - *this = v ? v : jsNumberCell(exec, d); - } - - inline JSValue::JSValue(ExecState* exec, int i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, i); - } - - inline JSValue::JSValue(ExecState* exec, unsigned i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, i); - } - - inline JSValue::JSValue(ExecState* exec, long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, i); - } - - inline JSValue::JSValue(ExecState* exec, unsigned long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, i); - } - - inline JSValue::JSValue(ExecState* exec, long long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, static_cast<double>(i)); - } - - inline JSValue::JSValue(ExecState* exec, unsigned long long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, static_cast<double>(i)); - } - - inline JSValue::JSValue(JSGlobalData* globalData, double d) - { - JSValue v = JSImmediate::from(d); - *this = v ? v : jsNumberCell(globalData, d); - } - - inline JSValue::JSValue(JSGlobalData* globalData, int i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(globalData, i); - } - - inline JSValue::JSValue(JSGlobalData* globalData, unsigned i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(globalData, i); - } - - inline bool JSValue::isDouble() const - { - return isNumberCell(asValue()); - } - - inline double JSValue::asDouble() const - { - return asNumberCell(asValue())->value(); - } - - inline bool JSValue::isNumber() const - { - return JSImmediate::isNumber(asValue()) || isDouble(); - } - - inline double JSValue::uncheckedGetNumber() const - { - ASSERT(isNumber()); - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asDouble(); - } - -#endif // USE(JSVALUE32) - #if USE(JSVALUE64) ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d) { @@ -295,7 +134,7 @@ namespace JSC { #endif // USE(JSVALUE64) -#if USE(JSVALUE32) || USE(JSVALUE64) +#if USE(JSVALUE64) inline JSValue::JSValue(ExecState*, char i) { @@ -351,7 +190,7 @@ namespace JSC { return true; } -#endif // USE(JSVALUE32) || USE(JSVALUE64) +#endif // USE(JSVALUE64) } // namespace JSC diff --git a/JavaScriptCore/runtime/JSONObject.cpp b/JavaScriptCore/runtime/JSONObject.cpp index ba50721..0794189 100644 --- a/JavaScriptCore/runtime/JSONObject.cpp +++ b/JavaScriptCore/runtime/JSONObject.cpp @@ -34,8 +34,8 @@ #include "LiteralParser.h" #include "Lookup.h" #include "PropertyNameArray.h" -#include "StringBuilder.h" -#include "StringConcatenate.h" +#include "UStringBuilder.h" +#include "UStringConcatenate.h" #include <wtf/MathExtras.h> namespace JSC { @@ -85,7 +85,7 @@ private: JSObject* object() const { return m_object; } - bool appendNextProperty(Stringifier&, StringBuilder&); + bool appendNextProperty(Stringifier&, UStringBuilder&); private: JSObject* const m_object; @@ -98,17 +98,17 @@ private: friend class Holder; - static void appendQuotedString(StringBuilder&, const UString&); + static void appendQuotedString(UStringBuilder&, const UString&); JSValue toJSON(JSValue, const PropertyNameForFunctionCall&); enum StringifyResult { StringifyFailed, StringifySucceeded, StringifyFailedDueToUndefinedValue }; - StringifyResult appendStringifiedValue(StringBuilder&, JSValue, JSObject* holder, const PropertyNameForFunctionCall&); + StringifyResult appendStringifiedValue(UStringBuilder&, JSValue, JSObject* holder, const PropertyNameForFunctionCall&); bool willIndent() const; void indent(); void unindent(); - void startNewLine(StringBuilder&) const; + void startNewLine(UStringBuilder&) const; Stringifier* const m_nextStringifierToMark; ExecState* const m_exec; @@ -270,21 +270,21 @@ JSValue Stringifier::stringify(JSValue value) PropertyNameForFunctionCall emptyPropertyName(m_exec->globalData().propertyNames->emptyIdentifier); object->putDirect(m_exec->globalData().propertyNames->emptyIdentifier, value); - StringBuilder result; + UStringBuilder result; if (appendStringifiedValue(result, value, object, emptyPropertyName) != StringifySucceeded) return jsUndefined(); if (m_exec->hadException()) return jsNull(); - return jsString(m_exec, result.build()); + return jsString(m_exec, result.toUString()); } -void Stringifier::appendQuotedString(StringBuilder& builder, const UString& value) +void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& value) { int length = value.length(); // String length plus 2 for quote marks plus 8 so we can accomodate a few escaped characters. - builder.reserveCapacity(builder.size() + length + 2 + 8); + builder.reserveCapacity(builder.length() + length + 2 + 8); builder.append('"'); @@ -361,7 +361,7 @@ inline JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFunctionC return call(m_exec, object, callType, callData, value, args); } -Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& builder, JSValue value, JSObject* holder, const PropertyNameForFunctionCall& propertyName) +Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder& builder, JSValue value, JSObject* holder, const PropertyNameForFunctionCall& propertyName) { // Call the toJSON function. value = toJSON(value, propertyName); @@ -466,7 +466,7 @@ inline void Stringifier::indent() // Use a single shared string, m_repeatedGap, so we don't keep allocating new ones as we indent and unindent. unsigned newSize = m_indent.length() + m_gap.length(); if (newSize > m_repeatedGap.length()) - m_repeatedGap = makeString(m_repeatedGap, m_gap); + m_repeatedGap = makeUString(m_repeatedGap, m_gap); ASSERT(newSize <= m_repeatedGap.length()); m_indent = m_repeatedGap.substringSharingImpl(0, newSize); } @@ -477,7 +477,7 @@ inline void Stringifier::unindent() m_indent = m_repeatedGap.substringSharingImpl(0, m_indent.length() - m_gap.length()); } -inline void Stringifier::startNewLine(StringBuilder& builder) const +inline void Stringifier::startNewLine(UStringBuilder& builder) const { if (m_gap.isEmpty()) return; @@ -492,7 +492,7 @@ inline Stringifier::Holder::Holder(JSObject* object) { } -bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBuilder& builder) +bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBuilder& builder) { ASSERT(m_index <= m_size); @@ -521,7 +521,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui // Last time through, finish up and return false. if (m_index == m_size) { stringifier.unindent(); - if (m_size && builder[builder.size() - 1] != '{') + if (m_size && builder[builder.length() - 1] != '{') stringifier.startNewLine(builder); builder.append(m_isArray ? ']' : '}'); return false; @@ -562,7 +562,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui if (exec->hadException()) return false; - rollBackPoint = builder.size(); + rollBackPoint = builder.length(); // Append the separator string. if (builder[rollBackPoint - 1] != '{') diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp index cabc428..30e40e4 100644 --- a/JavaScriptCore/runtime/JSObject.cpp +++ b/JavaScriptCore/runtime/JSObject.cpp @@ -43,6 +43,8 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSObject); +const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property."; + static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode) { // Add properties from the static hashtables of properties @@ -114,15 +116,19 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu for (JSObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) { prototype = obj->prototype(); if (prototype.isNull()) { - putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot); + if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } } unsigned attributes; JSCell* specificValue; - if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) + if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) { + if (slot.isStrictMode()) + throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError)); return; + } for (JSObject* obj = this; ; obj = asObject(prototype)) { if (JSValue gs = obj->getDirect(propertyName)) { @@ -151,7 +157,8 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu break; } - putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot); + if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } @@ -489,6 +496,11 @@ JSObject* JSObject::toThisObject(ExecState*) const return const_cast<JSObject*>(this); } +JSValue JSObject::toStrictThisObject(ExecState*) const +{ + return const_cast<JSObject*>(this); +} + JSObject* JSObject::unwrappedObject() { return this; @@ -702,4 +714,9 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName return true; } +JSObject* throwTypeError(ExecState* exec, const UString& message) +{ + return throwError(exec, createTypeError(exec, message)); +} + } // namespace JSC diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h index 4201703..8981469 100644 --- a/JavaScriptCore/runtime/JSObject.h +++ b/JavaScriptCore/runtime/JSObject.h @@ -55,6 +55,9 @@ namespace JSC { class Structure; struct HashTable; + JSObject* throwTypeError(ExecState*, const UString&); + extern const char* StrictModeReadonlyPropertyWriteError; + // ECMA 262-3 8.6.1 // Property attributes enum Attribute { @@ -140,6 +143,7 @@ namespace JSC { virtual JSObject* toObject(ExecState*) const; virtual JSObject* toThisObject(ExecState*) const; + virtual JSValue toStrictThisObject(ExecState*) const; virtual JSObject* unwrappedObject(); bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const; @@ -175,9 +179,9 @@ namespace JSC { bool hasCustomProperties() { return !m_structure->isEmpty(); } bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); } - void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); + bool putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0); - void putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&); + bool putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&); void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0); void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); @@ -205,6 +209,7 @@ namespace JSC { virtual bool isVariableObject() const { return false; } virtual bool isActivationObject() const { return false; } virtual bool isNotAnObjectErrorStub() const { return false; } + virtual bool isStrictModeFunction() const { return false; } virtual ComplType exceptionType() const { return Throw; } @@ -248,9 +253,6 @@ namespace JSC { void getString(ExecState* exec); void isObject(); void isString(); -#if USE(JSVALUE32) - void isNumber(); -#endif ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } @@ -265,8 +267,8 @@ namespace JSC { return reinterpret_cast<JSValue*>(&propertyStorage()[offset]); } - void putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*); - void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); + bool putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*); + bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr = 0); bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); @@ -299,9 +301,7 @@ inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure) ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity); ASSERT(m_structure->isEmpty()); ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); -#if USE(JSVALUE64) || USE(JSVALUE32_64) ASSERT(OBJECT_OFFSETOF(JSObject, m_inlineStorage) % sizeof(double) == 0); -#endif } inline JSObject::~JSObject() @@ -450,7 +450,7 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const return jsUndefined(); } -inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction) +inline bool JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -465,7 +465,8 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) m_structure->despecifyDictionaryFunction(propertyName); if (checkReadOnly && currentAttributes & ReadOnly) - return; + return false; + putDirectOffset(offset, value); // At this point, the objects structure only has a specific value set if previously there // had been one set, and if the new value being specified is the same (otherwise we would @@ -475,7 +476,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // If there was previously a value, and the new value is the same, then we cannot cache. if (!currentSpecificFunction || (specificFunction != currentSpecificFunction)) slot.setExistingProperty(this, offset); - return; + return true; } size_t currentCapacity = m_structure->propertyStorageCapacity(); @@ -488,7 +489,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // See comment on setNewProperty call below. if (!specificFunction) slot.setNewProperty(this, offset); - return; + return true; } size_t offset; @@ -504,7 +505,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // so leave the slot in an uncachable state. if (!specificFunction) slot.setNewProperty(this, offset); - return; + return true; } unsigned currentAttributes; @@ -512,7 +513,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction); if (offset != WTF::notFound) { if (checkReadOnly && currentAttributes & ReadOnly) - return; + return false; // There are three possibilities here: // (1) There is an existing specific value set, and we're overwriting with *the same value*. @@ -527,7 +528,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // case (1) Do the put, then return leaving the slot uncachable. if (specificFunction == currentSpecificFunction) { putDirectOffset(offset, value); - return; + return true; } // case (2) Despecify, fall through to (3). setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName)); @@ -536,7 +537,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // case (3) set the slot, do the put, return. slot.setExistingProperty(this, offset); putDirectOffset(offset, value); - return; + return true; } // If we have a specific function, we may have got to this point if there is @@ -561,14 +562,15 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // so leave the slot in an uncachable state. if (!specificFunction) slot.setNewProperty(this, offset); + return true; } -inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value)); + return putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value)); } inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) @@ -577,12 +579,12 @@ inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi putDirectInternal(propertyName, value, attributes, false, slot, getJSFunction(globalData, value)); } -inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +inline bool JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0); + return putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0); } inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes) @@ -591,9 +593,9 @@ inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, u putDirectInternal(propertyName, value, attributes, false, slot, 0); } -inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +inline bool JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { - putDirectInternal(propertyName, value, 0, false, slot, 0); + return putDirectInternal(propertyName, value, 0, false, slot, 0); } inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) @@ -698,10 +700,11 @@ inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValu asCell()->put(exec, propertyName, value, slot); } -inline void JSValue::putDirect(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +inline void JSValue::putDirect(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(isCell() && isObject()); - asObject(asCell())->putDirect(propertyName, value, slot); + if (!asObject(asCell())->putDirect(propertyName, value, slot) && slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); } inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) @@ -756,6 +759,13 @@ inline JSString* JSValue::toThisJSString(ExecState* exec) const return isString() ? static_cast<JSString*>(asCell()) : jsString(exec, toThisObject(exec)->toString(exec)); } +inline JSValue JSValue::toStrictThisObject(ExecState* exec) const +{ + if (!isObject()) + return *this; + return asObject(asCell())->toStrictThisObject(exec); +} + } // namespace JSC #endif // JSObject_h diff --git a/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/JavaScriptCore/runtime/JSStaticScopeObject.cpp index ad10218..7ab1d1c 100644 --- a/JavaScriptCore/runtime/JSStaticScopeObject.cpp +++ b/JavaScriptCore/runtime/JSStaticScopeObject.cpp @@ -42,6 +42,11 @@ JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const return exec->globalThisValue(); } +JSValue JSStaticScopeObject::toStrictThisObject(ExecState*) const +{ + return jsNull(); +} + void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&) { if (symbolTablePut(propertyName, value)) diff --git a/JavaScriptCore/runtime/JSStaticScopeObject.h b/JavaScriptCore/runtime/JSStaticScopeObject.h index c0519c1..e69356a 100644 --- a/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -53,6 +53,7 @@ namespace JSC{ virtual void markChildren(MarkStack&); bool isDynamicScope(bool& requiresDynamicChecks) const; virtual JSObject* toThisObject(ExecState*) const; + virtual JSValue toStrictThisObject(ExecState*) const; virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes); diff --git a/JavaScriptCore/runtime/JSStringBuilder.h b/JavaScriptCore/runtime/JSStringBuilder.h index 25fe685..49d4a63 100644 --- a/JavaScriptCore/runtime/JSStringBuilder.h +++ b/JavaScriptCore/runtime/JSStringBuilder.h @@ -28,7 +28,7 @@ #include "ExceptionHelpers.h" #include "JSString.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" #include "Vector.h" namespace JSC { @@ -87,7 +87,7 @@ protected: template<typename StringType1, typename StringType2> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2) { - PassRefPtr<StringImpl> result = tryMakeString(string1, string2); + PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -96,7 +96,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3) { - PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3); + PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -105,7 +105,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) { - PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3, string4); + PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -114,7 +114,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) { - PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3, string4, string5); + PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4, string5); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -123,7 +123,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) { - PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3, string4, string5, string6); + PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4, string5, string6); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h index b5834c1..b5dcbec 100644 --- a/JavaScriptCore/runtime/JSValue.h +++ b/JavaScriptCore/runtime/JSValue.h @@ -80,7 +80,7 @@ namespace JSC { public: static EncodedJSValue encode(JSValue value); static JSValue decode(EncodedJSValue ptr); -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) private: static JSValue makeImmediate(intptr_t value); intptr_t immediateValue(); @@ -193,6 +193,7 @@ namespace JSC { bool needsThisConversion() const; JSObject* toThisObject(ExecState*) const; + JSValue toStrictThisObject(ExecState*) const; UString toThisString(ExecState*) const; JSString* toThisJSString(ExecState*) const; diff --git a/JavaScriptCore/runtime/JSZombie.h b/JavaScriptCore/runtime/JSZombie.h index 711f673..da45699 100644 --- a/JavaScriptCore/runtime/JSZombie.h +++ b/JavaScriptCore/runtime/JSZombie.h @@ -60,6 +60,7 @@ public: virtual bool deleteProperty(ExecState*, const Identifier&) { ASSERT_NOT_REACHED(); return false; } virtual bool deleteProperty(ExecState*, unsigned) { ASSERT_NOT_REACHED(); return false; } virtual JSObject* toThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return 0; } + virtual JSValue toStrictThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return JSValue(); } virtual JSValue getJSNumber() { ASSERT_NOT_REACHED(); return jsNull(); } virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&) { ASSERT_NOT_REACHED(); return false; } virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&) { ASSERT_NOT_REACHED(); return false; } diff --git a/JavaScriptCore/runtime/LiteralParser.cpp b/JavaScriptCore/runtime/LiteralParser.cpp index cc33bae..f1df15f 100644 --- a/JavaScriptCore/runtime/LiteralParser.cpp +++ b/JavaScriptCore/runtime/LiteralParser.cpp @@ -29,7 +29,7 @@ #include "JSArray.h" #include "JSString.h" #include "Lexer.h" -#include "StringBuilder.h" +#include "UStringBuilder.h" #include <wtf/ASCIICType.h> #include <wtf/dtoa.h> @@ -135,7 +135,7 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera { ++m_ptr; const UChar* runStart; - StringBuilder builder; + UStringBuilder builder; do { runStart = m_ptr; while (m_ptr < m_end && isSafeStringCharacter<mode>(*m_ptr)) @@ -200,7 +200,7 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera if (m_ptr >= m_end || *m_ptr != '"') return TokError; - token.stringToken = builder.build(); + token.stringToken = builder.toUString(); token.type = TokString; token.end = ++m_ptr; return TokString; diff --git a/JavaScriptCore/runtime/NumberObject.h b/JavaScriptCore/runtime/NumberObject.h index 6c18cdd..e82b593 100644 --- a/JavaScriptCore/runtime/NumberObject.h +++ b/JavaScriptCore/runtime/NumberObject.h @@ -37,11 +37,7 @@ namespace JSC { } protected: -#if USE(JSVALUE32) - static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags; -#else static const unsigned StructureFlags = JSWrapperObject::StructureFlags; -#endif private: virtual const ClassInfo* classInfo() const { return &info; } diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp index e18553b..4a2ca74 100644 --- a/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/JavaScriptCore/runtime/NumberPrototype.cpp @@ -25,10 +25,8 @@ #include "Error.h" #include "JSFunction.h" #include "JSString.h" -#include "JSStringBuilder.h" #include "Operations.h" #include "PrototypeFunction.h" -#include "StringBuilder.h" #include "dtoa.h" #include <wtf/Assertions.h> #include <wtf/DecimalNumber.h> @@ -119,8 +117,8 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec) // Round if the argument is not undefined, always format as exponential. NumberToStringBuffer buffer; unsigned length = isUndefined - ? DecimalNumber(x).toStringExponential(buffer) - : DecimalNumber(x, RoundingSignificantFigures, decimalPlacesInExponent + 1).toStringExponential(buffer); + ? DecimalNumber(x).toStringExponential(buffer, WTF::NumberToStringBufferLength) + : DecimalNumber(x, RoundingSignificantFigures, decimalPlacesInExponent + 1).toStringExponential(buffer, WTF::NumberToStringBufferLength); return JSValue::encode(jsString(exec, UString(buffer, length))); } @@ -156,7 +154,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec) // Convert to decimal with rounding, and format as decimal. NumberToStringBuffer buffer; - unsigned length = DecimalNumber(x, RoundingDecimalPlaces, decimalPlaces).toStringDecimal(buffer); + unsigned length = DecimalNumber(x, RoundingDecimalPlaces, decimalPlaces).toStringDecimal(buffer, WTF::NumberToStringBufferLength); return JSValue::encode(jsString(exec, UString(buffer, length))); } @@ -198,8 +196,8 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec) // 1234 (1.234e+3) requires 4 digits. (See ECMA-262 15.7.4.7.10.c) NumberToStringBuffer buffer; unsigned length = number.exponent() >= -6 && number.exponent() < significantFigures - ? number.toStringDecimal(buffer) - : number.toStringExponential(buffer); + ? number.toStringDecimal(buffer, WTF::NumberToStringBufferLength) + : number.toStringExponential(buffer, WTF::NumberToStringBufferLength); return JSValue::encode(jsString(exec, UString(buffer, length))); } diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h index eed1f16..9226953 100644 --- a/JavaScriptCore/runtime/Operations.h +++ b/JavaScriptCore/runtime/Operations.h @@ -460,7 +460,7 @@ namespace JSC { } } - ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain) + ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain, bool isStrictPut) { ScopeChainIterator iter = scopeChain->begin(); ScopeChainIterator next = iter; @@ -472,7 +472,9 @@ namespace JSC { JSObject* base; while (true) { base = *iter; - if (next == end || base->getPropertySlot(callFrame, property, slot)) + if (next == end) + return isStrictPut ? JSValue() : base; + if (base->getPropertySlot(callFrame, property, slot)) return base; iter = next; diff --git a/JavaScriptCore/runtime/PutPropertySlot.h b/JavaScriptCore/runtime/PutPropertySlot.h index eb8ea8a..4b0b394 100644 --- a/JavaScriptCore/runtime/PutPropertySlot.h +++ b/JavaScriptCore/runtime/PutPropertySlot.h @@ -38,9 +38,10 @@ namespace JSC { public: enum Type { Uncachable, ExistingProperty, NewProperty }; - PutPropertySlot() + PutPropertySlot(bool isStrictMode = false) : m_type(Uncachable) , m_base(0) + , m_isStrictMode(isStrictMode) { } @@ -61,6 +62,7 @@ namespace JSC { Type type() const { return m_type; } JSObject* base() const { return m_base; } + bool isStrictMode() const { return m_isStrictMode; } bool isCacheable() const { return m_type != Uncachable; } size_t cachedOffset() const { ASSERT(isCacheable()); @@ -70,6 +72,7 @@ namespace JSC { Type m_type; JSObject* m_base; size_t m_offset; + bool m_isStrictMode; }; } // namespace JSC diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp index 214e528..b9aa587 100644 --- a/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -35,7 +35,7 @@ #include "RegExpPrototype.h" #include "RegExp.h" #include "RegExpCache.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" #include <wtf/PassOwnPtr.h> namespace JSC { @@ -307,7 +307,7 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args) RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags); if (!regExp->isValid()) - return throwError(exec, createSyntaxError(exec, makeString("Invalid regular expression: ", regExp->errorMessage()))); + return throwError(exec, createSyntaxError(exec, makeUString("Invalid regular expression: ", regExp->errorMessage()))); return new (exec) RegExpObject(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp.release()); } diff --git a/JavaScriptCore/runtime/RegExpObject.cpp b/JavaScriptCore/runtime/RegExpObject.cpp index 4462879..7d14814 100644 --- a/JavaScriptCore/runtime/RegExpObject.cpp +++ b/JavaScriptCore/runtime/RegExpObject.cpp @@ -29,7 +29,7 @@ #include "Lookup.h" #include "RegExpConstructor.h" #include "RegExpPrototype.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" #include <wtf/PassOwnPtr.h> namespace JSC { @@ -146,7 +146,7 @@ bool RegExpObject::match(ExecState* exec) UString input = !exec->argumentCount() ? regExpConstructor->input() : exec->argument(0).toString(exec); if (input.isNull()) { - throwError(exec, createError(exec, makeString("No input to ", toString(exec), "."))); + throwError(exec, createError(exec, makeUString("No input to ", toString(exec), "."))); return false; } diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp index d66f5d7..0a4c8bf 100644 --- a/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -34,6 +34,7 @@ #include "RegExpObject.h" #include "RegExp.h" #include "RegExpCache.h" +#include "UStringConcatenate.h" namespace JSC { @@ -94,7 +95,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec) } if (!regExp->isValid()) - return throwVMError(exec, createSyntaxError(exec, makeString("Invalid regular expression: ", regExp->errorMessage()))); + return throwVMError(exec, createSyntaxError(exec, makeUString("Invalid regular expression: ", regExp->errorMessage()))); asRegExpObject(thisValue)->setRegExp(regExp.release()); asRegExpObject(thisValue)->setLastIndex(0); diff --git a/JavaScriptCore/runtime/StrictEvalActivation.cpp b/JavaScriptCore/runtime/StrictEvalActivation.cpp new file mode 100644 index 0000000..5bb013b --- /dev/null +++ b/JavaScriptCore/runtime/StrictEvalActivation.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 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. 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 INC. 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 "StrictEvalActivation.h" + +namespace JSC { + +StrictEvalActivation::StrictEvalActivation(ExecState* exec) + : JSObject(exec->globalData().strictEvalActivationStructure) +{ +} + +bool StrictEvalActivation::deleteProperty(ExecState*, const Identifier&) +{ + return false; +} + +JSObject* StrictEvalActivation::toThisObject(ExecState* exec) const +{ + return exec->globalThisValue(); +} + +JSValue StrictEvalActivation::toStrictThisObject(ExecState*) const +{ + return jsNull(); +} + +} diff --git a/JavaScriptCore/runtime/StrictEvalActivation.h b/JavaScriptCore/runtime/StrictEvalActivation.h new file mode 100644 index 0000000..1385eec --- /dev/null +++ b/JavaScriptCore/runtime/StrictEvalActivation.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 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. 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 INC. 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 StrictEvalActivation_h +#define StrictEvalActivation_h + +#include "JSObject.h" + +namespace JSC { + +class StrictEvalActivation : public JSObject { +public: + StrictEvalActivation(ExecState*); + virtual bool deleteProperty(ExecState*, const Identifier&); + virtual JSObject* toThisObject(ExecState*) const; + virtual JSValue toStrictThisObject(ExecState*) const; +}; + +} // namespace JSC + +#endif // StrictEvalActivation_h diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp index 91e9b06..37436f9 100644 --- a/JavaScriptCore/runtime/StringPrototype.cpp +++ b/JavaScriptCore/runtime/StringPrototype.cpp @@ -206,7 +206,8 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem substitutedReplacement.append(replacement.characters() + offset, i - offset); i += 1 + advance; offset = i + 1; - substitutedReplacement.append(source.characters() + backrefStart, backrefLength); + if (backrefStart >= 0) + substitutedReplacement.append(source.characters() + backrefStart, backrefLength); } while ((i = replacement.find('$', i + 1)) != notFound); if (replacement.length() - offset) @@ -275,12 +276,16 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J int bufferPos = 0; for (int i = 0; i < maxCount; i++) { if (i < rangeCount) { - StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, substringRanges[i].length); - bufferPos += substringRanges[i].length; + if (int srcLen = substringRanges[i].length) { + StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, srcLen); + bufferPos += srcLen; + } } if (i < separatorCount) { - StringImpl::copyChars(buffer + bufferPos, separators[i].characters(), separators[i].length()); - bufferPos += separators[i].length(); + if (int sepLen = separators[i].length()) { + StringImpl::copyChars(buffer + bufferPos, separators[i].characters(), sepLen); + bufferPos += sepLen; + } } } @@ -302,6 +307,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) if (pattern.inherits(&RegExpObject::info)) { const UString& source = sourceVal->value(exec); + unsigned sourceLen = source.length(); if (exec->hadException()) return JSValue::encode(JSValue()); RegExp* reg = asRegExpObject(pattern)->regExp(); @@ -330,7 +336,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); if (matchIndex < 0) break; - + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); int completeMatchStart = ovector[0]; @@ -347,7 +353,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) cachedCall.setArgument(i++, jsNumber(exec, completeMatchStart)); cachedCall.setArgument(i++, sourceVal); - + cachedCall.setThis(exec->globalThisValue()); JSValue result = cachedCall.call(); if (LIKELY(result.isString())) @@ -363,10 +369,10 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) // special case of empty match if (matchLen == 0) { startPosition++; - if (startPosition > source.length()) + if (startPosition > sourceLen) break; } - } + } } else { do { int matchIndex; @@ -376,16 +382,16 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) if (matchIndex < 0) break; - sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); - if (callType != CallTypeNone) { + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); + int completeMatchStart = ovector[0]; MarkedArgumentBuffer args; for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) { int matchStart = ovector[i * 2]; int matchLen = ovector[i * 2 + 1] - matchStart; - + if (matchStart < 0) args.append(jsUndefined()); else @@ -398,8 +404,17 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec)); if (exec->hadException()) break; - } else - replacements.append(substituteBackreferences(replacementString, source, ovector, reg)); + } else { + int replLen = replacementString.length(); + if (lastIndex < matchIndex || replLen) { + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); + + if (replLen) + replacements.append(substituteBackreferences(replacementString, source, ovector, reg)); + else + replacements.append(UString()); + } + } lastIndex = matchIndex + matchLen; startPosition = lastIndex; @@ -407,7 +422,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) // special case of empty match if (matchLen == 0) { startPosition++; - if (startPosition > source.length()) + if (startPosition > sourceLen) break; } } while (global); @@ -416,8 +431,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) if (!lastIndex && replacements.isEmpty()) return JSValue::encode(sourceVal); - if (static_cast<unsigned>(lastIndex) < source.length()) - sourceRanges.append(StringRange(lastIndex, source.length() - lastIndex)); + if (static_cast<unsigned>(lastIndex) < sourceLen) + sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex)); return JSValue::encode(jsSpliceSubstringsWithSeparators(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size())); } diff --git a/JavaScriptCore/runtime/StringBuilder.h b/JavaScriptCore/runtime/UStringBuilder.h index 27aa57f..31ccf38 100644 --- a/JavaScriptCore/runtime/StringBuilder.h +++ b/JavaScriptCore/runtime/UStringBuilder.h @@ -23,65 +23,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StringBuilder_h -#define StringBuilder_h +#ifndef UStringBuilder_h +#define UStringBuilder_h -#include <wtf/Vector.h> +#include <wtf/text/StringBuilder.h> namespace JSC { -class StringBuilder { +class UStringBuilder : public StringBuilder { public: - void append(const UChar u) - { - buffer.append(u); - } + using StringBuilder::append; + void append(const UString& str) { append(String(str.impl())); } - void append(const char* str) - { - append(str, strlen(str)); - } - - void append(const char* str, size_t len) - { - reserveCapacity(buffer.size() + len); - for (size_t i = 0; i < len; i++) - buffer.append(static_cast<unsigned char>(str[i])); - } - - void append(const UChar* str, size_t len) - { - buffer.append(str, len); - } - - void append(const UString& str) - { - buffer.append(str.characters(), str.length()); - } - - bool isEmpty() { return buffer.isEmpty(); } - void reserveCapacity(size_t newCapacity) - { - if (newCapacity < buffer.capacity()) - return; - buffer.reserveCapacity(std::max(newCapacity, buffer.capacity() + buffer.capacity() / 4 + 1)); - } - void resize(size_t size) { buffer.resize(size); } - size_t size() const { return buffer.size(); } - - UChar operator[](size_t i) const { return buffer.at(i); } - - UString build() - { - buffer.shrinkToFit(); - ASSERT(buffer.data() || !buffer.size()); - return UString::adopt(buffer); - } - -protected: - Vector<UChar, 64> buffer; + UString toUString() { return toString().impl(); } }; -} +} // namespace JSC -#endif +#endif // UStringBuilder_h diff --git a/JavaScriptCore/runtime/UStringConcatenate.h b/JavaScriptCore/runtime/UStringConcatenate.h new file mode 100644 index 0000000..0990c72 --- /dev/null +++ b/JavaScriptCore/runtime/UStringConcatenate.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2010 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 UStringConcatenate_h +#define UStringConcatenate_h + +#include "UString.h" +#include <wtf/text/StringConcatenate.h> + +namespace WTF { + +template<> +class StringTypeAdapter<JSC::UString> { +public: + StringTypeAdapter<JSC::UString>(JSC::UString& string) + : m_data(string.characters()) + , m_length(string.length()) + { + } + + unsigned length() { return m_length; } + + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) + destination[i] = m_data[i]; + } + +private: + const UChar* m_data; + unsigned m_length; +}; + +}; // namespace WTF + +namespace JSC { + +template<typename StringType1, typename StringType2> +UString makeUString(StringType1 string1, StringType2 string2) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5, string6); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5, string6, string7); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +} // namespace JSC + +#endif diff --git a/JavaScriptCore/jsc/CMakeLists.txt b/JavaScriptCore/shell/CMakeLists.txt index 1f529a5..1f529a5 100644 --- a/JavaScriptCore/jsc/CMakeLists.txt +++ b/JavaScriptCore/shell/CMakeLists.txt diff --git a/JavaScriptCore/jsc/CMakeListsEfl.txt b/JavaScriptCore/shell/CMakeListsEfl.txt index 58d44f4..58d44f4 100644 --- a/JavaScriptCore/jsc/CMakeListsEfl.txt +++ b/JavaScriptCore/shell/CMakeListsEfl.txt diff --git a/JavaScriptCore/wscript b/JavaScriptCore/wscript index d85364c..8d7f69c 100644 --- a/JavaScriptCore/wscript +++ b/JavaScriptCore/wscript @@ -75,10 +75,10 @@ def build(bld): install_path = output_dir, ) - # we'll get an error if exceptions are on because of an unwind error when using __try if building_on_win32: - flags = obj.env.CXXFLAGS - flags.remove('/EHsc') - obj.env.CXXFLAGS = flags + myenv = obj.env.copy() + myenv.CXXFLAGS = myenv.CXXFLAGS[:] + myenv.CXXFLAGS.remove('/EHsc') + obj.env = myenv bld.install_files(os.path.join(output_dir, 'JavaScriptCore'), 'API/*.h') diff --git a/JavaScriptCore/wtf/CMakeLists.txt b/JavaScriptCore/wtf/CMakeLists.txt index 896794e..898d19b 100644 --- a/JavaScriptCore/wtf/CMakeLists.txt +++ b/JavaScriptCore/wtf/CMakeLists.txt @@ -2,6 +2,7 @@ SET(WTF_SOURCES Assertions.cpp ByteArray.cpp CurrentTime.cpp + DecimalNumber.cpp FastMalloc.cpp HashTable.cpp MainThread.cpp @@ -16,6 +17,7 @@ SET(WTF_SOURCES text/AtomicString.cpp text/CString.cpp + text/StringBuilder.cpp text/StringImpl.cpp text/StringStatics.cpp text/WTFString.cpp diff --git a/JavaScriptCore/wtf/CMakeListsEfl.txt b/JavaScriptCore/wtf/CMakeListsEfl.txt index 6a714ae..e5d8bd7 100644 --- a/JavaScriptCore/wtf/CMakeListsEfl.txt +++ b/JavaScriptCore/wtf/CMakeListsEfl.txt @@ -1,4 +1,10 @@ -ADD_DEFINITIONS(-DUSE_SYSTEM_MALLOC=1) +IF (ENABLE_FAST_MALLOC) + LIST(APPEND WTF_SOURCES + TCSystemAlloc.cpp + ) +ELSE () + ADD_DEFINITIONS(-DUSE_SYSTEM_MALLOC=1) +ENDIF() LIST(APPEND WTF_SOURCES efl/MainThreadEfl.cpp @@ -16,7 +22,12 @@ IF (ENABLE_GLIB_SUPPORT) ) LIST(APPEND WTF_INCLUDE_DIRECTORIES - ${JAVASCRIPTCORE_DIR}/wtf/gobject + ${Glib_INCLUDE_DIRS} + ${JAVASCRIPTCORE_DIR}/wtf/gobject + ) + + LIST(APPEND WTF_LIBRARIES + ${Glib_LIBRARIES} ) ENDIF () diff --git a/JavaScriptCore/wtf/CurrentTime.h b/JavaScriptCore/wtf/CurrentTime.h index dcb1f6c..7119656 100644 --- a/JavaScriptCore/wtf/CurrentTime.h +++ b/JavaScriptCore/wtf/CurrentTime.h @@ -61,6 +61,7 @@ namespace WTF { } // namespace WTF using WTF::currentTime; +using WTF::currentTimeMS; using WTF::getLocalTime; #endif // CurrentTime_h diff --git a/JavaScriptCore/wtf/DateMath.cpp b/JavaScriptCore/wtf/DateMath.cpp index b9a0207..d005859 100644 --- a/JavaScriptCore/wtf/DateMath.cpp +++ b/JavaScriptCore/wtf/DateMath.cpp @@ -3,6 +3,7 @@ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * Copyright (C) 2009 Google Inc. All rights reserved. * Copyright (C) 2007-2009 Torch Mobile, Inc. + * Copyright (C) 2010 &yet, LLC. (nate@andyet.net) * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. @@ -479,7 +480,7 @@ void initializeDates() equivalentYearForDST(2000); // Need to call once to initialize a static used in this function. } -static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second) +static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, double second) { double days = (day - 32075) + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4) @@ -557,6 +558,162 @@ static bool parseLong(const char* string, char** stopPosition, int base, long* r return true; } +double parseES5DateFromNullTerminatedCharacters(const char* dateString) +{ + // This parses a date of the form defined in ECMA-262-5, section 15.9.1.15 + // (similar to RFC 3339 / ISO 8601: YYYY-MM-DDTHH:mm:ss[.sss]Z). + // In most cases it is intentionally strict (e.g. correct field widths, no stray whitespace). + + static const long daysPerMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + const char* currentPosition = dateString; + char* postParsePosition; + + // This is a bit more lenient on the year string than ES5 specifies: + // instead of restricting to 4 digits (or 6 digits with mandatory +/-), + // it accepts any integer value. Consider this an implementation fallback. + long year; + if (!parseLong(currentPosition, &postParsePosition, 10, &year)) + return NaN; + if (*postParsePosition != '-') + return NaN; + currentPosition = postParsePosition + 1; + + long month; + if (!isASCIIDigit(*currentPosition)) + return NaN; + if (!parseLong(currentPosition, &postParsePosition, 10, &month)) + return NaN; + if (*postParsePosition != '-' || (postParsePosition - currentPosition) != 2) + return NaN; + currentPosition = postParsePosition + 1; + + long day; + if (!isASCIIDigit(*currentPosition)) + return NaN; + if (!parseLong(currentPosition, &postParsePosition, 10, &day)) + return NaN; + if (*postParsePosition != 'T' || (postParsePosition - currentPosition) != 2) + return NaN; + currentPosition = postParsePosition + 1; + + long hours; + if (!isASCIIDigit(*currentPosition)) + return NaN; + if (!parseLong(currentPosition, &postParsePosition, 10, &hours)) + return NaN; + if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2) + return NaN; + currentPosition = postParsePosition + 1; + + long minutes; + if (!isASCIIDigit(*currentPosition)) + return NaN; + if (!parseLong(currentPosition, &postParsePosition, 10, &minutes)) + return NaN; + if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2) + return NaN; + currentPosition = postParsePosition + 1; + + long intSeconds; + if (!isASCIIDigit(*currentPosition)) + return NaN; + if (!parseLong(currentPosition, &postParsePosition, 10, &intSeconds)) + return NaN; + if ((postParsePosition - currentPosition) != 2) + return NaN; + + double seconds = intSeconds; + if (*postParsePosition == '.') { + currentPosition = postParsePosition + 1; + + // In ECMA-262-5 it's a bit unclear if '.' can be present without milliseconds, but + // a reasonable interpretation guided by the given examples and RFC 3339 says "no". + // We check the next character to avoid reading +/- timezone hours after an invalid decimal. + if (!isASCIIDigit(*currentPosition)) + return NaN; + + // We are more lenient than ES5 by accepting more or less than 3 fraction digits. + long fracSeconds; + if (!parseLong(currentPosition, &postParsePosition, 10, &fracSeconds)) + return NaN; + + long numFracDigits = postParsePosition - currentPosition; + seconds += fracSeconds * pow(10.0, static_cast<double>(-numFracDigits)); + } + currentPosition = postParsePosition; + + // A few of these checks could be done inline above, but since many of them are interrelated + // we would be sacrificing readability to "optimize" the (presumably less common) failure path. + if (month < 1 || month > 12) + return NaN; + if (day < 1 || day > daysPerMonth[month - 1]) + return NaN; + if (month == 2 && day > 28 && !isLeapYear(year)) + return NaN; + if (hours < 0 || hours > 24) + return NaN; + if (hours == 24 && (minutes || seconds)) + return NaN; + if (minutes < 0 || minutes > 59) + return NaN; + if (seconds < 0 || seconds >= 61) + return NaN; + if (seconds > 60) { + // Discard leap seconds by clamping to the end of a minute. + seconds = 60; + } + + long timeZoneSeconds = 0; + if (*currentPosition != 'Z') { + bool tzNegative; + if (*currentPosition == '-') + tzNegative = true; + else if (*currentPosition == '+') + tzNegative = false; + else + return NaN; + currentPosition += 1; + + long tzHours; + long tzHoursAbs; + long tzMinutes; + + if (!isASCIIDigit(*currentPosition)) + return NaN; + if (!parseLong(currentPosition, &postParsePosition, 10, &tzHours)) + return NaN; + if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2) + return NaN; + tzHoursAbs = abs(tzHours); + currentPosition = postParsePosition + 1; + + if (!isASCIIDigit(*currentPosition)) + return NaN; + if (!parseLong(currentPosition, &postParsePosition, 10, &tzMinutes)) + return NaN; + if ((postParsePosition - currentPosition) != 2) + return NaN; + currentPosition = postParsePosition; + + if (tzHoursAbs > 24) + return NaN; + if (tzMinutes < 0 || tzMinutes > 59) + return NaN; + + timeZoneSeconds = 60 * (tzMinutes + (60 * tzHoursAbs)); + if (tzNegative) + timeZoneSeconds = -timeZoneSeconds; + } else { + currentPosition += 1; + } + if (*currentPosition) + return NaN; + + double dateSeconds = ymdhmsToSeconds(year, month, day, hours, minutes, seconds) - timeZoneSeconds; + return dateSeconds * msPerSecond; +} + // Odd case where 'exec' is allowed to be 0, to accomodate a caller in WebCore. static double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset) { diff --git a/JavaScriptCore/wtf/DateMath.h b/JavaScriptCore/wtf/DateMath.h index 033d25e..be51947 100644 --- a/JavaScriptCore/wtf/DateMath.h +++ b/JavaScriptCore/wtf/DateMath.h @@ -53,7 +53,8 @@ namespace WTF { void initializeDates(); int equivalentYearForDST(int year); -// Not really math related, but this is currently the only shared place to put these. +// Not really math related, but this is currently the only shared place to put these. +double parseES5DateFromNullTerminatedCharacters(const char* dateString); double parseDateFromNullTerminatedCharacters(const char* dateString); double timeClip(double); @@ -94,6 +95,7 @@ using WTF::msPerDay; using WTF::msPerSecond; using WTF::msToYear; using WTF::secondsPerMinute; +using WTF::parseDateFromNullTerminatedCharacters; #if USE(JSC) namespace JSC { diff --git a/JavaScriptCore/wtf/DecimalNumber.cpp b/JavaScriptCore/wtf/DecimalNumber.cpp new file mode 100644 index 0000000..70304e2 --- /dev/null +++ b/JavaScriptCore/wtf/DecimalNumber.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2010 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 "DecimalNumber.h" +#include <math.h> +#include <wtf/MathExtras.h> +#include <wtf/text/WTFString.h> + +namespace WTF { + +unsigned DecimalNumber::bufferLengthForStringDecimal() const +{ + unsigned length = 0; + // if the exponent is negative the number decimal representation is of the form: + // [<sign>]0.[<zeros>]<significand> + if (m_exponent < 0) { + if (m_sign) + ++length; + length += 2; // for "0." + length += -m_exponent - 1; + length += m_precision; + return length; + } + + unsigned digitsBeforeDecimalPoint = m_exponent + 1; + + // If the precision is <= than the number of digits to get up to the decimal + // point, then there is no fractional part, number is of the form: + // [<sign>]<significand>[<zeros>] + if (m_precision <= digitsBeforeDecimalPoint) { + if (m_sign) + ++length; + length += m_precision; + length += digitsBeforeDecimalPoint - m_precision; + return length; + } + + // If we get here, number starts before the decimal point, and ends after it, + // as such is of the form: + // [<sign>]<significand-begin>.<significand-end> + if (m_sign) + ++length; + length += digitsBeforeDecimalPoint; + ++length; // for decimal point + length += m_precision - digitsBeforeDecimalPoint; + + return length; +} + +unsigned DecimalNumber::bufferLengthForStringExponential() const +{ + unsigned length = 0; + if (m_sign) + ++length; + + // Add the significand + ++length; + + if (m_precision > 1) { + ++length; // for decimal point + length += m_precision - 1; + } + + // Add "e+" or "e-" + length += 2; + + int exponent = (m_exponent >= 0) ? m_exponent : -m_exponent; + + // Add the exponent + if (exponent >= 100) + ++length; + if (exponent >= 10) + ++length; + ++length; + + return length; +} + +unsigned DecimalNumber::toStringDecimal(UChar* buffer, unsigned bufferLength) const +{ + ASSERT_UNUSED(bufferLength, bufferLength >= bufferLengthForStringDecimal()); + + // Should always be at least one digit to add to the string! + ASSERT(m_precision); + UChar* next = buffer; + + // if the exponent is negative the number decimal representation is of the form: + // [<sign>]0.[<zeros>]<significand> + if (m_exponent < 0) { + unsigned zeros = -m_exponent - 1; + + if (m_sign) + *next++ = '-'; + *next++ = '0'; + *next++ = '.'; + for (unsigned i = 0; i < zeros; ++i) + *next++ = '0'; + for (unsigned i = 0; i < m_precision; ++i) + *next++ = m_significand[i]; + + return next - buffer; + } + + unsigned digitsBeforeDecimalPoint = m_exponent + 1; + + // If the precision is <= than the number of digits to get up to the decimal + // point, then there is no fractional part, number is of the form: + // [<sign>]<significand>[<zeros>] + if (m_precision <= digitsBeforeDecimalPoint) { + if (m_sign) + *next++ = '-'; + for (unsigned i = 0; i < m_precision; ++i) + *next++ = m_significand[i]; + for (unsigned i = 0; i < (digitsBeforeDecimalPoint - m_precision); ++i) + *next++ = '0'; + + return next - buffer; + } + + // If we get here, number starts before the decimal point, and ends after it, + // as such is of the form: + // [<sign>]<significand-begin>.<significand-end> + + if (m_sign) + *next++ = '-'; + for (unsigned i = 0; i < digitsBeforeDecimalPoint; ++i) + *next++ = m_significand[i]; + *next++ = '.'; + for (unsigned i = digitsBeforeDecimalPoint; i < m_precision; ++i) + *next++ = m_significand[i]; + + return next - buffer; +} + +unsigned DecimalNumber::toStringExponential(UChar* buffer, unsigned bufferLength) const +{ + ASSERT_UNUSED(bufferLength, bufferLength >= bufferLengthForStringExponential()); + + // Should always be at least one digit to add to the string! + ASSERT(m_precision); + UChar* next = buffer; + + // Add the sign + if (m_sign) + *next++ = '-'; + + // Add the significand + *next++ = m_significand[0]; + if (m_precision > 1) { + *next++ = '.'; + for (unsigned i = 1; i < m_precision; ++i) + *next++ = m_significand[i]; + } + + // Add "e+" or "e-" + *next++ = 'e'; + int exponent; + if (m_exponent >= 0) { + *next++ = '+'; + exponent = m_exponent; + } else { + *next++ = '-'; + exponent = -m_exponent; + } + + // Add the exponent + if (exponent >= 100) + *next++ = '0' + exponent / 100; + if (exponent >= 10) + *next++ = '0' + (exponent % 100) / 10; + *next++ = '0' + exponent % 10; + + return next - buffer; +} + +} // namespace WTF diff --git a/JavaScriptCore/wtf/DecimalNumber.h b/JavaScriptCore/wtf/DecimalNumber.h index 3a831b7..c42f00b 100644 --- a/JavaScriptCore/wtf/DecimalNumber.h +++ b/JavaScriptCore/wtf/DecimalNumber.h @@ -81,104 +81,16 @@ public: ASSERT(m_significand[0] != '0' || !m_exponent); } - unsigned toStringDecimal(NumberToStringBuffer buffer) - { - // Should always be at least one digit to add to the string! - ASSERT(m_precision); - UChar* next = buffer; - - // if the exponent is negative the number decimal representation is of the form: - // [<sign>]0.[<zeros>]<significand> - if (m_exponent < 0) { - unsigned zeros = -m_exponent - 1; - - if (m_sign) - *next++ = '-'; - *next++ = '0'; - *next++ = '.'; - for (unsigned i = 0; i < zeros; ++i) - *next++ = '0'; - for (unsigned i = 0; i < m_precision; ++i) - *next++ = m_significand[i]; - - return next - buffer; - } - - unsigned digitsBeforeDecimalPoint = m_exponent + 1; - - // If the precision is <= than the number of digits to get up to the decimal - // point, then there is no fractional part, number is of the form: - // [<sign>]<significand>[<zeros>] - if (m_precision <= digitsBeforeDecimalPoint) { - if (m_sign) - *next++ = '-'; - for (unsigned i = 0; i < m_precision; ++i) - *next++ = m_significand[i]; - for (unsigned i = 0; i < (digitsBeforeDecimalPoint - m_precision); ++i) - *next++ = '0'; - - return next - buffer; - } - - // If we get here, number starts before the decimal point, and ends after it, - // as such is of the form: - // [<sign>]<significand-begin>.<significand-end> - - if (m_sign) - *next++ = '-'; - for (unsigned i = 0; i < digitsBeforeDecimalPoint; ++i) - *next++ = m_significand[i]; - *next++ = '.'; - for (unsigned i = digitsBeforeDecimalPoint; i < m_precision; ++i) - *next++ = m_significand[i]; - - return next - buffer; - } + unsigned bufferLengthForStringDecimal() const; + unsigned bufferLengthForStringExponential() const; - unsigned toStringExponential(NumberToStringBuffer buffer) - { - // Should always be at least one digit to add to the string! - ASSERT(m_precision); - - UChar* next = buffer; - - // Add the sign - if (m_sign) - *next++ = '-'; - - // Add the significand - *next++ = m_significand[0]; - if (m_precision > 1) { - *next++ = '.'; - for (unsigned i = 1; i < m_precision; ++i) - *next++ = m_significand[i]; - } - - // Add "e+" or "e-" - *next++ = 'e'; - int exponent; - if (m_exponent >= 0) { - *next++ = '+'; - exponent = m_exponent; - } else { - *next++ = '-'; - exponent = -m_exponent; - } - - // Add the exponent - if (exponent >= 100) - *next++ = '0' + exponent / 100; - if (exponent >= 10) - *next++ = '0' + (exponent % 100) / 10; - *next++ = '0' + exponent % 10; - - return next - buffer; - } + unsigned toStringDecimal(UChar* buffer, unsigned bufferLength) const; + unsigned toStringExponential(UChar* buffer, unsigned bufferLength) const; - bool sign() { return m_sign; } - int exponent() { return m_exponent; } - const char* significand() { return m_significand; } // significand contains precision characters, is not null-terminated. - unsigned precision() { return m_precision; } + bool sign() const { return m_sign; } + int exponent() const { return m_exponent; } + const char* significand() const { return m_significand; } // significand contains precision characters, is not null-terminated. + unsigned precision() const { return m_precision; } private: bool m_sign; diff --git a/JavaScriptCore/wtf/FastAllocBase.h b/JavaScriptCore/wtf/FastAllocBase.h index 81b1de0..bb1825e 100644 --- a/JavaScriptCore/wtf/FastAllocBase.h +++ b/JavaScriptCore/wtf/FastAllocBase.h @@ -85,38 +85,41 @@ namespace WTF { - class FastAllocBase { - public: - // Placement operator new. - void* operator new(size_t, void* p) { return p; } - void* operator new[](size_t, void* p) { return p; } - - void* operator new(size_t size) - { - void* p = fastMalloc(size); - fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNew); - return p; - } - - void operator delete(void* p) - { - fastMallocMatchValidateFree(p, Internal::AllocTypeClassNew); - fastFree(p); - } - - void* operator new[](size_t size) - { - void* p = fastMalloc(size); - fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNewArray); - return p; - } - - void operator delete[](void* p) - { - fastMallocMatchValidateFree(p, Internal::AllocTypeClassNewArray); - fastFree(p); - } - }; +#define WTF_MAKE_FAST_ALLOCATED \ +public: \ + void* operator new(size_t, void* p) { return p; } \ + void* operator new[](size_t, void* p) { return p; } \ + \ + void* operator new(size_t size) \ + { \ + void* p = ::WTF::fastMalloc(size); \ + ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNew); \ + return p; \ + } \ + \ + void operator delete(void* p) \ + { \ + ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNew); \ + ::WTF::fastFree(p); \ + } \ + \ + void* operator new[](size_t size) \ + { \ + void* p = ::WTF::fastMalloc(size); \ + ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNewArray); \ + return p; \ + } \ + \ + void operator delete[](void* p) \ + { \ + ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNewArray); \ + ::WTF::fastFree(p); \ + } \ +private: + +class FastAllocBase { + WTF_MAKE_FAST_ALLOCATED +}; // fastNew / fastDelete diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp index 1e537b9..bbbdaf2 100644 --- a/JavaScriptCore/wtf/FastMalloc.cpp +++ b/JavaScriptCore/wtf/FastMalloc.cpp @@ -2185,10 +2185,10 @@ class TCMalloc_ThreadCache { // Total byte size in cache size_t Size() const { return size_; } - void* Allocate(size_t size); + ALWAYS_INLINE void* Allocate(size_t size); void Deallocate(void* ptr, size_t size_class); - void FetchFromCentralCache(size_t cl, size_t allocationSize); + ALWAYS_INLINE void FetchFromCentralCache(size_t cl, size_t allocationSize); void ReleaseToCentralCache(size_t cl, int N); void Scavenge(); void Print() const; @@ -2289,12 +2289,12 @@ class TCMalloc_Central_FreeList { // REQUIRES: lock_ is held // Release an object to spans. // May temporarily release lock_. - void ReleaseToSpans(void* object); + ALWAYS_INLINE void ReleaseToSpans(void* object); // REQUIRES: lock_ is held // Populate cache by fetching from the page heap. // May temporarily release lock_. - void Populate(); + ALWAYS_INLINE void Populate(); // REQUIRES: lock is held. // Tries to make room for a TCEntry. If the cache is full it will try to @@ -2307,7 +2307,7 @@ class TCMalloc_Central_FreeList { // just iterates over the sizeclasses but does so without taking a lock. // Returns true on success. // May temporarily lock a "random" size class. - static bool EvictRandomSizeClass(size_t locked_size_class, bool force); + static ALWAYS_INLINE bool EvictRandomSizeClass(size_t locked_size_class, bool force); // REQUIRES: lock_ is *not* held. // Tries to shrink the Cache. If force is true it will relase objects to @@ -3705,7 +3705,7 @@ extern "C" #define do_malloc do_malloc<crashOnFailure> template <bool crashOnFailure> -void* malloc(size_t); +ALWAYS_INLINE void* malloc(size_t); void* fastMalloc(size_t size) { @@ -3766,7 +3766,7 @@ void free(void* ptr) { extern "C" #else template <bool crashOnFailure> -void* calloc(size_t, size_t); +ALWAYS_INLINE void* calloc(size_t, size_t); void* fastCalloc(size_t n, size_t elem_size) { @@ -3830,7 +3830,7 @@ void cfree(void* ptr) { extern "C" #else template <bool crashOnFailure> -void* realloc(void*, size_t); +ALWAYS_INLINE void* realloc(void*, size_t); void* fastRealloc(void* old_ptr, size_t new_size) { diff --git a/JavaScriptCore/wtf/MD5.cpp b/JavaScriptCore/wtf/MD5.cpp index 375446e..c926a7b 100644 --- a/JavaScriptCore/wtf/MD5.cpp +++ b/JavaScriptCore/wtf/MD5.cpp @@ -76,7 +76,7 @@ static void expectMD5(CString input, CString expected) snprintf(buf, 3, "%02x", digest.at(i)); buf += 2; } - ASSERT_WITH_MESSAGE(actual == expected, "input:%s[%d] actual:%s expected:%s", input.data(), input.length(), actual.data(), expected.data()); + ASSERT_WITH_MESSAGE(actual == expected, "input:%s[%lu] actual:%s expected:%s", input.data(), static_cast<unsigned long>(input.length()), actual.data(), expected.data()); } static void testMD5() diff --git a/JavaScriptCore/wtf/Noncopyable.h b/JavaScriptCore/wtf/Noncopyable.h index 898c1ba..285ed2e 100644 --- a/JavaScriptCore/wtf/Noncopyable.h +++ b/JavaScriptCore/wtf/Noncopyable.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006, 2010 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 diff --git a/JavaScriptCore/wtf/NullPtr.h b/JavaScriptCore/wtf/NullPtr.h new file mode 100644 index 0000000..10a5814 --- /dev/null +++ b/JavaScriptCore/wtf/NullPtr.h @@ -0,0 +1,48 @@ +/* + +Copyright (C) 2010 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. 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 INC. 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 NullPtr_h +#define NullPtr_h + +// For compilers and standard libraries that do not yet include it, this adds the +// nullptr_t type and nullptr object. They are defined in the same namespaces they +// would be in compiler and library that had the support. + +#ifndef __has_feature + #define __has_feature(feature) 0 +#endif + +#if !__has_feature(cxx_nullptr) + +namespace std { + class nullptr_t { }; +} + +extern std::nullptr_t nullptr; + +#endif + +#endif diff --git a/JavaScriptCore/wtf/OwnArrayPtr.h b/JavaScriptCore/wtf/OwnArrayPtr.h index ce056b3..643b90b 100644 --- a/JavaScriptCore/wtf/OwnArrayPtr.h +++ b/JavaScriptCore/wtf/OwnArrayPtr.h @@ -23,6 +23,7 @@ #include "Assertions.h" #include "Noncopyable.h" +#include "NullPtr.h" #include "OwnArrayPtrCommon.h" #include <algorithm> @@ -73,6 +74,7 @@ public: #endif OwnArrayPtr& operator=(const PassOwnArrayPtr<T>&); + OwnArrayPtr& operator=(std::nullptr_t) { clear(); return *this; } template<typename U> OwnArrayPtr& operator=(const PassOwnArrayPtr<U>&); void swap(OwnArrayPtr& o) { std::swap(m_ptr, o.m_ptr); } diff --git a/JavaScriptCore/wtf/OwnPtr.h b/JavaScriptCore/wtf/OwnPtr.h index cadfad2..cdc277c 100644 --- a/JavaScriptCore/wtf/OwnPtr.h +++ b/JavaScriptCore/wtf/OwnPtr.h @@ -23,6 +23,7 @@ #include "Assertions.h" #include "Noncopyable.h" +#include "NullPtr.h" #include "OwnPtrCommon.h" #include "TypeTraits.h" #include <algorithm> @@ -72,6 +73,7 @@ namespace WTF { operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; } OwnPtr& operator=(const PassOwnPtr<T>&); + OwnPtr& operator=(std::nullptr_t) { clear(); return *this; } template<typename U> OwnPtr& operator=(const PassOwnPtr<U>&); void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); } diff --git a/JavaScriptCore/wtf/PassOwnArrayPtr.h b/JavaScriptCore/wtf/PassOwnArrayPtr.h index 597339c..6a55491 100644 --- a/JavaScriptCore/wtf/PassOwnArrayPtr.h +++ b/JavaScriptCore/wtf/PassOwnArrayPtr.h @@ -27,6 +27,7 @@ #define WTF_PassOwnArrayPtr_h #include "Assertions.h" +#include "NullPtr.h" #include "OwnArrayPtrCommon.h" #include "TypeTraits.h" @@ -72,6 +73,7 @@ public: #endif PassOwnArrayPtr& operator=(const PassOwnArrayPtr<T>&); + PassOwnArrayPtr& operator=(std::nullptr_t) { clear(); return *this; } template<typename U> PassOwnArrayPtr& operator=(const PassOwnArrayPtr<U>&); template<typename U> friend PassOwnArrayPtr<U> adoptArrayPtr(U*); diff --git a/JavaScriptCore/wtf/PassOwnPtr.h b/JavaScriptCore/wtf/PassOwnPtr.h index a223fa9..60453fc 100644 --- a/JavaScriptCore/wtf/PassOwnPtr.h +++ b/JavaScriptCore/wtf/PassOwnPtr.h @@ -27,6 +27,7 @@ #define WTF_PassOwnPtr_h #include "Assertions.h" +#include "NullPtr.h" #include "OwnPtrCommon.h" #include "TypeTraits.h" @@ -71,6 +72,7 @@ namespace WTF { operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; } PassOwnPtr& operator=(const PassOwnPtr<T>&); + PassOwnPtr& operator=(std::nullptr_t) { clear(); return *this; } template<typename U> PassOwnPtr& operator=(const PassOwnPtr<U>&); template<typename U> friend PassOwnPtr<U> adoptPtr(U*); diff --git a/JavaScriptCore/wtf/PassRefPtr.h b/JavaScriptCore/wtf/PassRefPtr.h index 052d6e2..b179cef 100644 --- a/JavaScriptCore/wtf/PassRefPtr.h +++ b/JavaScriptCore/wtf/PassRefPtr.h @@ -22,6 +22,7 @@ #define WTF_PassRefPtr_h #include "AlwaysInline.h" +#include "NullPtr.h" namespace WTF { @@ -90,6 +91,7 @@ namespace WTF { PassRefPtr& operator=(T*); PassRefPtr& operator=(const PassRefPtr&); + PassRefPtr& operator=(std::nullptr_t) { clear(); return *this; } template<typename U> PassRefPtr& operator=(const PassRefPtr<U>&); template<typename U> PassRefPtr& operator=(const RefPtr<U>&); diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h index 1843bea..9895824 100644 --- a/JavaScriptCore/wtf/Platform.h +++ b/JavaScriptCore/wtf/Platform.h @@ -398,7 +398,7 @@ /* OS(NETBSD) - NetBSD */ #if defined(__NetBSD__) -#define WTF_PLATFORM_NETBSD 1 +#define WTF_OS_NETBSD 1 #endif /* OS(OPENBSD) - OpenBSD */ @@ -574,6 +574,8 @@ #define WTF_USE_QT4_UNICODE 1 #elif OS(WINCE) #define WTF_USE_WINCE_UNICODE 1 +#elif PLATFORM(BREWMP) +#define WTF_USE_BREWMP_UNICODE 1 #elif PLATFORM(GTK) /* The GTK+ Unicode backend is configurable */ #else @@ -692,6 +694,10 @@ #define USE_SYSTEM_MALLOC 1 #endif +#if PLATFORM(BREWMP_SIMULATOR) +#define ENABLE_JIT 0 +#endif + #if !defined(HAVE_ACCESSIBILITY) #if PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM) #define HAVE_ACCESSIBILITY 1 @@ -934,19 +940,17 @@ #define ENABLE_FULLSCREEN_API 0 #endif -#if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64) +#if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64) #if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS))) \ || (CPU(IA64) && !CPU(IA64_32)) \ || CPU(ALPHA) \ || CPU(SPARC64) \ || CPU(PPC64) #define WTF_USE_JSVALUE64 1 -#elif CPU(ARM_TRADITIONAL) && COMPILER(MSVC) -#define WTF_USE_JSVALUE32 1 #else #define WTF_USE_JSVALUE32_64 1 #endif -#endif /* !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64) */ +#endif /* !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64) */ #if !defined(ENABLE_REPAINT_THROTTLING) #define ENABLE_REPAINT_THROTTLING 0 @@ -986,10 +990,6 @@ #endif #endif - #if !defined(ENABLE_JIT_OPTIMIZE_NATIVE_CALL) && CPU(X86) && USE(JSVALUE32) - #define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 0 - #endif - #ifndef ENABLE_JIT_OPTIMIZE_CALL #define ENABLE_JIT_OPTIMIZE_CALL 1 #endif diff --git a/JavaScriptCore/wtf/RandomNumber.cpp b/JavaScriptCore/wtf/RandomNumber.cpp index b20652b..7a9b6a8 100644 --- a/JavaScriptCore/wtf/RandomNumber.cpp +++ b/JavaScriptCore/wtf/RandomNumber.cpp @@ -44,6 +44,8 @@ extern "C" { #include <AEEAppGen.h> #include <AEESource.h> #include <AEEStdLib.h> +#include <wtf/brew/RefPtrBrew.h> +#include <wtf/brew/ShellBrew.h> #endif namespace WTF { @@ -97,12 +99,8 @@ double randomNumber() return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53); #elif PLATFORM(BREWMP) uint32_t bits; - ISource* randomSource; - - IShell* shell = reinterpret_cast<AEEApplet*>(GETAPPINSTANCE())->m_pIShell; - ISHELL_CreateInstance(shell, AEECLSID_RANDOM, reinterpret_cast<void**>(&randomSource)); - ISOURCE_Read(randomSource, reinterpret_cast<char*>(&bits), 4); - ISOURCE_Release(randomSource); + PlatformRefPtr<ISource> randomSource = createRefPtrInstance<ISource>(AEECLSID_RANDOM); + ISOURCE_Read(randomSource.get(), reinterpret_cast<char*>(&bits), 4); return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); #else diff --git a/JavaScriptCore/wtf/RandomNumberSeed.h b/JavaScriptCore/wtf/RandomNumberSeed.h index ae414c0..1f1c00e 100644 --- a/JavaScriptCore/wtf/RandomNumberSeed.h +++ b/JavaScriptCore/wtf/RandomNumberSeed.h @@ -64,6 +64,8 @@ inline void initializeRandomNumberGenerator() init_by_array(initializationBuffer, 4); #elif COMPILER(MSVC) && defined(_CRT_RAND_S) // On Windows we use rand_s which initialises itself +#elif PLATFORM(BREWMP) + // On Brew MP we use AEECLSID_RANDOM which initialises itself #elif OS(UNIX) // srandomdev is not guaranteed to exist on linux so we use this poor seed, this should be improved timeval time; diff --git a/JavaScriptCore/wtf/RefPtr.h b/JavaScriptCore/wtf/RefPtr.h index 8bd1ac3..6afa886 100644 --- a/JavaScriptCore/wtf/RefPtr.h +++ b/JavaScriptCore/wtf/RefPtr.h @@ -24,7 +24,6 @@ #define WTF_RefPtr_h #include <algorithm> -#include "AlwaysInline.h" #include "FastAllocBase.h" #include "PassRefPtr.h" @@ -75,6 +74,7 @@ namespace WTF { RefPtr& operator=(T*); RefPtr& operator=(const PassRefPtr<T>&); RefPtr& operator=(const NonNullPassRefPtr<T>&); + RefPtr& operator=(std::nullptr_t) { clear(); return *this; } template<typename U> RefPtr& operator=(const RefPtr<U>&); template<typename U> RefPtr& operator=(const PassRefPtr<U>&); template<typename U> RefPtr& operator=(const NonNullPassRefPtr<U>&); diff --git a/JavaScriptCore/wtf/RetainPtr.h b/JavaScriptCore/wtf/RetainPtr.h index 68b5a04..8a14cfe 100644 --- a/JavaScriptCore/wtf/RetainPtr.h +++ b/JavaScriptCore/wtf/RetainPtr.h @@ -22,6 +22,7 @@ #define RetainPtr_h #include "HashTraits.h" +#include "NullPtr.h" #include "TypeTraits.h" #include <algorithm> #include <CoreFoundation/CoreFoundation.h> @@ -86,6 +87,7 @@ namespace WTF { template<typename U> RetainPtr& operator=(const RetainPtr<U>&); RetainPtr& operator=(PtrType); template<typename U> RetainPtr& operator=(U*); + RetainPtr& operator=(std::nullptr_t) { clear(); return *this; } void adoptCF(PtrType); void adoptNS(PtrType); diff --git a/JavaScriptCore/wtf/StringHashFunctions.h b/JavaScriptCore/wtf/StringHasher.h index 3ad7701..63ce74f 100644 --- a/JavaScriptCore/wtf/StringHashFunctions.h +++ b/JavaScriptCore/wtf/StringHasher.h @@ -18,8 +18,8 @@ * Boston, MA 02110-1301, USA. * */ -#ifndef WTF_StringHashFunctions_h -#define WTF_StringHashFunctions_h +#ifndef WTF_StringHasher_h +#define WTF_StringHasher_h #include <wtf/unicode/Unicode.h> @@ -167,4 +167,4 @@ private: } // namespace WTF -#endif // WTF_StringHashFunctions_h +#endif // WTF_StringHasher_h diff --git a/JavaScriptCore/wtf/TCSpinLock.h b/JavaScriptCore/wtf/TCSpinLock.h index 240b497..81b7d0c 100644 --- a/JavaScriptCore/wtf/TCSpinLock.h +++ b/JavaScriptCore/wtf/TCSpinLock.h @@ -38,8 +38,6 @@ #include <time.h> /* For nanosleep() */ -#include <sched.h> /* For sched_yield() */ - #if HAVE(STDINT_H) #include <stdint.h> #elif HAVE(INTTYPES_H) @@ -53,6 +51,8 @@ #define WIN32_LEAN_AND_MEAN #endif #include <windows.h> +#else +#include <sched.h> /* For sched_yield() */ #endif static void TCMalloc_SlowLock(volatile unsigned int* lockword); @@ -135,7 +135,12 @@ struct TCMalloc_SpinLock { #define SPINLOCK_INITIALIZER { 0 } static void TCMalloc_SlowLock(volatile unsigned int* lockword) { - sched_yield(); // Yield immediately since fast path failed +// Yield immediately since fast path failed +#if OS(WINDOWS) + Sleep(0); +#else + sched_yield(); +#endif while (true) { int r; #if COMPILER(GCC) diff --git a/JavaScriptCore/wtf/TypeTraits.cpp b/JavaScriptCore/wtf/TypeTraits.cpp index a55019b..afeaa5e 100644 --- a/JavaScriptCore/wtf/TypeTraits.cpp +++ b/JavaScriptCore/wtf/TypeTraits.cpp @@ -136,4 +136,7 @@ COMPILE_ASSERT((IsSameType<int, RemovePointer<int>::Type>::value), WTF_Test_Remo COMPILE_ASSERT((IsSameType<int, RemovePointer<int*>::Type>::value), WTF_Test_RemovePointer_int_pointer); COMPILE_ASSERT((!IsSameType<int, RemovePointer<int**>::Type>::value), WTF_Test_RemovePointer_int_pointer_pointer); +COMPILE_ASSERT((IsSameType<int, RemoveReference<int>::Type>::value), WTF_Test_RemoveReference_int); +COMPILE_ASSERT((IsSameType<int, RemoveReference<int&>::Type>::value), WTF_Test_RemoveReference_int_reference); + } // namespace WTF diff --git a/JavaScriptCore/wtf/TypeTraits.h b/JavaScriptCore/wtf/TypeTraits.h index cf9b4af..44103cd 100644 --- a/JavaScriptCore/wtf/TypeTraits.h +++ b/JavaScriptCore/wtf/TypeTraits.h @@ -39,6 +39,7 @@ namespace WTF { // IsSameType<T, U>::value // // RemovePointer<T>::Type + // RemoveReference<T>::Type // RemoveConst<T>::Type // RemoveVolatile<T>::Type // RemoveConstVolatile<T>::Type @@ -170,6 +171,14 @@ namespace WTF { typedef T Type; }; + template <typename T> struct RemoveReference { + typedef T Type; + }; + + template <typename T> struct RemoveReference<T&> { + typedef T Type; + }; + #if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) // GCC's libstdc++ 20070724 and later supports C++ TR1 type_traits in the std namespace. diff --git a/JavaScriptCore/wtf/WTFThreadData.h b/JavaScriptCore/wtf/WTFThreadData.h index 7f91e1a..5019c33 100644 --- a/JavaScriptCore/wtf/WTFThreadData.h +++ b/JavaScriptCore/wtf/WTFThreadData.h @@ -95,12 +95,6 @@ public: } #if USE(JSC) - void initializeIdentifierTable(JSC::IdentifierTable* identifierTable) - { - m_defaultIdentifierTable = identifierTable; - m_currentIdentifierTable = identifierTable; - } - JSC::IdentifierTable* currentIdentifierTable() { return m_currentIdentifierTable; diff --git a/JavaScriptCore/wtf/brew/RefPtrBrew.h b/JavaScriptCore/wtf/brew/RefPtrBrew.h new file mode 100644 index 0000000..7fb0b7c --- /dev/null +++ b/JavaScriptCore/wtf/brew/RefPtrBrew.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2009 Martin Robinson + * Copyright (C) 2010 Company 100, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RefPtrBrew_h +#define RefPtrBrew_h + +#include "AlwaysInline.h" +#include "PlatformRefPtr.h" +#include <AEEIBase.h> +#include <algorithm> + +namespace WTF { + +// All Brew MP classes are derived from either IBase or IQI. +// Technically, IBase and IQI are different types. However, it is +// okay to cast both types to IBase because they have AddRef and Release +// in the same method vtable slots. +template <typename T> inline T* refPlatformPtr(T* ptr) +{ + if (ptr) + IBase_AddRef(reinterpret_cast<IBase*>(ptr)); + return ptr; +} + +template <typename T> inline void derefPlatformPtr(T* ptr) +{ + if (ptr) + IBase_Release(reinterpret_cast<IBase*>(ptr)); +} + +} // namespace WTF + +#endif // RefPtrBrew_h diff --git a/JavaScriptCore/wtf/brew/ShellBrew.h b/JavaScriptCore/wtf/brew/ShellBrew.h index 7416eca..faccc75 100644 --- a/JavaScriptCore/wtf/brew/ShellBrew.h +++ b/JavaScriptCore/wtf/brew/ShellBrew.h @@ -34,6 +34,7 @@ #include <wtf/Assertions.h> #include <wtf/PassOwnPtr.h> +#include <wtf/PlatformRefPtr.h> namespace WTF { @@ -49,8 +50,21 @@ static inline PassOwnPtr<T> createInstance(AEECLSID cls) return instance; } +template <typename T> +static inline PlatformRefPtr<T> createRefPtrInstance(AEECLSID cls) +{ + T* instance = 0; + + IShell* shell = reinterpret_cast<AEEApplet*>(GETAPPINSTANCE())->m_pIShell; + ISHELL_CreateInstance(shell, cls, reinterpret_cast<void**>(&instance)); + ASSERT(instance); + + return adoptPlatformRef(instance); +} + } // namespace WTF using WTF::createInstance; +using WTF::createRefPtrInstance; #endif // ShellBrew_h diff --git a/JavaScriptCore/wtf/dtoa.cpp b/JavaScriptCore/wtf/dtoa.cpp index 298bb27..c89c036 100644 --- a/JavaScriptCore/wtf/dtoa.cpp +++ b/JavaScriptCore/wtf/dtoa.cpp @@ -1824,8 +1824,8 @@ unsigned numberToString(double d, NumberToStringBuffer buffer) // Convert to decimal with rounding. DecimalNumber number(d); return number.exponent() >= -6 && number.exponent() < 21 - ? number.toStringDecimal(buffer) - : number.toStringExponential(buffer); + ? number.toStringDecimal(buffer, NumberToStringBufferLength) + : number.toStringExponential(buffer, NumberToStringBufferLength); } } // namespace WTF diff --git a/JavaScriptCore/wtf/dtoa.h b/JavaScriptCore/wtf/dtoa.h index 7e4fc41..3924a1c 100644 --- a/JavaScriptCore/wtf/dtoa.h +++ b/JavaScriptCore/wtf/dtoa.h @@ -39,7 +39,8 @@ void dtoaRoundSF(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exp void dtoaRoundDP(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision); // Size = 80 for sizeof(DtoaBuffer) + some sign bits, decimal point, 'e', exponent digits. -typedef UChar NumberToStringBuffer[96]; +const unsigned NumberToStringBufferLength = 96; +typedef UChar NumberToStringBuffer[NumberToStringBufferLength]; unsigned numberToString(double, NumberToStringBuffer); } // namespace WTF diff --git a/JavaScriptCore/wtf/text/CString.cpp b/JavaScriptCore/wtf/text/CString.cpp index 7d09f12..c048a1b 100644 --- a/JavaScriptCore/wtf/text/CString.cpp +++ b/JavaScriptCore/wtf/text/CString.cpp @@ -36,12 +36,12 @@ CString::CString(const char* str) init(str, strlen(str)); } -CString::CString(const char* str, unsigned length) +CString::CString(const char* str, size_t length) { init(str, length); } -void CString::init(const char* str, unsigned length) +void CString::init(const char* str, size_t length) { if (!str) return; diff --git a/JavaScriptCore/wtf/text/CString.h b/JavaScriptCore/wtf/text/CString.h index d8250c5..343a7a5 100644 --- a/JavaScriptCore/wtf/text/CString.h +++ b/JavaScriptCore/wtf/text/CString.h @@ -40,8 +40,8 @@ public: private: friend class CString; - static PassRefPtr<CStringBuffer> create(unsigned length) { return adoptRef(new CStringBuffer(length)); } - CStringBuffer(unsigned length) : m_vector(length) { } + static PassRefPtr<CStringBuffer> create(size_t length) { return adoptRef(new CStringBuffer(length)); } + CStringBuffer(size_t length) : m_vector(length) { } char* mutableData() { return m_vector.data(); } Vector<char> m_vector; @@ -53,7 +53,7 @@ class CString { public: CString() { } CString(const char*); - CString(const char*, unsigned length); + CString(const char*, size_t length); CString(CStringBuffer* buffer) : m_buffer(buffer) { } static CString newUninitialized(size_t length, char*& characterBuffer); @@ -62,7 +62,7 @@ public: return m_buffer ? m_buffer->data() : 0; } char* mutableData(); - unsigned length() const + size_t length() const { return m_buffer ? m_buffer->length() - 1 : 0; } @@ -73,7 +73,7 @@ public: private: void copyBufferIfNeeded(); - void init(const char*, unsigned length); + void init(const char*, size_t length); RefPtr<CStringBuffer> m_buffer; }; diff --git a/JavaScriptCore/wtf/text/StringBuffer.h b/JavaScriptCore/wtf/text/StringBuffer.h index c29dd79..a546bf3 100644 --- a/JavaScriptCore/wtf/text/StringBuffer.h +++ b/JavaScriptCore/wtf/text/StringBuffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,6 +32,7 @@ #include <wtf/Assertions.h> #include <wtf/Noncopyable.h> #include <wtf/unicode/Unicode.h> +#include <limits> namespace WTF { @@ -39,9 +40,12 @@ class StringBuffer : public Noncopyable { public: explicit StringBuffer(unsigned length) : m_length(length) - , m_data(static_cast<UChar*>(fastMalloc(length * sizeof(UChar)))) { + if (m_length > std::numeric_limits<unsigned>::max() / sizeof(UChar)) + CRASH(); + m_data = static_cast<UChar*>(fastMalloc(m_length * sizeof(UChar))); } + ~StringBuffer() { fastFree(m_data); @@ -55,8 +59,11 @@ public: void resize(unsigned newLength) { - if (newLength > m_length) + if (newLength > m_length) { + if (newLength > std::numeric_limits<unsigned>::max() / sizeof(UChar)) + CRASH(); m_data = static_cast<UChar*>(fastRealloc(m_data, newLength * sizeof(UChar))); + } m_length = newLength; } @@ -72,8 +79,8 @@ private: UChar* m_data; }; -} +} // namespace WTF using WTF::StringBuffer; -#endif +#endif // StringBuffer_h diff --git a/JavaScriptCore/wtf/text/StringBuilder.cpp b/JavaScriptCore/wtf/text/StringBuilder.cpp new file mode 100644 index 0000000..dfc9ff3 --- /dev/null +++ b/JavaScriptCore/wtf/text/StringBuilder.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2010 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 "StringBuilder.h" + +#include "WTFString.h" + +namespace WTF { + +void StringBuilder::reifyString() +{ + // Check if the string already exists. + if (!m_string.isNull()) { + ASSERT(m_string.length() == m_length); + return; + } + + // Check for empty. + if (!m_length) { + m_string = StringImpl::empty(); + return; + } + + // Must be valid in the buffer, take a substring (unless string fills the buffer). + ASSERT(m_buffer && m_length <= m_buffer->length()); + m_string = (m_length == m_buffer->length()) + ? m_buffer.get() + : StringImpl::create(m_buffer, 0, m_length); +} + +void StringBuilder::resize(unsigned newSize) +{ + // Check newSize < m_length, hence m_length > 0. + ASSERT(newSize <= m_length); + if (newSize == m_length) + return; + ASSERT(m_length); + + // If there is a buffer, we only need to duplicate it if it has more than one ref. + if (m_buffer) { + if (!m_buffer->hasOneRef()) + allocateBuffer(m_buffer->characters(), m_buffer->length()); + m_length = newSize; + m_string = String(); + return; + } + + // Since m_length && !m_buffer, the string must be valid in m_string, and m_string.length() > 0. + ASSERT(!m_string.isEmpty()); + ASSERT(m_length == m_string.length()); + ASSERT(newSize < m_string.length()); + m_length = newSize; + m_string = StringImpl::create(m_string.impl(), 0, newSize); +} + +void StringBuilder::reserveCapacity(unsigned newCapacity) +{ + if (m_buffer) { + // If there is already a buffer, then grow if necessary. + if (newCapacity > m_buffer->length()) + allocateBuffer(m_buffer->characters(), newCapacity); + } else { + // Grow the string, if necessary. + if (newCapacity > m_length) + allocateBuffer(m_string.characters(), newCapacity); + } +} + +// Allocate a new buffer, copying in currentCharacters (these may come from either m_string +// or m_buffer, neither will be reassigned until the copy has completed). +void StringBuilder::allocateBuffer(const UChar* currentCharacters, unsigned requiredLength) +{ + // Copy the existing data into a new buffer, set result to point to the end of the existing data. + RefPtr<StringImpl> buffer = StringImpl::createUninitialized(requiredLength, m_bufferCharacters); + memcpy(m_bufferCharacters, currentCharacters, static_cast<size_t>(m_length) * sizeof(UChar)); // This can't overflow. + + // Update the builder state. + m_buffer = buffer.release(); + m_string = String(); +} + +// Make 'length' additional capacity be available in m_buffer, update m_string & m_length, +// return a pointer to the newly allocated storage. +UChar* StringBuilder::appendUninitialized(unsigned length) +{ + ASSERT(length); + + // Calcuate the new size of the builder after appending. + unsigned requiredLength = length + m_length; + if (requiredLength < length) + CRASH(); + + if (m_buffer) { + // If the buffer is valid it must be at least as long as the current builder contents! + ASSERT(m_buffer->length() >= m_length); + + // Check if the buffer already has sufficient capacity. + if (requiredLength <= m_buffer->length()) { + unsigned currentLength = m_length; + m_string = String(); + m_length = requiredLength; + return m_bufferCharacters + currentLength; + } + + // We need to realloc the buffer. + allocateBuffer(m_buffer->characters(), std::max(requiredLength, m_buffer->length() * 2)); + } else { + ASSERT(m_string.length() == m_length); + allocateBuffer(m_string.characters(), std::max(requiredLength, requiredLength * 2)); + } + + UChar* result = m_bufferCharacters + m_length; + m_length = requiredLength; + return result; +} + +void StringBuilder::append(const UChar* characters, unsigned length) +{ + if (!length) + return; + ASSERT(characters); + + memcpy(appendUninitialized(length), characters, static_cast<size_t>(length) * 2); +} + +void StringBuilder::append(const char* characters, unsigned length) +{ + if (!length) + return; + ASSERT(characters); + + UChar* dest = appendUninitialized(length); + const char* end = characters + length; + while (characters < end) + *(dest++) = *(const unsigned char*)(characters++); +} + +void StringBuilder::shrinkToFit() +{ + // If the buffer is at least 80% full, don't bother copying. Need to tune this heuristic! + if (m_buffer && m_buffer->length() > (m_length + (m_length >> 2))) { + UChar* result; + m_string = StringImpl::createUninitialized(m_length, result); + memcpy(result, m_buffer->characters(), static_cast<size_t>(m_length) * 2); // This can't overflow. + m_buffer = 0; + } +} + +} // namespace WTF diff --git a/JavaScriptCore/wtf/text/StringBuilder.h b/JavaScriptCore/wtf/text/StringBuilder.h new file mode 100644 index 0000000..f10af64 --- /dev/null +++ b/JavaScriptCore/wtf/text/StringBuilder.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2009, 2010 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 StringBuilder_h +#define StringBuilder_h + +#include <wtf/Vector.h> +#include <wtf/text/WTFString.h> + +namespace WTF { + +class StringBuilder { +public: + StringBuilder() + : m_length(0) + { + } + + void append(const UChar*, unsigned); + void append(const char*, unsigned); + + void append(const String& string) + { + // If we're appending to an empty string, and there is not buffer + // (in case reserveCapacity has been called) then just retain the + // string. + if (!m_length && !m_buffer) { + m_string = string; + m_length = string.length(); + return; + } + append(string.characters(), string.length()); + } + + void append(const char* characters) + { + if (characters) + append(characters, strlen(characters)); + } + + void append(UChar c) + { + if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) + m_bufferCharacters[m_length++] = c; + else + append(&c, 1); + } + + void append(char c) + { + if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) + m_bufferCharacters[m_length++] = (unsigned char)c; + else + append(&c, 1); + } + + String toString() + { + if (m_string.isNull()) { + shrinkToFit(); + reifyString(); + } + return m_string; + } + + String toStringPreserveCapacity() + { + if (m_string.isNull()) + reifyString(); + return m_string; + } + + unsigned length() const + { + return m_length; + } + + bool isEmpty() const { return !length(); } + + void reserveCapacity(unsigned newCapacity); + + void resize(unsigned newSize); + + void shrinkToFit(); + + UChar operator[](unsigned i) const + { + ASSERT(i < m_length); + if (!m_string.isNull()) + return m_string[i]; + ASSERT(m_buffer); + return m_buffer->characters()[i]; + } + + void clear() + { + m_length = 0; + m_string = String(); + m_buffer = 0; + } + +private: + void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength); + UChar* appendUninitialized(unsigned length); + void reifyString(); + + unsigned m_length; + String m_string; + RefPtr<StringImpl> m_buffer; + UChar* m_bufferCharacters; +}; + +} // namespace WTF + +using WTF::StringBuilder; + +#endif // StringBuilder_h diff --git a/JavaScriptCore/runtime/StringConcatenate.h b/JavaScriptCore/wtf/text/StringConcatenate.h index 18a52ef..b54a108 100644 --- a/JavaScriptCore/runtime/StringConcatenate.h +++ b/JavaScriptCore/wtf/text/StringConcatenate.h @@ -26,15 +26,45 @@ #ifndef StringConcatenate_h #define StringConcatenate_h -#include "UString.h" +#include <wtf/text/WTFString.h> -namespace JSC { +namespace WTF { template<typename StringType> class StringTypeAdapter { }; template<> +class StringTypeAdapter<char> { +public: + StringTypeAdapter<char>(char buffer) + : m_buffer(buffer) + { + } + + unsigned length() { return 1; } + void writeTo(UChar* destination) { *destination = m_buffer; } + +private: + unsigned char m_buffer; +}; + +template<> +class StringTypeAdapter<UChar> { +public: + StringTypeAdapter<UChar>(UChar buffer) + : m_buffer(buffer) + { + } + + unsigned length() { return 1; } + void writeTo(UChar* destination) { *destination = m_buffer; } + +private: + UChar m_buffer; +}; + +template<> class StringTypeAdapter<char*> { public: StringTypeAdapter<char*>(char* buffer) @@ -79,9 +109,9 @@ private: }; template<> -class StringTypeAdapter<UString> { +class StringTypeAdapter<String> { public: - StringTypeAdapter<UString>(UString& string) + StringTypeAdapter<String>(String& string) : m_data(string.characters()) , m_length(string.length()) { @@ -360,8 +390,15 @@ PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, S return resultImpl; } +// Convenience only. +template<typename StringType1> +String makeString(StringType1 string1) +{ + return String(string1); +} + template<typename StringType1, typename StringType2> -UString makeString(StringType1 string1, StringType2 string2) +String makeString(StringType1 string1, StringType2 string2) { PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2); if (!resultImpl) @@ -370,7 +407,7 @@ UString makeString(StringType1 string1, StringType2 string2) } template<typename StringType1, typename StringType2, typename StringType3> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3) +String makeString(StringType1 string1, StringType2 string2, StringType3 string3) { PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3); if (!resultImpl) @@ -379,7 +416,7 @@ UString makeString(StringType1 string1, StringType2 string2, StringType3 string3 } template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) { PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4); if (!resultImpl) @@ -388,7 +425,7 @@ UString makeString(StringType1 string1, StringType2 string2, StringType3 string3 } template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) { PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5); if (!resultImpl) @@ -397,7 +434,7 @@ UString makeString(StringType1 string1, StringType2 string2, StringType3 string3 } template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) { PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6); if (!resultImpl) @@ -406,7 +443,7 @@ UString makeString(StringType1 string1, StringType2 string2, StringType3 string3 } template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) { PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7); if (!resultImpl) @@ -415,7 +452,7 @@ UString makeString(StringType1 string1, StringType2 string2, StringType3 string3 } template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) { PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); if (!resultImpl) @@ -423,6 +460,8 @@ UString makeString(StringType1 string1, StringType2 string2, StringType3 string3 return resultImpl; } -} // namespace JSC +} // namespace WTF + +using WTF::makeString; #endif diff --git a/JavaScriptCore/wtf/text/StringHash.h b/JavaScriptCore/wtf/text/StringHash.h index bfd05eb..d7aabdb 100644 --- a/JavaScriptCore/wtf/text/StringHash.h +++ b/JavaScriptCore/wtf/text/StringHash.h @@ -26,7 +26,7 @@ #include "WTFString.h" #include <wtf/Forward.h> #include <wtf/HashTraits.h> -#include <wtf/StringHashFunctions.h> +#include <wtf/StringHasher.h> #include <wtf/unicode/Unicode.h> namespace WTF { @@ -97,99 +97,26 @@ namespace WTF { class CaseFoldingHash { public: - // Paul Hsieh's SuperFastHash - // http://www.azillionmonkeys.com/qed/hash.html + template<typename T> static inline UChar foldCase(T ch) + { + return WTF::Unicode::foldCase(ch); + } + static unsigned hash(const UChar* data, unsigned length) { - unsigned l = length; - const UChar* s = data; - uint32_t hash = WTF::stringHashingStartValue; - uint32_t tmp; - - int rem = l & 1; - l >>= 1; - - // Main loop. - for (; l > 0; l--) { - hash += WTF::Unicode::foldCase(s[0]); - tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - s += 2; - hash += hash >> 11; - } - - // Handle end case. - if (rem) { - hash += WTF::Unicode::foldCase(s[0]); - hash ^= hash << 11; - hash += hash >> 17; - } - - // Force "avalanching" of final 127 bits. - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 2; - hash += hash >> 15; - hash ^= hash << 10; - - // This avoids ever returning a hash code of 0, since that is used to - // signal "hash not computed yet", using a value that is likely to be - // effectively the same as 0 when the low bits are masked. - hash |= !hash << 31; - - return hash; + return StringHasher::createHash<UChar, foldCase<UChar> >(data, length); } static unsigned hash(StringImpl* str) { return hash(str->characters(), str->length()); } - - static unsigned hash(const char* str, unsigned length) - { - // This hash is designed to work on 16-bit chunks at a time. But since the normal case - // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they - // were 16-bit chunks, which will give matching results. - unsigned l = length; - const char* s = str; - uint32_t hash = WTF::stringHashingStartValue; - uint32_t tmp; - - int rem = l & 1; - l >>= 1; - - // Main loop - for (; l > 0; l--) { - hash += WTF::Unicode::foldCase(s[0]); - tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - s += 2; - hash += hash >> 11; - } - - // Handle end case - if (rem) { - hash += WTF::Unicode::foldCase(s[0]); - hash ^= hash << 11; - hash += hash >> 17; - } - - // Force "avalanching" of final 127 bits - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 2; - hash += hash >> 15; - hash ^= hash << 10; - - // this avoids ever returning a hash code of 0, since that is used to - // signal "hash not computed yet", using a value that is likely to be - // effectively the same as 0 when the low bits are masked - hash |= !hash << 31; - - return hash; + static unsigned hash(const char* data, unsigned length) + { + return StringHasher::createHash<char, foldCase<char> >(data, length); } - + static bool equal(const StringImpl* a, const StringImpl* b) { if (a == b) diff --git a/JavaScriptCore/wtf/text/StringImpl.cpp b/JavaScriptCore/wtf/text/StringImpl.cpp index 7822c00..e1e08ee 100644 --- a/JavaScriptCore/wtf/text/StringImpl.cpp +++ b/JavaScriptCore/wtf/text/StringImpl.cpp @@ -81,7 +81,7 @@ PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& // Allocate a single buffer large enough to contain the StringImpl // struct as well as the data which it contains. This removes one // heap allocation from this call. - if (length > ((std::numeric_limits<size_t>::max() - sizeof(StringImpl)) / sizeof(UChar))) + if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar))) CRASH(); size_t size = sizeof(StringImpl) + length * sizeof(UChar); StringImpl* string = static_cast<StringImpl*>(fastMalloc(size)); diff --git a/JavaScriptCore/wtf/text/StringImpl.h b/JavaScriptCore/wtf/text/StringImpl.h index 7025d9f..897751d 100644 --- a/JavaScriptCore/wtf/text/StringImpl.h +++ b/JavaScriptCore/wtf/text/StringImpl.h @@ -29,7 +29,7 @@ #include <wtf/Forward.h> #include <wtf/OwnFastMallocPtr.h> #include <wtf/StdLibExtras.h> -#include <wtf/StringHashFunctions.h> +#include <wtf/StringHasher.h> #include <wtf/Vector.h> #include <wtf/text/StringImplBase.h> #include <wtf/unicode/Unicode.h> @@ -165,7 +165,7 @@ public: return empty(); } - if (length > ((std::numeric_limits<size_t>::max() - sizeof(StringImpl)) / sizeof(UChar))) { + if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar))) { output = 0; return 0; } @@ -187,6 +187,8 @@ public: { if (size_t size = vector.size()) { ASSERT(vector.data()); + if (size > std::numeric_limits<unsigned>::max()) + CRASH(); return adoptRef(new StringImpl(vector.releaseBuffer(), size)); } return empty(); diff --git a/JavaScriptCore/wtf/text/WTFString.cpp b/JavaScriptCore/wtf/text/WTFString.cpp index 9b53e81..5161477 100644 --- a/JavaScriptCore/wtf/text/WTFString.cpp +++ b/JavaScriptCore/wtf/text/WTFString.cpp @@ -48,9 +48,12 @@ String::String(const UChar* str) if (!str) return; - int len = 0; + size_t len = 0; while (str[len] != UChar(0)) len++; + + if (len > std::numeric_limits<unsigned>::max()) + CRASH(); m_impl = StringImpl::create(str, len); } @@ -175,6 +178,8 @@ void String::append(const UChar* charactersToAppend, unsigned lengthToAppend) ASSERT(charactersToAppend); UChar* data; + if (lengthToAppend > std::numeric_limits<unsigned>::max() - length()) + CRASH(); RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(length() + lengthToAppend, data); memcpy(data, characters(), length() * sizeof(UChar)); @@ -196,6 +201,8 @@ void String::insert(const UChar* charactersToInsert, unsigned lengthToInsert, un ASSERT(charactersToInsert); UChar* data; + if (lengthToInsert > std::numeric_limits<unsigned>::max() - length()) + CRASH(); RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(length() + lengthToInsert, data); memcpy(data, characters(), position * sizeof(UChar)); @@ -718,6 +725,9 @@ CString String::utf8(bool strict) const String String::fromUTF8(const char* stringStart, size_t length) { + if (length > std::numeric_limits<unsigned>::max()) + CRASH(); + if (!stringStart) return String(); diff --git a/JavaScriptCore/wtf/unicode/Unicode.h b/JavaScriptCore/wtf/unicode/Unicode.h index c755c6c..50524b1 100644 --- a/JavaScriptCore/wtf/unicode/Unicode.h +++ b/JavaScriptCore/wtf/unicode/Unicode.h @@ -33,6 +33,8 @@ #include <wtf/unicode/glib/UnicodeGLib.h> #elif USE(WINCE_UNICODE) #include <wtf/unicode/wince/UnicodeWinCE.h> +#elif USE(BREWMP_UNICODE) +#include <wtf/unicode/brew/UnicodeBrew.h> #else #error "Unknown Unicode implementation" #endif diff --git a/JavaScriptCore/wtf/unicode/brew/UnicodeBrew.cpp b/JavaScriptCore/wtf/unicode/brew/UnicodeBrew.cpp new file mode 100644 index 0000000..8367f17 --- /dev/null +++ b/JavaScriptCore/wtf/unicode/brew/UnicodeBrew.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2006 George Staikos <staikos@kde.org> + * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * Copyright (C) 2010 Company 100, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "UnicodeBrew.h" + +#include <wchar.h> +#include <wctype.h> + +namespace WTF { +namespace Unicode { + +UChar toLower(UChar c) +{ + return towlower(c); +} + +UChar toUpper(UChar c) +{ + return towupper(c); +} + +UChar foldCase(UChar c) +{ + return towlower(c); +} + +bool isPrintableChar(UChar c) +{ + return !!iswprint(c); +} + +bool isUpper(UChar c) +{ + return !!iswupper(c); +} + +bool isLower(UChar c) +{ + return !!iswlower(c); +} + +bool isDigit(UChar c) +{ + return !!iswdigit(c); +} + +bool isPunct(UChar c) +{ + return !!iswpunct(c); +} + +bool isAlphanumeric(UChar c) +{ + return !!iswalnum(c); +} + +int toLower(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError) +{ + const UChar* sourceIterator = source; + const UChar* sourceEnd = source + sourceLength; + UChar* resultIterator = result; + UChar* resultEnd = result + resultLength; + + if (sourceLength <= resultLength) { + while (sourceIterator < sourceEnd) + *resultIterator++ = towlower(*sourceIterator++); + } else { + while (resultIterator < resultEnd) + *resultIterator++ = towlower(*sourceIterator++); + } + + int remainingCharacters = sourceIterator < sourceEnd ? sourceEnd - sourceIterator : 0; + *isError = !!remainingCharacters; + if (resultIterator < resultEnd) + *resultIterator = 0; + + return (resultIterator - result) + remainingCharacters; +} + +int toUpper(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError) +{ + const UChar* sourceIterator = source; + const UChar* sourceEnd = source + sourceLength; + UChar* resultIterator = result; + UChar* resultEnd = result + resultLength; + + if (sourceLength <= resultLength) { + while (sourceIterator < sourceEnd) + *resultIterator++ = towupper(*sourceIterator++); + } else { + while (resultIterator < resultEnd) + *resultIterator++ = towupper(*sourceIterator++); + } + + int remainingCharacters = sourceIterator < sourceEnd ? sourceEnd - sourceIterator : 0; + *isError = !!remainingCharacters; + if (resultIterator < resultEnd) + *resultIterator = 0; + + return (resultIterator - result) + remainingCharacters; +} + +int foldCase(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError) +{ + *isError = false; + if (resultLength < sourceLength) { + *isError = true; + return sourceLength; + } + for (int i = 0; i < sourceLength; ++i) + result[i] = foldCase(source[i]); + return sourceLength; +} + +UChar toTitleCase(UChar c) +{ + return towupper(c); +} + +Direction direction(UChar32 c) +{ + return static_cast<Direction>(ICU::direction(c)); +} + +CharCategory category(unsigned int c) +{ + return static_cast<CharCategory>(TO_MASK((int8_t) ICU::category(c))); +} + +DecompositionType decompositionType(UChar32 c) +{ + return static_cast<DecompositionType>(ICU::decompositionType(c)); +} + +unsigned char combiningClass(UChar32 c) +{ + return ICU::combiningClass(c); +} + +UChar mirroredChar(UChar32 c) +{ + return ICU::mirroredChar(c); +} + +int digitValue(UChar c) +{ + return ICU::digitValue(c); +} + +bool isSpace(UChar c) +{ + return !!iswspace(c); +} + +bool isLetter(UChar c) +{ + return !!iswalpha(c); +} + +} // namespace Unicode +} // namespace WTF diff --git a/JavaScriptCore/wtf/unicode/brew/UnicodeBrew.h b/JavaScriptCore/wtf/unicode/brew/UnicodeBrew.h new file mode 100644 index 0000000..1d7576f --- /dev/null +++ b/JavaScriptCore/wtf/unicode/brew/UnicodeBrew.h @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2006 George Staikos <staikos@kde.org> + * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> + * Copyright (C) 2007 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * Copyright (C) 2010 Company 100, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef UnicodeBrew_h +#define UnicodeBrew_h + +#include "UnicodeFromICU.h" +#include "UnicodeMacrosFromICU.h" + +namespace WTF { +namespace Unicode { + +enum Direction { + LeftToRight = ICU::U_LEFT_TO_RIGHT, + RightToLeft = ICU::U_RIGHT_TO_LEFT, + EuropeanNumber = ICU::U_EUROPEAN_NUMBER, + EuropeanNumberSeparator = ICU::U_EUROPEAN_NUMBER_SEPARATOR, + EuropeanNumberTerminator = ICU::U_EUROPEAN_NUMBER_TERMINATOR, + ArabicNumber = ICU::U_ARABIC_NUMBER, + CommonNumberSeparator = ICU::U_COMMON_NUMBER_SEPARATOR, + BlockSeparator = ICU::U_BLOCK_SEPARATOR, + SegmentSeparator = ICU::U_SEGMENT_SEPARATOR, + WhiteSpaceNeutral = ICU::U_WHITE_SPACE_NEUTRAL, + OtherNeutral = ICU::U_OTHER_NEUTRAL, + LeftToRightEmbedding = ICU::U_LEFT_TO_RIGHT_EMBEDDING, + LeftToRightOverride = ICU::U_LEFT_TO_RIGHT_OVERRIDE, + RightToLeftArabic = ICU::U_RIGHT_TO_LEFT_ARABIC, + RightToLeftEmbedding = ICU::U_RIGHT_TO_LEFT_EMBEDDING, + RightToLeftOverride = ICU::U_RIGHT_TO_LEFT_OVERRIDE, + PopDirectionalFormat = ICU::U_POP_DIRECTIONAL_FORMAT, + NonSpacingMark = ICU::U_DIR_NON_SPACING_MARK, + BoundaryNeutral = ICU::U_BOUNDARY_NEUTRAL +}; + +enum DecompositionType { + DecompositionNone = ICU::U_DT_NONE, + DecompositionCanonical = ICU::U_DT_CANONICAL, + DecompositionCompat = ICU::U_DT_COMPAT, + DecompositionCircle = ICU::U_DT_CIRCLE, + DecompositionFinal = ICU::U_DT_FINAL, + DecompositionFont = ICU::U_DT_FONT, + DecompositionFraction = ICU::U_DT_FRACTION, + DecompositionInitial = ICU::U_DT_INITIAL, + DecompositionIsolated = ICU::U_DT_ISOLATED, + DecompositionMedial = ICU::U_DT_MEDIAL, + DecompositionNarrow = ICU::U_DT_NARROW, + DecompositionNoBreak = ICU::U_DT_NOBREAK, + DecompositionSmall = ICU::U_DT_SMALL, + DecompositionSquare = ICU::U_DT_SQUARE, + DecompositionSub = ICU::U_DT_SUB, + DecompositionSuper = ICU::U_DT_SUPER, + DecompositionVertical = ICU::U_DT_VERTICAL, + DecompositionWide = ICU::U_DT_WIDE, +}; + +enum CharCategory { + NoCategory = 0, + Other_NotAssigned = TO_MASK(ICU::U_GENERAL_OTHER_TYPES), + Letter_Uppercase = TO_MASK(ICU::U_UPPERCASE_LETTER), + Letter_Lowercase = TO_MASK(ICU::U_LOWERCASE_LETTER), + Letter_Titlecase = TO_MASK(ICU::U_TITLECASE_LETTER), + Letter_Modifier = TO_MASK(ICU::U_MODIFIER_LETTER), + Letter_Other = TO_MASK(ICU::U_OTHER_LETTER), + + Mark_NonSpacing = TO_MASK(ICU::U_NON_SPACING_MARK), + Mark_Enclosing = TO_MASK(ICU::U_ENCLOSING_MARK), + Mark_SpacingCombining = TO_MASK(ICU::U_COMBINING_SPACING_MARK), + + Number_DecimalDigit = TO_MASK(ICU::U_DECIMAL_DIGIT_NUMBER), + Number_Letter = TO_MASK(ICU::U_LETTER_NUMBER), + Number_Other = TO_MASK(ICU::U_OTHER_NUMBER), + + Separator_Space = TO_MASK(ICU::U_SPACE_SEPARATOR), + Separator_Line = TO_MASK(ICU::U_LINE_SEPARATOR), + Separator_Paragraph = TO_MASK(ICU::U_PARAGRAPH_SEPARATOR), + + Other_Control = TO_MASK(ICU::U_CONTROL_CHAR), + Other_Format = TO_MASK(ICU::U_FORMAT_CHAR), + Other_PrivateUse = TO_MASK(ICU::U_PRIVATE_USE_CHAR), + Other_Surrogate = TO_MASK(ICU::U_SURROGATE), + + Punctuation_Dash = TO_MASK(ICU::U_DASH_PUNCTUATION), + Punctuation_Open = TO_MASK(ICU::U_START_PUNCTUATION), + Punctuation_Close = TO_MASK(ICU::U_END_PUNCTUATION), + Punctuation_Connector = TO_MASK(ICU::U_CONNECTOR_PUNCTUATION), + Punctuation_Other = TO_MASK(ICU::U_OTHER_PUNCTUATION), + + Symbol_Math = TO_MASK(ICU::U_MATH_SYMBOL), + Symbol_Currency = TO_MASK(ICU::U_CURRENCY_SYMBOL), + Symbol_Modifier = TO_MASK(ICU::U_MODIFIER_SYMBOL), + Symbol_Other = TO_MASK(ICU::U_OTHER_SYMBOL), + + Punctuation_InitialQuote = TO_MASK(ICU::U_INITIAL_PUNCTUATION), + Punctuation_FinalQuote = TO_MASK(ICU::U_FINAL_PUNCTUATION) +}; + +UChar foldCase(UChar); + +int foldCase(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError); + +int toLower(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError); + +UChar toUpper(UChar); +UChar toLower(UChar); + +bool isUpper(UChar); + +int toUpper(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError); + +UChar toTitleCase(UChar); + +inline bool isArabicChar(UChar32 c) +{ + return c >= 0x0600 && c <= 0x06FF; +} + +bool isAlphanumeric(UChar); + +CharCategory category(unsigned int); + +inline bool isSeparatorSpace(UChar c) +{ + return category(c) == Separator_Space; +} + +bool isPrintableChar(UChar); + +bool isDigit(UChar); + +bool isPunct(UChar); + +inline bool hasLineBreakingPropertyComplexContext(UChar32) +{ + // FIXME: implement! + return false; +} + +inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c) +{ + // FIXME + return false; +} + +UChar mirroredChar(UChar32); + +Direction direction(UChar32); + +bool isLower(UChar); + +int digitValue(UChar); + +unsigned char combiningClass(UChar32); + +DecompositionType decompositionType(UChar32); + +inline int umemcasecmp(const UChar* a, const UChar* b, int len) +{ + for (int i = 0; i < len; ++i) { + UChar c1 = foldCase(a[i]); + UChar c2 = foldCase(b[i]); + if (c1 != c2) + return c1 - c2; + } + return 0; +} + +bool isSpace(UChar); +bool isLetter(UChar); + +} // namespace Unicode +} // namespace WTF + +#endif diff --git a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h index 547ed32..eaa7a07 100644 --- a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h +++ b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h @@ -31,6 +31,9 @@ #include <config.h> #include <stdint.h> +#if USE(QT_ICU_TEXT_BREAKING) +#include <unicode/ubrk.h> +#endif QT_BEGIN_NAMESPACE namespace QUnicodeTables { @@ -63,7 +66,10 @@ typedef wchar_t UChar; #else typedef uint16_t UChar; #endif + +#if !USE(QT_ICU_TEXT_BREAKING) typedef uint32_t UChar32; +#endif namespace WTF { namespace Unicode { @@ -150,7 +156,7 @@ enum CharCategory { inline UChar32 toLower(UChar32 ch) { - return QChar::toLower(ch); + return QChar::toLower(uint32_t(ch)); } inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) @@ -206,9 +212,9 @@ inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLen return rindex + needed; } -inline UChar32 toUpper(UChar32 ch) +inline UChar32 toUpper(UChar32 c) { - return QChar::toUpper(ch); + return QChar::toUpper(uint32_t(c)); } inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) @@ -266,12 +272,12 @@ inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLen inline int toTitleCase(UChar32 c) { - return QChar::toTitleCase(c); + return QChar::toTitleCase(uint32_t(c)); } inline UChar32 foldCase(UChar32 c) { - return QChar::toCaseFolded(c); + return QChar::toCaseFolded(uint32_t(c)); } inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) @@ -296,12 +302,12 @@ inline bool isPrintableChar(UChar32 c) { const uint test = U_MASK(QChar::Other_Control) | U_MASK(QChar::Other_NotAssigned); - return !(U_MASK(QChar::category(c)) & test); + return !(U_MASK(QChar::category(uint32_t(c))) & test); } inline bool isSeparatorSpace(UChar32 c) { - return QChar::category(c) == QChar::Separator_Space; + return QChar::category(uint32_t(c)) == QChar::Separator_Space; } inline bool isPunct(UChar32 c) @@ -313,12 +319,12 @@ inline bool isPunct(UChar32 c) U_MASK(QChar::Punctuation_InitialQuote) | U_MASK(QChar::Punctuation_FinalQuote) | U_MASK(QChar::Punctuation_Other); - return U_MASK(QChar::category(c)) & test; + return U_MASK(QChar::category(uint32_t(c))) & test; } inline bool isLower(UChar32 c) { - return QChar::category(c) == QChar::Letter_Lowercase; + return QChar::category(uint32_t(c)) == QChar::Letter_Lowercase; } inline bool hasLineBreakingPropertyComplexContext(UChar32) @@ -329,12 +335,12 @@ inline bool hasLineBreakingPropertyComplexContext(UChar32) inline UChar32 mirroredChar(UChar32 c) { - return QChar::mirroredChar(c); + return QChar::mirroredChar(uint32_t(c)); } inline uint8_t combiningClass(UChar32 c) { - return QChar::combiningClass(c); + return QChar::combiningClass(uint32_t(c)); } inline DecompositionType decompositionType(UChar32 c) @@ -356,12 +362,12 @@ inline int umemcasecmp(const UChar* a, const UChar* b, int len) inline Direction direction(UChar32 c) { - return (Direction)QChar::direction(c); + return (Direction)QChar::direction(uint32_t(c)); } inline CharCategory category(UChar32 c) { - return (CharCategory) U_MASK(QChar::category(c)); + return (CharCategory) U_MASK(QChar::category(uint32_t(c))); } } } diff --git a/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.cpp b/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.cpp index b52b05c..96dac7d 100644 --- a/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.cpp +++ b/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.cpp @@ -27,62 +27,62 @@ namespace WTF { namespace Unicode { -wchar_t toLower(wchar_t c) +UChar toLower(UChar c) { return towlower(c); } -wchar_t toUpper(wchar_t c) +UChar toUpper(UChar c) { return towupper(c); } -wchar_t foldCase(wchar_t c) +UChar foldCase(UChar c) { return towlower(c); } -bool isPrintableChar(wchar_t c) +bool isPrintableChar(UChar c) { return !!iswprint(c); } -bool isSpace(wchar_t c) +bool isSpace(UChar c) { return !!iswspace(c); } -bool isLetter(wchar_t c) +bool isLetter(UChar c) { return !!iswalpha(c); } -bool isUpper(wchar_t c) +bool isUpper(UChar c) { return !!iswupper(c); } -bool isLower(wchar_t c) +bool isLower(UChar c) { return !!iswlower(c); } -bool isDigit(wchar_t c) +bool isDigit(UChar c) { return !!iswdigit(c); } -bool isPunct(wchar_t c) +bool isPunct(UChar c) { return !!iswpunct(c); } -bool isAlphanumeric(wchar_t c) +bool isAlphanumeric(UChar c) { return !!iswalnum(c); } -int toLower(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError) +int toLower(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError) { const UChar* sourceIterator = source; const UChar* sourceEnd = source + sourceLength; @@ -99,14 +99,14 @@ int toLower(wchar_t* result, int resultLength, const wchar_t* source, int source if (sourceIterator < sourceEnd) remainingCharacters += sourceEnd - sourceIterator; - *isError = (remainingCharacters != 0); + *isError = !!remainingCharacters; if (resultIterator < resultEnd) *resultIterator = 0; return (resultIterator - result) + remainingCharacters; } -int toUpper(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError) +int toUpper(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError) { const UChar* sourceIterator = source; const UChar* sourceEnd = source + sourceLength; @@ -123,14 +123,14 @@ int toUpper(wchar_t* result, int resultLength, const wchar_t* source, int source if (sourceIterator < sourceEnd) remainingCharacters += sourceEnd - sourceIterator; - *isError = (remainingCharacters != 0); + *isError = !!remainingCharacters; if (resultIterator < resultEnd) *resultIterator = 0; return (resultIterator - result) + remainingCharacters; } -int foldCase(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError) +int foldCase(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError) { *isError = false; if (resultLength < sourceLength) { @@ -142,7 +142,7 @@ int foldCase(wchar_t* result, int resultLength, const wchar_t* source, int sourc return sourceLength; } -wchar_t toTitleCase(wchar_t c) +UChar toTitleCase(UChar c) { return towupper(c); } @@ -167,12 +167,12 @@ unsigned char combiningClass(UChar32 c) return UnicodeCE::combiningClass(c); } -wchar_t mirroredChar(UChar32 c) +UChar mirroredChar(UChar32 c) { return UnicodeCE::mirroredChar(c); } -int digitValue(wchar_t c) +int digitValue(UChar c) { return UnicodeCE::digitValue(c); } diff --git a/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h b/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h index 8cc9580..2688aa9 100644 --- a/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h +++ b/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h @@ -31,149 +31,147 @@ #define TO_MASK(x) (1 << (x)) namespace WTF { - - namespace Unicode { - - enum Direction { - LeftToRight = UnicodeCE::U_LEFT_TO_RIGHT, - RightToLeft = UnicodeCE::U_RIGHT_TO_LEFT, - EuropeanNumber = UnicodeCE::U_EUROPEAN_NUMBER, - EuropeanNumberSeparator = UnicodeCE::U_EUROPEAN_NUMBER_SEPARATOR, - EuropeanNumberTerminator = UnicodeCE::U_EUROPEAN_NUMBER_TERMINATOR, - ArabicNumber = UnicodeCE::U_ARABIC_NUMBER, - CommonNumberSeparator = UnicodeCE::U_COMMON_NUMBER_SEPARATOR, - BlockSeparator = UnicodeCE::U_BLOCK_SEPARATOR, - SegmentSeparator = UnicodeCE::U_SEGMENT_SEPARATOR, - WhiteSpaceNeutral = UnicodeCE::U_WHITE_SPACE_NEUTRAL, - OtherNeutral = UnicodeCE::U_OTHER_NEUTRAL, - LeftToRightEmbedding = UnicodeCE::U_LEFT_TO_RIGHT_EMBEDDING, - LeftToRightOverride = UnicodeCE::U_LEFT_TO_RIGHT_OVERRIDE, - RightToLeftArabic = UnicodeCE::U_RIGHT_TO_LEFT_ARABIC, - RightToLeftEmbedding = UnicodeCE::U_RIGHT_TO_LEFT_EMBEDDING, - RightToLeftOverride = UnicodeCE::U_RIGHT_TO_LEFT_OVERRIDE, - PopDirectionalFormat = UnicodeCE::U_POP_DIRECTIONAL_FORMAT, - NonSpacingMark = UnicodeCE::U_DIR_NON_SPACING_MARK, - BoundaryNeutral = UnicodeCE::U_BOUNDARY_NEUTRAL - }; - - enum DecompositionType { - DecompositionNone = UnicodeCE::U_DT_NONE, - DecompositionCanonical = UnicodeCE::U_DT_CANONICAL, - DecompositionCompat = UnicodeCE::U_DT_COMPAT, - DecompositionCircle = UnicodeCE::U_DT_CIRCLE, - DecompositionFinal = UnicodeCE::U_DT_FINAL, - DecompositionFont = UnicodeCE::U_DT_FONT, - DecompositionFraction = UnicodeCE::U_DT_FRACTION, - DecompositionInitial = UnicodeCE::U_DT_INITIAL, - DecompositionIsolated = UnicodeCE::U_DT_ISOLATED, - DecompositionMedial = UnicodeCE::U_DT_MEDIAL, - DecompositionNarrow = UnicodeCE::U_DT_NARROW, - DecompositionNoBreak = UnicodeCE::U_DT_NOBREAK, - DecompositionSmall = UnicodeCE::U_DT_SMALL, - DecompositionSquare = UnicodeCE::U_DT_SQUARE, - DecompositionSub = UnicodeCE::U_DT_SUB, - DecompositionSuper = UnicodeCE::U_DT_SUPER, - DecompositionVertical = UnicodeCE::U_DT_VERTICAL, - DecompositionWide = UnicodeCE::U_DT_WIDE, - }; - - enum CharCategory { - NoCategory = 0, - Other_NotAssigned = TO_MASK(UnicodeCE::U_GENERAL_OTHER_TYPES), - Letter_Uppercase = TO_MASK(UnicodeCE::U_UPPERCASE_LETTER), - Letter_Lowercase = TO_MASK(UnicodeCE::U_LOWERCASE_LETTER), - Letter_Titlecase = TO_MASK(UnicodeCE::U_TITLECASE_LETTER), - Letter_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_LETTER), - Letter_Other = TO_MASK(UnicodeCE::U_OTHER_LETTER), - - Mark_NonSpacing = TO_MASK(UnicodeCE::U_NON_SPACING_MARK), - Mark_Enclosing = TO_MASK(UnicodeCE::U_ENCLOSING_MARK), - Mark_SpacingCombining = TO_MASK(UnicodeCE::U_COMBINING_SPACING_MARK), - - Number_DecimalDigit = TO_MASK(UnicodeCE::U_DECIMAL_DIGIT_NUMBER), - Number_Letter = TO_MASK(UnicodeCE::U_LETTER_NUMBER), - Number_Other = TO_MASK(UnicodeCE::U_OTHER_NUMBER), - - Separator_Space = TO_MASK(UnicodeCE::U_SPACE_SEPARATOR), - Separator_Line = TO_MASK(UnicodeCE::U_LINE_SEPARATOR), - Separator_Paragraph = TO_MASK(UnicodeCE::U_PARAGRAPH_SEPARATOR), - - Other_Control = TO_MASK(UnicodeCE::U_CONTROL_CHAR), - Other_Format = TO_MASK(UnicodeCE::U_FORMAT_CHAR), - Other_PrivateUse = TO_MASK(UnicodeCE::U_PRIVATE_USE_CHAR), - Other_Surrogate = TO_MASK(UnicodeCE::U_SURROGATE), - - Punctuation_Dash = TO_MASK(UnicodeCE::U_DASH_PUNCTUATION), - Punctuation_Open = TO_MASK(UnicodeCE::U_START_PUNCTUATION), - Punctuation_Close = TO_MASK(UnicodeCE::U_END_PUNCTUATION), - Punctuation_Connector = TO_MASK(UnicodeCE::U_CONNECTOR_PUNCTUATION), - Punctuation_Other = TO_MASK(UnicodeCE::U_OTHER_PUNCTUATION), - - Symbol_Math = TO_MASK(UnicodeCE::U_MATH_SYMBOL), - Symbol_Currency = TO_MASK(UnicodeCE::U_CURRENCY_SYMBOL), - Symbol_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_SYMBOL), - Symbol_Other = TO_MASK(UnicodeCE::U_OTHER_SYMBOL), - - Punctuation_InitialQuote = TO_MASK(UnicodeCE::U_INITIAL_PUNCTUATION), - Punctuation_FinalQuote = TO_MASK(UnicodeCE::U_FINAL_PUNCTUATION) - }; - - CharCategory category(unsigned int); - - bool isSpace(wchar_t); - bool isLetter(wchar_t); - bool isPrintableChar(wchar_t); - bool isUpper(wchar_t); - bool isLower(wchar_t); - bool isPunct(wchar_t); - bool isDigit(wchar_t); - bool isAlphanumeric(wchar_t); - inline bool isSeparatorSpace(wchar_t c) { return category(c) == Separator_Space; } - inline bool isHighSurrogate(wchar_t c) { return (c & 0xfc00) == 0xd800; } - inline bool isLowSurrogate(wchar_t c) { return (c & 0xfc00) == 0xdc00; } - - wchar_t toLower(wchar_t); - wchar_t toUpper(wchar_t); - wchar_t foldCase(wchar_t); - wchar_t toTitleCase(wchar_t); - int toLower(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError); - int toUpper(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError); - int foldCase(UChar* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError); - - int digitValue(wchar_t); - - wchar_t mirroredChar(UChar32); - unsigned char combiningClass(UChar32); - DecompositionType decompositionType(UChar32); - Direction direction(UChar32); - inline bool isArabicChar(UChar32 c) - { - return c >= 0x0600 && c <= 0x06FF; - } - - inline bool hasLineBreakingPropertyComplexContext(UChar32) - { - return false; // FIXME: implement! - } - - inline int umemcasecmp(const wchar_t* a, const wchar_t* b, int len) - { - for (int i = 0; i < len; ++i) { - wchar_t c1 = foldCase(a[i]); - wchar_t c2 = foldCase(b[i]); - if (c1 != c2) - return c1 - c2; - } - return 0; - } - - inline UChar32 surrogateToUcs4(wchar_t high, wchar_t low) - { - return (UChar32(high) << 10) + low - 0x35fdc00; - } - - } // namespace Unicode - -} // namespace WTF +namespace Unicode { + +enum Direction { + LeftToRight = UnicodeCE::U_LEFT_TO_RIGHT, + RightToLeft = UnicodeCE::U_RIGHT_TO_LEFT, + EuropeanNumber = UnicodeCE::U_EUROPEAN_NUMBER, + EuropeanNumberSeparator = UnicodeCE::U_EUROPEAN_NUMBER_SEPARATOR, + EuropeanNumberTerminator = UnicodeCE::U_EUROPEAN_NUMBER_TERMINATOR, + ArabicNumber = UnicodeCE::U_ARABIC_NUMBER, + CommonNumberSeparator = UnicodeCE::U_COMMON_NUMBER_SEPARATOR, + BlockSeparator = UnicodeCE::U_BLOCK_SEPARATOR, + SegmentSeparator = UnicodeCE::U_SEGMENT_SEPARATOR, + WhiteSpaceNeutral = UnicodeCE::U_WHITE_SPACE_NEUTRAL, + OtherNeutral = UnicodeCE::U_OTHER_NEUTRAL, + LeftToRightEmbedding = UnicodeCE::U_LEFT_TO_RIGHT_EMBEDDING, + LeftToRightOverride = UnicodeCE::U_LEFT_TO_RIGHT_OVERRIDE, + RightToLeftArabic = UnicodeCE::U_RIGHT_TO_LEFT_ARABIC, + RightToLeftEmbedding = UnicodeCE::U_RIGHT_TO_LEFT_EMBEDDING, + RightToLeftOverride = UnicodeCE::U_RIGHT_TO_LEFT_OVERRIDE, + PopDirectionalFormat = UnicodeCE::U_POP_DIRECTIONAL_FORMAT, + NonSpacingMark = UnicodeCE::U_DIR_NON_SPACING_MARK, + BoundaryNeutral = UnicodeCE::U_BOUNDARY_NEUTRAL +}; + +enum DecompositionType { + DecompositionNone = UnicodeCE::U_DT_NONE, + DecompositionCanonical = UnicodeCE::U_DT_CANONICAL, + DecompositionCompat = UnicodeCE::U_DT_COMPAT, + DecompositionCircle = UnicodeCE::U_DT_CIRCLE, + DecompositionFinal = UnicodeCE::U_DT_FINAL, + DecompositionFont = UnicodeCE::U_DT_FONT, + DecompositionFraction = UnicodeCE::U_DT_FRACTION, + DecompositionInitial = UnicodeCE::U_DT_INITIAL, + DecompositionIsolated = UnicodeCE::U_DT_ISOLATED, + DecompositionMedial = UnicodeCE::U_DT_MEDIAL, + DecompositionNarrow = UnicodeCE::U_DT_NARROW, + DecompositionNoBreak = UnicodeCE::U_DT_NOBREAK, + DecompositionSmall = UnicodeCE::U_DT_SMALL, + DecompositionSquare = UnicodeCE::U_DT_SQUARE, + DecompositionSub = UnicodeCE::U_DT_SUB, + DecompositionSuper = UnicodeCE::U_DT_SUPER, + DecompositionVertical = UnicodeCE::U_DT_VERTICAL, + DecompositionWide = UnicodeCE::U_DT_WIDE +}; + +enum CharCategory { + NoCategory = 0, + Other_NotAssigned = TO_MASK(UnicodeCE::U_GENERAL_OTHER_TYPES), + Letter_Uppercase = TO_MASK(UnicodeCE::U_UPPERCASE_LETTER), + Letter_Lowercase = TO_MASK(UnicodeCE::U_LOWERCASE_LETTER), + Letter_Titlecase = TO_MASK(UnicodeCE::U_TITLECASE_LETTER), + Letter_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_LETTER), + Letter_Other = TO_MASK(UnicodeCE::U_OTHER_LETTER), + + Mark_NonSpacing = TO_MASK(UnicodeCE::U_NON_SPACING_MARK), + Mark_Enclosing = TO_MASK(UnicodeCE::U_ENCLOSING_MARK), + Mark_SpacingCombining = TO_MASK(UnicodeCE::U_COMBINING_SPACING_MARK), + + Number_DecimalDigit = TO_MASK(UnicodeCE::U_DECIMAL_DIGIT_NUMBER), + Number_Letter = TO_MASK(UnicodeCE::U_LETTER_NUMBER), + Number_Other = TO_MASK(UnicodeCE::U_OTHER_NUMBER), + + Separator_Space = TO_MASK(UnicodeCE::U_SPACE_SEPARATOR), + Separator_Line = TO_MASK(UnicodeCE::U_LINE_SEPARATOR), + Separator_Paragraph = TO_MASK(UnicodeCE::U_PARAGRAPH_SEPARATOR), + + Other_Control = TO_MASK(UnicodeCE::U_CONTROL_CHAR), + Other_Format = TO_MASK(UnicodeCE::U_FORMAT_CHAR), + Other_PrivateUse = TO_MASK(UnicodeCE::U_PRIVATE_USE_CHAR), + Other_Surrogate = TO_MASK(UnicodeCE::U_SURROGATE), + + Punctuation_Dash = TO_MASK(UnicodeCE::U_DASH_PUNCTUATION), + Punctuation_Open = TO_MASK(UnicodeCE::U_START_PUNCTUATION), + Punctuation_Close = TO_MASK(UnicodeCE::U_END_PUNCTUATION), + Punctuation_Connector = TO_MASK(UnicodeCE::U_CONNECTOR_PUNCTUATION), + Punctuation_Other = TO_MASK(UnicodeCE::U_OTHER_PUNCTUATION), + + Symbol_Math = TO_MASK(UnicodeCE::U_MATH_SYMBOL), + Symbol_Currency = TO_MASK(UnicodeCE::U_CURRENCY_SYMBOL), + Symbol_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_SYMBOL), + Symbol_Other = TO_MASK(UnicodeCE::U_OTHER_SYMBOL), + + Punctuation_InitialQuote = TO_MASK(UnicodeCE::U_INITIAL_PUNCTUATION), + Punctuation_FinalQuote = TO_MASK(UnicodeCE::U_FINAL_PUNCTUATION) +}; + +CharCategory category(unsigned int); + +bool isSpace(UChar); +bool isLetter(UChar); +bool isPrintableChar(UChar); +bool isUpper(UChar); +bool isLower(UChar); +bool isPunct(UChar); +bool isDigit(UChar); +bool isAlphanumeric(UChar); +inline bool isSeparatorSpace(UChar c) { return category(c) == Separator_Space; } +inline bool isHighSurrogate(UChar c) { return (c & 0xfc00) == 0xd800; } +inline bool isLowSurrogate(UChar c) { return (c & 0xfc00) == 0xdc00; } + +UChar toLower(UChar); +UChar toUpper(UChar); +UChar foldCase(UChar); +UChar toTitleCase(UChar); +int toLower(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError); +int toUpper(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError); +int foldCase(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError); + +int digitValue(UChar); + +UChar mirroredChar(UChar32); +unsigned char combiningClass(UChar32); +DecompositionType decompositionType(UChar32); +Direction direction(UChar32); +inline bool isArabicChar(UChar32 c) +{ + return c >= 0x0600 && c <= 0x06FF; +} + +inline bool hasLineBreakingPropertyComplexContext(UChar32) +{ + return false; // FIXME: implement! +} + +inline int umemcasecmp(const UChar* a, const UChar* b, int len) +{ + for (int i = 0; i < len; ++i) { + UChar c1 = foldCase(a[i]); + UChar c2 = foldCase(b[i]); + if (c1 != c2) + return c1 - c2; + } + return 0; +} + +inline UChar32 surrogateToUcs4(UChar high, UChar low) +{ + return (UChar32(high) << 10) + low - 0x35fdc00; +} + +} // namespace Unicode +} // namespace WTF #endif // WTF_UnicodeWinCE_h diff --git a/JavaScriptCore/wtf/url/src/URLCharacterTypes.cpp b/JavaScriptCore/wtf/url/src/URLCharacterTypes.cpp new file mode 100644 index 0000000..ee2014e --- /dev/null +++ b/JavaScriptCore/wtf/url/src/URLCharacterTypes.cpp @@ -0,0 +1,173 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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 "URLCharacterTypes.h" + +namespace WTF { + +const unsigned char URLCharacterTypes::characterTypeTable[0x100] = { + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x00 - 0x0f + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x10 - 0x1f + InvalidCharacter, // 0x20 ' ' (escape spaces in queries) + QueryCharacter | UserInfoCharacter, // 0x21 ! + InvalidCharacter, // 0x22 " + InvalidCharacter, // 0x23 # (invalid in query since it marks the ref) + QueryCharacter | UserInfoCharacter, // 0x24 $ + QueryCharacter | UserInfoCharacter, // 0x25 % + QueryCharacter | UserInfoCharacter, // 0x26 & + QueryCharacter | UserInfoCharacter, // 0x27 ' + QueryCharacter | UserInfoCharacter, // 0x28 ( + QueryCharacter | UserInfoCharacter, // 0x29 ) + QueryCharacter | UserInfoCharacter, // 0x2a * + QueryCharacter | UserInfoCharacter, // 0x2b + + QueryCharacter | UserInfoCharacter, // 0x2c , + QueryCharacter | UserInfoCharacter, // 0x2d - + QueryCharacter | UserInfoCharacter | IPv4Character, // 0x2e . + QueryCharacter, // 0x2f / + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x30 0 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x31 1 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x32 2 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x33 3 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x34 4 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x35 5 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x36 6 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x37 7 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter, // 0x38 8 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter, // 0x39 9 + QueryCharacter, // 0x3a : + QueryCharacter, // 0x3b ; + InvalidCharacter, // 0x3c < + QueryCharacter, // 0x3d = + InvalidCharacter, // 0x3e > + QueryCharacter, // 0x3f ? + QueryCharacter, // 0x40 @ + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x41 A + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x42 B + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x43 C + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x44 D + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x45 E + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x46 F + QueryCharacter | UserInfoCharacter, // 0x47 G + QueryCharacter | UserInfoCharacter, // 0x48 H + QueryCharacter | UserInfoCharacter, // 0x49 I + QueryCharacter | UserInfoCharacter, // 0x4a J + QueryCharacter | UserInfoCharacter, // 0x4b K + QueryCharacter | UserInfoCharacter, // 0x4c L + QueryCharacter | UserInfoCharacter, // 0x4d M + QueryCharacter | UserInfoCharacter, // 0x4e N + QueryCharacter | UserInfoCharacter, // 0x4f O + QueryCharacter | UserInfoCharacter, // 0x50 P + QueryCharacter | UserInfoCharacter, // 0x51 Q + QueryCharacter | UserInfoCharacter, // 0x52 R + QueryCharacter | UserInfoCharacter, // 0x53 S + QueryCharacter | UserInfoCharacter, // 0x54 T + QueryCharacter | UserInfoCharacter, // 0x55 U + QueryCharacter | UserInfoCharacter, // 0x56 V + QueryCharacter | UserInfoCharacter, // 0x57 W + QueryCharacter | UserInfoCharacter | IPv4Character, // 0x58 X + QueryCharacter | UserInfoCharacter, // 0x59 Y + QueryCharacter | UserInfoCharacter, // 0x5a Z + QueryCharacter, // 0x5b [ + QueryCharacter, // 0x5c '\' + QueryCharacter, // 0x5d ] + QueryCharacter, // 0x5e ^ + QueryCharacter | UserInfoCharacter, // 0x5f _ + QueryCharacter, // 0x60 ` + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x61 a + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x62 b + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x63 c + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x64 d + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x65 e + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x66 f + QueryCharacter | UserInfoCharacter, // 0x67 g + QueryCharacter | UserInfoCharacter, // 0x68 h + QueryCharacter | UserInfoCharacter, // 0x69 i + QueryCharacter | UserInfoCharacter, // 0x6a j + QueryCharacter | UserInfoCharacter, // 0x6b k + QueryCharacter | UserInfoCharacter, // 0x6c l + QueryCharacter | UserInfoCharacter, // 0x6d m + QueryCharacter | UserInfoCharacter, // 0x6e n + QueryCharacter | UserInfoCharacter, // 0x6f o + QueryCharacter | UserInfoCharacter, // 0x70 p + QueryCharacter | UserInfoCharacter, // 0x71 q + QueryCharacter | UserInfoCharacter, // 0x72 r + QueryCharacter | UserInfoCharacter, // 0x73 s + QueryCharacter | UserInfoCharacter, // 0x74 t + QueryCharacter | UserInfoCharacter, // 0x75 u + QueryCharacter | UserInfoCharacter, // 0x76 v + QueryCharacter | UserInfoCharacter, // 0x77 w + QueryCharacter | UserInfoCharacter | IPv4Character, // 0x78 x + QueryCharacter | UserInfoCharacter, // 0x79 y + QueryCharacter | UserInfoCharacter, // 0x7a z + QueryCharacter, // 0x7b { + QueryCharacter, // 0x7c | + QueryCharacter, // 0x7d } + QueryCharacter | UserInfoCharacter, // 0x7e ~ + InvalidCharacter, // 0x7f + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x80 - 0x8f + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x90 - 0x9f + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xa0 - 0xaf + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xb0 - 0xbf + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xc0 - 0xcf + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xd0 - 0xdf + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xe0 - 0xef + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xf0 - 0xff +}; + +} diff --git a/JavaScriptCore/wtf/url/src/URLCharacterTypes.h b/JavaScriptCore/wtf/url/src/URLCharacterTypes.h new file mode 100644 index 0000000..194f6b0 --- /dev/null +++ b/JavaScriptCore/wtf/url/src/URLCharacterTypes.h @@ -0,0 +1,61 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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 URLCharacterTypes_h +#define URLCharacterTypes_h + +namespace WTF { + +class URLCharacterTypes { +public: + static inline bool isQueryChar(unsigned char c) { return isCharOfType(c, QueryCharacter); } + static inline bool isIPv4Char(unsigned char c) { return isCharOfType(c, IPv4Character); } + static inline bool isHexChar(unsigned char c) { return isCharOfType(c, HexCharacter); } + +private: + enum CharTypes { + InvalidCharacter = 0, + QueryCharacter = 1 << 0, + UserInfoCharacter = 1 << 1, + IPv4Character = 1 << 2, + HexCharacter = 1 << 3, + DecimalCharacter = 1 << 4, + OctalCharacter = 1 << 5, + }; + + static const unsigned char characterTypeTable[0x100]; + + static inline bool isCharOfType(unsigned char c, CharTypes type) + { + return !!(characterTypeTable[c] & type); + } +}; + +} + +#endif diff --git a/JavaScriptCore/wtf/url/src/URLEscape.cpp b/JavaScriptCore/wtf/url/src/URLEscape.cpp new file mode 100644 index 0000000..2987343 --- /dev/null +++ b/JavaScriptCore/wtf/url/src/URLEscape.cpp @@ -0,0 +1,39 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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 "URLEscape.h" + +namespace WTF { + +const char hexCharacterTable[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', +}; + +} diff --git a/JavaScriptCore/wtf/url/src/URLEscape.h b/JavaScriptCore/wtf/url/src/URLEscape.h new file mode 100644 index 0000000..cc2b77f --- /dev/null +++ b/JavaScriptCore/wtf/url/src/URLEscape.h @@ -0,0 +1,49 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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 URLEscape_h +#define URLEscape_h + +#include "URLBuffer.h" + +namespace WTF { + +extern const char hexCharacterTable[16]; + +template<typename InChar, typename OutChar> +inline void appendURLEscapedCharacter(InChar ch, URLBuffer<OutChar>& buffer) +{ + buffer.append('%'); + buffer.append(hexCharacterTable[ch >> 4]); + buffer.append(hexCharacterTable[ch & 0xf]); +} + +} + +#endif diff --git a/JavaScriptCore/wtf/url/src/URLQueryCanonicalizer.h b/JavaScriptCore/wtf/url/src/URLQueryCanonicalizer.h new file mode 100644 index 0000000..7740200 --- /dev/null +++ b/JavaScriptCore/wtf/url/src/URLQueryCanonicalizer.h @@ -0,0 +1,107 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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 URLQueryCanonicalizer_h +#define URLQueryCanonicalizer_h + +#include "RawURLBuffer.h" +#include "URLBuffer.h" +#include "URLCharacterTypes.h" +#include "URLComponent.h" +#include "URLEscape.h" + +namespace WTF { + +template<typename InChar, typename OutChar, void convertCharset(const InChar*, int length, URLBuffer<char>&)> +class URLQueryCanonicalizer { +public: + static void canonicalize(const InChar* spec, const URLComponent& query, URLBuffer<OutChar>& buffer, URLComponent& resultQuery) + { + if (query.length() < 0) { + resultQuery = URLComponent(); + return; + } + + buffer->append('?'); + resultQuery.setBegin(buffer->length()); + convertToQueryEncoding(spec, query, buffer); + resultQuery.setLength(buffer->length() - resultQuery.begin()); + } + +private: + static bool isAllASCII(const InChar* spec, const URLComponent& query) + { + int end = query.end(); + for (int i = query.begin(); i < end; ++i) { + if (static_cast<unsigned>(spec[i]) >= 0x80) + return false; + } + return true; + } + +#ifndef NDEBUG + static bool isRaw8Bit(const InChar* source, int length) + { + for (int i = source; i < length; ++i) { + if (source[i] & 0xFF != source[i]) + return false; + } + return true; + } +#endif + + static void appendRaw8BitQueryString(const InChar* source, int length, URLBuffer<OutChar>* buffer) + { + ASSERT(isRaw8Bit(source, length)); + for (int i = 0; i < length; ++i) { + if (!URLCharacterTypes::isQueryChar(source[i])) + appendURLEscapedCharacter(static_cast<unsigned char>(source[i]), buffer); + else + buffer->append(static_cast<char>(source[i])); + } + } + + static void convertToQueryEncoding(const InChar* spec, const URLComponent& query, URLBuffer<OutChar>& buffer) + { + if (isAllASCII(spec, query)) { + appendRaw8BitQueryString(&spec[query.begin()], query.length(), buffer); + return; + } + + RawURLBuffer<char, 1024> convertedQuery; + convertCharset(spec, query, convertedQuery); + appendRaw8BitQueryString(convertedQuery.data(), convertedQuery.length(), buffer); + } +}; + +} + +#endif + + diff --git a/JavaScriptCore/wtf/wtf.pri b/JavaScriptCore/wtf/wtf.pri index 84ac20e..83e71d8 100644 --- a/JavaScriptCore/wtf/wtf.pri +++ b/JavaScriptCore/wtf/wtf.pri @@ -6,6 +6,7 @@ SOURCES += \ wtf/CurrentTime.cpp \ wtf/DateMath.cpp \ wtf/dtoa.cpp \ + wtf/DecimalNumber.cpp \ wtf/FastMalloc.cpp \ wtf/HashTable.cpp \ wtf/MD5.cpp \ @@ -22,6 +23,7 @@ SOURCES += \ wtf/WTFThreadData.cpp \ wtf/text/AtomicString.cpp \ wtf/text/CString.cpp \ + wtf/text/StringBuilder.cpp \ wtf/text/StringImpl.cpp \ wtf/text/StringStatics.cpp \ wtf/text/WTFString.cpp \ diff --git a/JavaScriptCore/yarr/RegexInterpreter.cpp b/JavaScriptCore/yarr/RegexInterpreter.cpp index 17ffd8f..33f3c89 100644 --- a/JavaScriptCore/yarr/RegexInterpreter.cpp +++ b/JavaScriptCore/yarr/RegexInterpreter.cpp @@ -313,10 +313,24 @@ public: if (!input.checkInput(matchSize)) return false; - for (int i = 0; i < matchSize; ++i) { - if (!checkCharacter(input.reread(matchBegin + i), inputOffset - matchSize + i)) { - input.uncheckInput(matchSize); - return false; + if (pattern->m_ignoreCase) { + for (int i = 0; i < matchSize; ++i) { + int ch = input.reread(matchBegin + i); + + int lo = Unicode::toLower(ch); + int hi = Unicode::toUpper(ch); + + if ((lo != hi) ? (!checkCasedCharacter(lo, hi, inputOffset - matchSize + i)) : (!checkCharacter(ch, inputOffset - matchSize + i))) { + input.uncheckInput(matchSize); + return false; + } + } + } else { + for (int i = 0; i < matchSize; ++i) { + if (!checkCharacter(input.reread(matchBegin + i), inputOffset - matchSize + i)) { + input.uncheckInput(matchSize); + return false; + } } } @@ -481,6 +495,13 @@ public: int matchBegin = output[(term.atom.subpatternId << 1)]; int matchEnd = output[(term.atom.subpatternId << 1) + 1]; + + // If the end position of the referenced match hasn't set yet then the backreference in the same parentheses where it references to that. + // In this case the result of match is empty string like when it references to a parentheses with zero-width match. + // Eg.: /(a\1)/ + if (matchEnd == -1) + return true; + ASSERT((matchBegin == -1) == (matchEnd == -1)); ASSERT(matchBegin <= matchEnd); @@ -1497,7 +1518,7 @@ public: m_currentAlternativeIndex = newAlternativeIndex; } - void emitDisjunction(PatternDisjunction* disjunction, unsigned inputCountAlreadyChecked = 0, unsigned parenthesesInputCountAlreadyChecked = 0) + void emitDisjunction(PatternDisjunction* disjunction, unsigned inputCountAlreadyChecked = 0, unsigned parenthesesInputCountAlreadyChecked = 0, bool isParentheticalAssertion = false) { for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) { unsigned currentCountAlreadyChecked = inputCountAlreadyChecked; @@ -1512,12 +1533,18 @@ public: } unsigned minimumSize = alternative->m_minimumSize; + int countToCheck; - ASSERT(minimumSize >= parenthesesInputCountAlreadyChecked); - unsigned countToCheck = minimumSize - parenthesesInputCountAlreadyChecked; - if (countToCheck) + if (isParentheticalAssertion && parenthesesInputCountAlreadyChecked > minimumSize) + countToCheck = 0; + else + countToCheck = minimumSize - parenthesesInputCountAlreadyChecked; + + ASSERT(countToCheck >= 0); + if (countToCheck) { checkInput(countToCheck); - currentCountAlreadyChecked += countToCheck; + currentCountAlreadyChecked += countToCheck; + } for (unsigned i = 0; i < alternative->m_terms.size(); ++i) { PatternTerm& term = alternative->m_terms[i]; @@ -1577,8 +1604,11 @@ public: case PatternTerm::TypeParentheticalAssertion: { unsigned alternativeFrameLocation = term.frameLocation + RegexStackSpaceForBackTrackInfoParentheticalAssertion; + ASSERT(currentCountAlreadyChecked >= (unsigned)term.inputPosition); + int positiveInputOffset = currentCountAlreadyChecked - term.inputPosition; + atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invertOrCapture, term.frameLocation, alternativeFrameLocation); - emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0); + emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, positiveInputOffset, true); atomParenthesesEnd(true, term.parentheses.lastSubpatternId, 0, term.frameLocation, term.quantityCount, term.quantityType); break; } |