diff options
Diffstat (limited to 'JavaScriptCore')
82 files changed, 2501 insertions, 543 deletions
diff --git a/JavaScriptCore/API/JSClassRef.cpp b/JavaScriptCore/API/JSClassRef.cpp index c6685bf..747aa16 100644 --- a/JavaScriptCore/API/JSClassRef.cpp +++ b/JavaScriptCore/API/JSClassRef.cpp @@ -33,12 +33,28 @@ #include <runtime/JSGlobalObject.h> #include <runtime/ObjectPrototype.h> #include <runtime/Identifier.h> +#include <wtf/unicode/UTF8.h> using namespace std; using namespace JSC; +using namespace WTF::Unicode; const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static inline UString tryCreateStringFromUTF8(const char* string) +{ + if (!string) + return UString::null(); + + size_t length = strlen(string); + Vector<UChar, 1024> buffer(length); + UChar* p = buffer.data(); + if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length)) + return UString::null(); + + return UString(buffer.data(), p - buffer.data()); +} + OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* protoClass) : parentClass(definition->parentClass) , prototypeClass(0) @@ -53,7 +69,7 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* , callAsConstructor(definition->callAsConstructor) , hasInstance(definition->hasInstance) , convertToType(definition->convertToType) - , m_className(UString::createFromUTF8(definition->className).rep()->ref()) + , m_className(tryCreateStringFromUTF8(definition->className)) , m_staticValues(0) , m_staticFunctions(0) { @@ -62,9 +78,12 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* if (const JSStaticValue* staticValue = definition->staticValues) { m_staticValues = new OpaqueJSClassStaticValuesTable(); while (staticValue->name) { - // Use a local variable here to sidestep an RVCT compiler bug. - StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes); - m_staticValues->add(UString::createFromUTF8(staticValue->name).rep()->ref(), entry); + UString valueName = tryCreateStringFromUTF8(staticValue->name); + if (!valueName.isNull()) { + // Use a local variable here to sidestep an RVCT compiler bug. + StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes); + m_staticValues->add(valueName.rep()->ref(), entry); + } ++staticValue; } } @@ -72,9 +91,12 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* if (const JSStaticFunction* staticFunction = definition->staticFunctions) { m_staticFunctions = new OpaqueJSClassStaticFunctionsTable(); while (staticFunction->name) { - // Use a local variable here to sidestep an RVCT compiler bug. - StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes); - m_staticFunctions->add(UString::createFromUTF8(staticFunction->name).rep()->ref(), entry); + UString functionName = tryCreateStringFromUTF8(staticFunction->name); + if (!functionName.isNull()) { + // Use a local variable here to sidestep an RVCT compiler bug. + StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes); + m_staticFunctions->add(functionName.rep()->ref(), entry); + } ++staticFunction; } } @@ -118,7 +140,7 @@ static void clearReferenceToPrototype(JSObjectRef prototype) { OpaqueJSClassContextData* jsClassData = static_cast<OpaqueJSClassContextData*>(JSObjectGetPrivate(prototype)); ASSERT(jsClassData); - jsClassData->cachedPrototype = 0; + jsClassData->cachedPrototype.clear(toJS(prototype)); } PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* clientDefinition) @@ -146,12 +168,9 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass) // Use a local variable here to sidestep an RVCT compiler bug. StaticValueEntry* entry = new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes); staticValues->add(UString::Rep::create(it->first->data(), it->first->size()), entry); - } - } else staticValues = 0; - if (jsClass->m_staticFunctions) { staticFunctions = new OpaqueJSClassStaticFunctionsTable; diff --git a/JavaScriptCore/API/JSStringRef.h b/JavaScriptCore/API/JSStringRef.h index c58b958..92135b1 100644 --- a/JavaScriptCore/API/JSStringRef.h +++ b/JavaScriptCore/API/JSStringRef.h @@ -37,7 +37,8 @@ extern "C" { #endif -#if !defined(WIN32) && !defined(_WIN32) && !defined(__WINSCW__) +#if !defined(WIN32) && !defined(_WIN32) && !defined(__WINSCW__) \ + && !(defined(__CC_ARM) || defined(__ARMCC__)) /* RVCT */ /*! @typedef JSChar @abstract A Unicode character. diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index 578e282..4257344 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,809 @@ +2010-02-12 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Tor Arne Vestbø. + + Additional refptr/passrefptr workarounds for WINSCW compiler + https://bugs.webkit.org/show_bug.cgi?id=28054 + + * wtf/PassRefPtr.h: + (WTF::refIfNotNull): + (WTF::PassRefPtr::PassRefPtr): + (WTF::PassRefPtr::~PassRefPtr): + (WTF::PassRefPtr::clear): + (WTF::::operator): + * wtf/RefPtr.h: + (WTF::RefPtr::RefPtr): + (WTF::::operator): + +2010-02-12 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + + Don't import the cmath functions from std:: for WINSCW. + + * wtf/MathExtras.h: + +2010-02-12 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Adam Barth. + + Typedef both JSChar and UChar to wchar_t in RVCT. + https://bugs.webkit.org/show_bug.cgi?id=34560 + + Define both JSChar and UChar to wchar_t as the size + of wchar_t is 2 bytes in RVCT. + + * API/JSStringRef.h: + * wtf/unicode/qt4/UnicodeQt4.h: + +2010-02-11 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt and Darin Adler. + + The rest of the fix for + https://bugs.webkit.org/show_bug.cgi?id=34864 | <rdar://problem/7594198> + Many objects left uncollected after visiting mail.google.com and closing + window + + Don't unconditionally hang onto small strings. Instead, hang onto all + small strings as long as any small string is still referenced. + + SunSpider reports no change. + + * runtime/Collector.cpp: + (JSC::Heap::markRoots): Mark the small strings cache last, so it can + check if anything else has kept any strings alive. + + * runtime/SmallStrings.cpp: + (JSC::isMarked): + (JSC::SmallStrings::markChildren): Only keep our strings alive if some + other reference to at least one of them exists, too. + +2010-02-11 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Gavin Barraclough. + + Some progress toward fixing + https://bugs.webkit.org/show_bug.cgi?id=34864 | <rdar://problem/7594198> + Many objects left uncollected after visiting mail.google.com and closing + window + + SunSpider reports no change. + + Keep weak references, rather than protected references, to cached for-in + property name enumerators. + + One problem with protected references is that a chain like + [ gc object 1 ] => [ non-gc object ] => [ gc object 2 ] + takes two GC passes to break, since the first pass collects [ gc object 1 ], + releasing [ non-gc object ] and unprotecting [ gc object 2 ], and only + then can a second pass collect [ gc object 2 ]. + + Another problem with protected references is that they can keep a bunch + of strings alive long after they're useful. In SunSpider and a few popular + websites, the size-speed tradeoff seems to favor weak references. + + * runtime/JSPropertyNameIterator.cpp: + (JSC::JSPropertyNameIterator::JSPropertyNameIterator): Moved this constructor + into the .cpp file, since it's not used elsewhere. + + (JSC::JSPropertyNameIterator::~JSPropertyNameIterator): Added a destructor + to support our weak reference. + + * runtime/JSPropertyNameIterator.h: + (JSC::Structure::setEnumerationCache): + (JSC::Structure::clearEnumerationCache): + (JSC::Structure::enumerationCache): Added a function for clearing a + Structure's enumeration cache, used by our new destructor. Also fixed + indentation to match the rest of the file. + + * runtime/Structure.h: Changed from protected pointer to weak pointer. + +2010-02-11 Chris Rogers <crogers@google.com> + + Reviewed by David Levin. + + audio engine: add Complex number class + https://bugs.webkit.org/show_bug.cgi?id=34538 + + * wtf/Complex.h: Added. + (WebCore::complexFromMagnitudePhase): + +2010-02-10 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Added an SPI for asking about all the different live objects on the heap. + Useful for memory debugging. + + * JavaScriptCore.exp: Export the new SPI. + + * runtime/Collector.cpp: + (JSC::typeName): Use a little capitalization. Don't crash in the case of + a non-object cell, since it might just be an uninitialized cell. + + (JSC::Heap::objectTypeCounts): The new SPI. + + * runtime/Collector.h: + * runtime/CollectorHeapIterator.h: + (JSC::CollectorHeapIterator::advance): + (JSC::LiveObjectIterator::operator++): + (JSC::DeadObjectIterator::operator++): + (JSC::ObjectIterator::operator++): Made 2 tweaks to these iterators: + (1) Skip the last cell in the block, since it's a dummy sentinel, and + we don't want it to confuse the object count; (2) Fixed a logic error + in LiveObjectIterator that could cause it to iterate dead objects if + m_block were equal to m_heap.nextBlock and m_cell were less than + m_heap.nextCell. No test for this since I can't think of a way that this + could make WebKit behave badly. + +2010-02-11 Steve Block <steveblock@google.com> + + Reviewed by Darin Adler. + + Guard cmath using declarations in MathExtras.h on Android + https://bugs.webkit.org/show_bug.cgi?id=34840 + + Android does not provide these functions. + + * wtf/MathExtras.h: + +2010-02-08 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Cameron Zwarich. + + Restore ENABLE_RUBY flag so vendors can ship with Ruby disabled if they choose. + https://bugs.webkit.org/show_bug.cgi?id=34698 + + * Configurations/FeatureDefines.xcconfig: + +2010-02-10 Kevin Watters <kevinwatters@gmail.com> + + Reviewed by Kevin Ollivier. + + [wx] Add Windows complex text support and Mac support for containsCharacters. + + https://bugs.webkit.org/show_bug.cgi?id=34759 + + * wscript: + +2010-02-10 Alexey Proskuryakov <ap@apple.com> + + Addressing issues found by style bot. + + * wtf/ValueCheck.h: Renamed header guard to match final file name. + + * wtf/Vector.h: (WTF::::checkConsistency): Remove braces around a one-line clause. + +2010-02-09 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Geoffrey Garen. + + https://bugs.webkit.org/show_bug.cgi?id=34490 + WebCore::ImageEventSender::dispatchPendingEvents() crashes in certain conditions + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + Added ValueCheck.h. + + * wtf/ValueCheck.h: Added. Moved code out of HashTraits, since it would be awkward to + include that from Vector.h. + (WTF::ValueCheck::checkConsistency): Allow null pointers, those are pretty consistent. + + * wtf/HashTraits.h: Moved value checking code out of here. + + * wtf/HashTable.h: (WTF::::checkTableConsistencyExceptSize): Updated for the above changes. + + * wtf/Vector.h: + (WTF::::checkConsistency): Check all vector elements. + (WTF::ValueCheck): Support checking a Vector as an element in other containers. Currently + unused. + +2010-02-10 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + Fix QScriptValue::toBool. + + Fix ECMA compliance in the QScriptValue for values like 0, NaN and + empty strings. + + [Qt] QScriptValue::toBool problem + https://bugs.webkit.org/show_bug.cgi?id=34793 + + * qt/api/qscriptvalue_p.h: + (QScriptValuePrivate::toBool): + * qt/tests/qscriptvalue/tst_qscriptvalue.h: + * qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp: + (tst_QScriptValue::toBool_initData): + (tst_QScriptValue::toBool_makeData): + (tst_QScriptValue::toBool_test): + (tst_QScriptValue::toBoolean_initData): + (tst_QScriptValue::toBoolean_makeData): + (tst_QScriptValue::toBoolean_test): + +2009-10-06 Yongjun Zhang <yongjun.zhang@nokia.com> + + Reviewed by Simon Hausmann. + + Use derefIfNotNull() to work around WINSCW compiler forward declaration bug + + The compiler bug is reported at + https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=9812. + + The change should be reverted when the above bug is fixed in WINSCW compiler. + + https://bugs.webkit.org/show_bug.cgi?id=28054 + +2009-10-06 Yongjun Zhang <yongjun.zhang@nokia.com> + + Reviewed by Simon Hausmann. + + Get rid of WINSCW hack for UnSpecifiedBoolType + + Add parenthesis around (RefPtr::*UnspecifiedBoolType) to make the WINSCW + compiler work with the default UnSpecifiedBoolType() operator. + + https://bugs.webkit.org/show_bug.cgi?id=28054 + + * wtf/RefPtr.h: + +2010-02-09 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + New functions nullValue() and undefinedValue(). + + [Qt] QScriptEngine should contain nullValue and undefinedValue methods + https://bugs.webkit.org/show_bug.cgi?id=34749 + + * qt/api/qscriptengine.cpp: + (QScriptEngine::nullValue): + (QScriptEngine::undefinedValue): + * qt/api/qscriptengine.h: + * qt/tests/qscriptengine/tst_qscriptengine.cpp: + (tst_QScriptEngine::nullValue): + (tst_QScriptEngine::undefinedValue): + +2010-02-09 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + Fixes for QScriptValue::toNumber(). + + Fix ECMA compliance in QScriptValue for values unbound + to a QScriptEngine. + + [Qt] QScriptValue::toNumber() is broken + https://bugs.webkit.org/show_bug.cgi?id=34592 + + * qt/api/qscriptvalue_p.h: + (QScriptValuePrivate::toNumber): + * qt/tests/qscriptvalue/tst_qscriptvalue.h: + * qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp: + (tst_QScriptValue::toNumber_initData): + (tst_QScriptValue::toNumber_makeData): + (tst_QScriptValue::toNumber_test): + +2010-02-09 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + Fix QScriptValue::isNumber(). + + The isNumber() should return 'true' if the value is in the CNumber + state. + + [Qt] QScriptValue::isNumber() returns an incorrect value + https://bugs.webkit.org/show_bug.cgi?id=34575 + + * qt/api/qscriptvalue_p.h: + (QScriptValuePrivate::isNumber): + * qt/tests/qscriptvalue/tst_qscriptvalue.h: + * qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp: + (tst_QScriptValue::isNumber_initData): + (tst_QScriptValue::isNumber_makeData): + (tst_QScriptValue::isNumber_test): + +2010-02-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Small refactoring to the small strings cache to allow it to be cleared + dynamically. + + * runtime/SmallStrings.cpp: + (JSC::SmallStrings::SmallStrings): + (JSC::SmallStrings::clear): + * runtime/SmallStrings.h: Moved initialization code into a shared function, + and changed the constructor to call it. + +2010-02-09 Gavin Barraclough <barraclough@apple.com> + + Rubber Stamped by Geoff Garen. + + Rename StringBuilder::release && JSStringBuilder::releaseJSString + to 'build()'. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToLocaleString): + (JSC::arrayProtoFuncJoin): + * runtime/Executable.cpp: + (JSC::FunctionExecutable::paramString): + * runtime/FunctionConstructor.cpp: + (JSC::constructFunction): + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::encode): + (JSC::decode): + (JSC::globalFuncEscape): + (JSC::globalFuncUnescape): + * runtime/JSONObject.cpp: + (JSC::Stringifier::stringify): + * runtime/JSStringBuilder.h: + (JSC::JSStringBuilder::build): + * runtime/LiteralParser.cpp: + (JSC::LiteralParser::Lexer::lexString): + * runtime/NumberPrototype.cpp: + (JSC::integerPartNoExp): + (JSC::numberProtoFuncToFixed): + * runtime/StringBuilder.h: + (JSC::StringBuilder::build): + +2010-02-09 John Sullivan <sullivan@apple.com> + + https://bugs.webkit.org/show_bug.cgi?id=34772 + Overzealous new assertion in URStringImpl::adopt() + + Reviewed by Adam Barth. + + * runtime/UStringImpl.h: + (JSC::UStringImpl::adopt): + Only assert that vector.data() is non-zero if vector.size() is non-zero. + +2010-02-09 Nikolas Zimmermann <nzimmermann@rim.com> + + Not reviewed. Try to fix build problem on SnowLeopard slaves to bring them back. + + * API/JSClassRef.cpp: + (tryCreateStringFromUTF8): Mark method as 'static inline' to suppress "warning: no previous prototype for ..." + +2010-02-09 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Three small string fixes: + (1) StringBuilder::release should CRASH if the buffer allocation failed. + (2) Remove weird, dead code from JSString::tryGetValue, replace with an ASSERT. + (3) Move UString::createFromUTF8 out to the API, as tryCreateStringFromUTF8. + This is only used from the API, and (now) unlike other UString::create + methods may return UString::null() to indicate failure cases. Better + handle these in the API. + + * API/JSClassRef.cpp: + (tryCreateStringFromUTF8): + (OpaqueJSClass::OpaqueJSClass): + (OpaqueJSClassContextData::OpaqueJSClassContextData): + * runtime/JSString.h: + (JSC::Fiber::tryGetValue): + * runtime/StringBuilder.h: + (JSC::StringBuilder::release): + * runtime/UString.cpp: + (JSC::UString::UString): + (JSC::UString::from): + (JSC::UString::find): + * runtime/UString.h: + +2010-02-09 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Laszlo Gombos. + + [Qt] use nanval() for Symbian as nonInlineNaN + https://bugs.webkit.org/show_bug.cgi?id=34170 + + numeric_limits<double>::quiet_NaN is broken in Symbian + causing NaN to be evaluated as a number. + + * runtime/JSValue.cpp: + (JSC::nonInlineNaN): + +2010-02-09 Tamas Szirbucz <szirbucz@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + Add a soft modulo operation to ARM JIT using a trampoline function. + The performance progression is about ~1.8% on ARMv7 + https://bugs.webkit.org/show_bug.cgi?id=34424 + + Developed in cooperation with Gabor Loki. + + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_mod): + (JSC::JIT::emitSlow_op_mod): + * jit/JITOpcodes.cpp: + (JSC::JIT::softModulo): + * jit/JITStubs.h: + (JSC::JITThunks::ctiSoftModulo): + * wtf/Platform.h: + +2010-02-08 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (SL/win build fixes). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * runtime/StringPrototype.cpp: + +2010-02-08 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt + + Make String.replace throw an exception on out-of-memory, rather than + returning a null (err, empty-ish) string. Move String::replaceRange + and String::spliceSubstringsWithSeparators out to StringPrototype - + these were fairly specific use anyway, and we can better integrate + throwing the JS expcetion this way. + + Also removes redundant assignment operator from UString. + + * JavaScriptCore.exp: + * runtime/StringPrototype.cpp: + (JSC::StringRange::StringRange): + (JSC::jsSpliceSubstringsWithSeparators): + (JSC::jsReplaceRange): + (JSC::stringProtoFuncReplace): + * runtime/UString.cpp: + * runtime/UString.h: + +2010-02-08 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Eric Seidel. + + [BREWMP] Undefine WTF_OS_WINDOWS and WTF_PLATFORM_WIN + https://bugs.webkit.org/show_bug.cgi?id=34561 + + As the binary for simulator is built with MSVC 2005, + WTF_OS_WINDOWS and WTF_PLATFORM_WIN are defined. + Undefine them as we don't target Windows. + + * wtf/Platform.h: + +2010-02-08 Chris Rogers <crogers@google.com> + + Reviewed by Darin Adler. + + audio engine: add Vector3 class + https://bugs.webkit.org/show_bug.cgi?id=34548 + + * wtf/Vector3.h: Added. + (WebCore::Vector3::Vector3): + (WebCore::Vector3::abs): + (WebCore::Vector3::isZero): + (WebCore::Vector3::normalize): + (WebCore::Vector3::x): + (WebCore::Vector3::y): + (WebCore::Vector3::z): + (WebCore::operator+): + (WebCore::operator-): + (WebCore::operator*): + (WebCore::dot): + (WebCore::cross): + (WebCore::distance): + +2010-02-08 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Fix warning in clang++ + + * runtime/Structure.h: + (JSC::Structure::propertyStorageSize): + +2010-02-08 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Make makeString CRASH if we fail to allocate a string. + + (tryMakeString or jsMakeNontrivialString can be used where we + expect allocation may fail and want to handle the error). + + * runtime/JSStringBuilder.h: + (JSC::jsMakeNontrivialString): + * runtime/UString.h: + (JSC::tryMakeString): + (JSC::makeString): + +2010-02-08 Gavin Barraclough <barraclough@apple.com> + + Rubber Stamped by Oliver Hunt. + + Remove a couple of unnecesary C-style casts spotted by Darin. + + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::encode): + (JSC::globalFuncEscape): + +2010-02-08 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Switch some more StringBuilder/jsNontrivialString code to use + JSStringBuilder/jsMakeNontrivialString - these methods will + throw an exception if we hit out-of-memory, rather than just + CRASHing. + + * runtime/FunctionPrototype.cpp: + (JSC::functionProtoFuncToString): + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::encode): + (JSC::decode): + (JSC::globalFuncEscape): + +2010-02-08 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Use an empty identifier instead of a null identifier for parse + tokens without an identifier. + + This helps encapsulate the null UStringImpl within UString. + + * parser/Grammar.y: + * parser/NodeConstructors.h: + (JSC::ContinueNode::ContinueNode): + (JSC::BreakNode::BreakNode): + (JSC::ForInNode::ForInNode): + * runtime/CommonIdentifiers.cpp: + (JSC::CommonIdentifiers::CommonIdentifiers): + * runtime/CommonIdentifiers.h: + * runtime/FunctionPrototype.cpp: + (JSC::FunctionPrototype::FunctionPrototype): + +2010-02-08 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Build fix for make distcheck. + + * GNUmakefile.am: + +2010-02-08 Simon Hausmann <simon.hausmann@nokia.com> + + Unreviewed RVCT build fix. + + Similar to r54391, don't import the cmath functions from std:: for RVCT. + + * wtf/MathExtras.h: + +2010-02-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Change UStringImpl::create to CRASH if the string cannot be allocated, + rather than returning a null string (which will behave like a zero-length + string if used). + + Also move createRep function from UString to become new overloaded + UStringImpl::create methods. In doing so, bring their behaviour closer to + being in line with WebCore::StringImpl, in removing the behaviour that they + can be used to produce null UStrings (ASSERT the char* provided is non-null). + This behaviour of converting null C-strings to null UStrings is inefficient + (cmompared to just using UString::null()), incompatible with WebCore::StringImpl's + behaviour, and may generate unexpected behaviour, since in many cases a null + UString can be used like an empty string. + + With these changes UStringImpl need not have a concept of null impls, we can + start transitioning this to become an implementation detail of UString, that + internally it chooses to use a null-object rather than an actually zero impl + pointer. + + * JavaScriptCore.exp: + * debugger/Debugger.cpp: + (JSC::Debugger::recompileAllJSFunctions): + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::calculatedFunctionName): + * parser/Parser.cpp: + (JSC::Parser::parse): + * profiler/Profile.cpp: + (JSC::Profile::Profile): + * profiler/ProfileGenerator.cpp: + (JSC::ProfileGenerator::stopProfiling): + * runtime/Error.cpp: + (JSC::Error::create): + (JSC::throwError): + * runtime/ExceptionHelpers.cpp: + (JSC::createError): + * runtime/Identifier.cpp: + (JSC::Identifier::add): + * runtime/PropertyNameArray.cpp: + (JSC::PropertyNameArray::add): + * runtime/UString.cpp: + (JSC::initializeUString): + (JSC::UString::UString): + (JSC::UString::operator=): + * runtime/UString.h: + (JSC::UString::isNull): + (JSC::UString::null): + (JSC::UString::rep): + (JSC::UString::UString): + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::create): + * runtime/UStringImpl.h: + +2010-02-05 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Eric Seidel. + + [BREWMP] Define SYSTEM_MALLOC 1 + https://bugs.webkit.org/show_bug.cgi?id=34640 + + Make BREWMP use system malloc because FastMalloc is not ported. + + * wtf/Platform.h: + +2010-02-05 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Alexey Proskuryakov. + + Don't call CRASH() in fastMalloc and fastCalloc when the requested memory size is 0 + https://bugs.webkit.org/show_bug.cgi?id=34569 + + With USE_SYSTEM_MALLOC=1, fastMalloc and fastCalloc call CRASH() + if the return value of malloc and calloc is 0. + + However, these functions can return 0 when the request size is 0. + Libc manual says, "If size is 0, then malloc() returns either NULL, + or a unique pointer value that can later be successfully passed to free()." + Though malloc returns a unique pointer in most systems, + 0 can be returned in some systems. For instance, BREW's MALLOC returns 0 + when size is 0. + + If malloc or calloc returns 0 due to allocation size, increase the size + to 1 and try again. + + * wtf/FastMalloc.cpp: + (WTF::fastMalloc): + (WTF::fastCalloc): + +2010-02-04 Mark Rowe <mrowe@apple.com> + + Reviewed by Timothy Hatcher. + + Build fix. Remove a symbol corresponding to an inline function from the linker export + file to prevent a weak external failure. + + * JavaScriptCore.xcodeproj/project.pbxproj: Accommodate rename of script. + +2010-02-04 Daniel Bates <dbates@webkit.org> + + [Qt] Unreviewed, build fix for Qt bot. + + * runtime/JSStringBuilder.h: Changed #include <X.h> notation #include "X.h". + +2010-02-04 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Clearing a WeakGCPtr is weird + https://bugs.webkit.org/show_bug.cgi?id=34627 + + Added a WeakGCPtr::clear interface. + + As discussed in https://bugs.webkit.org/show_bug.cgi?id=33383, the old + interface made it pretty weird for a client to conditionally clear a + WeakGCPtr, which is exactly what clients want to do when objects are + finalized. + + * API/JSClassRef.cpp: + (clearReferenceToPrototype): Use the new WeakGCPtr::clear() interface. + + * runtime/WeakGCPtr.h: + (JSC::WeakGCPtr::clear): Added an interface for clearing a WeakGCPtr, + iff its current value is the value passed in. It's cumbersome for the + client to do this test, since WeakGCPtr sometimes pretends to be null. + +2010-02-04 Geoffrey Garen <ggaren@apple.com> + + Build fix: export a header. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2010-02-04 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Add a JSStringBuilder class (similar-to, and derived-from StringBuilder) to + construct JSStrings, throwing a JS exception should we run out of memory whilst + allocating storage for the string. + + Similarly, add jsMakeNontrivialString methods to use in cases where previously + we were calling makeString & passing the result to jsNontrivialString. Again, + these new methods throw if we hit an out of memory condition. + + Move throwOutOfMemoryError into ExceptionHelpers, to make it more widely available. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + (JSC::arrayProtoFuncToLocaleString): + (JSC::arrayProtoFuncJoin): + * runtime/DateConstructor.cpp: + (JSC::callDate): + * runtime/DatePrototype.cpp: + (JSC::dateProtoFuncToString): + (JSC::dateProtoFuncToUTCString): + (JSC::dateProtoFuncToGMTString): + * runtime/ErrorPrototype.cpp: + (JSC::errorProtoFuncToString): + * runtime/ExceptionHelpers.cpp: + (JSC::throwOutOfMemoryError): + * runtime/ExceptionHelpers.h: + * runtime/JSStringBuilder.h: Added. + (JSC::JSStringBuilder::releaseJSString): + (JSC::jsMakeNontrivialString): + * runtime/NumberPrototype.cpp: + (JSC::numberProtoFuncToPrecision): + * runtime/ObjectPrototype.cpp: + (JSC::objectProtoFuncToString): + * runtime/Operations.cpp: + * runtime/Operations.h: + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncToString): + * runtime/StringBuilder.h: + (JSC::StringBuilder::append): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncBig): + (JSC::stringProtoFuncSmall): + (JSC::stringProtoFuncBlink): + (JSC::stringProtoFuncBold): + (JSC::stringProtoFuncFixed): + (JSC::stringProtoFuncItalics): + (JSC::stringProtoFuncStrike): + (JSC::stringProtoFuncSub): + (JSC::stringProtoFuncSup): + (JSC::stringProtoFuncFontcolor): + (JSC::stringProtoFuncFontsize): + (JSC::stringProtoFuncAnchor): + +2010-02-04 Steve Falkenburg <sfalken@apple.com> + + Windows build fix. + + * wtf/MathExtras.h: + +2010-02-04 Darin Adler <darin@apple.com> + + Reviewed by David Levin. + + Make MathExtras.h compatible with <cmath> + https://bugs.webkit.org/show_bug.cgi?id=34618 + + * wtf/MathExtras.h: Include <cmath> instead of <math.h>. + Use "using" as we do elsewhere in WTF for the four functions from <cmath> + we want to use without the prefix. Later we could consider making the std + explicit at call sites instead. + +2010-02-04 Tamas Szirbucz <szirbucz@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + Use an easily appendable structure for trampolines instead of pointer parameters. + https://bugs.webkit.org/show_bug.cgi?id=34424 + + * assembler/ARMAssembler.cpp: + (JSC::ARMAssembler::executableCopy): + * jit/JIT.h: + (JSC::JIT::compileCTIMachineTrampolines): + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JITStubs.cpp: + (JSC::JITThunks::JITThunks): + * jit/JITStubs.h: + (JSC::JITThunks::ctiStringLengthTrampoline): + (JSC::JITThunks::ctiVirtualCallLink): + (JSC::JITThunks::ctiVirtualCall): + (JSC::JITThunks::ctiNativeCallThunk): + 2010-02-04 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> Reviewed by Simon Hausmann. diff --git a/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/JavaScriptCore/Configurations/FeatureDefines.xcconfig index 24589c7..8343ce7 100644 --- a/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -56,6 +56,7 @@ ENABLE_JAVASCRIPT_DEBUGGER = ENABLE_JAVASCRIPT_DEBUGGER; ENABLE_MATHML = ; ENABLE_NOTIFICATIONS = ; ENABLE_OFFLINE_WEB_APPLICATIONS = ENABLE_OFFLINE_WEB_APPLICATIONS; +ENABLE_RUBY = ENABLE_RUBY; ENABLE_SHARED_WORKERS = ENABLE_SHARED_WORKERS; ENABLE_SVG = ENABLE_SVG; ENABLE_SVG_ANIMATION = ENABLE_SVG_ANIMATION; @@ -72,4 +73,4 @@ ENABLE_XHTMLMP = ; ENABLE_XPATH = ENABLE_XPATH; ENABLE_XSLT = ENABLE_XSLT; -FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(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_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT); +FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(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_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT); diff --git a/JavaScriptCore/Configurations/Version.xcconfig b/JavaScriptCore/Configurations/Version.xcconfig index 75f9bd4..0e289b1 100644 --- a/JavaScriptCore/Configurations/Version.xcconfig +++ b/JavaScriptCore/Configurations/Version.xcconfig @@ -21,8 +21,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -MAJOR_VERSION = 532; -MINOR_VERSION = 9; +MAJOR_VERSION = 533; +MINOR_VERSION = 1; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am index 7ac6a8c..4ac89d9 100644 --- a/JavaScriptCore/GNUmakefile.am +++ b/JavaScriptCore/GNUmakefile.am @@ -192,6 +192,7 @@ javascriptcore_sources += \ JavaScriptCore/runtime/JSONObject.h \ JavaScriptCore/runtime/JSPropertyNameIterator.cpp \ JavaScriptCore/runtime/JSPropertyNameIterator.h \ + JavaScriptCore/runtime/JSStringBuilder.h \ JavaScriptCore/runtime/JSZombie.h \ JavaScriptCore/runtime/LiteralParser.cpp \ JavaScriptCore/runtime/LiteralParser.h \ @@ -288,6 +289,7 @@ javascriptcore_sources += \ JavaScriptCore/wtf/TypeTraits.cpp \ JavaScriptCore/wtf/TypeTraits.h \ JavaScriptCore/wtf/UnusedParam.h \ + JavaScriptCore/wtf/ValueCheck.h \ JavaScriptCore/wtf/Vector.h \ JavaScriptCore/wtf/VectorTraits.h \ JavaScriptCore/wtf/gtk/GOwnPtr.cpp \ diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp index 01d3144..f562b52 100644 --- a/JavaScriptCore/JavaScriptCore.exp +++ b/JavaScriptCore/JavaScriptCore.exp @@ -104,7 +104,6 @@ __ZN3JSC11JSByteArray15createStructureENS_7JSValueE __ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE __ZN3JSC11ParserArena5resetEv __ZN3JSC11UStringImpl12sharedBufferEv -__ZN3JSC11UStringImpl6s_nullE __ZN3JSC11UStringImpl7s_emptyE __ZN3JSC11UStringImplD1Ev __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE @@ -191,6 +190,7 @@ __ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE __ZN3JSC3NaNE __ZN3JSC4Heap14primaryHeapEndEv __ZN3JSC4Heap15recordExtraCostEm +__ZN3JSC4Heap16objectTypeCountsEv __ZN3JSC4Heap16primaryHeapBeginEv __ZN3JSC4Heap17collectAllGarbageEv __ZN3JSC4Heap17globalObjectCountEv @@ -238,9 +238,9 @@ __ZN3JSC7UString4fromEd __ZN3JSC7UString4fromEi __ZN3JSC7UString4fromEj __ZN3JSC7UString4fromEl +__ZN3JSC7UString9s_nullRepE __ZN3JSC7UStringC1EPKc __ZN3JSC7UStringC1EPKti -__ZN3JSC7UStringaSEPKc __ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE __ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE __ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE @@ -300,6 +300,7 @@ __ZN3JSCgtERKNS_7UStringES2_ __ZN3JSCltERKNS_7UStringES2_ __ZN3WTF10fastCallocEmm __ZN3WTF10fastMallocEm +__ZN3WTF10fastStrDupEPKc __ZN3WTF11currentTimeEv __ZN3WTF11fastReallocEPvm __ZN3WTF12createThreadEPFPvS0_ES0_ @@ -348,10 +349,9 @@ __ZN3WTF8Collator18setOrderLowerFirstEb __ZN3WTF8CollatorC1EPKc __ZN3WTF8CollatorD1Ev __ZN3WTF8fastFreeEPv -__ZN3WTF10fastStrDupEPKc __ZN3WTF8msToYearEd -__ZN3WTF9dayInYearEdi __ZN3WTF9ByteArray6createEm +__ZN3WTF9dayInYearEdi __ZNK3JSC10JSFunction23isHostFunctionNonInlineEv __ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE __ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE diff --git a/JavaScriptCore/JavaScriptCore.gypi b/JavaScriptCore/JavaScriptCore.gypi index 24577da..c67b6a8 100644 --- a/JavaScriptCore/JavaScriptCore.gypi +++ b/JavaScriptCore/JavaScriptCore.gypi @@ -441,6 +441,7 @@ 'wtf/unicode/UTF8.cpp', 'wtf/unicode/UTF8.h', 'wtf/UnusedParam.h', + 'wtf/ValueCheck.h', 'wtf/Vector.h', 'wtf/VectorTraits.h', 'wtf/VMTags.h', diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index 6a0f1d8..6afef77 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -32,7 +32,6 @@ EXPORTS ??1ThreadCondition@WTF@@QAE@XZ ??1UStringImpl@JSC@@AAE@XZ ??2JSGlobalObject@JSC@@SAPAXIPAVJSGlobalData@1@@Z - ??4UString@JSC@@QAEAAV01@PBD@Z ??8JSC@@YA_NABVUString@0@0@Z ?NaN@JSC@@3NB ?UTF8String@UString@JSC@@QBE?AVCString@2@_N@Z @@ -126,6 +125,7 @@ EXPORTS ?fastFree@WTF@@YAXPAX@Z ?fastMalloc@WTF@@YAPAXI@Z ?fastRealloc@WTF@@YAPAXPAXI@Z + ?fastStrDup@WTF@@YAPADPBD@Z ?fastZeroedMalloc@WTF@@YAPAXI@Z ?fillGetterPropertySlot@JSObject@JSC@@QAEXAAVPropertySlot@2@PAVJSValue@2@@Z ?focus@Profile@JSC@@QAEXPBVProfileNode@2@@Z diff --git a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj index 7a93632..c5b826c 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj @@ -545,6 +545,10 @@ >
</File>
<File
+ RelativePath="..\..\wtf\ValueCheck.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\Vector.h"
>
</File>
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 58016d0..5f904ce 100644 --- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -44,7 +44,7 @@ 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, ); }; }; - 14035DB110DBFB2A00FFFFE7 /* WeakGCPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */; }; + 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 */; }; 140566D6107EC271005DBC8D /* JSFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A85E0255597D01FF60F7 /* JSFunction.cpp */; }; @@ -232,6 +232,7 @@ 86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */; }; 86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; }; 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; }; + 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E85538111B9968001AF51E /* JSStringBuilder.h */; }; 86EAC4950F93E8D1008EC948 /* RegexCompiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EAC48D0F93E8D1008EC948 /* RegexCompiler.cpp */; }; 86EAC4960F93E8D1008EC948 /* RegexCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EAC48E0F93E8D1008EC948 /* RegexCompiler.h */; }; 86EAC4970F93E8D1008EC948 /* RegexInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EAC48F0F93E8D1008EC948 /* RegexInterpreter.cpp */; }; @@ -474,6 +475,7 @@ E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; }; E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E124A8F60E555775003091F1 /* OpaqueJSString.cpp */; }; E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */; }; + E17FF771112131D200076A19 /* ValueCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = E17FF770112131D200076A19 /* ValueCheck.h */; settings = {ATTRIBUTES = (Private, ); }; }; E18E3A590DF9278C00D90B34 /* JSGlobalData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E18E3A570DF9278C00D90B34 /* JSGlobalData.cpp */; }; E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; }; E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */; }; @@ -766,6 +768,7 @@ 86DB645F0F954E9100D7D921 /* ExecutableAllocatorWin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorWin.cpp; sourceTree = "<group>"; }; 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorFixedVMPool.cpp; sourceTree = "<group>"; }; 86E116B00FE75AC800B512BC /* CodeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeLocation.h; sourceTree = "<group>"; }; + 86E85538111B9968001AF51E /* JSStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringBuilder.h; sourceTree = "<group>"; }; 86EAC48D0F93E8D1008EC948 /* RegexCompiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegexCompiler.cpp; path = yarr/RegexCompiler.cpp; sourceTree = "<group>"; }; 86EAC48E0F93E8D1008EC948 /* RegexCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegexCompiler.h; path = yarr/RegexCompiler.h; sourceTree = "<group>"; }; 86EAC48F0F93E8D1008EC948 /* RegexInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegexInterpreter.cpp; path = yarr/RegexInterpreter.cpp; sourceTree = "<group>"; }; @@ -977,6 +980,7 @@ E124A8F60E555775003091F1 /* OpaqueJSString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpaqueJSString.cpp; sourceTree = "<group>"; }; E178633F0D9BEC0000D74E75 /* InitializeThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializeThreading.h; sourceTree = "<group>"; }; E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeThreading.cpp; sourceTree = "<group>"; }; + E17FF770112131D200076A19 /* ValueCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueCheck.h; sourceTree = "<group>"; }; E18E3A560DF9278C00D90B34 /* JSGlobalData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalData.h; sourceTree = "<group>"; }; E18E3A570DF9278C00D90B34 /* JSGlobalData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalData.cpp; sourceTree = "<group>"; }; E195678F09E7CF1200B89D13 /* UnicodeIcu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnicodeIcu.h; sourceTree = "<group>"; }; @@ -1384,6 +1388,7 @@ 0B330C260F38C62300692DE3 /* TypeTraits.cpp */, 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */, 935AF46B09E9D9DB00ACD1D8 /* UnusedParam.h */, + E17FF770112131D200076A19 /* ValueCheck.h */, 6592C316098B7DE10003D4F6 /* Vector.h */, 6592C317098B7DE10003D4F6 /* VectorTraits.h */, 96DD73780F9DA3100027FBCC /* VMTags.h */, @@ -1544,6 +1549,7 @@ A7E42C180E3938830065A544 /* JSStaticScopeObject.h */, BC02E9B60E1842FA000F9297 /* JSString.cpp */, F692A8620255597D01FF60F7 /* JSString.h */, + 86E85538111B9968001AF51E /* JSStringBuilder.h */, 14ABB454099C2A0F00E2A24F /* JSType.h */, 6507D2970E871E4A00D7D896 /* JSTypeInfo.h */, F692A8870255597D01FF60F7 /* JSValue.cpp */, @@ -2050,6 +2056,8 @@ 1429DAE00ED2645B00B89619 /* WRECGenerator.h in Headers */, 1429DABF0ED263E700B89619 /* WRECParser.h in Headers */, 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */, + 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */, + E17FF771112131D200076A19 /* ValueCheck.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2104,7 +2112,7 @@ 932F5BD20822A1C700736975 /* Frameworks */, 9319586B09D9F91A00A56FD4 /* Check For Global Initializers */, 933457200EBFDC3F00B80894 /* Check For Exit Time Destructors */, - 5D29D8BE0E9860B400C3D2D0 /* Check For Weak VTables */, + 5D29D8BE0E9860B400C3D2D0 /* Check For Weak VTables and Externals */, ); buildRules = ( ); @@ -2203,7 +2211,7 @@ shellPath = /bin/sh; shellScript = "# exclude NPN functions on 64-bit\nsed -e s/^.\\*NPN.\\*$// \"${SRCROOT}/JavaScriptCore.exp\" > \"${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore/JavaScriptCore.LP64.exp\"\n"; }; - 5D29D8BE0E9860B400C3D2D0 /* Check For Weak VTables */ = { + 5D29D8BE0E9860B400C3D2D0 /* Check For Weak VTables and Externals */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2211,12 +2219,12 @@ inputPaths = ( "$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)", ); - name = "Check For Weak VTables"; + name = "Check For Weak VTables and Externals"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -f ../WebKitTools/Scripts/check-for-weak-vtables ]; then\n ../WebKitTools/Scripts/check-for-weak-vtables || exit $?\nfi"; + shellScript = "if [ -f ../WebKitTools/Scripts/check-for-weak-vtables-and-externals ]; then\n ../WebKitTools/Scripts/check-for-weak-vtables-and-externals || exit $?\nfi"; }; 5D2F7CF90C6875BB00B5B72B /* Update Info.plist with version information */ = { isa = PBXShellScriptBuildPhase; diff --git a/JavaScriptCore/debugger/Debugger.cpp b/JavaScriptCore/debugger/Debugger.cpp index 1d2e4fb..cbcbd21 100644 --- a/JavaScriptCore/debugger/Debugger.cpp +++ b/JavaScriptCore/debugger/Debugger.cpp @@ -94,7 +94,7 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData) // JavaScript in the inspector. SourceProviderMap::const_iterator end = sourceProviders.end(); for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter) - sourceParsed(iter->second, SourceCode(iter->first), -1, 0); + sourceParsed(iter->second, SourceCode(iter->first), -1, UString()); } JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject) diff --git a/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/JavaScriptCore/debugger/DebuggerCallFrame.cpp index c6b4223..05a385d 100644 --- a/JavaScriptCore/debugger/DebuggerCallFrame.cpp +++ b/JavaScriptCore/debugger/DebuggerCallFrame.cpp @@ -50,11 +50,11 @@ const UString* DebuggerCallFrame::functionName() const UString DebuggerCallFrame::calculatedFunctionName() const { if (!m_callFrame->codeBlock()) - return 0; + return UString(); JSFunction* function = asFunction(m_callFrame->callee()); if (!function) - return 0; + return UString(); return function->calculatedDisplayName(m_callFrame); } diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h index 8e0c9ac..bfbb1ee 100644 --- a/JavaScriptCore/jit/JIT.h +++ b/JavaScriptCore/jit/JIT.h @@ -317,10 +317,10 @@ namespace JSC { jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress); } - static void compileCTIMachineTrampolines(JSGlobalData* globalData, RefPtr<ExecutablePool>* executablePool, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk) + static void compileCTIMachineTrampolines(JSGlobalData* globalData, RefPtr<ExecutablePool>* executablePool, TrampolineStructure *trampolines) { JIT jit(globalData); - jit.privateCompileCTIMachineTrampolines(executablePool, globalData, ctiStringLengthTrampoline, ctiVirtualCallLink, ctiVirtualCall, ctiNativeCallThunk); + jit.privateCompileCTIMachineTrampolines(executablePool, globalData, trampolines); } static void patchGetByIdSelf(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress); @@ -361,7 +361,7 @@ namespace JSC { void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame); void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress); - void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk); + void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, TrampolineStructure *trampolines); void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress); void addSlowCase(Jump); @@ -800,6 +800,9 @@ namespace JSC { void emit_op_to_jsnumber(Instruction*); void emit_op_to_primitive(Instruction*); void emit_op_unexpected_load(Instruction*); +#if ENABLE(JIT_OPTIMIZE_MOD) + void softModulo(); +#endif void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_bitand(Instruction*, Vector<SlowCaseEntry>::iterator&); diff --git a/JavaScriptCore/jit/JITArithmetic.cpp b/JavaScriptCore/jit/JITArithmetic.cpp index feee8d2..2f2ffe3 100644 --- a/JavaScriptCore/jit/JITArithmetic.cpp +++ b/JavaScriptCore/jit/JITArithmetic.cpp @@ -31,6 +31,7 @@ #include "CodeBlock.h" #include "JITInlineMethods.h" #include "JITStubCall.h" +#include "JITStubs.h" #include "JSArray.h" #include "JSFunction.h" #include "Interpreter.h" @@ -1186,14 +1187,40 @@ void JIT::emit_op_mod(Instruction* currentInstruction) unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; +#if ENABLE(JIT_OPTIMIZE_MOD) + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + + addSlowCase(branch32(Equal, regT2, Imm32(0))); + + emitNakedCall(m_globalData->jitStubs.ctiSoftModulo()); + + emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); +#else JITStubCall stubCall(this, cti_op_mod); stubCall.addArgument(op1); stubCall.addArgument(op2); stubCall.call(dst); +#endif } -void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&) +void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { +#if ENABLE(JIT_OPTIMIZE_MOD) + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + JITStubCall stubCall(this, cti_op_mod); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(result); +#else + ASSERT_NOT_REACHED(); +#endif } #endif // CPU(X86) || CPU(X86_64) @@ -2138,15 +2165,40 @@ void JIT::emit_op_mod(Instruction* currentInstruction) unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; +#if ENABLE(JIT_OPTIMIZE_MOD) + emitGetVirtualRegisters(op1, regT0, op2, regT2); + emitJumpSlowCaseIfNotImmediateInteger(regT0); + emitJumpSlowCaseIfNotImmediateInteger(regT2); + + addSlowCase(branch32(Equal, regT2, Imm32(1))); + + emitNakedCall(m_globalData->jitStubs.ctiSoftModulo()); + + emitPutVirtualRegister(result, regT0); +#else JITStubCall stubCall(this, cti_op_mod); stubCall.addArgument(op1, regT2); stubCall.addArgument(op2, regT2); stubCall.call(result); +#endif } -void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&) +void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { +#if ENABLE(JIT_OPTIMIZE_MOD) + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + JITStubCall stubCall(this, cti_op_mod); + stubCall.addArgument(op1, regT2); + stubCall.addArgument(op2, regT2); + stubCall.call(result); +#else ASSERT_NOT_REACHED(); +#endif } #endif // CPU(X86) || CPU(X86_64) diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp index d9a32d9..c3f20f1 100644 --- a/JavaScriptCore/jit/JITOpcodes.cpp +++ b/JavaScriptCore/jit/JITOpcodes.cpp @@ -40,8 +40,12 @@ namespace JSC { #if USE(JSVALUE32_64) -void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk) +void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, TrampolineStructure *trampolines) { +#if ENABLE(JIT_OPTIMIZE_MOD) + Label softModBegin = align(); + softModulo(); +#endif #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) // (1) This function provides fast property access for string length Label stringLengthBegin = align(); @@ -365,18 +369,21 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable CodeRef finalCode = patchBuffer.finalizeCode(); *executablePool = finalCode.m_executablePool; - *ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin); - *ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk); + trampolines->ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin); + trampolines->ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk); #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) - *ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin); + trampolines->ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin); #else UNUSED_PARAM(ctiStringLengthTrampoline); #endif #if ENABLE(JIT_OPTIMIZE_CALL) - *ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin); + trampolines->ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin); #else UNUSED_PARAM(ctiVirtualCallLink); #endif +#if ENABLE(JIT_OPTIMIZE_MOD) + trampolines->ctiSoftModulo = trampolineAt(finalCode, softModBegin); +#endif } void JIT::emit_op_mov(Instruction* currentInstruction) @@ -1495,8 +1502,12 @@ void JIT::emit_op_profile_did_call(Instruction* currentInstruction) #define RECORD_JUMP_TARGET(targetOffset) \ do { m_labels[m_bytecodeIndex + (targetOffset)].used(); } while (false) -void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk) +void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, TrampolineStructure *trampolines) { +#if ENABLE(JIT_OPTIMIZE_MOD) + Label softModBegin = align(); + softModulo(); +#endif #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) // (2) The second function provides fast property access for string length Label stringLengthBegin = align(); @@ -1827,11 +1838,14 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable CodeRef finalCode = patchBuffer.finalizeCode(); *executablePool = finalCode.m_executablePool; - *ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin); - *ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin); - *ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk); + trampolines->ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin); + trampolines->ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin); + trampolines->ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk); +#if ENABLE(JIT_OPTIMIZE_MOD) + trampolines->ctiSoftModulo = trampolineAt(finalCode, softModBegin); +#endif #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) - *ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin); + trampolines->ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin); #else UNUSED_PARAM(ctiStringLengthTrampoline); #endif @@ -2978,6 +2992,81 @@ void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCa #endif // USE(JSVALUE32_64) +// For both JSValue32_64 and JSValue32 +#if ENABLE(JIT_OPTIMIZE_MOD) +#if CPU(ARM_TRADITIONAL) +void JIT::softModulo() +{ + push(regS0); + push(regS1); + push(regT1); + push(regT3); +#if USE(JSVALUE32_64) + m_assembler.mov_r(regT3, regT2); + m_assembler.mov_r(regT2, regT0); +#else + m_assembler.mov_r(regT3, m_assembler.asr(regT2, 1)); + m_assembler.mov_r(regT2, m_assembler.asr(regT0, 1)); +#endif + m_assembler.mov_r(regT1, ARMAssembler::getOp2(0)); + + m_assembler.teq_r(regT3, ARMAssembler::getOp2(0)); + m_assembler.rsb_r(regT3, regT3, ARMAssembler::getOp2(0), ARMAssembler::MI); + m_assembler.eor_r(regT1, regT1, ARMAssembler::getOp2(1), ARMAssembler::MI); + + m_assembler.teq_r(regT2, ARMAssembler::getOp2(0)); + m_assembler.rsb_r(regT2, regT2, ARMAssembler::getOp2(0), ARMAssembler::MI); + m_assembler.eor_r(regT1, regT1, ARMAssembler::getOp2(2), ARMAssembler::MI); + + Jump exitBranch = branch32(LessThan, regT2, regT3); + + m_assembler.sub_r(regS1, regT3, ARMAssembler::getOp2(1)); + m_assembler.tst_r(regS1, regT3); + m_assembler.and_r(regT2, regT2, regS1, ARMAssembler::EQ); + m_assembler.and_r(regT0, regS1, regT3); + Jump exitBranch2 = branchTest32(Zero, regT0); + + m_assembler.clz_r(regS1, regT2); + m_assembler.clz_r(regS0, regT3); + m_assembler.sub_r(regS0, regS0, regS1); + + m_assembler.rsbs_r(regS0, regS0, ARMAssembler::getOp2(31)); + + m_assembler.mov_r(regS0, m_assembler.lsl(regS0, 1), ARMAssembler::NE); + + m_assembler.add_r(ARMRegisters::pc, ARMRegisters::pc, m_assembler.lsl(regS0, 2), ARMAssembler::NE); + m_assembler.mov_r(regT0, regT0); + + for (int i = 31; i > 0; --i) { + m_assembler.cmp_r(regT2, m_assembler.lsl(regT3, i)); + m_assembler.sub_r(regT2, regT2, m_assembler.lsl(regT3, i), ARMAssembler::CS); + } + + m_assembler.cmp_r(regT2, regT3); + m_assembler.sub_r(regT2, regT2, regT3, ARMAssembler::CS); + + exitBranch.link(this); + exitBranch2.link(this); + + m_assembler.teq_r(regT1, ARMAssembler::getOp2(0)); + m_assembler.rsb_r(regT2, regT2, ARMAssembler::getOp2(0), ARMAssembler::GT); + +#if USE(JSVALUE32_64) + m_assembler.mov_r(regT0, regT2); +#else + m_assembler.mov_r(regT0, m_assembler.lsl(regT2, 1)); + m_assembler.eor_r(regT0, regT0, ARMAssembler::getOp2(1)); +#endif + pop(regT3); + pop(regT1); + pop(regS1); + pop(regS0); + ret(); +} +#else +#error "JIT_OPTIMIZE_MOD not yet supported on this platform." +#endif // CPU(ARM_TRADITIONAL) +#endif } // namespace JSC #endif // ENABLE(JIT) diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp index bf5168b..85471de 100644 --- a/JavaScriptCore/jit/JITStubs.cpp +++ b/JavaScriptCore/jit/JITStubs.cpp @@ -757,7 +757,7 @@ extern "C" { JITThunks::JITThunks(JSGlobalData* globalData) { - JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &m_ctiNativeCallThunk); + JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_trampolineStructure); #if CPU(ARM_THUMB2) // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types), diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h index 99c2dd2..17fd0d9 100644 --- a/JavaScriptCore/jit/JITStubs.h +++ b/JavaScriptCore/jit/JITStubs.h @@ -74,6 +74,14 @@ namespace JSC { JSString* jsString() { return static_cast<JSString*>(asPointer); } ReturnAddressPtr returnAddress() { return ReturnAddressPtr(asPointer); } }; + + struct TrampolineStructure { + MacroAssemblerCodePtr ctiStringLengthTrampoline; + MacroAssemblerCodePtr ctiVirtualCallLink; + MacroAssemblerCodePtr ctiVirtualCall; + MacroAssemblerCodePtr ctiNativeCallThunk; + MacroAssemblerCodePtr ctiSoftModulo; + }; #if CPU(X86_64) struct JITStackFrame { @@ -239,18 +247,16 @@ namespace JSC { static void tryCacheGetByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot&, StructureStubInfo* stubInfo); static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&, StructureStubInfo* stubInfo); - MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_ctiStringLengthTrampoline; } - MacroAssemblerCodePtr ctiVirtualCallLink() { return m_ctiVirtualCallLink; } - MacroAssemblerCodePtr ctiVirtualCall() { return m_ctiVirtualCall; } - MacroAssemblerCodePtr ctiNativeCallThunk() { return m_ctiNativeCallThunk; } + MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_trampolineStructure.ctiStringLengthTrampoline; } + MacroAssemblerCodePtr ctiVirtualCallLink() { return m_trampolineStructure.ctiVirtualCallLink; } + MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; } + MacroAssemblerCodePtr ctiNativeCallThunk() { return m_trampolineStructure.ctiNativeCallThunk; } + MacroAssemblerCodePtr ctiSoftModulo() { return m_trampolineStructure.ctiSoftModulo; } private: RefPtr<ExecutablePool> m_executablePool; - MacroAssemblerCodePtr m_ctiStringLengthTrampoline; - MacroAssemblerCodePtr m_ctiVirtualCallLink; - MacroAssemblerCodePtr m_ctiVirtualCall; - MacroAssemblerCodePtr m_ctiNativeCallThunk; + TrampolineStructure m_trampolineStructure; }; extern "C" { diff --git a/JavaScriptCore/parser/Grammar.y b/JavaScriptCore/parser/Grammar.y index 717a266..a017cff 100644 --- a/JavaScriptCore/parser/Grammar.y +++ b/JavaScriptCore/parser/Grammar.y @@ -1147,7 +1147,7 @@ ThrowStatement: ; TryStatement: - TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->nullIdentifier, false, 0, $4.m_node), + TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->emptyIdentifier, false, 0, $4.m_node), mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations), mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations), $2.m_features | $4.m_features, @@ -1188,10 +1188,10 @@ FunctionDeclaration: ; FunctionExpr: - FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $5, GLOBAL_DATA->lexer->sourceCode($4, $6, @4.first_line)), ClosureFeature, 0); setStatementLocation($5, @4, @6); } + FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->emptyIdentifier, $5, GLOBAL_DATA->lexer->sourceCode($4, $6, @4.first_line)), ClosureFeature, 0); setStatementLocation($5, @4, @6); } | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE { - $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line), $3.m_node.head), $3.m_features | ClosureFeature, 0); + $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->emptyIdentifier, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line), $3.m_node.head), $3.m_features | ClosureFeature, 0); if ($3.m_features & ArgumentsFeature) $6->setUsesArguments(); setStatementLocation($6, @5, @7); @@ -1981,7 +1981,7 @@ static PropertyNode* makeGetterOrSetterPropertyNode(JSGlobalData* globalData, co type = PropertyNode::Setter; else return 0; - return new (globalData) PropertyNode(globalData, name, new (globalData) FuncExprNode(globalData, globalData->propertyNames->nullIdentifier, body, source, params), type); + return new (globalData) PropertyNode(globalData, name, new (globalData) FuncExprNode(globalData, globalData->propertyNames->emptyIdentifier, body, source, params), type); } static ExpressionNode* makeNegateNode(JSGlobalData* globalData, ExpressionNode* n) diff --git a/JavaScriptCore/parser/NodeConstructors.h b/JavaScriptCore/parser/NodeConstructors.h index dd3b981..fa8dd4b 100644 --- a/JavaScriptCore/parser/NodeConstructors.h +++ b/JavaScriptCore/parser/NodeConstructors.h @@ -741,7 +741,7 @@ namespace JSC { inline ContinueNode::ContinueNode(JSGlobalData* globalData) : StatementNode(globalData) - , m_ident(globalData->propertyNames->nullIdentifier) + , m_ident(globalData->propertyNames->emptyIdentifier) { } @@ -753,7 +753,7 @@ namespace JSC { inline BreakNode::BreakNode(JSGlobalData* globalData) : StatementNode(globalData) - , m_ident(globalData->propertyNames->nullIdentifier) + , m_ident(globalData->propertyNames->emptyIdentifier) { } @@ -877,7 +877,7 @@ namespace JSC { inline ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement) : StatementNode(globalData) - , m_ident(globalData->propertyNames->nullIdentifier) + , m_ident(globalData->propertyNames->emptyIdentifier) , m_init(0) , m_lexpr(l) , m_expr(expr) diff --git a/JavaScriptCore/parser/Parser.cpp b/JavaScriptCore/parser/Parser.cpp index 003ca0b..56c96b4 100644 --- a/JavaScriptCore/parser/Parser.cpp +++ b/JavaScriptCore/parser/Parser.cpp @@ -57,7 +57,7 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg) errMsg = &defaultErrMsg; *errLine = -1; - *errMsg = 0; + *errMsg = UString(); Lexer& lexer = *globalData->lexer; lexer.setCode(*m_source, m_arena); diff --git a/JavaScriptCore/profiler/Profile.cpp b/JavaScriptCore/profiler/Profile.cpp index de75e71..c90f9b0 100644 --- a/JavaScriptCore/profiler/Profile.cpp +++ b/JavaScriptCore/profiler/Profile.cpp @@ -42,7 +42,7 @@ Profile::Profile(const UString& title, unsigned uid) { // FIXME: When multi-threading is supported this will be a vector and calls // into the profiler will need to know which thread it is executing on. - m_head = ProfileNode::create(CallIdentifier("Thread_1", 0, 0), 0, 0); + m_head = ProfileNode::create(CallIdentifier("Thread_1", UString(), 0), 0, 0); } Profile::~Profile() diff --git a/JavaScriptCore/profiler/ProfileGenerator.cpp b/JavaScriptCore/profiler/ProfileGenerator.cpp index 17d37d7..f367033 100644 --- a/JavaScriptCore/profiler/ProfileGenerator.cpp +++ b/JavaScriptCore/profiler/ProfileGenerator.cpp @@ -124,7 +124,7 @@ void ProfileGenerator::stopProfiling() m_currentNode = m_currentNode->parent(); if (double headSelfTime = m_head->selfTime()) { - RefPtr<ProfileNode> idleNode = ProfileNode::create(CallIdentifier(NonJSExecution, 0, 0), m_head.get(), m_head.get()); + RefPtr<ProfileNode> idleNode = ProfileNode::create(CallIdentifier(NonJSExecution, UString(), 0), m_head.get(), m_head.get()); idleNode->setTotalTime(headSelfTime); idleNode->setSelfTime(headSelfTime); diff --git a/JavaScriptCore/qt/api/qscriptengine.cpp b/JavaScriptCore/qt/api/qscriptengine.cpp index f12f410..fbeb902 100644 --- a/JavaScriptCore/qt/api/qscriptengine.cpp +++ b/JavaScriptCore/qt/api/qscriptengine.cpp @@ -86,3 +86,23 @@ void QScriptEngine::collectGarbage() { d_ptr->collectGarbage(); } + +/*! + Returns a QScriptValue of the primitive type Null. + + \sa undefinedValue() +*/ +QScriptValue QScriptEngine::nullValue() +{ + return QScriptValue(this, QScriptValue::NullValue); +} + +/*! + Returns a QScriptValue of the primitive type Undefined. + + \sa nullValue() +*/ +QScriptValue QScriptEngine::undefinedValue() +{ + return QScriptValue(this, QScriptValue::UndefinedValue); +} diff --git a/JavaScriptCore/qt/api/qscriptengine.h b/JavaScriptCore/qt/api/qscriptengine.h index cf61d35..b8bd5e6 100644 --- a/JavaScriptCore/qt/api/qscriptengine.h +++ b/JavaScriptCore/qt/api/qscriptengine.h @@ -38,6 +38,8 @@ public: QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1); void collectGarbage(); + QScriptValue nullValue(); + QScriptValue undefinedValue(); private: friend class QScriptEnginePrivate; diff --git a/JavaScriptCore/qt/api/qscriptvalue_p.h b/JavaScriptCore/qt/api/qscriptvalue_p.h index 6a5b388..dea2298 100644 --- a/JavaScriptCore/qt/api/qscriptvalue_p.h +++ b/JavaScriptCore/qt/api/qscriptvalue_p.h @@ -24,6 +24,8 @@ #include "qscriptengine_p.h" #include "qscriptvalue.h" #include <JavaScriptCore/JavaScript.h> +#include <QtCore/qmath.h> +#include <QtCore/qnumeric.h> #include <QtCore/qshareddata.h> #include <QtCore/qvarlengtharray.h> @@ -337,7 +339,7 @@ bool QScriptValuePrivate::isNumber() { switch (m_state) { case CNumber: - return m_number; + return true; case JSValue: if (isObject()) return false; @@ -468,20 +470,30 @@ QString QScriptValuePrivate::toString() const qsreal QScriptValuePrivate::toNumber() const { - // TODO Check it. switch (m_state) { case JSValue: case JSNative: case JSObject: return JSValueToNumber(context(), value(), /* exception */ 0); case CNumber: - case CBool: return m_number; + case CBool: + return m_number ? 1 : 0; case Invalid: + return 0; case CSpecial: - return false; + return m_number == QScriptValue::NullValue ? 0 : qQNaN(); case CString: - return m_string.isEmpty(); + bool ok; + qsreal result = m_string.toDouble(&ok); + if (ok) + return result; + result = m_string.toInt(&ok, 0); // Try other bases. + if (ok) + return result; + if (m_string == "Infinity" || m_string == "-Infinity") + return qInf(); + return m_string.length() ? qQNaN() : 0; } Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement."); @@ -493,16 +505,18 @@ bool QScriptValuePrivate::toBool() const switch (m_state) { case JSValue: case JSNative: - case JSObject: return JSValueToBoolean(context(), value()); + case JSObject: + return true; case CNumber: + return !(qIsNaN(m_number) || !m_number); case CBool: return m_number; case Invalid: case CSpecial: return false; case CString: - return m_string.isEmpty(); + return m_string.length(); } Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement."); diff --git a/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp b/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp index 37f3d11..b36e364 100644 --- a/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp +++ b/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp @@ -35,6 +35,8 @@ public slots: private slots: void evaluate(); void collectGarbage(); + void nullValue(); + void undefinedValue(); }; /* Evaluating a script that throw an unhandled exception should return an invalid value. */ @@ -54,5 +56,22 @@ void tst_QScriptEngine::collectGarbage() engine.collectGarbage(); QCOMPARE(foo.call().toString(), QString::fromAscii("pong")); } + +void tst_QScriptEngine::nullValue() +{ + QScriptEngine engine; + QScriptValue value = engine.nullValue(); + QVERIFY(value.isValid()); + QVERIFY(value.isNull()); +} + +void tst_QScriptEngine::undefinedValue() +{ + QScriptEngine engine; + QScriptValue value = engine.undefinedValue(); + QVERIFY(value.isValid()); + QVERIFY(value.isUndefined()); +} + QTEST_MAIN(tst_QScriptEngine) #include "tst_qscriptengine.moc" diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h index ae81c49..828ef96 100644 --- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h +++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h @@ -55,6 +55,9 @@ private slots: void isBoolean_data(); void isBoolean(); + void isNumber_data(); + void isNumber(); + void isFunction_data(); void isFunction(); @@ -73,6 +76,15 @@ private slots: void isValid_data(); void isValid(); + void toNumber_data(); + void toNumber(); + + void toBool_data(); + void toBool(); + + void toBoolean_data(); + void toBoolean(); + private: typedef void (tst_QScriptValue::*InitDataFunction)(); typedef void (tst_QScriptValue::*DefineDataFunction)(const char*); @@ -94,6 +106,10 @@ private: void isBoolean_makeData(const char* expr); void isBoolean_test(const char* expr, const QScriptValue& value); + void isNumber_initData(); + void isNumber_makeData(const char* expr); + void isNumber_test(const char* expr, const QScriptValue&); + void isFunction_initData(); void isFunction_makeData(const char* expr); void isFunction_test(const char* expr, const QScriptValue& value); @@ -118,6 +134,18 @@ private: void isValid_makeData(const char* expr); void isValid_test(const char* expr, const QScriptValue& value); + void toNumber_initData(); + void toNumber_makeData(const char*); + void toNumber_test(const char*, const QScriptValue&); + + void toBool_initData(); + void toBool_makeData(const char*); + void toBool_test(const char*, const QScriptValue&); + + void toBoolean_initData(); + void toBoolean_makeData(const char*); + void toBoolean_test(const char*, const QScriptValue&); + private: QScriptEngine* engine; QHash<QString, QScriptValue> m_values; diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp index 6d8ef48..f9891a6 100644 --- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp +++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp @@ -315,6 +315,70 @@ void tst_QScriptValue::isBoolean_test(const char*, const QScriptValue& value) DEFINE_TEST_FUNCTION(isBoolean) +void tst_QScriptValue::isNumber_initData() +{ + QTest::addColumn<bool>("expected"); + initScriptValues(); +} + +void tst_QScriptValue::isNumber_makeData(const char* expr) +{ + static QSet<QString> isNumber; + if (isNumber.isEmpty()) { + isNumber << "QScriptValue(int(122))" + << "QScriptValue(uint(124))" + << "QScriptValue(0)" + << "QScriptValue(0.0)" + << "QScriptValue(123.0)" + << "QScriptValue(6.37e-8)" + << "QScriptValue(-6.37e-8)" + << "QScriptValue(0x43211234)" + << "QScriptValue(0x10000)" + << "QScriptValue(0x10001)" + << "QScriptValue(qSNaN())" + << "QScriptValue(qQNaN())" + << "QScriptValue(qInf())" + << "QScriptValue(-qInf())" + << "QScriptValue(0, int(122))" + << "QScriptValue(0, uint(124))" + << "QScriptValue(0, 0)" + << "QScriptValue(0, 0.0)" + << "QScriptValue(0, 123.0)" + << "QScriptValue(0, 6.37e-8)" + << "QScriptValue(0, -6.37e-8)" + << "QScriptValue(0, 0x43211234)" + << "QScriptValue(0, 0x10000)" + << "QScriptValue(0, 0x10001)" + << "QScriptValue(0, qSNaN())" + << "QScriptValue(0, qQNaN())" + << "QScriptValue(0, qInf())" + << "QScriptValue(0, -qInf())" + << "QScriptValue(engine, int(122))" + << "QScriptValue(engine, uint(124))" + << "QScriptValue(engine, 0)" + << "QScriptValue(engine, 0.0)" + << "QScriptValue(engine, 123.0)" + << "QScriptValue(engine, 6.37e-8)" + << "QScriptValue(engine, -6.37e-8)" + << "QScriptValue(engine, 0x43211234)" + << "QScriptValue(engine, 0x10000)" + << "QScriptValue(engine, 0x10001)" + << "QScriptValue(engine, qSNaN())" + << "QScriptValue(engine, qQNaN())" + << "QScriptValue(engine, qInf())" + << "QScriptValue(engine, -qInf())"; + } + newRow(expr) << isNumber.contains(expr); +} + +void tst_QScriptValue::isNumber_test(const char*, const QScriptValue& value) +{ + QFETCH(bool, expected); + QCOMPARE(value.isNumber(), expected); +} + +DEFINE_TEST_FUNCTION(isNumber) + void tst_QScriptValue::isFunction_initData() { @@ -492,4 +556,387 @@ void tst_QScriptValue::isObject_test(const char*, const QScriptValue& value) DEFINE_TEST_FUNCTION(isObject) +void tst_QScriptValue::toNumber_initData() +{ + QTest::addColumn<qsreal>("expected"); + initScriptValues(); +} + +void tst_QScriptValue::toNumber_makeData(const char* expr) +{ + static QHash<QString, qsreal> toNumber; + if (toNumber.isEmpty()) { + toNumber.insert("QScriptValue()", 0); + toNumber.insert("QScriptValue(QScriptValue::UndefinedValue)", qQNaN()); + toNumber.insert("QScriptValue(QScriptValue::NullValue)", 0); + toNumber.insert("QScriptValue(true)", 1); + toNumber.insert("QScriptValue(false)", 0); + toNumber.insert("QScriptValue(int(122))", 122); + toNumber.insert("QScriptValue(uint(124))", 124); + toNumber.insert("QScriptValue(0)", 0); + toNumber.insert("QScriptValue(0.0)", 0); + toNumber.insert("QScriptValue(123.0)", 123); + toNumber.insert("QScriptValue(6.37e-8)", 6.369999999999999e-08); + toNumber.insert("QScriptValue(-6.37e-8)", -6.369999999999999e-08); + toNumber.insert("QScriptValue(0x43211234)", 1126240820); + toNumber.insert("QScriptValue(0x10000)", 65536); + toNumber.insert("QScriptValue(0x10001)", 65537); + toNumber.insert("QScriptValue(qSNaN())", qQNaN()); + toNumber.insert("QScriptValue(qQNaN())", qQNaN()); + toNumber.insert("QScriptValue(qInf())", qInf()); + toNumber.insert("QScriptValue(-qInf())", qInf()); + toNumber.insert("QScriptValue(\"NaN\")", qQNaN()); + toNumber.insert("QScriptValue(\"Infinity\")", qInf()); + toNumber.insert("QScriptValue(\"-Infinity\")", qInf()); + toNumber.insert("QScriptValue(\"ciao\")", qQNaN()); + toNumber.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", qQNaN()); + toNumber.insert("QScriptValue(QString(\"\"))", 0); + toNumber.insert("QScriptValue(QString())", 0); + toNumber.insert("QScriptValue(QString(\"0\"))", 0); + toNumber.insert("QScriptValue(QString(\"123\"))", 123); + toNumber.insert("QScriptValue(QString(\"12.4\"))", 12.4); + toNumber.insert("QScriptValue(0, QScriptValue::UndefinedValue)", qQNaN()); + toNumber.insert("QScriptValue(0, QScriptValue::NullValue)", 0); + toNumber.insert("QScriptValue(0, true)", 1); + toNumber.insert("QScriptValue(0, false)", 0); + toNumber.insert("QScriptValue(0, int(122))", 122); + toNumber.insert("QScriptValue(0, uint(124))", 124); + toNumber.insert("QScriptValue(0, 0)", 0); + toNumber.insert("QScriptValue(0, 0.0)", 0); + toNumber.insert("QScriptValue(0, 123.0)", 123); + toNumber.insert("QScriptValue(0, 6.37e-8)", 6.369999999999999e-08); + toNumber.insert("QScriptValue(0, -6.37e-8)", -6.369999999999999e-08); + toNumber.insert("QScriptValue(0, 0x43211234)", 1126240820); + toNumber.insert("QScriptValue(0, 0x10000)", 65536); + toNumber.insert("QScriptValue(0, 0x10001)", 65537); + toNumber.insert("QScriptValue(0, qSNaN())", qQNaN()); + toNumber.insert("QScriptValue(0, qQNaN())", qQNaN()); + toNumber.insert("QScriptValue(0, qInf())", qInf()); + toNumber.insert("QScriptValue(0, -qInf())", qInf()); + toNumber.insert("QScriptValue(0, \"NaN\")", qQNaN()); + toNumber.insert("QScriptValue(0, \"Infinity\")", qInf()); + toNumber.insert("QScriptValue(0, \"-Infinity\")", qInf()); + toNumber.insert("QScriptValue(0, \"ciao\")", qQNaN()); + toNumber.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", qQNaN()); + toNumber.insert("QScriptValue(0, QString(\"\"))", 0); + toNumber.insert("QScriptValue(0, QString())", 0); + toNumber.insert("QScriptValue(0, QString(\"0\"))", 0); + toNumber.insert("QScriptValue(0, QString(\"123\"))", 123); + toNumber.insert("QScriptValue(0, QString(\"12.3\"))", 12.3); + toNumber.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", qQNaN()); + toNumber.insert("QScriptValue(engine, QScriptValue::NullValue)", 0); + toNumber.insert("QScriptValue(engine, true)", 1); + toNumber.insert("QScriptValue(engine, false)", 0); + toNumber.insert("QScriptValue(engine, int(122))", 122); + toNumber.insert("QScriptValue(engine, uint(124))", 124); + toNumber.insert("QScriptValue(engine, 0)", 0); + toNumber.insert("QScriptValue(engine, 0.0)", 0); + toNumber.insert("QScriptValue(engine, 123.0)", 123); + toNumber.insert("QScriptValue(engine, 6.37e-8)", 6.369999999999999e-08); + toNumber.insert("QScriptValue(engine, -6.37e-8)", -6.369999999999999e-08); + toNumber.insert("QScriptValue(engine, 0x43211234)", 1126240820); + toNumber.insert("QScriptValue(engine, 0x10000)", 65536); + toNumber.insert("QScriptValue(engine, 0x10001)", 65537); + toNumber.insert("QScriptValue(engine, qSNaN())", qQNaN()); + toNumber.insert("QScriptValue(engine, qQNaN())", qQNaN()); + toNumber.insert("QScriptValue(engine, qInf())", qInf()); + toNumber.insert("QScriptValue(engine, -qInf())", qInf()); + toNumber.insert("QScriptValue(engine, \"NaN\")", qQNaN()); + toNumber.insert("QScriptValue(engine, \"Infinity\")", qInf()); + toNumber.insert("QScriptValue(engine, \"-Infinity\")", qInf()); + toNumber.insert("QScriptValue(engine, \"ciao\")", qQNaN()); + toNumber.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", qQNaN()); + toNumber.insert("QScriptValue(engine, QString(\"\"))", 0); + toNumber.insert("QScriptValue(engine, QString())", 0); + toNumber.insert("QScriptValue(engine, QString(\"0\"))", 0); + toNumber.insert("QScriptValue(engine, QString(\"123\"))", 123); + toNumber.insert("QScriptValue(engine, QString(\"1.23\"))", 1.23); + toNumber.insert("engine->evaluate(\"[]\")", 0); + toNumber.insert("engine->evaluate(\"{}\")", qQNaN()); + toNumber.insert("engine->evaluate(\"Object.prototype\")", qQNaN()); + toNumber.insert("engine->evaluate(\"Date.prototype\")", qQNaN()); + toNumber.insert("engine->evaluate(\"Array.prototype\")", 0); + toNumber.insert("engine->evaluate(\"Function.prototype\")", qQNaN()); + toNumber.insert("engine->evaluate(\"Error.prototype\")", qQNaN()); + toNumber.insert("engine->evaluate(\"Object\")", qQNaN()); + toNumber.insert("engine->evaluate(\"Array\")", qQNaN()); + toNumber.insert("engine->evaluate(\"Number\")", qQNaN()); + toNumber.insert("engine->evaluate(\"Function\")", qQNaN()); + toNumber.insert("engine->evaluate(\"(function() { return 1; })\")", qQNaN()); + toNumber.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", qQNaN()); + toNumber.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", qQNaN()); + toNumber.insert("engine->evaluate(\"/foo/\")", qQNaN()); + toNumber.insert("engine->evaluate(\"new Object()\")", qQNaN()); + toNumber.insert("engine->evaluate(\"new Array()\")", 0); + toNumber.insert("engine->evaluate(\"new Error()\")", qQNaN()); + } + newRow(expr) << toNumber.value(expr); +} + +void tst_QScriptValue::toNumber_test(const char*, const QScriptValue& value) +{ + QFETCH(qsreal, expected); + if (qIsNaN(expected)) { + QVERIFY(qIsNaN(value.toNumber())); + return; + } + if (qIsInf(expected)) { + QVERIFY(qIsInf(value.toNumber())); + return; + } + QCOMPARE(value.toNumber(), expected); +} + +DEFINE_TEST_FUNCTION(toNumber) + + +void tst_QScriptValue::toBool_initData() +{ + QTest::addColumn<bool>("expected"); + initScriptValues(); +} + +void tst_QScriptValue::toBool_makeData(const char* expr) +{ + static QHash<QString, bool> toBool; + if (toBool.isEmpty()) { + toBool.insert("QScriptValue()", false); + toBool.insert("QScriptValue(QScriptValue::UndefinedValue)", false); + toBool.insert("QScriptValue(QScriptValue::NullValue)", false); + toBool.insert("QScriptValue(true)", true); + toBool.insert("QScriptValue(false)", false); + toBool.insert("QScriptValue(int(122))", true); + toBool.insert("QScriptValue(uint(124))", true); + toBool.insert("QScriptValue(0)", false); + toBool.insert("QScriptValue(0.0)", false); + toBool.insert("QScriptValue(123.0)", true); + toBool.insert("QScriptValue(6.37e-8)", true); + toBool.insert("QScriptValue(-6.37e-8)", true); + toBool.insert("QScriptValue(0x43211234)", true); + toBool.insert("QScriptValue(0x10000)", true); + toBool.insert("QScriptValue(0x10001)", true); + toBool.insert("QScriptValue(qSNaN())", false); + toBool.insert("QScriptValue(qQNaN())", false); + toBool.insert("QScriptValue(qInf())", true); + toBool.insert("QScriptValue(-qInf())", true); + toBool.insert("QScriptValue(\"NaN\")", true); + toBool.insert("QScriptValue(\"Infinity\")", true); + toBool.insert("QScriptValue(\"-Infinity\")", true); + toBool.insert("QScriptValue(\"ciao\")", true); + toBool.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", true); + toBool.insert("QScriptValue(QString(\"\"))", false); + toBool.insert("QScriptValue(QString())", false); + toBool.insert("QScriptValue(QString(\"0\"))", true); + toBool.insert("QScriptValue(QString(\"123\"))", true); + toBool.insert("QScriptValue(QString(\"12.4\"))", true); + toBool.insert("QScriptValue(0, QScriptValue::UndefinedValue)", false); + toBool.insert("QScriptValue(0, QScriptValue::NullValue)", false); + toBool.insert("QScriptValue(0, true)", true); + toBool.insert("QScriptValue(0, false)", false); + toBool.insert("QScriptValue(0, int(122))", true); + toBool.insert("QScriptValue(0, uint(124))", true); + toBool.insert("QScriptValue(0, 0)", false); + toBool.insert("QScriptValue(0, 0.0)", false); + toBool.insert("QScriptValue(0, 123.0)", true); + toBool.insert("QScriptValue(0, 6.37e-8)", true); + toBool.insert("QScriptValue(0, -6.37e-8)", true); + toBool.insert("QScriptValue(0, 0x43211234)", true); + toBool.insert("QScriptValue(0, 0x10000)", true); + toBool.insert("QScriptValue(0, 0x10001)", true); + toBool.insert("QScriptValue(0, qSNaN())", false); + toBool.insert("QScriptValue(0, qQNaN())", false); + toBool.insert("QScriptValue(0, qInf())", true); + toBool.insert("QScriptValue(0, -qInf())", true); + toBool.insert("QScriptValue(0, \"NaN\")", true); + toBool.insert("QScriptValue(0, \"Infinity\")", true); + toBool.insert("QScriptValue(0, \"-Infinity\")", true); + toBool.insert("QScriptValue(0, \"ciao\")", true); + toBool.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", true); + toBool.insert("QScriptValue(0, QString(\"\"))", false); + toBool.insert("QScriptValue(0, QString())", false); + toBool.insert("QScriptValue(0, QString(\"0\"))", true); + toBool.insert("QScriptValue(0, QString(\"123\"))", true); + toBool.insert("QScriptValue(0, QString(\"12.3\"))", true); + toBool.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", false); + toBool.insert("QScriptValue(engine, QScriptValue::NullValue)", false); + toBool.insert("QScriptValue(engine, true)", true); + toBool.insert("QScriptValue(engine, false)", false); + toBool.insert("QScriptValue(engine, int(122))", true); + toBool.insert("QScriptValue(engine, uint(124))", true); + toBool.insert("QScriptValue(engine, 0)", false); + toBool.insert("QScriptValue(engine, 0.0)", false); + toBool.insert("QScriptValue(engine, 123.0)", true); + toBool.insert("QScriptValue(engine, 6.37e-8)", true); + toBool.insert("QScriptValue(engine, -6.37e-8)", true); + toBool.insert("QScriptValue(engine, 0x43211234)", true); + toBool.insert("QScriptValue(engine, 0x10000)", true); + toBool.insert("QScriptValue(engine, 0x10001)", true); + toBool.insert("QScriptValue(engine, qSNaN())", false); + toBool.insert("QScriptValue(engine, qQNaN())", false); + toBool.insert("QScriptValue(engine, qInf())", true); + toBool.insert("QScriptValue(engine, -qInf())", true); + toBool.insert("QScriptValue(engine, \"NaN\")", true); + toBool.insert("QScriptValue(engine, \"Infinity\")", true); + toBool.insert("QScriptValue(engine, \"-Infinity\")", true); + toBool.insert("QScriptValue(engine, \"ciao\")", true); + toBool.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", true); + toBool.insert("QScriptValue(engine, QString(\"\"))", false); + toBool.insert("QScriptValue(engine, QString())", false); + toBool.insert("QScriptValue(engine, QString(\"0\"))", true); + toBool.insert("QScriptValue(engine, QString(\"123\"))", true); + toBool.insert("QScriptValue(engine, QString(\"1.23\"))", true); + toBool.insert("engine->evaluate(\"[]\")", true); + toBool.insert("engine->evaluate(\"{}\")", false); + toBool.insert("engine->evaluate(\"Object.prototype\")", true); + toBool.insert("engine->evaluate(\"Date.prototype\")", true); + toBool.insert("engine->evaluate(\"Array.prototype\")", true); + toBool.insert("engine->evaluate(\"Function.prototype\")", true); + toBool.insert("engine->evaluate(\"Error.prototype\")", true); + toBool.insert("engine->evaluate(\"Object\")", true); + toBool.insert("engine->evaluate(\"Array\")", true); + toBool.insert("engine->evaluate(\"Number\")", true); + toBool.insert("engine->evaluate(\"Function\")", true); + toBool.insert("engine->evaluate(\"(function() { return 1; })\")", true); + toBool.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", true); + toBool.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", true); + toBool.insert("engine->evaluate(\"/foo/\")", true); + toBool.insert("engine->evaluate(\"new Object()\")", true); + toBool.insert("engine->evaluate(\"new Array()\")", true); + toBool.insert("engine->evaluate(\"new Error()\")", true); + } + newRow(expr) << toBool.value(expr); +} + +void tst_QScriptValue::toBool_test(const char*, const QScriptValue& value) +{ + QFETCH(bool, expected); + QCOMPARE(value.toBool(), expected); +} + +DEFINE_TEST_FUNCTION(toBool) + + +void tst_QScriptValue::toBoolean_initData() +{ + QTest::addColumn<bool>("expected"); + initScriptValues(); +} + +void tst_QScriptValue::toBoolean_makeData(const char* expr) +{ + static QHash<QString, bool> toBoolean; + if (toBoolean.isEmpty()) { + toBoolean.insert("QScriptValue()", false); + toBoolean.insert("QScriptValue(QScriptValue::UndefinedValue)", false); + toBoolean.insert("QScriptValue(QScriptValue::NullValue)", false); + toBoolean.insert("QScriptValue(true)", true); + toBoolean.insert("QScriptValue(false)", false); + toBoolean.insert("QScriptValue(int(122))", true); + toBoolean.insert("QScriptValue(uint(124))", true); + toBoolean.insert("QScriptValue(0)", false); + toBoolean.insert("QScriptValue(0.0)", false); + toBoolean.insert("QScriptValue(123.0)", true); + toBoolean.insert("QScriptValue(6.37e-8)", true); + toBoolean.insert("QScriptValue(-6.37e-8)", true); + toBoolean.insert("QScriptValue(0x43211234)", true); + toBoolean.insert("QScriptValue(0x10000)", true); + toBoolean.insert("QScriptValue(0x10001)", true); + toBoolean.insert("QScriptValue(qSNaN())", false); + toBoolean.insert("QScriptValue(qQNaN())", false); + toBoolean.insert("QScriptValue(qInf())", true); + toBoolean.insert("QScriptValue(-qInf())", true); + toBoolean.insert("QScriptValue(\"NaN\")", true); + toBoolean.insert("QScriptValue(\"Infinity\")", true); + toBoolean.insert("QScriptValue(\"-Infinity\")", true); + toBoolean.insert("QScriptValue(\"ciao\")", true); + toBoolean.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", true); + toBoolean.insert("QScriptValue(QString(\"\"))", false); + toBoolean.insert("QScriptValue(QString())", false); + toBoolean.insert("QScriptValue(QString(\"0\"))", true); + toBoolean.insert("QScriptValue(QString(\"123\"))", true); + toBoolean.insert("QScriptValue(QString(\"12.4\"))", true); + toBoolean.insert("QScriptValue(0, QScriptValue::UndefinedValue)", false); + toBoolean.insert("QScriptValue(0, QScriptValue::NullValue)", false); + toBoolean.insert("QScriptValue(0, true)", true); + toBoolean.insert("QScriptValue(0, false)", false); + toBoolean.insert("QScriptValue(0, int(122))", true); + toBoolean.insert("QScriptValue(0, uint(124))", true); + toBoolean.insert("QScriptValue(0, 0)", false); + toBoolean.insert("QScriptValue(0, 0.0)", false); + toBoolean.insert("QScriptValue(0, 123.0)", true); + toBoolean.insert("QScriptValue(0, 6.37e-8)", true); + toBoolean.insert("QScriptValue(0, -6.37e-8)", true); + toBoolean.insert("QScriptValue(0, 0x43211234)", true); + toBoolean.insert("QScriptValue(0, 0x10000)", true); + toBoolean.insert("QScriptValue(0, 0x10001)", true); + toBoolean.insert("QScriptValue(0, qSNaN())", false); + toBoolean.insert("QScriptValue(0, qQNaN())", false); + toBoolean.insert("QScriptValue(0, qInf())", true); + toBoolean.insert("QScriptValue(0, -qInf())", true); + toBoolean.insert("QScriptValue(0, \"NaN\")", true); + toBoolean.insert("QScriptValue(0, \"Infinity\")", true); + toBoolean.insert("QScriptValue(0, \"-Infinity\")", true); + toBoolean.insert("QScriptValue(0, \"ciao\")", true); + toBoolean.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", true); + toBoolean.insert("QScriptValue(0, QString(\"\"))", false); + toBoolean.insert("QScriptValue(0, QString())", false); + toBoolean.insert("QScriptValue(0, QString(\"0\"))", true); + toBoolean.insert("QScriptValue(0, QString(\"123\"))", true); + toBoolean.insert("QScriptValue(0, QString(\"12.3\"))", true); + toBoolean.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", false); + toBoolean.insert("QScriptValue(engine, QScriptValue::NullValue)", false); + toBoolean.insert("QScriptValue(engine, true)", true); + toBoolean.insert("QScriptValue(engine, false)", false); + toBoolean.insert("QScriptValue(engine, int(122))", true); + toBoolean.insert("QScriptValue(engine, uint(124))", true); + toBoolean.insert("QScriptValue(engine, 0)", false); + toBoolean.insert("QScriptValue(engine, 0.0)", false); + toBoolean.insert("QScriptValue(engine, 123.0)", true); + toBoolean.insert("QScriptValue(engine, 6.37e-8)", true); + toBoolean.insert("QScriptValue(engine, -6.37e-8)", true); + toBoolean.insert("QScriptValue(engine, 0x43211234)", true); + toBoolean.insert("QScriptValue(engine, 0x10000)", true); + toBoolean.insert("QScriptValue(engine, 0x10001)", true); + toBoolean.insert("QScriptValue(engine, qSNaN())", false); + toBoolean.insert("QScriptValue(engine, qQNaN())", false); + toBoolean.insert("QScriptValue(engine, qInf())", true); + toBoolean.insert("QScriptValue(engine, -qInf())", true); + toBoolean.insert("QScriptValue(engine, \"NaN\")", true); + toBoolean.insert("QScriptValue(engine, \"Infinity\")", true); + toBoolean.insert("QScriptValue(engine, \"-Infinity\")", true); + toBoolean.insert("QScriptValue(engine, \"ciao\")", true); + toBoolean.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", true); + toBoolean.insert("QScriptValue(engine, QString(\"\"))", false); + toBoolean.insert("QScriptValue(engine, QString())", false); + toBoolean.insert("QScriptValue(engine, QString(\"0\"))", true); + toBoolean.insert("QScriptValue(engine, QString(\"123\"))", true); + toBoolean.insert("QScriptValue(engine, QString(\"1.23\"))", true); + toBoolean.insert("engine->evaluate(\"[]\")", true); + toBoolean.insert("engine->evaluate(\"{}\")", false); + toBoolean.insert("engine->evaluate(\"Object.prototype\")", true); + toBoolean.insert("engine->evaluate(\"Date.prototype\")", true); + toBoolean.insert("engine->evaluate(\"Array.prototype\")", true); + toBoolean.insert("engine->evaluate(\"Function.prototype\")", true); + toBoolean.insert("engine->evaluate(\"Error.prototype\")", true); + toBoolean.insert("engine->evaluate(\"Object\")", true); + toBoolean.insert("engine->evaluate(\"Array\")", true); + toBoolean.insert("engine->evaluate(\"Number\")", true); + toBoolean.insert("engine->evaluate(\"Function\")", true); + toBoolean.insert("engine->evaluate(\"(function() { return 1; })\")", true); + toBoolean.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", true); + toBoolean.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", true); + toBoolean.insert("engine->evaluate(\"/foo/\")", true); + toBoolean.insert("engine->evaluate(\"new Object()\")", true); + toBoolean.insert("engine->evaluate(\"new Array()\")", true); + toBoolean.insert("engine->evaluate(\"new Error()\")", true); + } + newRow(expr) << toBoolean.value(expr); +} + +void tst_QScriptValue::toBoolean_test(const char*, const QScriptValue& value) +{ + QFETCH(bool, expected); + QCOMPARE(value.toBoolean(), expected); +} +DEFINE_TEST_FUNCTION(toBoolean) diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp index ce814b2..b64abad 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -28,6 +28,7 @@ #include "CachedCall.h" #include "Interpreter.h" #include "JIT.h" +#include "JSStringBuilder.h" #include "ObjectPrototype.h" #include "Lookup.h" #include "Operations.h" @@ -182,8 +183,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue totalSize += str.size(); if (!strBuffer.data()) { - JSObject* error = Error::create(exec, GeneralError, "Out of memory"); - exec->setException(error); + throwOutOfMemoryError(exec); } if (exec->hadException()) @@ -195,7 +195,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue Vector<UChar> buffer; buffer.reserveCapacity(totalSize); if (!buffer.data()) - return throwError(exec, GeneralError, "Out of memory"); + return throwOutOfMemoryError(exec); for (unsigned i = 0; i < length; i++) { if (i) @@ -223,42 +223,28 @@ JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, J if (alreadyVisited) return jsEmptyString(exec); // return an empty string, avoding infinite recursion. - Vector<UChar, 256> strBuffer; + JSStringBuilder strBuffer; unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length; k++) { if (k >= 1) strBuffer.append(','); - if (!strBuffer.data()) { - JSObject* error = Error::create(exec, GeneralError, "Out of memory"); - exec->setException(error); - break; - } JSValue element = thisObj->get(exec, k); - if (element.isUndefinedOrNull()) - continue; - - JSObject* o = element.toObject(exec); - JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); - UString str; - CallData callData; - CallType callType = conversionFunction.getCallData(callData); - if (callType != CallTypeNone) - str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec); - else - str = element.toString(exec); - strBuffer.append(str.data(), str.size()); - - if (!strBuffer.data()) { - JSObject* error = Error::create(exec, GeneralError, "Out of memory"); - exec->setException(error); + if (!element.isUndefinedOrNull()) { + JSObject* o = element.toObject(exec); + JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); + UString str; + CallData callData; + CallType callType = conversionFunction.getCallData(callData); + if (callType != CallTypeNone) + str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec); + else + str = element.toString(exec); + strBuffer.append(str); } - - if (exec->hadException()) - break; } arrayVisitedElements.remove(thisObj); - return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0)); + return strBuffer.build(exec); } JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -275,38 +261,27 @@ JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue thi if (alreadyVisited) return jsEmptyString(exec); // return an empty string, avoding infinite recursion. - Vector<UChar, 256> strBuffer; + JSStringBuilder strBuffer; - UChar comma = ','; - UString separator = args.at(0).isUndefined() ? UString(&comma, 1) : args.at(0).toString(exec); + UString separator; + if (!args.at(0).isUndefined()) + separator = args.at(0).toString(exec); unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length; k++) { - if (k >= 1) - strBuffer.append(separator.data(), separator.size()); - if (!strBuffer.data()) { - JSObject* error = Error::create(exec, GeneralError, "Out of memory"); - exec->setException(error); - break; + if (k >= 1) { + if (separator.isNull()) + strBuffer.append(','); + else + strBuffer.append(separator); } JSValue element = thisObj->get(exec, k); - if (element.isUndefinedOrNull()) - continue; - - UString str = element.toString(exec); - strBuffer.append(str.data(), str.size()); - - if (!strBuffer.data()) { - JSObject* error = Error::create(exec, GeneralError, "Out of memory"); - exec->setException(error); - } - - if (exec->hadException()) - break; + if (!element.isUndefinedOrNull()) + strBuffer.append(element.toString(exec)); } arrayVisitedElements.remove(thisObj); - return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0)); + return strBuffer.build(exec); } JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp index 63139a2..2873e0b 100644 --- a/JavaScriptCore/runtime/Collector.cpp +++ b/JavaScriptCore/runtime/Collector.cpp @@ -1122,12 +1122,15 @@ void Heap::markRoots() MarkedArgumentBuffer::markLists(markStack, *m_markListSet); if (m_globalData->exception) markStack.append(m_globalData->exception); - m_globalData->smallStrings.markChildren(markStack); if (m_globalData->functionCodeBlockBeingReparsed) m_globalData->functionCodeBlockBeingReparsed->markAggregate(markStack); if (m_globalData->firstStringifierToMark) JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark); + // Mark the small strings cache last, since it will clear itself if nothing + // else has marked it. + m_globalData->smallStrings.markChildren(markStack); + markStack.drain(); markStack.compact(); @@ -1197,12 +1200,13 @@ static const char* typeName(JSCell* cell) return "number"; #endif if (cell->isGetterSetter()) - return "gettersetter"; + return "Getter-Setter"; if (cell->isAPIValueWrapper()) - return "value wrapper"; + return "API wrapper"; if (cell->isPropertyNameIterator()) - return "for-in iterator"; - ASSERT(cell->isObject()); + return "For-in iterator"; + if (!cell->isObject()) + return "[empty cell]"; const ClassInfo* info = cell->classInfo(); return info ? info->className : "Object"; } @@ -1218,6 +1222,18 @@ HashCountedSet<const char*>* Heap::protectedObjectTypeCounts() return counts; } +HashCountedSet<const char*>* Heap::objectTypeCounts() +{ + HashCountedSet<const char*>* counts = new HashCountedSet<const char*>; + + LiveObjectIterator it = primaryHeapBegin(); + LiveObjectIterator heapEnd = primaryHeapEnd(); + for ( ; it != heapEnd; ++it) + counts->add(typeName(*it)); + + return counts; +} + bool Heap::isBusy() { return m_heap.operationInProgress != NoOperation; diff --git a/JavaScriptCore/runtime/Collector.h b/JavaScriptCore/runtime/Collector.h index 7f7a679..82aa8a1 100644 --- a/JavaScriptCore/runtime/Collector.h +++ b/JavaScriptCore/runtime/Collector.h @@ -100,6 +100,7 @@ namespace JSC { size_t protectedObjectCount(); size_t protectedGlobalObjectCount(); HashCountedSet<const char*>* protectedObjectTypeCounts(); + HashCountedSet<const char*>* objectTypeCounts(); void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads. diff --git a/JavaScriptCore/runtime/CollectorHeapIterator.h b/JavaScriptCore/runtime/CollectorHeapIterator.h index e4f2f91..be6f3c9 100644 --- a/JavaScriptCore/runtime/CollectorHeapIterator.h +++ b/JavaScriptCore/runtime/CollectorHeapIterator.h @@ -38,7 +38,7 @@ namespace JSC { protected: CollectorHeapIterator(CollectorHeap&, size_t startBlock, size_t startCell); - void advance(size_t cellsPerBlock); + void advance(size_t max); CollectorHeap& m_heap; size_t m_block; @@ -80,10 +80,12 @@ namespace JSC { return reinterpret_cast<JSCell*>(m_heap.blocks[m_block]->cells + m_cell); } - inline void CollectorHeapIterator::advance(size_t cellsPerBlock) + // Iterators advance up to the next-to-last -- and not the last -- cell in a + // block, since the last cell is a dummy sentinel. + inline void CollectorHeapIterator::advance(size_t max) { ++m_cell; - if (m_cell == cellsPerBlock) { + if (m_cell == max) { m_cell = 0; ++m_block; } @@ -97,14 +99,12 @@ namespace JSC { inline LiveObjectIterator& LiveObjectIterator::operator++() { - if (m_block < m_heap.nextBlock || m_cell < m_heap.nextCell) { - advance(HeapConstants::cellsPerBlock); + advance(HeapConstants::cellsPerBlock - 1); + if (m_block < m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell < m_heap.nextCell)) return *this; - } - do { - advance(HeapConstants::cellsPerBlock); - } while (m_block < m_heap.usedBlocks && !m_heap.blocks[m_block]->marked.get(m_cell)); + while (m_block < m_heap.usedBlocks && !m_heap.blocks[m_block]->marked.get(m_cell)) + advance(HeapConstants::cellsPerBlock - 1); return *this; } @@ -117,7 +117,7 @@ namespace JSC { inline DeadObjectIterator& DeadObjectIterator::operator++() { do { - advance(HeapConstants::cellsPerBlock); + advance(HeapConstants::cellsPerBlock - 1); ASSERT(m_block > m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell >= m_heap.nextCell)); } while (m_block < m_heap.usedBlocks && m_heap.blocks[m_block]->marked.get(m_cell)); return *this; @@ -131,7 +131,7 @@ namespace JSC { inline ObjectIterator& ObjectIterator::operator++() { - advance(HeapConstants::cellsPerBlock); + advance(HeapConstants::cellsPerBlock - 1); return *this; } diff --git a/JavaScriptCore/runtime/CommonIdentifiers.cpp b/JavaScriptCore/runtime/CommonIdentifiers.cpp index 3837817..ed5e304 100644 --- a/JavaScriptCore/runtime/CommonIdentifiers.cpp +++ b/JavaScriptCore/runtime/CommonIdentifiers.cpp @@ -28,8 +28,7 @@ static const char* const nullCString = 0; #define INITIALIZE_PROPERTY_NAME(name) , name(globalData, #name) CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData) - : nullIdentifier(globalData, nullCString) - , emptyIdentifier(globalData, "") + : emptyIdentifier(globalData, "") , underscoreProto(globalData, "__proto__") , thisIdentifier(globalData, "this") JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME) diff --git a/JavaScriptCore/runtime/CommonIdentifiers.h b/JavaScriptCore/runtime/CommonIdentifiers.h index de24f4a..0a3d774 100644 --- a/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/JavaScriptCore/runtime/CommonIdentifiers.h @@ -90,7 +90,6 @@ namespace JSC { friend class JSGlobalData; public: - const Identifier nullIdentifier; const Identifier emptyIdentifier; const Identifier underscoreProto; const Identifier thisIdentifier; diff --git a/JavaScriptCore/runtime/DateConstructor.cpp b/JavaScriptCore/runtime/DateConstructor.cpp index e9a5c29..ab95d06 100644 --- a/JavaScriptCore/runtime/DateConstructor.cpp +++ b/JavaScriptCore/runtime/DateConstructor.cpp @@ -28,6 +28,7 @@ #include "JSFunction.h" #include "JSGlobalObject.h" #include "JSString.h" +#include "JSStringBuilder.h" #include "ObjectPrototype.h" #include "PrototypeFunction.h" #include <math.h> @@ -137,7 +138,7 @@ static JSValue JSC_HOST_CALL callDate(ExecState* exec, JSObject*, JSValue, const DateConversionBuffer time; formatDate(ts, date); formatTime(ts, time); - return jsNontrivialString(exec, makeString(date, " ", time)); + return jsMakeNontrivialString(exec, date, " ", time); } CallType DateConstructor::getCallData(CallData& callData) diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp index ca9d4ea..25b0ac4 100644 --- a/JavaScriptCore/runtime/DatePrototype.cpp +++ b/JavaScriptCore/runtime/DatePrototype.cpp @@ -26,6 +26,7 @@ #include "DateConversion.h" #include "Error.h" #include "JSString.h" +#include "JSStringBuilder.h" #include "ObjectPrototype.h" #include "DateInstance.h" @@ -427,7 +428,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue DateConversionBuffer time; formatDate(*gregorianDateTime, date); formatTime(*gregorianDateTime, time); - return jsNontrivialString(exec, makeString(date, " ", time)); + return jsMakeNontrivialString(exec, date, " ", time); } JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -444,7 +445,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSVal DateConversionBuffer time; formatDateUTCVariant(*gregorianDateTime, date); formatTimeUTC(*gregorianDateTime, time); - return jsNontrivialString(exec, makeString(date, " ", time)); + return jsMakeNontrivialString(exec, date, " ", time); } JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -570,7 +571,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSVal DateConversionBuffer time; formatDateUTCVariant(*gregorianDateTime, date); formatTimeUTC(*gregorianDateTime, time); - return jsNontrivialString(exec, makeString(date, " ", time)); + return jsMakeNontrivialString(exec, date, " ", time); } JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) diff --git a/JavaScriptCore/runtime/Error.cpp b/JavaScriptCore/runtime/Error.cpp index ddd4bc4..69464b7 100644 --- a/JavaScriptCore/runtime/Error.cpp +++ b/JavaScriptCore/runtime/Error.cpp @@ -94,7 +94,7 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const UString& message, JSObject* Error::create(ExecState* exec, ErrorType type, const char* message) { - return create(exec, type, message, -1, -1, NULL); + return create(exec, type, message, -1, -1, UString()); } JSObject* throwError(ExecState* exec, JSObject* error) @@ -105,21 +105,21 @@ JSObject* throwError(ExecState* exec, JSObject* error) JSObject* throwError(ExecState* exec, ErrorType type) { - JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL); + JSObject* error = Error::create(exec, type, UString(), -1, -1, UString()); exec->setException(error); return error; } JSObject* throwError(ExecState* exec, ErrorType type, const UString& message) { - JSObject* error = Error::create(exec, type, message, -1, -1, NULL); + JSObject* error = Error::create(exec, type, message, -1, -1, UString()); exec->setException(error); return error; } JSObject* throwError(ExecState* exec, ErrorType type, const char* message) { - JSObject* error = Error::create(exec, type, message, -1, -1, NULL); + JSObject* error = Error::create(exec, type, message, -1, -1, UString()); exec->setException(error); return error; } diff --git a/JavaScriptCore/runtime/ErrorPrototype.cpp b/JavaScriptCore/runtime/ErrorPrototype.cpp index be9e4b8..eb35733 100644 --- a/JavaScriptCore/runtime/ErrorPrototype.cpp +++ b/JavaScriptCore/runtime/ErrorPrototype.cpp @@ -23,6 +23,7 @@ #include "JSFunction.h" #include "JSString.h" +#include "JSStringBuilder.h" #include "ObjectPrototype.h" #include "PrototypeFunction.h" #include "UString.h" @@ -55,11 +56,11 @@ JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec, JSObject*, JSValue if (!name.isUndefined()) { if (!message.isUndefined()) - return jsNontrivialString(exec, makeString(name.toString(exec), ": ", message.toString(exec))); + return jsMakeNontrivialString(exec, name.toString(exec), ": ", message.toString(exec)); return jsNontrivialString(exec, name.toString(exec)); } if (!message.isUndefined()) - return jsNontrivialString(exec, makeString("Error: ", message.toString(exec))); + return jsMakeNontrivialString(exec, "Error: ", message.toString(exec)); return jsNontrivialString(exec, "Error"); } diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp index 9bb740e..b9c6319 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -58,7 +58,7 @@ JSValue createInterruptedExecutionException(JSGlobalData* globalData) static JSValue createError(ExecState* exec, ErrorType e, const char* msg) { - return Error::create(exec, e, msg, -1, -1, 0); + return Error::create(exec, e, msg, -1, -1, UString()); } JSValue createStackOverflowError(ExecState* exec) @@ -188,4 +188,9 @@ JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error, return exception; } +JSValue throwOutOfMemoryError(ExecState* exec) +{ + return throwError(exec, GeneralError, "Out of memory"); +} + } // namespace JSC diff --git a/JavaScriptCore/runtime/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h index e739d09..b6e7373 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.h +++ b/JavaScriptCore/runtime/ExceptionHelpers.h @@ -51,6 +51,7 @@ namespace JSC { JSObject* createNotAConstructorError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*); JSValue createNotAFunctionError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*); JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*); + JSValue throwOutOfMemoryError(ExecState*); } // namespace JSC diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp index bc18cc9..79900dc 100644 --- a/JavaScriptCore/runtime/Executable.cpp +++ b/JavaScriptCore/runtime/Executable.cpp @@ -272,7 +272,7 @@ UString FunctionExecutable::paramString() const builder.append(", "); builder.append(parameters[pos].ustring()); } - return builder.release(); + return builder.build(); } }; diff --git a/JavaScriptCore/runtime/FunctionConstructor.cpp b/JavaScriptCore/runtime/FunctionConstructor.cpp index 9d55dd1..9b0b1bb 100644 --- a/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -89,7 +89,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.release(); + program = builder.build(); } int errLine; diff --git a/JavaScriptCore/runtime/FunctionPrototype.cpp b/JavaScriptCore/runtime/FunctionPrototype.cpp index f08bd5e..3475f08 100644 --- a/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -25,6 +25,7 @@ #include "JSArray.h" #include "JSFunction.h" #include "JSString.h" +#include "JSStringBuilder.h" #include "Interpreter.h" #include "Lexer.h" #include "PrototypeFunction.h" @@ -38,7 +39,7 @@ static JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*, JSObject*, JSVal static JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*, JSObject*, JSValue, const ArgList&); FunctionPrototype::FunctionPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure) - : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier) + : InternalFunction(&exec->globalData(), structure, exec->propertyNames().emptyIdentifier) { putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum); } @@ -90,13 +91,13 @@ JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSVa FunctionExecutable* executable = function->jsExecutable(); UString sourceString = executable->source().toString(); insertSemicolonIfNeeded(sourceString); - return jsString(exec, makeString("function ", function->name(exec), "(", executable->paramString(), ") ", sourceString)); + return jsMakeNontrivialString(exec, "function ", function->name(exec), "(", executable->paramString(), ") ", sourceString); } } if (thisValue.inherits(&InternalFunction::info)) { InternalFunction* function = asInternalFunction(thisValue); - return jsString(exec, makeString("function ", function->name(exec), "() {\n [native code]\n}")); + return jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n [native code]\n}"); } return throwError(exec, TypeError); diff --git a/JavaScriptCore/runtime/Identifier.cpp b/JavaScriptCore/runtime/Identifier.cpp index 747c4ac..97929e2 100644 --- a/JavaScriptCore/runtime/Identifier.cpp +++ b/JavaScriptCore/runtime/Identifier.cpp @@ -123,10 +123,8 @@ struct CStringTranslator { PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c) { - if (!c) { - UString::Rep::null().hash(); - return &UString::Rep::null(); - } + ASSERT(c); + if (!c[0]) { UString::Rep::empty().hash(); return &UString::Rep::empty(); diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 0bc1274..3ddac7c 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -30,11 +30,11 @@ #include "Interpreter.h" #include "JSGlobalObject.h" #include "JSString.h" +#include "JSStringBuilder.h" #include "Lexer.h" #include "LiteralParser.h" #include "Nodes.h" #include "Parser.h" -#include "StringBuilder.h" #include "StringExtras.h" #include "dtoa.h" #include <stdio.h> @@ -57,7 +57,7 @@ static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEsc if (!cstr.c_str()) return throwError(exec, URIError, "String contained an illegal UTF-16 sequence."); - StringBuilder builder; + JSStringBuilder builder; const char* p = cstr.c_str(); for (size_t k = 0; k < cstr.size(); k++, p++) { char c = *p; @@ -66,15 +66,15 @@ static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEsc else { char tmp[4]; snprintf(tmp, 4, "%%%02X", static_cast<unsigned char>(c)); - builder.append((const char*)tmp); + builder.append(tmp); } } - return jsString(exec, builder.release()); + return builder.build(exec); } static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict) { - StringBuilder builder; + JSStringBuilder builder; UString str = args.at(0).toString(exec); int k = 0; int len = str.size(); @@ -135,7 +135,7 @@ static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUne k++; builder.append(c); } - return jsString(exec, builder.release()); + return builder.build(exec); } bool isStrWhiteSpace(UChar c) @@ -378,8 +378,7 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons "0123456789" "*+-./@_"; - StringBuilder builder; - UString s; + JSStringBuilder builder; UString str = args.at(0).toString(exec); const UChar* c = str.data(); for (int k = 0; k < str.size(); k++, c++) { @@ -387,18 +386,17 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons if (u > 255) { char tmp[7]; sprintf(tmp, "%%u%04X", u); - s = UString(tmp); + builder.append(tmp); } else if (u != 0 && strchr(do_not_escape, static_cast<char>(u))) - s = UString(c, 1); + builder.append(c, 1); else { char tmp[4]; sprintf(tmp, "%%%02X", u); - s = UString(tmp); + builder.append(tmp); } - builder.append(s); } - return jsString(exec, builder.release()); + return builder.build(exec); } JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, const ArgList& args) @@ -425,7 +423,7 @@ JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, co builder.append(*c); } - return jsString(exec, builder.release()); + return jsString(exec, builder.build()); } #ifndef NDEBUG diff --git a/JavaScriptCore/runtime/JSONObject.cpp b/JavaScriptCore/runtime/JSONObject.cpp index ce0dcff..acd9280 100644 --- a/JavaScriptCore/runtime/JSONObject.cpp +++ b/JavaScriptCore/runtime/JSONObject.cpp @@ -268,7 +268,7 @@ JSValue Stringifier::stringify(JSValue value) if (m_exec->hadException()) return jsNull(); - return jsString(m_exec, result.release()); + return jsString(m_exec, result.build()); } void Stringifier::appendQuotedString(StringBuilder& builder, const UString& value) diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp index d3dcb83..a5d4da0 100644 --- a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp +++ b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp @@ -35,6 +35,24 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator); +inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots) + : JSCell(exec->globalData().propertyNameIteratorStructure.get()) + , m_cachedStructure(0) + , m_numCacheableSlots(numCacheableSlots) + , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size()) + , m_jsStrings(new JSValue[m_jsStringsSize]) +{ + PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector(); + for (size_t i = 0; i < m_jsStringsSize; ++i) + m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring()); +} + +JSPropertyNameIterator::~JSPropertyNameIterator() +{ + if (m_cachedStructure) + m_cachedStructure->clearEnumerationCache(this); +} + JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o) { ASSERT(!o->structure()->enumerationCache() || diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.h b/JavaScriptCore/runtime/JSPropertyNameIterator.h index d18c2c5..3f533a0 100644 --- a/JavaScriptCore/runtime/JSPropertyNameIterator.h +++ b/JavaScriptCore/runtime/JSPropertyNameIterator.h @@ -49,6 +49,8 @@ namespace JSC { { return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount); } + + virtual ~JSPropertyNameIterator(); virtual bool isPropertyNameIterator() const { return true; } @@ -81,23 +83,21 @@ namespace JSC { OwnArrayPtr<JSValue> m_jsStrings; }; -inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots) - : JSCell(exec->globalData().propertyNameIteratorStructure.get()) - , m_cachedStructure(0) - , m_numCacheableSlots(numCacheableSlots) - , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size()) - , m_jsStrings(new JSValue[m_jsStringsSize]) -{ - PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector(); - for (size_t i = 0; i < m_jsStringsSize; ++i) - m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring()); -} - -inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache) -{ - ASSERT(!isDictionary()); - m_enumerationCache = enumerationCache; -} + inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache) + { + ASSERT(!isDictionary()); + m_enumerationCache = enumerationCache; + } + + inline void Structure::clearEnumerationCache(JSPropertyNameIterator* enumerationCache) + { + m_enumerationCache.clear(enumerationCache); + } + + inline JSPropertyNameIterator* Structure::enumerationCache() + { + return m_enumerationCache.get(); + } } // namespace JSC diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h index af03025..cff8e3a 100644 --- a/JavaScriptCore/runtime/JSString.h +++ b/JavaScriptCore/runtime/JSString.h @@ -283,8 +283,9 @@ namespace JSC { } const UString tryGetValue() const { - if (isRope()) - UString(); + // If this is a rope, m_value should be null - + // if this is not a rope, m_value should be non-null. + ASSERT(isRope() == m_value.isNull()); return m_value; } unsigned length() { return m_stringLength; } diff --git a/JavaScriptCore/runtime/JSStringBuilder.h b/JavaScriptCore/runtime/JSStringBuilder.h new file mode 100644 index 0000000..2b11736 --- /dev/null +++ b/JavaScriptCore/runtime/JSStringBuilder.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2009 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 JSStringBuilder_h +#define JSStringBuilder_h + +#include "ExceptionHelpers.h" +#include "JSString.h" +#include "StringBuilder.h" + +namespace JSC { + +class JSStringBuilder : public StringBuilder { +public: + JSValue build(ExecState* exec) + { + buffer.shrinkToFit(); + if (!buffer.data()) + return throwOutOfMemoryError(exec); + return jsString(exec, UString::adopt(buffer)); + } + +private: + // Make attempts to call this compile error - if you only wanted a UString, + // Why didn't you just use a StringBuilder?! (This may change, maybe at some + // point in the future we'll need to start building a string not knowing whether + // we'll want a UString or a JSValue - but until we have this requirement, + // block this). + UString build() + { + ASSERT_NOT_REACHED(); + return StringBuilder::build(); + } +}; + +template<typename StringType1, typename StringType2> +inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2) +{ + PassRefPtr<UStringImpl> result = tryMakeString(string1, string2); + if (!result) + return throwOutOfMemoryError(exec); + return jsNontrivialString(exec, result); +} + +template<typename StringType1, typename StringType2, typename StringType3> +inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3) +{ + PassRefPtr<UStringImpl> result = tryMakeString(string1, string2, string3); + if (!result) + return throwOutOfMemoryError(exec); + return jsNontrivialString(exec, result); +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> +inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) +{ + PassRefPtr<UStringImpl> result = tryMakeString(string1, string2, string3, string4); + if (!result) + return throwOutOfMemoryError(exec); + return jsNontrivialString(exec, result); +} + +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<UStringImpl> result = tryMakeString(string1, string2, string3, string4, string5); + if (!result) + return throwOutOfMemoryError(exec); + return jsNontrivialString(exec, result); +} + +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<UStringImpl> result = tryMakeString(string1, string2, string3, string4, string5, string6); + if (!result) + return throwOutOfMemoryError(exec); + return jsNontrivialString(exec, result); +} + +} + +#endif diff --git a/JavaScriptCore/runtime/JSValue.cpp b/JavaScriptCore/runtime/JSValue.cpp index 699c1cd..502312c 100644 --- a/JavaScriptCore/runtime/JSValue.cpp +++ b/JavaScriptCore/runtime/JSValue.cpp @@ -174,7 +174,11 @@ uint32_t toUInt32SlowCase(double d, bool& ok) NEVER_INLINE double nonInlineNaN() { +#if OS(SYMBIAN) + return nanval(); +#else return std::numeric_limits<double>::quiet_NaN(); +#endif } } // namespace JSC diff --git a/JavaScriptCore/runtime/LiteralParser.cpp b/JavaScriptCore/runtime/LiteralParser.cpp index aa1e5ed..cc33bae 100644 --- a/JavaScriptCore/runtime/LiteralParser.cpp +++ b/JavaScriptCore/runtime/LiteralParser.cpp @@ -200,7 +200,7 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera if (m_ptr >= m_end || *m_ptr != '"') return TokError; - token.stringToken = builder.release(); + token.stringToken = builder.build(); token.type = TokString; token.end = ++m_ptr; return TokString; diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp index 67210fa..fa32b86 100644 --- a/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/JavaScriptCore/runtime/NumberPrototype.cpp @@ -25,6 +25,7 @@ #include "Error.h" #include "JSFunction.h" #include "JSString.h" +#include "JSStringBuilder.h" #include "Operations.h" #include "PrototypeFunction.h" #include "StringBuilder.h" @@ -94,7 +95,7 @@ static UString integerPartNoExp(double d) builder.append((const char*)(buf.data())); } - return builder.release(); + return builder.build(); } static UString charSequence(char c, int count) @@ -262,7 +263,7 @@ JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue for (int i = 0; i < f + 1 - k; i++) z.append('0'); z.append(m); - m = z.release(); + m = z.build(); k = f + 1; ASSERT(k == m.size()); } @@ -432,8 +433,8 @@ JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSV if (m.size() > 1) m = makeString(m.substr(0, 1), ".", m.substr(1)); if (e >= 0) - return jsNontrivialString(exec, makeString(s, m, "e+", UString::from(e))); - return jsNontrivialString(exec, makeString(s, m, "e-", UString::from(-e))); + return jsMakeNontrivialString(exec, s, m, "e+", UString::from(e)); + return jsMakeNontrivialString(exec, s, m, "e-", UString::from(-e)); } } else { m = charSequence('0', precision); @@ -447,7 +448,7 @@ JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSV return jsString(exec, makeString(s, m.substr(0, e + 1), ".", m.substr(e + 1))); return jsString(exec, makeString(s, m)); } - return jsNontrivialString(exec, makeString(s, "0.", charSequence('0', -(e + 1)), m)); + return jsMakeNontrivialString(exec, s, "0.", charSequence('0', -(e + 1)), m); } } // namespace JSC diff --git a/JavaScriptCore/runtime/ObjectPrototype.cpp b/JavaScriptCore/runtime/ObjectPrototype.cpp index 3065c6d..c32a007 100644 --- a/JavaScriptCore/runtime/ObjectPrototype.cpp +++ b/JavaScriptCore/runtime/ObjectPrototype.cpp @@ -24,6 +24,7 @@ #include "Error.h" #include "JSFunction.h" #include "JSString.h" +#include "JSStringBuilder.h" #include "PrototypeFunction.h" namespace JSC { @@ -148,7 +149,7 @@ JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - return jsNontrivialString(exec, makeString("[object ", thisValue.toThisObject(exec)->className(), "]")); + return jsMakeNontrivialString(exec, "[object ", thisValue.toThisObject(exec)->className(), "]"); } } // namespace JSC diff --git a/JavaScriptCore/runtime/Operations.cpp b/JavaScriptCore/runtime/Operations.cpp index 0e1887c..cf236bf 100644 --- a/JavaScriptCore/runtime/Operations.cpp +++ b/JavaScriptCore/runtime/Operations.cpp @@ -41,13 +41,6 @@ bool JSValue::strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2) return strictEqualSlowCaseInline(exec, v1, v2); } -NEVER_INLINE JSValue throwOutOfMemoryError(ExecState* exec) -{ - JSObject* error = Error::create(exec, GeneralError, "Out of memory"); - exec->setException(error); - return error; -} - NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2) { // exception for the Date exception in defaultValue() diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h index c3aa0fa..9b27074 100644 --- a/JavaScriptCore/runtime/Operations.h +++ b/JavaScriptCore/runtime/Operations.h @@ -22,6 +22,7 @@ #ifndef Operations_h #define Operations_h +#include "ExceptionHelpers.h" #include "Interpreter.h" #include "JSImmediate.h" #include "JSNumberCell.h" @@ -29,7 +30,6 @@ namespace JSC { - NEVER_INLINE JSValue throwOutOfMemoryError(ExecState*); NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue); JSValue jsTypeStringForValue(CallFrame*, JSValue); bool jsIsObjectType(JSValue); diff --git a/JavaScriptCore/runtime/PropertyNameArray.cpp b/JavaScriptCore/runtime/PropertyNameArray.cpp index 5108272..4937b7c 100644 --- a/JavaScriptCore/runtime/PropertyNameArray.cpp +++ b/JavaScriptCore/runtime/PropertyNameArray.cpp @@ -30,7 +30,7 @@ static const size_t setThreshold = 20; void PropertyNameArray::add(UString::Rep* identifier) { - ASSERT(identifier == &UString::Rep::null() || identifier == &UString::Rep::empty() || identifier->isIdentifier()); + ASSERT(identifier == &UString::Rep::empty() || identifier->isIdentifier()); size_t size = m_data->propertyNameVector().size(); if (size < setThreshold) { diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp index 5f9d357..dd5fe02 100644 --- a/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -27,6 +27,7 @@ #include "JSFunction.h" #include "JSObject.h" #include "JSString.h" +#include "JSStringBuilder.h" #include "JSValue.h" #include "ObjectPrototype.h" #include "PrototypeFunction.h" @@ -116,7 +117,7 @@ JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValu postfix[index] = 'm'; UString source = asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec); // If source is empty, use "/(?:)/" to avoid colliding with comment syntax - return jsNontrivialString(exec, makeString("/", source.size() ? source : UString("(?:)"), postfix)); + return jsMakeNontrivialString(exec, "/", source.size() ? source : UString("(?:)"), postfix); } } // namespace JSC diff --git a/JavaScriptCore/runtime/SmallStrings.cpp b/JavaScriptCore/runtime/SmallStrings.cpp index ac71735..d9d4377 100644 --- a/JavaScriptCore/runtime/SmallStrings.cpp +++ b/JavaScriptCore/runtime/SmallStrings.cpp @@ -34,6 +34,11 @@ namespace JSC { static const unsigned numCharactersToStore = 0x100; +static inline bool isMarked(JSString* string) +{ + return string && Heap::isCellMarked(string); +} + class SmallStringsStorage : public Noncopyable { public: SmallStringsStorage(); @@ -55,13 +60,9 @@ SmallStringsStorage::SmallStringsStorage() } SmallStrings::SmallStrings() - : m_emptyString(0) - , m_storage(0) { COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); - - for (unsigned i = 0; i < numCharactersToStore; ++i) - m_singleCharacterStrings[i] = 0; + clear(); } SmallStrings::~SmallStrings() @@ -70,6 +71,25 @@ SmallStrings::~SmallStrings() void SmallStrings::markChildren(MarkStack& markStack) { + /* + Our hypothesis is that small strings are very common. So, we cache them + to avoid GC churn. However, in cases where this hypothesis turns out to + be false -- including the degenerate case where all JavaScript execution + has terminated -- we don't want to waste memory. + + To test our hypothesis, we check if any small string has been marked. If + so, it's probably reasonable to mark the rest. If not, we clear the cache. + */ + + bool isAnyStringMarked = isMarked(m_emptyString); + for (unsigned i = 0; i < numCharactersToStore && !isAnyStringMarked; ++i) + isAnyStringMarked |= isMarked(m_singleCharacterStrings[i]); + + if (!isAnyStringMarked) { + clear(); + return; + } + if (m_emptyString) markStack.append(m_emptyString); for (unsigned i = 0; i < numCharactersToStore; ++i) { @@ -78,6 +98,13 @@ void SmallStrings::markChildren(MarkStack& markStack) } } +void SmallStrings::clear() +{ + m_emptyString = 0; + for (unsigned i = 0; i < numCharactersToStore; ++i) + m_singleCharacterStrings[i] = 0; +} + unsigned SmallStrings::count() const { unsigned count = 0; diff --git a/JavaScriptCore/runtime/SmallStrings.h b/JavaScriptCore/runtime/SmallStrings.h index efecbb0..cc11d0a 100644 --- a/JavaScriptCore/runtime/SmallStrings.h +++ b/JavaScriptCore/runtime/SmallStrings.h @@ -57,6 +57,7 @@ namespace JSC { UString::Rep* singleCharacterStringRep(unsigned char character); void markChildren(MarkStack&); + void clear(); unsigned count() const; diff --git a/JavaScriptCore/runtime/StringBuilder.h b/JavaScriptCore/runtime/StringBuilder.h index 8e18d37..27dbbd7 100644 --- a/JavaScriptCore/runtime/StringBuilder.h +++ b/JavaScriptCore/runtime/StringBuilder.h @@ -39,7 +39,7 @@ public: void append(const char* str) { - buffer.append(str, strlen(str)); + append(str, strlen(str)); } void append(const char* str, size_t len) @@ -66,13 +66,15 @@ public: UChar operator[](size_t i) const { return buffer.at(i); } - UString release() + UString build() { buffer.shrinkToFit(); + if (buffer.size() && !buffer.data()) + CRASH(); return UString::adopt(buffer); } -private: +protected: Vector<UChar, 64> buffer; }; diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp index d002e07..8c014ec 100644 --- a/JavaScriptCore/runtime/StringPrototype.cpp +++ b/JavaScriptCore/runtime/StringPrototype.cpp @@ -28,6 +28,7 @@ #include "JSGlobalObjectFunctions.h" #include "JSArray.h" #include "JSFunction.h" +#include "JSStringBuilder.h" #include "ObjectPrototype.h" #include "Operations.h" #include "PropertyNameArray.h" @@ -227,6 +228,86 @@ static inline int localeCompare(const UString& a, const UString& b) return Collator::userDefault()->collate(reinterpret_cast<const ::UChar*>(a.data()), a.size(), reinterpret_cast<const ::UChar*>(b.data()), b.size()); } +struct StringRange { +public: + StringRange(int pos, int len) + : position(pos) + , length(len) + { + } + + StringRange() + { + } + + int position; + int length; +}; + +JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount); +JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount) +{ + if (rangeCount == 1 && separatorCount == 0) { + int sourceSize = source.size(); + int position = substringRanges[0].position; + int length = substringRanges[0].length; + if (position <= 0 && length >= sourceSize) + return sourceVal; + // We could call UString::substr, but this would result in redundant checks + return jsString(exec, UStringImpl::create(source.rep(), max(0, position), min(sourceSize, length))); + } + + int totalLength = 0; + for (int i = 0; i < rangeCount; i++) + totalLength += substringRanges[i].length; + for (int i = 0; i < separatorCount; i++) + totalLength += separators[i].size(); + + if (totalLength == 0) + return jsString(exec, ""); + + UChar* buffer; + PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(totalLength, buffer); + if (!impl) + return throwOutOfMemoryError(exec); + + int maxCount = max(rangeCount, separatorCount); + int bufferPos = 0; + for (int i = 0; i < maxCount; i++) { + if (i < rangeCount) { + UStringImpl::copyChars(buffer + bufferPos, source.data() + substringRanges[i].position, substringRanges[i].length); + bufferPos += substringRanges[i].length; + } + if (i < separatorCount) { + UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size()); + bufferPos += separators[i].size(); + } + } + + return jsString(exec, impl); +} + +JSValue jsReplaceRange(ExecState* exec, const UString& source, int rangeStart, int rangeLength, const UString& replacement); +JSValue jsReplaceRange(ExecState* exec, const UString& source, int rangeStart, int rangeLength, const UString& replacement) +{ + int replacementLength = replacement.size(); + int totalLength = source.size() - rangeLength + replacementLength; + if (totalLength == 0) + return jsString(exec, ""); + + UChar* buffer; + PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(totalLength, buffer); + if (!impl) + return throwOutOfMemoryError(exec); + + UStringImpl::copyChars(buffer, source.data(), rangeStart); + UStringImpl::copyChars(buffer + rangeStart, replacement.data(), replacementLength); + int rangeEnd = rangeStart + rangeLength; + UStringImpl::copyChars(buffer + rangeStart + replacementLength, source.data() + rangeEnd, source.size() - rangeEnd); + + return jsString(exec, impl); +} + JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { JSString* sourceVal = thisValue.toThisJSString(exec); @@ -250,7 +331,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue int lastIndex = 0; int startPosition = 0; - Vector<UString::Range, 16> sourceRanges; + Vector<StringRange, 16> sourceRanges; Vector<UString, 16> replacements; // This is either a loop (if global is set) or a one-way (if not). @@ -269,7 +350,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue if (matchIndex < 0) break; - sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); int completeMatchStart = ovector[0]; unsigned i = 0; @@ -311,7 +392,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue if (matchIndex < 0) break; - sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); if (callType != CallTypeNone) { int completeMatchStart = ovector[0]; @@ -352,10 +433,9 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue return sourceVal; if (lastIndex < source.size()) - sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex)); + sourceRanges.append(StringRange(lastIndex, source.size() - lastIndex)); - return jsString(exec, source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), - replacements.data(), replacements.size())); + return jsSpliceSubstringsWithSeparators(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()); } // Not a regular expression, so treat the pattern as a string. @@ -377,7 +457,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue } int ovector[2] = { matchPos, matchPos + matchLen }; - return jsString(exec, source.replaceRange(matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0))); + return jsReplaceRange(exec, source, matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0)); } JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -789,62 +869,62 @@ JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, J JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<big>", s, "</big>")); + return jsMakeNontrivialString(exec, "<big>", s, "</big>"); } JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<small>", s, "</small>")); + return jsMakeNontrivialString(exec, "<small>", s, "</small>"); } JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<blink>", s, "</blink>")); + return jsMakeNontrivialString(exec, "<blink>", s, "</blink>"); } JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<b>", s, "</b>")); + return jsMakeNontrivialString(exec, "<b>", s, "</b>"); } JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsString(exec, makeString("<tt>", s, "</tt>")); + return jsMakeNontrivialString(exec, "<tt>", s, "</tt>"); } JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<i>", s, "</i>")); + return jsMakeNontrivialString(exec, "<i>", s, "</i>"); } JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<strike>", s, "</strike>")); + return jsMakeNontrivialString(exec, "<strike>", s, "</strike>"); } JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<sub>", s, "</sub>")); + return jsMakeNontrivialString(exec, "<sub>", s, "</sub>"); } JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<sup>", s, "</sup>")); + return jsMakeNontrivialString(exec, "<sup>", s, "</sup>"); } JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); - return jsNontrivialString(exec, makeString("<font color=\"", a0.toString(exec), "\">", s, "</font>")); + return jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec), "\">", s, "</font>"); } JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -886,14 +966,14 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu return jsNontrivialString(exec, impl); } - return jsNontrivialString(exec, makeString("<font size=\"", a0.toString(exec), "\">", s, "</font>")); + return jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec), "\">", s, "</font>"); } JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); - return jsNontrivialString(exec, makeString("<a name=\"", a0.toString(exec), "\">", s, "</a>")); + return jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec), "\">", s, "</a>"); } JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) diff --git a/JavaScriptCore/runtime/Structure.h b/JavaScriptCore/runtime/Structure.h index 1353a5a..95cf94c 100644 --- a/JavaScriptCore/runtime/Structure.h +++ b/JavaScriptCore/runtime/Structure.h @@ -36,6 +36,7 @@ #include "StructureTransitionTable.h" #include "JSTypeInfo.h" #include "UString.h" +#include "WeakGCPtr.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -101,7 +102,7 @@ namespace JSC { void growPropertyStorageCapacity(); unsigned propertyStorageCapacity() const { return m_propertyStorageCapacity; } - unsigned propertyStorageSize() const { return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1); } + unsigned propertyStorageSize() const { return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : static_cast<unsigned>(m_offset + 1)); } bool isUsingInlineStorage() const; size_t get(const Identifier& propertyName); @@ -135,7 +136,8 @@ namespace JSC { void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; } void setEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h. - JSPropertyNameIterator* enumerationCache() { return m_enumerationCache.get(); } + void clearEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h. + JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h. void getPropertyNames(PropertyNameArray&, EnumerationMode mode); private: @@ -199,7 +201,7 @@ namespace JSC { StructureTransitionTable table; - ProtectedPtr<JSPropertyNameIterator> m_enumerationCache; + WeakGCPtr<JSPropertyNameIterator> m_enumerationCache; PropertyMapHashTable* m_propertyTable; diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp index e75a05c..4a89a23 100644 --- a/JavaScriptCore/runtime/UString.cpp +++ b/JavaScriptCore/runtime/UString.cpp @@ -53,7 +53,7 @@ using namespace WTF::Unicode; using namespace std; namespace JSC { - + extern const double NaN; extern const double Inf; @@ -146,95 +146,46 @@ bool operator==(const CString& c1, const CString& c2) return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0); } -// These static strings are immutable, except for rc, whose initial value is chosen to +// These static strings are immutable, except for rc, whose initial value is chosen to // reduce the possibility of it becoming zero due to ref/deref not being thread-safe. static UChar sharedEmptyChar; -UStringImpl* UStringImpl::s_null; UStringImpl* UStringImpl::s_empty; -UString* UString::nullUString; + +UString::Rep* UString::s_nullRep; +UString* UString::s_nullUString; void initializeUString() { - UStringImpl::s_null = new UStringImpl(0, 0, UStringImpl::ConstructStaticString); UStringImpl::s_empty = new UStringImpl(&sharedEmptyChar, 0, UStringImpl::ConstructStaticString); - UString::nullUString = new UString; -} - -static PassRefPtr<UString::Rep> createRep(const char* c) -{ - if (!c) - return &UString::Rep::null(); - - if (!c[0]) - return &UString::Rep::empty(); - size_t length = strlen(c); - UChar* d; - PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, d); - if (!result) - return &UString::Rep::null(); - - for (size_t i = 0; i < length; i++) - d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend - return result; -} - -static inline PassRefPtr<UString::Rep> createRep(const char* c, int length) -{ - if (!c) - return &UString::Rep::null(); - - if (!length) - return &UString::Rep::empty(); - - UChar* d; - PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, d); - if (!result) - return &UString::Rep::null(); - - for (int i = 0; i < length; i++) - d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend - return result; + UString::s_nullRep = new UStringImpl(0, 0, UStringImpl::ConstructStaticString); + UString::s_nullUString = new UString; } UString::UString(const char* c) - : m_rep(createRep(c)) + : m_rep(Rep::create(c)) { } UString::UString(const char* c, int length) - : m_rep(createRep(c, length)) + : m_rep(Rep::create(c, length)) { } UString::UString(const UChar* c, int length) { - if (length == 0) + if (length == 0) m_rep = &Rep::empty(); else m_rep = Rep::create(c, length); } -UString UString::createFromUTF8(const char* string) -{ - if (!string) - return null(); - - size_t length = strlen(string); - Vector<UChar, 1024> buffer(length); - UChar* p = buffer.data(); - if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length)) - return null(); - - return UString(buffer.data(), p - buffer.data()); -} - UString UString::from(int i) { UChar buf[1 + sizeof(i) * 3]; UChar* end = buf + sizeof(buf) / sizeof(UChar); UChar* p = end; - + if (i == 0) *--p = '0'; else if (i == INT_MIN) { @@ -296,7 +247,7 @@ UString UString::from(unsigned int u) UChar buf[sizeof(u) * 3]; UChar* end = buf + sizeof(buf) / sizeof(UChar); UChar* p = end; - + if (u == 0) *--p = '0'; else { @@ -305,7 +256,7 @@ UString UString::from(unsigned int u) u /= 10; } } - + return UString(p, static_cast<int>(end - p)); } @@ -346,71 +297,6 @@ UString UString::from(double d) return UString(buffer, length); } -UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const -{ - m_rep->checkConsistency(); - - if (rangeCount == 1 && separatorCount == 0) { - int thisSize = size(); - int position = substringRanges[0].position; - int length = substringRanges[0].length; - if (position <= 0 && length >= thisSize) - return *this; - return UString::Rep::create(m_rep, max(0, position), min(thisSize, length)); - } - - int totalLength = 0; - for (int i = 0; i < rangeCount; i++) - totalLength += substringRanges[i].length; - for (int i = 0; i < separatorCount; i++) - totalLength += separators[i].size(); - - if (totalLength == 0) - return ""; - - UChar* buffer; - PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer); - if (!rep) - return null(); - - int maxCount = max(rangeCount, separatorCount); - int bufferPos = 0; - for (int i = 0; i < maxCount; i++) { - if (i < rangeCount) { - UStringImpl::copyChars(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length); - bufferPos += substringRanges[i].length; - } - if (i < separatorCount) { - UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size()); - bufferPos += separators[i].size(); - } - } - - return rep; -} - -UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const -{ - m_rep->checkConsistency(); - - int replacementLength = replacement.size(); - int totalLength = size() - rangeLength + replacementLength; - if (totalLength == 0) - return ""; - - UChar* buffer; - PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer); - if (!rep) - return null(); - - UStringImpl::copyChars(buffer, data(), rangeStart); - UStringImpl::copyChars(buffer + rangeStart, replacement.data(), replacementLength); - int rangeEnd = rangeStart + rangeLength; - UStringImpl::copyChars(buffer + rangeStart + replacementLength, data() + rangeEnd, size() - rangeEnd); - - return rep; -} - bool UString::getCString(CStringBuffer& buffer) const { int length = size(); @@ -456,30 +342,6 @@ char* UString::ascii() const return asciiBuffer; } -UString& UString::operator=(const char* c) -{ - if (!c) { - m_rep = &Rep::null(); - return *this; - } - - if (!c[0]) { - m_rep = &Rep::empty(); - return *this; - } - - int l = static_cast<int>(strlen(c)); - UChar* d = 0; - m_rep = Rep::tryCreateUninitialized(l, d); - if (m_rep) { - for (int i = 0; i < l; i++) - d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend - } else - makeNull(); - - return *this; -} - bool UString::is8Bit() const { const UChar* u = data(); @@ -721,7 +583,7 @@ int UString::find(UChar ch, int pos) const if (*c == ch) return static_cast<int>(c - data()); } - + return -1; } @@ -888,16 +750,4 @@ CString UString::UTF8String(bool strict) const return CString(buffer.data(), p - buffer.data()); } -// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X. -NEVER_INLINE void UString::makeNull() -{ - m_rep = &Rep::null(); -} - -// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X. -NEVER_INLINE UString::Rep* UString::nullRep() -{ - return &Rep::null(); -} - } // namespace JSC diff --git a/JavaScriptCore/runtime/UString.h b/JavaScriptCore/runtime/UString.h index 0c13689..7d9ec49 100644 --- a/JavaScriptCore/runtime/UString.h +++ b/JavaScriptCore/runtime/UString.h @@ -81,7 +81,6 @@ namespace JSC { typedef UStringImpl Rep; public: - // UString constructors passed char*s assume ISO Latin-1 encoding; for UTF8 use 'createFromUTF8', below. UString(); UString(const char*); // Constructor for null-terminated string. UString(const char*, int length); @@ -109,34 +108,12 @@ namespace JSC { return Rep::adopt(vector); } - static UString createFromUTF8(const char*); - static UString from(int); static UString from(long long); static UString from(unsigned int); static UString from(long); static UString from(double); - struct Range { - public: - Range(int pos, int len) - : position(pos) - , length(len) - { - } - - Range() - { - } - - int position; - int length; - }; - - UString spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const; - - UString replaceRange(int rangeStart, int RangeEnd, const UString& replacement) const; - bool getCString(CStringBuffer&) const; // NOTE: This method should only be used for *debugging* purposes as it @@ -153,11 +130,9 @@ namespace JSC { */ CString UTF8String(bool strict = false) const; - UString& operator=(const char*c); - const UChar* data() const { return m_rep->data(); } - bool isNull() const { return m_rep == &Rep::null(); } + bool isNull() const { return m_rep == s_nullRep; } bool isEmpty() const { return !m_rep->size(); } bool is8Bit() const; @@ -183,10 +158,9 @@ namespace JSC { UString substr(int pos = 0, int len = -1) const; - static const UString& null() { return *nullUString; } + static const UString& null() { return *s_nullUString; } Rep* rep() const { return m_rep.get(); } - static Rep* nullRep(); UString(PassRefPtr<Rep> r) : m_rep(r) @@ -197,10 +171,10 @@ namespace JSC { size_t cost() const { return m_rep->cost(); } private: - void makeNull(); - RefPtr<Rep> m_rep; - static UString* nullUString; + + JS_EXPORTDATA static Rep* s_nullRep; + static UString* s_nullUString; friend void initializeUString(); friend bool operator==(const UString&, const UString&); @@ -255,7 +229,7 @@ namespace JSC { int compare(const UString&, const UString&); inline UString::UString() - : m_rep(&Rep::null()) + : m_rep(s_nullRep) { } @@ -354,7 +328,7 @@ namespace JSC { }; template<typename StringType1, typename StringType2> - UString makeString(StringType1 string1, StringType2 string2) + PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2) { StringTypeAdapter<StringType1> adapter1(string1); StringTypeAdapter<StringType2> adapter2(string2); @@ -363,7 +337,7 @@ namespace JSC { unsigned length = adapter1.length() + adapter2.length(); PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); if (!resultImpl) - return UString(); + return 0; UChar* result = buffer; adapter1.writeTo(result); @@ -374,7 +348,7 @@ namespace JSC { } template<typename StringType1, typename StringType2, typename StringType3> - UString makeString(StringType1 string1, StringType2 string2, StringType3 string3) + PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3) { StringTypeAdapter<StringType1> adapter1(string1); StringTypeAdapter<StringType2> adapter2(string2); @@ -384,7 +358,7 @@ namespace JSC { unsigned length = adapter1.length() + adapter2.length() + adapter3.length(); PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); if (!resultImpl) - return UString(); + return 0; UChar* result = buffer; adapter1.writeTo(result); @@ -397,7 +371,7 @@ namespace JSC { } template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> - UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) + PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) { StringTypeAdapter<StringType1> adapter1(string1); StringTypeAdapter<StringType2> adapter2(string2); @@ -408,7 +382,7 @@ namespace JSC { unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length(); PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); if (!resultImpl) - return UString(); + return 0; UChar* result = buffer; adapter1.writeTo(result); @@ -423,7 +397,7 @@ namespace JSC { } template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> - UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) + PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) { StringTypeAdapter<StringType1> adapter1(string1); StringTypeAdapter<StringType2> adapter2(string2); @@ -435,7 +409,7 @@ namespace JSC { unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length(); PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); if (!resultImpl) - return UString(); + return 0; UChar* result = buffer; adapter1.writeTo(result); @@ -452,7 +426,7 @@ namespace JSC { } 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) + PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) { StringTypeAdapter<StringType1> adapter1(string1); StringTypeAdapter<StringType2> adapter2(string2); @@ -465,7 +439,7 @@ namespace JSC { unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length(); PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); if (!resultImpl) - return UString(); + return 0; UChar* result = buffer; adapter1.writeTo(result); @@ -484,7 +458,7 @@ namespace JSC { } 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) + PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) { StringTypeAdapter<StringType1> adapter1(string1); StringTypeAdapter<StringType2> adapter2(string2); @@ -498,7 +472,7 @@ namespace JSC { unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length(); PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); if (!resultImpl) - return UString(); + return 0; UChar* result = buffer; adapter1.writeTo(result); @@ -519,7 +493,7 @@ namespace JSC { } 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) + PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) { StringTypeAdapter<StringType1> adapter1(string1); StringTypeAdapter<StringType2> adapter2(string2); @@ -534,7 +508,7 @@ namespace JSC { unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length() + adapter8.length(); PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); if (!resultImpl) - return UString(); + return 0; UChar* result = buffer; adapter1.writeTo(result); @@ -556,6 +530,69 @@ namespace JSC { return resultImpl; } + template<typename StringType1, typename StringType2> + UString makeString(StringType1 string1, StringType2 string2) + { + PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2); + if (!resultImpl) + CRASH(); + return resultImpl; + } + + template<typename StringType1, typename StringType2, typename StringType3> + UString makeString(StringType1 string1, StringType2 string2, StringType3 string3) + { + PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3); + if (!resultImpl) + CRASH(); + return resultImpl; + } + + template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> + UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) + { + PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4); + if (!resultImpl) + CRASH(); + return resultImpl; + } + + template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> + UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) + { + PassRefPtr<UStringImpl> resultImpl = 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 makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) + { + PassRefPtr<UStringImpl> resultImpl = 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 makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) + { + PassRefPtr<UStringImpl> resultImpl = 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 makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) + { + PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); + if (!resultImpl) + CRASH(); + return resultImpl; + } + } // namespace JSC namespace WTF { diff --git a/JavaScriptCore/runtime/UStringImpl.cpp b/JavaScriptCore/runtime/UStringImpl.cpp index 4b0d1c9..9882007 100644 --- a/JavaScriptCore/runtime/UStringImpl.cpp +++ b/JavaScriptCore/runtime/UStringImpl.cpp @@ -34,7 +34,44 @@ using namespace WTF::Unicode; using namespace std; namespace JSC { - + +PassRefPtr<UStringImpl> UStringImpl::create(const char* c) +{ + ASSERT(c); + + if (!c[0]) + return &UStringImpl::empty(); + + size_t length = strlen(c); + UChar* d; + PassRefPtr<UStringImpl> result = UStringImpl::createUninitialized(length, d); + for (size_t i = 0; i < length; i++) + d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend + return result; +} + +PassRefPtr<UStringImpl> UStringImpl::create(const char* c, int length) +{ + ASSERT(c); + + if (!length) + return &UStringImpl::empty(); + + UChar* d; + PassRefPtr<UStringImpl> result = UStringImpl::createUninitialized(length, d); + for (int i = 0; i < length; i++) + d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend + return result; +} + +PassRefPtr<UStringImpl> UStringImpl::create(const UChar* buffer, int length) +{ + UChar* newBuffer; + PassRefPtr<UStringImpl> impl = createUninitialized(length, newBuffer); + copyChars(newBuffer, buffer, length); + return impl; +} + SharedUChar* UStringImpl::baseSharedBuffer() { ASSERT((bufferOwnership() == BufferShared) diff --git a/JavaScriptCore/runtime/UStringImpl.h b/JavaScriptCore/runtime/UStringImpl.h index abed637..bbea0aa 100644 --- a/JavaScriptCore/runtime/UStringImpl.h +++ b/JavaScriptCore/runtime/UStringImpl.h @@ -87,20 +87,16 @@ public: template<size_t inlineCapacity> static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector) { - if (unsigned length = vector.size()) + if (unsigned length = vector.size()) { + ASSERT(vector.data()); return adoptRef(new UStringImpl(vector.releaseBuffer(), length, BufferOwned)); + } return &empty(); } - static PassRefPtr<UStringImpl> create(const UChar* buffer, int length) - { - UChar* newBuffer; - if (PassRefPtr<UStringImpl> impl = tryCreateUninitialized(length, newBuffer)) { - copyChars(newBuffer, buffer, length); - return impl; - } - return &null(); - } + static PassRefPtr<UStringImpl> create(const char* c); + static PassRefPtr<UStringImpl> create(const char* c, int length); + static PassRefPtr<UStringImpl> create(const UChar* buffer, int length); static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, int offset, int length) { @@ -180,7 +176,6 @@ public: static unsigned computeHash(const char* s, int length) { ASSERT(length >= 0); return WTF::stringHash(s, length); } static unsigned computeHash(const char* s) { return WTF::stringHash(s); } - static UStringImpl& null() { return *s_null; } static UStringImpl& empty() { return *s_empty; } ALWAYS_INLINE void checkConsistency() const @@ -288,7 +283,6 @@ private: mutable unsigned m_isIdentifier : 1; UntypedPtrAndBitfield m_dataBuffer; - JS_EXPORTDATA static UStringImpl* s_null; JS_EXPORTDATA static UStringImpl* s_empty; friend class JIT; diff --git a/JavaScriptCore/runtime/WeakGCPtr.h b/JavaScriptCore/runtime/WeakGCPtr.h index 8653721..3ed4645 100644 --- a/JavaScriptCore/runtime/WeakGCPtr.h +++ b/JavaScriptCore/runtime/WeakGCPtr.h @@ -44,7 +44,11 @@ public: return m_ptr; } - void clear() { m_ptr = 0; } + void clear(JSCell* ptr) + { + if (ptr == m_ptr) + m_ptr = 0; + } T& operator*() const { return *get(); } T* operator->() const { return get(); } diff --git a/JavaScriptCore/wscript b/JavaScriptCore/wscript index f5a041f..7caf8b4 100644 --- a/JavaScriptCore/wscript +++ b/JavaScriptCore/wscript @@ -72,6 +72,8 @@ def build(bld): full_dirs = get_dirs_for_features(jscore_dir, features=[build_port], dirs=jscore_dirs) includes = common_includes + full_dirs + if sys.platform.startswith('darwin'): + includes.append(os.path.join(jscore_dir, 'icu')) # 1. A simple program jscore = bld.new_task_gen( diff --git a/JavaScriptCore/wtf/Complex.h b/JavaScriptCore/wtf/Complex.h new file mode 100644 index 0000000..cfd1d20 --- /dev/null +++ b/JavaScriptCore/wtf/Complex.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 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: + * + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Complex_h +#define Complex_h + +#include <complex> +#include <wtf/MathExtras.h> + +namespace WebCore { + +typedef std::complex<double> Complex; + +inline Complex complexFromMagnitudePhase(double magnitude, double phase) +{ + return Complex(magnitude * cos(phase), magnitude * sin(phase)); +} + +} // namespace WebCore + +#endif // Complex_h diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp index 7b14809..79d2bfb 100644 --- a/JavaScriptCore/wtf/FastMalloc.cpp +++ b/JavaScriptCore/wtf/FastMalloc.cpp @@ -239,8 +239,16 @@ void* fastMalloc(size_t n) void* result = malloc(n); #endif - if (!result) + if (!result) { +#if PLATFORM(BREWMP) + // The behavior of malloc(0) is implementation defined. + // To make sure that fastMalloc never returns 0, retry with fastMalloc(1). + if (!n) + return fastMalloc(1); +#endif CRASH(); + } + return result; } @@ -279,8 +287,16 @@ void* fastCalloc(size_t n_elements, size_t element_size) void* result = calloc(n_elements, element_size); #endif - if (!result) + if (!result) { +#if PLATFORM(BREWMP) + // If either n_elements or element_size is 0, the behavior of calloc is implementation defined. + // To make sure that fastCalloc never returns 0, retry with fastCalloc(1, 1). + if (!n_elements || !element_size) + return fastCalloc(1, 1); +#endif CRASH(); + } + return result; } diff --git a/JavaScriptCore/wtf/HashTable.h b/JavaScriptCore/wtf/HashTable.h index f1473e3..ceb8963 100644 --- a/JavaScriptCore/wtf/HashTable.h +++ b/JavaScriptCore/wtf/HashTable.h @@ -24,6 +24,7 @@ #include "FastMalloc.h" #include "HashTraits.h" +#include "ValueCheck.h" #include <wtf/Assertions.h> #include <wtf/Threading.h> @@ -1021,7 +1022,7 @@ namespace WTF { ASSERT(entry == it.m_position); ++count; - KeyTraits::checkValueConsistency(it->first); + ValueCheck<Key>::checkConsistency(it->first); } ASSERT(count == m_keyCount); diff --git a/JavaScriptCore/wtf/HashTraits.h b/JavaScriptCore/wtf/HashTraits.h index 96ecac9..c8d40f7 100644 --- a/JavaScriptCore/wtf/HashTraits.h +++ b/JavaScriptCore/wtf/HashTraits.h @@ -26,13 +26,6 @@ #include <utility> #include <limits> -// For malloc_size and _msize. -#if OS(DARWIN) -#include <malloc/malloc.h> -#elif COMPILER(MSVC) -#include <malloc.h> -#endif - namespace WTF { using std::pair; @@ -58,7 +51,6 @@ namespace WTF { template<typename T> struct GenericHashTraits : GenericHashTraitsBase<IsInteger<T>::value, T> { typedef T TraitType; static T emptyValue() { return T(); } - static void checkValueConsistency(const T&) { } }; template<typename T> struct HashTraits : GenericHashTraits<T> { }; @@ -87,19 +79,6 @@ namespace WTF { static const bool needsDestruction = false; static void constructDeletedValue(P*& slot) { slot = reinterpret_cast<P*>(-1); } static bool isDeletedValue(P* value) { return value == reinterpret_cast<P*>(-1); } -#if !ASSERT_DISABLED - static void checkValueConsistency(const P* p) - { -#if (defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) || !defined(NDEBUG) -#if OS(DARWIN) - ASSERT(malloc_size(p)); -#elif COMPILER(MSVC) - ASSERT(_msize(const_cast<P*>(p))); -#endif -#endif - HashTraits<P>::checkValueConsistency(*p); - } -#endif }; template<typename P> struct HashTraits<RefPtr<P> > : GenericHashTraits<RefPtr<P> > { diff --git a/JavaScriptCore/wtf/MathExtras.h b/JavaScriptCore/wtf/MathExtras.h index a18949e..8666724 100644 --- a/JavaScriptCore/wtf/MathExtras.h +++ b/JavaScriptCore/wtf/MathExtras.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 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 @@ -26,8 +26,8 @@ #ifndef WTF_MathExtras_h #define WTF_MathExtras_h +#include <cmath> #include <float.h> -#include <math.h> #include <stdlib.h> #if OS(SOLARIS) @@ -186,4 +186,11 @@ inline float deg2turn(float d) { return d / 360.0f; } inline float rad2grad(float r) { return r * 200.0f / piFloat; } inline float grad2rad(float g) { return g * piFloat / 200.0f; } +#if !COMPILER(MSVC) && !COMPILER(RVCT) && !OS(ANDROID) && !COMPILER(WINSCW) +using std::isfinite; +using std::isinf; +using std::isnan; +using std::signbit; +#endif + #endif // #ifndef WTF_MathExtras_h diff --git a/JavaScriptCore/wtf/PassRefPtr.h b/JavaScriptCore/wtf/PassRefPtr.h index 36ba78e..9c6e44f 100644 --- a/JavaScriptCore/wtf/PassRefPtr.h +++ b/JavaScriptCore/wtf/PassRefPtr.h @@ -28,10 +28,21 @@ namespace WTF { template<typename T> class RefPtr; template<typename T> class PassRefPtr; template <typename T> PassRefPtr<T> adoptRef(T*); - - // Remove inline for winscw compiler to prevent the compiler agressively resolving - // T::deref(), which will fail compiling when PassRefPtr<T> is used as class member - // or function arguments before T is defined. + + + // Remove inline for WINSCW compiler to prevent the compiler agressively resolving + // T::ref() and T::deref(), which will fail compiling when PassRefPtr<T> is used as + // a class member or function arguments before T is defined. + template<typename T> +#if !COMPILER(WINSCW) + inline +#endif + void refIfNotNull(T* ptr) + { + if (UNLIKELY(ptr != 0)) + ptr->ref(); + } + template<typename T> #if !COMPILER(WINSCW) inline @@ -45,7 +56,7 @@ namespace WTF { template<typename T> class PassRefPtr { public: PassRefPtr() : m_ptr(0) {} - PassRefPtr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); } + PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } // It somewhat breaks the type system to allow transfer of ownership out of // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr // temporaries, and we don't really have a need to use real const PassRefPtrs @@ -53,14 +64,14 @@ namespace WTF { PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {} template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { } - ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull<T>(m_ptr); } + ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); } template <class U> - PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); } + PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { T* ptr = m_ptr; refIfNotNull(ptr); } T* get() const { return m_ptr; } - void clear() { if (T* ptr = m_ptr) ptr->deref(); m_ptr = 0; } + void clear() { T* ptr = m_ptr; derefIfNotNull(ptr); m_ptr = 0; } T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; } T& operator*() const { return *m_ptr; } @@ -143,23 +154,19 @@ namespace WTF { template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o) { T* optr = o.get(); - if (optr) - optr->ref(); + refIfNotNull(optr); T* ptr = m_ptr; m_ptr = optr; - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } template <typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr) { - if (optr) - optr->ref(); + refIfNotNull(optr); T* ptr = m_ptr; m_ptr = optr; - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } @@ -167,8 +174,7 @@ namespace WTF { { T* ptr = m_ptr; m_ptr = ref.releaseRef(); - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } @@ -176,8 +182,7 @@ namespace WTF { { T* ptr = m_ptr; m_ptr = ref.releaseRef(); - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h index d61d596..b113e79 100644 --- a/JavaScriptCore/wtf/Platform.h +++ b/JavaScriptCore/wtf/Platform.h @@ -422,6 +422,8 @@ #else #define WTF_PLATFORM_BREWMP_SIMULATOR 0 #endif +#undef WTF_OS_WINDOWS +#undef WTF_PLATFORM_WIN #elif OS(DARWIN) #define WTF_PLATFORM_MAC 1 #elif OS(WINDOWS) @@ -627,6 +629,10 @@ #define ENABLE_NETSCAPE_PLUGIN_API 0 #endif +#if PLATFORM(BREWMP) +#define USE_SYSTEM_MALLOC 1 +#endif + #if !defined(HAVE_ACCESSIBILITY) #if PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM) #define HAVE_ACCESSIBILITY 1 @@ -889,6 +895,13 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #endif /* !defined(ENABLE_JIT) */ +/* CPU architecture specific optimizations */ +#if CPU(ARM_TRADITIONAL) +#if ENABLE(JIT) && !defined(ENABLE_JIT_OPTIMIZE_MOD) && WTF_ARM_ARCH_AT_LEAST(5) +#define ENABLE_JIT_OPTIMIZE_MOD 1 +#endif +#endif + #if ENABLE(JIT) #ifndef ENABLE_JIT_OPTIMIZE_CALL #define ENABLE_JIT_OPTIMIZE_CALL 1 @@ -902,6 +915,9 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #ifndef ENABLE_JIT_OPTIMIZE_METHOD_CALLS #define ENABLE_JIT_OPTIMIZE_METHOD_CALLS 1 #endif +#ifndef ENABLE_JIT_OPTIMIZE_MOD +#define ENABLE_JIT_OPTIMIZE_MOD 0 +#endif #endif #if CPU(X86) && COMPILER(MSVC) diff --git a/JavaScriptCore/wtf/RefPtr.h b/JavaScriptCore/wtf/RefPtr.h index e6d1047..84e841c 100644 --- a/JavaScriptCore/wtf/RefPtr.h +++ b/JavaScriptCore/wtf/RefPtr.h @@ -24,6 +24,7 @@ #include <algorithm> #include "AlwaysInline.h" #include "FastAllocBase.h" +#include "PassRefPtr.h" namespace WTF { @@ -37,8 +38,8 @@ namespace WTF { template <typename T> class RefPtr : public FastAllocBase { public: RefPtr() : m_ptr(0) { } - RefPtr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); } - RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { if (T* ptr = m_ptr) ptr->ref(); } + RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } + RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { T* ptr = m_ptr; refIfNotNull(ptr); } // see comment in PassRefPtr.h for why this takes const reference template <typename U> RefPtr(const PassRefPtr<U>&); template <typename U> RefPtr(const NonNullPassRefPtr<U>&); @@ -50,13 +51,13 @@ namespace WTF { RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } - ~RefPtr() { if (T* ptr = m_ptr) ptr->deref(); } + ~RefPtr() { derefIfNotNull(m_ptr); } - template <typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); } + template <typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { T* ptr = m_ptr; refIfNotNull(ptr); } T* get() const { return m_ptr; } - void clear() { if (T* ptr = m_ptr) ptr->deref(); m_ptr = 0; } + void clear() { derefIfNotNull(m_ptr); m_ptr = 0; } PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; } T& operator*() const { return *m_ptr; } @@ -65,12 +66,8 @@ namespace WTF { bool operator!() const { return !m_ptr; } // This conversion operator allows implicit conversion to bool but not to other integer types. -#if COMPILER(WINSCW) - operator bool() const { return m_ptr; } -#else - typedef T* RefPtr::*UnspecifiedBoolType; + typedef T* (RefPtr::*UnspecifiedBoolType); operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; } -#endif RefPtr& operator=(const RefPtr&); RefPtr& operator=(T*); @@ -101,35 +98,29 @@ namespace WTF { template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o) { T* optr = o.get(); - if (optr) - optr->ref(); + refIfNotNull(optr); T* ptr = m_ptr; m_ptr = optr; - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o) { T* optr = o.get(); - if (optr) - optr->ref(); + refIfNotNull(optr); T* ptr = m_ptr; m_ptr = optr; - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr) { - if (optr) - optr->ref(); + refIfNotNull(optr); T* ptr = m_ptr; m_ptr = optr; - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } @@ -137,8 +128,7 @@ namespace WTF { { T* ptr = m_ptr; m_ptr = o.releaseRef(); - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } @@ -146,8 +136,7 @@ namespace WTF { { T* ptr = m_ptr; m_ptr = o.releaseRef(); - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } @@ -155,8 +144,7 @@ namespace WTF { { T* ptr = m_ptr; m_ptr = o.releaseRef(); - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } @@ -164,8 +152,7 @@ namespace WTF { { T* ptr = m_ptr; m_ptr = o.releaseRef(); - if (ptr) - ptr->deref(); + derefIfNotNull(ptr); return *this; } diff --git a/JavaScriptCore/wtf/ValueCheck.h b/JavaScriptCore/wtf/ValueCheck.h new file mode 100644 index 0000000..cd321b8 --- /dev/null +++ b/JavaScriptCore/wtf/ValueCheck.h @@ -0,0 +1,64 @@ +/* + * 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 ValueCheck_h +#define ValueCheck_h + +// For malloc_size and _msize. +#if OS(DARWIN) +#include <malloc/malloc.h> +#elif COMPILER(MSVC) +#include <malloc.h> +#endif + +namespace WTF { + +template<typename T> struct ValueCheck { + typedef T TraitType; + static void checkConsistency(const T&) { } +}; + +#if !ASSERT_DISABLED +template<typename P> struct ValueCheck<P*> { + typedef P* TraitType; + static void checkConsistency(const P* p) + { + if (!p) + return; +#if (defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) || !defined(NDEBUG) +#if OS(DARWIN) + ASSERT(malloc_size(p)); +#elif COMPILER(MSVC) + ASSERT(_msize(const_cast<P*>(p))); +#endif +#endif + ValueCheck<P>::checkConsistency(*p); + } +}; +#endif + +} + +#endif // ValueCheck_h diff --git a/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h index decc9c9..81ea321 100644 --- a/JavaScriptCore/wtf/Vector.h +++ b/JavaScriptCore/wtf/Vector.h @@ -24,6 +24,7 @@ #include "FastAllocBase.h" #include "Noncopyable.h" #include "NotFound.h" +#include "ValueCheck.h" #include "VectorTraits.h" #include <limits> #include <utility> @@ -586,6 +587,8 @@ namespace WTF { m_buffer.swap(other.m_buffer); } + void checkConsistency(); + private: void expandCapacity(size_t newMinCapacity); const T* expandCapacity(size_t newMinCapacity, const T*); @@ -987,6 +990,15 @@ namespace WTF { } template<typename T, size_t inlineCapacity> + inline void Vector<T, inlineCapacity>::checkConsistency() + { +#if !ASSERT_DISABLED + for (size_t i = 0; i < size(); ++i) + ValueCheck<T>::checkConsistency(at(i)); +#endif + } + + template<typename T, size_t inlineCapacity> void deleteAllValues(const Vector<T, inlineCapacity>& collection) { typedef typename Vector<T, inlineCapacity>::const_iterator iterator; @@ -1016,6 +1028,15 @@ namespace WTF { return !(a == b); } +#if !ASSERT_DISABLED + template<typename T> struct ValueCheck<Vector<T> > { + typedef Vector<T> TraitType; + static void checkConsistency(const Vector<T>& v) + { + v.checkConsistency(); + } + }; +#endif } // namespace WTF diff --git a/JavaScriptCore/wtf/Vector3.h b/JavaScriptCore/wtf/Vector3.h new file mode 100644 index 0000000..3c40b61 --- /dev/null +++ b/JavaScriptCore/wtf/Vector3.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 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: + * + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Vector3_h +#define Vector3_h + +#include <math.h> + +namespace WebCore { + +class Vector3 { +public: + Vector3() + : m_x(0.0) + , m_y(0.0) + , m_z(0.0) + { + } + + Vector3(double x, double y, double z) + : m_x(x) + , m_y(y) + , m_z(z) + { + } + + Vector3(const float p[3]) + : m_x(p[0]) + , m_y(p[1]) + , m_z(p[2]) + { + } + + Vector3(const double p[3]) + : m_x(p[0]) + , m_y(p[1]) + , m_z(p[2]) + { + } + + double abs() const + { + return sqrt(m_x * m_x + m_y * m_y + m_z * m_z); + } + + bool isZero() const + { + return !m_x && !m_y && !m_z; + } + + void normalize() + { + double absValue = abs(); + if (!absValue) + return; + + double k = 1.0 / absValue; + m_x *= k; + m_y *= k; + m_z *= k; + } + + double x() const { return m_x; } + double y() const { return m_y; } + double z() const { return m_z; } + +private: + double m_x; + double m_y; + double m_z; +}; + +inline Vector3 operator+(const Vector3& v1, const Vector3& v2) +{ + return Vector3(v1.x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z()); +} + +inline Vector3 operator-(const Vector3& v1, const Vector3& v2) +{ + return Vector3(v1.x() - v2.x(), v1.y() - v2.y(), v1.z() - v2.z()); +} + +inline Vector3 operator*(double k, const Vector3& v) +{ + return Vector3(k * v.x(), k * v.y(), k * v.z()); +} + +inline Vector3 operator*(const Vector3& v, double k) +{ + return Vector3(k * v.x(), k * v.y(), k * v.z()); +} + +inline double dot(const Vector3& v1, const Vector3& v2) +{ + return v1.x() * v2.x() + v1.y() * v2.y() + v1.z() * v2.z(); +} + +inline Vector3 cross(const Vector3& v1, const Vector3& v2) +{ + double x3 = v1.y() * v2.z() - v1.z() * v2.y(); + double y3 = v1.z() * v2.x() - v1.x() * v2.z(); + double z3 = v1.x() * v2.y() - v1.y() * v2.x(); + return Vector3(x3, y3, z3); +} + +inline double distance(const Vector3& v1, const Vector3& v2) +{ + return (v1 - v2).abs(); +} + +} // WebCore + +#endif // Vector3_h diff --git a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h index cfd482d..9b1754a 100644 --- a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h +++ b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h @@ -56,7 +56,7 @@ namespace QUnicodeTables { QT_END_NAMESPACE // ugly hack to make UChar compatible with JSChar in API/JSStringRef.h -#if defined(Q_OS_WIN) || COMPILER(WINSCW) +#if defined(Q_OS_WIN) || COMPILER(WINSCW) || COMPILER(RVCT) typedef wchar_t UChar; #else typedef uint16_t UChar; |