diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2009-06-15 09:06:43 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-06-15 09:31:31 (GMT) |
commit | c411f16870f112c3407c28c22b617f613a82cff4 (patch) | |
tree | 29a1bcd590c8b31af2aab445bfe8a978dc5bf582 /src/3rdparty/webkit/JavaScriptCore/runtime | |
parent | 3d77b56b32a0c53ec0bbfaa07236fedb900ff336 (diff) | |
download | Qt-c411f16870f112c3407c28c22b617f613a82cff4.zip Qt-c411f16870f112c3407c28c22b617f613a82cff4.tar.gz Qt-c411f16870f112c3407c28c22b617f613a82cff4.tar.bz2 |
Updated WebKit from /home/shausman/src/webkit/trunk to qtwebkit-4.6-snapshot-15062009 ( 65232bf00dc494ebfd978f998c88f58d18ecce1e )
Diffstat (limited to 'src/3rdparty/webkit/JavaScriptCore/runtime')
127 files changed, 5933 insertions, 3239 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ArgList.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ArgList.cpp index 5ead733..0b5d958 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ArgList.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ArgList.cpp @@ -30,19 +30,18 @@ namespace JSC { void ArgList::getSlice(int startIndex, ArgList& result) const { - ASSERT(!result.m_isReadOnly); - - const_iterator start = min(begin() + startIndex, end()); - result.m_vector.appendRange(start, end()); - result.m_size = result.m_vector.size(); - result.m_buffer = result.m_vector.data(); + if (startIndex <= 0 || static_cast<unsigned>(startIndex) >= m_argCount) { + result = ArgList(m_args, 0); + return; + } + result = ArgList(m_args + startIndex, m_argCount - startIndex); } -void ArgList::markLists(ListSet& markSet) +void MarkedArgumentBuffer::markLists(ListSet& markSet) { ListSet::iterator end = markSet.end(); for (ListSet::iterator it = markSet.begin(); it != end; ++it) { - ArgList* list = *it; + MarkedArgumentBuffer* list = *it; iterator end2 = list->end(); for (iterator it2 = list->begin(); it2 != end2; ++it2) @@ -51,7 +50,7 @@ void ArgList::markLists(ListSet& markSet) } } -void ArgList::slowAppend(JSValuePtr v) +void MarkedArgumentBuffer::slowAppend(JSValue v) { // As long as our size stays within our Vector's inline // capacity, all our values are allocated on the stack, and diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ArgList.h b/src/3rdparty/webkit/JavaScriptCore/runtime/ArgList.h index a1763e0..8e85d7f 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ArgList.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ArgList.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008 Apple Computer, Inc. + * Copyright (C) 2003, 2007, 2008, 2009 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -31,11 +31,11 @@ namespace JSC { - class ArgList : Noncopyable { + class MarkedArgumentBuffer : Noncopyable { private: static const unsigned inlineCapacity = 8; typedef Vector<Register, inlineCapacity> VectorType; - typedef HashSet<ArgList*> ListSet; + typedef HashSet<MarkedArgumentBuffer*> ListSet; public: typedef VectorType::iterator iterator; @@ -43,7 +43,7 @@ namespace JSC { // Constructor for a read-write list, to which you may append values. // FIXME: Remove all clients of this API, then remove this API. - ArgList() + MarkedArgumentBuffer() : m_markSet(0) #ifndef NDEBUG , m_isReadOnly(false) @@ -54,7 +54,7 @@ namespace JSC { } // Constructor for a read-only list whose data has already been allocated elsewhere. - ArgList(Register* buffer, size_t size) + MarkedArgumentBuffer(Register* buffer, size_t size) : m_buffer(buffer) , m_size(size) , m_markSet(0) @@ -76,7 +76,7 @@ namespace JSC { #endif } - ~ArgList() + ~MarkedArgumentBuffer() { if (m_markSet) m_markSet->remove(this); @@ -85,10 +85,10 @@ namespace JSC { size_t size() const { return m_size; } bool isEmpty() const { return !m_size; } - JSValuePtr at(ExecState* exec, size_t i) const + JSValue at(size_t i) const { if (i < m_size) - return m_buffer[i].jsValue(exec); + return m_buffer[i].jsValue(); return jsUndefined(); } @@ -99,7 +99,7 @@ namespace JSC { m_size = 0; } - void append(JSValuePtr v) + void append(JSValue v) { ASSERT(!m_isReadOnly); @@ -114,8 +114,6 @@ namespace JSC { } } - void getSlice(int startIndex, ArgList& result) const; - iterator begin() { return m_buffer; } iterator end() { return m_buffer + m_size; } @@ -125,7 +123,7 @@ namespace JSC { static void markLists(ListSet&); private: - void slowAppend(JSValuePtr); + void slowAppend(JSValue); Register* m_buffer; size_t m_size; @@ -156,6 +154,60 @@ namespace JSC { void operator delete(void*, size_t); }; + class ArgList { + friend class JIT; + public: + typedef JSValue* iterator; + typedef const JSValue* const_iterator; + + ArgList() + : m_args(0) + , m_argCount(0) + { + } + + ArgList(JSValue* args, unsigned argCount) + : m_args(args) + , m_argCount(argCount) + { + } + + ArgList(Register* args, int argCount) + : m_args(reinterpret_cast<JSValue*>(args)) + , m_argCount(argCount) + { + ASSERT(argCount >= 0); + } + + ArgList(const MarkedArgumentBuffer& args) + : m_args(reinterpret_cast<JSValue*>(const_cast<Register*>(args.begin()))) + , m_argCount(args.size()) + { + } + + JSValue at(size_t idx) const + { + if (idx < m_argCount) + return m_args[idx]; + return jsUndefined(); + } + + bool isEmpty() const { return !m_argCount; } + + size_t size() const { return m_argCount; } + + iterator begin() { return m_args; } + iterator end() { return m_args + m_argCount; } + + const_iterator begin() const { return m_args; } + const_iterator end() const { return m_args + m_argCount; } + + void getSlice(int startIndex, ArgList& result) const; + private: + JSValue* m_args; + size_t m_argCount; + }; + } // namespace JSC #endif // ArgList_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.cpp index b0429a9..f867fe8 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.cpp @@ -69,8 +69,50 @@ void Arguments::mark() d->activation->mark(); } -void Arguments::fillArgList(ExecState* exec, ArgList& args) +void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize) { + if (UNLIKELY(d->overrodeLength)) { + unsigned length = min(get(exec, exec->propertyNames().length).toUInt32(exec), maxSize); + for (unsigned i = 0; i < length; i++) + buffer[i] = get(exec, i); + return; + } + + if (LIKELY(!d->deletedArguments)) { + unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize); + unsigned i = 0; + for (; i < parametersLength; ++i) + buffer[i] = d->registers[d->firstParameterIndex + i].jsValue(); + for (; i < d->numArguments; ++i) + buffer[i] = d->extraArguments[i - d->numParameters].jsValue(); + return; + } + + unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize); + unsigned i = 0; + for (; i < parametersLength; ++i) { + if (!d->deletedArguments[i]) + buffer[i] = d->registers[d->firstParameterIndex + i].jsValue(); + else + buffer[i] = get(exec, i); + } + for (; i < d->numArguments; ++i) { + if (!d->deletedArguments[i]) + buffer[i] = d->extraArguments[i - d->numParameters].jsValue(); + else + buffer[i] = get(exec, i); + } +} + +void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) +{ + if (UNLIKELY(d->overrodeLength)) { + unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec); + for (unsigned i = 0; i < length; i++) + args.append(get(exec, i)); + return; + } + if (LIKELY(!d->deletedArguments)) { if (LIKELY(!d->numParameters)) { args.initialize(d->extraArguments, d->numArguments); @@ -85,9 +127,9 @@ void Arguments::fillArgList(ExecState* exec, ArgList& args) unsigned parametersLength = min(d->numParameters, d->numArguments); unsigned i = 0; for (; i < parametersLength; ++i) - args.append(d->registers[d->firstParameterIndex + i].jsValue(exec)); + args.append(d->registers[d->firstParameterIndex + i].jsValue()); for (; i < d->numArguments; ++i) - args.append(d->extraArguments[i - d->numParameters].jsValue(exec)); + args.append(d->extraArguments[i - d->numParameters].jsValue()); return; } @@ -95,13 +137,13 @@ void Arguments::fillArgList(ExecState* exec, ArgList& args) unsigned i = 0; for (; i < parametersLength; ++i) { if (!d->deletedArguments[i]) - args.append(d->registers[d->firstParameterIndex + i].jsValue(exec)); + args.append(d->registers[d->firstParameterIndex + i].jsValue()); else args.append(get(exec, i)); } for (; i < d->numArguments; ++i) { if (!d->deletedArguments[i]) - args.append(d->extraArguments[i - d->numParameters].jsValue(exec)); + args.append(d->extraArguments[i - d->numParameters].jsValue()); else args.append(get(exec, i)); } @@ -113,7 +155,7 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& sl if (i < d->numParameters) { slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]); } else - slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec)); + slot.setValue(d->extraArguments[i - d->numParameters].jsValue()); return true; } @@ -128,7 +170,7 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa if (i < d->numParameters) { slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]); } else - slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec)); + slot.setValue(d->extraArguments[i - d->numParameters].jsValue()); return true; } @@ -145,28 +187,28 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa return JSObject::getOwnPropertySlot(exec, propertyName, slot); } -void Arguments::put(ExecState* exec, unsigned i, JSValuePtr value, PutPropertySlot& slot) +void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot) { if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) - d->registers[d->firstParameterIndex + i] = JSValuePtr(value); + d->registers[d->firstParameterIndex + i] = JSValue(value); else - d->extraArguments[i - d->numParameters] = JSValuePtr(value); + d->extraArguments[i - d->numParameters] = JSValue(value); return; } JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot); } -void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) - d->registers[d->firstParameterIndex + i] = JSValuePtr(value); + d->registers[d->firstParameterIndex + i] = JSValue(value); else - d->extraArguments[i - d->numParameters] = JSValuePtr(value); + d->extraArguments[i - d->numParameters] = JSValue(value); return; } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.h index ebea6ad..72697eb 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.h @@ -63,8 +63,16 @@ namespace JSC { virtual void mark(); - void fillArgList(ExecState*, ArgList&); + void fillArgList(ExecState*, MarkedArgumentBuffer&); + uint32_t numProvidedArguments(ExecState* exec) const + { + if (UNLIKELY(d->overrodeLength)) + return get(exec, exec->propertyNames().length).toUInt32(exec); + return d->numArguments; + } + + void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize); void copyRegisters(); bool isTornOff() const { return d->registerArray; } void setActivation(JSActivation* activation) @@ -73,7 +81,7 @@ namespace JSC { d->registers = &activation->registerAt(0); } - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType)); } @@ -82,8 +90,8 @@ namespace JSC { void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValuePtr, PutPropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); @@ -94,9 +102,9 @@ namespace JSC { OwnPtr<ArgumentsData> d; }; - Arguments* asArguments(JSValuePtr); + Arguments* asArguments(JSValue); - inline Arguments* asArguments(JSValuePtr value) + inline Arguments* asArguments(JSValue value) { ASSERT(asObject(value)->inherits(&Arguments::info)); return static_cast<Arguments*>(asObject(value)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ArrayConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ArrayConstructor.cpp index e63abbc..e96bdfc 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -26,6 +26,7 @@ #include "ArrayPrototype.h" #include "JSArray.h" +#include "JSFunction.h" #include "Lookup.h" namespace JSC { @@ -45,15 +46,15 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> struct static JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args) { // a single numeric argument denotes the array size (!) - if (args.size() == 1 && args.at(exec, 0)->isNumber()) { - uint32_t n = args.at(exec, 0)->toUInt32(exec); - if (n != args.at(exec, 0)->toNumber(exec)) + if (args.size() == 1 && args.at(0).isNumber()) { + uint32_t n = args.at(0).toUInt32(exec); + if (n != args.at(0).toNumber(exec)) return throwError(exec, RangeError, "Array size is not a small enough positive integer."); return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), n); } // otherwise the array is constructed with the arguments in it - return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), args); + return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), args); } static JSObject* constructWithArrayConstructor(ExecState* exec, JSObject*, const ArgList& args) @@ -68,7 +69,7 @@ ConstructType ArrayConstructor::getConstructData(ConstructData& constructData) return ConstructTypeHost; } -static JSValuePtr callArrayConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL callArrayConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args) { return constructArrayWithSizeQuirk(exec, args); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp index 0d6ebdd..807e59a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2003 Peter Kelly (pmk@post.com) * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * @@ -24,7 +24,10 @@ #include "config.h" #include "ArrayPrototype.h" +#include "CodeBlock.h" +#include "CachedCall.h" #include "Interpreter.h" +#include "JIT.h" #include "ObjectPrototype.h" #include "Lookup.h" #include "Operations.h" @@ -36,25 +39,27 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ArrayPrototype); -static JSValuePtr arrayProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncConcat(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncJoin(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncPop(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncPush(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncReverse(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncShift(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncSlice(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncSort(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncSplice(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncUnShift(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncEvery(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncForEach(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncSome(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncFilter(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncMap(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue, const ArgList&); } @@ -62,6 +67,23 @@ static JSValuePtr arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValuePtr, c namespace JSC { +static inline bool isNumericCompareFunction(CallType callType, const CallData& callData) +{ + if (callType != CallTypeJS) + return false; + +#if ENABLE(JIT) + // If the JIT is enabled then we need to preserve the invariant that every + // function with a CodeBlock also has JIT code. + callData.js.functionBody->jitCode(callData.js.scopeChain); + CodeBlock& codeBlock = callData.js.functionBody->generatedBytecode(); +#else + CodeBlock& codeBlock = callData.js.functionBody->bytecode(callData.js.scopeChain); +#endif + + return codeBlock.isNumericCompareFunction(); +} + // ------------------------------ ArrayPrototype ---------------------------- const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::arrayTable}; @@ -86,6 +108,8 @@ const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::a indexOf arrayProtoFuncIndexOf DontEnum|Function 1 lastIndexOf arrayProtoFuncLastIndexOf DontEnum|Function 1 filter arrayProtoFuncFilter DontEnum|Function 1 + reduce arrayProtoFuncReduce DontEnum|Function 1 + reduceRight arrayProtoFuncReduceRight DontEnum|Function 1 map arrayProtoFuncMap DontEnum|Function 1 @end */ @@ -104,36 +128,38 @@ bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& prope // ------------------------------ Array Functions ---------------------------- // Helper function -static JSValuePtr getProperty(ExecState* exec, JSObject* obj, unsigned index) +static JSValue getProperty(ExecState* exec, JSObject* obj, unsigned index) { PropertySlot slot(obj); if (!obj->getPropertySlot(exec, index, slot)) - return noValue(); + return JSValue(); return slot.getValue(exec, index); } -static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValuePtr value) +static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValue value) { PutPropertySlot slot; obj->put(exec, propertyName, value, slot); } -JSValuePtr arrayProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&JSArray::info)) + if (!thisValue.isObject(&JSArray::info)) return throwError(exec, TypeError); JSObject* thisObj = asArray(thisValue); HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements; - if (arrayVisitedElements.size() > MaxReentryDepth) - return throwError(exec, RangeError, "Maximum call stack size exceeded."); + if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) { + if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth) + return throwError(exec, RangeError, "Maximum call stack size exceeded."); + } bool alreadyVisited = !arrayVisitedElements.add(thisObj).second; if (alreadyVisited) return jsEmptyString(exec); // return an empty string, avoiding infinite recursion. Vector<UChar, 256> strBuffer; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length; k++) { if (k >= 1) strBuffer.append(','); @@ -143,11 +169,11 @@ JSValuePtr arrayProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisVal break; } - JSValuePtr element = thisObj->get(exec, k); - if (element->isUndefinedOrNull()) + JSValue element = thisObj->get(exec, k); + if (element.isUndefinedOrNull()) continue; - UString str = element->toString(exec); + UString str = element.toString(exec); strBuffer.append(str.data(), str.size()); if (!strBuffer.data()) { @@ -162,22 +188,24 @@ JSValuePtr arrayProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisVal return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0)); } -JSValuePtr arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&JSArray::info)) + if (!thisValue.isObject(&JSArray::info)) return throwError(exec, TypeError); JSObject* thisObj = asArray(thisValue); HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements; - if (arrayVisitedElements.size() > MaxReentryDepth) - return throwError(exec, RangeError, "Maximum call stack size exceeded."); + if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) { + if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth) + return throwError(exec, RangeError, "Maximum call stack size exceeded."); + } bool alreadyVisited = !arrayVisitedElements.add(thisObj).second; if (alreadyVisited) return jsEmptyString(exec); // return an empty string, avoding infinite recursion. Vector<UChar, 256> strBuffer; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length; k++) { if (k >= 1) strBuffer.append(','); @@ -187,19 +215,19 @@ JSValuePtr arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr t break; } - JSValuePtr element = thisObj->get(exec, k); - if (element->isUndefinedOrNull()) + JSValue element = thisObj->get(exec, k); + if (element.isUndefinedOrNull()) continue; - JSObject* o = element->toObject(exec); - JSValuePtr conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); + JSObject* o = element.toObject(exec); + JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); UString str; CallData callData; - CallType callType = conversionFunction->getCallData(callData); + CallType callType = conversionFunction.getCallData(callData); if (callType != CallTypeNone) - str = call(exec, conversionFunction, callType, callData, element, exec->emptyList())->toString(exec); + str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec); else - str = element->toString(exec); + str = element.toString(exec); strBuffer.append(str.data(), str.size()); if (!strBuffer.data()) { @@ -214,13 +242,15 @@ JSValuePtr arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr t return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0)); } -JSValuePtr arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements; - if (arrayVisitedElements.size() > MaxReentryDepth) - return throwError(exec, RangeError, "Maximum call stack size exceeded."); + if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) { + if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth) + return throwError(exec, RangeError, "Maximum call stack size exceeded."); + } bool alreadyVisited = !arrayVisitedElements.add(thisObj).second; if (alreadyVisited) @@ -229,9 +259,9 @@ JSValuePtr arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValuePtr thisValue, Vector<UChar, 256> strBuffer; UChar comma = ','; - UString separator = args.at(exec, 0)->isUndefined() ? UString(&comma, 1) : args.at(exec, 0)->toString(exec); + UString separator = args.at(0).isUndefined() ? UString(&comma, 1) : args.at(0).toString(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(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()); @@ -241,11 +271,11 @@ JSValuePtr arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValuePtr thisValue, break; } - JSValuePtr element = thisObj->get(exec, k); - if (element->isUndefinedOrNull()) + JSValue element = thisObj->get(exec, k); + if (element.isUndefinedOrNull()) continue; - UString str = element->toString(exec); + UString str = element.toString(exec); strBuffer.append(str.data(), str.size()); if (!strBuffer.data()) { @@ -260,19 +290,19 @@ JSValuePtr arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValuePtr thisValue, return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0)); } -JSValuePtr arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { JSArray* arr = constructEmptyArray(exec); int n = 0; - JSValuePtr curArg = thisValue->toThisObject(exec); + JSValue curArg = thisValue.toThisObject(exec); ArgList::const_iterator it = args.begin(); ArgList::const_iterator end = args.end(); while (1) { - if (curArg->isObject(&JSArray::info)) { - JSArray* curArray = asArray(curArg); - unsigned length = curArray->length(); + if (curArg.isObject(&JSArray::info)) { + unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec); + JSObject* curObject = curArg.toObject(exec); for (unsigned k = 0; k < length; ++k) { - if (JSValuePtr v = getProperty(exec, curArray, k)) + if (JSValue v = getProperty(exec, curObject, k)) arr->put(exec, n, v); n++; } @@ -282,21 +312,21 @@ JSValuePtr arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue } if (it == end) break; - curArg = (*it).jsValue(exec); + curArg = (*it); ++it; } arr->setLength(n); return arr; } -JSValuePtr arrayProtoFuncPop(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (exec->interpreter()->isJSArray(thisValue)) + if (isJSArray(&exec->globalData(), thisValue)) return asArray(thisValue)->pop(); - JSObject* thisObj = thisValue->toThisObject(exec); - JSValuePtr result; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + JSObject* thisObj = thisValue.toThisObject(exec); + JSValue result; + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (length == 0) { putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length)); result = jsUndefined(); @@ -308,33 +338,33 @@ JSValuePtr arrayProtoFuncPop(ExecState* exec, JSObject*, JSValuePtr thisValue, c return result; } -JSValuePtr arrayProtoFuncPush(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (exec->interpreter()->isJSArray(thisValue) && args.size() == 1) { + if (isJSArray(&exec->globalData(), thisValue) && args.size() == 1) { JSArray* array = asArray(thisValue); - array->push(exec, args.begin()->jsValue(exec)); + array->push(exec, *args.begin()); return jsNumber(exec, array->length()); } - JSObject* thisObj = thisValue->toThisObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + JSObject* thisObj = thisValue.toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned n = 0; n < args.size(); n++) - thisObj->put(exec, length + n, args.at(exec, n)); + thisObj->put(exec, length + n, args.at(n)); length += args.size(); putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length)); return jsNumber(exec, length); } -JSValuePtr arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - JSObject* thisObj = thisValue->toThisObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + JSObject* thisObj = thisValue.toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned middle = length / 2; for (unsigned k = 0; k < middle; k++) { unsigned lk1 = length - k - 1; - JSValuePtr obj2 = getProperty(exec, thisObj, lk1); - JSValuePtr obj = getProperty(exec, thisObj, k); + JSValue obj2 = getProperty(exec, thisObj, lk1); + JSValue obj = getProperty(exec, thisObj, k); if (obj2) thisObj->put(exec, k, obj2); @@ -349,19 +379,19 @@ JSValuePtr arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValuePtr thisValu return thisObj; } -JSValuePtr arrayProtoFuncShift(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - JSObject* thisObj = thisValue->toThisObject(exec); - JSValuePtr result; + JSObject* thisObj = thisValue.toThisObject(exec); + JSValue result; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (length == 0) { putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length)); result = jsUndefined(); } else { result = thisObj->get(exec, 0); for (unsigned k = 1; k < length; k++) { - if (JSValuePtr obj = getProperty(exec, thisObj, k)) + if (JSValue obj = getProperty(exec, thisObj, k)) thisObj->put(exec, k - 1, obj); else thisObj->deleteProperty(exec, k - 1); @@ -372,17 +402,17 @@ JSValuePtr arrayProtoFuncShift(ExecState* exec, JSObject*, JSValuePtr thisValue, return result; } -JSValuePtr arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10 - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); // We return a new array JSArray* resObj = constructEmptyArray(exec); - JSValuePtr result = resObj; - double begin = args.at(exec, 0)->toInteger(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + JSValue result = resObj; + double begin = args.at(0).toInteger(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (begin >= 0) { if (begin > length) begin = length; @@ -392,10 +422,10 @@ JSValuePtr arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, begin = 0; } double end; - if (args.at(exec, 1)->isUndefined()) + if (args.at(1).isUndefined()) end = length; else { - end = args.at(exec, 1)->toInteger(exec); + end = args.at(1).toInteger(exec); if (end < 0) { end += length; if (end < 0) @@ -410,30 +440,32 @@ JSValuePtr arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, int b = static_cast<int>(begin); int e = static_cast<int>(end); for (int k = b; k < e; k++, n++) { - if (JSValuePtr v = getProperty(exec, thisObj, k)) + if (JSValue v = getProperty(exec, thisObj, k)) resObj->put(exec, n, v); } resObj->setLength(n); return result; } -JSValuePtr arrayProtoFuncSort(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValuePtr function = args.at(exec, 0); + JSValue function = args.at(0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (thisObj->classInfo() == &JSArray::info) { - if (callType != CallTypeNone) + if (isNumericCompareFunction(callType, callData)) + asArray(thisObj)->sortNumeric(exec, function, callType, callData); + else if (callType != CallTypeNone) asArray(thisObj)->sort(exec, function, callType, callData); else asArray(thisObj)->sort(exec); return thisObj; } - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (!length) return thisObj; @@ -441,23 +473,23 @@ JSValuePtr arrayProtoFuncSort(ExecState* exec, JSObject*, JSValuePtr thisValue, // "Min" sort. Not the fastest, but definitely less code than heapsort // or quicksort, and much less swapping than bubblesort/insertionsort. for (unsigned i = 0; i < length - 1; ++i) { - JSValuePtr iObj = thisObj->get(exec, i); + JSValue iObj = thisObj->get(exec, i); unsigned themin = i; - JSValuePtr minObj = iObj; + JSValue minObj = iObj; for (unsigned j = i + 1; j < length; ++j) { - JSValuePtr jObj = thisObj->get(exec, j); + JSValue jObj = thisObj->get(exec, j); double compareResult; - if (jObj->isUndefined()) + if (jObj.isUndefined()) compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1) - else if (minObj->isUndefined()) + else if (minObj.isUndefined()) compareResult = -1; else if (callType != CallTypeNone) { - ArgList l; + MarkedArgumentBuffer l; l.append(jObj); l.append(minObj); - compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l)->toNumber(exec); + compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l).toNumber(exec); } else - compareResult = (jObj->toString(exec) < minObj->toString(exec)) ? -1 : 1; + compareResult = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1; if (compareResult < 0) { themin = j; @@ -473,17 +505,17 @@ JSValuePtr arrayProtoFuncSort(ExecState* exec, JSObject*, JSValuePtr thisValue, return thisObj; } -JSValuePtr arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); // 15.4.4.12 JSArray* resObj = constructEmptyArray(exec); - JSValuePtr result = resObj; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + JSValue result = resObj; + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (!args.size()) return jsUndefined(); - int begin = args.at(exec, 0)->toUInt32(exec); + int begin = args.at(0).toUInt32(exec); if (begin < 0) begin = std::max<int>(begin + length, 0); else @@ -491,12 +523,12 @@ JSValuePtr arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValuePtr thisValue unsigned deleteCount; if (args.size() > 1) - deleteCount = std::min<int>(std::max<int>(args.at(exec, 1)->toUInt32(exec), 0), length - begin); + deleteCount = std::min<int>(std::max<int>(args.at(1).toUInt32(exec), 0), length - begin); else deleteCount = length - begin; for (unsigned k = 0; k < deleteCount; k++) { - if (JSValuePtr v = getProperty(exec, thisObj, k + begin)) + if (JSValue v = getProperty(exec, thisObj, k + begin)) resObj->put(exec, k, v); } resObj->setLength(deleteCount); @@ -505,7 +537,7 @@ JSValuePtr arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValuePtr thisValue if (additionalArgs != deleteCount) { if (additionalArgs < deleteCount) { for (unsigned k = begin; k < length - deleteCount; ++k) { - if (JSValuePtr v = getProperty(exec, thisObj, k + deleteCount)) + if (JSValue v = getProperty(exec, thisObj, k + deleteCount)) thisObj->put(exec, k + additionalArgs, v); else thisObj->deleteProperty(exec, k + additionalArgs); @@ -514,7 +546,7 @@ JSValuePtr arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValuePtr thisValue thisObj->deleteProperty(exec, k - 1); } else { for (unsigned k = length - deleteCount; (int)k > begin; --k) { - if (JSValuePtr obj = getProperty(exec, thisObj, k + deleteCount - 1)) + if (JSValue obj = getProperty(exec, thisObj, k + deleteCount - 1)) thisObj->put(exec, k + additionalArgs - 1, obj); else thisObj->deleteProperty(exec, k + additionalArgs - 1); @@ -522,101 +554,138 @@ JSValuePtr arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValuePtr thisValue } } for (unsigned k = 0; k < additionalArgs; ++k) - thisObj->put(exec, k + begin, args.at(exec, k + 2)); + thisObj->put(exec, k + begin, args.at(k + 2)); putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - deleteCount + additionalArgs)); return result; } -JSValuePtr arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); // 15.4.4.13 - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned nrArgs = args.size(); if (nrArgs) { for (unsigned k = length; k > 0; --k) { - if (JSValuePtr v = getProperty(exec, thisObj, k - 1)) + if (JSValue v = getProperty(exec, thisObj, k - 1)) thisObj->put(exec, k + nrArgs - 1, v); else thisObj->deleteProperty(exec, k + nrArgs - 1); } } for (unsigned k = 0; k < nrArgs; ++k) - thisObj->put(exec, k, args.at(exec, k)); - JSValuePtr result = jsNumber(exec, length + nrArgs); + thisObj->put(exec, k, args.at(k)); + JSValue result = jsNumber(exec, length + nrArgs); putProperty(exec, thisObj, exec->propertyNames().length, result); return result; } -JSValuePtr arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValuePtr function = args.at(exec, 0); + JSValue function = args.at(0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec); + JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec); JSArray* resultArray = constructEmptyArray(exec); unsigned filterIndex = 0; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); - for (unsigned k = 0; k < length && !exec->hadException(); ++k) { + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + unsigned k = 0; + if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { + JSFunction* f = asFunction(function); + JSArray* array = asArray(thisObj); + CachedCall cachedCall(exec, f, 3, exec->exceptionSlot()); + for (; k < length && !exec->hadException(); ++k) { + if (!array->canGetIndex(k)) + break; + JSValue v = array->getIndex(k); + cachedCall.setThis(applyThis); + cachedCall.setArgument(0, v); + cachedCall.setArgument(1, jsNumber(exec, k)); + cachedCall.setArgument(2, thisObj); + + JSValue result = cachedCall.call(); + if (result.toBoolean(exec)) + resultArray->put(exec, filterIndex++, v); + } + if (k == length) + return resultArray; + } + for (; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); if (!thisObj->getPropertySlot(exec, k, slot)) continue; - JSValuePtr v = slot.getValue(exec, k); + JSValue v = slot.getValue(exec, k); - ArgList eachArguments; + MarkedArgumentBuffer eachArguments; eachArguments.append(v); eachArguments.append(jsNumber(exec, k)); eachArguments.append(thisObj); - JSValuePtr result = call(exec, function, callType, callData, applyThis, eachArguments); + JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); - if (result->toBoolean(exec)) + if (result.toBoolean(exec)) resultArray->put(exec, filterIndex++, v); } return resultArray; } -JSValuePtr arrayProtoFuncMap(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValuePtr function = args.at(exec, 0); + JSValue function = args.at(0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec); + JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); JSArray* resultArray = constructEmptyArray(exec, length); - - for (unsigned k = 0; k < length && !exec->hadException(); ++k) { + unsigned k = 0; + if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { + JSFunction* f = asFunction(function); + JSArray* array = asArray(thisObj); + CachedCall cachedCall(exec, f, 3, exec->exceptionSlot()); + for (; k < length && !exec->hadException(); ++k) { + if (UNLIKELY(!array->canGetIndex(k))) + break; + + cachedCall.setThis(applyThis); + cachedCall.setArgument(0, array->getIndex(k)); + cachedCall.setArgument(1, jsNumber(exec, k)); + cachedCall.setArgument(2, thisObj); + + resultArray->JSArray::put(exec, k, cachedCall.call()); + } + } + for (; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); if (!thisObj->getPropertySlot(exec, k, slot)) continue; - JSValuePtr v = slot.getValue(exec, k); + JSValue v = slot.getValue(exec, k); - ArgList eachArguments; + MarkedArgumentBuffer eachArguments; eachArguments.append(v); eachArguments.append(jsNumber(exec, k)); eachArguments.append(thisObj); - JSValuePtr result = call(exec, function, callType, callData, applyThis, eachArguments); + JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); resultArray->put(exec, k, result); } @@ -628,34 +697,52 @@ JSValuePtr arrayProtoFuncMap(ExecState* exec, JSObject*, JSValuePtr thisValue, c // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some -JSValuePtr arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValuePtr function = args.at(exec, 0); + JSValue function = args.at(0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec); - - JSValuePtr result = jsBoolean(true); - - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); - for (unsigned k = 0; k < length && !exec->hadException(); ++k) { + JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec); + + JSValue result = jsBoolean(true); + + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + unsigned k = 0; + if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { + JSFunction* f = asFunction(function); + JSArray* array = asArray(thisObj); + CachedCall cachedCall(exec, f, 3, exec->exceptionSlot()); + for (; k < length && !exec->hadException(); ++k) { + if (UNLIKELY(!array->canGetIndex(k))) + break; + + cachedCall.setThis(applyThis); + cachedCall.setArgument(0, array->getIndex(k)); + cachedCall.setArgument(1, jsNumber(exec, k)); + cachedCall.setArgument(2, thisObj); + + if (!cachedCall.call().toBoolean(exec)) + return jsBoolean(false); + } + } + for (; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); if (!thisObj->getPropertySlot(exec, k, slot)) continue; - ArgList eachArguments; + MarkedArgumentBuffer eachArguments; eachArguments.append(slot.getValue(exec, k)); eachArguments.append(jsNumber(exec, k)); eachArguments.append(thisObj); - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec); + bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); if (!predicateResult) { result = jsBoolean(false); @@ -666,25 +753,42 @@ JSValuePtr arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValuePtr thisValue, return result; } -JSValuePtr arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValuePtr function = args.at(exec, 0); + JSValue function = args.at(0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec); + JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec); + + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + unsigned k = 0; + if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { + JSFunction* f = asFunction(function); + JSArray* array = asArray(thisObj); + CachedCall cachedCall(exec, f, 3, exec->exceptionSlot()); + for (; k < length && !exec->hadException(); ++k) { + if (UNLIKELY(!array->canGetIndex(k))) + break; - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); - for (unsigned k = 0; k < length && !exec->hadException(); ++k) { + cachedCall.setThis(applyThis); + cachedCall.setArgument(0, array->getIndex(k)); + cachedCall.setArgument(1, jsNumber(exec, k)); + cachedCall.setArgument(2, thisObj); + + cachedCall.call(); + } + } + for (; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); if (!thisObj->getPropertySlot(exec, k, slot)) continue; - ArgList eachArguments; + MarkedArgumentBuffer eachArguments; eachArguments.append(slot.getValue(exec, k)); eachArguments.append(jsNumber(exec, k)); eachArguments.append(thisObj); @@ -694,32 +798,50 @@ JSValuePtr arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValuePtr thisValu return jsUndefined(); } -JSValuePtr arrayProtoFuncSome(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - JSValuePtr function = args.at(exec, 0); + JSValue function = args.at(0); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec); - - JSValuePtr result = jsBoolean(false); - - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); - for (unsigned k = 0; k < length && !exec->hadException(); ++k) { + JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec); + + JSValue result = jsBoolean(false); + + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + unsigned k = 0; + if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { + JSFunction* f = asFunction(function); + JSArray* array = asArray(thisObj); + CachedCall cachedCall(exec, f, 3, exec->exceptionSlot()); + for (; k < length && !exec->hadException(); ++k) { + if (UNLIKELY(!array->canGetIndex(k))) + break; + + cachedCall.setThis(applyThis); + cachedCall.setArgument(0, array->getIndex(k)); + cachedCall.setArgument(1, jsNumber(exec, k)); + cachedCall.setArgument(2, thisObj); + + if (cachedCall.call().toBoolean(exec)) + return jsBoolean(true); + } + } + for (; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); if (!thisObj->getPropertySlot(exec, k, slot)) continue; - ArgList eachArguments; + MarkedArgumentBuffer eachArguments; eachArguments.append(slot.getValue(exec, k)); eachArguments.append(jsNumber(exec, k)); eachArguments.append(thisObj); - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec); + bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); if (predicateResult) { result = jsBoolean(true); @@ -729,16 +851,155 @@ JSValuePtr arrayProtoFuncSome(ExecState* exec, JSObject*, JSValuePtr thisValue, return result; } -JSValuePtr arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + JSObject* thisObj = thisValue.toThisObject(exec); + + JSValue function = args.at(0); + CallData callData; + CallType callType = function.getCallData(callData); + if (callType == CallTypeNone) + return throwError(exec, TypeError); + + unsigned i = 0; + JSValue rv; + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (!length && args.size() == 1) + return throwError(exec, TypeError); + JSArray* array = 0; + if (isJSArray(&exec->globalData(), thisObj)) + array = asArray(thisObj); + + if (args.size() >= 2) + rv = args.at(1); + else if (array && array->canGetIndex(0)){ + rv = array->getIndex(0); + i = 1; + } else { + for (i = 0; i < length; i++) { + rv = getProperty(exec, thisObj, i); + if (rv) + break; + } + if (!rv) + return throwError(exec, TypeError); + i++; + } + + if (callType == CallTypeJS && array) { + CachedCall cachedCall(exec, asFunction(function), 4, exec->exceptionSlot()); + for (; i < length && !exec->hadException(); ++i) { + cachedCall.setThis(jsNull()); + cachedCall.setArgument(0, rv); + JSValue v; + if (LIKELY(array->canGetIndex(i))) + v = array->getIndex(i); + else + break; // length has been made unsafe while we enumerate fallback to slow path + cachedCall.setArgument(1, v); + cachedCall.setArgument(2, jsNumber(exec, i)); + cachedCall.setArgument(3, array); + rv = cachedCall.call(); + } + if (i == length) // only return if we reached the end of the array + return rv; + } + + for (; i < length && !exec->hadException(); ++i) { + JSValue prop = getProperty(exec, thisObj, i); + if (!prop) + continue; + + MarkedArgumentBuffer eachArguments; + eachArguments.append(rv); + eachArguments.append(prop); + eachArguments.append(jsNumber(exec, i)); + eachArguments.append(thisObj); + + rv = call(exec, function, callType, callData, jsNull(), eachArguments); + } + return rv; +} + +JSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + JSObject* thisObj = thisValue.toThisObject(exec); + + JSValue function = args.at(0); + CallData callData; + CallType callType = function.getCallData(callData); + if (callType == CallTypeNone) + return throwError(exec, TypeError); + + unsigned i = 0; + JSValue rv; + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (!length && args.size() == 1) + return throwError(exec, TypeError); + JSArray* array = 0; + if (isJSArray(&exec->globalData(), thisObj)) + array = asArray(thisObj); + + if (args.size() >= 2) + rv = args.at(1); + else if (array && array->canGetIndex(length - 1)){ + rv = array->getIndex(length - 1); + i = 1; + } else { + for (i = 0; i < length; i++) { + rv = getProperty(exec, thisObj, length - i - 1); + if (rv) + break; + } + if (!rv) + return throwError(exec, TypeError); + i++; + } + + if (callType == CallTypeJS && array) { + CachedCall cachedCall(exec, asFunction(function), 4, exec->exceptionSlot()); + for (; i < length && !exec->hadException(); ++i) { + unsigned idx = length - i - 1; + cachedCall.setThis(jsNull()); + cachedCall.setArgument(0, rv); + if (UNLIKELY(!array->canGetIndex(idx))) + break; // length has been made unsafe while we enumerate fallback to slow path + cachedCall.setArgument(1, array->getIndex(idx)); + cachedCall.setArgument(2, jsNumber(exec, idx)); + cachedCall.setArgument(3, array); + rv = cachedCall.call(); + } + if (i == length) // only return if we reached the end of the array + return rv; + } + + for (; i < length && !exec->hadException(); ++i) { + unsigned idx = length - i - 1; + JSValue prop = getProperty(exec, thisObj, idx); + if (!prop) + continue; + + MarkedArgumentBuffer eachArguments; + eachArguments.append(rv); + eachArguments.append(prop); + eachArguments.append(jsNumber(exec, idx)); + eachArguments.append(thisObj); + + rv = call(exec, function, callType, callData, jsNull(), eachArguments); + } + return rv; +} + +JSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { // JavaScript 1.5 Extension by Mozilla // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); unsigned index = 0; - double d = args.at(exec, 1)->toInteger(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + double d = args.at(1).toInteger(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (d < 0) d += length; if (d > 0) { @@ -748,28 +1009,28 @@ JSValuePtr arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValu index = static_cast<unsigned>(d); } - JSValuePtr searchElement = args.at(exec, 0); + JSValue searchElement = args.at(0); for (; index < length; ++index) { - JSValuePtr e = getProperty(exec, thisObj, index); + JSValue e = getProperty(exec, thisObj, index); if (!e) continue; - if (strictEqual(searchElement, e)) + if (JSValue::strictEqual(searchElement, e)) return jsNumber(exec, index); } return jsNumber(exec, -1); } -JSValuePtr arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { // JavaScript 1.6 Extension by Mozilla // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); int index = length - 1; - double d = args.at(exec, 1)->toIntegerPreserveNaN(exec); + double d = args.at(1).toIntegerPreserveNaN(exec); if (d < 0) { d += length; @@ -779,12 +1040,12 @@ JSValuePtr arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr this if (d < length) index = static_cast<int>(d); - JSValuePtr searchElement = args.at(exec, 0); + JSValue searchElement = args.at(0); for (; index >= 0; --index) { - JSValuePtr e = getProperty(exec, thisObj, index); + JSValue e = getProperty(exec, thisObj, index); if (!e) continue; - if (strictEqual(searchElement, e)) + if (JSValue::strictEqual(searchElement, e)) return jsNumber(exec, index); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanConstructor.cpp index aa245bb..9fcba37 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -41,7 +41,7 @@ BooleanConstructor::BooleanConstructor(ExecState* exec, PassRefPtr<Structure> st JSObject* constructBoolean(ExecState* exec, const ArgList& args) { BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure()); - obj->setInternalValue(jsBoolean(args.at(exec, 0)->toBoolean(exec))); + obj->setInternalValue(jsBoolean(args.at(0).toBoolean(exec))); return obj; } @@ -57,9 +57,9 @@ ConstructType BooleanConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.6.1 -static JSValuePtr callBooleanConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL callBooleanConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsBoolean(args.at(exec, 0)->toBoolean(exec)); + return jsBoolean(args.at(0).toBoolean(exec)); } CallType BooleanConstructor::getCallData(CallData& callData) @@ -68,7 +68,7 @@ CallType BooleanConstructor::getCallData(CallData& callData) return CallTypeHost; } -JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValuePtr immediateBooleanValue) +JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValue immediateBooleanValue) { BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure()); obj->setInternalValue(immediateBooleanValue); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanConstructor.h b/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanConstructor.h index db4e8e2..d9f51ab 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanConstructor.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanConstructor.h @@ -36,7 +36,7 @@ namespace JSC { virtual CallType getCallData(CallData&); }; - JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValuePtr); + JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValue); JSObject* constructBoolean(ExecState*, const ArgList&); } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanObject.h index 68941e3..cfd55fe 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanObject.h @@ -33,9 +33,9 @@ namespace JSC { static const ClassInfo info; }; - BooleanObject* asBooleanObject(JSValuePtr); + BooleanObject* asBooleanObject(JSValue); - inline BooleanObject* asBooleanObject(JSValuePtr value) + inline BooleanObject* asBooleanObject(JSValue value) { ASSERT(asObject(value)->inherits(&BooleanObject::info)); return static_cast<BooleanObject*>(asObject(value)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanPrototype.cpp index 77a7a1e..703a568 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/BooleanPrototype.cpp @@ -22,6 +22,7 @@ #include "BooleanPrototype.h" #include "Error.h" +#include "JSFunction.h" #include "JSString.h" #include "ObjectPrototype.h" #include "PrototypeFunction.h" @@ -31,8 +32,8 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype); // Functions -static JSValuePtr booleanProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr booleanProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*, JSObject*, JSValue, const ArgList&); // ECMA 15.6.4 @@ -41,8 +42,8 @@ BooleanPrototype::BooleanPrototype(ExecState* exec, PassRefPtr<Structure> struct { setInternalValue(jsBoolean(false)); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum); } @@ -50,7 +51,7 @@ BooleanPrototype::BooleanPrototype(ExecState* exec, PassRefPtr<Structure> struct // ECMA 15.6.4.2 + 15.6.4.3 -JSValuePtr booleanProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { if (thisValue == jsBoolean(false)) return jsNontrivialString(exec, "false"); @@ -58,7 +59,7 @@ JSValuePtr booleanProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisV if (thisValue == jsBoolean(true)) return jsNontrivialString(exec, "true"); - if (!thisValue->isObject(&BooleanObject::info)) + if (!thisValue.isObject(&BooleanObject::info)) return throwError(exec, TypeError); if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false)) @@ -68,12 +69,12 @@ JSValuePtr booleanProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisV return jsNontrivialString(exec, "true"); } -JSValuePtr booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (JSImmediate::isBoolean(thisValue)) + if (thisValue.isBoolean()) return thisValue; - if (!thisValue->isObject(&BooleanObject::info)) + if (!thisValue.isObject(&BooleanObject::info)) return throwError(exec, TypeError); return asBooleanObject(thisValue)->internalValue(); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ByteArray.h b/src/3rdparty/webkit/JavaScriptCore/runtime/ByteArray.h deleted file mode 100644 index 7448942..0000000 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ByteArray.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 ByteArray_h -#define ByteArray_h - -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" - -namespace JSC { - class ByteArray : public RefCounted<ByteArray> { - public: - unsigned length() const { return m_size; } - - void set(unsigned index, double value) - { - if (index >= m_size) - return; - if (!(value > 0)) // Clamp NaN to 0 - value = 0; - else if (value > 255) - value = 255; - m_data[index] = static_cast<unsigned char>(value + 0.5); - } - - bool get(unsigned index, unsigned char& result) const - { - if (index >= m_size) - return false; - result = m_data[index]; - return true; - } - - unsigned char* data() { return m_data; } - - static PassRefPtr<ByteArray> create(size_t size); - - private: - ByteArray(size_t size) - : m_size(size) - { - } - size_t m_size; - unsigned char m_data[sizeof(size_t)]; - }; -} - -#endif diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp index fbb6392..62e42fe 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp @@ -30,7 +30,7 @@ namespace JSC { -JSValuePtr call(ExecState* exec, JSValuePtr functionObject, CallType callType, const CallData& callData, JSValuePtr thisValue, const ArgList& args) +JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args) { if (callType == CallTypeHost) return callData.native.function(exec, asObject(functionObject), thisValue, args); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.h b/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.h index b8d84cd..d5b0172 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.h @@ -29,13 +29,15 @@ #ifndef CallData_h #define CallData_h +#include "NativeFunctionWrapper.h" + namespace JSC { class ArgList; class ExecState; class FunctionBodyNode; class JSObject; - class JSValuePtr; + class JSValue; class ScopeChainNode; enum CallType { @@ -44,7 +46,7 @@ namespace JSC { CallTypeJS }; - typedef JSValuePtr (*NativeFunction)(ExecState*, JSObject*, JSValuePtr thisValue, const ArgList&); + typedef JSValue (JSC_HOST_CALL *NativeFunction)(ExecState*, JSObject*, JSValue thisValue, const ArgList&); union CallData { struct { @@ -56,7 +58,7 @@ namespace JSC { } js; }; - JSValuePtr call(ExecState*, JSValuePtr functionObject, CallType, const CallData&, JSValuePtr thisValue, const ArgList&); + JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&); } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.cpp index 69cb05e..1e5eab3 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.cpp @@ -23,13 +23,14 @@ #include "Collector.h" #include "ArgList.h" -#include "CollectorHeapIterator.h" #include "CallFrame.h" +#include "CollectorHeapIterator.h" +#include "Interpreter.h" #include "JSGlobalObject.h" #include "JSLock.h" #include "JSString.h" #include "JSValue.h" -#include "Interpreter.h" +#include "Nodes.h" #include "Tracing.h" #include <algorithm> #include <setjmp.h> @@ -37,11 +38,12 @@ #include <wtf/FastMalloc.h> #include <wtf/HashCountedSet.h> #include <wtf/UnusedParam.h> +#include <wtf/VMTags.h> #if PLATFORM(DARWIN) -#include <mach/mach_port.h> #include <mach/mach_init.h> +#include <mach/mach_port.h> #include <mach/task.h> #include <mach/thread_act.h> #include <mach/vm_map.h> @@ -74,9 +76,7 @@ extern int *__libc_stack_end; #if PLATFORM(SOLARIS) #include <thread.h> -#endif - -#if PLATFORM(OPENBSD) +#else #include <pthread.h> #endif @@ -199,7 +199,7 @@ static NEVER_INLINE CollectorBlock* allocateBlock() #if PLATFORM(DARWIN) vm_address_t address = 0; // FIXME: tag the region as a JavaScriptCore heap when we get a registered VM tag: <rdar://problem/6054788>. - vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT); + vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE | VM_TAG_FOR_COLLECTOR_MEMORY, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT); #elif PLATFORM(SYMBIAN) // no memory map in symbian, need to hack with fastMalloc void* address = fastMalloc(BLOCK_SIZE); @@ -365,6 +365,9 @@ collect: // didn't find a block, and GC didn't reclaim anything, need to allocate a new block size_t numBlocks = heap.numBlocks; if (usedBlocks == numBlocks) { + static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR; + if (numBlocks > maxNumBlocks) + CRASH(); numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR); heap.numBlocks = numBlocks; heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*))); @@ -483,6 +486,15 @@ static inline void* currentThreadStackBase() stack_t stack; pthread_stackseg_np(thread, &stack); return stack.ss_sp; +#elif PLATFORM(SYMBIAN) + static void* stackBase = 0; + if (stackBase == 0) { + TThreadStackInfo info; + RThread thread; + thread.StackInfo(info); + stackBase = (void*)info.iBase; + } + return (void*)stackBase; #elif PLATFORM(UNIX) #ifdef UCLIBC_USE_PROC_SELF_MAPS // Read /proc/self/maps and locate the line whose address @@ -548,15 +560,6 @@ static inline void* currentThreadStackBase() } return static_cast<char*>(stackBase) + stackSize; #endif -#elif PLATFORM(SYMBIAN) - static void* stackBase = 0; - if (stackBase == 0) { - TThreadStackInfo info; - RThread thread; - thread.StackInfo(info); - stackBase = (void*)info.iBase; - } - return (void*)stackBase; #else #error Need a way to get the stack base on this platform #endif @@ -768,7 +771,7 @@ typedef CONTEXT PlatformThreadRegisters; #error Need a thread register struct for this platform #endif -size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs) +static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs) { #if PLATFORM(DARWIN) @@ -906,45 +909,45 @@ void Heap::setGCProtectNeedsLocking() m_protectedValuesMutex.set(new Mutex); } -void Heap::protect(JSValuePtr k) +void Heap::protect(JSValue k) { ASSERT(k); ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance); - if (JSImmediate::isImmediate(k)) + if (!k.isCell()) return; if (m_protectedValuesMutex) m_protectedValuesMutex->lock(); - m_protectedValues.add(k->asCell()); + m_protectedValues.add(k.asCell()); if (m_protectedValuesMutex) m_protectedValuesMutex->unlock(); } -void Heap::unprotect(JSValuePtr k) +void Heap::unprotect(JSValue k) { ASSERT(k); ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance); - if (JSImmediate::isImmediate(k)) + if (!k.isCell()) return; if (m_protectedValuesMutex) m_protectedValuesMutex->lock(); - m_protectedValues.remove(k->asCell()); + m_protectedValues.remove(k.asCell()); if (m_protectedValuesMutex) m_protectedValuesMutex->unlock(); } -Heap* Heap::heap(JSValuePtr v) +Heap* Heap::heap(JSValue v) { - if (JSImmediate::isImmediate(v)) + if (!v.isCell()) return 0; - return Heap::cellBlock(v->asCell())->heap; + return Heap::cellBlock(v.asCell())->heap; } void Heap::markProtectedObjects() @@ -1084,11 +1087,13 @@ bool Heap::collect() markStackObjectsConservatively(); markProtectedObjects(); if (m_markListSet && m_markListSet->size()) - ArgList::markLists(*m_markListSet); - if (m_globalData->exception && !m_globalData->exception->marked()) - m_globalData->exception->mark(); + MarkedArgumentBuffer::markLists(*m_markListSet); + if (m_globalData->exception && !m_globalData->exception.marked()) + m_globalData->exception.mark(); m_globalData->interpreter->registerFile().markCallFrames(this); m_globalData->smallStrings.mark(); + if (m_globalData->scopeNodeBeingReparsed) + m_globalData->scopeNodeBeingReparsed->mark(); JAVASCRIPTCORE_GC_MARKED(); @@ -1105,7 +1110,7 @@ bool Heap::collect() size_t Heap::objectCount() { - return primaryHeap.numLiveObjects + numberHeap.numLiveObjects; + return primaryHeap.numLiveObjects + numberHeap.numLiveObjects - m_globalData->smallStrings.count(); } template <HeapType heapType> @@ -1175,16 +1180,16 @@ size_t Heap::protectedObjectCount() return result; } -static const char* typeName(JSCell* val) +static const char* typeName(JSCell* cell) { - if (val->isString()) + if (cell->isString()) return "string"; - if (val->isNumber()) + if (cell->isNumber()) return "number"; - if (val->isGetterSetter()) + if (cell->isGetterSetter()) return "gettersetter"; - ASSERT(val->isObject()); - const ClassInfo* info = static_cast<JSObject*>(val)->classInfo(); + ASSERT(cell->isObject()); + const ClassInfo* info = static_cast<JSObject*>(cell)->classInfo(); return info ? info->className : "Object"; } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.h index ba41d60..23f9f15 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.h @@ -39,11 +39,11 @@ namespace JSC { - class ArgList; + class MarkedArgumentBuffer; class CollectorBlock; class JSCell; class JSGlobalData; - class JSValuePtr; + class JSValue; enum OperationInProgress { NoOperation, Allocation, Collection }; enum HeapType { PrimaryHeap, NumberHeap }; @@ -96,10 +96,10 @@ namespace JSC { Statistics statistics() const; void setGCProtectNeedsLocking(); - void protect(JSValuePtr); - void unprotect(JSValuePtr); + void protect(JSValue); + void unprotect(JSValue); - static Heap* heap(JSValuePtr); // 0 for immediate values + static Heap* heap(JSValue); // 0 for immediate values size_t globalObjectCount(); size_t protectedObjectCount(); @@ -113,7 +113,7 @@ namespace JSC { void markConservatively(void* start, void* end); - HashSet<ArgList*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<ArgList*>; return *m_markListSet; } + HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; } JSGlobalData* globalData() const { return m_globalData; } static bool isNumber(JSCell*); @@ -147,7 +147,7 @@ namespace JSC { OwnPtr<Mutex> m_protectedValuesMutex; // Only non-null if the client explicitly requested it via setGCPrtotectNeedsLocking(). ProtectCountSet m_protectedValues; - HashSet<ArgList*>* m_markListSet; + HashSet<MarkedArgumentBuffer*>* m_markListSet; #if ENABLE(JSC_MULTIPLE_THREADS) void makeUsableFromMultipleThreads(); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/CommonIdentifiers.h b/src/3rdparty/webkit/JavaScriptCore/runtime/CommonIdentifiers.h index 45b99a8..d4c5d52 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/CommonIdentifiers.h @@ -24,7 +24,7 @@ #include "Identifier.h" #include <wtf/Noncopyable.h> -// ArgList of property names, passed to a macro so we can do set them up various +// MarkedArgumentBuffer of property names, passed to a macro so we can do set them up various // ways without repeating the list. #define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \ macro(__defineGetter__) \ @@ -63,7 +63,8 @@ macro(toPrecision) \ macro(toString) \ macro(UTC) \ - macro(valueOf) + macro(valueOf) \ + macro(displayName) namespace JSC { diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp index b4923f7..b8b1581 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp @@ -50,7 +50,7 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source) return Completion(Normal); } -Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValuePtr thisValue) +Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue) { JSLock lock(exec); @@ -61,14 +61,14 @@ Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& s if (!programNode) return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url())); - JSObject* thisObj = (!thisValue || thisValue->isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue->toObject(exec); + JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); - JSValuePtr exception = noValue(); - JSValuePtr result = exec->interpreter()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception); + JSValue exception; + JSValue result = exec->interpreter()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception); if (exception) { - if (exception->isObject() && asObject(exception)->isWatchdogException()) - return Completion(Interrupted, result); + if (exception.isObject() && asObject(exception)->isWatchdogException()) + return Completion(Interrupted, exception); return Completion(Throw, exception); } return Completion(Normal, result); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.h index 9631b50..41c9a64 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.h @@ -39,24 +39,24 @@ namespace JSC { */ class Completion { public: - Completion(ComplType type = Normal, JSValuePtr value = noValue()) + Completion(ComplType type = Normal, JSValue value = JSValue()) : m_type(type) , m_value(value) { } ComplType complType() const { return m_type; } - JSValuePtr value() const { return m_value; } - void setValue(JSValuePtr v) { m_value = v; } + JSValue value() const { return m_value; } + void setValue(JSValue v) { m_value = v; } bool isValueCompletion() const { return m_value; } private: ComplType m_type; - JSValuePtr m_value; + JSValue m_value; }; Completion checkSyntax(ExecState*, const SourceCode&); - Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValuePtr thisValue = noValue()); + Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValue thisValue = JSValue()); } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.cpp index 7a729ae..7ee59d7 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.cpp @@ -30,7 +30,7 @@ namespace JSC { -JSObject* construct(ExecState* exec, JSValuePtr object, ConstructType constructType, const ConstructData& constructData, const ArgList& args) +JSObject* construct(ExecState* exec, JSValue object, ConstructType constructType, const ConstructData& constructData, const ArgList& args) { if (constructType == ConstructTypeHost) return constructData.native.function(exec, asObject(object), args); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.h b/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.h index 559c1bd..9d580d5 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.h @@ -35,7 +35,7 @@ namespace JSC { class ExecState; class FunctionBodyNode; class JSObject; - class JSValuePtr; + class JSValue; class ScopeChainNode; enum ConstructType { @@ -56,7 +56,7 @@ namespace JSC { } js; }; - JSObject* construct(ExecState*, JSValuePtr constructor, ConstructType, const ConstructData&, const ArgList&); + JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&); } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/DateConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/DateConstructor.cpp index 6510f4b..54362d0 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/DateConstructor.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/DateConstructor.cpp @@ -25,6 +25,7 @@ #include "DateInstance.h" #include "DateMath.h" #include "DatePrototype.h" +#include "JSFunction.h" #include "JSGlobalObject.h" #include "JSString.h" #include "ObjectPrototype.h" @@ -47,18 +48,18 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(DateConstructor); -static JSValuePtr dateParse(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateNow(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateUTC(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL dateParse(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateNow(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateUTC(ExecState*, JSObject*, JSValue, const ArgList&); DateConstructor::DateConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, datePrototype->classInfo()->className)) { putDirectWithoutTransition(exec->propertyNames().prototype, datePrototype, DontEnum|DontDelete|ReadOnly); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().parse, dateParse), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 7, exec->propertyNames().UTC, dateUTC), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().now, dateNow), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().parse, dateParse), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 7, exec->propertyNames().UTC, dateUTC), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().now, dateNow), DontEnum); putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 7), ReadOnly | DontEnum | DontDelete); } @@ -73,35 +74,35 @@ JSObject* constructDate(ExecState* exec, const ArgList& args) if (numArgs == 0) // new Date() ECMA 15.9.3.3 value = getCurrentUTCTime(); else if (numArgs == 1) { - if (args.at(exec, 0)->isObject(&DateInstance::info)) - value = asDateInstance(args.at(exec, 0))->internalNumber(); + if (args.at(0).isObject(&DateInstance::info)) + value = asDateInstance(args.at(0))->internalNumber(); else { - JSValuePtr primitive = args.at(exec, 0)->toPrimitive(exec); - if (primitive->isString()) - value = parseDate(primitive->getString()); + JSValue primitive = args.at(0).toPrimitive(exec); + if (primitive.isString()) + value = parseDate(primitive.getString()); else - value = primitive->toNumber(exec); + value = primitive.toNumber(exec); } } else { - if (isnan(args.at(exec, 0)->toNumber(exec)) - || isnan(args.at(exec, 1)->toNumber(exec)) - || (numArgs >= 3 && isnan(args.at(exec, 2)->toNumber(exec))) - || (numArgs >= 4 && isnan(args.at(exec, 3)->toNumber(exec))) - || (numArgs >= 5 && isnan(args.at(exec, 4)->toNumber(exec))) - || (numArgs >= 6 && isnan(args.at(exec, 5)->toNumber(exec))) - || (numArgs >= 7 && isnan(args.at(exec, 6)->toNumber(exec)))) + if (isnan(args.at(0).toNumber(exec)) + || isnan(args.at(1).toNumber(exec)) + || (numArgs >= 3 && isnan(args.at(2).toNumber(exec))) + || (numArgs >= 4 && isnan(args.at(3).toNumber(exec))) + || (numArgs >= 5 && isnan(args.at(4).toNumber(exec))) + || (numArgs >= 6 && isnan(args.at(5).toNumber(exec))) + || (numArgs >= 7 && isnan(args.at(6).toNumber(exec)))) value = NaN; else { GregorianDateTime t; - int year = args.at(exec, 0)->toInt32(exec); + int year = args.at(0).toInt32(exec); t.year = (year >= 0 && year <= 99) ? year : year - 1900; - t.month = args.at(exec, 1)->toInt32(exec); - t.monthDay = (numArgs >= 3) ? args.at(exec, 2)->toInt32(exec) : 1; - t.hour = args.at(exec, 3)->toInt32(exec); - t.minute = args.at(exec, 4)->toInt32(exec); - t.second = args.at(exec, 5)->toInt32(exec); + t.month = args.at(1).toInt32(exec); + t.monthDay = (numArgs >= 3) ? args.at(2).toInt32(exec) : 1; + t.hour = args.at(3).toInt32(exec); + t.minute = args.at(4).toInt32(exec); + t.second = args.at(5).toInt32(exec); t.isDST = -1; - double ms = (numArgs >= 7) ? args.at(exec, 6)->toNumber(exec) : 0; + double ms = (numArgs >= 7) ? args.at(6).toNumber(exec) : 0; value = gregorianDateTimeToMS(t, ms, false); } } @@ -123,7 +124,7 @@ ConstructType DateConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.9.2 -static JSValuePtr callDate(ExecState* exec, JSObject*, JSValuePtr, const ArgList&) +static JSValue JSC_HOST_CALL callDate(ExecState* exec, JSObject*, JSValue, const ArgList&) { time_t localTime = time(0); tm localTM; @@ -138,37 +139,37 @@ CallType DateConstructor::getCallData(CallData& callData) return CallTypeHost; } -static JSValuePtr dateParse(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL dateParse(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, parseDate(args.at(exec, 0)->toString(exec))); + return jsNumber(exec, parseDate(args.at(0).toString(exec))); } -static JSValuePtr dateNow(ExecState* exec, JSObject*, JSValuePtr, const ArgList&) +static JSValue JSC_HOST_CALL dateNow(ExecState* exec, JSObject*, JSValue, const ArgList&) { return jsNumber(exec, getCurrentUTCTime()); } -static JSValuePtr dateUTC(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL dateUTC(ExecState* exec, JSObject*, JSValue, const ArgList& args) { int n = args.size(); - if (isnan(args.at(exec, 0)->toNumber(exec)) - || isnan(args.at(exec, 1)->toNumber(exec)) - || (n >= 3 && isnan(args.at(exec, 2)->toNumber(exec))) - || (n >= 4 && isnan(args.at(exec, 3)->toNumber(exec))) - || (n >= 5 && isnan(args.at(exec, 4)->toNumber(exec))) - || (n >= 6 && isnan(args.at(exec, 5)->toNumber(exec))) - || (n >= 7 && isnan(args.at(exec, 6)->toNumber(exec)))) + if (isnan(args.at(0).toNumber(exec)) + || isnan(args.at(1).toNumber(exec)) + || (n >= 3 && isnan(args.at(2).toNumber(exec))) + || (n >= 4 && isnan(args.at(3).toNumber(exec))) + || (n >= 5 && isnan(args.at(4).toNumber(exec))) + || (n >= 6 && isnan(args.at(5).toNumber(exec))) + || (n >= 7 && isnan(args.at(6).toNumber(exec)))) return jsNaN(exec); GregorianDateTime t; - int year = args.at(exec, 0)->toInt32(exec); + int year = args.at(0).toInt32(exec); t.year = (year >= 0 && year <= 99) ? year : year - 1900; - t.month = args.at(exec, 1)->toInt32(exec); - t.monthDay = (n >= 3) ? args.at(exec, 2)->toInt32(exec) : 1; - t.hour = args.at(exec, 3)->toInt32(exec); - t.minute = args.at(exec, 4)->toInt32(exec); - t.second = args.at(exec, 5)->toInt32(exec); - double ms = (n >= 7) ? args.at(exec, 6)->toNumber(exec) : 0; + t.month = args.at(1).toInt32(exec); + t.monthDay = (n >= 3) ? args.at(2).toInt32(exec) : 1; + t.hour = args.at(3).toInt32(exec); + t.minute = args.at(4).toInt32(exec); + t.second = args.at(5).toInt32(exec); + double ms = (n >= 7) ? args.at(6).toNumber(exec) : 0; return jsNumber(exec, gregorianDateTimeToMS(t, ms, true)); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/DateInstance.h b/src/3rdparty/webkit/JavaScriptCore/runtime/DateInstance.h index 8dbca81..0ecd1db 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/DateInstance.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/DateInstance.h @@ -32,7 +32,7 @@ namespace JSC { explicit DateInstance(PassRefPtr<Structure>); virtual ~DateInstance(); - double internalNumber() const { return internalValue()->uncheckedGetNumber(); } + double internalNumber() const { return internalValue().uncheckedGetNumber(); } bool getTime(GregorianDateTime&, int& offset) const; bool getUTCTime(GregorianDateTime&) const; @@ -52,9 +52,9 @@ namespace JSC { mutable Cache* m_cache; }; - DateInstance* asDateInstance(JSValuePtr); + DateInstance* asDateInstance(JSValue); - inline DateInstance* asDateInstance(JSValuePtr value) + inline DateInstance* asDateInstance(JSValue value) { ASSERT(asObject(value)->inherits(&DateInstance::info)); return static_cast<DateInstance*>(asObject(value)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/DateMath.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/DateMath.cpp index 9cfe256..2f8c88c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/DateMath.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/DateMath.cpp @@ -48,6 +48,7 @@ #include <time.h> #include <wtf/ASCIICType.h> #include <wtf/Assertions.h> +#include <wtf/CurrentTime.h> #include <wtf/MathExtras.h> #include <wtf/StringExtras.h> @@ -67,10 +68,6 @@ #include <sys/timeb.h> #endif -#if HAVE(STRINGS_H) -#include <strings.h> -#endif - using namespace WTF; namespace JSC { @@ -291,139 +288,10 @@ double getCurrentUTCTime() return floor(getCurrentUTCTimeWithMicroseconds()); } -#if PLATFORM(WIN_OS) - -static LARGE_INTEGER qpcFrequency; -static bool syncedTime; - -static double highResUpTime() -{ - // We use QPC, but only after sanity checking its result, due to bugs: - // http://support.microsoft.com/kb/274323 - // http://support.microsoft.com/kb/895980 - // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("...you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL)." - - static LARGE_INTEGER qpcLast; - static DWORD tickCountLast; - static bool inited; - - LARGE_INTEGER qpc; - QueryPerformanceCounter(&qpc); - DWORD tickCount = GetTickCount(); - - if (inited) { - __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFrequency.QuadPart; - __int64 tickCountElapsed; - if (tickCount >= tickCountLast) - tickCountElapsed = (tickCount - tickCountLast); - else { -#if COMPILER(MINGW) - __int64 tickCountLarge = tickCount + 0x100000000ULL; -#else - __int64 tickCountLarge = tickCount + 0x100000000I64; -#endif - tickCountElapsed = tickCountLarge - tickCountLast; - } - - // force a re-sync if QueryPerformanceCounter differs from GetTickCount by more than 500ms. - // (500ms value is from http://support.microsoft.com/kb/274323) - __int64 diff = tickCountElapsed - qpcElapsed; - if (diff > 500 || diff < -500) - syncedTime = false; - } else - inited = true; - - qpcLast = qpc; - tickCountLast = tickCount; - - return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart);; -} - -static double lowResUTCTime() -{ -#if PLATFORM(WIN_CE) - SYSTEMTIME systemTime; - GetSystemTime(&systemTime); - struct tm tmtime; - tmtime.tm_year = systemTime.wYear - 1900; - tmtime.tm_mon = systemTime.wMonth - 1; - tmtime.tm_mday = systemTime.wDay; - tmtime.tm_wday = systemTime.wDayOfWeek; - tmtime.tm_hour = systemTime.wHour; - tmtime.tm_min = systemTime.wMinute; - tmtime.tm_sec = systemTime.wSecond; - time_t timet = mktime(&tmtime); - return timet * msPerSecond + systemTime.wMilliseconds; -#else - struct _timeb timebuffer; - _ftime(&timebuffer); - return timebuffer.time * msPerSecond + timebuffer.millitm; -#endif -} - -static bool qpcAvailable() -{ - static bool available; - static bool checked; - - if (checked) - return available; - - available = QueryPerformanceFrequency(&qpcFrequency); - checked = true; - return available; -} - -#endif - +// Returns current time in milliseconds since 1 Jan 1970. double getCurrentUTCTimeWithMicroseconds() { -#if PLATFORM(WIN_OS) - // Use a combination of ftime and QueryPerformanceCounter. - // ftime returns the information we want, but doesn't have sufficient resolution. - // QueryPerformanceCounter has high resolution, but is only usable to measure time intervals. - // To combine them, we call ftime and QueryPerformanceCounter initially. Later calls will use QueryPerformanceCounter - // by itself, adding the delta to the saved ftime. We periodically re-sync to correct for drift. - static bool started; - static double syncLowResUTCTime; - static double syncHighResUpTime; - static double lastUTCTime; - - double lowResTime = lowResUTCTime(); - - if (!qpcAvailable()) - return lowResTime; - - double highResTime = highResUpTime(); - - if (!syncedTime) { - timeBeginPeriod(1); // increase time resolution around low-res time getter - syncLowResUTCTime = lowResTime = lowResUTCTime(); - timeEndPeriod(1); // restore time resolution - syncHighResUpTime = highResTime; - syncedTime = true; - } - - double highResElapsed = highResTime - syncHighResUpTime; - double utc = syncLowResUTCTime + highResElapsed; - - // force a clock re-sync if we've drifted - double lowResElapsed = lowResTime - syncLowResUTCTime; - const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-res accuracy - if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec) - syncedTime = false; - - // make sure time doesn't run backwards (only correct if difference is < 2 seconds, since DST or clock changes could occur) - const double backwardTimeLimit = 2000.0; - if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit) - return lastUTCTime; - lastUTCTime = utc; -#else - struct timeval tv; - gettimeofday(&tv, 0); - double utc = tv.tv_sec * msPerSecond + tv.tv_usec / 1000.0; -#endif - return utc; + return currentTime() * 1000.0; } void getLocalTime(const time_t* localTime, struct tm* localTM) @@ -1047,14 +915,14 @@ UString formatTime(const GregorianDateTime &t, bool utc) snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", t.hour, t.minute, t.second); } else { int offset = abs(gmtoffset(t)); - char tzname[70]; + char timeZoneName[70]; struct tm gtm = t; - strftime(tzname, sizeof(tzname), "%Z", >m); + strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m); - if (tzname[0]) { + if (timeZoneName[0]) { snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d (%s)", t.hour, t.minute, t.second, - gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, tzname); + gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, timeZoneName); } else { snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d", t.hour, t.minute, t.second, diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/DatePrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/DatePrototype.cpp index 79ab2a2..ff3fb19 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/DatePrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/DatePrototype.cpp @@ -23,10 +23,16 @@ #include "DatePrototype.h" #include "DateMath.h" +#include "Error.h" #include "JSString.h" #include "ObjectPrototype.h" #include "DateInstance.h" #include <float.h> + +#if !PLATFORM(MAC) && HAVE(LANGINFO_H) +#include <langinfo.h> +#endif + #include <limits.h> #include <locale.h> #include <math.h> @@ -58,50 +64,49 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(DatePrototype); -static JSValuePtr dateProtoFuncGetDate(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetDay(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetHours(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetTime(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncGetYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetDate(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetHours(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetTime(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncSetYear(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncToDateString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncToGMTString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncToTimeString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncToUTCString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr dateProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState*, JSObject*, JSValue, const ArgList&); } @@ -109,8 +114,13 @@ static JSValuePtr dateProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const namespace JSC { +enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime }; + #if PLATFORM(MAC) +// FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)? +// Instead we should consider using this whenever PLATFORM(CF) is true. + static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle) { if (string == "short") @@ -124,24 +134,24 @@ static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateForm return defaultStyle; } -static UString formatLocaleDate(ExecState* exec, double time, bool includeDate, bool includeTime, const ArgList& args) +static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList& args) { - CFDateFormatterStyle dateStyle = (includeDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle); - CFDateFormatterStyle timeStyle = (includeTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle); + CFDateFormatterStyle dateStyle = (format != LocaleTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle); + CFDateFormatterStyle timeStyle = (format != LocaleDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle); bool useCustomFormat = false; UString customFormatString; - UString arg0String = args.at(exec, 0)->toString(exec); - if (arg0String == "custom" && !args.at(exec, 1)->isUndefined()) { + UString arg0String = args.at(0).toString(exec); + if (arg0String == "custom" && !args.at(1).isUndefined()) { useCustomFormat = true; - customFormatString = args.at(exec, 1)->toString(exec); - } else if (includeDate && includeTime && !args.at(exec, 1)->isUndefined()) { + customFormatString = args.at(1).toString(exec); + } else if (format == LocaleDateAndTime && !args.at(1).isUndefined()) { dateStyle = styleFromArgString(arg0String, dateStyle); - timeStyle = styleFromArgString(args.at(exec, 1)->toString(exec), timeStyle); - } else if (includeDate && !args.at(exec, 0)->isUndefined()) + timeStyle = styleFromArgString(args.at(1).toString(exec), timeStyle); + } else if (format != LocaleTime && !args.at(0).isUndefined()) dateStyle = styleFromArgString(arg0String, dateStyle); - else if (includeTime && !args.at(exec, 0)->isUndefined()) + else if (format != LocaleDate && !args.at(0).isUndefined()) timeStyle = styleFromArgString(arg0String, timeStyle); CFLocaleRef locale = CFLocaleCopyCurrent(); @@ -149,12 +159,12 @@ static UString formatLocaleDate(ExecState* exec, double time, bool includeDate, CFRelease(locale); if (useCustomFormat) { - CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, (UniChar *)customFormatString.data(), customFormatString.size()); + CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, customFormatString.data(), customFormatString.size()); CFDateFormatterSetFormat(formatter, customFormatCFString); CFRelease(customFormatCFString); } - CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, time - kCFAbsoluteTimeIntervalSince1970); + CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, floor(timeInMilliseconds / msPerSecond) - kCFAbsoluteTimeIntervalSince1970); CFRelease(formatter); @@ -166,20 +176,22 @@ static UString formatLocaleDate(ExecState* exec, double time, bool includeDate, ASSERT(length <= bufferLength); if (length > bufferLength) length = bufferLength; - CFStringGetCharacters(string, CFRangeMake(0, length), reinterpret_cast<UniChar *>(buffer)); + CFStringGetCharacters(string, CFRangeMake(0, length), buffer); CFRelease(string); - return UString(buffer, length); + return jsNontrivialString(exec, UString(buffer, length)); } -#else +#else // !PLATFORM(MAC) -enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime }; - -static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, const LocaleDateTimeFormat format) +static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format) { - static const char* formatStrings[] = {"%#c", "%#x", "%X"}; +#if HAVE(LANGINFO_H) + static const nl_item formats[] = { D_T_FMT, D_FMT, T_FMT }; +#else + static const char* const formatStrings[] = { "%#c", "%#x", "%X" }; +#endif // Offset year if needed struct tm localTM = gdt; @@ -188,10 +200,26 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, c if (yearNeedsOffset) localTM.tm_year = equivalentYearForDST(year) - 1900; +#if HAVE(LANGINFO_H) + // We do not allow strftime to generate dates with 2-digits years, + // both to avoid ambiguity, and a crash in strncpy, for years that + // need offset. + char* formatString = strdup(nl_langinfo(formats[format])); + char* yPos = strchr(formatString, 'y'); + if (yPos) + *yPos = 'Y'; +#endif + // Do the formatting const int bufsize = 128; char timebuffer[bufsize]; + +#if HAVE(LANGINFO_H) + size_t ret = strftime(timebuffer, bufsize, formatString, &localTM); + free(formatString); +#else size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM); +#endif if (ret == 0) return jsEmptyString(exec); @@ -211,7 +239,15 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, c return jsNontrivialString(exec, timebuffer); } -#endif // PLATFORM(WIN_OS) +static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList&) +{ + GregorianDateTime gregorianDateTime; + const bool notUTC = false; + dateObject->msToGregorianDateTime(timeInMilliseconds, notUTC, gregorianDateTime); + return formatLocaleDate(exec, gregorianDateTime, format); +} + +#endif // !PLATFORM(MAC) // Converts a list of arguments sent to a Date member function into milliseconds, updating // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately. @@ -231,19 +267,19 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, in // hours if (maxArgs >= 4 && idx < numArgs) { t->hour = 0; - milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerHour; + milliseconds += args.at(idx++).toInt32(exec, ok) * msPerHour; } // minutes if (maxArgs >= 3 && idx < numArgs && ok) { t->minute = 0; - milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerMinute; + milliseconds += args.at(idx++).toInt32(exec, ok) * msPerMinute; } // seconds if (maxArgs >= 2 && idx < numArgs && ok) { t->second = 0; - milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerSecond; + milliseconds += args.at(idx++).toInt32(exec, ok) * msPerSecond; } if (!ok) @@ -251,7 +287,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, in // milliseconds if (idx < numArgs) { - double millis = args.at(exec, idx)->toNumber(exec); + double millis = args.at(idx).toNumber(exec); ok = isfinite(millis); milliseconds += millis; } else @@ -277,16 +313,16 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, const ArgList& args, in // years if (maxArgs >= 3 && idx < numArgs) - t->year = args.at(exec, idx++)->toInt32(exec, ok) - 1900; + t->year = args.at(idx++).toInt32(exec, ok) - 1900; // months if (maxArgs >= 2 && idx < numArgs && ok) - t->month = args.at(exec, idx++)->toInt32(exec, ok); + t->month = args.at(idx++).toInt32(exec, ok); // days if (idx < numArgs && ok) { t->monthDay = 0; - *ms += args.at(exec, idx)->toInt32(exec, ok) * msPerDay; + *ms += args.at(idx).toInt32(exec, ok) * msPerDay; } return ok; @@ -295,7 +331,6 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, const ArgList& args, in const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState::dateTable}; /* Source for DatePrototype.lut.h - FIXME: We could use templates to simplify the UTC variants. @begin dateTable toString dateProtoFuncToString DontEnum|Function 0 toUTCString dateProtoFuncToUTCString DontEnum|Function 0 @@ -304,7 +339,7 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0 toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0 toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0 - valueOf dateProtoFuncValueOf DontEnum|Function 0 + valueOf dateProtoFuncGetTime DontEnum|Function 0 getTime dateProtoFuncGetTime DontEnum|Function 0 getFullYear dateProtoFuncGetFullYear DontEnum|Function 0 getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0 @@ -343,6 +378,7 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState getYear dateProtoFuncGetYear DontEnum|Function 0 @end */ + // ECMA 15.9.4 DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<Structure> structure) @@ -359,9 +395,9 @@ bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& proper // Functions -JSValuePtr dateProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -376,9 +412,9 @@ JSValuePtr dateProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValu return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc)); } -JSValuePtr dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -393,9 +429,9 @@ JSValuePtr dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValuePtr thisV return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc)); } -JSValuePtr dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -410,9 +446,9 @@ JSValuePtr dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValuePtr this return jsNontrivialString(exec, formatDate(t)); } -JSValuePtr dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -427,9 +463,9 @@ JSValuePtr dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValuePtr this return jsNontrivialString(exec, formatTime(t, utc)); } -JSValuePtr dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -437,23 +473,12 @@ JSValuePtr dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr th if (isnan(milli)) return jsNontrivialString(exec, "Invalid Date"); -#if PLATFORM(MAC) - double secs = floor(milli / msPerSecond); - return jsNontrivialString(exec, formatLocaleDate(exec, secs, true, true, args)); -#else - UNUSED_PARAM(args); - - const bool utc = false; - - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return formatLocaleDate(exec, t, LocaleDateAndTime); -#endif + return formatLocaleDate(exec, thisDateObj, milli, LocaleDateAndTime, args); } -JSValuePtr dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -461,23 +486,12 @@ JSValuePtr dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValuePt if (isnan(milli)) return jsNontrivialString(exec, "Invalid Date"); -#if PLATFORM(MAC) - double secs = floor(milli / msPerSecond); - return jsNontrivialString(exec, formatLocaleDate(exec, secs, true, false, args)); -#else - UNUSED_PARAM(args); - - const bool utc = false; - - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return formatLocaleDate(exec, t, LocaleDate); -#endif + return formatLocaleDate(exec, thisDateObj, milli, LocaleDate, args); } -JSValuePtr dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -485,36 +499,12 @@ JSValuePtr dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValuePt if (isnan(milli)) return jsNontrivialString(exec, "Invalid Date"); -#if PLATFORM(MAC) - double secs = floor(milli / msPerSecond); - return jsNontrivialString(exec, formatLocaleDate(exec, secs, false, true, args)); -#else - UNUSED_PARAM(args); - - const bool utc = false; - - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return formatLocaleDate(exec, t, LocaleTime); -#endif -} - -JSValuePtr dateProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) -{ - if (!thisValue->isObject(&DateInstance::info)) - return throwError(exec, TypeError); - - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - - return jsNumber(exec, milli); + return formatLocaleDate(exec, thisDateObj, milli, LocaleTime, args); } -JSValuePtr dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -525,9 +515,9 @@ JSValuePtr dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValuePtr thisValue return jsNumber(exec, milli); } -JSValuePtr dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -542,9 +532,9 @@ JSValuePtr dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValuePtr thisV return jsNumber(exec, 1900 + t.year); } -JSValuePtr dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -559,9 +549,9 @@ JSValuePtr dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValuePtr th return jsNumber(exec, 1900 + t.year); } -JSValuePtr dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -576,9 +566,9 @@ JSValuePtr dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValuePtr thisV return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc)); } -JSValuePtr dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -593,9 +583,9 @@ JSValuePtr dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValuePtr thisValu return jsNumber(exec, t.month); } -JSValuePtr dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -610,9 +600,9 @@ JSValuePtr dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValuePtr thisV return jsNumber(exec, t.month); } -JSValuePtr dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -627,9 +617,9 @@ JSValuePtr dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValuePtr thisValue return jsNumber(exec, t.monthDay); } -JSValuePtr dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -644,9 +634,9 @@ JSValuePtr dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValuePtr thisVa return jsNumber(exec, t.monthDay); } -JSValuePtr dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -661,9 +651,9 @@ JSValuePtr dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValuePtr thisValue, return jsNumber(exec, t.weekDay); } -JSValuePtr dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -678,9 +668,9 @@ JSValuePtr dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValuePtr thisVal return jsNumber(exec, t.weekDay); } -JSValuePtr dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -695,9 +685,9 @@ JSValuePtr dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValuePtr thisValu return jsNumber(exec, t.hour); } -JSValuePtr dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -712,9 +702,9 @@ JSValuePtr dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValuePtr thisV return jsNumber(exec, t.hour); } -JSValuePtr dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -729,9 +719,9 @@ JSValuePtr dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValuePtr thisVa return jsNumber(exec, t.minute); } -JSValuePtr dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -746,9 +736,9 @@ JSValuePtr dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValuePtr thi return jsNumber(exec, t.minute); } -JSValuePtr dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -763,9 +753,9 @@ JSValuePtr dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValuePtr thisVa return jsNumber(exec, t.second); } -JSValuePtr dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -780,9 +770,9 @@ JSValuePtr dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValuePtr thi return jsNumber(exec, t.second); } -JSValuePtr dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -795,9 +785,9 @@ JSValuePtr dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr t return jsNumber(exec, ms); } -JSValuePtr dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -810,9 +800,9 @@ JSValuePtr dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValuePt return jsNumber(exec, ms); } -JSValuePtr dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -827,29 +817,29 @@ JSValuePtr dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValuePtr return jsNumber(exec, -gmtoffset(t) / minutesPerHour); } -JSValuePtr dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = timeClip(args.at(exec, 0)->toNumber(exec)); - JSValuePtr result = jsNumber(exec, milli); + double milli = timeClip(args.at(0).toNumber(exec)); + JSValue result = jsNumber(exec, milli); thisDateObj->setInternalValue(result); return result; } -static JSValuePtr setNewValueFromTimeArgs(ExecState* exec, JSValuePtr thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC) +static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); double milli = thisDateObj->internalNumber(); if (args.isEmpty() || isnan(milli)) { - JSValuePtr result = jsNaN(exec); + JSValue result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } @@ -861,24 +851,24 @@ static JSValuePtr setNewValueFromTimeArgs(ExecState* exec, JSValuePtr thisValue, thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t); if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) { - JSValuePtr result = jsNaN(exec); + JSValue result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } - JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC)); + JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC)); thisDateObj->setInternalValue(result); return result; } -static JSValuePtr setNewValueFromDateArgs(ExecState* exec, JSValuePtr thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC) +static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); if (args.isEmpty()) { - JSValuePtr result = jsNaN(exec); + JSValue result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } @@ -898,110 +888,110 @@ static JSValuePtr setNewValueFromDateArgs(ExecState* exec, JSValuePtr thisValue, } if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) { - JSValuePtr result = jsNaN(exec); + JSValue result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } - JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC)); + JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC)); thisDateObj->setInternalValue(result); return result; } -JSValuePtr dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC); } -JSValuePtr dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC); } -JSValuePtr dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC); } -JSValuePtr dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC); } -JSValuePtr dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC); } -JSValuePtr dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC); } -JSValuePtr dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC); } -JSValuePtr dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC); } -JSValuePtr dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC); } -JSValuePtr dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC); } -JSValuePtr dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC); } -JSValuePtr dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC); } -JSValuePtr dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = false; return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC); } -JSValuePtr dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { const bool inputIsUTC = true; return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC); } -JSValuePtr dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; DateInstance* thisDateObj = asDateInstance(thisValue); if (args.isEmpty()) { - JSValuePtr result = jsNaN(exec); + JSValue result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } @@ -1021,22 +1011,22 @@ JSValuePtr dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValuePtr thisValue } bool ok = true; - int32_t year = args.at(exec, 0)->toInt32(exec, ok); + int32_t year = args.at(0).toInt32(exec, ok); if (!ok) { - JSValuePtr result = jsNaN(exec); + JSValue result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } t.year = (year > 99 || year < 0) ? year - 1900 : year; - JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc)); + JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc)); thisDateObj->setInternalValue(result); return result; } -JSValuePtr dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&DateInstance::info)) + if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/DatePrototype.h b/src/3rdparty/webkit/JavaScriptCore/runtime/DatePrototype.h index a6bbdf2..5f4d0ec 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/DatePrototype.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/DatePrototype.h @@ -36,7 +36,7 @@ namespace JSC { virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType)); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Error.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Error.cpp index 5e21c8e..db1d8cc 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Error.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Error.cpp @@ -26,6 +26,7 @@ #include "ConstructData.h" #include "ErrorConstructor.h" +#include "JSFunction.h" #include "JSGlobalObject.h" #include "JSObject.h" #include "JSString.h" @@ -72,7 +73,7 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const UString& message, break; } - ArgList args; + MarkedArgumentBuffer args; if (message.isEmpty()) args.append(jsString(exec, name)); else diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ErrorConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ErrorConstructor.cpp index 2e8a523..07b7e23 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ErrorConstructor.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ErrorConstructor.cpp @@ -41,8 +41,8 @@ ErrorConstructor::ErrorConstructor(ExecState* exec, PassRefPtr<Structure> struct ErrorInstance* constructError(ExecState* exec, const ArgList& args) { ErrorInstance* obj = new (exec) ErrorInstance(exec->lexicalGlobalObject()->errorStructure()); - if (!args.at(exec, 0)->isUndefined()) - obj->putDirect(exec->propertyNames().message, jsString(exec, args.at(exec, 0)->toString(exec))); + if (!args.at(0).isUndefined()) + obj->putDirect(exec->propertyNames().message, jsString(exec, args.at(0).toString(exec))); return obj; } @@ -58,7 +58,7 @@ ConstructType ErrorConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.9.2 -static JSValuePtr callErrorConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL callErrorConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args) { // "Error()" gives the sames result as "new Error()" return constructError(exec, args); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ErrorPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ErrorPrototype.cpp index 35358f7..599390e 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ErrorPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ErrorPrototype.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "ErrorPrototype.h" +#include "JSFunction.h" #include "JSString.h" #include "ObjectPrototype.h" #include "PrototypeFunction.h" @@ -30,7 +31,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype); -static JSValuePtr errorProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); // ECMA 15.9.4 ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) @@ -41,24 +42,24 @@ ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, putDirectWithoutTransition(exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum); putDirectWithoutTransition(exec->propertyNames().message, jsNontrivialString(exec, "Unknown error"), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum); } -JSValuePtr errorProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); UString s = "Error"; - JSValuePtr v = thisObj->get(exec, exec->propertyNames().name); - if (!v->isUndefined()) - s = v->toString(exec); + JSValue v = thisObj->get(exec, exec->propertyNames().name); + if (!v.isUndefined()) + s = v.toString(exec); v = thisObj->get(exec, exec->propertyNames().message); - if (!v->isUndefined()) { + if (!v.isUndefined()) { // Mozilla-compatible format. s += ": "; - s += v->toString(exec); + s += v.toString(exec); } return jsNontrivialString(exec, s); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ExceptionHelpers.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ExceptionHelpers.cpp index 42ddf04..e63594c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -31,6 +31,7 @@ #include "CodeBlock.h" #include "CallFrame.h" +#include "JSGlobalObjectFunctions.h" #include "JSObject.h" #include "JSNotAnObject.h" #include "Interpreter.h" @@ -38,16 +39,6 @@ namespace JSC { -static void substitute(UString& string, const UString& substring) -{ - int position = string.find("%s"); - ASSERT(position != -1); - UString newString = string.substr(0, position); - newString.append(substring); - newString.append(string.substr(position + 2)); - string = newString; -} - class InterruptedExecutionError : public JSObject { public: InterruptedExecutionError(JSGlobalData* globalData) @@ -56,38 +47,26 @@ public: } virtual bool isWatchdogException() const { return true; } + + virtual UString toString(ExecState*) const { return "JavaScript execution exceeded timeout."; } }; -JSValuePtr createInterruptedExecutionException(JSGlobalData* globalData) +JSValue createInterruptedExecutionException(JSGlobalData* globalData) { return new (globalData) InterruptedExecutionError(globalData); } -JSValuePtr createError(ExecState* exec, ErrorType e, const char* msg) +static JSValue createError(ExecState* exec, ErrorType e, const char* msg) { return Error::create(exec, e, msg, -1, -1, 0); } -JSValuePtr createError(ExecState* exec, ErrorType e, const char* msg, const Identifier& label) -{ - UString message = msg; - substitute(message, label.ustring()); - return Error::create(exec, e, message, -1, -1, 0); -} - -JSValuePtr createError(ExecState* exec, ErrorType e, const char* msg, JSValuePtr v) -{ - UString message = msg; - substitute(message, v->toString(exec)); - return Error::create(exec, e, message, -1, -1, 0); -} - -JSValuePtr createStackOverflowError(ExecState* exec) +JSValue createStackOverflowError(ExecState* exec) { return createError(exec, RangeError, "Maximum call stack size exceeded."); } -JSValuePtr createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock) +JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock) { int startOffset = 0; int endOffset = 0; @@ -102,12 +81,10 @@ JSValuePtr createUndefinedVariableError(ExecState* exec, const Identifier& ident return exception; } -bool isStrWhiteSpace(UChar c); - -static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValuePtr value, UString error) +static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue value, UString error) { if (!expressionStop || expressionStart > codeBlock->source()->length()) { - UString errorText = value->toString(exec); + UString errorText = value.toString(exec); errorText.append(" is "); errorText.append(error); return errorText; @@ -119,7 +96,7 @@ static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, in errorText.append('\''); errorText.append(codeBlock->source()->getRange(expressionStart, expressionStop)); errorText.append("' ["); - errorText.append(value->toString(exec)); + errorText.append(value.toString(exec)); errorText.append("] is "); } else { // No range information, so give a few characters of context @@ -140,7 +117,7 @@ static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, in errorText.append("near '..."); errorText.append(codeBlock->source()->getRange(start, stop)); errorText.append("...' ["); - errorText.append(value->toString(exec)); + errorText.append(value.toString(exec)); errorText.append("] is "); } errorText.append(error); @@ -148,7 +125,7 @@ static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, in return errorText; } -JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock) +JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock) { UString message = "not a valid argument for '"; message.append(op); @@ -166,7 +143,7 @@ JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValuePtr va return exception; } -JSObject* createNotAConstructorError(ExecState* exec, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock) +JSObject* createNotAConstructorError(ExecState* exec, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock) { int startOffset = 0; int endOffset = 0; @@ -187,7 +164,7 @@ JSObject* createNotAConstructorError(ExecState* exec, JSValuePtr value, unsigned return exception; } -JSValuePtr createNotAFunctionError(ExecState* exec, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock) +JSValue createNotAFunctionError(ExecState* exec, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock) { int startOffset = 0; int endOffset = 0; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ExceptionHelpers.h b/src/3rdparty/webkit/JavaScriptCore/runtime/ExceptionHelpers.h index d4dfdd8..09d99dc 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ExceptionHelpers.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ExceptionHelpers.h @@ -40,16 +40,16 @@ namespace JSC { class JSGlobalData; class JSNotAnObjectErrorStub; class JSObject; - class JSValuePtr; + class JSValue; class Node; - JSValuePtr createInterruptedExecutionException(JSGlobalData*); - JSValuePtr createStackOverflowError(ExecState*); - JSValuePtr createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*); + JSValue createInterruptedExecutionException(JSGlobalData*); + JSValue createStackOverflowError(ExecState*); + JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*); JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull); - JSObject* createInvalidParamError(ExecState*, const char* op, JSValuePtr, unsigned bytecodeOffset, CodeBlock*); - JSObject* createNotAConstructorError(ExecState*, JSValuePtr, unsigned bytecodeOffset, CodeBlock*); - JSValuePtr createNotAFunctionError(ExecState*, JSValuePtr, unsigned bytecodeOffset, CodeBlock*); + JSObject* createInvalidParamError(ExecState*, const char* op, JSValue, unsigned bytecodeOffset, CodeBlock*); + JSObject* createNotAConstructorError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*); + JSValue createNotAFunctionError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*); JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*); } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionConstructor.cpp index e8cfe65..f4f5cc8 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -54,7 +54,7 @@ ConstructType FunctionConstructor::getConstructData(ConstructData& constructData return ConstructTypeHost; } -static JSValuePtr callFunctionConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args) { return constructFunction(exec, args); } @@ -66,7 +66,7 @@ CallType FunctionConstructor::getCallData(CallData& callData) return CallTypeHost; } -static FunctionBodyNode* functionBody(ProgramNode* program) +FunctionBodyNode* extractFunctionBody(ProgramNode* program) { if (!program) return 0; @@ -75,17 +75,19 @@ static FunctionBodyNode* functionBody(ProgramNode* program) if (children.size() != 1) return 0; - ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(children[0].get()); + StatementNode* exprStatement = children[0]; + ASSERT(exprStatement); ASSERT(exprStatement->isExprStatement()); if (!exprStatement || !exprStatement->isExprStatement()) return 0; - FuncExprNode* funcExpr = static_cast<FuncExprNode*>(exprStatement->expr()); + ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); + ASSERT(funcExpr); ASSERT(funcExpr->isFuncExprNode()); if (!funcExpr || !funcExpr->isFuncExprNode()) return 0; - FunctionBodyNode* body = funcExpr->body(); + FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); ASSERT(body); return body; } @@ -93,16 +95,19 @@ static FunctionBodyNode* functionBody(ProgramNode* program) // ECMA 15.3.2 The Function Constructor JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber) { + // Functions need to have a space following the opening { due to for web compatibility + // see https://bugs.webkit.org/show_bug.cgi?id=24350 + // We also need \n before the closing } to handle // comments at the end of the last line UString program; if (args.isEmpty()) - program = "(function(){})"; + program = "(function() { \n})"; else if (args.size() == 1) - program = "(function(){" + args.at(exec, 0)->toString(exec) + "})"; + program = "(function() { " + args.at(0).toString(exec) + "\n})"; else { - program = "(function(" + args.at(exec, 0)->toString(exec); + program = "(function(" + args.at(0).toString(exec); for (size_t i = 1; i < args.size() - 1; i++) - program += "," + args.at(exec, i)->toString(exec); - program += "){" + args.at(exec, args.size() - 1)->toString(exec) + "})"; + program += "," + args.at(i).toString(exec); + program += ") { " + args.at(args.size() - 1).toString(exec) + "\n})"; } int errLine; @@ -110,7 +115,7 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi SourceCode source = makeSource(program, sourceURL, lineNumber); RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); - FunctionBodyNode* body = functionBody(programNode.get()); + FunctionBodyNode* body = extractFunctionBody(programNode.get()); if (!body) return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionConstructor.h b/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionConstructor.h index e8486dc..124b354 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionConstructor.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionConstructor.h @@ -26,6 +26,8 @@ namespace JSC { class FunctionPrototype; + class ProgramNode; + class FunctionBodyNode; class FunctionConstructor : public InternalFunction { public: @@ -39,6 +41,8 @@ namespace JSC { JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber); JSObject* constructFunction(ExecState*, const ArgList&); + FunctionBodyNode* extractFunctionBody(ProgramNode*); + } // namespace JSC #endif // FunctionConstructor_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.cpp index 4d9d682..9ba2144 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -26,15 +26,16 @@ #include "JSFunction.h" #include "JSString.h" #include "Interpreter.h" +#include "Lexer.h" #include "PrototypeFunction.h" namespace JSC { ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype); -static JSValuePtr functionProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr functionProtoFuncApply(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr functionProtoFuncCall(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*, JSObject*, JSValue, const ArgList&); FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<Structure> structure) : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier) @@ -42,14 +43,16 @@ FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<Structure> stru putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum); } -void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure) +void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction) { - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum); + *applyFunction = new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply); + putDirectFunctionWithoutTransition(exec, *applyFunction, DontEnum); + *callFunction = new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall); + putDirectFunctionWithoutTransition(exec, *callFunction, DontEnum); } -static JSValuePtr callFunctionPrototype(ExecState*, JSObject*, JSValuePtr, const ArgList&) +static JSValue JSC_HOST_CALL callFunctionPrototype(ExecState*, JSObject*, JSValue, const ArgList&) { return jsUndefined(); } @@ -63,14 +66,34 @@ CallType FunctionPrototype::getCallData(CallData& callData) // Functions -JSValuePtr functionProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +// Compatibility hack for the Optimost JavaScript library. (See <rdar://problem/6595040>.) +static inline void insertSemicolonIfNeeded(UString& functionBody) { - if (thisValue->isObject(&JSFunction::info)) { + ASSERT(functionBody[0] == '{'); + ASSERT(functionBody[functionBody.size() - 1] == '}'); + + for (size_t i = functionBody.size() - 2; i > 0; --i) { + UChar ch = functionBody[i]; + if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) { + if (ch != ';' && ch != '}') + functionBody = functionBody.substr(0, i + 1) + ";" + functionBody.substr(i + 1, functionBody.size() - (i + 1)); + return; + } + } +} + +JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) +{ + if (thisValue.isObject(&JSFunction::info)) { JSFunction* function = asFunction(thisValue); - return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->body()->paramString() + ") " + function->body()->toSourceString()); + if (!function->isHostFunction()) { + UString functionBody = function->body()->toSourceString(); + insertSemicolonIfNeeded(functionBody); + return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->body()->paramString() + ") " + functionBody); + } } - if (thisValue->isObject(&InternalFunction::info)) { + if (thisValue.isObject(&InternalFunction::info)) { InternalFunction* function = asInternalFunction(thisValue); return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n [native code]\n}"); } @@ -78,59 +101,44 @@ JSValuePtr functionProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr this return throwError(exec, TypeError); } -JSValuePtr functionProtoFuncApply(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { CallData callData; - CallType callType = thisValue->getCallData(callData); + CallType callType = thisValue.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSValuePtr thisArg = args.at(exec, 0); - JSValuePtr argArray = args.at(exec, 1); + JSValue array = args.at(1); - JSValuePtr applyThis; - if (thisArg->isUndefinedOrNull()) - applyThis = exec->globalThisValue(); - else - applyThis = thisArg->toObject(exec); - - ArgList applyArgs; - if (!argArray->isUndefinedOrNull()) { - if (!argArray->isObject()) + MarkedArgumentBuffer applyArgs; + if (!array.isUndefinedOrNull()) { + if (!array.isObject()) return throwError(exec, TypeError); - if (asObject(argArray)->classInfo() == &Arguments::info) - asArguments(argArray)->fillArgList(exec, applyArgs); - else if (exec->interpreter()->isJSArray(argArray)) - asArray(argArray)->fillArgList(exec, applyArgs); - else if (asObject(argArray)->inherits(&JSArray::info)) { - unsigned length = asArray(argArray)->get(exec, exec->propertyNames().length)->toUInt32(exec); + if (asObject(array)->classInfo() == &Arguments::info) + asArguments(array)->fillArgList(exec, applyArgs); + else if (isJSArray(&exec->globalData(), array)) + asArray(array)->fillArgList(exec, applyArgs); + else if (asObject(array)->inherits(&JSArray::info)) { + unsigned length = asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned i = 0; i < length; ++i) - applyArgs.append(asArray(argArray)->get(exec, i)); + applyArgs.append(asArray(array)->get(exec, i)); } else return throwError(exec, TypeError); } - return call(exec, thisValue, callType, callData, applyThis, applyArgs); + return call(exec, thisValue, callType, callData, args.at(0), applyArgs); } -JSValuePtr functionProtoFuncCall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { CallData callData; - CallType callType = thisValue->getCallData(callData); + CallType callType = thisValue.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - JSValuePtr thisArg = args.at(exec, 0); - - JSObject* callThis; - if (thisArg->isUndefinedOrNull()) - callThis = exec->globalThisValue(); - else - callThis = thisArg->toObject(exec); - - ArgList argsTail; - args.getSlice(1, argsTail); - return call(exec, thisValue, callType, callData, callThis, argsTail); + ArgList callArgs; + args.getSlice(1, callArgs); + return call(exec, thisValue, callType, callData, args.at(0), callArgs); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.h b/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.h index 33d68b7..607ddab 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.h @@ -25,12 +25,14 @@ namespace JSC { + class PrototypeFunction; + class FunctionPrototype : public InternalFunction { public: FunctionPrototype(ExecState*, PassRefPtr<Structure>); - void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure); + void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction); - static PassRefPtr<Structure> createStructure(JSValuePtr proto) + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/GetterSetter.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/GetterSetter.cpp index d24a024..cd1b40a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/GetterSetter.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/GetterSetter.cpp @@ -38,17 +38,17 @@ void GetterSetter::mark() m_setter->mark(); } -JSValuePtr GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const +JSValue GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const { ASSERT_NOT_REACHED(); return jsNull(); } -bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value) +bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValue& value) { ASSERT_NOT_REACHED(); number = 0; - value = noValue(); + value = JSValue(); return true; } @@ -73,7 +73,7 @@ UString GetterSetter::toString(ExecState*) const JSObject* GetterSetter::toObject(ExecState* exec) const { ASSERT_NOT_REACHED(); - return jsNull()->toObject(exec); + return jsNull().toObject(exec); } bool GetterSetter::isGetterSetter() const diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/GetterSetter.h b/src/3rdparty/webkit/JavaScriptCore/runtime/GetterSetter.h index 48e1baf..e6b74a1 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/GetterSetter.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/GetterSetter.h @@ -50,8 +50,8 @@ namespace JSC { private: virtual bool isGetterSetter() const; - virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value); + virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; @@ -61,9 +61,9 @@ namespace JSC { JSObject* m_setter; }; - GetterSetter* asGetterSetter(JSValuePtr); + GetterSetter* asGetterSetter(JSValue); - inline GetterSetter* asGetterSetter(JSValuePtr value) + inline GetterSetter* asGetterSetter(JSValue value) { ASSERT(asCell(value)->isGetterSetter()); return static_cast<GetterSetter*>(asCell(value)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Identifier.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Identifier.cpp index 8372010..040c123 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Identifier.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Identifier.cpp @@ -124,12 +124,12 @@ struct CStringTranslator { PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c) { if (!c) { - UString::Rep::null.hash(); - return &UString::Rep::null; + UString::Rep::null().hash(); + return &UString::Rep::null(); } if (!c[0]) { - UString::Rep::empty.hash(); - return &UString::Rep::empty; + UString::Rep::empty().hash(); + return &UString::Rep::empty(); } if (!c[1]) return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0]))); @@ -194,8 +194,8 @@ PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const UChar* return add(globalData, globalData->smallStrings.singleCharacterStringRep(c)); } if (!length) { - UString::Rep::empty.hash(); - return &UString::Rep::empty; + UString::Rep::empty().hash(); + return &UString::Rep::empty(); } UCharBuffer buf = {s, length}; pair<HashSet<UString::Rep*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, UCharBufferTranslator>(buf); @@ -225,8 +225,8 @@ PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UStri } } if (!r->len) { - UString::Rep::empty.hash(); - return &UString::Rep::empty; + UString::Rep::empty().hash(); + return &UString::Rep::empty(); } return *globalData->identifierTable->add(r).first; } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/InitializeThreading.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/InitializeThreading.cpp index a17c386..cda9fb1 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/InitializeThreading.cpp @@ -49,9 +49,9 @@ static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT; static void initializeThreadingOnce() { WTF::initializeThreading(); + initializeUString(); #if ENABLE(JSC_MULTIPLE_THREADS) s_dtoaP5Mutex = new Mutex; - UString::null(); initDateMath(); #endif } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/InternalFunction.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/InternalFunction.cpp index 6714cf5..b5c9571 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/InternalFunction.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/InternalFunction.cpp @@ -48,4 +48,24 @@ const UString& InternalFunction::name(JSGlobalData* globalData) return asString(getDirect(globalData->propertyNames->name))->value(); } +const UString InternalFunction::displayName(JSGlobalData* globalData) +{ + JSValue displayName = getDirect(globalData->propertyNames->displayName); + + if (displayName && isJSString(globalData, displayName)) + return asString(displayName)->value(); + + return UString::null(); +} + +const UString InternalFunction::calculatedDisplayName(JSGlobalData* globalData) +{ + const UString explicitName = displayName(globalData); + + if (!explicitName.isEmpty()) + return explicitName; + + return name(globalData); +} + } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/InternalFunction.h b/src/3rdparty/webkit/JavaScriptCore/runtime/InternalFunction.h index cc4b917..310644c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/InternalFunction.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/InternalFunction.h @@ -34,11 +34,13 @@ namespace JSC { class InternalFunction : public JSObject { public: virtual const ClassInfo* classInfo() const; - static const ClassInfo info; + static JS_EXPORTDATA const ClassInfo info; const UString& name(JSGlobalData*); + const UString displayName(JSGlobalData*); + const UString calculatedDisplayName(JSGlobalData*); - static PassRefPtr<Structure> createStructure(JSValuePtr proto) + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot)); } @@ -51,9 +53,9 @@ namespace JSC { virtual CallType getCallData(CallData&) = 0; }; - InternalFunction* asInternalFunction(JSValuePtr); + InternalFunction* asInternalFunction(JSValue); - inline InternalFunction* asInternalFunction(JSValuePtr value) + inline InternalFunction* asInternalFunction(JSValue value) { ASSERT(asObject(value)->inherits(&InternalFunction::info)); return static_cast<InternalFunction*>(asObject(value)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.cpp index d03b3f0..8996629 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.cpp @@ -75,7 +75,7 @@ void JSActivation::mark() for ( ; i < count; ++i) { Register& r = registerArray[i]; - if (!r.marked()) + if (r.jsValue() && !r.marked()) r.mark(); } } @@ -85,7 +85,7 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert if (symbolTableGet(propertyName, slot)) return true; - if (JSValuePtr* location = getDirectLocation(propertyName)) { + if (JSValue* location = getDirectLocation(propertyName)) { slot.setValueSlot(location); return true; } @@ -99,11 +99,11 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert // We don't call through to JSObject because there's no way to give an // activation object getter properties or a prototype. ASSERT(!hasGetterSetterProperties()); - ASSERT(prototype()->isNull()); + ASSERT(prototype().isNull()); return false; } -void JSActivation::put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -118,7 +118,7 @@ void JSActivation::put(ExecState*, const Identifier& propertyName, JSValuePtr va } // FIXME: Make this function honor ReadOnly (const) and DontEnum -void JSActivation::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes) +void JSActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -130,7 +130,7 @@ void JSActivation::putWithAttributes(ExecState*, const Identifier& propertyName, // expose in the activation object. ASSERT(!hasGetterSetterProperties()); PutPropertySlot slot; - putDirect(propertyName, value, attributes, true, slot); + JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot); } bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName) @@ -151,7 +151,7 @@ bool JSActivation::isDynamicScope() const return d()->functionBody->usesEval(); } -JSValuePtr JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { JSActivation* activation = asActivation(slot.slotBase()); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.h index 222f423..c183dac 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.h @@ -50,11 +50,13 @@ namespace JSC { virtual bool isDynamicScope() const; + virtual bool isActivationObject() const { return true; } + virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); - virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&); + virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); - virtual void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes); + virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual JSObject* toThisObject(ExecState*) const; @@ -64,7 +66,7 @@ namespace JSC { virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; - static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); } private: struct JSActivationData : public JSVariableObjectData { @@ -77,15 +79,15 @@ namespace JSC { RefPtr<FunctionBodyNode> functionBody; }; - static JSValuePtr argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); } }; - JSActivation* asActivation(JSValuePtr); + JSActivation* asActivation(JSValue); - inline JSActivation* asActivation(JSValuePtr value) + inline JSActivation* asActivation(JSValue value) { ASSERT(asObject(value)->inherits(&JSActivation::info)); return static_cast<JSActivation*>(asObject(value)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp index 35d0dec..296ac9d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp @@ -24,9 +24,11 @@ #include "JSArray.h" #include "ArrayPrototype.h" +#include "CachedCall.h" #include "PropertyNameArray.h" #include <wtf/AVLTree.h> #include <wtf/Assertions.h> +#include <wtf/OwnPtr.h> #include <Operations.h> #define CHECK_ARRAY_CONSISTENCY 0 @@ -65,9 +67,9 @@ ASSERT_CLASS_FITS_IN_CELL(JSArray); // The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize // function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage -// size calculation cannot overflow. (sizeof(ArrayStorage) - sizeof(JSValuePtr)) + -// (vectorLength * sizeof(JSValuePtr)) must be <= 0xFFFFFFFFU (which is maximum value of size_t). -#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(JSValuePtr))) / sizeof(JSValuePtr)) +// size calculation cannot overflow. (sizeof(ArrayStorage) - sizeof(JSValue)) + +// (vectorLength * sizeof(JSValue)) must be <= 0xFFFFFFFFU (which is maximum value of size_t). +#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(JSValue))) / sizeof(JSValue)) // These values have to be macros to be used in max() and min() without introducing // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>. @@ -90,10 +92,10 @@ static inline size_t storageSize(unsigned vectorLength) // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH) // - as asserted above - the following calculation cannot overflow. - size_t size = (sizeof(ArrayStorage) - sizeof(JSValuePtr)) + (vectorLength * sizeof(JSValuePtr)); + size_t size = (sizeof(ArrayStorage) - sizeof(JSValue)) + (vectorLength * sizeof(JSValue)); // Assertion to detect integer overflow in previous calculation (should not be possible, provided that // MAX_STORAGE_VECTOR_LENGTH is correctly defined). - ASSERT(((size - (sizeof(ArrayStorage) - sizeof(JSValuePtr))) / sizeof(JSValuePtr) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(JSValuePtr)))); + ASSERT(((size - (sizeof(ArrayStorage) - sizeof(JSValue))) / sizeof(JSValue) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(JSValue)))); return size; } @@ -149,12 +151,12 @@ JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength) m_storage->m_vectorLength = initialCapacity; m_storage->m_length = initialLength; - Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValuePtr)); + Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue)); checkConsistency(); } -JSArray::JSArray(ExecState* exec, PassRefPtr<Structure> structure, const ArgList& list) +JSArray::JSArray(PassRefPtr<Structure> structure, const ArgList& list) : JSObject(structure) { unsigned length = list.size(); @@ -171,12 +173,11 @@ JSArray::JSArray(ExecState* exec, PassRefPtr<Structure> structure, const ArgList size_t i = 0; ArgList::const_iterator end = list.end(); for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i) - storage->m_vector[i] = (*it).jsValue(exec); + storage->m_vector[i] = *it; m_storage = storage; - // When the array is created non-empty, its cells are filled, so it's really no worse than - // a property map. Therefore don't report extra memory cost. + Heap::heap(this)->reportExtraMemoryCost(storageSize(length)); checkConsistency(); } @@ -200,7 +201,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot } if (i < storage->m_vectorLength) { - JSValuePtr& valueSlot = storage->m_vector[i]; + JSValue& valueSlot = storage->m_vector[i]; if (valueSlot) { slot.setValueSlot(&valueSlot); return true; @@ -234,7 +235,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName } // ECMA 15.4.5.1 -void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); @@ -244,8 +245,8 @@ void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr va } if (propertyName == exec->propertyNames().length) { - unsigned newLength = value->toUInt32(exec); - if (value->toNumber(exec) != static_cast<double>(newLength)) { + unsigned newLength = value.toUInt32(exec); + if (value.toNumber(exec) != static_cast<double>(newLength)) { throwError(exec, RangeError, "Invalid array length."); return; } @@ -256,7 +257,7 @@ void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr va JSObject::put(exec, propertyName, value, slot); } -void JSArray::put(ExecState* exec, unsigned i, JSValuePtr value) +void JSArray::put(ExecState* exec, unsigned i, JSValue value) { checkConsistency(); @@ -267,7 +268,7 @@ void JSArray::put(ExecState* exec, unsigned i, JSValuePtr value) } if (i < m_storage->m_vectorLength) { - JSValuePtr& valueSlot = m_storage->m_vector[i]; + JSValue& valueSlot = m_storage->m_vector[i]; if (valueSlot) { valueSlot = value; checkConsistency(); @@ -283,7 +284,7 @@ void JSArray::put(ExecState* exec, unsigned i, JSValuePtr value) putSlowCase(exec, i, value); } -NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValuePtr value) +NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue value) { ArrayStorage* storage = m_storage; SparseArrayValueMap* map = storage->m_sparseValueMap; @@ -349,14 +350,17 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValuePtr v } unsigned vectorLength = storage->m_vectorLength; + + Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); + if (newNumValuesInVector == storage->m_numValuesInVector + 1) { for (unsigned j = vectorLength; j < newVectorLength; ++j) - storage->m_vector[j] = noValue(); + storage->m_vector[j] = JSValue(); if (i > MIN_SPARSE_ARRAY_INDEX) map->remove(i); } else { for (unsigned j = vectorLength; j < max(vectorLength, MIN_SPARSE_ARRAY_INDEX); ++j) - storage->m_vector[j] = noValue(); + storage->m_vector[j] = JSValue(); for (unsigned j = max(vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j) storage->m_vector[j] = map->take(j); } @@ -391,12 +395,12 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i) ArrayStorage* storage = m_storage; if (i < storage->m_vectorLength) { - JSValuePtr& valueSlot = storage->m_vector[i]; + JSValue& valueSlot = storage->m_vector[i]; if (!valueSlot) { checkConsistency(); return false; } - valueSlot = noValue(); + valueSlot = JSValue(); --storage->m_numValuesInVector; if (m_fastAccessCutoff > i) m_fastAccessCutoff = i; @@ -462,10 +466,11 @@ bool JSArray::increaseVectorLength(unsigned newLength) if (!storage) return false; + Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); storage->m_vectorLength = newVectorLength; for (unsigned i = vectorLength; i < newVectorLength; ++i) - storage->m_vector[i] = noValue(); + storage->m_vector[i] = JSValue(); m_storage = storage; return true; @@ -485,9 +490,9 @@ void JSArray::setLength(unsigned newLength) unsigned usedVectorLength = min(length, storage->m_vectorLength); for (unsigned i = newLength; i < usedVectorLength; ++i) { - JSValuePtr& valueSlot = storage->m_vector[i]; + JSValue& valueSlot = storage->m_vector[i]; bool hadValue = valueSlot; - valueSlot = noValue(); + valueSlot = JSValue(); storage->m_numValuesInVector -= hadValue; } @@ -510,7 +515,7 @@ void JSArray::setLength(unsigned newLength) checkConsistency(); } -JSValuePtr JSArray::pop() +JSValue JSArray::pop() { checkConsistency(); @@ -520,19 +525,19 @@ JSValuePtr JSArray::pop() --length; - JSValuePtr result; + JSValue result; if (m_fastAccessCutoff > length) { - JSValuePtr& valueSlot = m_storage->m_vector[length]; + JSValue& valueSlot = m_storage->m_vector[length]; result = valueSlot; ASSERT(result); - valueSlot = noValue(); + valueSlot = JSValue(); --m_storage->m_numValuesInVector; m_fastAccessCutoff = length; } else if (length < m_storage->m_vectorLength) { - JSValuePtr& valueSlot = m_storage->m_vector[length]; + JSValue& valueSlot = m_storage->m_vector[length]; result = valueSlot; - valueSlot = noValue(); + valueSlot = JSValue(); if (result) --m_storage->m_numValuesInVector; else @@ -559,7 +564,7 @@ JSValuePtr JSArray::pop() return result; } -void JSArray::push(ExecState* exec, JSValuePtr value) +void JSArray::push(ExecState* exec, JSValue value) { checkConsistency(); @@ -599,30 +604,68 @@ void JSArray::mark() unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength); for (unsigned i = 0; i < usedVectorLength; ++i) { - JSValuePtr value = storage->m_vector[i]; - if (value && !value->marked()) - value->mark(); + JSValue value = storage->m_vector[i]; + if (value && !value.marked()) + value.mark(); } if (SparseArrayValueMap* map = storage->m_sparseValueMap) { SparseArrayValueMap::iterator end = map->end(); for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) { - JSValuePtr value = it->second; - if (!value->marked()) - value->mark(); + JSValue value = it->second; + if (!value.marked()) + value.mark(); } } } -typedef std::pair<JSValuePtr, UString> ArrayQSortPair; +static int compareNumbersForQSort(const void* a, const void* b) +{ + double da = static_cast<const JSValue*>(a)->uncheckedGetNumber(); + double db = static_cast<const JSValue*>(b)->uncheckedGetNumber(); + return (da > db) - (da < db); +} + +typedef std::pair<JSValue, UString> ValueStringPair; static int compareByStringPairForQSort(const void* a, const void* b) { - const ArrayQSortPair* va = static_cast<const ArrayQSortPair*>(a); - const ArrayQSortPair* vb = static_cast<const ArrayQSortPair*>(b); + const ValueStringPair* va = static_cast<const ValueStringPair*>(a); + const ValueStringPair* vb = static_cast<const ValueStringPair*>(b); return compare(va->second, vb->second); } +void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData) +{ + unsigned lengthNotIncludingUndefined = compactForSorting(); + if (m_storage->m_sparseValueMap) { + throwOutOfMemoryError(exec); + return; + } + + if (!lengthNotIncludingUndefined) + return; + + bool allValuesAreNumbers = true; + size_t size = m_storage->m_numValuesInVector; + for (size_t i = 0; i < size; ++i) { + if (!m_storage->m_vector[i].isNumber()) { + allValuesAreNumbers = false; + break; + } + } + + if (!allValuesAreNumbers) + return sort(exec, compareFunction, callType, callData); + + // For numeric comparison, which is fast, qsort is faster than mergesort. We + // also don't require mergesort's stability, since there's no user visible + // side-effect from swapping the order of equal primitive values. + qsort(m_storage->m_vector, size, sizeof(JSValue), compareNumbersForQSort); + + checkConsistency(SortConsistencyCheck); +} + void JSArray::sort(ExecState* exec) { unsigned lengthNotIncludingUndefined = compactForSorting(); @@ -639,15 +682,15 @@ void JSArray::sort(ExecState* exec) // buffer. Besides, this protects us from crashing if some objects have custom toString methods that return // random or otherwise changing results, effectively making compare function inconsistent. - Vector<ArrayQSortPair> values(lengthNotIncludingUndefined); + Vector<ValueStringPair> values(lengthNotIncludingUndefined); if (!values.begin()) { throwOutOfMemoryError(exec); return; } for (size_t i = 0; i < lengthNotIncludingUndefined; i++) { - JSValuePtr value = m_storage->m_vector[i]; - ASSERT(!value->isUndefined()); + JSValue value = m_storage->m_vector[i]; + ASSERT(!value.isUndefined()); values[i].first = value; } @@ -658,7 +701,7 @@ void JSArray::sort(ExecState* exec) // a toString call raises an exception. for (size_t i = 0; i < lengthNotIncludingUndefined; i++) - values[i].second = values[i].first->toString(exec); + values[i].second = values[i].first.toString(exec); if (exec->hadException()) return; @@ -667,11 +710,11 @@ void JSArray::sort(ExecState* exec) // than O(N log N). #if HAVE(MERGESORT) - mergesort(values.begin(), values.size(), sizeof(ArrayQSortPair), compareByStringPairForQSort); + mergesort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort); #else // FIXME: The qsort library function is likely to not be a stable sort. // ECMAScript-262 does not specify a stable sort, but in practice, browsers perform a stable sort. - qsort(values.begin(), values.size(), sizeof(ArrayQSortPair), compareByStringPairForQSort); + qsort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort); #endif // FIXME: If the toString function changed the length of the array, this might be @@ -684,7 +727,7 @@ void JSArray::sort(ExecState* exec) } struct AVLTreeNodeForArrayCompare { - JSValuePtr value; + JSValue value; // Child pointers. The high bit of gt is robbed and used as the // balance factor sign. The high bit of lt is robbed and used as @@ -695,15 +738,16 @@ struct AVLTreeNodeForArrayCompare { struct AVLTreeAbstractorForArrayCompare { typedef int32_t handle; // Handle is an index into m_nodes vector. - typedef JSValuePtr key; + typedef JSValue key; typedef int32_t size; Vector<AVLTreeNodeForArrayCompare> m_nodes; ExecState* m_exec; - JSValuePtr m_compareFunction; + JSValue m_compareFunction; CallType m_compareCallType; const CallData* m_compareCallData; - JSValuePtr m_globalThisValue; + JSValue m_globalThisValue; + OwnPtr<CachedCall> m_cachedCall; handle get_less(handle h) { return m_nodes[h].lt & 0x7FFFFFFF; } void set_less(handle h, handle lh) { m_nodes[h].lt &= 0x80000000; m_nodes[h].lt |= lh; } @@ -733,16 +777,24 @@ struct AVLTreeAbstractorForArrayCompare { int compare_key_key(key va, key vb) { - ASSERT(!va->isUndefined()); - ASSERT(!vb->isUndefined()); + ASSERT(!va.isUndefined()); + ASSERT(!vb.isUndefined()); if (m_exec->hadException()) return 1; - ArgList arguments; - arguments.append(va); - arguments.append(vb); - double compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, m_globalThisValue, arguments)->toNumber(m_exec); + double compareResult; + if (m_cachedCall) { + m_cachedCall->setThis(m_globalThisValue); + m_cachedCall->setArgument(0, va); + m_cachedCall->setArgument(1, vb); + compareResult = m_cachedCall->call().toNumber(m_cachedCall->newCallFrame()); + } else { + MarkedArgumentBuffer arguments; + arguments.append(va); + arguments.append(vb); + compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, m_globalThisValue, arguments).toNumber(m_exec); + } return (compareResult < 0) ? -1 : 1; // Not passing equality through, because we need to store all values, even if equivalent. } @@ -752,7 +804,7 @@ struct AVLTreeAbstractorForArrayCompare { static handle null() { return 0x7FFFFFFF; } }; -void JSArray::sort(ExecState* exec, JSValuePtr compareFunction, CallType callType, const CallData& callData) +void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData) { checkConsistency(); @@ -777,6 +829,9 @@ void JSArray::sort(ExecState* exec, JSValuePtr compareFunction, CallType callTyp tree.abstractor().m_globalThisValue = exec->globalThisValue(); tree.abstractor().m_nodes.resize(usedVectorLength + (m_storage->m_sparseValueMap ? m_storage->m_sparseValueMap->size() : 0)); + if (callType == CallTypeJS) + tree.abstractor().m_cachedCall.set(new CachedCall(exec, asFunction(compareFunction), 2, exec->exceptionSlot())); + if (!tree.abstractor().m_nodes.begin()) { throwOutOfMemoryError(exec); return; @@ -790,16 +845,16 @@ void JSArray::sort(ExecState* exec, JSValuePtr compareFunction, CallType callTyp // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree. for (; numDefined < usedVectorLength; ++numDefined) { - JSValuePtr v = m_storage->m_vector[numDefined]; - if (!v || v->isUndefined()) + JSValue v = m_storage->m_vector[numDefined]; + if (!v || v.isUndefined()) break; tree.abstractor().m_nodes[numDefined].value = v; tree.insert(numDefined); } for (unsigned i = numDefined; i < usedVectorLength; ++i) { - JSValuePtr v = m_storage->m_vector[i]; + JSValue v = m_storage->m_vector[i]; if (v) { - if (v->isUndefined()) + if (v.isUndefined()) ++numUndefined; else { tree.abstractor().m_nodes[numDefined].value = v; @@ -851,7 +906,7 @@ void JSArray::sort(ExecState* exec, JSValuePtr compareFunction, CallType callTyp // Ensure that unused values in the vector are zeroed out. for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i) - m_storage->m_vector[i] = noValue(); + m_storage->m_vector[i] = JSValue(); m_fastAccessCutoff = newUsedVectorLength; m_storage->m_numValuesInVector = newUsedVectorLength; @@ -859,7 +914,7 @@ void JSArray::sort(ExecState* exec, JSValuePtr compareFunction, CallType callTyp checkConsistency(SortConsistencyCheck); } -void JSArray::fillArgList(ExecState* exec, ArgList& args) +void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) { unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff); unsigned i = 0; @@ -869,6 +924,19 @@ void JSArray::fillArgList(ExecState* exec, ArgList& args) args.append(get(exec, i)); } +void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize) +{ + ASSERT(m_storage->m_length == maxSize); + UNUSED_PARAM(maxSize); + unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff); + unsigned i = 0; + for (; i < fastAccessLength; ++i) + buffer[i] = getIndex(i); + uint32_t size = m_storage->m_length; + for (; i < size; ++i) + buffer[i] = get(exec, i); +} + unsigned JSArray::compactForSorting() { checkConsistency(); @@ -881,14 +949,14 @@ unsigned JSArray::compactForSorting() unsigned numUndefined = 0; for (; numDefined < usedVectorLength; ++numDefined) { - JSValuePtr v = storage->m_vector[numDefined]; - if (!v || v->isUndefined()) + JSValue v = storage->m_vector[numDefined]; + if (!v || v.isUndefined()) break; } for (unsigned i = numDefined; i < usedVectorLength; ++i) { - JSValuePtr v = storage->m_vector[i]; + JSValue v = storage->m_vector[i]; if (v) { - if (v->isUndefined()) + if (v.isUndefined()) ++numUndefined; else storage->m_vector[numDefined++] = v; @@ -918,7 +986,7 @@ unsigned JSArray::compactForSorting() for (unsigned i = numDefined; i < newUsedVectorLength; ++i) storage->m_vector[i] = jsUndefined(); for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i) - storage->m_vector[i] = noValue(); + storage->m_vector[i] = JSValue(); m_fastAccessCutoff = newUsedVectorLength; storage->m_numValuesInVector = newUsedVectorLength; @@ -951,7 +1019,7 @@ void JSArray::checkConsistency(ConsistencyCheckType type) unsigned numValuesInVector = 0; for (unsigned i = 0; i < m_storage->m_vectorLength; ++i) { - if (JSValuePtr value = m_storage->m_vector[i]) { + if (JSValue value = m_storage->m_vector[i]) { ASSERT(i < m_storage->m_length); if (type != DestructorConsistencyCheck) value->type(); // Likely to crash if the object was deallocated. @@ -990,16 +1058,16 @@ JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength) return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength); } -JSArray* constructArray(ExecState* exec, JSValuePtr singleItemValue) +JSArray* constructArray(ExecState* exec, JSValue singleItemValue) { - ArgList values; + MarkedArgumentBuffer values; values.append(singleItemValue); - return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), values); + return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values); } JSArray* constructArray(ExecState* exec, const ArgList& values) { - return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), values); + return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.h index e280022..ea490d8 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.h @@ -25,7 +25,7 @@ namespace JSC { - typedef HashMap<unsigned, JSValuePtr> SparseArrayValueMap; + typedef HashMap<unsigned, JSValue> SparseArrayValueMap; struct ArrayStorage { unsigned m_length; @@ -33,7 +33,7 @@ namespace JSC { unsigned m_numValuesInVector; SparseArrayValueMap* m_sparseValueMap; void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily. - JSValuePtr m_vector[1]; + JSValue m_vector[1]; }; class JSArray : public JSObject { @@ -42,47 +42,49 @@ namespace JSC { public: explicit JSArray(PassRefPtr<Structure>); JSArray(PassRefPtr<Structure>, unsigned initialLength); - JSArray(ExecState*, PassRefPtr<Structure>, const ArgList& initialValues); + JSArray(PassRefPtr<Structure>, const ArgList& initialValues); virtual ~JSArray(); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValuePtr); // FIXME: Make protected and add setItem. + virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem. - static const ClassInfo info; + static JS_EXPORTDATA const ClassInfo info; unsigned length() const { return m_storage->m_length; } void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray. void sort(ExecState*); - void sort(ExecState*, JSValuePtr compareFunction, CallType, const CallData&); + void sort(ExecState*, JSValue compareFunction, CallType, const CallData&); + void sortNumeric(ExecState*, JSValue compareFunction, CallType, const CallData&); - void push(ExecState*, JSValuePtr); - JSValuePtr pop(); + void push(ExecState*, JSValue); + JSValue pop(); bool canGetIndex(unsigned i) { return i < m_fastAccessCutoff; } - JSValuePtr getIndex(unsigned i) + JSValue getIndex(unsigned i) { ASSERT(canGetIndex(i)); return m_storage->m_vector[i]; } bool canSetIndex(unsigned i) { return i < m_fastAccessCutoff; } - JSValuePtr setIndex(unsigned i, JSValuePtr v) + JSValue setIndex(unsigned i, JSValue v) { ASSERT(canSetIndex(i)); return m_storage->m_vector[i] = v; } - void fillArgList(ExecState*, ArgList&); + void fillArgList(ExecState*, MarkedArgumentBuffer&); + void copyToRegisters(ExecState*, Register*, uint32_t); - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType)); } protected: - virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); virtual void getPropertyNames(ExecState*, PropertyNameArray&); @@ -95,7 +97,7 @@ namespace JSC { virtual const ClassInfo* classInfo() const { return &info; } bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&); - void putSlowCase(ExecState*, unsigned propertyName, JSValuePtr); + void putSlowCase(ExecState*, unsigned propertyName, JSValue); bool increaseVectorLength(unsigned newLength); @@ -108,19 +110,21 @@ namespace JSC { ArrayStorage* m_storage; }; - JSArray* asArray(JSValuePtr); + JSArray* asArray(JSValue); JSArray* constructEmptyArray(ExecState*); JSArray* constructEmptyArray(ExecState*, unsigned initialLength); - JSArray* constructArray(ExecState*, JSValuePtr singleItemValue); + JSArray* constructArray(ExecState*, JSValue singleItemValue); JSArray* constructArray(ExecState*, const ArgList& values); - inline JSArray* asArray(JSValuePtr value) + inline JSArray* asArray(JSValue value) { ASSERT(asObject(value)->inherits(&JSArray::info)); return static_cast<JSArray*>(asObject(value)); } + inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr; } + } // namespace JSC #endif // JSArray_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.cpp index 4a19038..2a5e72f 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.cpp @@ -29,6 +29,8 @@ #include "JSGlobalObject.h" #include "PropertyNameArray.h" +using namespace WTF; + namespace JSC { const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", 0, 0, 0 }; @@ -41,7 +43,7 @@ JSByteArray::JSByteArray(ExecState* exec, PassRefPtr<Structure> structure, ByteA putDirect(exec->globalData().propertyNames->length, jsNumber(exec, m_storage->length()), ReadOnly | DontDelete); } -PassRefPtr<Structure> JSByteArray::createStructure(JSValuePtr prototype) +PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype) { PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType)); return result; @@ -52,7 +54,7 @@ bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& property bool ok; unsigned index = propertyName.toUInt32(&ok, false); if (ok && canAccessIndex(index)) { - slot.setValue(getIndex(index)); + slot.setValue(getIndex(exec, index)); return true; } return JSObject::getOwnPropertySlot(exec, propertyName, slot); @@ -61,13 +63,13 @@ bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& property bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { if (canAccessIndex(propertyName)) { - slot.setValue(getIndex(propertyName)); + slot.setValue(getIndex(exec, propertyName)); return true; } return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot); } -void JSByteArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void JSByteArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { bool ok; unsigned index = propertyName.toUInt32(&ok, false); @@ -78,7 +80,7 @@ void JSByteArray::put(ExecState* exec, const Identifier& propertyName, JSValuePt JSObject::put(exec, propertyName, value, slot); } -void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValuePtr value) +void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValue value) { setIndex(exec, propertyName, value); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.h index 895200b..57374e0 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.h @@ -26,19 +26,20 @@ #ifndef JSByteArray_h #define JSByteArray_h -#include "ByteArray.h" #include "JSObject.h" +#include <wtf/ByteArray.h> + namespace JSC { class JSByteArray : public JSObject { - friend class Interpreter; + friend class VPtrSet; public: bool canAccessIndex(unsigned i) { return i < m_storage->length(); } - JSValuePtr getIndex(unsigned i) + JSValue getIndex(ExecState* exec, unsigned i) { ASSERT(canAccessIndex(i)); - return JSImmediate::from(m_storage->data()[i]); + return jsNumber(exec, m_storage->data()[i]); } void setIndex(unsigned i, int value) @@ -63,22 +64,22 @@ namespace JSC { m_storage->data()[i] = static_cast<unsigned char>(value + 0.5); } - void setIndex(ExecState* exec, unsigned i, JSValuePtr value) + void setIndex(ExecState* exec, unsigned i, JSValue value) { - double byteValue = value->toNumber(exec); + double byteValue = value.toNumber(exec); if (exec->hadException()) return; if (canAccessIndex(i)) setIndex(i, byteValue); } - JSByteArray(ExecState* exec, PassRefPtr<Structure>, ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo); - static PassRefPtr<Structure> createStructure(JSValuePtr prototype); + JSByteArray(ExecState* exec, PassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo); + static PassRefPtr<Structure> createStructure(JSValue prototype); virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); - virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValuePtr, JSC::PutPropertySlot&); - virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValuePtr); + virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); + virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue); virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); @@ -87,7 +88,7 @@ namespace JSC { size_t length() const { return m_storage->length(); } - ByteArray* storage() const { return m_storage.get(); } + WTF::ByteArray* storage() const { return m_storage.get(); } private: enum VPtrStealingHackType { VPtrStealingHack }; @@ -97,15 +98,18 @@ namespace JSC { { } - RefPtr<ByteArray> m_storage; + RefPtr<WTF::ByteArray> m_storage; const ClassInfo* m_classInfo; }; - JSByteArray* asByteArray(JSValuePtr value); - inline JSByteArray* asByteArray(JSValuePtr value) + JSByteArray* asByteArray(JSValue value); + inline JSByteArray* asByteArray(JSValue value) { return static_cast<JSByteArray*>(asCell(value)); } -} -#endif + inline bool isJSByteArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsByteArrayVPtr; } + +} // namespace JSC + +#endif // JSByteArray_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.cpp index c1c1ce4..8cf7943 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.cpp @@ -100,19 +100,6 @@ bool JSCell::getTruncatedUInt32(uint32_t&) const return false; } -bool JSCell::getNumber(double& numericValue) const -{ - if (!isNumber()) - return false; - numericValue = static_cast<const JSNumberCell*>(this)->value(); - return true; -} - -double JSCell::getNumber() const -{ - return isNumber() ? static_cast<const JSNumberCell*>(this)->value() : NaN; -} - bool JSCell::getString(UString&stringValue) const { if (!isString()) @@ -170,12 +157,12 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySl return true; } -void JSCell::put(ExecState* exec, const Identifier& identifier, JSValuePtr value, PutPropertySlot& slot) +void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot) { toObject(exec)->put(exec, identifier, value, slot); } -void JSCell::put(ExecState* exec, unsigned identifier, JSValuePtr value) +void JSCell::put(ExecState* exec, unsigned identifier, JSValue value) { toObject(exec)->put(exec, identifier, value); } @@ -210,9 +197,9 @@ const ClassInfo* JSCell::classInfo() const return 0; } -JSValuePtr JSCell::getJSNumber() +JSValue JSCell::getJSNumber() { - return noValue(); + return JSValue(); } bool JSCell::isGetterSetter() const diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.h index 6d963b3..e0a9b4d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.h @@ -23,6 +23,7 @@ #ifndef JSCell_h #define JSCell_h +#include <wtf/Noncopyable.h> #include "Structure.h" #include "JSValue.h" #include "JSImmediate.h" @@ -30,16 +31,16 @@ namespace JSC { - class JSCell : public JSValue { - friend class JIT; + class JSCell : Noncopyable { friend class GetterSetter; friend class Heap; + friend class JIT; friend class JSNumberCell; friend class JSObject; friend class JSPropertyNameIterator; friend class JSString; friend class JSValue; - friend class Interpreter; + friend class VPtrSet; private: explicit JSCell(Structure*); @@ -56,8 +57,6 @@ namespace JSC { Structure* structure() const; // Extracting the value. - bool getNumber(double&) const; - double getNumber() const; // NaN if not a number bool getString(UString&) const; UString getString() const; // null string if not a string JSObject* getObject(); // NULL if not an object @@ -67,13 +66,14 @@ namespace JSC { virtual ConstructType getConstructData(ConstructData&); // Extracting integer values. + // FIXME: remove these methods, can check isNumberCell in JSValue && then call asNumberCell::*. virtual bool getUInt32(uint32_t&) const; virtual bool getTruncatedInt32(int32_t&) const; virtual bool getTruncatedUInt32(uint32_t&) const; // Basic conversions. - virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const = 0; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&) = 0; + virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const = 0; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&) = 0; virtual bool toBoolean(ExecState*) const = 0; virtual double toNumber(ExecState*) const = 0; virtual UString toString(ExecState*) const = 0; @@ -88,15 +88,15 @@ namespace JSC { // Object operations, with the toObject operation included. virtual const ClassInfo* classInfo() const; - virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValuePtr); + virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + virtual void put(ExecState*, unsigned propertyName, JSValue); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); virtual JSObject* toThisObject(ExecState*) const; virtual UString toThisString(ExecState*) const; virtual JSString* toThisJSString(ExecState*); - virtual JSValuePtr getJSNumber(); + virtual JSValue getJSNumber(); void* vptr() { return *reinterpret_cast<void**>(this); } private: @@ -108,12 +108,11 @@ namespace JSC { Structure* m_structure; }; - JSCell* asCell(JSValuePtr); + JSCell* asCell(JSValue); - inline JSCell* asCell(JSValuePtr value) + inline JSCell* asCell(JSValue value) { - ASSERT(!JSImmediate::isImmediate(value)); - return value->asCell(); + return value.asCell(); } inline JSCell::JSCell(Structure* structure) @@ -157,8 +156,8 @@ namespace JSC { ALWAYS_INLINE JSCell* JSValue::asCell() const { - ASSERT(!JSImmediate::isImmediate(asValue())); - return const_cast<JSCell*>(reinterpret_cast<const JSCell*>(this)); + ASSERT(isCell()); + return m_ptr; } inline void* JSCell::operator new(size_t size, JSGlobalData* globalData) @@ -172,11 +171,6 @@ namespace JSC { // --- JSValue inlines ---------------------------- - inline bool JSValue::isNumber() const - { - return JSImmediate::isNumber(asValue()) || (!JSImmediate::isImmediate(asValue()) && asCell()->isNumber()); - } - inline bool JSValue::isString() const { return !JSImmediate::isImmediate(asValue()) && asCell()->isString(); @@ -192,11 +186,6 @@ namespace JSC { return !JSImmediate::isImmediate(asValue()) && asCell()->isObject(); } - inline double JSValue::getNumber() const - { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asCell()->getNumber(); - } - inline bool JSValue::getString(UString& s) const { return !JSImmediate::isImmediate(asValue()) && asCell()->getString(s); @@ -247,12 +236,12 @@ namespace JSC { return JSImmediate::isImmediate(asValue()) || asCell()->marked(); } - inline JSValuePtr JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const + inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const { return JSImmediate::isImmediate(asValue()) ? asValue() : asCell()->toPrimitive(exec, preferredType); } - inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValuePtr& value) + inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value) { if (JSImmediate::isImmediate(asValue())) { number = JSImmediate::toDouble(asValue()); @@ -301,9 +290,9 @@ namespace JSC { return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toThisString(exec); } - inline JSValuePtr JSValue::getJSNumber() + inline JSValue JSValue::getJSNumber() { - return JSImmediate::isNumber(asValue()) ? asValue() : JSImmediate::isImmediate(asValue()) ? noValue() : asCell()->getJSNumber(); + return JSImmediate::isNumber(asValue()) ? asValue() : JSImmediate::isImmediate(asValue()) ? JSValue() : asCell()->getJSNumber(); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.cpp index a22cb34..f456451 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.cpp @@ -45,11 +45,29 @@ ASSERT_CLASS_FITS_IN_CELL(JSFunction); const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 }; +JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func) + : Base(&exec->globalData(), structure, name) +#if ENABLE(JIT) + , m_body(exec->globalData().nativeFunctionThunk()) +#else + , m_body(0) +#endif +{ +#if ENABLE(JIT) + setNativeFunction(func); + putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum); +#else + UNUSED_PARAM(length); + UNUSED_PARAM(func); + ASSERT_NOT_REACHED(); +#endif +} + JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* body, ScopeChainNode* scopeChainNode) : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), name) , m_body(body) - , m_scopeChain(scopeChainNode) { + setScopeChain(scopeChainNode); } JSFunction::~JSFunction() @@ -58,55 +76,72 @@ JSFunction::~JSFunction() // JIT code for other functions may have had calls linked directly to the code for this function; these links // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once // this memory is freed and may be reused (potentially for another, different JSFunction). - if (m_body && m_body->isGenerated()) - m_body->generatedBytecode().unlinkCallers(); + if (!isHostFunction()) { + if (m_body && m_body->isGenerated()) + m_body->generatedBytecode().unlinkCallers(); + scopeChain().~ScopeChain(); + } + #endif } void JSFunction::mark() { Base::mark(); - m_body->mark(); - m_scopeChain.mark(); + if (!isHostFunction()) { + m_body->mark(); + scopeChain().mark(); + } } CallType JSFunction::getCallData(CallData& callData) { + if (isHostFunction()) { + callData.native.function = nativeFunction(); + return CallTypeHost; + } callData.js.functionBody = m_body.get(); - callData.js.scopeChain = m_scopeChain.node(); + callData.js.scopeChain = scopeChain().node(); return CallTypeJS; } -JSValuePtr JSFunction::call(ExecState* exec, JSValuePtr thisValue, const ArgList& args) +JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args) { - return exec->interpreter()->execute(m_body.get(), exec, this, thisValue->toThisObject(exec), args, m_scopeChain.node(), exec->exceptionSlot()); + ASSERT(!isHostFunction()); + return exec->interpreter()->execute(m_body.get(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot()); } -JSValuePtr JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { JSFunction* thisObj = asFunction(slot.slotBase()); + ASSERT(!thisObj->isHostFunction()); return exec->interpreter()->retrieveArguments(exec, thisObj); } -JSValuePtr JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { JSFunction* thisObj = asFunction(slot.slotBase()); + ASSERT(!thisObj->isHostFunction()); return exec->interpreter()->retrieveCaller(exec, thisObj); } -JSValuePtr JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { JSFunction* thisObj = asFunction(slot.slotBase()); + ASSERT(!thisObj->isHostFunction()); return jsNumber(exec, thisObj->m_body->parameterCount()); } bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { + if (isHostFunction()) + return Base::getOwnPropertySlot(exec, propertyName, slot); + if (propertyName == exec->propertyNames().prototype) { - JSValuePtr* location = getDirectLocation(propertyName); + JSValue* location = getDirectLocation(propertyName); if (!location) { - JSObject* prototype = new (exec) JSObject(m_scopeChain.globalObject()->emptyObjectStructure()); + JSObject* prototype = new (exec) JSObject(scopeChain().globalObject()->emptyObjectStructure()); prototype->putDirect(exec->propertyNames().constructor, this, DontEnum); putDirect(exec->propertyNames().prototype, prototype, DontDelete); location = getDirectLocation(propertyName); @@ -133,8 +168,12 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN return Base::getOwnPropertySlot(exec, propertyName, slot); } -void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { + if (isHostFunction()) { + Base::put(exec, propertyName, value, slot); + return; + } if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) return; Base::put(exec, propertyName, value, slot); @@ -142,6 +181,8 @@ void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValuePtr bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName) { + if (isHostFunction()) + return Base::deleteProperty(exec, propertyName); if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) return false; return Base::deleteProperty(exec, propertyName); @@ -150,23 +191,26 @@ bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName) // ECMA 13.2.2 [[Construct]] ConstructType JSFunction::getConstructData(ConstructData& constructData) { + if (isHostFunction()) + return ConstructTypeNone; constructData.js.functionBody = m_body.get(); - constructData.js.scopeChain = m_scopeChain.node(); + constructData.js.scopeChain = scopeChain().node(); return ConstructTypeJS; } JSObject* JSFunction::construct(ExecState* exec, const ArgList& args) { + ASSERT(!isHostFunction()); Structure* structure; - JSValuePtr prototype = get(exec, exec->propertyNames().prototype); - if (prototype->isObject()) + JSValue prototype = get(exec, exec->propertyNames().prototype); + if (prototype.isObject()) structure = asObject(prototype)->inheritorID(); else structure = exec->lexicalGlobalObject()->emptyObjectStructure(); JSObject* thisObj = new (exec) JSObject(structure); - JSValuePtr result = exec->interpreter()->execute(m_body.get(), exec, this, thisObj, args, m_scopeChain.node(), exec->exceptionSlot()); - if (exec->hadException() || !result->isObject()) + JSValue result = exec->interpreter()->execute(m_body.get(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot()); + if (exec->hadException() || !result.isObject()) return thisObj; return asObject(result); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.h index 6a43737..b27e515 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.h @@ -39,29 +39,30 @@ namespace JSC { class JSFunction : public InternalFunction { friend class JIT; - friend class Interpreter; + friend class VPtrSet; typedef InternalFunction Base; JSFunction(PassRefPtr<Structure> structure) : InternalFunction(structure) - , m_scopeChain(NoScopeChain()) { + clearScopeChain(); } public: + JSFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction); JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*); ~JSFunction(); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); JSObject* construct(ExecState*, const ArgList&); - JSValuePtr call(ExecState*, JSValuePtr thisValue, const ArgList&); + JSValue call(ExecState*, JSValue thisValue, const ArgList&); - void setScope(const ScopeChain& scopeChain) { m_scopeChain = scopeChain; } - ScopeChain& scope() { return m_scopeChain; } + void setScope(const ScopeChain& scopeChain) { setScopeChain(scopeChain); } + ScopeChain& scope() { return scopeChain(); } void setBody(FunctionBodyNode* body) { m_body = body; } void setBody(PassRefPtr<FunctionBodyNode> body) { m_body = body; } @@ -69,30 +70,64 @@ namespace JSC { virtual void mark(); - static const ClassInfo info; + static JS_EXPORTDATA const ClassInfo info; - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); } - private: - virtual const ClassInfo* classInfo() const { return &info; } +#if ENABLE(JIT) + bool isHostFunction() const { return m_body && m_body->isHostFunction(); } +#else + bool isHostFunction() const { return false; } +#endif + NativeFunction nativeFunction() + { + return *reinterpret_cast<NativeFunction*>(m_data); + } virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); - static JSValuePtr argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValuePtr callerGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValuePtr lengthGetter(ExecState*, const Identifier&, const PropertySlot&); + private: + virtual const ClassInfo* classInfo() const { return &info; } + + static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValue callerGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValue lengthGetter(ExecState*, const Identifier&, const PropertySlot&); RefPtr<FunctionBodyNode> m_body; - ScopeChain m_scopeChain; + ScopeChain& scopeChain() + { + ASSERT(!isHostFunction()); + return *reinterpret_cast<ScopeChain*>(m_data); + } + void clearScopeChain() + { + ASSERT(!isHostFunction()); + new (m_data) ScopeChain(NoScopeChain()); + } + void setScopeChain(ScopeChainNode* sc) + { + ASSERT(!isHostFunction()); + new (m_data) ScopeChain(sc); + } + void setScopeChain(const ScopeChain& sc) + { + ASSERT(!isHostFunction()); + *reinterpret_cast<ScopeChain*>(m_data) = sc; + } + void setNativeFunction(NativeFunction func) + { + *reinterpret_cast<NativeFunction*>(m_data) = func; + } + unsigned char m_data[sizeof(void*)]; }; - JSFunction* asFunction(JSValuePtr); + JSFunction* asFunction(JSValue); - inline JSFunction* asFunction(JSValuePtr value) + inline JSFunction* asFunction(JSValue value) { ASSERT(asObject(value)->inherits(&JSFunction::info)); return static_cast<JSFunction*>(asObject(value)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.cpp index 62df65e..1594848 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.cpp @@ -30,15 +30,19 @@ #include "JSGlobalData.h" #include "ArgList.h" +#include "Collector.h" #include "CommonIdentifiers.h" +#include "FunctionConstructor.h" +#include "Interpreter.h" #include "JSActivation.h" +#include "JSArray.h" +#include "JSByteArray.h" #include "JSClassRef.h" +#include "JSFunction.h" #include "JSLock.h" #include "JSNotAnObject.h" #include "JSStaticScopeObject.h" -#include "Interpreter.h" #include "Parser.h" -#include "Collector.h" #include "Lexer.h" #include "Lookup.h" #include "Nodes.h" @@ -63,40 +67,80 @@ extern const HashTable regExpTable; extern const HashTable regExpConstructorTable; extern const HashTable stringTable; -JSGlobalData::JSGlobalData(bool isShared) - : interpreter(new Interpreter) - , exception(noValue()) - , arrayTable(new HashTable(JSC::arrayTable)) - , dateTable(new HashTable(JSC::dateTable)) - , mathTable(new HashTable(JSC::mathTable)) - , numberTable(new HashTable(JSC::numberTable)) - , regExpTable(new HashTable(JSC::regExpTable)) - , regExpConstructorTable(new HashTable(JSC::regExpConstructorTable)) - , stringTable(new HashTable(JSC::stringTable)) +struct VPtrSet { + VPtrSet(); + + void* jsArrayVPtr; + void* jsByteArrayVPtr; + void* jsStringVPtr; + void* jsFunctionVPtr; +}; + +VPtrSet::VPtrSet() +{ + // Bizarrely, calling fastMalloc here is faster than allocating space on the stack. + void* storage = fastMalloc(sizeof(CollectorBlock)); + + JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull())); + jsArrayVPtr = jsArray->vptr(); + jsArray->~JSCell(); + + JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack); + jsByteArrayVPtr = jsByteArray->vptr(); + jsByteArray->~JSCell(); + + JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack); + jsStringVPtr = jsString->vptr(); + jsString->~JSCell(); + + JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull())); + jsFunctionVPtr = jsFunction->vptr(); + jsFunction->~JSCell(); + + fastFree(storage); +} + +JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet) + : isSharedInstance(isShared) + , clientData(0) + , arrayTable(fastNew<HashTable>(JSC::arrayTable)) + , dateTable(fastNew<HashTable>(JSC::dateTable)) + , mathTable(fastNew<HashTable>(JSC::mathTable)) + , numberTable(fastNew<HashTable>(JSC::numberTable)) + , regExpTable(fastNew<HashTable>(JSC::regExpTable)) + , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) + , stringTable(fastNew<HashTable>(JSC::stringTable)) , activationStructure(JSActivation::createStructure(jsNull())) , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull())) , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull())) , stringStructure(JSString::createStructure(jsNull())) , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull())) , notAnObjectStructure(JSNotAnObject::createStructure(jsNull())) +#if !USE(ALTERNATE_JSIMMEDIATE) , numberStructure(JSNumberCell::createStructure(jsNull())) +#endif + , jsArrayVPtr(vptrSet.jsArrayVPtr) + , jsByteArrayVPtr(vptrSet.jsByteArrayVPtr) + , jsStringVPtr(vptrSet.jsStringVPtr) + , jsFunctionVPtr(vptrSet.jsFunctionVPtr) , identifierTable(createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) - , emptyList(new ArgList) - , newParserObjects(0) - , parserObjectExtraRefCounts(0) + , emptyList(new MarkedArgumentBuffer) , lexer(new Lexer(this)) , parser(new Parser) + , interpreter(new Interpreter) +#if ENABLE(JIT) + , jitStubs(this) +#endif + , heap(this) + , initializingLazyNumericCompareFunction(false) , head(0) , dynamicGlobalObject(0) - , isSharedInstance(isShared) - , clientData(0) - , heap(this) + , scopeNodeBeingReparsed(0) { #if PLATFORM(MAC) startProfilerServerIfNeeded(); #endif - interpreter->initialize(this); } JSGlobalData::~JSGlobalData() @@ -116,13 +160,17 @@ JSGlobalData::~JSGlobalData() regExpTable->deleteTable(); regExpConstructorTable->deleteTable(); stringTable->deleteTable(); - delete arrayTable; - delete dateTable; - delete mathTable; - delete numberTable; - delete regExpTable; - delete regExpConstructorTable; - delete stringTable; +#if ENABLE(JIT) + lazyNativeFunctionThunk.clear(); +#endif + + fastDelete(const_cast<HashTable*>(arrayTable)); + fastDelete(const_cast<HashTable*>(dateTable)); + fastDelete(const_cast<HashTable*>(mathTable)); + fastDelete(const_cast<HashTable*>(numberTable)); + fastDelete(const_cast<HashTable*>(regExpTable)); + fastDelete(const_cast<HashTable*>(regExpConstructorTable)); + fastDelete(const_cast<HashTable*>(stringTable)); delete parser; delete lexer; @@ -134,27 +182,20 @@ JSGlobalData::~JSGlobalData() delete propertyNames; deleteIdentifierTable(identifierTable); - delete newParserObjects; - delete parserObjectExtraRefCounts; - delete clientData; } -PassRefPtr<JSGlobalData> JSGlobalData::create() +PassRefPtr<JSGlobalData> JSGlobalData::create(bool isShared) { - return adoptRef(new JSGlobalData); + return adoptRef(new JSGlobalData(isShared, VPtrSet())); } PassRefPtr<JSGlobalData> JSGlobalData::createLeaked() { -#ifndef NDEBUG Structure::startIgnoringLeaks(); RefPtr<JSGlobalData> data = create(); Structure::stopIgnoringLeaks(); return data.release(); -#else - return create(); -#endif } bool JSGlobalData::sharedInstanceExists() @@ -166,7 +207,7 @@ JSGlobalData& JSGlobalData::sharedInstance() { JSGlobalData*& instance = sharedInstanceInternal(); if (!instance) { - instance = new JSGlobalData(true); + instance = create(true).releaseRef(); #if ENABLE(JSC_MULTIPLE_THREADS) instance->makeUsableFromMultipleThreads(); #endif @@ -181,8 +222,31 @@ JSGlobalData*& JSGlobalData::sharedInstanceInternal() return sharedInstance; } -JSGlobalData::ClientData::~ClientData() +#if ENABLE(JIT) + +void JSGlobalData::createNativeThunk() +{ + lazyNativeFunctionThunk = FunctionBodyNode::createNativeThunk(this); +} + +#endif + +// FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc. +const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec) { + if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) { + initializingLazyNumericCompareFunction = true; + RefPtr<ProgramNode> programNode = parser->parse<ProgramNode>(exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0); + RefPtr<FunctionBodyNode> functionBody = extractFunctionBody(programNode.get()); + lazyNumericCompareFunction = functionBody->bytecode(exec->scopeChain()).instructions(); + initializingLazyNumericCompareFunction = false; + } + + return lazyNumericCompareFunction; } +JSGlobalData::ClientData::~ClientData() +{ } + +} // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.h index 67f4178..e53746b 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 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 @@ -29,39 +29,46 @@ #ifndef JSGlobalData_h #define JSGlobalData_h -#include <wtf/Forward.h> -#include <wtf/HashMap.h> -#include <wtf/RefCounted.h> #include "Collector.h" #include "ExecutableAllocator.h" -#include "SmallStrings.h" +#include "JITStubs.h" #include "JSValue.h" +#include "SmallStrings.h" +#include "TimeoutChecker.h" +#include <wtf/Forward.h> +#include <wtf/HashMap.h> +#include <wtf/RefCounted.h> struct OpaqueJSClass; struct OpaqueJSClassContextData; namespace JSC { - class ArgList; class CommonIdentifiers; - class Heap; + class FunctionBodyNode; class IdentifierTable; + class Instruction; + class Interpreter; class JSGlobalObject; class JSObject; class Lexer; - class Interpreter; class Parser; - class ParserRefCounted; + class ScopeNode; class Structure; class UString; struct HashTable; + struct VPtrSet; class JSGlobalData : public RefCounted<JSGlobalData> { public: + struct ClientData { + virtual ~ClientData() = 0; + }; + static bool sharedInstanceExists(); static JSGlobalData& sharedInstance(); - static PassRefPtr<JSGlobalData> create(); + static PassRefPtr<JSGlobalData> create(bool isShared = false); static PassRefPtr<JSGlobalData> createLeaked(); ~JSGlobalData(); @@ -70,12 +77,8 @@ namespace JSC { void makeUsableFromMultipleThreads() { heap.makeUsableFromMultipleThreads(); } #endif - Interpreter* interpreter; - - JSValuePtr exception; -#if ENABLE(JIT) - void* exceptionLocation; -#endif + bool isSharedInstance; + ClientData* clientData; const HashTable* arrayTable; const HashTable* dateTable; @@ -91,48 +94,64 @@ namespace JSC { RefPtr<Structure> stringStructure; RefPtr<Structure> notAnObjectErrorStubStructure; RefPtr<Structure> notAnObjectStructure; +#if !USE(ALTERNATE_JSIMMEDIATE) RefPtr<Structure> numberStructure; +#endif + + void* jsArrayVPtr; + void* jsByteArrayVPtr; + void* jsStringVPtr; + void* jsFunctionVPtr; IdentifierTable* identifierTable; CommonIdentifiers* propertyNames; - const ArgList* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark. - + const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark. SmallStrings smallStrings; - - HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData; - HashSet<ParserRefCounted*>* newParserObjects; - HashCountedSet<ParserRefCounted*>* parserObjectExtraRefCounts; +#if ENABLE(ASSEMBLER) + ExecutableAllocator executableAllocator; +#endif Lexer* lexer; Parser* parser; + Interpreter* interpreter; +#if ENABLE(JIT) + JITThunks jitStubs; + FunctionBodyNode* nativeFunctionThunk() + { + if (!lazyNativeFunctionThunk) + createNativeThunk(); + return lazyNativeFunctionThunk.get(); + } + RefPtr<FunctionBodyNode> lazyNativeFunctionThunk; +#endif + TimeoutChecker timeoutChecker; + Heap heap; - JSGlobalObject* head; - JSGlobalObject* dynamicGlobalObject; + JSValue exception; +#if ENABLE(JIT) + void* exceptionLocation; +#endif - bool isSharedInstance; + const Vector<Instruction>& numericCompareFunction(ExecState*); + Vector<Instruction> lazyNumericCompareFunction; + bool initializingLazyNumericCompareFunction; - struct ClientData { - virtual ~ClientData() = 0; - }; + HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData; - ClientData* clientData; + JSGlobalObject* head; + JSGlobalObject* dynamicGlobalObject; HashSet<JSObject*> arrayVisitedElements; - Heap heap; -#if ENABLE(ASSEMBLER) - PassRefPtr<ExecutablePool> poolForSize(size_t n) { return m_executableAllocator.poolForSize(n); } -#endif - private: - JSGlobalData(bool isShared = false); -#if ENABLE(ASSEMBLER) - ExecutableAllocator m_executableAllocator; -#endif + ScopeNode* scopeNodeBeingReparsed; + private: + JSGlobalData(bool isShared, const VPtrSet&); static JSGlobalData*& sharedInstanceInternal(); + void createNativeThunk(); }; -} +} // namespace JSC -#endif +#endif // JSGlobalData_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp index dfe291c..1e9f670 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -47,6 +47,7 @@ #include "FunctionConstructor.h" #include "FunctionPrototype.h" #include "GlobalEvalFunction.h" +#include "JSFunction.h" #include "JSGlobalObjectFunctions.h" #include "JSLock.h" #include "Interpreter.h" @@ -78,10 +79,10 @@ static const int initialTickCountThreshold = 255; // Preferred number of milliseconds between each timeout check static const int preferredScriptCheckTimeInterval = 1000; -static inline void markIfNeeded(JSValuePtr v) +static inline void markIfNeeded(JSValue v) { - if (v && !v->marked()) - v->mark(); + if (v && !v.marked()) + v.mark(); } static inline void markIfNeeded(const RefPtr<Structure>& s) @@ -147,7 +148,7 @@ void JSGlobalObject::init(JSObject* thisValue) reset(prototype()); } -void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -156,20 +157,20 @@ void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValu JSVariableObject::put(exec, propertyName, value, slot); } -void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValuePtr value, unsigned attributes) +void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); if (symbolTablePutWithAttributes(propertyName, value, attributes)) return; - JSValuePtr valueBefore = getDirect(propertyName); + JSValue valueBefore = getDirect(propertyName); PutPropertySlot slot; JSVariableObject::put(exec, propertyName, value, slot); if (!valueBefore) { - JSValuePtr valueAfter = getDirect(propertyName); + JSValue valueAfter = getDirect(propertyName); if (valueAfter) - putDirect(propertyName, valueAfter, attributes); + JSObject::putWithAttributes(exec, propertyName, valueAfter, attributes); } } @@ -190,12 +191,12 @@ void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyNam static inline JSObject* lastInPrototypeChain(JSObject* object) { JSObject* o = object; - while (o->prototype()->isObject()) + while (o->prototype().isObject()) o = asObject(o->prototype()); return o; } -void JSGlobalObject::reset(JSValuePtr prototype) +void JSGlobalObject::reset(JSValue prototype) { ExecState* exec = JSGlobalObject::globalExec(); @@ -203,7 +204,11 @@ void JSGlobalObject::reset(JSValuePtr prototype) d()->functionPrototype = new (exec) FunctionPrototype(exec, FunctionPrototype::createStructure(jsNull())); // The real prototype will be set once ObjectPrototype is created. d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype); - d()->functionPrototype->addFunctionProperties(exec, d()->prototypeFunctionStructure.get()); + NativeFunctionWrapper* callFunction = 0; + NativeFunctionWrapper* applyFunction = 0; + d()->functionPrototype->addFunctionProperties(exec, d()->prototypeFunctionStructure.get(), &callFunction, &applyFunction); + d()->callFunction = callFunction; + d()->applyFunction = applyFunction; d()->objectPrototype = new (exec) ObjectPrototype(exec, ObjectPrototype::createStructure(jsNull()), d()->prototypeFunctionStructure.get()); d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype); @@ -234,6 +239,8 @@ void JSGlobalObject::reset(JSValuePtr prototype) d()->regExpPrototype = new (exec) RegExpPrototype(exec, RegExpPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get()); d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype); + d()->methodCallDummy = constructEmptyObject(exec); + ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, ErrorPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get()); d()->errorStructure = ErrorInstance::createStructure(errorPrototype); @@ -248,13 +255,13 @@ void JSGlobalObject::reset(JSValuePtr prototype) // Constructors - JSValuePtr objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype); - JSValuePtr functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype); - JSValuePtr arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype); - JSValuePtr stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype); - JSValuePtr booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype); - JSValuePtr numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype); - JSValuePtr dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype); + JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype); + JSCell* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype); + JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype); + JSCell* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype); + JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype); + JSCell* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype); + JSCell* dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype); d()->regExpConstructor = new (exec) RegExpConstructor(exec, RegExpConstructor::createStructure(d()->functionPrototype), d()->regExpPrototype); @@ -269,15 +276,15 @@ void JSGlobalObject::reset(JSValuePtr prototype) d()->typeErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, typeErrorPrototype); d()->URIErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, URIErrorPrototype); - d()->objectPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum); - d()->functionPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum); - d()->arrayPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum); - d()->booleanPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum); - d()->stringPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum); - d()->numberPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum); - d()->datePrototype->putDirectWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum); - d()->regExpPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum); - errorPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum); + d()->objectPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum); + d()->functionPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum); + d()->arrayPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum); + d()->booleanPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum); + d()->stringPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum); + d()->numberPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum); + d()->datePrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum); + d()->regExpPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum); + errorPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum); evalErrorPrototype->putDirect(exec->propertyNames().constructor, d()->evalErrorConstructor, DontEnum); rangeErrorPrototype->putDirect(exec->propertyNames().constructor, d()->rangeErrorConstructor, DontEnum); @@ -290,21 +297,21 @@ void JSGlobalObject::reset(JSValuePtr prototype) // FIXME: These properties could be handled by a static hash table. - putDirectWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum); - putDirectWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum); - putDirectWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum); - putDirectWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum); - putDirectWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum); - putDirectWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum); - putDirectWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum); - putDirectWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum); - putDirectWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum); - putDirectWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor); - putDirectWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor); - putDirectWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor); - putDirectWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor); - putDirectWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor); - putDirectWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor); + putDirectFunctionWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor); + putDirectFunctionWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor); + putDirectFunctionWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor); + putDirectFunctionWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor); + putDirectFunctionWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor); + putDirectFunctionWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor); // Set global values. GlobalPropertyInfo staticGlobals[] = { @@ -320,43 +327,32 @@ void JSGlobalObject::reset(JSValuePtr prototype) d()->evalFunction = new (exec) GlobalEvalFunction(exec, GlobalEvalFunction::createStructure(d()->functionPrototype), 1, exec->propertyNames().eval, globalFuncEval, this); putDirectFunctionWithoutTransition(exec, d()->evalFunction, DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum); #ifndef NDEBUG - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum); #endif resetPrototype(prototype); } // Set prototype, and also insert the object prototype at the end of the chain. -void JSGlobalObject::resetPrototype(JSValuePtr prototype) +void JSGlobalObject::resetPrototype(JSValue prototype) { setPrototype(prototype); - lastInPrototypeChain(this)->setPrototype(d()->objectPrototype); -} - -void JSGlobalObject::setTimeoutTime(unsigned timeoutTime) -{ - globalData()->interpreter->setTimeoutTime(timeoutTime); -} -void JSGlobalObject::startTimeoutCheck() -{ - globalData()->interpreter->startTimeoutCheck(); -} - -void JSGlobalObject::stopTimeoutCheck() -{ - globalData()->interpreter->stopTimeoutCheck(); + JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this); + JSObject* objectPrototype = d()->objectPrototype; + if (oldLastInPrototypeChain != objectPrototype) + oldLastInPrototypeChain->setPrototype(objectPrototype); } void JSGlobalObject::mark() @@ -381,6 +377,8 @@ void JSGlobalObject::mark() markIfNeeded(d()->URIErrorConstructor); markIfNeeded(d()->evalFunction); + markIfNeeded(d()->callFunction); + markIfNeeded(d()->applyFunction); markIfNeeded(d()->objectPrototype); markIfNeeded(d()->functionPrototype); @@ -391,6 +389,8 @@ void JSGlobalObject::mark() markIfNeeded(d()->datePrototype); markIfNeeded(d()->regExpPrototype); + markIfNeeded(d()->methodCallDummy); + markIfNeeded(d()->errorStructure); // No need to mark the other structures, because their prototypes are all diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h index 4a10f64..da9a819 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h @@ -24,6 +24,7 @@ #include "JSGlobalData.h" #include "JSVariableObject.h" +#include "NativeFunctionWrapper.h" #include "NumberPrototype.h" #include "StringPrototype.h" #include <wtf/HashSet.h> @@ -40,6 +41,7 @@ namespace JSC { class GlobalEvalFunction; class NativeErrorConstructor; class ProgramCodeBlock; + class PrototypeFunction; class RegExpConstructor; class RegExpPrototype; class RegisterFile; @@ -67,6 +69,8 @@ namespace JSC { , typeErrorConstructor(0) , URIErrorConstructor(0) , evalFunction(0) + , callFunction(0) + , applyFunction(0) , objectPrototype(0) , functionPrototype(0) , arrayPrototype(0) @@ -75,6 +79,7 @@ namespace JSC { , numberPrototype(0) , datePrototype(0) , regExpPrototype(0) + , methodCallDummy(0) { } @@ -104,6 +109,8 @@ namespace JSC { NativeErrorConstructor* URIErrorConstructor; GlobalEvalFunction* evalFunction; + NativeFunctionWrapper* callFunction; + NativeFunctionWrapper* applyFunction; ObjectPrototype* objectPrototype; FunctionPrototype* functionPrototype; @@ -114,6 +121,8 @@ namespace JSC { DatePrototype* datePrototype; RegExpPrototype* regExpPrototype; + JSObject* methodCallDummy; + RefPtr<Structure> argumentsStructure; RefPtr<Structure> arrayStructure; RefPtr<Structure> booleanObjectStructure; @@ -161,8 +170,8 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable); - virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&); - virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes); + virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); + virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes); virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc); virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc); @@ -195,6 +204,8 @@ namespace JSC { DatePrototype* datePrototype() const { return d()->datePrototype; } RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; } + JSObject* methodCallDummy() const { return d()->methodCallDummy; } + Structure* argumentsStructure() const { return d()->argumentsStructure.get(); } Structure* arrayStructure() const { return d()->arrayStructure.get(); } Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); } @@ -214,10 +225,6 @@ namespace JSC { void setProfileGroup(unsigned value) { d()->profileGroup = value; } unsigned profileGroup() const { return d()->profileGroup; } - void setTimeoutTime(unsigned timeoutTime); - void startTimeoutCheck(); - void stopTimeoutCheck(); - Debugger* debugger() const { return d()->debugger; } void setDebugger(Debugger* debugger) { d()->debugger = debugger; } @@ -244,19 +251,19 @@ namespace JSC { void copyGlobalsFrom(RegisterFile&); void copyGlobalsTo(RegisterFile&); - void resetPrototype(JSValuePtr prototype); + void resetPrototype(JSValue prototype); JSGlobalData* globalData() { return d()->globalData.get(); } JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); } - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType)); } protected: struct GlobalPropertyInfo { - GlobalPropertyInfo(const Identifier& i, JSValuePtr v, unsigned a) + GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a) : identifier(i) , value(v) , attributes(a) @@ -264,7 +271,7 @@ namespace JSC { } const Identifier identifier; - JSValuePtr value; + JSValue value; unsigned attributes; }; void addStaticGlobals(GlobalPropertyInfo*, int count); @@ -272,16 +279,16 @@ namespace JSC { private: // FIXME: Fold reset into init. void init(JSObject* thisValue); - void reset(JSValuePtr prototype); + void reset(JSValue prototype); void setRegisters(Register* registers, Register* registerArray, size_t count); void* operator new(size_t); // can only be allocated with JSGlobalData }; - JSGlobalObject* asGlobalObject(JSValuePtr); + JSGlobalObject* asGlobalObject(JSValue); - inline JSGlobalObject* asGlobalObject(JSValuePtr value) + inline JSGlobalObject* asGlobalObject(JSValue value) { ASSERT(asObject(value)->isGlobalObject()); return static_cast<JSGlobalObject*>(asObject(value)); @@ -333,7 +340,7 @@ namespace JSC { return asGlobalObject(n->object); } - inline JSValuePtr Structure::prototypeForLookup(ExecState* exec) + inline JSValue Structure::prototypeForLookup(ExecState* exec) const { if (typeInfo().type() == ObjectType) return m_prototype; @@ -345,6 +352,32 @@ namespace JSC { return exec->lexicalGlobalObject()->numberPrototype(); } + inline StructureChain* Structure::prototypeChain(ExecState* exec) const + { + // We cache our prototype chain so our clients can share it. + if (!isValid(exec, m_cachedPrototypeChain.get())) { + JSValue prototype = prototypeForLookup(exec); + m_cachedPrototypeChain = StructureChain::create(prototype.isNull() ? 0 : asObject(prototype)->structure()); + } + return m_cachedPrototypeChain.get(); + } + + inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const + { + if (!cachedPrototypeChain) + return false; + + JSValue prototype = prototypeForLookup(exec); + RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head(); + while(*cachedStructure && !prototype.isNull()) { + if (asObject(prototype)->structure() != *cachedStructure) + return false; + ++cachedStructure; + prototype = asObject(prototype)->prototype(); + } + return prototype.isNull() && !*cachedStructure; + } + inline JSGlobalObject* ExecState::dynamicGlobalObject() { if (this == lexicalGlobalObject()->globalExec()) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index ecdddcf..b013957 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -28,6 +28,7 @@ #include "CallFrame.h" #include "GlobalEvalFunction.h" #include "JSGlobalObject.h" +#include "LiteralParser.h" #include "JSString.h" #include "Interpreter.h" #include "Parser.h" @@ -47,9 +48,9 @@ using namespace Unicode; namespace JSC { -static JSValuePtr encode(ExecState* exec, const ArgList& args, const char* doNotEscape) +static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEscape) { - UString str = args.at(exec, 0)->toString(exec); + UString str = args.at(0).toString(exec); CString cstr = str.UTF8String(true); if (!cstr.c_str()) return throwError(exec, URIError, "String contained an illegal UTF-16 sequence."); @@ -69,10 +70,10 @@ static JSValuePtr encode(ExecState* exec, const ArgList& args, const char* doNot return jsString(exec, result); } -static JSValuePtr decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict) +static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict) { UString result = ""; - UString str = args.at(exec, 0)->toString(exec); + UString str = args.at(0).toString(exec); int k = 0; int len = str.size(); const UChar* d = str.data(); @@ -268,18 +269,22 @@ static double parseFloat(const UString& s) return s.toDouble(true /*tolerant*/, false /* NaN for empty string */); } -JSValuePtr globalFuncEval(ExecState* exec, JSObject* function, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncEval(ExecState* exec, JSObject* function, JSValue thisValue, const ArgList& args) { - JSObject* thisObject = thisValue->toThisObject(exec); + JSObject* thisObject = thisValue.toThisObject(exec); JSObject* unwrappedObject = thisObject->unwrappedObject(); if (!unwrappedObject->isGlobalObject() || static_cast<JSGlobalObject*>(unwrappedObject)->evalFunction() != function) return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated"); - JSValuePtr x = args.at(exec, 0); - if (!x->isString()) + JSValue x = args.at(0); + if (!x.isString()) return x; - UString s = x->toString(exec); + UString s = x.toString(exec); + + LiteralParser preparser(exec, s); + if (JSValue parsedObject = preparser.tryLiteralParse()) + return parsedObject; int errLine; UString errMsg; @@ -293,42 +298,42 @@ JSValuePtr globalFuncEval(ExecState* exec, JSObject* function, JSValuePtr thisVa return exec->interpreter()->execute(evalNode.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot()); } -JSValuePtr globalFuncParseInt(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - JSValuePtr value = args.at(exec, 0); - int32_t radix = args.at(exec, 1)->toInt32(exec); + JSValue value = args.at(0); + int32_t radix = args.at(1).toInt32(exec); - if (value->isNumber() && (radix == 0 || radix == 10)) { - if (JSImmediate::isImmediate(value)) + if (value.isNumber() && (radix == 0 || radix == 10)) { + if (value.isInt32Fast()) return value; - double d = value->uncheckedGetNumber(); + double d = value.uncheckedGetNumber(); if (isfinite(d)) - return jsNumber(exec, floor(d)); + return jsNumber(exec, (d > 0) ? floor(d) : ceil(d)); if (isnan(d) || isinf(d)) return jsNaN(&exec->globalData()); - return JSImmediate::zeroImmediate(); + return jsNumber(exec, 0); } - return jsNumber(exec, parseInt(value->toString(exec), radix)); + return jsNumber(exec, parseInt(value.toString(exec), radix)); } -JSValuePtr globalFuncParseFloat(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, parseFloat(args.at(exec, 0)->toString(exec))); + return jsNumber(exec, parseFloat(args.at(0).toString(exec))); } -JSValuePtr globalFuncIsNaN(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsBoolean(isnan(args.at(exec, 0)->toNumber(exec))); + return jsBoolean(isnan(args.at(0).toNumber(exec))); } -JSValuePtr globalFuncIsFinite(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncIsFinite(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - double n = args.at(exec, 0)->toNumber(exec); + double n = args.at(0).toNumber(exec); return jsBoolean(!isnan(n) && !isinf(n)); } -JSValuePtr globalFuncDecodeURI(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue, const ArgList& args) { static const char do_not_unescape_when_decoding_URI[] = "#$&+,/:;=?@"; @@ -336,12 +341,12 @@ JSValuePtr globalFuncDecodeURI(ExecState* exec, JSObject*, JSValuePtr, const Arg return decode(exec, args, do_not_unescape_when_decoding_URI, true); } -JSValuePtr globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValue, const ArgList& args) { return decode(exec, args, "", true); } -JSValuePtr globalFuncEncodeURI(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue, const ArgList& args) { static const char do_not_escape_when_encoding_URI[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -352,7 +357,7 @@ JSValuePtr globalFuncEncodeURI(ExecState* exec, JSObject*, JSValuePtr, const Arg return encode(exec, args, do_not_escape_when_encoding_URI); } -JSValuePtr globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue, const ArgList& args) { static const char do_not_escape_when_encoding_URI_component[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -363,7 +368,7 @@ JSValuePtr globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValuePtr, return encode(exec, args, do_not_escape_when_encoding_URI_component); } -JSValuePtr globalFuncEscape(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, const ArgList& args) { static const char do_not_escape[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -373,7 +378,7 @@ JSValuePtr globalFuncEscape(ExecState* exec, JSObject*, JSValuePtr, const ArgLis UString result = ""; UString s; - UString str = args.at(exec, 0)->toString(exec); + UString str = args.at(0).toString(exec); const UChar* c = str.data(); for (int k = 0; k < str.size(); k++, c++) { int u = c[0]; @@ -394,22 +399,22 @@ JSValuePtr globalFuncEscape(ExecState* exec, JSObject*, JSValuePtr, const ArgLis return jsString(exec, result); } -JSValuePtr globalFuncUnescape(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, const ArgList& args) { UString result = ""; - UString str = args.at(exec, 0)->toString(exec); + UString str = args.at(0).toString(exec); int k = 0; int len = str.size(); while (k < len) { const UChar* c = str.data() + k; UChar u; if (c[0] == '%' && k <= len - 6 && c[1] == 'u') { - if (Lexer::isHexDigit(c[2]) && Lexer::isHexDigit(c[3]) && Lexer::isHexDigit(c[4]) && Lexer::isHexDigit(c[5])) { + if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) { u = Lexer::convertUnicode(c[2], c[3], c[4], c[5]); c = &u; k += 5; } - } else if (c[0] == '%' && k <= len - 3 && Lexer::isHexDigit(c[1]) && Lexer::isHexDigit(c[2])) { + } else if (c[0] == '%' && k <= len - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) { u = UChar(Lexer::convertHex(c[1], c[2])); c = &u; k += 2; @@ -422,10 +427,10 @@ JSValuePtr globalFuncUnescape(ExecState* exec, JSObject*, JSValuePtr, const ArgL } #ifndef NDEBUG -JSValuePtr globalFuncJSCPrint(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL globalFuncJSCPrint(ExecState* exec, JSObject*, JSValue, const ArgList& args) { CStringBuffer string; - args.at(exec, 0)->toString(exec).getCString(string); + args.at(0).toString(exec).getCString(string); puts(string.data()); return jsUndefined(); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.h index ea1f106..b1046f2 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.h @@ -24,34 +24,36 @@ #ifndef JSGlobalObjectFunctions_h #define JSGlobalObjectFunctions_h -#include "JSImmediate.h" // temporary until JSValue* becomes a class we can forward-declare +#include <wtf/unicode/Unicode.h> namespace JSC { class ArgList; class ExecState; class JSObject; + class JSValue; // FIXME: These functions should really be in JSGlobalObject.cpp, but putting them there // is a 0.5% reduction. - JSValuePtr globalFuncEval(ExecState*, JSObject*, JSValuePtr, const ArgList&); - JSValuePtr globalFuncParseInt(ExecState*, JSObject*, JSValuePtr, const ArgList&); - JSValuePtr globalFuncParseFloat(ExecState*, JSObject*, JSValuePtr, const ArgList&); - JSValuePtr globalFuncIsNaN(ExecState*, JSObject*, JSValuePtr, const ArgList&); - JSValuePtr globalFuncIsFinite(ExecState*, JSObject*, JSValuePtr, const ArgList&); - JSValuePtr globalFuncDecodeURI(ExecState*, JSObject*, JSValuePtr, const ArgList&); - JSValuePtr globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValuePtr, const ArgList&); - JSValuePtr globalFuncEncodeURI(ExecState*, JSObject*, JSValuePtr, const ArgList&); - JSValuePtr globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValuePtr, const ArgList&); - JSValuePtr globalFuncEscape(ExecState*, JSObject*, JSValuePtr, const ArgList&); - JSValuePtr globalFuncUnescape(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValue JSC_HOST_CALL globalFuncEval(ExecState*, JSObject*, JSValue, const ArgList&); + JSValue JSC_HOST_CALL globalFuncParseInt(ExecState*, JSObject*, JSValue, const ArgList&); + JSValue JSC_HOST_CALL globalFuncParseFloat(ExecState*, JSObject*, JSValue, const ArgList&); + JSValue JSC_HOST_CALL globalFuncIsNaN(ExecState*, JSObject*, JSValue, const ArgList&); + JSValue JSC_HOST_CALL globalFuncIsFinite(ExecState*, JSObject*, JSValue, const ArgList&); + JSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState*, JSObject*, JSValue, const ArgList&); + JSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValue, const ArgList&); + JSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState*, JSObject*, JSValue, const ArgList&); + JSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValue, const ArgList&); + JSValue JSC_HOST_CALL globalFuncEscape(ExecState*, JSObject*, JSValue, const ArgList&); + JSValue JSC_HOST_CALL globalFuncUnescape(ExecState*, JSObject*, JSValue, const ArgList&); #ifndef NDEBUG - JSValuePtr globalFuncJSCPrint(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValue JSC_HOST_CALL globalFuncJSCPrint(ExecState*, JSObject*, JSValue, const ArgList&); #endif static const double mantissaOverflowLowerBound = 9007199254740992.0; double parseIntOverflow(const char*, int length, int radix); + bool isStrWhiteSpace(UChar); } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.cpp index 09b3750..201e56c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.cpp @@ -32,35 +32,31 @@ namespace JSC { -JSObject* JSImmediate::toThisObject(JSValuePtr v, ExecState* exec) +JSObject* JSImmediate::toThisObject(JSValue v, ExecState* exec) { ASSERT(isImmediate(v)); if (isNumber(v)) - return constructNumberFromImmediateNumber(exec, v); + return constructNumber(exec, v); if (isBoolean(v)) return constructBooleanFromImmediateBoolean(exec, v); - if (v->isNull()) - return exec->globalThisValue(); - - JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull()); - exec->setException(exception); - return new (exec) JSNotAnObject(exec, exception); + ASSERT(v.isUndefinedOrNull()); + return exec->globalThisValue(); } -JSObject* JSImmediate::toObject(JSValuePtr v, ExecState* exec) +JSObject* JSImmediate::toObject(JSValue v, ExecState* exec) { ASSERT(isImmediate(v)); if (isNumber(v)) - return constructNumberFromImmediateNumber(exec, v); + return constructNumber(exec, v); if (isBoolean(v)) return constructBooleanFromImmediateBoolean(exec, v); - JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull()); + JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v.isNull()); exec->setException(exception); return new (exec) JSNotAnObject(exec, exception); } -JSObject* JSImmediate::prototype(JSValuePtr v, ExecState* exec) +JSObject* JSImmediate::prototype(JSValue v, ExecState* exec) { ASSERT(isImmediate(v)); if (isNumber(v)) @@ -68,23 +64,34 @@ JSObject* JSImmediate::prototype(JSValuePtr v, ExecState* exec) if (isBoolean(v)) return exec->lexicalGlobalObject()->booleanPrototype(); - JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull()); + JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v.isNull()); exec->setException(exception); return new (exec) JSNotAnObject(exec, exception); } -UString JSImmediate::toString(JSValuePtr v) +UString JSImmediate::toString(JSValue v) { ASSERT(isImmediate(v)); - if (isNumber(v)) + if (isIntegerNumber(v)) return UString::from(getTruncatedInt32(v)); +#if USE(ALTERNATE_JSIMMEDIATE) + if (isNumber(v)) { + ASSERT(isDoubleNumber(v)); + double value = doubleValue(v); + if (value == 0.0) // +0.0 or -0.0 + return "0"; + return UString::from(value); + } +#else + ASSERT(!isNumber(v)); +#endif if (jsBoolean(false) == v) return "false"; if (jsBoolean(true) == v) return "true"; - if (v->isNull()) + if (v.isNull()) return "null"; - ASSERT(v->isUndefined()); + ASSERT(v.isUndefined()); return "undefined"; } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.h index 37bca2a..706396e 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.h @@ -25,6 +25,7 @@ #include <wtf/Assertions.h> #include <wtf/AlwaysInline.h> #include <wtf/MathExtras.h> +#include <wtf/StdLibExtras.h> #include "JSValue.h" #include <limits> #include <limits.h> @@ -36,10 +37,23 @@ namespace JSC { class ExecState; class JSCell; + class JSFastMath; + class JSGlobalData; class JSObject; - class JSValue; class UString; +#if USE(ALTERNATE_JSIMMEDIATE) + inline intptr_t reinterpretDoubleToIntptr(double value) + { + return WTF::bitwise_cast<intptr_t>(value); + } + + inline double reinterpretIntptrToDouble(intptr_t value) + { + return WTF::bitwise_cast<double>(value); + } +#endif + /* * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging @@ -84,14 +98,33 @@ namespace JSC { /* * On 64-bit platforms, we support an alternative encoding form for immediates, if - * USE(ALTERNATE_JSIMMEDIATE) is defined. + * USE(ALTERNATE_JSIMMEDIATE) is defined. When this format is used, double precision + * floating point values may also be encoded as JSImmediates. + * + * The encoding makes use of unused NaN space in the IEEE754 representation. Any value + * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values + * can encode a 51-bit payload. Hardware produced and C-library payloads typically + * have a payload of zero. We assume that non-zero payloads are available to encode + * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are + * all set represents a NaN with a non-zero payload, we can use this space in the NaN + * ranges to encode other values (however there are also other ranges of NaN space that + * could have been selected). This range of NaN space is represented by 64-bit numbers + * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no + * valid double-precision numbers will begin fall in these ranges. * - * The top 16-bits denote the type: + * The scheme we have implemented encodes double precision values by adding 2^48 to the + * 64-bit integer representation of the number. After this manipulation, no encoded + * double-precision value will begin with the pattern 0x0000 or 0xFFFF. + * + * The top 16-bits denote the type of the encoded JSImmediate: * * Pointer: 0000:PPPP:PPPP:PPPP + * 0001:****:****:**** + * Double:{ ... + * FFFE:****:****:**** * Integer: FFFF:0000:IIII:IIII * - * 32-bit signed integers are marked with the 16-bit tag '0xFFFF'. The tag '0x0000' + * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. The tag 0x0000 * denotes a pointer, or another form of tagged immediate. Boolean, null and undefined * values are encoded in the same manner as the default format. */ @@ -99,14 +132,41 @@ namespace JSC { class JSImmediate { private: friend class JIT; - + friend class JSValue; + friend class JSFastMath; + friend JSValue jsNumber(ExecState* exec, double d); + friend JSValue jsNumber(ExecState*, char i); + friend JSValue jsNumber(ExecState*, unsigned char i); + friend JSValue jsNumber(ExecState*, short i); + friend JSValue jsNumber(ExecState*, unsigned short i); + friend JSValue jsNumber(ExecState* exec, int i); + friend JSValue jsNumber(ExecState* exec, unsigned i); + friend JSValue jsNumber(ExecState* exec, long i); + friend JSValue jsNumber(ExecState* exec, unsigned long i); + friend JSValue jsNumber(ExecState* exec, long long i); + friend JSValue jsNumber(ExecState* exec, unsigned long long i); + friend JSValue jsNumber(JSGlobalData* globalData, double d); + friend JSValue jsNumber(JSGlobalData* globalData, short i); + friend JSValue jsNumber(JSGlobalData* globalData, unsigned short i); + friend JSValue jsNumber(JSGlobalData* globalData, int i); + friend JSValue jsNumber(JSGlobalData* globalData, unsigned i); + friend JSValue jsNumber(JSGlobalData* globalData, long i); + friend JSValue jsNumber(JSGlobalData* globalData, unsigned long i); + friend JSValue jsNumber(JSGlobalData* globalData, long long i); + friend JSValue jsNumber(JSGlobalData* globalData, unsigned long long i); + #if USE(ALTERNATE_JSIMMEDIATE) - static const intptr_t TagTypeInteger = 0xffff000000000000ll; // bottom bit set indicates integer, this dominates the following bit + // If all bits in the mask are set, this indicates an integer number, + // if any but not all are set this value is a double precision number. + static const intptr_t TagTypeNumber = 0xffff000000000000ll; + // This value is 2^48, used to encode doubles such that the encoded value will begin + // with a 16-bit pattern within the range 0x0001..0xFFFE. + static const intptr_t DoubleEncodeOffset = 0x1000000000000ll; #else - static const intptr_t TagTypeInteger = 0x1; // bottom bit set indicates integer, this dominates the following bit + static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit #endif static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer - static const intptr_t TagMask = TagTypeInteger | TagBitTypeOther; + static const intptr_t TagMask = TagTypeNumber | TagBitTypeOther; static const intptr_t ExtendedTagMask = 0xC; // extended tag holds a further two bits static const intptr_t ExtendedTagBitBool = 0x4; @@ -128,157 +188,102 @@ namespace JSC { static const int32_t signBit = 0x80000000; - public: - static ALWAYS_INLINE bool isImmediate(JSValuePtr v) + static ALWAYS_INLINE bool isImmediate(JSValue v) { return rawValue(v) & TagMask; } - static ALWAYS_INLINE bool isNumber(JSValuePtr v) + static ALWAYS_INLINE bool isNumber(JSValue v) + { + return rawValue(v) & TagTypeNumber; + } + + static ALWAYS_INLINE bool isIntegerNumber(JSValue v) + { +#if USE(ALTERNATE_JSIMMEDIATE) + return (rawValue(v) & TagTypeNumber) == TagTypeNumber; +#else + return isNumber(v); +#endif + } + +#if USE(ALTERNATE_JSIMMEDIATE) + static ALWAYS_INLINE bool isDoubleNumber(JSValue v) { - return rawValue(v) & TagTypeInteger; + return isNumber(v) && !isIntegerNumber(v); } +#endif - static ALWAYS_INLINE bool isPositiveNumber(JSValuePtr v) + static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValue v) { // A single mask to check for the sign bit and the number tag all at once. - return (rawValue(v) & (signBit | TagTypeInteger)) == TagTypeInteger; + return (rawValue(v) & (signBit | TagTypeNumber)) == TagTypeNumber; } - static ALWAYS_INLINE bool isBoolean(JSValuePtr v) + static ALWAYS_INLINE bool isBoolean(JSValue v) { return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool; } - static ALWAYS_INLINE bool isUndefinedOrNull(JSValuePtr v) + static ALWAYS_INLINE bool isUndefinedOrNull(JSValue v) { // Undefined and null share the same value, bar the 'undefined' bit in the extended tag. return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull; } - static bool isNegative(JSValuePtr v) - { - ASSERT(isNumber(v)); - return rawValue(v) & signBit; - } - - static JSValuePtr from(char); - static JSValuePtr from(signed char); - static JSValuePtr from(unsigned char); - static JSValuePtr from(short); - static JSValuePtr from(unsigned short); - static JSValuePtr from(int); - static JSValuePtr from(unsigned); - static JSValuePtr from(long); - static JSValuePtr from(unsigned long); - static JSValuePtr from(long long); - static JSValuePtr from(unsigned long long); - static JSValuePtr from(double); - - static ALWAYS_INLINE bool isEitherImmediate(JSValuePtr v1, JSValuePtr v2) + static JSValue from(char); + static JSValue from(signed char); + static JSValue from(unsigned char); + static JSValue from(short); + static JSValue from(unsigned short); + static JSValue from(int); + static JSValue from(unsigned); + static JSValue from(long); + static JSValue from(unsigned long); + static JSValue from(long long); + static JSValue from(unsigned long long); + static JSValue from(double); + + static ALWAYS_INLINE bool isEitherImmediate(JSValue v1, JSValue v2) { return (rawValue(v1) | rawValue(v2)) & TagMask; } - static ALWAYS_INLINE bool isAnyImmediate(JSValuePtr v1, JSValuePtr v2, JSValuePtr v3) - { - return (rawValue(v1) | rawValue(v2) | rawValue(v3)) & TagMask; - } - - static ALWAYS_INLINE bool areBothImmediate(JSValuePtr v1, JSValuePtr v2) + static ALWAYS_INLINE bool areBothImmediate(JSValue v1, JSValue v2) { return isImmediate(v1) & isImmediate(v2); } - static ALWAYS_INLINE bool areBothImmediateNumbers(JSValuePtr v1, JSValuePtr v2) - { - return rawValue(v1) & rawValue(v2) & TagTypeInteger; - } - - static ALWAYS_INLINE JSValuePtr andImmediateNumbers(JSValuePtr v1, JSValuePtr v2) - { - ASSERT(areBothImmediateNumbers(v1, v2)); - return makeValue(rawValue(v1) & rawValue(v2)); - } - - static ALWAYS_INLINE JSValuePtr xorImmediateNumbers(JSValuePtr v1, JSValuePtr v2) - { - ASSERT(areBothImmediateNumbers(v1, v2)); - return makeValue((rawValue(v1) ^ rawValue(v2)) | TagTypeInteger); - } - - static ALWAYS_INLINE JSValuePtr orImmediateNumbers(JSValuePtr v1, JSValuePtr v2) - { - ASSERT(areBothImmediateNumbers(v1, v2)); - return makeValue(rawValue(v1) | rawValue(v2)); - } - - static ALWAYS_INLINE JSValuePtr rightShiftImmediateNumbers(JSValuePtr val, JSValuePtr shift) + static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValue v1, JSValue v2) { - ASSERT(areBothImmediateNumbers(val, shift)); #if USE(ALTERNATE_JSIMMEDIATE) - return makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(rawValue(val)) >> ((rawValue(shift) >> IntegerPayloadShift) & 0x1f))) | TagTypeInteger); + return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber; #else - return makeValue((rawValue(val) >> ((rawValue(shift) >> IntegerPayloadShift) & 0x1f)) | TagTypeInteger); + return rawValue(v1) & rawValue(v2) & TagTypeNumber; #endif } - static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValuePtr v) - { - // Number is non-negative and an operation involving two of these can't overflow. - // Checking for allowed negative numbers takes more time than it's worth on SunSpider. - return (rawValue(v) & (TagTypeInteger + (signBit | (signBit >> 1)))) == TagTypeInteger; - } - - static ALWAYS_INLINE JSValuePtr addImmediateNumbers(JSValuePtr v1, JSValuePtr v2) - { - ASSERT(canDoFastAdditiveOperations(v1)); - ASSERT(canDoFastAdditiveOperations(v2)); - return makeValue(rawValue(v1) + rawValue(v2) - TagTypeInteger); - } - - static ALWAYS_INLINE JSValuePtr subImmediateNumbers(JSValuePtr v1, JSValuePtr v2) - { - ASSERT(canDoFastAdditiveOperations(v1)); - ASSERT(canDoFastAdditiveOperations(v2)); - return makeValue(rawValue(v1) - rawValue(v2) + TagTypeInteger); - } - - static ALWAYS_INLINE JSValuePtr incImmediateNumber(JSValuePtr v) - { - ASSERT(canDoFastAdditiveOperations(v)); - return makeValue(rawValue(v) + (1 << IntegerPayloadShift)); - } - - static ALWAYS_INLINE JSValuePtr decImmediateNumber(JSValuePtr v) - { - ASSERT(canDoFastAdditiveOperations(v)); - return makeValue(rawValue(v) - (1 << IntegerPayloadShift)); - } - - static double toDouble(JSValuePtr); - static bool toBoolean(JSValuePtr); - static JSObject* toObject(JSValuePtr, ExecState*); - static JSObject* toThisObject(JSValuePtr, ExecState*); - static UString toString(JSValuePtr); + static double toDouble(JSValue); + static bool toBoolean(JSValue); + static JSObject* toObject(JSValue, ExecState*); + static JSObject* toThisObject(JSValue, ExecState*); + static UString toString(JSValue); - static bool getUInt32(JSValuePtr, uint32_t&); - static bool getTruncatedInt32(JSValuePtr, int32_t&); - static bool getTruncatedUInt32(JSValuePtr, uint32_t&); + static bool getUInt32(JSValue, uint32_t&); + static bool getTruncatedInt32(JSValue, int32_t&); + static bool getTruncatedUInt32(JSValue, uint32_t&); - static int32_t getTruncatedInt32(JSValuePtr); - static uint32_t getTruncatedUInt32(JSValuePtr); + static int32_t getTruncatedInt32(JSValue); + static uint32_t getTruncatedUInt32(JSValue); - static JSValuePtr trueImmediate(); - static JSValuePtr falseImmediate(); - static JSValuePtr undefinedImmediate(); - static JSValuePtr nullImmediate(); - static JSValuePtr zeroImmediate(); - static JSValuePtr oneImmediate(); + static JSValue trueImmediate(); + static JSValue falseImmediate(); + static JSValue undefinedImmediate(); + static JSValue nullImmediate(); + static JSValue zeroImmediate(); + static JSValue oneImmediate(); - static JSValuePtr impossibleValue(); - - static JSObject* prototype(JSValuePtr, ExecState*); + static JSObject* prototype(JSValue, ExecState*); private: #if USE(ALTERNATE_JSIMMEDIATE) @@ -290,51 +295,71 @@ namespace JSC { #endif static const unsigned maxImmediateUInt = maxImmediateInt; - static ALWAYS_INLINE JSValuePtr makeValue(intptr_t integer) + static ALWAYS_INLINE JSValue makeValue(intptr_t integer) { - return JSValuePtr::makeImmediate(integer); + return JSValue::makeImmediate(integer); } + // With USE(ALTERNATE_JSIMMEDIATE) we want the argument to be zero extended, so the + // integer doesn't interfere with the tag bits in the upper word. In the default encoding, + // if intptr_t id larger then int32_t we sign extend the value through the upper word. #if USE(ALTERNATE_JSIMMEDIATE) - static ALWAYS_INLINE JSValuePtr makeInt(uint32_t value) + static ALWAYS_INLINE JSValue makeInt(uint32_t value) #else - static ALWAYS_INLINE JSValuePtr makeInt(int32_t value) + static ALWAYS_INLINE JSValue makeInt(int32_t value) #endif { - return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeInteger); + return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber); + } + +#if USE(ALTERNATE_JSIMMEDIATE) + static ALWAYS_INLINE JSValue makeDouble(double value) + { + return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset); } +#endif - static ALWAYS_INLINE JSValuePtr makeBool(bool b) + static ALWAYS_INLINE JSValue makeBool(bool b) { return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool); } - static ALWAYS_INLINE JSValuePtr makeUndefined() + static ALWAYS_INLINE JSValue makeUndefined() { return makeValue(FullTagTypeUndefined); } - static ALWAYS_INLINE JSValuePtr makeNull() + static ALWAYS_INLINE JSValue makeNull() { return makeValue(FullTagTypeNull); } - - static ALWAYS_INLINE int32_t intValue(JSValuePtr v) + + template<typename T> + static JSValue fromNumberOutsideIntegerRange(T); + +#if USE(ALTERNATE_JSIMMEDIATE) + static ALWAYS_INLINE double doubleValue(JSValue v) + { + return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset); + } +#endif + + static ALWAYS_INLINE int32_t intValue(JSValue v) { return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift); } - static ALWAYS_INLINE uint32_t uintValue(JSValuePtr v) + static ALWAYS_INLINE uint32_t uintValue(JSValue v) { return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift); } - static ALWAYS_INLINE bool boolValue(JSValuePtr v) + static ALWAYS_INLINE bool boolValue(JSValue v) { return rawValue(v) & ExtendedPayloadBitBoolValue; } - static ALWAYS_INLINE intptr_t rawValue(JSValuePtr v) + static ALWAYS_INLINE intptr_t rawValue(JSValue v) { return v.immediateValue(); } @@ -342,177 +367,204 @@ namespace JSC { static double nonInlineNaN(); }; - ALWAYS_INLINE JSValuePtr JSImmediate::trueImmediate() { return makeBool(true); } - ALWAYS_INLINE JSValuePtr JSImmediate::falseImmediate() { return makeBool(false); } - ALWAYS_INLINE JSValuePtr JSImmediate::undefinedImmediate() { return makeUndefined(); } - ALWAYS_INLINE JSValuePtr JSImmediate::nullImmediate() { return makeNull(); } - ALWAYS_INLINE JSValuePtr JSImmediate::zeroImmediate() { return makeInt(0); } - ALWAYS_INLINE JSValuePtr JSImmediate::oneImmediate() { return makeInt(1); } + ALWAYS_INLINE JSValue JSImmediate::trueImmediate() { return makeBool(true); } + ALWAYS_INLINE JSValue JSImmediate::falseImmediate() { return makeBool(false); } + ALWAYS_INLINE JSValue JSImmediate::undefinedImmediate() { return makeUndefined(); } + ALWAYS_INLINE JSValue JSImmediate::nullImmediate() { return makeNull(); } + ALWAYS_INLINE JSValue JSImmediate::zeroImmediate() { return makeInt(0); } + ALWAYS_INLINE JSValue JSImmediate::oneImmediate() { return makeInt(1); } - // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate - ALWAYS_INLINE JSValuePtr JSImmediate::impossibleValue() { return makeValue(0x4); } +#if USE(ALTERNATE_JSIMMEDIATE) + inline bool doubleToBoolean(double value) + { + return value < 0.0 || value > 0.0; + } - ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v) + ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v) + { + ASSERT(isImmediate(v)); + return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate() + : doubleToBoolean(doubleValue(v)) : v == trueImmediate(); + } +#else + ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v) { ASSERT(isImmediate(v)); - intptr_t bits = rawValue(v); - return (bits & TagTypeInteger) - ? bits != TagTypeInteger // !0 ints - : bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue); // bool true + return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate(); } +#endif - ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValuePtr v) + ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue v) { - ASSERT(isNumber(v)); + // FIXME: should probably be asserting isPositiveIntegerNumber here. + ASSERT(isIntegerNumber(v)); return intValue(v); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(char i) +#if USE(ALTERNATE_JSIMMEDIATE) + template<typename T> + inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T value) + { + return makeDouble(static_cast<double>(value)); + } +#else + template<typename T> + inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T) + { + return JSValue(); + } +#endif + + ALWAYS_INLINE JSValue JSImmediate::from(char i) { return makeInt(i); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(signed char i) + ALWAYS_INLINE JSValue JSImmediate::from(signed char i) { return makeInt(i); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned char i) + ALWAYS_INLINE JSValue JSImmediate::from(unsigned char i) { return makeInt(i); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(short i) + ALWAYS_INLINE JSValue JSImmediate::from(short i) { return makeInt(i); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned short i) + ALWAYS_INLINE JSValue JSImmediate::from(unsigned short i) { return makeInt(i); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(int i) + ALWAYS_INLINE JSValue JSImmediate::from(int i) { +#if !USE(ALTERNATE_JSIMMEDIATE) if ((i < minImmediateInt) | (i > maxImmediateInt)) - return noValue(); + return fromNumberOutsideIntegerRange(i); +#endif return makeInt(i); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned i) + ALWAYS_INLINE JSValue JSImmediate::from(unsigned i) { if (i > maxImmediateUInt) - return noValue(); + return fromNumberOutsideIntegerRange(i); return makeInt(i); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(long i) + ALWAYS_INLINE JSValue JSImmediate::from(long i) { if ((i < minImmediateInt) | (i > maxImmediateInt)) - return noValue(); + return fromNumberOutsideIntegerRange(i); return makeInt(i); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long i) + ALWAYS_INLINE JSValue JSImmediate::from(unsigned long i) { if (i > maxImmediateUInt) - return noValue(); + return fromNumberOutsideIntegerRange(i); return makeInt(i); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(long long i) + ALWAYS_INLINE JSValue JSImmediate::from(long long i) { if ((i < minImmediateInt) | (i > maxImmediateInt)) - return noValue(); + return JSValue(); return makeInt(static_cast<intptr_t>(i)); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long long i) + ALWAYS_INLINE JSValue JSImmediate::from(unsigned long long i) { if (i > maxImmediateUInt) - return noValue(); + return fromNumberOutsideIntegerRange(i); return makeInt(static_cast<intptr_t>(i)); } - ALWAYS_INLINE JSValuePtr JSImmediate::from(double d) + ALWAYS_INLINE JSValue JSImmediate::from(double d) { const int intVal = static_cast<int>(d); - if ((intVal < minImmediateInt) | (intVal > maxImmediateInt)) - return noValue(); - // Check for data loss from conversion to int. if (intVal != d || (!intVal && signbit(d))) - return noValue(); + return fromNumberOutsideIntegerRange(d); - return makeInt(intVal); + return from(intVal); } - ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValuePtr v) + ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValue v) { - ASSERT(isNumber(v)); + ASSERT(isIntegerNumber(v)); return intValue(v); } - ALWAYS_INLINE double JSImmediate::toDouble(JSValuePtr v) + ALWAYS_INLINE double JSImmediate::toDouble(JSValue v) { ASSERT(isImmediate(v)); - int i; - if (isNumber(v)) - i = intValue(v); - else if (rawValue(v) == FullTagTypeUndefined) + + if (isIntegerNumber(v)) + return intValue(v); + +#if USE(ALTERNATE_JSIMMEDIATE) + if (isNumber(v)) { + ASSERT(isDoubleNumber(v)); + return doubleValue(v); + } +#else + ASSERT(!isNumber(v)); +#endif + + if (rawValue(v) == FullTagTypeUndefined) return nonInlineNaN(); - else - i = rawValue(v) >> ExtendedPayloadShift; - return i; + + ASSERT(JSImmediate::isBoolean(v) || (v == JSImmediate::nullImmediate())); + return rawValue(v) >> ExtendedPayloadShift; } - ALWAYS_INLINE bool JSImmediate::getUInt32(JSValuePtr v, uint32_t& i) + ALWAYS_INLINE bool JSImmediate::getUInt32(JSValue v, uint32_t& i) { i = uintValue(v); - return isPositiveNumber(v); + return isPositiveIntegerNumber(v); } - ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValuePtr v, int32_t& i) + ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValue v, int32_t& i) { i = intValue(v); - return isNumber(v); + return isIntegerNumber(v); } - ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValuePtr v, uint32_t& i) + ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValue v, uint32_t& i) { return getUInt32(v, i); } - inline JSValuePtr jsNull() - { - return JSImmediate::nullImmediate(); - } + // These are identical logic to the JSValue functions above, and faster than jsNumber(number).toInt32(). + int32_t toInt32(double); + uint32_t toUInt32(double); + int32_t toInt32SlowCase(double, bool& ok); + uint32_t toUInt32SlowCase(double, bool& ok); - inline JSValuePtr jsBoolean(bool b) + inline JSValue::JSValue(JSNullTag) { - return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate(); + *this = JSImmediate::nullImmediate(); } - - inline JSValuePtr jsUndefined() + + inline JSValue::JSValue(JSUndefinedTag) { - return JSImmediate::undefinedImmediate(); + *this = JSImmediate::undefinedImmediate(); } - // These are identical logic to the JSValue functions above, and faster than jsNumber(number)->toInt32(). - int32_t toInt32(double); - uint32_t toUInt32(double); - int32_t toInt32SlowCase(double, bool& ok); - uint32_t toUInt32SlowCase(double, bool& ok); - - inline bool JSValue::isUndefined() const + inline JSValue::JSValue(JSTrueTag) { - return asValue() == jsUndefined(); + *this = JSImmediate::trueImmediate(); } - inline bool JSValue::isNull() const + inline JSValue::JSValue(JSFalseTag) { - return asValue() == jsNull(); + *this = JSImmediate::falseImmediate(); } inline bool JSValue::isUndefinedOrNull() const @@ -545,8 +597,8 @@ namespace JSC { int32_t i; if (getTruncatedInt32(i)) return i; - bool ok; - return toInt32SlowCase(exec, ok); + bool ignored; + return toInt32SlowCase(toNumber(exec), ignored); } inline uint32_t JSValue::toUInt32(ExecState* exec) const @@ -554,8 +606,8 @@ namespace JSC { uint32_t i; if (getTruncatedUInt32(i)) return i; - bool ok; - return toUInt32SlowCase(exec, ok); + bool ignored; + return toUInt32SlowCase(toNumber(exec), ignored); } inline int32_t toInt32(double val) @@ -583,7 +635,7 @@ namespace JSC { ok = true; return i; } - return toInt32SlowCase(exec, ok); + return toInt32SlowCase(toNumber(exec), ok); } inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const @@ -593,9 +645,142 @@ namespace JSC { ok = true; return i; } - return toUInt32SlowCase(exec, ok); + return toUInt32SlowCase(toNumber(exec), ok); + } + + inline bool JSValue::isCell() const + { + return !JSImmediate::isImmediate(asValue()); + } + + inline bool JSValue::isInt32Fast() const + { + return JSImmediate::isIntegerNumber(asValue()); + } + + inline int32_t JSValue::getInt32Fast() const + { + ASSERT(isInt32Fast()); + return JSImmediate::getTruncatedInt32(asValue()); + } + + inline bool JSValue::isUInt32Fast() const + { + return JSImmediate::isPositiveIntegerNumber(asValue()); + } + + inline uint32_t JSValue::getUInt32Fast() const + { + ASSERT(isUInt32Fast()); + return JSImmediate::getTruncatedUInt32(asValue()); + } + + inline JSValue JSValue::makeInt32Fast(int32_t i) + { + return JSImmediate::from(i); + } + + inline bool JSValue::areBothInt32Fast(JSValue v1, JSValue v2) + { + return JSImmediate::areBothImmediateIntegerNumbers(v1, v2); } + class JSFastMath { + public: + static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValue v1, JSValue v2) + { + return JSImmediate::areBothImmediateIntegerNumbers(v1, v2); + } + + static ALWAYS_INLINE JSValue equal(JSValue v1, JSValue v2) + { + ASSERT(canDoFastBitwiseOperations(v1, v2)); + return jsBoolean(v1 == v2); + } + + static ALWAYS_INLINE JSValue notEqual(JSValue v1, JSValue v2) + { + ASSERT(canDoFastBitwiseOperations(v1, v2)); + return jsBoolean(v1 != v2); + } + + static ALWAYS_INLINE JSValue andImmediateNumbers(JSValue v1, JSValue v2) + { + ASSERT(canDoFastBitwiseOperations(v1, v2)); + return JSImmediate::makeValue(JSImmediate::rawValue(v1) & JSImmediate::rawValue(v2)); + } + + static ALWAYS_INLINE JSValue xorImmediateNumbers(JSValue v1, JSValue v2) + { + ASSERT(canDoFastBitwiseOperations(v1, v2)); + return JSImmediate::makeValue((JSImmediate::rawValue(v1) ^ JSImmediate::rawValue(v2)) | JSImmediate::TagTypeNumber); + } + + static ALWAYS_INLINE JSValue orImmediateNumbers(JSValue v1, JSValue v2) + { + ASSERT(canDoFastBitwiseOperations(v1, v2)); + return JSImmediate::makeValue(JSImmediate::rawValue(v1) | JSImmediate::rawValue(v2)); + } + + static ALWAYS_INLINE bool canDoFastRshift(JSValue v1, JSValue v2) + { + return JSImmediate::areBothImmediateIntegerNumbers(v1, v2); + } + + static ALWAYS_INLINE bool canDoFastUrshift(JSValue v1, JSValue v2) + { + return JSImmediate::areBothImmediateIntegerNumbers(v1, v2) && !(JSImmediate::rawValue(v1) & JSImmediate::signBit); + } + + static ALWAYS_INLINE JSValue rightShiftImmediateNumbers(JSValue val, JSValue shift) + { + ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift)); +#if USE(ALTERNATE_JSIMMEDIATE) + return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val)) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f))) | JSImmediate::TagTypeNumber); +#else + return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber); +#endif + } + + static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v) + { + // Number is non-negative and an operation involving two of these can't overflow. + // Checking for allowed negative numbers takes more time than it's worth on SunSpider. + return (JSImmediate::rawValue(v) & (JSImmediate::TagTypeNumber + (JSImmediate::signBit | (JSImmediate::signBit >> 1)))) == JSImmediate::TagTypeNumber; + } + + static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v1, JSValue v2) + { + // Number is non-negative and an operation involving two of these can't overflow. + // Checking for allowed negative numbers takes more time than it's worth on SunSpider. + return canDoFastAdditiveOperations(v1) && canDoFastAdditiveOperations(v2); + } + + static ALWAYS_INLINE JSValue addImmediateNumbers(JSValue v1, JSValue v2) + { + ASSERT(canDoFastAdditiveOperations(v1, v2)); + return JSImmediate::makeValue(JSImmediate::rawValue(v1) + JSImmediate::rawValue(v2) - JSImmediate::TagTypeNumber); + } + + static ALWAYS_INLINE JSValue subImmediateNumbers(JSValue v1, JSValue v2) + { + ASSERT(canDoFastAdditiveOperations(v1, v2)); + return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeNumber); + } + + static ALWAYS_INLINE JSValue incImmediateNumber(JSValue v) + { + ASSERT(canDoFastAdditiveOperations(v)); + return JSImmediate::makeValue(JSImmediate::rawValue(v) + (1 << JSImmediate::IntegerPayloadShift)); + } + + static ALWAYS_INLINE JSValue decImmediateNumber(JSValue v) + { + ASSERT(canDoFastAdditiveOperations(v)); + return JSImmediate::makeValue(JSImmediate::rawValue(v) - (1 << JSImmediate::IntegerPayloadShift)); + } + }; + } // namespace JSC #endif // JSImmediate_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSLock.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSLock.cpp index 5662a41..7ece5da 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSLock.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSLock.cpp @@ -119,11 +119,58 @@ bool JSLock::currentThreadIsHoldingLock() return !!pthread_getspecific(JSLockCount); } +// This is fairly nasty. We allow multiple threads to run on the same +// context, and we do not require any locking semantics in doing so - +// clients of the API may simply use the context from multiple threads +// concurently, and assume this will work. In order to make this work, +// We lock the context when a thread enters, and unlock it when it leaves. +// However we do not only unlock when the thread returns from its +// entry point (evaluate script or call function), we also unlock the +// context if the thread leaves JSC by making a call out to an external +// function through a callback. +// +// All threads using the context share the same JS stack (the RegisterFile). +// Whenever a thread calls into JSC it starts using the RegisterFile from the +// previous 'high water mark' - the maximum point the stack has ever grown to +// (returned by RegisterFile::end()). So if a first thread calls out to a +// callback, and a second thread enters JSC, then also exits by calling out +// to a callback, we can be left with stackframes from both threads in the +// RegisterFile. As such, a problem may occur should the first thread's +// callback complete first, and attempt to return to JSC. Were we to allow +// this to happen, and were its stack to grow further, then it may potentially +// write over the second thread's call frames. +// +// In avoid JS stack corruption we enforce a policy of only ever allowing two +// threads to use a JS context concurrently, and only allowing the second of +// these threads to execute until it has completed and fully returned from its +// outermost call into JSC. We enforce this policy using 'lockDropDepth'. The +// first time a thread exits it will call DropAllLocks - which will do as expected +// and drop locks allowing another thread to enter. Should another thread, or the +// same thread again, enter JSC (through evaluate script or call function), and exit +// again through a callback, then the locks will not be dropped when DropAllLocks +// is called (since lockDropDepth is non-zero). Since this thread is still holding +// the locks, only it will re able to re-enter JSC (either be returning from the +// callback, or by re-entering through another call to evaulate script or call +// function). +// +// This policy is slightly more restricive than it needs to be for correctness - +// we could validly allow futher entries into JSC from other threads, we only +// need ensure that callbacks return in the reverse chronological order of the +// order in which they were made - though implementing the less restrictive policy +// would likely increase complexity and overhead. +// +static unsigned lockDropDepth = 0; + JSLock::DropAllLocks::DropAllLocks(ExecState* exec) : m_lockingForReal(exec->globalData().isSharedInstance) { pthread_once(&createJSLockCountOnce, createJSLockCount); + if (lockDropDepth++) { + m_lockCount = 0; + return; + } + m_lockCount = JSLock::lockCount(); for (intptr_t i = 0; i < m_lockCount; i++) JSLock::unlock(m_lockingForReal); @@ -134,6 +181,11 @@ JSLock::DropAllLocks::DropAllLocks(bool lockingForReal) { pthread_once(&createJSLockCountOnce, createJSLockCount); + if (lockDropDepth++) { + m_lockCount = 0; + return; + } + // It is necessary to drop even "unreal" locks, because having a non-zero lock count // will prevent a real lock from being taken. @@ -146,6 +198,8 @@ JSLock::DropAllLocks::~DropAllLocks() { for (intptr_t i = 0; i < m_lockCount; i++) JSLock::lock(m_lockingForReal); + + --lockDropDepth; } #else diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.cpp index d4310fc..937dc2b 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.cpp @@ -37,13 +37,13 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject); // JSValue methods -JSValuePtr JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const +JSValue JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const { ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return m_exception; } -bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValuePtr&) +bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValue&) { ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return false; @@ -69,8 +69,7 @@ UString JSNotAnObject::toString(ExecState* exec) const JSObject* JSNotAnObject::toObject(ExecState* exec) const { - UNUSED_PARAM(exec); - ASSERT(exec->hadException() && exec->exception() == m_exception); + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); return m_exception; } @@ -95,12 +94,12 @@ bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&) return false; } -void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValuePtr, PutPropertySlot&) +void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue, PutPropertySlot&) { ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); } -void JSNotAnObject::put(ExecState* exec, unsigned, JSValuePtr) +void JSNotAnObject::put(ExecState* exec, unsigned, JSValue) { ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.h index c69593f..a8e36bd 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.h @@ -60,15 +60,15 @@ namespace JSC { { } - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType)); } private: // JSValue methods - virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&); + virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; @@ -81,8 +81,8 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValuePtr); + virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + virtual void put(ExecState*, unsigned propertyName, JSValue); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNumberCell.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNumberCell.cpp index efda0c6..669440b 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNumberCell.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNumberCell.cpp @@ -28,12 +28,14 @@ namespace JSC { -JSValuePtr JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const +#if !USE(ALTERNATE_JSIMMEDIATE) + +JSValue JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const { return const_cast<JSNumberCell*>(this); } -bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value) +bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValue& value) { number = m_value; value = this; @@ -96,29 +98,40 @@ bool JSNumberCell::getTruncatedUInt32(uint32_t& uint32) const return true; } -JSValuePtr JSNumberCell::getJSNumber() +JSValue JSNumberCell::getJSNumber() { return this; } -NEVER_INLINE JSValuePtr jsNumberCell(ExecState* exec, double d) +JSValue jsNumberCell(ExecState* exec, double d) { return new (exec) JSNumberCell(exec, d); } -NEVER_INLINE JSValuePtr jsNaN(ExecState* exec) +JSValue jsNumberCell(JSGlobalData* globalData, double d) { - return new (exec) JSNumberCell(exec, NaN); + return new (globalData) JSNumberCell(globalData, d); } -NEVER_INLINE JSValuePtr jsNumberCell(JSGlobalData* globalData, double d) +JSValue jsAPIMangledNumber(ExecState* exec, double d) { - return new (globalData) JSNumberCell(globalData, d); + return new (exec) JSNumberCell(JSNumberCell::APIMangled, d); +} + +#else + +JSValue jsNumberCell(ExecState*, double) +{ + ASSERT_NOT_REACHED(); + return JSValue(); } -NEVER_INLINE JSValuePtr jsNaN(JSGlobalData* globalData) +JSValue jsAPIMangledNumber(ExecState*, double) { - return new (globalData) JSNumberCell(globalData, NaN); + ASSERT_NOT_REACHED(); + return JSValue(); } +#endif + } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNumberCell.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNumberCell.h index 00d190d..a35e210 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNumberCell.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNumberCell.h @@ -32,6 +32,14 @@ namespace JSC { + extern const double NaN; + extern const double Inf; + + JSValue jsNumberCell(ExecState*, double); + JSValue jsAPIMangledNumber(ExecState*, double); + +#if !USE(ALTERNATE_JSIMMEDIATE) + class Identifier; class JSCell; class JSObject; @@ -43,15 +51,14 @@ namespace JSC { class JSNumberCell : public JSCell { friend class JIT; - friend JSValuePtr jsNumberCell(JSGlobalData*, double); - friend JSValuePtr jsNaN(JSGlobalData*); - friend JSValuePtr jsNumberCell(ExecState*, double); - friend JSValuePtr jsNaN(ExecState*); + friend JSValue jsNumberCell(JSGlobalData*, double); + friend JSValue jsNumberCell(ExecState*, double); + friend JSValue jsAPIMangledNumber(ExecState*, double); public: double value() const { return m_value; } - virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value); + virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; @@ -59,10 +66,10 @@ namespace JSC { virtual UString toThisString(ExecState*) const; virtual JSObject* toThisObject(ExecState*) const; - virtual JSValuePtr getJSNumber(); + virtual JSValue getJSNumber(); - int32_t toInt32() const; - uint32_t toUInt32() const; + static const uintptr_t JSAPIMangledMagicNumber = 0xbbadbeef; + bool isAPIMangledNumber() const { return m_structure == reinterpret_cast<Structure*>(JSAPIMangledMagicNumber); } void* operator new(size_t size, ExecState* exec) { @@ -82,7 +89,7 @@ namespace JSC { #endif } - static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion)); } private: JSNumberCell(JSGlobalData* globalData, double value) @@ -97,6 +104,13 @@ namespace JSC { { } + enum APIMangledTag { APIMangled }; + JSNumberCell(APIMangledTag, double value) + : JSCell(reinterpret_cast<Structure*>(JSAPIMangledMagicNumber)) + , m_value(value) + { + } + virtual bool getUInt32(uint32_t&) const; virtual bool getTruncatedInt32(int32_t&) const; virtual bool getTruncatedUInt32(uint32_t&) const; @@ -104,157 +118,361 @@ namespace JSC { double m_value; }; - extern const double NaN; - extern const double Inf; + JSValue jsNumberCell(JSGlobalData*, double); - JSNumberCell* asNumberCell(JSValuePtr); + inline bool isNumberCell(JSValue v) + { + return v.isCell() && v.asCell()->isNumber(); + } + + inline JSNumberCell* asNumberCell(JSValue v) + { + ASSERT(isNumberCell(v)); + return static_cast<JSNumberCell*>(v.asCell()); + } - JSValuePtr jsNumberCell(JSGlobalData*, double); - JSValuePtr jsNaN(JSGlobalData*); - JSValuePtr jsNumberCell(ExecState*, double); - JSValuePtr jsNaN(ExecState*); - inline JSNumberCell* asNumberCell(JSValuePtr value) + inline JSValue::JSValue(ExecState* exec, double d) { - ASSERT(asCell(value)->isNumber()); - return static_cast<JSNumberCell*>(asCell(value)); + JSValue v = JSImmediate::from(d); + *this = v ? v : jsNumberCell(exec, d); } - ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, double d) + inline JSValue::JSValue(ExecState* exec, int i) { - JSValuePtr v = JSImmediate::from(d); - return v ? v : jsNumberCell(exec, d); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(exec, i); } - ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, short i) + inline JSValue::JSValue(ExecState* exec, unsigned i) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(exec, i); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(exec, i); } - ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned short i) + inline JSValue::JSValue(ExecState* exec, long i) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(exec, i); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(exec, i); } - ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, int i) + inline JSValue::JSValue(ExecState* exec, unsigned long i) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(exec, i); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(exec, i); } - ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned i) + inline JSValue::JSValue(ExecState* exec, long long i) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(exec, i); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(exec, static_cast<double>(i)); } - ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, long i) + inline JSValue::JSValue(ExecState* exec, unsigned long long i) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(exec, i); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(exec, static_cast<double>(i)); } - ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned long i) + inline JSValue::JSValue(JSGlobalData* globalData, double d) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(exec, i); + JSValue v = JSImmediate::from(d); + *this = v ? v : jsNumberCell(globalData, d); } - ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, long long i) + inline JSValue::JSValue(JSGlobalData* globalData, int i) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(exec, static_cast<double>(i)); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(globalData, i); } - ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned long long i) + inline JSValue::JSValue(JSGlobalData* globalData, unsigned i) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(exec, static_cast<double>(i)); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(globalData, i); } - ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, double d) + inline JSValue::JSValue(JSGlobalData* globalData, long i) { - JSValuePtr v = JSImmediate::from(d); - return v ? v : jsNumberCell(globalData, d); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(globalData, i); } - ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, short i) + inline JSValue::JSValue(JSGlobalData* globalData, unsigned long i) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, i); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(globalData, i); } - ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned short i) + inline JSValue::JSValue(JSGlobalData* globalData, long long i) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, i); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(globalData, static_cast<double>(i)); } - ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, int i) + inline JSValue::JSValue(JSGlobalData* globalData, unsigned long long i) { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, i); + JSValue v = JSImmediate::from(i); + *this = v ? v : jsNumberCell(globalData, static_cast<double>(i)); } - ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i) + inline bool JSValue::isDoubleNumber() const { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, i); + return isNumberCell(asValue()); } - ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long i) + inline double JSValue::getDoubleNumber() const { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, i); + return asNumberCell(asValue())->value(); } - ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i) + inline bool JSValue::isNumber() const { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, i); + return JSImmediate::isNumber(asValue()) || isDoubleNumber(); } - ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long long i) + inline double JSValue::uncheckedGetNumber() const { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, static_cast<double>(i)); + ASSERT(isNumber()); + return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : getDoubleNumber(); } - ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i) + inline bool JSValue::isAPIMangledNumber() { - JSValuePtr v = JSImmediate::from(i); - return v ? v : jsNumberCell(globalData, static_cast<double>(i)); + ASSERT(isNumber()); + return JSImmediate::isImmediate(asValue()) ? false : asNumberCell(asValue())->isAPIMangledNumber(); } - // --- JSValue inlines ---------------------------- +#else + + inline JSValue::JSValue(ExecState*, double d) + { + JSValue v = JSImmediate::from(d); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(ExecState*, int i) + { + JSValue v = JSImmediate::from(i); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(ExecState*, unsigned i) + { + JSValue v = JSImmediate::from(i); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(ExecState*, long i) + { + JSValue v = JSImmediate::from(i); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(ExecState*, unsigned long i) + { + JSValue v = JSImmediate::from(i); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(ExecState*, long long i) + { + JSValue v = JSImmediate::from(static_cast<double>(i)); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(ExecState*, unsigned long long i) + { + JSValue v = JSImmediate::from(static_cast<double>(i)); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(JSGlobalData*, double d) + { + JSValue v = JSImmediate::from(d); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(JSGlobalData*, int i) + { + JSValue v = JSImmediate::from(i); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(JSGlobalData*, unsigned i) + { + JSValue v = JSImmediate::from(i); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(JSGlobalData*, long i) + { + JSValue v = JSImmediate::from(i); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(JSGlobalData*, unsigned long i) + { + JSValue v = JSImmediate::from(i); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(JSGlobalData*, long long i) + { + JSValue v = JSImmediate::from(static_cast<double>(i)); + ASSERT(v); + *this = v; + } + + inline JSValue::JSValue(JSGlobalData*, unsigned long long i) + { + JSValue v = JSImmediate::from(static_cast<double>(i)); + ASSERT(v); + *this = v; + } + + inline bool JSValue::isDoubleNumber() const + { + return JSImmediate::isDoubleNumber(asValue()); + } + + inline double JSValue::getDoubleNumber() const + { + return JSImmediate::doubleValue(asValue()); + } + + inline bool JSValue::isNumber() const + { + return JSImmediate::isNumber(asValue()); + } inline double JSValue::uncheckedGetNumber() const { - ASSERT(JSImmediate::isImmediate(asValue()) || asCell()->isNumber()); - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asNumberCell(asValue())->value(); + ASSERT(isNumber()); + return JSImmediate::toDouble(asValue()); + } + +#endif + + inline JSValue::JSValue(ExecState*, char i) + { + ASSERT(JSImmediate::from(i)); + *this = JSImmediate::from(i); + } + + inline JSValue::JSValue(ExecState*, unsigned char i) + { + ASSERT(JSImmediate::from(i)); + *this = JSImmediate::from(i); + } + + inline JSValue::JSValue(ExecState*, short i) + { + ASSERT(JSImmediate::from(i)); + *this = JSImmediate::from(i); + } + + inline JSValue::JSValue(ExecState*, unsigned short i) + { + ASSERT(JSImmediate::from(i)); + *this = JSImmediate::from(i); + } + + inline JSValue::JSValue(JSGlobalData*, char i) + { + ASSERT(JSImmediate::from(i)); + *this = JSImmediate::from(i); + } + + inline JSValue::JSValue(JSGlobalData*, unsigned char i) + { + ASSERT(JSImmediate::from(i)); + *this = JSImmediate::from(i); } - inline int32_t JSNumberCell::toInt32() const + inline JSValue::JSValue(JSGlobalData*, short i) { - if (m_value >= -2147483648.0 && m_value < 2147483648.0) - return static_cast<int32_t>(m_value); - bool scratch; - return JSC::toInt32SlowCase(m_value, scratch); + ASSERT(JSImmediate::from(i)); + *this = JSImmediate::from(i); } - inline uint32_t JSNumberCell::toUInt32() const + inline JSValue::JSValue(JSGlobalData*, unsigned short i) { - if (m_value >= 0.0 && m_value < 4294967296.0) - return static_cast<uint32_t>(m_value); - bool scratch; - return JSC::toUInt32SlowCase(m_value, scratch); + ASSERT(JSImmediate::from(i)); + *this = JSImmediate::from(i); } - ALWAYS_INLINE JSValuePtr JSValue::toJSNumber(ExecState* exec) const + inline JSValue jsNaN(ExecState* exec) { - return JSImmediate::isNumber(asValue()) ? asValue() : jsNumber(exec, this->toNumber(exec)); + return jsNumber(exec, NaN); + } + + inline JSValue jsNaN(JSGlobalData* globalData) + { + return jsNumber(globalData, NaN); + } + + // --- JSValue inlines ---------------------------- + + ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const + { + return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec)); + } + + inline bool JSValue::getNumber(double &result) const + { + if (isInt32Fast()) + result = getInt32Fast(); + else if (LIKELY(isDoubleNumber())) + result = getDoubleNumber(); + else { + ASSERT(!isNumber()); + return false; + } + return true; + } + + inline bool JSValue::numberToInt32(int32_t& arg) + { + if (isInt32Fast()) + arg = getInt32Fast(); + else if (LIKELY(isDoubleNumber())) + arg = JSC::toInt32(getDoubleNumber()); + else { + ASSERT(!isNumber()); + return false; + } + return true; + } + + inline bool JSValue::numberToUInt32(uint32_t& arg) + { + if (isUInt32Fast()) + arg = getUInt32Fast(); + else if (LIKELY(isDoubleNumber())) + arg = JSC::toUInt32(getDoubleNumber()); + else if (isInt32Fast()) { + // FIXME: I think this case can be merged with the uint case; toUInt32SlowCase + // on a negative value is equivalent to simple static_casting. + bool ignored; + arg = toUInt32SlowCase(getInt32Fast(), ignored); + } else { + ASSERT(!isNumber()); + return false; + } + return true; } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp index d38c325..415c25d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp @@ -69,11 +69,13 @@ void JSObject::mark() JSCell::mark(); m_structure->mark(); + PropertyStorage storage = propertyStorage(); + size_t storageSize = m_structure->propertyStorageSize(); for (size_t i = 0; i < storageSize; ++i) { - JSValuePtr v = m_propertyStorage[i]; - if (!v->marked()) - v->mark(); + JSValue v = JSValue::decode(storage[i]); + if (!v.marked()) + v.mark(); } JSOBJECT_MARK_END(); @@ -98,18 +100,18 @@ static void throwSetterError(ExecState* exec) } // ECMA 8.6.2.2 -void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); if (propertyName == exec->propertyNames().underscoreProto) { // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla. - if (!value->isObject() && !value->isNull()) + if (!value.isObject() && !value.isNull()) return; - JSValuePtr nextPrototypeValue = value; - while (nextPrototypeValue && nextPrototypeValue->isObject()) { + JSValue nextPrototypeValue = value; + while (nextPrototypeValue && nextPrototypeValue.isObject()) { JSObject* nextPrototype = asObject(nextPrototypeValue)->unwrappedObject(); if (nextPrototype == this) { throwError(exec, GeneralError, "cyclic __proto__ value"); @@ -123,22 +125,23 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr v } // Check if there are any setters or getters in the prototype chain - JSValuePtr prototype; + JSValue prototype; for (JSObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) { prototype = obj->prototype(); - if (prototype->isNull()) { - putDirect(propertyName, value, 0, true, slot); + if (prototype.isNull()) { + putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot); return; } } unsigned attributes; - if ((m_structure->get(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly) + JSCell* specificValue; + if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) return; for (JSObject* obj = this; ; obj = asObject(prototype)) { - if (JSValuePtr gs = obj->getDirect(propertyName)) { - if (gs->isGetterSetter()) { + if (JSValue gs = obj->getDirect(propertyName)) { + if (gs.isGetterSetter()) { JSObject* setterFunc = asGetterSetter(gs)->setter(); if (!setterFunc) { throwSetterError(exec); @@ -147,7 +150,7 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr v CallData callData; CallType callType = setterFunc->getCallData(callData); - ArgList args; + MarkedArgumentBuffer args; args.append(value); call(exec, setterFunc, callType, callData, this, args); return; @@ -159,26 +162,31 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr v } prototype = obj->prototype(); - if (prototype->isNull()) + if (prototype.isNull()) break; } - putDirect(propertyName, value, 0, true, slot); + putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot); return; } -void JSObject::put(ExecState* exec, unsigned propertyName, JSValuePtr value) +void JSObject::put(ExecState* exec, unsigned propertyName, JSValue value) { PutPropertySlot slot; put(exec, Identifier::from(exec, propertyName), value, slot); } -void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes) +void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { - putDirect(propertyName, value, attributes); + putDirectInternal(exec->globalData(), propertyName, value, attributes, checkReadOnly, slot); } -void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValuePtr value, unsigned attributes) +void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) +{ + putDirectInternal(exec->globalData(), propertyName, value, attributes); +} + +void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes) { putWithAttributes(exec, Identifier::from(exec, propertyName), value, attributes); } @@ -199,7 +207,8 @@ bool JSObject::hasProperty(ExecState* exec, unsigned propertyName) const bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName) { unsigned attributes; - if (m_structure->get(propertyName, attributes) != WTF::notFound) { + JSCell* specificValue; + if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) { if ((attributes & DontDelete)) return false; removeDirect(propertyName); @@ -226,11 +235,11 @@ bool JSObject::deleteProperty(ExecState* exec, unsigned propertyName) return deleteProperty(exec, Identifier::from(exec, propertyName)); } -static ALWAYS_INLINE JSValuePtr callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName) +static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName) { - JSValuePtr function = object->get(exec, propertyName); + JSValue function = object->get(exec, propertyName); CallData callData; - CallType callType = function->getCallData(callData); + CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return exec->exception(); @@ -239,35 +248,35 @@ static ALWAYS_INLINE JSValuePtr callDefaultValueFunction(ExecState* exec, const if (exec->hadException()) return exec->exception(); - JSValuePtr result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList()); - ASSERT(!result->isGetterSetter()); + JSValue result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList()); + ASSERT(!result.isGetterSetter()); if (exec->hadException()) return exec->exception(); - if (result->isObject()) - return noValue(); + if (result.isObject()) + return JSValue(); return result; } -bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValuePtr& result) +bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result) { result = defaultValue(exec, PreferNumber); - number = result->toNumber(exec); - return !result->isString(); + number = result.toNumber(exec); + return !result.isString(); } // ECMA 8.6.2.6 -JSValuePtr JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const +JSValue JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const { // Must call toString first for Date objects. if ((hint == PreferString) || (hint != PreferNumber && prototype() == exec->lexicalGlobalObject()->datePrototype())) { - JSValuePtr value = callDefaultValueFunction(exec, this, exec->propertyNames().toString); + JSValue value = callDefaultValueFunction(exec, this, exec->propertyNames().toString); if (value) return value; value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf); if (value) return value; } else { - JSValuePtr value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf); + JSValue value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf); if (value) return value; value = callDefaultValueFunction(exec, this, exec->propertyNames().toString); @@ -293,8 +302,8 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction) { - JSValuePtr object = getDirect(propertyName); - if (object && object->isGetterSetter()) { + JSValue object = getDirect(propertyName); + if (object && object.isGetterSetter()) { ASSERT(m_structure->hasGetterSetterProperties()); asGetterSetter(object)->setGetter(getterFunction); return; @@ -302,7 +311,7 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO PutPropertySlot slot; GetterSetter* getterSetter = new (exec) GetterSetter; - putDirect(propertyName, getterSetter, None, true, slot); + putDirectInternal(exec->globalData(), propertyName, getterSetter, Getter, true, slot); // putDirect will change our Structure if we add a new property. For // getters and setters, though, we also need to change our Structure @@ -320,8 +329,8 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction) { - JSValuePtr object = getDirect(propertyName); - if (object && object->isGetterSetter()) { + JSValue object = getDirect(propertyName); + if (object && object.isGetterSetter()) { ASSERT(m_structure->hasGetterSetterProperties()); asGetterSetter(object)->setSetter(setterFunction); return; @@ -329,7 +338,7 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO PutPropertySlot slot; GetterSetter* getterSetter = new (exec) GetterSetter; - putDirect(propertyName, getterSetter, None, true, slot); + putDirectInternal(exec->globalData(), propertyName, getterSetter, Setter, true, slot); // putDirect will change our Structure if we add a new property. For // getters and setters, though, we also need to change our Structure @@ -345,12 +354,12 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO getterSetter->setSetter(setterFunction); } -JSValuePtr JSObject::lookupGetter(ExecState*, const Identifier& propertyName) +JSValue JSObject::lookupGetter(ExecState*, const Identifier& propertyName) { JSObject* object = this; while (true) { - if (JSValuePtr value = object->getDirect(propertyName)) { - if (!value->isGetterSetter()) + if (JSValue value = object->getDirect(propertyName)) { + if (!value.isGetterSetter()) return jsUndefined(); JSObject* functionObject = asGetterSetter(value)->getter(); if (!functionObject) @@ -358,18 +367,18 @@ JSValuePtr JSObject::lookupGetter(ExecState*, const Identifier& propertyName) return functionObject; } - if (!object->prototype() || !object->prototype()->isObject()) + if (!object->prototype() || !object->prototype().isObject()) return jsUndefined(); object = asObject(object->prototype()); } } -JSValuePtr JSObject::lookupSetter(ExecState*, const Identifier& propertyName) +JSValue JSObject::lookupSetter(ExecState*, const Identifier& propertyName) { JSObject* object = this; while (true) { - if (JSValuePtr value = object->getDirect(propertyName)) { - if (!value->isGetterSetter()) + if (JSValue value = object->getDirect(propertyName)) { + if (!value.isGetterSetter()) return jsUndefined(); JSObject* functionObject = asGetterSetter(value)->setter(); if (!functionObject) @@ -377,24 +386,24 @@ JSValuePtr JSObject::lookupSetter(ExecState*, const Identifier& propertyName) return functionObject; } - if (!object->prototype() || !object->prototype()->isObject()) + if (!object->prototype() || !object->prototype().isObject()) return jsUndefined(); object = asObject(object->prototype()); } } -bool JSObject::hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr proto) +bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue proto) { - if (!proto->isObject()) { - throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property."); + if (!value.isObject()) return false; - } - if (!value->isObject()) + if (!proto.isObject()) { + throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property."); return false; + } JSObject* object = asObject(value); - while ((object = object->prototype()->getObject())) { + while ((object = object->prototype().getObject())) { if (proto == object) return true; } @@ -411,7 +420,8 @@ bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyN bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const { - if (m_structure->get(propertyName, attributes) != WTF::notFound) + JSCell* specificValue; + if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) return true; // Look in the static hashtable of properties @@ -424,6 +434,19 @@ bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& property return false; } +bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyName, JSCell*& specificValue) const +{ + unsigned attributes; + if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) + return true; + + // This could be a function within the static table? - should probably + // also look in the hash? This currently should not be a problem, since + // we've currently always call 'get' first, which should have populated + // the normal storage. + return false; +} + void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) { m_structure->getEnumerablePropertyNames(exec, propertyNames, this); @@ -436,18 +459,18 @@ bool JSObject::toBoolean(ExecState*) const double JSObject::toNumber(ExecState* exec) const { - JSValuePtr primitive = toPrimitive(exec, PreferNumber); + JSValue primitive = toPrimitive(exec, PreferNumber); if (exec->hadException()) // should be picked up soon in Nodes.cpp return 0.0; - return primitive->toNumber(exec); + return primitive.toNumber(exec); } UString JSObject::toString(ExecState* exec) const { - JSValuePtr primitive = toPrimitive(exec, PreferString); + JSValue primitive = toPrimitive(exec, PreferString); if (exec->hadException()) return ""; - return primitive->toString(exec); + return primitive.toString(exec); } JSObject* JSObject::toObject(ExecState*) const @@ -471,27 +494,27 @@ void JSObject::removeDirect(const Identifier& propertyName) if (m_structure->isDictionary()) { offset = m_structure->removePropertyWithoutTransition(propertyName); if (offset != WTF::notFound) - m_propertyStorage[offset] = jsUndefined(); + putDirectOffset(offset, jsUndefined()); return; } RefPtr<Structure> structure = Structure::removePropertyTransition(m_structure, propertyName, offset); - if (offset != WTF::notFound) - m_propertyStorage[offset] = jsUndefined(); setStructure(structure.release()); + if (offset != WTF::notFound) + putDirectOffset(offset, jsUndefined()); } void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr) { - putDirect(Identifier(exec, function->name(&exec->globalData())), function, attr); + putDirectFunction(Identifier(exec, function->name(&exec->globalData())), function, attr); } void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr) { - putDirectWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr); + putDirectFunctionWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr); } -NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValuePtr* location) +NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue* location) { if (JSObject* getterFunction = asGetterSetter(*location)->getter()) slot.setGetterSlot(getterFunction); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h index 5918b9d..54805f2 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h @@ -32,9 +32,17 @@ #include "PutPropertySlot.h" #include "ScopeChain.h" #include "Structure.h" +#include "JSGlobalData.h" namespace JSC { + inline JSCell* getJSFunction(JSGlobalData& globalData, JSValue value) + { + if (value.isCell() && (value.asCell()->vptr() == globalData.jsFunctionVPtr)) + return value.asCell(); + return 0; + } + class InternalFunction; class PropertyNameArray; class Structure; @@ -49,9 +57,12 @@ namespace JSC { DontEnum = 1 << 2, // property doesn't appear in (for .. in ..) DontDelete = 1 << 3, // property can't be deleted Function = 1 << 4, // property is a function - only used by static hashtables + Getter = 1 << 5, // property is a getter + Setter = 1 << 6 // property is a setter }; - typedef JSValuePtr* PropertyStorage; + typedef EncodedJSValue* PropertyStorage; + typedef const EncodedJSValue* ConstPropertyStorage; class JSObject : public JSCell { friend class BatchedTransitionOptimizer; @@ -69,18 +80,16 @@ namespace JSC { bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); } - JSValuePtr prototype() const; - void setPrototype(JSValuePtr prototype); + JSValue prototype() const; + void setPrototype(JSValue prototype); void setStructure(PassRefPtr<Structure>); Structure* inheritorID(); - PropertyStorage& propertyStorage() { return m_propertyStorage; } - virtual UString className() const; - JSValuePtr get(ExecState*, const Identifier& propertyName) const; - JSValuePtr get(ExecState*, unsigned propertyName) const; + JSValue get(ExecState*, const Identifier& propertyName) const; + JSValue get(ExecState*, unsigned propertyName) const; bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); @@ -88,11 +97,12 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValuePtr value); + virtual void put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&); + virtual void put(ExecState*, unsigned propertyName, JSValue value); - virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes); - virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValuePtr value, unsigned attributes); + virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot); + virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes); + virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValue value, unsigned attributes); bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const; @@ -103,14 +113,14 @@ namespace JSC { virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); - virtual JSValuePtr defaultValue(ExecState*, PreferredPrimitiveType) const; + virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const; - virtual bool hasInstance(ExecState*, JSValuePtr, JSValuePtr prototypeProperty); + virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty); virtual void getPropertyNames(ExecState*, PropertyNameArray&); - virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value); + virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; @@ -120,34 +130,31 @@ namespace JSC { virtual JSObject* unwrappedObject(); virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; + bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const; // This get function only looks at the property map. - JSValuePtr getDirect(const Identifier& propertyName) const + JSValue getDirect(const Identifier& propertyName) const { size_t offset = m_structure->get(propertyName); - return offset != WTF::notFound ? m_propertyStorage[offset] : noValue(); + return offset != WTF::notFound ? getDirectOffset(offset) : JSValue(); } - JSValuePtr* getDirectLocation(const Identifier& propertyName) + JSValue* getDirectLocation(const Identifier& propertyName) { size_t offset = m_structure->get(propertyName); return offset != WTF::notFound ? locationForOffset(offset) : 0; } - JSValuePtr* getDirectLocation(const Identifier& propertyName, unsigned& attributes) + JSValue* getDirectLocation(const Identifier& propertyName, unsigned& attributes) { - size_t offset = m_structure->get(propertyName, attributes); + JSCell* specificFunction; + size_t offset = m_structure->get(propertyName, attributes, specificFunction); return offset != WTF::notFound ? locationForOffset(offset) : 0; } - size_t offsetForLocation(JSValuePtr* location) - { - return location - m_propertyStorage; - } - - JSValuePtr* locationForOffset(size_t offset) + size_t offsetForLocation(JSValue* location) const { - return &m_propertyStorage[offset]; + return location - reinterpret_cast<const JSValue*>(propertyStorage()); } void transitionTo(Structure*); @@ -156,36 +163,42 @@ namespace JSC { bool hasCustomProperties() { return !m_structure->isEmpty(); } bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); } - void putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attr = 0); - void putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); + void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); + void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0); + + void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0); + void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); void putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr = 0); - void putDirectWithoutTransition(const Identifier& propertyName, JSValuePtr value, unsigned attr = 0); + + void putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attr = 0); + void putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attr = 0); void putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr = 0); // Fast access to known property offsets. - JSValuePtr getDirectOffset(size_t offset) { return m_propertyStorage[offset]; } - void putDirectOffset(size_t offset, JSValuePtr value) { m_propertyStorage[offset] = value; } + JSValue getDirectOffset(size_t offset) const { return JSValue::decode(propertyStorage()[offset]); } + void putDirectOffset(size_t offset, JSValue value) { propertyStorage()[offset] = JSValue::encode(value); } - void fillGetterPropertySlot(PropertySlot&, JSValuePtr* location); + void fillGetterPropertySlot(PropertySlot&, JSValue* location); virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction); virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction); - virtual JSValuePtr lookupGetter(ExecState*, const Identifier& propertyName); - virtual JSValuePtr lookupSetter(ExecState*, const Identifier& propertyName); + virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName); + virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName); virtual bool isGlobalObject() const { return false; } virtual bool isVariableObject() const { return false; } + virtual bool isActivationObject() const { return false; } virtual bool isWatchdogException() const { return false; } virtual bool isNotAnObjectErrorStub() const { return false; } void allocatePropertyStorage(size_t oldSize, size_t newSize); void allocatePropertyStorageInline(size_t oldSize, size_t newSize); - bool usingInlineStorage() const { return m_propertyStorage == m_inlineStorage; } + bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); } - static const size_t inlineStorageCapacity = 2; + static const size_t inlineStorageCapacity = 3; static const size_t nonInlineBaseStorageCapacity = 16; - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); } @@ -194,6 +207,23 @@ namespace JSC { bool getOwnPropertySlotForWrite(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable); private: + ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } + PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } + + const JSValue* locationForOffset(size_t offset) const + { + return reinterpret_cast<const JSValue*>(&propertyStorage()[offset]); + } + + JSValue* locationForOffset(size_t offset) + { + return reinterpret_cast<JSValue*>(&propertyStorage()[offset]); + } + + void putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*); + void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); + void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr = 0); + bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const; @@ -201,15 +231,17 @@ namespace JSC { RefPtr<Structure> m_inheritorID; - PropertyStorage m_propertyStorage; - JSValuePtr m_inlineStorage[inlineStorageCapacity]; + union { + PropertyStorage m_externalStorage; + EncodedJSValue m_inlineStorage[inlineStorageCapacity]; + }; }; - JSObject* asObject(JSValuePtr); + JSObject* asObject(JSValue); JSObject* constructEmptyObject(ExecState*); -inline JSObject* asObject(JSValuePtr value) +inline JSObject* asObject(JSValue value) { ASSERT(asCell(value)->isObject()); return static_cast<JSObject*>(asCell(value)); @@ -217,28 +249,27 @@ inline JSObject* asObject(JSValuePtr value) inline JSObject::JSObject(PassRefPtr<Structure> structure) : JSCell(structure.releaseRef()) // ~JSObject balances this ref() - , m_propertyStorage(m_inlineStorage) { ASSERT(m_structure); ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity); ASSERT(m_structure->isEmpty()); - ASSERT(prototype()->isNull() || Heap::heap(this) == Heap::heap(prototype())); + ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); } inline JSObject::~JSObject() { ASSERT(m_structure); - if (m_propertyStorage != m_inlineStorage) - delete [] m_propertyStorage; + if (!isUsingInlineStorage()) + delete [] m_externalStorage; m_structure->deref(); } -inline JSValuePtr JSObject::prototype() const +inline JSValue JSObject::prototype() const { return m_structure->storedPrototype(); } -inline void JSObject::setPrototype(JSValuePtr prototype) +inline void JSObject::setPrototype(JSValue prototype) { ASSERT(prototype); RefPtr<Structure> newStructure = Structure::changePrototypeTransition(m_structure, prototype); @@ -258,6 +289,11 @@ inline Structure* JSObject::inheritorID() return createInheritorID(); } +inline bool Structure::isUsingInlineStorage() const +{ + return (propertyStorageCapacity() == JSObject::inlineStorageCapacity); +} + inline bool JSCell::isObject(const ClassInfo* info) const { for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) { @@ -270,13 +306,13 @@ inline bool JSCell::isObject(const ClassInfo* info) const // this method is here to be after the inline declaration of JSCell::isObject inline bool JSValue::isObject(const ClassInfo* classInfo) const { - return !JSImmediate::isImmediate(asValue()) && asCell()->isObject(classInfo); + return isCell() && asCell()->isObject(classInfo); } ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - if (JSValuePtr* location = getDirectLocation(propertyName)) { - if (m_structure->hasGetterSetterProperties() && location[0]->isGetterSetter()) + if (JSValue* location = getDirectLocation(propertyName)) { + if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter()) fillGetterPropertySlot(slot, location); else slot.setValueSlot(this, location, offsetForLocation(location)); @@ -295,8 +331,8 @@ ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Ide ALWAYS_INLINE bool JSObject::getOwnPropertySlotForWrite(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable) { unsigned attributes; - if (JSValuePtr* location = getDirectLocation(propertyName, attributes)) { - if (m_structure->hasGetterSetterProperties() && location[0]->isGetterSetter()) { + if (JSValue* location = getDirectLocation(propertyName, attributes)) { + if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter()) { slotIsWriteable = false; fillGetterPropertySlot(slot, location); } else { @@ -339,8 +375,8 @@ inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propert while (true) { if (object->fastGetOwnPropertySlot(exec, propertyName, slot)) return true; - JSValuePtr prototype = object->prototype(); - if (!prototype->isObject()) + JSValue prototype = object->prototype(); + if (!prototype.isObject()) return false; object = asObject(prototype); } @@ -352,14 +388,14 @@ inline bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, Pr while (true) { if (object->getOwnPropertySlot(exec, propertyName, slot)) return true; - JSValuePtr prototype = object->prototype(); - if (!prototype->isObject()) + JSValue prototype = object->prototype(); + if (!prototype.isObject()) return false; object = asObject(prototype); } } -inline JSValuePtr JSObject::get(ExecState* exec, const Identifier& propertyName) const +inline JSValue JSObject::get(ExecState* exec, const Identifier& propertyName) const { PropertySlot slot(this); if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot)) @@ -368,7 +404,7 @@ inline JSValuePtr JSObject::get(ExecState* exec, const Identifier& propertyName) return jsUndefined(); } -inline JSValuePtr JSObject::get(ExecState* exec, unsigned propertyName) const +inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const { PropertySlot slot(this); if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot)) @@ -377,80 +413,139 @@ inline JSValuePtr JSObject::get(ExecState* exec, unsigned propertyName) const return jsUndefined(); } -inline void JSObject::putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attr) -{ - PutPropertySlot slot; - putDirect(propertyName, value, attr, false, slot); -} - -inline void JSObject::putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction) { + ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); if (m_structure->isDictionary()) { unsigned currentAttributes; - size_t offset = m_structure->get(propertyName, currentAttributes); + JSCell* currentSpecificFunction; + size_t offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction); if (offset != WTF::notFound) { + if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) + m_structure->despecifyDictionaryFunction(propertyName); if (checkReadOnly && currentAttributes & ReadOnly) return; - m_propertyStorage[offset] = value; - slot.setExistingProperty(this, offset); + putDirectOffset(offset, value); + if (!specificFunction && !currentSpecificFunction) + slot.setExistingProperty(this, offset); return; } size_t currentCapacity = m_structure->propertyStorageCapacity(); - offset = m_structure->addPropertyWithoutTransition(propertyName, attributes); + offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, specificFunction); if (currentCapacity != m_structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); ASSERT(offset < m_structure->propertyStorageCapacity()); - m_propertyStorage[offset] = value; - slot.setNewProperty(this, offset); + putDirectOffset(offset, value); + // See comment on setNewProperty call below. + if (!specificFunction) + slot.setNewProperty(this, offset); return; } size_t offset; size_t currentCapacity = m_structure->propertyStorageCapacity(); - if (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, offset)) { + if (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, specificFunction, offset)) { if (currentCapacity != structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity()); ASSERT(offset < structure->propertyStorageCapacity()); - m_propertyStorage[offset] = value; - slot.setNewProperty(this, offset); - slot.setWasTransition(true); setStructure(structure.release()); + putDirectOffset(offset, value); + // See comment on setNewProperty call below. + if (!specificFunction) + slot.setNewProperty(this, offset); return; } unsigned currentAttributes; - offset = m_structure->get(propertyName, currentAttributes); + JSCell* currentSpecificFunction; + offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction); if (offset != WTF::notFound) { if (checkReadOnly && currentAttributes & ReadOnly) return; - m_propertyStorage[offset] = value; + + if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) { + setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName)); + putDirectOffset(offset, value); + // Function transitions are not currently cachable, so leave the slot in an uncachable state. + return; + } + putDirectOffset(offset, value); slot.setExistingProperty(this, offset); return; } - RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, offset); + RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset); if (currentCapacity != structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity()); ASSERT(offset < structure->propertyStorageCapacity()); - m_propertyStorage[offset] = value; - slot.setNewProperty(this, offset); - slot.setWasTransition(true); setStructure(structure.release()); + putDirectOffset(offset, value); + // Function transitions are not currently cachable, so leave the slot in an uncachable state. + if (!specificFunction) + slot.setNewProperty(this, offset); +} + +inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +{ + ASSERT(value); + ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + + putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value)); +} + +inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) +{ + PutPropertySlot slot; + putDirectInternal(propertyName, value, attributes, false, slot, getJSFunction(globalData, value)); +} + +inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +{ + ASSERT(value); + ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + + putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0); +} + +inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes) +{ + PutPropertySlot slot; + putDirectInternal(propertyName, value, attributes, false, slot, 0); +} + +inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +{ + putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, value); +} + +inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr) +{ + PutPropertySlot slot; + putDirectInternal(propertyName, value, attr, false, slot, value); +} + +inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attributes) +{ + size_t currentCapacity = m_structure->propertyStorageCapacity(); + size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, 0); + if (currentCapacity != m_structure->propertyStorageCapacity()) + allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); + putDirectOffset(offset, value); } -inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValuePtr value, unsigned attributes) +inline void JSObject::putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attributes) { size_t currentCapacity = m_structure->propertyStorageCapacity(); - size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes); + size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, value); if (currentCapacity != m_structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); - m_propertyStorage[offset] = value; + putDirectOffset(offset, value); } inline void JSObject::transitionTo(Structure* newStructure) @@ -460,21 +555,23 @@ inline void JSObject::transitionTo(Structure* newStructure) setStructure(newStructure); } -inline JSValuePtr JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const +inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const { return defaultValue(exec, preferredType); } -inline JSValuePtr JSValue::get(ExecState* exec, const Identifier& propertyName) const +inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName) const { - PropertySlot slot(this); + PropertySlot slot(asValue()); return get(exec, propertyName, slot); } -inline JSValuePtr JSValue::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const +inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) { + if (UNLIKELY(!isCell())) { JSObject* prototype = JSImmediate::prototype(asValue(), exec); + if (propertyName == exec->propertyNames().underscoreProto) + return prototype; if (!prototype->getPropertySlot(exec, propertyName, slot)) return jsUndefined(); return slot.getValue(exec, propertyName); @@ -484,22 +581,22 @@ inline JSValuePtr JSValue::get(ExecState* exec, const Identifier& propertyName, if (cell->fastGetOwnPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, propertyName); ASSERT(cell->isObject()); - JSValuePtr prototype = static_cast<JSObject*>(cell)->prototype(); - if (!prototype->isObject()) + JSValue prototype = static_cast<JSObject*>(cell)->prototype(); + if (!prototype.isObject()) return jsUndefined(); cell = asObject(prototype); } } -inline JSValuePtr JSValue::get(ExecState* exec, unsigned propertyName) const +inline JSValue JSValue::get(ExecState* exec, unsigned propertyName) const { - PropertySlot slot(this); + PropertySlot slot(asValue()); return get(exec, propertyName, slot); } -inline JSValuePtr JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const +inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) { + if (UNLIKELY(!isCell())) { JSObject* prototype = JSImmediate::prototype(asValue(), exec); if (!prototype->getPropertySlot(exec, propertyName, slot)) return jsUndefined(); @@ -510,25 +607,25 @@ inline JSValuePtr JSValue::get(ExecState* exec, unsigned propertyName, PropertyS if (cell->getOwnPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, propertyName); ASSERT(cell->isObject()); - JSValuePtr prototype = static_cast<JSObject*>(cell)->prototype(); - if (!prototype->isObject()) + JSValue prototype = static_cast<JSObject*>(cell)->prototype(); + if (!prototype.isObject()) return jsUndefined(); - cell = prototype->asCell(); + cell = prototype.asCell(); } } -inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) { + if (UNLIKELY(!isCell())) { JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value, slot); return; } asCell()->put(exec, propertyName, value, slot); } -inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValuePtr value) +inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) { + if (UNLIKELY(!isCell())) { JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value); return; } @@ -539,14 +636,20 @@ ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_ { ASSERT(newSize > oldSize); - JSValuePtr* oldPropertyStorage = m_propertyStorage; - m_propertyStorage = new JSValuePtr[newSize]; + // It's important that this function not rely on m_structure, since + // we might be in the middle of a transition. + bool wasInline = (oldSize == JSObject::inlineStorageCapacity); + + PropertyStorage oldPropertyStorage = (wasInline ? m_inlineStorage : m_externalStorage); + PropertyStorage newPropertyStorage = new EncodedJSValue[newSize]; for (unsigned i = 0; i < oldSize; ++i) - m_propertyStorage[i] = oldPropertyStorage[i]; + newPropertyStorage[i] = oldPropertyStorage[i]; - if (oldPropertyStorage != m_inlineStorage) + if (!wasInline) delete [] oldPropertyStorage; + + m_externalStorage = newPropertyStorage; } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSPropertyNameIterator.cpp index ec8efea..8c7b53d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSPropertyNameIterator.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSPropertyNameIterator.cpp @@ -37,13 +37,13 @@ JSPropertyNameIterator::~JSPropertyNameIterator() { } -JSValuePtr JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const +JSValue JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const { ASSERT_NOT_REACHED(); - return noValue(); + return JSValue(); } -bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValuePtr&) +bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValue&) { ASSERT_NOT_REACHED(); return false; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSPropertyNameIterator.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSPropertyNameIterator.h index fddb4f6..9817c07 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSPropertyNameIterator.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSPropertyNameIterator.h @@ -40,12 +40,12 @@ namespace JSC { class JSPropertyNameIterator : public JSCell { public: - static JSPropertyNameIterator* create(ExecState*, JSValuePtr); + static JSPropertyNameIterator* create(ExecState*, JSValue); virtual ~JSPropertyNameIterator(); - virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double&, JSValuePtr&); + virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double&, JSValue&); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; @@ -53,7 +53,7 @@ namespace JSC { virtual void mark(); - JSValuePtr next(ExecState*); + JSValue next(ExecState*); void invalidate(); private: @@ -83,23 +83,23 @@ inline JSPropertyNameIterator::JSPropertyNameIterator(JSObject* object, PassRefP { } -inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValuePtr v) +inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue v) { - if (v->isUndefinedOrNull()) + if (v.isUndefinedOrNull()) return new (exec) JSPropertyNameIterator; - JSObject* o = v->toObject(exec); + JSObject* o = v.toObject(exec); PropertyNameArray propertyNames(exec); o->getPropertyNames(exec, propertyNames); return new (exec) JSPropertyNameIterator(o, propertyNames.releaseData()); } -inline JSValuePtr JSPropertyNameIterator::next(ExecState* exec) +inline JSValue JSPropertyNameIterator::next(ExecState* exec) { if (m_position == m_end) - return noValue(); + return JSValue(); - if (m_data->cachedStructure() == m_object->structure() && structureChainsAreEqual(m_data->cachedPrototypeChain(), m_object->structure()->cachedPrototypeChain())) + if (m_data->cachedStructure() == m_object->structure() && m_data->cachedPrototypeChain() == m_object->structure()->prototypeChain(exec)) return jsOwnedString(exec, (*m_position++).ustring()); do { @@ -108,7 +108,7 @@ inline JSValuePtr JSPropertyNameIterator::next(ExecState* exec) m_position++; } while (m_position != m_end); - return noValue(); + return JSValue(); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSStaticScopeObject.cpp index 4196822..0253fdd 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSStaticScopeObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSStaticScopeObject.cpp @@ -44,7 +44,7 @@ JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const return exec->globalThisValue(); } -void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot&) +void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&) { if (symbolTablePut(propertyName, value)) return; @@ -52,7 +52,7 @@ void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValu ASSERT_NOT_REACHED(); } -void JSStaticScopeObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes) +void JSStaticScopeObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes) { if (symbolTablePutWithAttributes(propertyName, value, attributes)) return; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSStaticScopeObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSStaticScopeObject.h index e1400b7..7e7ce65 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -43,7 +43,7 @@ namespace JSC{ }; public: - JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValuePtr value, unsigned attributes) + JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue value, unsigned attributes) : JSVariableObject(exec->globalData().staticScopeStructure, new JSStaticScopeObjectData()) { d()->registerStore = value; @@ -55,10 +55,10 @@ namespace JSC{ virtual JSObject* toThisObject(ExecState*) const; virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable); - virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&); - void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes); + virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); + void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes); - static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); } private: JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.cpp index e644bf6..86f95e0 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.cpp @@ -30,12 +30,12 @@ namespace JSC { -JSValuePtr JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const +JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const { return const_cast<JSString*>(this); } -bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value) +bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValue& value) { value = this; number = m_value.toDouble(); @@ -88,9 +88,13 @@ bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNam // This function should only be called by JSValue::get. if (getStringPropertySlot(exec, propertyName, slot)) return true; + if (propertyName == exec->propertyNames().underscoreProto) { + slot.setValue(exec->lexicalGlobalObject()->stringPrototype()); + return true; + } slot.setBase(this); JSObject* object; - for (JSValuePtr prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype->isNull(); prototype = object->prototype()) { + for (JSValue prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) { object = asObject(prototype); if (object->getOwnPropertySlot(exec, propertyName, slot)) return true; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.h index a584a3c..900c565 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.h @@ -60,7 +60,7 @@ namespace JSC { class JSString : public JSCell { friend class JIT; - friend class Interpreter; + friend class VPtrSet; public: JSString(JSGlobalData* globalData, const UString& value) @@ -90,7 +90,7 @@ namespace JSC { bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); } JSString* getIndex(JSGlobalData*, unsigned); - static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion)); } private: enum VPtrStealingHackType { VPtrStealingHack }; @@ -99,8 +99,8 @@ namespace JSC { { } - virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value); + virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual JSObject* toObject(ExecState*) const; @@ -117,9 +117,9 @@ namespace JSC { UString m_value; }; - JSString* asString(JSValuePtr); + JSString* asString(JSValue); - inline JSString* asString(JSValuePtr value) + inline JSString* asString(JSValue value) { ASSERT(asCell(value)->isString()); return static_cast<JSString*>(asCell(value)); @@ -202,6 +202,8 @@ namespace JSC { return false; } + inline bool isJSString(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsStringVPtr; } + // --- JSValue inlines ---------------------------- inline JSString* JSValue::toThisJSString(ExecState* exec) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.cpp index 73580b0..885914d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.cpp @@ -33,18 +33,16 @@ static const double D32 = 4294967296.0; // ECMA 9.4 double JSValue::toInteger(ExecState* exec) const { - int32_t i; - if (getTruncatedInt32(i)) - return i; + if (isInt32Fast()) + return getInt32Fast(); double d = toNumber(exec); return isnan(d) ? 0.0 : trunc(d); } double JSValue::toIntegerPreserveNaN(ExecState* exec) const { - int32_t i; - if (getTruncatedInt32(i)) - return i; + if (isInt32Fast()) + return getInt32Fast(); return trunc(toNumber(exec)); } @@ -68,11 +66,6 @@ int32_t toInt32SlowCase(double d, bool& ok) return static_cast<int32_t>(d32); } -int32_t JSValue::toInt32SlowCase(ExecState* exec, bool& ok) const -{ - return JSC::toInt32SlowCase(toNumber(exec), ok); -} - uint32_t toUInt32SlowCase(double d, bool& ok) { ok = true; @@ -91,14 +84,4 @@ uint32_t toUInt32SlowCase(double d, bool& ok) return static_cast<uint32_t>(d32); } -uint32_t JSValue::toUInt32SlowCase(ExecState* exec, bool& ok) const -{ - return JSC::toUInt32SlowCase(toNumber(exec), ok); -} - -float JSValue::toFloat(ExecState* exec) const -{ - return static_cast<float>(toNumber(exec)); -} - } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.h index f04b67f..391425c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSValue.h @@ -28,12 +28,15 @@ #include "CallData.h" #include "ConstructData.h" -#include <wtf/Noncopyable.h> +#include <wtf/HashTraits.h> +#include <wtf/AlwaysInline.h> namespace JSC { class Identifier; class JSCell; + class JSGlobalData; + class JSImmediate; class JSObject; class JSString; class PropertySlot; @@ -45,12 +48,67 @@ namespace JSC { enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; - class JSValue : Noncopyable { - protected: - JSValue() { } - virtual ~JSValue() { } + typedef void* EncodedJSValue; + + class JSValue { + friend class JSImmediate; + friend struct JSValueHashTraits; + static JSValue makeImmediate(intptr_t value) + { + return JSValue(reinterpret_cast<JSCell*>(value)); + } + + intptr_t immediateValue() + { + return reinterpret_cast<intptr_t>(m_ptr); + } + public: + enum JSNullTag { JSNull }; + enum JSUndefinedTag { JSUndefined }; + enum JSTrueTag { JSTrue }; + enum JSFalseTag { JSFalse }; + + static EncodedJSValue encode(JSValue value); + static JSValue decode(EncodedJSValue ptr); + + JSValue(); + JSValue(JSNullTag); + JSValue(JSUndefinedTag); + JSValue(JSTrueTag); + JSValue(JSFalseTag); + JSValue(JSCell* ptr); + JSValue(const JSCell* ptr); + + // Numbers + JSValue(ExecState*, double); + JSValue(ExecState*, char); + JSValue(ExecState*, unsigned char); + JSValue(ExecState*, short); + JSValue(ExecState*, unsigned short); + JSValue(ExecState*, int); + JSValue(ExecState*, unsigned); + JSValue(ExecState*, long); + JSValue(ExecState*, unsigned long); + JSValue(ExecState*, long long); + JSValue(ExecState*, unsigned long long); + JSValue(JSGlobalData*, double); + JSValue(JSGlobalData*, char); + JSValue(JSGlobalData*, unsigned char); + JSValue(JSGlobalData*, short); + JSValue(JSGlobalData*, unsigned short); + JSValue(JSGlobalData*, int); + JSValue(JSGlobalData*, unsigned); + JSValue(JSGlobalData*, long); + JSValue(JSGlobalData*, unsigned long); + JSValue(JSGlobalData*, long long); + JSValue(JSGlobalData*, unsigned long long); + + operator bool() const; + bool operator==(const JSValue other) const; + bool operator!=(const JSValue other) const; + // Querying the type. bool isUndefined() const; bool isNull() const; @@ -65,7 +123,7 @@ namespace JSC { // Extracting the value. bool getBoolean(bool&) const; bool getBoolean() const; // false if not a boolean - double getNumber() const; // NaN if not a number + bool getNumber(double&) const; double uncheckedGetNumber() const; bool getString(UString&) const; UString getString() const; // null string if not a string @@ -80,143 +138,282 @@ namespace JSC { bool getTruncatedUInt32(uint32_t&) const; // Basic conversions. - JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; - bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&); + JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; + bool getPrimitiveNumber(ExecState*, double& number, JSValue&); bool toBoolean(ExecState*) const; // toNumber conversion is expected to be side effect free if an exception has // been set in the ExecState already. double toNumber(ExecState*) const; - JSValuePtr toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number. - + JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number. UString toString(ExecState*) const; JSObject* toObject(ExecState*) const; // Integer conversions. + // 'x.numberToInt32(output)' is equivalent to 'x.isNumber() && x.toInt32(output)' double toInteger(ExecState*) const; double toIntegerPreserveNaN(ExecState*) const; int32_t toInt32(ExecState*) const; int32_t toInt32(ExecState*, bool& ok) const; + bool numberToInt32(int32_t& arg); uint32_t toUInt32(ExecState*) const; uint32_t toUInt32(ExecState*, bool& ok) const; - - // Floating point conversions. - float toFloat(ExecState*) const; + bool numberToUInt32(uint32_t& arg); + + // Fast integer operations; these values return results where the value is trivially available + // in a convenient form, for use in optimizations. No assumptions should be made based on the + // results of these operations, for example !isInt32Fast() does not necessarily indicate the + // result of getNumber will not be 0. + bool isInt32Fast() const; + int32_t getInt32Fast() const; + bool isUInt32Fast() const; + uint32_t getUInt32Fast() const; + static JSValue makeInt32Fast(int32_t); + static bool areBothInt32Fast(JSValue, JSValue); + + // Floating point conversions (this is a convenience method for webcore; + // signle precision float is not a representation used in JS or JSC). + float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); } + + // API Mangled Numbers + bool isAPIMangledNumber(); // Garbage collection. void mark(); bool marked() const; // Object operations, with the toObject operation included. - JSValuePtr get(ExecState*, const Identifier& propertyName) const; - JSValuePtr get(ExecState*, const Identifier& propertyName, PropertySlot&) const; - JSValuePtr get(ExecState*, unsigned propertyName) const; - JSValuePtr get(ExecState*, unsigned propertyName, PropertySlot&) const; - void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); - void put(ExecState*, unsigned propertyName, JSValuePtr); - bool deleteProperty(ExecState*, const Identifier& propertyName); - bool deleteProperty(ExecState*, unsigned propertyName); + JSValue get(ExecState*, const Identifier& propertyName) const; + JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const; + JSValue get(ExecState*, unsigned propertyName) const; + JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const; + void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + void put(ExecState*, unsigned propertyName, JSValue); bool needsThisConversion() const; JSObject* toThisObject(ExecState*) const; UString toThisString(ExecState*) const; JSString* toThisJSString(ExecState*); - JSValuePtr getJSNumber(); // 0 if this is not a JSNumber or number object + static bool equal(ExecState* exec, JSValue v1, JSValue v2); + static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2); + static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2); + static bool strictEqual(JSValue v1, JSValue v2); + static bool strictEqualSlowCase(JSValue v1, JSValue v2); + static bool strictEqualSlowCaseInline(JSValue v1, JSValue v2); - JSValuePtr asValue() const; + JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object + bool isCell() const; JSCell* asCell() const; private: - bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); - bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - int32_t toInt32SlowCase(ExecState*, bool& ok) const; - uint32_t toUInt32SlowCase(ExecState*, bool& ok) const; + enum HashTableDeletedValueTag { HashTableDeletedValue }; + JSValue(HashTableDeletedValueTag); + + inline const JSValue asValue() const { return *this; } + + bool isDoubleNumber() const; + double getDoubleNumber() const; + + JSCell* m_ptr; }; - class JSImmediate; - class JSValueEncodedAsPointer; + struct JSValueHashTraits : HashTraits<EncodedJSValue> { + static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } + static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } + }; - class JSValuePtr { - friend class JSImmediate; + // Stand-alone helper functions. + inline JSValue jsNull() + { + return JSValue(JSValue::JSNull); + } - static JSValuePtr makeImmediate(intptr_t value) - { - return JSValuePtr(reinterpret_cast<JSValue*>(value)); - } + inline JSValue jsUndefined() + { + return JSValue(JSValue::JSUndefined); + } - intptr_t immediateValue() - { - return reinterpret_cast<intptr_t>(m_ptr); - } - - public: - JSValuePtr() - : m_ptr(0) - { - } + inline JSValue jsBoolean(bool b) + { + return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse); + } - JSValuePtr(JSValue* ptr) - : m_ptr(ptr) - { - } + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d) + { + return JSValue(exec, d); + } - JSValuePtr(const JSValue* ptr) - : m_ptr(const_cast<JSValue*>(ptr)) - { - } + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, char i) + { + return JSValue(exec, i); + } - JSValue* operator->() const - { - return m_ptr; - } + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned char i) + { + return JSValue(exec, i); + } - operator bool() const - { - return m_ptr; - } + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, short i) + { + return JSValue(exec, i); + } - bool operator==(const JSValuePtr other) const - { - return m_ptr == other.m_ptr; - } + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned short i) + { + return JSValue(exec, i); + } - bool operator!=(const JSValuePtr other) const - { - return m_ptr != other.m_ptr; - } + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, int i) + { + return JSValue(exec, i); + } - static JSValueEncodedAsPointer* encode(JSValuePtr value) - { - return reinterpret_cast<JSValueEncodedAsPointer*>(value.m_ptr); - } + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned i) + { + return JSValue(exec, i); + } - static JSValuePtr decode(JSValueEncodedAsPointer* ptr) - { - return JSValuePtr(reinterpret_cast<JSValue*>(ptr)); - } + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long i) + { + return JSValue(exec, i); + } - private: - JSValue* m_ptr; - }; + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long i) + { + return JSValue(exec, i); + } + + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long long i) + { + return JSValue(exec, i); + } + + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long long i) + { + return JSValue(exec, i); + } + + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, double d) + { + return JSValue(globalData, d); + } + + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, char i) + { + return JSValue(globalData, i); + } + + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned char i) + { + return JSValue(globalData, i); + } - inline JSValuePtr JSValue::asValue() const + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, short i) { - return JSValuePtr(this); + return JSValue(globalData, i); } - inline JSValuePtr noValue() + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned short i) { - return JSValuePtr(); + return JSValue(globalData, i); } - inline bool operator==(const JSValuePtr a, const JSValue* b) { return a == JSValuePtr(b); } - inline bool operator==(const JSValue* a, const JSValuePtr b) { return JSValuePtr(a) == b; } + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i) + { + return JSValue(globalData, i); + } + + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned i) + { + return JSValue(globalData, i); + } + + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, long i) + { + return JSValue(globalData, i); + } + + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned long i) + { + return JSValue(globalData, i); + } + + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, long long i) + { + return JSValue(globalData, i); + } + + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned long long i) + { + return JSValue(globalData, i); + } - inline bool operator!=(const JSValuePtr a, const JSValue* b) { return a != JSValuePtr(b); } - inline bool operator!=(const JSValue* a, const JSValuePtr b) { return JSValuePtr(a) != b; } + inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); } + inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; } + + inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); } + inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; } + + // JSValue member functions. + inline EncodedJSValue JSValue::encode(JSValue value) + { + return reinterpret_cast<EncodedJSValue>(value.m_ptr); + } + + inline JSValue JSValue::decode(EncodedJSValue ptr) + { + return JSValue(reinterpret_cast<JSCell*>(ptr)); + } + + // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page. + inline JSValue::JSValue() + : m_ptr(0) + { + } + + // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page. + inline JSValue::JSValue(HashTableDeletedValueTag) + : m_ptr(reinterpret_cast<JSCell*>(0x4)) + { + } + + inline JSValue::JSValue(JSCell* ptr) + : m_ptr(ptr) + { + } + + inline JSValue::JSValue(const JSCell* ptr) + : m_ptr(const_cast<JSCell*>(ptr)) + { + } + + inline JSValue::operator bool() const + { + return m_ptr; + } + + inline bool JSValue::operator==(const JSValue other) const + { + return m_ptr == other.m_ptr; + } + + inline bool JSValue::operator!=(const JSValue other) const + { + return m_ptr != other.m_ptr; + } + + inline bool JSValue::isUndefined() const + { + return asValue() == jsUndefined(); + } + + inline bool JSValue::isNull() const + { + return asValue() == jsNull(); + } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.h index 9bf5c4f..b969da5 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.h @@ -46,7 +46,7 @@ namespace JSC { public: SymbolTable& symbolTable() const { return *d->symbolTable; } - virtual void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes) = 0; + virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0; virtual bool deleteProperty(ExecState*, const Identifier&); virtual void getPropertyNames(ExecState*, PropertyNameArray&); @@ -90,8 +90,8 @@ namespace JSC { bool symbolTableGet(const Identifier&, PropertySlot&); bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable); - bool symbolTablePut(const Identifier&, JSValuePtr); - bool symbolTablePutWithAttributes(const Identifier&, JSValuePtr, unsigned attributes); + bool symbolTablePut(const Identifier&, JSValue); + bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes); JSVariableObjectData* d; }; @@ -117,7 +117,7 @@ namespace JSC { return false; } - inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValuePtr value) + inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue value) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -130,7 +130,7 @@ namespace JSC { return true; } - inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValuePtr value, unsigned attributes) + inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue value, unsigned attributes) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSWrapperObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSWrapperObject.cpp index c791d93..fb57018 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSWrapperObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSWrapperObject.cpp @@ -29,8 +29,8 @@ ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject); void JSWrapperObject::mark() { JSObject::mark(); - if (m_internalValue && !m_internalValue->marked()) - m_internalValue->mark(); + if (m_internalValue && !m_internalValue.marked()) + m_internalValue.mark(); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSWrapperObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSWrapperObject.h index 4ca96f4..2a2e3c6 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSWrapperObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSWrapperObject.h @@ -33,25 +33,24 @@ namespace JSC { explicit JSWrapperObject(PassRefPtr<Structure>); public: - JSValuePtr internalValue() const { return m_internalValue; } - void setInternalValue(JSValuePtr); + JSValue internalValue() const { return m_internalValue; } + void setInternalValue(JSValue); virtual void mark(); private: - JSValuePtr m_internalValue; + JSValue m_internalValue; }; inline JSWrapperObject::JSWrapperObject(PassRefPtr<Structure> structure) : JSObject(structure) - , m_internalValue(noValue()) { } - inline void JSWrapperObject::setInternalValue(JSValuePtr value) + inline void JSWrapperObject::setInternalValue(JSValue value) { ASSERT(value); - ASSERT(!value->isObject()); + ASSERT(!value.isObject()); m_internalValue = value; } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/LiteralParser.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/LiteralParser.cpp new file mode 100644 index 0000000..10f9a13 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/LiteralParser.cpp @@ -0,0 +1,306 @@ +/* + * 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. + */ + +#include "config.h" +#include "LiteralParser.h" + +#include "JSArray.h" +#include "JSString.h" +#include <wtf/ASCIICType.h> + +namespace JSC { + +class LiteralParser::StackGuard { +public: + StackGuard(LiteralParser* parser) + : m_parser(parser) + { + m_parser->m_depth++; + } + ~StackGuard() + { + m_parser->m_depth--; + } + bool isSafe() { return m_parser->m_depth < 10; } +private: + LiteralParser* m_parser; +}; + +static bool isSafeStringCharacter(UChar c) +{ + return (c >= ' ' && c <= 0xff && c != '\\') || c == '\t'; +} + +LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token) +{ + while (m_ptr < m_end && isASCIISpace(*m_ptr)) + ++m_ptr; + + ASSERT(m_ptr <= m_end); + if (m_ptr >= m_end) { + token.type = TokEnd; + token.start = token.end = m_ptr; + return TokEnd; + } + token.type = TokError; + token.start = m_ptr; + switch (*m_ptr) { + case '[': + token.type = TokLBracket; + token.end = ++m_ptr; + return TokLBracket; + case ']': + token.type = TokRBracket; + token.end = ++m_ptr; + return TokRBracket; + case '(': + token.type = TokLParen; + token.end = ++m_ptr; + return TokLBracket; + case ')': + token.type = TokRParen; + token.end = ++m_ptr; + return TokRBracket; + case '{': + token.type = TokLBrace; + token.end = ++m_ptr; + return TokLBrace; + case '}': + token.type = TokRBrace; + token.end = ++m_ptr; + return TokRBrace; + case ',': + token.type = TokComma; + token.end = ++m_ptr; + return TokComma; + case ':': + token.type = TokColon; + token.end = ++m_ptr; + return TokColon; + case '"': + return lexString(token); + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return lexNumber(token); + } + return TokError; +} + +LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token) +{ + ++m_ptr; + while (m_ptr < m_end && isSafeStringCharacter(*m_ptr) && *m_ptr != '"') + ++m_ptr; + if (m_ptr >= m_end || *m_ptr != '"') { + token.type = TokError; + token.end = ++m_ptr; + return TokError; + } + token.type = TokString; + token.end = ++m_ptr; + return TokString; +} + +LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& token) +{ + // ES5 and json.org define numbers as + // number + // int + // int frac? exp? + // + // int + // -? 0 + // -? digit1-9 digits? + // + // digits + // digit digits? + // + // -?(0 | [1-9][0-9]*) ('.' [0-9]+)? ([eE][+-]? [0-9]+)? + + if (m_ptr < m_end && *m_ptr == '-') // -? + ++m_ptr; + + // (0 | [1-9][0-9]*) + if (m_ptr < m_end && *m_ptr == '0') // 0 + ++m_ptr; + else if (m_ptr < m_end && *m_ptr >= '1' && *m_ptr <= '9') { // [1-9] + ++m_ptr; + // [0-9]* + while (m_ptr < m_end && isASCIIDigit(*m_ptr)) + ++m_ptr; + } else + return TokError; + + // ('.' [0-9]+)? + if (m_ptr < m_end && *m_ptr == '.') { + ++m_ptr; + // [0-9]+ + if (m_ptr >= m_end && !isASCIIDigit(*m_ptr)) + return TokError; + + ++m_ptr; + while (m_ptr < m_end && isASCIIDigit(*m_ptr)) + ++m_ptr; + } + + // ([eE][+-]? [0-9]+)? + if (m_ptr < m_end && (*m_ptr == 'e' || *m_ptr == 'E')) { // [eE] + ++m_ptr; + + // [-+]? + if (m_ptr < m_end && (*m_ptr == '-' || *m_ptr == '+')) + ++m_ptr; + + // [0-9]+ + if (m_ptr >= m_end && !isASCIIDigit(*m_ptr)) + return TokError; + + ++m_ptr; + while (m_ptr < m_end && isASCIIDigit(*m_ptr)) + ++m_ptr; + } + + token.type = TokNumber; + token.end = m_ptr; + return TokNumber; +} + +JSValue LiteralParser::parseStatement() +{ + StackGuard guard(this); + if (!guard.isSafe()) + return abortParse(); + + switch (m_lexer.currentToken().type) { + case TokLBracket: + case TokNumber: + case TokString: + return parseExpression(); + case TokLParen: { + m_lexer.next(); + JSValue result = parseExpression(); + if (m_aborted || m_lexer.currentToken().type != TokRParen) + return abortParse(); + m_lexer.next(); + return result; + } + default: + return abortParse(); + } +} + +JSValue LiteralParser::parseExpression() +{ + StackGuard guard(this); + if (!guard.isSafe()) + return abortParse(); + switch (m_lexer.currentToken().type) { + case TokLBracket: + return parseArray(); + case TokLBrace: + return parseObject(); + case TokString: { + Lexer::LiteralParserToken stringToken = m_lexer.currentToken(); + m_lexer.next(); + return jsString(m_exec, UString(stringToken.start + 1, stringToken.end - stringToken.start - 2)); + } + case TokNumber: { + Lexer::LiteralParserToken numberToken = m_lexer.currentToken(); + m_lexer.next(); + return jsNumber(m_exec, UString(numberToken.start, numberToken.end - numberToken.start).toDouble()); + } + default: + return JSValue(); + } +} + +JSValue LiteralParser::parseArray() +{ + StackGuard guard(this); + if (!guard.isSafe()) + return abortParse(); + JSArray* array = constructEmptyArray(m_exec); + while (true) { + m_lexer.next(); + JSValue value = parseExpression(); + if (m_aborted) + return JSValue(); + if (!value) + break; + array->push(m_exec, value); + + if (m_lexer.currentToken().type != TokComma) + break; + } + if (m_lexer.currentToken().type != TokRBracket) + return abortParse(); + + m_lexer.next(); + return array; +} + +JSValue LiteralParser::parseObject() +{ + StackGuard guard(this); + if (!guard.isSafe()) + return abortParse(); + JSObject* object = constructEmptyObject(m_exec); + + while (m_lexer.next() == TokString) { + Lexer::LiteralParserToken identifierToken = m_lexer.currentToken(); + + // Check for colon + if (m_lexer.next() != TokColon) + return abortParse(); + m_lexer.next(); + + JSValue value = parseExpression(); + if (!value || m_aborted) + return abortParse(); + + Identifier ident(m_exec, identifierToken.start + 1, identifierToken.end - identifierToken.start - 2); + object->putDirect(ident, value); + + if (m_lexer.currentToken().type != TokComma) + break; + } + + if (m_lexer.currentToken().type != TokRBrace) + return abortParse(); + m_lexer.next(); + return object; +} + +} diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/LiteralParser.h b/src/3rdparty/webkit/JavaScriptCore/runtime/LiteralParser.h new file mode 100644 index 0000000..a72e3d0 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/LiteralParser.h @@ -0,0 +1,112 @@ +/* + * 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 LiteralParser_h +#define LiteralParser_h + +#include "JSGlobalObjectFunctions.h" +#include "JSValue.h" +#include "UString.h" + +namespace JSC { + + class LiteralParser { + public: + LiteralParser(ExecState* exec, const UString& s) + : m_exec(exec) + , m_lexer(s) + , m_depth(0) + , m_aborted(false) + { + } + + JSValue tryLiteralParse() + { + m_lexer.next(); + JSValue result = parseStatement(); + if (m_aborted || m_lexer.currentToken().type != TokEnd) + return JSValue(); + return result; + } + private: + + enum TokenType { TokLBracket, TokRBracket, TokLBrace, TokRBrace, + TokString, TokIdentifier, TokNumber, TokColon, + TokLParen, TokRParen, TokComma, TokEnd, TokError }; + + class Lexer { + public: + struct LiteralParserToken { + TokenType type; + const UChar* start; + const UChar* end; + }; + Lexer(const UString& s) + : m_string(s) + , m_ptr(s.data()) + , m_end(s.data() + s.size()) + { + } + + TokenType next() + { + return lex(m_currentToken); + } + + const LiteralParserToken& currentToken() + { + return m_currentToken; + } + + private: + TokenType lex(LiteralParserToken&); + TokenType lexString(LiteralParserToken&); + TokenType lexNumber(LiteralParserToken&); + LiteralParserToken m_currentToken; + UString m_string; + const UChar* m_ptr; + const UChar* m_end; + }; + + class StackGuard; + JSValue parseStatement(); + JSValue parseExpression(); + JSValue parseArray(); + JSValue parseObject(); + + JSValue abortParse() + { + m_aborted = true; + return JSValue(); + } + + ExecState* m_exec; + LiteralParser::Lexer m_lexer; + int m_depth; + bool m_aborted; + }; +} + +#endif diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Lookup.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Lookup.cpp index 98133a8..8359ff7 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Lookup.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Lookup.cpp @@ -20,25 +20,13 @@ #include "config.h" #include "Lookup.h" +#include "JSFunction.h" #include "PrototypeFunction.h" namespace JSC { void HashTable::createTable(JSGlobalData* globalData) const { -#if ENABLE(PERFECT_HASH_SIZE) - ASSERT(!table); - HashEntry* entries = new HashEntry[hashSizeMask + 1]; - for (int i = 0; i <= hashSizeMask; ++i) - entries[i].setKey(0); - for (int i = 0; values[i].key; ++i) { - UString::Rep* identifier = Identifier::add(globalData, values[i].key).releaseRef(); - int hashIndex = identifier->computedHash() & hashSizeMask; - ASSERT(!entries[hashIndex].key()); - entries[hashIndex].initialize(identifier, values[i].attributes, values[i].value1, values[i].value2); - } - table = entries; -#else ASSERT(!table); int linkIndex = compactHashSizeMask + 1; HashEntry* entries = new HashEntry[compactSize]; @@ -61,17 +49,12 @@ void HashTable::createTable(JSGlobalData* globalData) const entry->initialize(identifier, values[i].attributes, values[i].value1, values[i].value2); } table = entries; -#endif } void HashTable::deleteTable() const { if (table) { -#if ENABLE(PERFECT_HASH_SIZE) - int max = hashSizeMask + 1; -#else int max = compactSize; -#endif for (int i = 0; i != max; ++i) { if (UString::Rep* key = table[i].key()) key->deref(); @@ -84,11 +67,12 @@ void HashTable::deleteTable() const void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot) { ASSERT(entry->attributes() & Function); - JSValuePtr* location = thisObj->getDirectLocation(propertyName); + JSValue* location = thisObj->getDirectLocation(propertyName); if (!location) { - PrototypeFunction* function = new (exec) PrototypeFunction(exec, entry->functionLength(), propertyName, entry->function()); - thisObj->putDirect(propertyName, function, entry->attributes()); + InternalFunction* function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, entry->function()); + + thisObj->putDirectFunction(propertyName, function, entry->attributes()); location = thisObj->getDirectLocation(propertyName); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Lookup.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Lookup.h index 55c3221..3b7353d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Lookup.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Lookup.h @@ -23,17 +23,12 @@ #include "CallFrame.h" #include "Identifier.h" -#include "JSFunction.h" #include "JSGlobalObject.h" #include "JSObject.h" #include "PropertySlot.h" #include <stdio.h> #include <wtf/Assertions.h> -// Set ENABLE_PERFECT_HASH_SIZE to 0 to save memory at the -// cost of speed. Test your platform as results may vary. -#define ENABLE_PERFECT_HASH_SIZE 1 - namespace JSC { // Hash table generated by the create_hash_table script. @@ -45,9 +40,9 @@ namespace JSC { }; // FIXME: There is no reason this get function can't be simpler. - // ie. typedef JSValuePtr (*GetFunction)(ExecState*, JSObject* baseObject) + // ie. typedef JSValue (*GetFunction)(ExecState*, JSObject* baseObject) typedef PropertySlot::GetValueFunc GetFunction; - typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValuePtr value); + typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value); class HashEntry { public: @@ -57,9 +52,7 @@ namespace JSC { m_attributes = attributes; m_u.store.value1 = v1; m_u.store.value2 = v2; -#if !ENABLE(PERFECT_HASH_SIZE) m_next = 0; -#endif } void setKey(UString::Rep* key) { m_key = key; } @@ -75,10 +68,8 @@ namespace JSC { intptr_t lexerValue() const { ASSERT(!m_attributes); return m_u.lexer.value; } -#if !ENABLE(PERFECT_HASH_SIZE) void setNext(HashEntry *next) { m_next = next; } HashEntry* next() const { return m_next; } -#endif private: UString::Rep* m_key; @@ -103,18 +94,14 @@ namespace JSC { } lexer; } m_u; -#if !ENABLE(PERFECT_HASH_SIZE) HashEntry* m_next; -#endif }; struct HashTable { -#if ENABLE(PERFECT_HASH_SIZE) - int hashSizeMask; // Precomputed size for the hash table (minus 1). -#else + int compactSize; int compactHashSizeMask; -#endif + const HashTableValue* values; // Fixed values generated by script. mutable const HashEntry* table; // Table allocated at runtime. @@ -148,13 +135,6 @@ namespace JSC { private: ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const { -#if ENABLE(PERFECT_HASH_SIZE) - ASSERT(table); - const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & hashSizeMask]; - if (entry->key() != identifier.ustring().rep()) - return 0; - return entry; -#else ASSERT(table); const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & compactHashSizeMask]; @@ -169,7 +149,6 @@ namespace JSC { } while (entry); return 0; -#endif } // Convert the hash table keys to identifiers. @@ -243,16 +222,19 @@ namespace JSC { * is found it sets the value and returns true, else it returns false. */ template <class ThisImp> - inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValuePtr value, const HashTable* table, ThisImp* thisObj) + inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj) { const HashEntry* entry = table->entry(exec, propertyName); if (!entry) return false; - if (entry->attributes() & Function) // function: put as override property - thisObj->putDirect(propertyName, value); - else if (!(entry->attributes() & ReadOnly)) + if (entry->attributes() & Function) { // function: put as override property + if (LIKELY(value.isCell())) + thisObj->putDirectFunction(propertyName, value.asCell()); + else + thisObj->putDirect(propertyName, value); + } else if (!(entry->attributes() & ReadOnly)) entry->propertyPutter()(exec, thisObj, value); return true; @@ -265,7 +247,7 @@ namespace JSC { * then it calls put() on the ParentImp class. */ template <class ThisImp, class ParentImp> - inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValuePtr value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot) + inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot) { if (!lookupPut<ThisImp>(exec, propertyName, value, table, thisObj)) thisObj->ParentImp::put(exec, propertyName, value, slot); // not found: forward to parent diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/MathObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/MathObject.cpp index 5bec2e6..2572bc9 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/MathObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/MathObject.cpp @@ -27,29 +27,30 @@ #include <wtf/Assertions.h> #include <wtf/MathExtras.h> #include <wtf/RandomNumber.h> +#include <wtf/RandomNumberSeed.h> namespace JSC { ASSERT_CLASS_FITS_IN_CELL(MathObject); -static JSValuePtr mathProtoFuncAbs(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncACos(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncASin(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncATan(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncATan2(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncCeil(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncCos(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncExp(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncFloor(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncLog(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncMax(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncMin(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncPow(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncRandom(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncRound(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncSin(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncSqrt(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr mathProtoFuncTan(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncMin(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncPow(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState*, JSObject*, JSValue, const ArgList&); } @@ -95,6 +96,7 @@ MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure) putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(exec, piDouble), DontDelete | DontEnum | ReadOnly); putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(exec, sqrt(0.5)), DontDelete | DontEnum | ReadOnly); putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(exec, sqrt(2.0)), DontDelete | DontEnum | ReadOnly); + WTF::initializeWeakRandomNumberGenerator(); } // ECMA 15.8 @@ -113,62 +115,62 @@ bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN // ------------------------------ Functions -------------------------------- -JSValuePtr mathProtoFuncAbs(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, fabs(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, fabs(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncACos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, acos(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, acos(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncASin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, asin(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, asin(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncATan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, atan(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, atan(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncATan2(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, atan2(args.at(exec, 0)->toNumber(exec), args.at(exec, 1)->toNumber(exec))); + return jsNumber(exec, atan2(args.at(0).toNumber(exec), args.at(1).toNumber(exec))); } -JSValuePtr mathProtoFuncCeil(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, ceil(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, ceil(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncCos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, cos(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, cos(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncExp(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, exp(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, exp(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncFloor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, floor(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, floor(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncLog(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, log(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, log(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncMax(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec, JSObject*, JSValue, const ArgList& args) { unsigned argsCount = args.size(); double result = -Inf; for (unsigned k = 0; k < argsCount; ++k) { - double val = args.at(exec, k)->toNumber(exec); + double val = args.at(k).toNumber(exec); if (isnan(val)) { result = NaN; break; @@ -179,12 +181,12 @@ JSValuePtr mathProtoFuncMax(ExecState* exec, JSObject*, JSValuePtr, const ArgLis return jsNumber(exec, result); } -JSValuePtr mathProtoFuncMin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec, JSObject*, JSValue, const ArgList& args) { unsigned argsCount = args.size(); double result = +Inf; for (unsigned k = 0; k < argsCount; ++k) { - double val = args.at(exec, k)->toNumber(exec); + double val = args.at(k).toNumber(exec); if (isnan(val)) { result = NaN; break; @@ -195,12 +197,12 @@ JSValuePtr mathProtoFuncMin(ExecState* exec, JSObject*, JSValuePtr, const ArgLis return jsNumber(exec, result); } -JSValuePtr mathProtoFuncPow(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec, JSObject*, JSValue, const ArgList& args) { // ECMA 15.8.2.1.13 - double arg = args.at(exec, 0)->toNumber(exec); - double arg2 = args.at(exec, 1)->toNumber(exec); + double arg = args.at(0).toNumber(exec); + double arg2 = args.at(1).toNumber(exec); if (isnan(arg2)) return jsNaN(exec); @@ -209,32 +211,32 @@ JSValuePtr mathProtoFuncPow(ExecState* exec, JSObject*, JSValuePtr, const ArgLis return jsNumber(exec, pow(arg, arg2)); } -JSValuePtr mathProtoFuncRandom(ExecState* exec, JSObject*, JSValuePtr, const ArgList&) +JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue, const ArgList&) { - return jsNumber(exec, WTF::randomNumber()); + return jsNumber(exec, WTF::weakRandomNumber()); } -JSValuePtr mathProtoFuncRound(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - double arg = args.at(exec, 0)->toNumber(exec); + double arg = args.at(0).toNumber(exec); if (signbit(arg) && arg >= -0.5) return jsNumber(exec, -0.0); return jsNumber(exec, floor(arg + 0.5)); } -JSValuePtr mathProtoFuncSin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, sin(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, sin(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, sqrt(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, sqrt(args.at(0).toNumber(exec))); } -JSValuePtr mathProtoFuncTan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, tan(args.at(exec, 0)->toNumber(exec))); + return jsNumber(exec, tan(args.at(0).toNumber(exec))); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/MathObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/MathObject.h index d6163fd..3557d1e 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/MathObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/MathObject.h @@ -34,7 +34,7 @@ namespace JSC { virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType)); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorConstructor.cpp index 3d043e9..0205fc5 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorConstructor.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorConstructor.cpp @@ -33,7 +33,7 @@ ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor); const ClassInfo NativeErrorConstructor::info = { "Function", &InternalFunction::info, 0, 0 }; NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, NativeErrorPrototype* nativeErrorPrototype) - : InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name)->getString())) + : InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name).getString())) , m_errorStructure(ErrorInstance::createStructure(nativeErrorPrototype)) { putDirect(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5 @@ -43,8 +43,8 @@ NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, PassRefPtr<Struc ErrorInstance* NativeErrorConstructor::construct(ExecState* exec, const ArgList& args) { ErrorInstance* object = new (exec) ErrorInstance(m_errorStructure); - if (!args.at(exec, 0)->isUndefined()) - object->putDirect(exec->propertyNames().message, jsString(exec, args.at(exec, 0)->toString(exec))); + if (!args.at(0).isUndefined()) + object->putDirect(exec->propertyNames().message, jsString(exec, args.at(0).toString(exec))); return object; } @@ -58,8 +58,8 @@ ConstructType NativeErrorConstructor::getConstructData(ConstructData& constructD constructData.native.function = constructWithNativeErrorConstructor; return ConstructTypeHost; } - -static JSValuePtr callNativeErrorConstructor(ExecState* exec, JSObject* constructor, JSValuePtr, const ArgList& args) + +static JSValue JSC_HOST_CALL callNativeErrorConstructor(ExecState* exec, JSObject* constructor, JSValue, const ArgList& args) { return static_cast<NativeErrorConstructor*>(constructor)->construct(exec, args); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ByteArray.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/NativeFunctionWrapper.h index 4b88fd6..d4eeb3b 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ByteArray.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/NativeFunctionWrapper.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * 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 @@ -20,19 +20,20 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "ByteArray.h" +#ifndef NativeFunctionWrapper_h +#define NativeFunctionWrapper_h namespace JSC { - -PassRefPtr<ByteArray> ByteArray::create(size_t size) -{ - unsigned char* buffer = new unsigned char[size + sizeof(ByteArray) - sizeof(size_t)]; - ASSERT((reinterpret_cast<size_t>(buffer) & 3) == 0); - return adoptRef(new (buffer) ByteArray(size)); +#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL) + class JSFunction; + typedef JSFunction NativeFunctionWrapper; +#else + class PrototypeFunction; + typedef PrototypeFunction NativeFunctionWrapper; +#endif } -} +#endif diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/NumberConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/NumberConstructor.cpp index 0da4d69..2840bf0 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/NumberConstructor.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/NumberConstructor.cpp @@ -29,11 +29,11 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(NumberConstructor); -static JSValuePtr numberConstructorNaNValue(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr numberConstructorNegInfinity(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr numberConstructorPosInfinity(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr numberConstructorMaxValue(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr numberConstructorMinValue(ExecState*, const Identifier&, const PropertySlot&); +static JSValue numberConstructorNaNValue(ExecState*, const Identifier&, const PropertySlot&); +static JSValue numberConstructorNegInfinity(ExecState*, const Identifier&, const PropertySlot&); +static JSValue numberConstructorPosInfinity(ExecState*, const Identifier&, const PropertySlot&); +static JSValue numberConstructorMaxValue(ExecState*, const Identifier&, const PropertySlot&); +static JSValue numberConstructorMinValue(ExecState*, const Identifier&, const PropertySlot&); } // namespace JSC @@ -68,36 +68,36 @@ bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& pr return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot); } -JSValuePtr numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&) +static JSValue numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&) { return jsNaN(exec); } -JSValuePtr numberConstructorNegInfinity(ExecState* exec, const Identifier&, const PropertySlot&) +static JSValue numberConstructorNegInfinity(ExecState* exec, const Identifier&, const PropertySlot&) { - return jsNumberCell(exec, -Inf); + return jsNumber(exec, -Inf); } -JSValuePtr numberConstructorPosInfinity(ExecState* exec, const Identifier&, const PropertySlot&) +static JSValue numberConstructorPosInfinity(ExecState* exec, const Identifier&, const PropertySlot&) { - return jsNumberCell(exec, Inf); + return jsNumber(exec, Inf); } -JSValuePtr numberConstructorMaxValue(ExecState* exec, const Identifier&, const PropertySlot&) +static JSValue numberConstructorMaxValue(ExecState* exec, const Identifier&, const PropertySlot&) { - return jsNumberCell(exec, 1.7976931348623157E+308); + return jsNumber(exec, 1.7976931348623157E+308); } -JSValuePtr numberConstructorMinValue(ExecState* exec, const Identifier&, const PropertySlot&) +static JSValue numberConstructorMinValue(ExecState* exec, const Identifier&, const PropertySlot&) { - return jsNumberCell(exec, 5E-324); + return jsNumber(exec, 5E-324); } // ECMA 15.7.1 static JSObject* constructWithNumberConstructor(ExecState* exec, JSObject*, const ArgList& args) { NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure()); - double n = args.isEmpty() ? 0 : args.at(exec, 0)->toNumber(exec); + double n = args.isEmpty() ? 0 : args.at(0).toNumber(exec); object->setInternalValue(jsNumber(exec, n)); return object; } @@ -109,9 +109,9 @@ ConstructType NumberConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.7.2 -static JSValuePtr callNumberConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL callNumberConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, args.isEmpty() ? 0 : args.at(exec, 0)->toNumber(exec)); + return jsNumber(exec, args.isEmpty() ? 0 : args.at(0).toNumber(exec)); } CallType NumberConstructor::getCallData(CallData& callData) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/NumberConstructor.h b/src/3rdparty/webkit/JavaScriptCore/runtime/NumberConstructor.h index 070be5f..b1224ec 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/NumberConstructor.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/NumberConstructor.h @@ -32,11 +32,11 @@ namespace JSC { NumberConstructor(ExecState*, PassRefPtr<Structure>, NumberPrototype*); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); - JSValuePtr getValueProperty(ExecState*, int token) const; + JSValue getValueProperty(ExecState*, int token) const; static const ClassInfo info; - static PassRefPtr<Structure> createStructure(JSValuePtr proto) + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance)); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/NumberObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/NumberObject.cpp index 6613390..0e8df17 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/NumberObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/NumberObject.cpp @@ -36,23 +36,16 @@ NumberObject::NumberObject(PassRefPtr<Structure> structure) { } -JSValuePtr NumberObject::getJSNumber() +JSValue NumberObject::getJSNumber() { return internalValue(); } -NumberObject* constructNumber(ExecState* exec, JSNumberCell* number) +NumberObject* constructNumber(ExecState* exec, JSValue number) { NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure()); object->setInternalValue(number); return object; } -NumberObject* constructNumberFromImmediateNumber(ExecState* exec, JSValuePtr value) -{ - NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure()); - object->setInternalValue(value); - return object; -} - } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/NumberObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/NumberObject.h index 8cc2715..d354b9b 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/NumberObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/NumberObject.h @@ -25,8 +25,6 @@ namespace JSC { - class JSNumberCell; - class NumberObject : public JSWrapperObject { public: explicit NumberObject(PassRefPtr<Structure>); @@ -36,11 +34,10 @@ namespace JSC { private: virtual const ClassInfo* classInfo() const { return &info; } - virtual JSValuePtr getJSNumber(); + virtual JSValue getJSNumber(); }; - NumberObject* constructNumber(ExecState*, JSNumberCell*); - NumberObject* constructNumberFromImmediateNumber(ExecState*, JSValuePtr); + NumberObject* constructNumber(ExecState*, JSValue); } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/NumberPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/NumberPrototype.cpp index 8b45f54..947324c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/NumberPrototype.cpp @@ -23,6 +23,7 @@ #include "NumberPrototype.h" #include "Error.h" +#include "JSFunction.h" #include "JSString.h" #include "PrototypeFunction.h" #include "dtoa.h" @@ -35,12 +36,12 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(NumberPrototype); -static JSValuePtr numberProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr numberProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr numberProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr numberProtoFuncToFixed(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr numberProtoFuncToExponential(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr numberProtoFuncToPrecision(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL numberProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*, JSObject*, JSValue, const ArgList&); // ECMA 15.7.4 @@ -51,12 +52,12 @@ NumberPrototype::NumberPrototype(ExecState* exec, PassRefPtr<Structure> structur // The constructor will be added later, after NumberConstructor has been constructed - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum); } // ------------------------------ Functions --------------------------- @@ -67,7 +68,8 @@ static UString integerPartNoExp(double d) { int decimalPoint; int sign; - char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL); + char result[80]; + WTF::dtoa(result, d, 0, &decimalPoint, &sign, NULL); bool resultIsInfOrNan = (decimalPoint == 9999); size_t length = strlen(result); @@ -80,17 +82,16 @@ static UString integerPartNoExp(double d) Vector<char, 1024> buf(decimalPoint + 1); if (static_cast<int>(length) <= decimalPoint) { - strcpy(buf.data(), result); + ASSERT(decimalPoint < 1024); + memcpy(buf.data(), result, length); memset(buf.data() + length, '0', decimalPoint - length); } else strncpy(buf.data(), result, decimalPoint); - buf[decimalPoint] = '\0'; + str.append(buf.data()); } - WTF::freedtoa(result); - return str; } @@ -133,15 +134,15 @@ static double intPow10(int e) return static_cast<double>(result); } -JSValuePtr numberProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSValuePtr v = thisValue->getJSNumber(); + JSValue v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); - double radixAsDouble = args.at(exec, 0)->toInteger(exec); // nan -> 0 - if (radixAsDouble == 10 || args.at(exec, 0)->isUndefined()) - return jsString(exec, v->toString(exec)); + double radixAsDouble = args.at(0).toInteger(exec); // nan -> 0 + if (radixAsDouble == 10 || args.at(0).isUndefined()) + return jsString(exec, v.toString(exec)); if (radixAsDouble < 2 || radixAsDouble > 36) return throwError(exec, RangeError, "toString() radix argument must be between 2 and 36"); @@ -153,7 +154,7 @@ JSValuePtr numberProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisVa // unless someone finds a precise rule. char s[2048 + 3]; const char* lastCharInString = s + sizeof(s) - 1; - double x = v->uncheckedGetNumber(); + double x = v.uncheckedGetNumber(); if (isnan(x) || isinf(x)) return jsString(exec, UString::from(x)); @@ -197,39 +198,39 @@ JSValuePtr numberProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisVa return jsString(exec, startOfResultString); } -JSValuePtr numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { // FIXME: Not implemented yet. - JSValuePtr v = thisValue->getJSNumber(); + JSValue v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); - return jsString(exec, v->toString(exec)); + return jsString(exec, v.toString(exec)); } -JSValuePtr numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - JSValuePtr v = thisValue->getJSNumber(); + JSValue v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); return v; } -JSValuePtr numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSValuePtr v = thisValue->getJSNumber(); + JSValue v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); - JSValuePtr fractionDigits = args.at(exec, 0); - double df = fractionDigits->toInteger(exec); + JSValue fractionDigits = args.at(0); + double df = fractionDigits.toInteger(exec); if (!(df >= 0 && df <= 20)) return throwError(exec, RangeError, "toFixed() digits argument must be between 0 and 20"); int f = static_cast<int>(df); - double x = v->uncheckedGetNumber(); + double x = v.uncheckedGetNumber(); if (isnan(x)) return jsNontrivialString(exec, "NaN"); @@ -277,7 +278,8 @@ static void fractionalPartToString(char* buf, int& i, const char* result, int re strncpy(buf + i, result + 1, fractionalDigits); i += fractionalDigits; } else { - strcpy(buf + i, result + 1); + ASSERT(i + resultLength - 1 < 80); + memcpy(buf + i, result + 1, resultLength - 1); i += static_cast<int>(resultLength) - 1; } } @@ -302,23 +304,23 @@ static void exponentialPartToString(char* buf, int& i, int decimalPoint) buf[i++] = static_cast<char>('0' + exponential % 10); } -JSValuePtr numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSValuePtr v = thisValue->getJSNumber(); + JSValue v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); - double x = v->uncheckedGetNumber(); + double x = v.uncheckedGetNumber(); if (isnan(x) || isinf(x)) return jsString(exec, UString::from(x)); - JSValuePtr fractionalDigitsValue = args.at(exec, 0); - double df = fractionalDigitsValue->toInteger(exec); + JSValue fractionalDigitsValue = args.at(0); + double df = fractionalDigitsValue.toInteger(exec); if (!(df >= 0 && df <= 20)) return throwError(exec, RangeError, "toExponential() argument must between 0 and 20"); int fractionalDigits = static_cast<int>(df); - bool includeAllDigits = fractionalDigitsValue->isUndefined(); + bool includeAllDigits = fractionalDigitsValue.isUndefined(); int decimalAdjust = 0; if (x && !includeAllDigits) { @@ -344,7 +346,8 @@ JSValuePtr numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValuePtr t int decimalPoint; int sign; - char* result = WTF::dtoa(x, 0, &decimalPoint, &sign, NULL); + char result[80]; + WTF::dtoa(result, x, 0, &decimalPoint, &sign, NULL); size_t resultLength = strlen(result); decimalPoint += decimalAdjust; @@ -353,9 +356,12 @@ JSValuePtr numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValuePtr t if (sign) buf[i++] = '-'; - if (decimalPoint == 999) // ? 9999 is the magical "result is Inf or NaN" value. what's 999?? - strcpy(buf + i, result); - else { + // ? 9999 is the magical "result is Inf or NaN" value. what's 999?? + if (decimalPoint == 999) { + ASSERT(i + resultLength < 80); + memcpy(buf + i, result, resultLength); + buf[i + resultLength] = '\0'; + } else { buf[i++] = result[0]; if (includeAllDigits) @@ -367,21 +373,19 @@ JSValuePtr numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValuePtr t } ASSERT(i <= 80); - WTF::freedtoa(result); - return jsString(exec, buf); } -JSValuePtr numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSValuePtr v = thisValue->getJSNumber(); + JSValue v = thisValue.getJSNumber(); if (!v) return throwError(exec, TypeError); - double doublePrecision = args.at(exec, 0)->toIntegerPreserveNaN(exec); - double x = v->uncheckedGetNumber(); - if (args.at(exec, 0)->isUndefined() || isnan(x) || isinf(x)) - return jsString(exec, v->toString(exec)); + double doublePrecision = args.at(0).toIntegerPreserveNaN(exec); + double x = v.uncheckedGetNumber(); + if (args.at(0).isUndefined() || isnan(x) || isinf(x)) + return jsString(exec, v.toString(exec)); UString s; if (x < 0) { diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectConstructor.cpp index ff97ca4..cf1790f 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "ObjectConstructor.h" +#include "JSFunction.h" #include "JSGlobalObject.h" #include "ObjectPrototype.h" @@ -41,10 +42,10 @@ ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> stru // ECMA 15.2.2 static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args) { - JSValuePtr arg = args.at(exec, 0); - if (arg->isUndefinedOrNull()) + JSValue arg = args.at(0); + if (arg.isUndefinedOrNull()) return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure()); - return arg->toObject(exec); + return arg.toObject(exec); } static JSObject* constructWithObjectConstructor(ExecState* exec, JSObject*, const ArgList& args) @@ -58,7 +59,7 @@ ConstructType ObjectConstructor::getConstructData(ConstructData& constructData) return ConstructTypeHost; } -static JSValuePtr callObjectConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args) { return constructObject(exec, args); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectPrototype.cpp index 696570b..98e4713 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectPrototype.cpp @@ -22,6 +22,7 @@ #include "ObjectPrototype.h" #include "Error.h" +#include "JSFunction.h" #include "JSString.h" #include "PrototypeFunction.h" @@ -29,58 +30,58 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ObjectPrototype); -static JSValuePtr objectProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr objectProtoFuncHasOwnProperty(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr objectProtoFuncDefineGetter(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr objectProtoFuncDefineSetter(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr objectProtoFuncLookupGetter(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr objectProtoFuncLookupSetter(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&); ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure) : JSObject(stucture) { - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().isPrototypeOf, objectProtoFuncIsPrototypeOf), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().isPrototypeOf, objectProtoFuncIsPrototypeOf), DontEnum); // Mozilla extensions - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum); } // ------------------------------ Functions -------------------------------- // ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7 -JSValuePtr objectProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - return thisValue->toThisObject(exec); + return thisValue.toThisObject(exec); } -JSValuePtr objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - return jsBoolean(thisValue->toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args.at(exec, 0)->toString(exec)))); + return jsBoolean(thisValue.toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args.at(0).toString(exec)))); } -JSValuePtr objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSObject* thisObj = thisValue->toThisObject(exec); + JSObject* thisObj = thisValue.toThisObject(exec); - if (!args.at(exec, 0)->isObject()) + if (!args.at(0).isObject()) return jsBoolean(false); - JSValuePtr v = asObject(args.at(exec, 0))->prototype(); + JSValue v = asObject(args.at(0))->prototype(); while (true) { - if (!v->isObject()) + if (!v.isObject()) return jsBoolean(false); if (v == thisObj) return jsBoolean(true); @@ -88,47 +89,47 @@ JSValuePtr objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValuePtr t } } -JSValuePtr objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { CallData callData; - if (args.at(exec, 1)->getCallData(callData) == CallTypeNone) + if (args.at(1).getCallData(callData) == CallTypeNone) return throwError(exec, SyntaxError, "invalid getter usage"); - thisValue->toThisObject(exec)->defineGetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec)), asObject(args.at(exec, 1))); + thisValue.toThisObject(exec)->defineGetter(exec, Identifier(exec, args.at(0).toString(exec)), asObject(args.at(1))); return jsUndefined(); } -JSValuePtr objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { CallData callData; - if (args.at(exec, 1)->getCallData(callData) == CallTypeNone) + if (args.at(1).getCallData(callData) == CallTypeNone) return throwError(exec, SyntaxError, "invalid setter usage"); - thisValue->toThisObject(exec)->defineSetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec)), asObject(args.at(exec, 1))); + thisValue.toThisObject(exec)->defineSetter(exec, Identifier(exec, args.at(0).toString(exec)), asObject(args.at(1))); return jsUndefined(); } -JSValuePtr objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - return thisValue->toThisObject(exec)->lookupGetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec))); + return thisValue.toThisObject(exec)->lookupGetter(exec, Identifier(exec, args.at(0).toString(exec))); } -JSValuePtr objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - return thisValue->toThisObject(exec)->lookupSetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec))); + return thisValue.toThisObject(exec)->lookupSetter(exec, Identifier(exec, args.at(0).toString(exec))); } -JSValuePtr objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - return jsBoolean(thisValue->toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args.at(exec, 0)->toString(exec)))); + return jsBoolean(thisValue.toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args.at(0).toString(exec)))); } -JSValuePtr objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - return thisValue->toThisJSString(exec); + return thisValue.toThisJSString(exec); } -JSValuePtr objectProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - return jsNontrivialString(exec, "[object " + thisValue->toThisObject(exec)->className() + "]"); + return jsNontrivialString(exec, "[object " + thisValue.toThisObject(exec)->className() + "]"); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectPrototype.h b/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectPrototype.h index 1c432fe..7790ae0 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectPrototype.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ObjectPrototype.h @@ -30,7 +30,7 @@ namespace JSC { ObjectPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); }; - JSValuePtr objectProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); + JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.cpp index 6f84303..093bbec 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.cpp @@ -35,41 +35,87 @@ namespace JSC { -// ECMA 11.9.3 -bool equal(ExecState* exec, JSValuePtr v1, JSValuePtr v2) +bool JSValue::equalSlowCase(ExecState* exec, JSValue v1, JSValue v2) { - if (JSImmediate::areBothImmediateNumbers(v1, v2)) - return v1 == v2; - return equalSlowCaseInline(exec, v1, v2); } -bool equalSlowCase(ExecState* exec, JSValuePtr v1, JSValuePtr v2) +bool JSValue::strictEqualSlowCase(JSValue v1, JSValue v2) { - return equalSlowCaseInline(exec, v1, v2); + return strictEqualSlowCaseInline(v1, v2); } -bool strictEqual(JSValuePtr v1, JSValuePtr v2) +NEVER_INLINE JSValue throwOutOfMemoryError(ExecState* exec) { - if (JSImmediate::areBothImmediate(v1, v2)) - return v1 == v2; + JSObject* error = Error::create(exec, GeneralError, "Out of memory"); + exec->setException(error); + return error; +} - if (JSImmediate::isEitherImmediate(v1, v2) & (v1 != JSImmediate::from(0)) & (v2 != JSImmediate::from(0))) - return false; +NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2) +{ + // exception for the Date exception in defaultValue() + JSValue p1 = v1.toPrimitive(callFrame); + JSValue p2 = v2.toPrimitive(callFrame); - return strictEqualSlowCaseInline(v1, v2); + if (p1.isString() || p2.isString()) { + RefPtr<UString::Rep> value = concatenate(p1.toString(callFrame).rep(), p2.toString(callFrame).rep()); + if (!value) + return throwOutOfMemoryError(callFrame); + return jsString(callFrame, value.release()); + } + + return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame)); } -bool strictEqualSlowCase(JSValuePtr v1, JSValuePtr v2) +JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v) { - return strictEqualSlowCaseInline(v1, v2); + if (v.isUndefined()) + return jsNontrivialString(callFrame, "undefined"); + if (v.isBoolean()) + return jsNontrivialString(callFrame, "boolean"); + if (v.isNumber()) + return jsNontrivialString(callFrame, "number"); + if (v.isString()) + return jsNontrivialString(callFrame, "string"); + if (v.isObject()) { + // Return "undefined" for objects that should be treated + // as null when doing comparisons. + if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined()) + return jsNontrivialString(callFrame, "undefined"); + CallData callData; + if (asObject(v)->getCallData(callData) != CallTypeNone) + return jsNontrivialString(callFrame, "function"); + } + return jsNontrivialString(callFrame, "object"); } -NEVER_INLINE JSValuePtr throwOutOfMemoryError(ExecState* exec) +bool jsIsObjectType(JSValue v) { - JSObject* error = Error::create(exec, GeneralError, "Out of memory"); - exec->setException(error); - return error; + if (!v.isCell()) + return v.isNull(); + + JSType type = asCell(v)->structure()->typeInfo().type(); + if (type == NumberType || type == StringType) + return false; + if (type == ObjectType) { + if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined()) + return false; + CallData callData; + if (asObject(v)->getCallData(callData) != CallTypeNone) + return false; + } + return true; +} + +bool jsIsFunctionType(JSValue v) +{ + if (v.isObject()) { + CallData callData; + if (asObject(v)->getCallData(callData) != CallTypeNone) + return true; + } + return false; } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h index f627c52..acfc6c2 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h @@ -22,116 +22,313 @@ #ifndef Operations_h #define Operations_h +#include "Interpreter.h" #include "JSImmediate.h" #include "JSNumberCell.h" #include "JSString.h" namespace JSC { - // ECMA 11.9.3 - bool equal(ExecState*, JSValuePtr, JSValuePtr); - bool equalSlowCase(ExecState*, JSValuePtr, JSValuePtr); - - ALWAYS_INLINE bool equalSlowCaseInline(ExecState* exec, JSValuePtr v1, JSValuePtr v2) - { - ASSERT(!JSImmediate::areBothImmediateNumbers(v1, v2)); - - do { - if (v1->isNumber() && v2->isNumber()) - return v1->uncheckedGetNumber() == v2->uncheckedGetNumber(); - - bool s1 = v1->isString(); - bool s2 = v2->isString(); - if (s1 && s2) - return asString(v1)->value() == asString(v2)->value(); - - if (v1->isUndefinedOrNull()) { - if (v2->isUndefinedOrNull()) - return true; - if (JSImmediate::isImmediate(v2)) - return false; - return v2->asCell()->structure()->typeInfo().masqueradesAsUndefined(); - } - - if (v2->isUndefinedOrNull()) { - if (JSImmediate::isImmediate(v1)) - return false; - return v1->asCell()->structure()->typeInfo().masqueradesAsUndefined(); - } - - if (v1->isObject()) { - if (v2->isObject()) - return v1 == v2; - JSValuePtr p1 = v1->toPrimitive(exec); - if (exec->hadException()) - return false; - v1 = p1; - if (JSImmediate::areBothImmediateNumbers(v1, v2)) - return v1 == v2; - continue; - } - - if (v2->isObject()) { - JSValuePtr p2 = v2->toPrimitive(exec); - if (exec->hadException()) - return false; - v2 = p2; - if (JSImmediate::areBothImmediateNumbers(v1, v2)) - return v1 == v2; - continue; - } - - if (s1 || s2) { - double d1 = v1->toNumber(exec); - double d2 = v2->toNumber(exec); - return d1 == d2; - } - - if (v1->isBoolean()) { - if (v2->isNumber()) - return static_cast<double>(v1->getBoolean()) == v2->uncheckedGetNumber(); - } else if (v2->isBoolean()) { - if (v1->isNumber()) - return v1->uncheckedGetNumber() == static_cast<double>(v2->getBoolean()); - } - - return v1 == v2; - } while (true); - } - - - bool strictEqual(JSValuePtr, JSValuePtr); - bool strictEqualSlowCase(JSValuePtr, JSValuePtr); - - inline bool strictEqualSlowCaseInline(JSValuePtr v1, JSValuePtr v2) - { - ASSERT(!JSImmediate::areBothImmediate(v1, v2)); - - if (JSImmediate::isEitherImmediate(v1, v2)) { - ASSERT(v1 == JSImmediate::zeroImmediate() || v2 == JSImmediate::zeroImmediate()); - ASSERT(v1 != v2); - - // The reason we can't just return false here is that 0 === -0, - // and while the former is an immediate number, the latter is not. - if (v1 == JSImmediate::zeroImmediate()) - return asCell(v2)->isNumber() && asNumberCell(v2)->value() == 0; - return asCell(v1)->isNumber() && asNumberCell(v1)->value() == 0; - } - - if (asCell(v1)->isNumber()) { - return asCell(v2)->isNumber() - && asNumberCell(v1)->value() == asNumberCell(v2)->value(); - } - - if (asCell(v1)->isString()) { - return asCell(v2)->isString() - && asString(v1)->value() == asString(v2)->value(); - } - - return v1 == v2; - } - - JSValuePtr throwOutOfMemoryError(ExecState*); -} - -#endif + NEVER_INLINE JSValue throwOutOfMemoryError(ExecState*); + NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue); + JSValue jsTypeStringForValue(CallFrame*, JSValue); + bool jsIsObjectType(JSValue); + bool jsIsFunctionType(JSValue); + + // ECMA 11.9.3 + inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2) + { + if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + return v1 == v2; + + return equalSlowCase(exec, v1, v2); + } + + ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2) + { + ASSERT(!JSImmediate::areBothImmediateIntegerNumbers(v1, v2)); + + do { + if (v1.isNumber() && v2.isNumber()) + return v1.uncheckedGetNumber() == v2.uncheckedGetNumber(); + + bool s1 = v1.isString(); + bool s2 = v2.isString(); + if (s1 && s2) + return asString(v1)->value() == asString(v2)->value(); + + if (v1.isUndefinedOrNull()) { + if (v2.isUndefinedOrNull()) + return true; + if (JSImmediate::isImmediate(v2)) + return false; + return v2.asCell()->structure()->typeInfo().masqueradesAsUndefined(); + } + + if (v2.isUndefinedOrNull()) { + if (JSImmediate::isImmediate(v1)) + return false; + return v1.asCell()->structure()->typeInfo().masqueradesAsUndefined(); + } + + if (v1.isObject()) { + if (v2.isObject()) + return v1 == v2; + JSValue p1 = v1.toPrimitive(exec); + if (exec->hadException()) + return false; + v1 = p1; + if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + return v1 == v2; + continue; + } + + if (v2.isObject()) { + JSValue p2 = v2.toPrimitive(exec); + if (exec->hadException()) + return false; + v2 = p2; + if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + return v1 == v2; + continue; + } + + if (s1 || s2) { + double d1 = v1.toNumber(exec); + double d2 = v2.toNumber(exec); + return d1 == d2; + } + + if (v1.isBoolean()) { + if (v2.isNumber()) + return static_cast<double>(v1.getBoolean()) == v2.uncheckedGetNumber(); + } else if (v2.isBoolean()) { + if (v1.isNumber()) + return v1.uncheckedGetNumber() == static_cast<double>(v2.getBoolean()); + } + + return v1 == v2; + } while (true); + } + + // ECMA 11.9.3 + ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(JSValue v1, JSValue v2) + { + ASSERT(!JSImmediate::isEitherImmediate(v1, v2)); + + if (v1.asCell()->isString() && v2.asCell()->isString()) + return asString(v1)->value() == asString(v2)->value(); + + return v1 == v2; + } + + inline bool JSValue::strictEqual(JSValue v1, JSValue v2) + { + if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + return v1 == v2; + + if (v1.isNumber() && v2.isNumber()) + return v1.uncheckedGetNumber() == v2.uncheckedGetNumber(); + + if (JSImmediate::isEitherImmediate(v1, v2)) + return v1 == v2; + + return strictEqualSlowCaseInline(v1, v2); + } + + inline bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2) + { + if (JSValue::areBothInt32Fast(v1, v2)) + return v1.getInt32Fast() < v2.getInt32Fast(); + + double n1; + double n2; + if (v1.getNumber(n1) && v2.getNumber(n2)) + return n1 < n2; + + JSGlobalData* globalData = &callFrame->globalData(); + if (isJSString(globalData, v1) && isJSString(globalData, v2)) + return asString(v1)->value() < asString(v2)->value(); + + JSValue p1; + JSValue p2; + bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); + bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); + + if (wasNotString1 | wasNotString2) + return n1 < n2; + + return asString(p1)->value() < asString(p2)->value(); + } + + inline bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2) + { + if (JSValue::areBothInt32Fast(v1, v2)) + return v1.getInt32Fast() <= v2.getInt32Fast(); + + double n1; + double n2; + if (v1.getNumber(n1) && v2.getNumber(n2)) + return n1 <= n2; + + JSGlobalData* globalData = &callFrame->globalData(); + if (isJSString(globalData, v1) && isJSString(globalData, v2)) + return !(asString(v2)->value() < asString(v1)->value()); + + JSValue p1; + JSValue p2; + bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); + bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); + + if (wasNotString1 | wasNotString2) + return n1 <= n2; + + return !(asString(p2)->value() < asString(p1)->value()); + } + + // Fast-path choices here are based on frequency data from SunSpider: + // <times> Add case: <t1> <t2> + // --------------------------- + // 5626160 Add case: 3 3 (of these, 3637690 are for immediate values) + // 247412 Add case: 5 5 + // 20900 Add case: 5 6 + // 13962 Add case: 5 3 + // 4000 Add case: 3 5 + + ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2) + { + double left; + double right = 0.0; + + bool rightIsNumber = v2.getNumber(right); + if (rightIsNumber && v1.getNumber(left)) + return jsNumber(callFrame, left + right); + + bool leftIsString = v1.isString(); + if (leftIsString && v2.isString()) { + RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep()); + if (!value) + return throwOutOfMemoryError(callFrame); + return jsString(callFrame, value.release()); + } + + if (rightIsNumber & leftIsString) { + RefPtr<UString::Rep> value = v2.isInt32Fast() ? + concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) : + concatenate(asString(v1)->value().rep(), right); + + if (!value) + return throwOutOfMemoryError(callFrame); + return jsString(callFrame, value.release()); + } + + // All other cases are pretty uncommon + return jsAddSlowCase(callFrame, v1, v2); + } + + inline size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValue baseValue, const PropertySlot& slot) + { + JSCell* cell = asCell(baseValue); + size_t count = 0; + + while (slot.slotBase() != cell) { + JSValue v = cell->structure()->prototypeForLookup(callFrame); + + // If we didn't find slotBase in baseValue's prototype chain, then baseValue + // must be a proxy for another object. + + if (v.isNull()) + return 0; + + cell = asCell(v); + + // Since we're accessing a prototype in a loop, it's a good bet that it + // should not be treated as a dictionary. + if (cell->structure()->isDictionary()) + asObject(cell)->setStructure(Structure::fromDictionaryTransition(cell->structure())); + + ++count; + } + + ASSERT(count); + return count; + } + + ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain) + { + ScopeChainIterator iter = scopeChain->begin(); + ScopeChainIterator next = iter; + ++next; + ScopeChainIterator end = scopeChain->end(); + ASSERT(iter != end); + + PropertySlot slot; + JSObject* base; + while (true) { + base = *iter; + if (next == end || base->getPropertySlot(callFrame, property, slot)) + return base; + + iter = next; + ++next; + } + + ASSERT_NOT_REACHED(); + return JSValue(); + } + + ALWAYS_INLINE JSValue concatenateStrings(CallFrame* callFrame, Register* strings, unsigned count) + { + ASSERT(count >= 3); + + // Estimate the amount of space required to hold the entire string. If all + // arguments are strings, we can easily calculate the exact amount of space + // required. For any other arguments, for now let's assume they may require + // 11 UChars of storage. This is enouch to hold any int, and likely is also + // reasonable for the other immediates. We may want to come back and tune + // this value at some point. + unsigned bufferSize = 0; + for (unsigned i = 0; i < count; ++i) { + JSValue v = strings[i].jsValue(); + if (LIKELY(v.isString())) + bufferSize += asString(v)->value().size(); + else + bufferSize += 11; + } + + // Allocate an output string to store the result. + // If the first argument is a String, and if it has the capacity (or can grow + // its capacity) to hold the entire result then use this as a base to concatenate + // onto. Otherwise, allocate a new empty output buffer. + JSValue firstValue = strings[0].jsValue(); + RefPtr<UString::Rep> resultRep; + if (firstValue.isString() && (resultRep = asString(firstValue)->value().rep())->reserveCapacity(bufferSize)) { + // We're going to concatenate onto the first string - remove it from the list of items to be appended. + ++strings; + --count; + } else + resultRep = UString::Rep::createEmptyBuffer(bufferSize); + UString result(resultRep); + + // Loop over the openards, writing them into the output buffer. + for (unsigned i = 0; i < count; ++i) { + JSValue v = strings[i].jsValue(); + if (LIKELY(v.isString())) + result.append(asString(v)->value()); + else if (v.isInt32Fast()) + result.appendNumeric(v.getInt32Fast()); + else { + double d; + if (v.getNumber(d)) + result.appendNumeric(d); + else + result.append(v.toString(callFrame)); + } + } + + return jsString(callFrame, result); + } + +} // namespace JSC + +#endif // Operations_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyMapHashTable.h b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyMapHashTable.h index 935df68..44dc2b8 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyMapHashTable.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyMapHashTable.h @@ -30,20 +30,23 @@ namespace JSC { UString::Rep* key; unsigned offset; unsigned attributes; + JSCell* specificValue; unsigned index; - PropertyMapEntry(UString::Rep* key, unsigned attributes) + PropertyMapEntry(UString::Rep* key, unsigned attributes, JSCell* specificValue) : key(key) , offset(0) , attributes(attributes) + , specificValue(specificValue) , index(0) { } - PropertyMapEntry(UString::Rep* key, unsigned offset, unsigned attributes, unsigned index) + PropertyMapEntry(UString::Rep* key, unsigned offset, unsigned attributes, JSCell* specificValue, unsigned index) : key(key) , offset(offset) , attributes(attributes) + , specificValue(specificValue) , index(index) { } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyNameArray.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyNameArray.cpp index 47e9d84..0878e73 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyNameArray.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyNameArray.cpp @@ -27,7 +27,7 @@ static const size_t setThreshold = 20; void PropertyNameArray::add(UString::Rep* identifier) { - ASSERT(identifier == &UString::Rep::null || identifier == &UString::Rep::empty || identifier->identifierTable()); + ASSERT(identifier == &UString::Rep::null() || identifier == &UString::Rep::empty() || identifier->identifierTable()); size_t size = m_data->propertyNameVector().size(); if (size < setThreshold) { diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyNameArray.h b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyNameArray.h index 7dc14fe..b4382f4 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyNameArray.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertyNameArray.h @@ -65,14 +65,14 @@ namespace JSC { PropertyNameArray(JSGlobalData* globalData) : m_data(PropertyNameArrayData::create()) , m_globalData(globalData) - , m_cacheable(true) + , m_shouldCache(true) { } PropertyNameArray(ExecState* exec) : m_data(PropertyNameArrayData::create()) , m_globalData(&exec->globalData()) - , m_cacheable(true) + , m_shouldCache(true) { } @@ -95,8 +95,8 @@ namespace JSC { PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); } - void setCacheable(bool cacheable) { m_cacheable = cacheable; } - bool cacheable() const { return m_cacheable; } + void setShouldCache(bool shouldCache) { m_shouldCache = shouldCache; } + bool shouldCache() const { return m_shouldCache; } private: typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet; @@ -104,7 +104,7 @@ namespace JSC { RefPtr<PropertyNameArrayData> m_data; IdentifierSet m_set; JSGlobalData* m_globalData; - bool m_cacheable; + bool m_shouldCache; }; } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.cpp index 175f271..36fa5d8 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.cpp @@ -27,7 +27,7 @@ namespace JSC { -JSValuePtr PropertySlot::functionGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue PropertySlot::functionGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { // Prevent getter functions from observing execution if an exception is pending. if (exec->hadException()) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.h b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.h index 1dd1afa..7af60ce 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.h @@ -45,30 +45,30 @@ namespace JSC { clearValue(); } - explicit PropertySlot(const JSValuePtr base) + explicit PropertySlot(const JSValue base) : m_slotBase(base) , m_offset(WTF::notFound) { clearValue(); } - typedef JSValuePtr (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&); + typedef JSValue (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&); - JSValuePtr getValue(ExecState* exec, const Identifier& propertyName) const + JSValue getValue(ExecState* exec, const Identifier& propertyName) const { if (m_getValue == JSC_VALUE_SLOT_MARKER) return *m_data.valueSlot; if (m_getValue == JSC_REGISTER_SLOT_MARKER) - return (*m_data.registerSlot).jsValue(exec); + return (*m_data.registerSlot).jsValue(); return m_getValue(exec, propertyName, *this); } - JSValuePtr getValue(ExecState* exec, unsigned propertyName) const + JSValue getValue(ExecState* exec, unsigned propertyName) const { if (m_getValue == JSC_VALUE_SLOT_MARKER) return *m_data.valueSlot; if (m_getValue == JSC_REGISTER_SLOT_MARKER) - return (*m_data.registerSlot).jsValue(exec); + return (*m_data.registerSlot).jsValue(); return m_getValue(exec, Identifier::from(exec, propertyName), *this); } @@ -79,17 +79,17 @@ namespace JSC { return m_offset; } - void putValue(JSValuePtr value) + void putValue(JSValue value) { if (m_getValue == JSC_VALUE_SLOT_MARKER) { *m_data.valueSlot = value; return; } ASSERT(m_getValue == JSC_REGISTER_SLOT_MARKER); - *m_data.registerSlot = JSValuePtr(value); + *m_data.registerSlot = JSValue(value); } - void setValueSlot(JSValuePtr* valueSlot) + void setValueSlot(JSValue* valueSlot) { ASSERT(valueSlot); m_getValue = JSC_VALUE_SLOT_MARKER; @@ -97,7 +97,7 @@ namespace JSC { m_data.valueSlot = valueSlot; } - void setValueSlot(JSValuePtr slotBase, JSValuePtr* valueSlot) + void setValueSlot(JSValue slotBase, JSValue* valueSlot) { ASSERT(valueSlot); m_getValue = JSC_VALUE_SLOT_MARKER; @@ -105,7 +105,7 @@ namespace JSC { m_data.valueSlot = valueSlot; } - void setValueSlot(JSValuePtr slotBase, JSValuePtr* valueSlot, size_t offset) + void setValueSlot(JSValue slotBase, JSValue* valueSlot, size_t offset) { ASSERT(valueSlot); m_getValue = JSC_VALUE_SLOT_MARKER; @@ -114,7 +114,7 @@ namespace JSC { m_offset = offset; } - void setValue(JSValuePtr value) + void setValue(JSValue value) { ASSERT(value); m_getValue = JSC_VALUE_SLOT_MARKER; @@ -131,7 +131,7 @@ namespace JSC { m_data.registerSlot = registerSlot; } - void setCustom(JSValuePtr slotBase, GetValueFunc getValue) + void setCustom(JSValue slotBase, GetValueFunc getValue) { ASSERT(slotBase); ASSERT(getValue); @@ -139,7 +139,7 @@ namespace JSC { m_slotBase = slotBase; } - void setCustomIndex(JSValuePtr slotBase, unsigned index, GetValueFunc getValue) + void setCustomIndex(JSValue slotBase, unsigned index, GetValueFunc getValue) { ASSERT(slotBase); ASSERT(getValue); @@ -161,13 +161,13 @@ namespace JSC { setValue(jsUndefined()); } - JSValuePtr slotBase() const + JSValue slotBase() const { ASSERT(m_slotBase); return m_slotBase; } - void setBase(JSValuePtr base) + void setBase(JSValue base) { ASSERT(m_slotBase); ASSERT(base); @@ -177,33 +177,33 @@ namespace JSC { void clearBase() { #ifndef NDEBUG - m_slotBase = noValue(); + m_slotBase = JSValue(); #endif } void clearValue() { #ifndef NDEBUG - m_value = noValue(); + m_value = JSValue(); #endif } unsigned index() const { return m_data.index; } private: - static JSValuePtr functionGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValue functionGetter(ExecState*, const Identifier&, const PropertySlot&); GetValueFunc m_getValue; - JSValuePtr m_slotBase; + JSValue m_slotBase; union { JSObject* getterFunc; - JSValuePtr* valueSlot; + JSValue* valueSlot; Register* registerSlot; unsigned index; } m_data; - JSValuePtr m_value; + JSValue m_value; size_t m_offset; }; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Protect.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Protect.h index efbc4bb..224164d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Protect.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Protect.h @@ -49,18 +49,16 @@ namespace JSC { gcUnprotect(val); } - inline void gcProtect(JSValuePtr value) + inline void gcProtect(JSValue value) { - if (!value || JSImmediate::isImmediate(value)) - return; - gcProtect(asCell(value)); + if (value && value.isCell()) + gcProtect(asCell(value)); } - inline void gcUnprotect(JSValuePtr value) + inline void gcUnprotect(JSValue value) { - if (!value || JSImmediate::isImmediate(value)) - return; - gcUnprotect(asCell(value)); + if (value && value.isCell()) + gcUnprotect(asCell(value)); } // FIXME: Share more code with RefPtr template? The only differences are the ref/deref operation @@ -76,7 +74,7 @@ namespace JSC { T* get() const { return m_ptr; } operator T*() const { return m_ptr; } - operator JSValuePtr() const { return JSValuePtr(m_ptr); } + operator JSValue() const { return JSValue(m_ptr); } T* operator->() const { return m_ptr; } operator bool() const { return m_ptr; } @@ -89,27 +87,27 @@ namespace JSC { T* m_ptr; }; - class ProtectedJSValuePtr { + class ProtectedJSValue { public: - ProtectedJSValuePtr() {} - ProtectedJSValuePtr(JSValuePtr value); - ProtectedJSValuePtr(const ProtectedJSValuePtr&); - ~ProtectedJSValuePtr(); + ProtectedJSValue() {} + ProtectedJSValue(JSValue value); + ProtectedJSValue(const ProtectedJSValue&); + ~ProtectedJSValue(); - template <class U> ProtectedJSValuePtr(const ProtectedPtr<U>&); + template <class U> ProtectedJSValue(const ProtectedPtr<U>&); - JSValuePtr get() const { return m_value; } - operator JSValuePtr() const { return m_value; } - JSValuePtr operator->() const { return m_value; } + JSValue get() const { return m_value; } + operator JSValue() const { return m_value; } + JSValue operator->() const { return m_value; } operator bool() const { return m_value; } bool operator!() const { return !m_value; } - ProtectedJSValuePtr& operator=(const ProtectedJSValuePtr&); - ProtectedJSValuePtr& operator=(JSValuePtr); + ProtectedJSValue& operator=(const ProtectedJSValue&); + ProtectedJSValue& operator=(JSValue); private: - JSValuePtr m_value; + JSValue m_value; }; template <class T> inline ProtectedPtr<T>::ProtectedPtr(T* ptr) @@ -152,39 +150,39 @@ namespace JSC { return *this; } - inline ProtectedJSValuePtr::ProtectedJSValuePtr(JSValuePtr value) + inline ProtectedJSValue::ProtectedJSValue(JSValue value) : m_value(value) { gcProtect(m_value); } - inline ProtectedJSValuePtr::ProtectedJSValuePtr(const ProtectedJSValuePtr& o) + inline ProtectedJSValue::ProtectedJSValue(const ProtectedJSValue& o) : m_value(o.get()) { gcProtect(m_value); } - inline ProtectedJSValuePtr::~ProtectedJSValuePtr() + inline ProtectedJSValue::~ProtectedJSValue() { gcUnprotect(m_value); } - template <class U> ProtectedJSValuePtr::ProtectedJSValuePtr(const ProtectedPtr<U>& o) + template <class U> ProtectedJSValue::ProtectedJSValue(const ProtectedPtr<U>& o) : m_value(o.get()) { gcProtect(m_value); } - inline ProtectedJSValuePtr& ProtectedJSValuePtr::operator=(const ProtectedJSValuePtr& o) + inline ProtectedJSValue& ProtectedJSValue::operator=(const ProtectedJSValue& o) { - JSValuePtr ovalue = o.m_value; + JSValue ovalue = o.m_value; gcProtect(ovalue); gcUnprotect(m_value); m_value = ovalue; return *this; } - inline ProtectedJSValuePtr& ProtectedJSValuePtr::operator=(JSValuePtr ovalue) + inline ProtectedJSValue& ProtectedJSValue::operator=(JSValue ovalue) { gcProtect(ovalue); gcUnprotect(m_value); @@ -200,17 +198,17 @@ namespace JSC { template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const T* b) { return a.get() != b; } template <class T> inline bool operator!=(const T* a, const ProtectedPtr<T>& b) { return a != b.get(); } - inline bool operator==(const ProtectedJSValuePtr& a, const ProtectedJSValuePtr& b) { return a.get() == b.get(); } - inline bool operator==(const ProtectedJSValuePtr& a, const JSValuePtr b) { return a.get() == b; } - template <class T> inline bool operator==(const ProtectedJSValuePtr& a, const ProtectedPtr<T>& b) { return a.get() == JSValuePtr(b.get()); } - inline bool operator==(const JSValuePtr a, const ProtectedJSValuePtr& b) { return a == b.get(); } - template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedJSValuePtr& b) { return JSValuePtr(a.get()) == b.get(); } - - inline bool operator!=(const ProtectedJSValuePtr& a, const ProtectedJSValuePtr& b) { return a.get() != b.get(); } - inline bool operator!=(const ProtectedJSValuePtr& a, const JSValuePtr b) { return a.get() != b; } - template <class T> inline bool operator!=(const ProtectedJSValuePtr& a, const ProtectedPtr<T>& b) { return a.get() != JSValuePtr(b.get()); } - inline bool operator!=(const JSValuePtr a, const ProtectedJSValuePtr& b) { return a != b.get(); } - template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedJSValuePtr& b) { return JSValuePtr(a.get()) != b.get(); } + inline bool operator==(const ProtectedJSValue& a, const ProtectedJSValue& b) { return a.get() == b.get(); } + inline bool operator==(const ProtectedJSValue& a, const JSValue b) { return a.get() == b; } + template <class T> inline bool operator==(const ProtectedJSValue& a, const ProtectedPtr<T>& b) { return a.get() == JSValue(b.get()); } + inline bool operator==(const JSValue a, const ProtectedJSValue& b) { return a == b.get(); } + template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedJSValue& b) { return JSValue(a.get()) == b.get(); } + + inline bool operator!=(const ProtectedJSValue& a, const ProtectedJSValue& b) { return a.get() != b.get(); } + inline bool operator!=(const ProtectedJSValue& a, const JSValue b) { return a.get() != b; } + template <class T> inline bool operator!=(const ProtectedJSValue& a, const ProtectedPtr<T>& b) { return a.get() != JSValue(b.get()); } + inline bool operator!=(const JSValue a, const ProtectedJSValue& b) { return a != b.get(); } + template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedJSValue& b) { return JSValue(a.get()) != b.get(); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/PutPropertySlot.h b/src/3rdparty/webkit/JavaScriptCore/runtime/PutPropertySlot.h index 1e2dfe9..eb8ea8a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/PutPropertySlot.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/PutPropertySlot.h @@ -32,15 +32,15 @@ namespace JSC { class JSObject; + class JSFunction; class PutPropertySlot { public: - enum Type { Invalid, ExistingProperty, NewProperty }; + enum Type { Uncachable, ExistingProperty, NewProperty }; PutPropertySlot() - : m_type(Invalid) + : m_type(Uncachable) , m_base(0) - , m_wasTransition(false) { } @@ -61,18 +61,14 @@ namespace JSC { Type type() const { return m_type; } JSObject* base() const { return m_base; } - bool isCacheable() const { return m_type != Invalid; } + bool isCacheable() const { return m_type != Uncachable; } size_t cachedOffset() const { ASSERT(isCacheable()); return m_offset; } - - bool wasTransition() const { return m_wasTransition; } - void setWasTransition(bool wasTransition) { m_wasTransition = wasTransition; } private: Type m_type; JSObject* m_base; - bool m_wasTransition; size_t m_offset; }; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.cpp index 722914d8..857a316 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.cpp @@ -20,17 +20,33 @@ #include "config.h" #include "RegExp.h" - -#include "JIT.h" #include "Lexer.h" -#include "WRECGenerator.h" -#include <pcre/pcre.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <wtf/Assertions.h> #include <wtf/OwnArrayPtr.h> + +#if ENABLE(YARR) + +#include "yarr/RegexCompiler.h" +#if ENABLE(YARR_JIT) +#include "yarr/RegexJIT.h" +#else +#include "yarr/RegexInterpreter.h" +#endif + +#else + +#if ENABLE(WREC) +#include "JIT.h" +#include "WRECGenerator.h" +#endif +#include <pcre/pcre.h> + +#endif + namespace JSC { #if ENABLE(WREC) @@ -40,62 +56,41 @@ using namespace WREC; inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern) : m_pattern(pattern) , m_flagBits(0) - , m_regExp(0) , m_constructionError(0) , m_numSubpatterns(0) { - UNUSED_PARAM(globalData); -#if ENABLE(WREC) - m_wrecFunction = Generator::compileRegExp(globalData, pattern, &m_numSubpatterns, &m_constructionError, m_executablePool); - if (m_wrecFunction || m_constructionError) - return; - // Fall through to non-WREC case. -#endif - m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(), - JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, &m_numSubpatterns, &m_constructionError); -} - -PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern) -{ - return adoptRef(new RegExp(globalData, pattern)); + compile(globalData); } inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags) : m_pattern(pattern) , m_flags(flags) , m_flagBits(0) - , m_regExp(0) , m_constructionError(0) , m_numSubpatterns(0) { - UNUSED_PARAM(globalData); - // NOTE: The global flag is handled on a case-by-case basis by functions like // String::match and RegExpObject::match. if (flags.find('g') != -1) m_flagBits |= Global; - - // FIXME: Eliminate duplication by adding a way ask a JSRegExp what its flags are? - JSRegExpIgnoreCaseOption ignoreCaseOption = JSRegExpDoNotIgnoreCase; - if (flags.find('i') != -1) { + if (flags.find('i') != -1) m_flagBits |= IgnoreCase; - ignoreCaseOption = JSRegExpIgnoreCase; - } - - JSRegExpMultilineOption multilineOption = JSRegExpSingleLine; - if (flags.find('m') != -1) { + if (flags.find('m') != -1) m_flagBits |= Multiline; - multilineOption = JSRegExpMultiline; - } -#if ENABLE(WREC) - m_wrecFunction = Generator::compileRegExp(globalData, pattern, &m_numSubpatterns, &m_constructionError, m_executablePool, (m_flagBits & IgnoreCase), (m_flagBits & Multiline)); - if (m_wrecFunction || m_constructionError) - return; - // Fall through to non-WREC case. + compile(globalData); +} + +#if !ENABLE(YARR) +RegExp::~RegExp() +{ + jsRegExpFree(m_regExp); +} #endif - m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(), - ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError); + +PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern) +{ + return adoptRef(new RegExp(globalData, pattern)); } PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags) @@ -103,9 +98,83 @@ PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& patte return adoptRef(new RegExp(globalData, pattern, flags)); } -RegExp::~RegExp() +#if ENABLE(YARR) + +void RegExp::compile(JSGlobalData* globalData) { - jsRegExpFree(m_regExp); +#if ENABLE(YARR_JIT) + Yarr::jitCompileRegex(globalData, m_regExpJITCode, m_pattern, m_numSubpatterns, m_constructionError, ignoreCase(), multiline()); +#else + UNUSED_PARAM(globalData); + m_regExpBytecode.set(Yarr::byteCompileRegex(m_pattern, m_numSubpatterns, m_constructionError, ignoreCase(), multiline())); +#endif +} + +int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector) +{ + if (startOffset < 0) + startOffset = 0; + if (ovector) + ovector->clear(); + + if (startOffset > s.size() || s.isNull()) + return -1; + +#if ENABLE(YARR_JIT) + if (!!m_regExpJITCode) { +#else + if (m_regExpBytecode) { +#endif + int offsetVectorSize = (m_numSubpatterns + 1) * 3; // FIXME: should be 2 - but adding temporary fallback to pcre. + int* offsetVector = new int [offsetVectorSize]; + ASSERT(offsetVector); + for (int j = 0; j < offsetVectorSize; ++j) + offsetVector[j] = -1; + + OwnArrayPtr<int> nonReturnedOvector; + if (!ovector) + nonReturnedOvector.set(offsetVector); + else + ovector->set(offsetVector); + +#if ENABLE(YARR_JIT) + int result = Yarr::executeRegex(m_regExpJITCode, s.data(), startOffset, s.size(), offsetVector, offsetVectorSize); +#else + int result = Yarr::interpretRegex(m_regExpBytecode.get(), s.data(), startOffset, s.size(), offsetVector); +#endif + + if (result < 0) { +#ifndef NDEBUG + // TODO: define up a symbol, rather than magic -1 + if (result != -1) + fprintf(stderr, "jsRegExpExecute failed with result %d\n", result); +#endif + if (ovector) + ovector->clear(); + } + return result; + } + + return -1; +} + +#else + +void RegExp::compile(JSGlobalData* globalData) +{ + m_regExp = 0; +#if ENABLE(WREC) + m_wrecFunction = Generator::compileRegExp(globalData, m_pattern, &m_numSubpatterns, &m_constructionError, m_executablePool, ignoreCase(), multiline()); + if (m_wrecFunction || m_constructionError) + return; + // Fall through to non-WREC case. +#else + UNUSED_PARAM(globalData); +#endif + + JSRegExpIgnoreCaseOption ignoreCaseOption = ignoreCase() ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase; + JSRegExpMultilineOption multilineOption = multiline() ? JSRegExpMultiline : JSRegExpSingleLine; + m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(m_pattern.data()), m_pattern.size(), ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError); } int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector) @@ -122,6 +191,7 @@ int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector) if (m_wrecFunction) { int offsetVectorSize = (m_numSubpatterns + 1) * 2; int* offsetVector = new int [offsetVectorSize]; + ASSERT(offsetVector); for (int j = 0; j < offsetVectorSize; ++j) offsetVector[j] = -1; @@ -178,4 +248,6 @@ int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector) return -1; } +#endif + } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.h b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.h index 139c754..f3be656 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.h @@ -26,6 +26,8 @@ #include "ExecutableAllocator.h" #include <wtf/Forward.h> #include <wtf/RefCounted.h> +#include "yarr/RegexJIT.h" +#include "yarr/RegexInterpreter.h" struct JSRegExp; @@ -37,7 +39,9 @@ namespace JSC { public: static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern); static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, const UString& flags); +#if !ENABLE(YARR) ~RegExp(); +#endif bool global() const { return m_flagBits & Global; } bool ignoreCase() const { return m_flagBits & IgnoreCase; } @@ -56,21 +60,27 @@ namespace JSC { RegExp(JSGlobalData* globalData, const UString& pattern); RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags); - void compile(); + void compile(JSGlobalData*); enum FlagBits { Global = 1, IgnoreCase = 2, Multiline = 4 }; UString m_pattern; // FIXME: Just decompile m_regExp instead of storing this. UString m_flags; // FIXME: Just decompile m_regExp instead of storing this. int m_flagBits; - JSRegExp* m_regExp; const char* m_constructionError; unsigned m_numSubpatterns; +#if ENABLE(YARR_JIT) + Yarr::RegexCodeBlock m_regExpJITCode; +#elif ENABLE(YARR) + OwnPtr<Yarr::BytecodePattern> m_regExpBytecode; +#else #if ENABLE(WREC) WREC::CompiledRegExp m_wrecFunction; RefPtr<ExecutablePool> m_executablePool; #endif + JSRegExp* m_regExp; +#endif }; } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpConstructor.cpp index 84a297c..bcd0d07 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -33,24 +33,24 @@ namespace JSC { -static JSValuePtr regExpConstructorInput(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorLastMatch(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorLastParen(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorLeftContext(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorRightContext(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorDollar1(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorDollar2(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorDollar3(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorDollar4(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorDollar5(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorDollar6(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorDollar7(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorDollar8(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpConstructorDollar9(ExecState*, const Identifier&, const PropertySlot&); - -static void setRegExpConstructorInput(ExecState*, JSObject*, JSValuePtr); -static void setRegExpConstructorMultiline(ExecState*, JSObject*, JSValuePtr); +static JSValue regExpConstructorInput(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorLastMatch(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorLastParen(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorLeftContext(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorRightContext(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorDollar1(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorDollar2(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorDollar3(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorDollar4(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorDollar5(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorDollar6(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorDollar7(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorDollar8(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorDollar9(ExecState*, const Identifier&, const PropertySlot&); + +static void setRegExpConstructorInput(ExecState*, JSObject*, JSValue); +static void setRegExpConstructorMultiline(ExecState*, JSObject*, JSValue); } // namespace JSC @@ -185,7 +185,7 @@ JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const return new (exec) RegExpMatchesArray(exec, d.get()); } -JSValuePtr RegExpConstructor::getBackref(ExecState* exec, unsigned i) const +JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) const { if (d->lastOvector && i <= d->lastNumSubPatterns) { int start = d->lastOvector[2 * i]; @@ -195,7 +195,7 @@ JSValuePtr RegExpConstructor::getBackref(ExecState* exec, unsigned i) const return jsEmptyString(exec); } -JSValuePtr RegExpConstructor::getLastParen(ExecState* exec) const +JSValue RegExpConstructor::getLastParen(ExecState* exec) const { unsigned i = d->lastNumSubPatterns; if (i > 0) { @@ -207,14 +207,14 @@ JSValuePtr RegExpConstructor::getLastParen(ExecState* exec) const return jsEmptyString(exec); } -JSValuePtr RegExpConstructor::getLeftContext(ExecState* exec) const +JSValue RegExpConstructor::getLeftContext(ExecState* exec) const { if (d->lastOvector) return jsSubstring(exec, d->lastInput, 0, d->lastOvector[0]); return jsEmptyString(exec); } -JSValuePtr RegExpConstructor::getRightContext(ExecState* exec) const +JSValue RegExpConstructor::getRightContext(ExecState* exec) const { if (d->lastOvector) return jsSubstring(exec, d->lastInput, d->lastOvector[1], d->lastInput.size() - d->lastOvector[1]); @@ -226,110 +226,110 @@ bool RegExpConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& pr return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot); } -JSValuePtr regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 1); } -JSValuePtr regExpConstructorDollar2(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar2(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 2); } -JSValuePtr regExpConstructorDollar3(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar3(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 3); } -JSValuePtr regExpConstructorDollar4(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar4(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 4); } -JSValuePtr regExpConstructorDollar5(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar5(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 5); } -JSValuePtr regExpConstructorDollar6(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar6(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 6); } -JSValuePtr regExpConstructorDollar7(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar7(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 7); } -JSValuePtr regExpConstructorDollar8(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar8(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 8); } -JSValuePtr regExpConstructorDollar9(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar9(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 9); } -JSValuePtr regExpConstructorInput(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorInput(ExecState* exec, const Identifier&, const PropertySlot& slot) { return jsString(exec, asRegExpConstructor(slot.slotBase())->input()); } -JSValuePtr regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot& slot) { return jsBoolean(asRegExpConstructor(slot.slotBase())->multiline()); } -JSValuePtr regExpConstructorLastMatch(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorLastMatch(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 0); } -JSValuePtr regExpConstructorLastParen(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorLastParen(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getLastParen(exec); } -JSValuePtr regExpConstructorLeftContext(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorLeftContext(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getLeftContext(exec); } -JSValuePtr regExpConstructorRightContext(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorRightContext(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getRightContext(exec); } -void RegExpConstructor::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void RegExpConstructor::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), this, slot); } -void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValuePtr value) +void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue value) { - asRegExpConstructor(baseObject)->setInput(value->toString(exec)); + asRegExpConstructor(baseObject)->setInput(value.toString(exec)); } -void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValuePtr value) +void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value) { - asRegExpConstructor(baseObject)->setMultiline(value->toBoolean(exec)); + asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec)); } // ECMA 15.10.4 JSObject* constructRegExp(ExecState* exec, const ArgList& args) { - JSValuePtr arg0 = args.at(exec, 0); - JSValuePtr arg1 = args.at(exec, 1); + JSValue arg0 = args.at(0); + JSValue arg1 = args.at(1); - if (arg0->isObject(&RegExpObject::info)) { - if (!arg1->isUndefined()) + if (arg0.isObject(&RegExpObject::info)) { + if (!arg1.isUndefined()) return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); return asObject(arg0); } - UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec); - UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec); + UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec); + UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags); if (!regExp->isValid()) @@ -349,7 +349,7 @@ ConstructType RegExpConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.10.3 -static JSValuePtr callRegExpConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args) { return constructRegExp(exec, args); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpConstructor.h b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpConstructor.h index f8c4366..6823f3f 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpConstructor.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpConstructor.h @@ -34,12 +34,12 @@ namespace JSC { public: RegExpConstructor(ExecState*, PassRefPtr<Structure>, RegExpPrototype*); - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); } - virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); static const ClassInfo info; @@ -53,10 +53,10 @@ namespace JSC { void setMultiline(bool); bool multiline() const; - JSValuePtr getBackref(ExecState*, unsigned) const; - JSValuePtr getLastParen(ExecState*) const; - JSValuePtr getLeftContext(ExecState*) const; - JSValuePtr getRightContext(ExecState*) const; + JSValue getBackref(ExecState*, unsigned) const; + JSValue getLastParen(ExecState*) const; + JSValue getLeftContext(ExecState*) const; + JSValue getRightContext(ExecState*) const; private: virtual ConstructType getConstructData(ConstructData&); @@ -67,11 +67,11 @@ namespace JSC { OwnPtr<RegExpConstructorPrivate> d; }; - RegExpConstructor* asRegExpConstructor(JSValuePtr); + RegExpConstructor* asRegExpConstructor(JSValue); JSObject* constructRegExp(ExecState*, const ArgList&); - inline RegExpConstructor* asRegExpConstructor(JSValuePtr value) + inline RegExpConstructor* asRegExpConstructor(JSValue value) { ASSERT(asObject(value)->inherits(&RegExpConstructor::info)); return static_cast<RegExpConstructor*>(asObject(value)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpMatchesArray.h b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpMatchesArray.h index 3583941..9ae18b9 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpMatchesArray.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpMatchesArray.h @@ -44,14 +44,14 @@ namespace JSC { return JSArray::getOwnPropertySlot(exec, propertyName, slot); } - virtual void put(ExecState* exec, const Identifier& propertyName, JSValuePtr v, PutPropertySlot& slot) + virtual void put(ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::put(exec, propertyName, v, slot); } - virtual void put(ExecState* exec, unsigned propertyName, JSValuePtr v) + virtual void put(ExecState* exec, unsigned propertyName, JSValue v) { if (lazyCreationData()) fillArrayInstance(exec); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpObject.cpp index 5a54ad0..687844e 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpObject.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "RegExpObject.h" +#include "Error.h" #include "JSArray.h" #include "JSGlobalObject.h" #include "JSString.h" @@ -29,12 +30,12 @@ namespace JSC { -static JSValuePtr regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&); -static JSValuePtr regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&); -static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValuePtr); +static JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&); +static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue); } // namespace JSC @@ -71,54 +72,54 @@ bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propert return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot); } -JSValuePtr regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot) +JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot) { return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global()); } -JSValuePtr regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot) +JSValue regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot) { return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->ignoreCase()); } -JSValuePtr regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot) +JSValue regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot) { return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->multiline()); } -JSValuePtr regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot) { return jsString(exec, asRegExpObject(slot.slotBase())->regExp()->pattern()); } -JSValuePtr regExpObjectLastIndex(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpObjectLastIndex(ExecState* exec, const Identifier&, const PropertySlot& slot) { return jsNumber(exec, asRegExpObject(slot.slotBase())->lastIndex()); } -void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this, slot); } -void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValuePtr value) +void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value) { - asRegExpObject(baseObject)->setLastIndex(value->toInteger(exec)); + asRegExpObject(baseObject)->setLastIndex(value.toInteger(exec)); } -JSValuePtr RegExpObject::test(ExecState* exec, const ArgList& args) +JSValue RegExpObject::test(ExecState* exec, const ArgList& args) { return jsBoolean(match(exec, args)); } -JSValuePtr RegExpObject::exec(ExecState* exec, const ArgList& args) +JSValue RegExpObject::exec(ExecState* exec, const ArgList& args) { if (match(exec, args)) return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec); return jsNull(); } -static JSValuePtr callRegExpObject(ExecState* exec, JSObject* function, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL callRegExpObject(ExecState* exec, JSObject* function, JSValue, const ArgList& args) { return asRegExpObject(function)->exec(exec, args); } @@ -134,7 +135,7 @@ bool RegExpObject::match(ExecState* exec, const ArgList& args) { RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); - UString input = args.isEmpty() ? regExpConstructor->input() : args.at(exec, 0)->toString(exec); + UString input = args.isEmpty() ? regExpConstructor->input() : args.at(0).toString(exec); if (input.isNull()) { throwError(exec, GeneralError, "No input to " + toString(exec) + "."); return false; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpObject.h index 4c99c30..fac9978 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpObject.h @@ -37,16 +37,16 @@ namespace JSC { void setLastIndex(double lastIndex) { d->lastIndex = lastIndex; } double lastIndex() const { return d->lastIndex; } - JSValuePtr test(ExecState*, const ArgList&); - JSValuePtr exec(ExecState*, const ArgList&); + JSValue test(ExecState*, const ArgList&); + JSValue exec(ExecState*, const ArgList&); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType)); } @@ -70,9 +70,9 @@ namespace JSC { OwnPtr<RegExpObjectData> d; }; - RegExpObject* asRegExpObject(JSValuePtr); + RegExpObject* asRegExpObject(JSValue); - inline RegExpObject* asRegExpObject(JSValuePtr value) + inline RegExpObject* asRegExpObject(JSValue value) { ASSERT(asObject(value)->inherits(&RegExpObject::info)); return static_cast<RegExpObject*>(asObject(value)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpPrototype.cpp index b47d489..b1ab889 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -23,6 +23,7 @@ #include "ArrayPrototype.h" #include "JSArray.h" +#include "JSFunction.h" #include "JSObject.h" #include "JSString.h" #include "JSValue.h" @@ -35,10 +36,10 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(RegExpPrototype); -static JSValuePtr regExpProtoFuncTest(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr regExpProtoFuncExec(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr regExpProtoFuncCompile(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr regExpProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); // ECMA 15.10.5 @@ -47,44 +48,44 @@ const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 }; RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) : JSObject(structure) { - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum); } // ------------------------------ Functions --------------------------- -JSValuePtr regExpProtoFuncTest(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue->isObject(&RegExpObject::info)) + if (!thisValue.isObject(&RegExpObject::info)) return throwError(exec, TypeError); return asRegExpObject(thisValue)->test(exec, args); } -JSValuePtr regExpProtoFuncExec(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue->isObject(&RegExpObject::info)) + if (!thisValue.isObject(&RegExpObject::info)) return throwError(exec, TypeError); return asRegExpObject(thisValue)->exec(exec, args); } -JSValuePtr regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue->isObject(&RegExpObject::info)) + if (!thisValue.isObject(&RegExpObject::info)) return throwError(exec, TypeError); RefPtr<RegExp> regExp; - JSValuePtr arg0 = args.at(exec, 0); - JSValuePtr arg1 = args.at(exec, 1); + JSValue arg0 = args.at(0); + JSValue arg1 = args.at(1); - if (arg0->isObject(&RegExpObject::info)) { - if (!arg1->isUndefined()) + if (arg0.isObject(&RegExpObject::info)) { + if (!arg1.isUndefined()) return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); regExp = asRegExpObject(arg0)->regExp(); } else { - UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec); - UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec); + UString pattern = args.isEmpty() ? UString("") : arg0.toString(exec); + UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); regExp = RegExp::create(&exec->globalData(), pattern, flags); } @@ -96,21 +97,21 @@ JSValuePtr regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValuePtr thisVal return jsUndefined(); } -JSValuePtr regExpProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue->isObject(&RegExpObject::info)) { - if (thisValue->isObject(&RegExpPrototype::info)) + if (!thisValue.isObject(&RegExpObject::info)) { + if (thisValue.isObject(&RegExpPrototype::info)) return jsNontrivialString(exec, "//"); return throwError(exec, TypeError); } - UString result = "/" + asRegExpObject(thisValue)->get(exec, exec->propertyNames().source)->toString(exec); + UString result = "/" + asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec); result.append('/'); - if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global)->toBoolean(exec)) + if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global).toBoolean(exec)) result.append('g'); - if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec)) + if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec)) result.append('i'); - if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline)->toBoolean(exec)) + if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline).toBoolean(exec)) result.append('m'); return jsNontrivialString(exec, result); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ScopeChain.h b/src/3rdparty/webkit/JavaScriptCore/runtime/ScopeChain.h index 32b5e92..6f1560a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ScopeChain.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ScopeChain.h @@ -41,6 +41,18 @@ namespace JSC { { ASSERT(globalData); } +#ifndef NDEBUG + // Due to the number of subtle and timing dependent bugs that have occurred due + // to deleted but still "valid" ScopeChainNodes we now deliberately clobber the + // contents in debug builds. + ~ScopeChainNode() + { + next = 0; + object = 0; + globalData = 0; + globalThis = 0; + } +#endif ScopeChainNode* next; JSObject* object; @@ -171,6 +183,9 @@ namespace JSC { { if (m_node) m_node->deref(); +#ifndef NDEBUG + m_node = 0; +#endif } void swap(ScopeChain&); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/SmallStrings.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/SmallStrings.cpp index 06811b9..87b49f0 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/SmallStrings.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/SmallStrings.cpp @@ -29,48 +29,52 @@ #include "JSGlobalObject.h" #include "JSString.h" +#include <wtf/Noncopyable.h> + namespace JSC { +static const unsigned numCharactersToStore = 0x100; -class SmallStringsStorage { +class SmallStringsStorage : Noncopyable { public: SmallStringsStorage(); - ~SmallStringsStorage(); - UString::Rep* rep(unsigned char character) { return &reps[character]; } + UString::Rep* rep(unsigned char character) { return &m_reps[character]; } private: - UChar characters[0x100]; - UString::Rep* reps; + UChar m_characters[numCharactersToStore]; + UString::BaseString m_base; + UString::Rep m_reps[numCharactersToStore]; }; SmallStringsStorage::SmallStringsStorage() - : reps(static_cast<UString::Rep*>(fastZeroedMalloc(sizeof(UString::Rep) * 0x100))) + : m_base(m_characters, numCharactersToStore) { - for (unsigned i = 0; i < 0x100; ++i) { - characters[i] = i; - reps[i].offset = i; - reps[i].len = 1; - reps[i].rc = 1; - reps[i].baseString = &reps[0]; - } - reps[0].rc = 0x101; - reps[0].buf = characters; - + m_base.rc = numCharactersToStore + 1; // make sure UString doesn't try to reuse the buffer by pretending we have one more character in it - reps[0].usedCapacity = 0x101; - reps[0].capacity = 0x101; -} + m_base.usedCapacity = numCharactersToStore + 1; + m_base.capacity = numCharactersToStore + 1; + m_base.checkConsistency(); -SmallStringsStorage::~SmallStringsStorage() -{ - fastFree(reps); + for (unsigned i = 0; i < numCharactersToStore; ++i) + m_characters[i] = i; + + memset(&m_reps, 0, sizeof(m_reps)); + for (unsigned i = 0; i < numCharactersToStore; ++i) { + m_reps[i].offset = i; + m_reps[i].len = 1; + m_reps[i].rc = 1; + m_reps[i].setBaseString(&m_base); + m_reps[i].checkConsistency(); + } } SmallStrings::SmallStrings() : m_emptyString(0) , m_storage(0) { - for (unsigned i = 0; i < 0x100; ++i) + COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); + + for (unsigned i = 0; i < numCharactersToStore; ++i) m_singleCharacterStrings[i] = 0; } @@ -82,12 +86,24 @@ void SmallStrings::mark() { if (m_emptyString && !m_emptyString->marked()) m_emptyString->mark(); - for (unsigned i = 0; i < 0x100; ++i) { + for (unsigned i = 0; i < numCharactersToStore; ++i) { if (m_singleCharacterStrings[i] && !m_singleCharacterStrings[i]->marked()) m_singleCharacterStrings[i]->mark(); } } - + +unsigned SmallStrings::count() const +{ + unsigned count = 0; + if (m_emptyString) + ++count; + for (unsigned i = 0; i < numCharactersToStore; ++i) { + if (m_singleCharacterStrings[i]) + ++count; + } + return count; +} + void SmallStrings::createEmptyString(JSGlobalData* globalData) { ASSERT(!m_emptyString); @@ -109,4 +125,4 @@ UString::Rep* SmallStrings::singleCharacterStringRep(unsigned char character) return m_storage->rep(character); } -} +} // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/SmallStrings.h b/src/3rdparty/webkit/JavaScriptCore/runtime/SmallStrings.h index 7e5f5c8..e7f1170 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/SmallStrings.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/SmallStrings.h @@ -55,9 +55,11 @@ namespace JSC { } UString::Rep* singleCharacterStringRep(unsigned char character); - + void mark(); - + + unsigned count() const; + private: void createEmptyString(JSGlobalData*); void createSingleCharacterString(JSGlobalData*, unsigned char); @@ -66,7 +68,7 @@ namespace JSC { JSString* m_singleCharacterStrings[0x100]; OwnPtr<SmallStringsStorage> m_storage; }; - -} -#endif +} // namespace JSC + +#endif // SmallStrings_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StringConstructor.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/StringConstructor.cpp index bac819f..6380445 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/StringConstructor.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StringConstructor.cpp @@ -21,26 +21,27 @@ #include "config.h" #include "StringConstructor.h" +#include "JSFunction.h" #include "JSGlobalObject.h" #include "PrototypeFunction.h" #include "StringPrototype.h" namespace JSC { -static NEVER_INLINE JSValuePtr stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args) +static NEVER_INLINE JSValue stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args) { UChar* buf = static_cast<UChar*>(fastMalloc(args.size() * sizeof(UChar))); UChar* p = buf; ArgList::const_iterator end = args.end(); for (ArgList::const_iterator it = args.begin(); it != end; ++it) - *p++ = static_cast<UChar>((*it).jsValue(exec)->toUInt32(exec)); + *p++ = static_cast<UChar>((*it).toUInt32(exec)); return jsString(exec, UString(buf, p - buf, false)); } -static JSValuePtr stringFromCharCode(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec, JSObject*, JSValue, const ArgList& args) { if (LIKELY(args.size() == 1)) - return jsSingleCharacterString(exec, args.at(exec, 0)->toUInt32(exec)); + return jsSingleCharacterString(exec, args.at(0).toUInt32(exec)); return stringFromCharCodeSlowCase(exec, args); } @@ -53,7 +54,7 @@ StringConstructor::StringConstructor(ExecState* exec, PassRefPtr<Structure> stru putDirectWithoutTransition(exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete); // ECMA 15.5.3.2 fromCharCode() - putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum); // no. of arguments for constructor putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete); @@ -64,7 +65,7 @@ static JSObject* constructWithStringConstructor(ExecState* exec, JSObject*, cons { if (args.isEmpty()) return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure()); - return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), args.at(exec, 0)->toString(exec)); + return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), args.at(0).toString(exec)); } ConstructType StringConstructor::getConstructData(ConstructData& constructData) @@ -74,11 +75,11 @@ ConstructType StringConstructor::getConstructData(ConstructData& constructData) } // ECMA 15.5.1 -static JSValuePtr callStringConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args) +static JSValue JSC_HOST_CALL callStringConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args) { if (args.isEmpty()) return jsEmptyString(exec); - return jsString(exec, args.at(exec, 0)->toString(exec)); + return jsString(exec, args.at(0).toString(exec)); } CallType StringConstructor::getCallData(CallData& callData) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.cpp index 093f5de..fb44498 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.cpp @@ -61,7 +61,7 @@ bool StringObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Pr return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot); } -void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { if (propertyName == exec->propertyNames().length) return; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.h index 540c576..ea3a045 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.h @@ -36,16 +36,16 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - virtual void put(ExecState* exec, const Identifier& propertyName, JSValuePtr, PutPropertySlot&); + virtual void put(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual void getPropertyNames(ExecState*, PropertyNameArray&); virtual const ClassInfo* classInfo() const { return &info; } - static const ClassInfo info; + static const JS_EXPORTDATA ClassInfo info; JSString* internalValue() const { return asString(JSWrapperObject::internalValue());} - static PassRefPtr<Structure> createStructure(JSValuePtr prototype) + static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(ObjectType)); } @@ -59,9 +59,9 @@ namespace JSC { virtual JSString* toThisJSString(ExecState*); }; - StringObject* asStringObject(JSValuePtr); + StringObject* asStringObject(JSValue); - inline StringObject* asStringObject(JSValuePtr value) + inline StringObject* asStringObject(JSValue value) { ASSERT(asObject(value)->inherits(&StringObject::info)); return static_cast<StringObject*>(asObject(value)); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/src/3rdparty/webkit/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h index 72c0f47..bc5c0a5 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h @@ -42,7 +42,7 @@ namespace JSC { { } - static PassRefPtr<Structure> createStructure(JSValuePtr proto) + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined)); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StringPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/StringPrototype.cpp index 1f43cd6..d6939cb 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/StringPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StringPrototype.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "StringPrototype.h" +#include "CachedCall.h" #include "JSArray.h" #include "JSFunction.h" #include "ObjectPrototype.h" @@ -37,36 +38,36 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(StringPrototype); -static JSValuePtr stringProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncCharAt(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncCharCodeAt(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncConcat(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncLastIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncMatch(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncReplace(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncSearch(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncSlice(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncSplit(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncSubstr(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncSubstring(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncToLowerCase(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncToUpperCase(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncLocaleCompare(ExecState*, JSObject*, JSValuePtr, const ArgList&); - -static JSValuePtr stringProtoFuncBig(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncSmall(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncBlink(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncBold(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncFixed(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncItalics(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncStrike(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncSub(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncSup(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncFontcolor(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncFontsize(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncAnchor(ExecState*, JSObject*, JSValuePtr, const ArgList&); -static JSValuePtr stringProtoFuncLink(ExecState*, JSObject*, JSValuePtr, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState*, JSObject*, JSValue, const ArgList&); + +static JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState*, JSObject*, JSValue, const ArgList&); } @@ -140,13 +141,12 @@ static inline UString substituteBackreferences(const UString& replacement, const if (i + 1 == replacement.size()) break; - unsigned short ref = replacement[i + 1]; + UChar ref = replacement[i + 1]; if (ref == '$') { // "$$" -> "$" ++i; substitutedReplacement.append(replacement.data() + offset, i - offset); offset = i + 1; - substitutedReplacement.append('$'); continue; } @@ -205,21 +205,21 @@ 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()); } -JSValuePtr stringProtoFuncReplace(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - JSString* sourceVal = thisValue->toThisJSString(exec); + JSString* sourceVal = thisValue.toThisJSString(exec); const UString& source = sourceVal->value(); - JSValuePtr pattern = args.at(exec, 0); + JSValue pattern = args.at(0); - JSValuePtr replacement = args.at(exec, 1); + JSValue replacement = args.at(1); UString replacementString; CallData callData; - CallType callType = replacement->getCallData(callData); + CallType callType = replacement.getCallData(callData); if (callType == CallTypeNone) - replacementString = replacement->toString(exec); + replacementString = replacement.toString(exec); - if (pattern->isObject(&RegExpObject::info)) { + if (pattern.isObject(&RegExpObject::info)) { RegExp* reg = asRegExpObject(pattern)->regExp(); bool global = reg->global(); @@ -232,167 +232,223 @@ JSValuePtr stringProtoFuncReplace(ExecState* exec, JSObject*, JSValuePtr thisVal Vector<UString, 16> replacements; // This is either a loop (if global is set) or a one-way (if not). - do { - int matchIndex; - int matchLen; - int* ovector; - regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); - if (matchIndex < 0) - break; - - sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); + if (global && callType == CallTypeJS) { + // reg->numSubpatterns() + 1 for pattern args, + 2 for match start and sourceValue + int argCount = reg->numSubpatterns() + 1 + 2; + JSFunction* func = asFunction(replacement); + CachedCall cachedCall(exec, func, argCount, exec->exceptionSlot()); + if (exec->hadException()) + return jsNull(); + while (true) { + int matchIndex; + int matchLen; + int* ovector; + regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); + if (matchIndex < 0) + break; + + sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); - if (callType != CallTypeNone) { int completeMatchStart = ovector[0]; - ArgList args; - - for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) { + unsigned i = 0; + for (; i < reg->numSubpatterns() + 1; ++i) { int matchStart = ovector[i * 2]; int matchLen = ovector[i * 2 + 1] - matchStart; if (matchStart < 0) - args.append(jsUndefined()); + cachedCall.setArgument(i, jsUndefined()); else - args.append(jsSubstring(exec, source, matchStart, matchLen)); + cachedCall.setArgument(i, jsSubstring(exec, source, matchStart, matchLen)); } - args.append(jsNumber(exec, completeMatchStart)); - args.append(sourceVal); - - replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec)); + cachedCall.setArgument(i++, jsNumber(exec, completeMatchStart)); + cachedCall.setArgument(i++, sourceVal); + + cachedCall.setThis(exec->globalThisValue()); + replacements.append(cachedCall.call().toString(cachedCall.newCallFrame())); if (exec->hadException()) break; - } else - replacements.append(substituteBackreferences(replacementString, source, ovector, reg)); - lastIndex = matchIndex + matchLen; - startPosition = lastIndex; + lastIndex = matchIndex + matchLen; + startPosition = lastIndex; - // special case of empty match - if (matchLen == 0) { - startPosition++; - if (startPosition > source.size()) + // special case of empty match + if (matchLen == 0) { + startPosition++; + if (startPosition > source.size()) + break; + } + } + } else { + do { + int matchIndex; + int matchLen; + int* ovector; + regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); + if (matchIndex < 0) break; - } - } while (global); - if (lastIndex < source.size()) - sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex)); + sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); - UString result = source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()); + if (callType != CallTypeNone) { + int completeMatchStart = ovector[0]; + MarkedArgumentBuffer args; - if (result == source) + for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) { + int matchStart = ovector[i * 2]; + int matchLen = ovector[i * 2 + 1] - matchStart; + + if (matchStart < 0) + args.append(jsUndefined()); + else + args.append(jsSubstring(exec, source, matchStart, matchLen)); + } + + args.append(jsNumber(exec, completeMatchStart)); + args.append(sourceVal); + + replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec)); + if (exec->hadException()) + break; + } else + replacements.append(substituteBackreferences(replacementString, source, ovector, reg)); + + lastIndex = matchIndex + matchLen; + startPosition = lastIndex; + + // special case of empty match + if (matchLen == 0) { + startPosition++; + if (startPosition > source.size()) + break; + } + } while (global); + } + + if (!lastIndex && replacements.isEmpty()) return sourceVal; - return jsString(exec, result); + if (lastIndex < source.size()) + sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex)); + + return jsString(exec, source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), + replacements.data(), replacements.size())); } - // First arg is a string - UString patternString = pattern->toString(exec); + // Not a regular expression, so treat the pattern as a string. + + UString patternString = pattern.toString(exec); int matchPos = source.find(patternString); - int matchLen = patternString.size(); - // Do the replacement + if (matchPos == -1) return sourceVal; + int matchLen = patternString.size(); if (callType != CallTypeNone) { - ArgList args; + MarkedArgumentBuffer args; args.append(jsSubstring(exec, source, matchPos, matchLen)); args.append(jsNumber(exec, matchPos)); args.append(sourceVal); - replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec); + replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec); } int ovector[2] = { matchPos, matchPos + matchLen }; - return jsString(exec, source.substr(0, matchPos) - + substituteBackreferences(replacementString, source, ovector, 0) - + source.substr(matchPos + matchLen)); + return jsString(exec, source.replaceRange(matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0))); } -JSValuePtr stringProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { // Also used for valueOf. - if (thisValue->isString()) + if (thisValue.isString()) return thisValue; - if (thisValue->isObject(&StringObject::info)) + if (thisValue.isObject(&StringObject::info)) return asStringObject(thisValue)->internalValue(); return throwError(exec, TypeError); } -JSValuePtr stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); unsigned len = s.size(); - JSValuePtr a0 = args.at(exec, 0); - if (JSImmediate::isNumber(a0)) { - uint32_t i; - if (JSImmediate::getUInt32(a0, i) && i < len) + JSValue a0 = args.at(0); + if (a0.isUInt32Fast()) { + uint32_t i = a0.getUInt32Fast(); + if (i < len) return jsSingleCharacterSubstring(exec, s, i); return jsEmptyString(exec); } - double dpos = a0->toInteger(exec); + double dpos = a0.toInteger(exec); if (dpos >= 0 && dpos < len) return jsSingleCharacterSubstring(exec, s, static_cast<unsigned>(dpos)); return jsEmptyString(exec); } -JSValuePtr stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); unsigned len = s.size(); - JSValuePtr a0 = args.at(exec, 0); - if (JSImmediate::isNumber(a0)) { - uint32_t i; - if (JSImmediate::getUInt32(a0, i) && i < len) + JSValue a0 = args.at(0); + if (a0.isUInt32Fast()) { + uint32_t i = a0.getUInt32Fast(); + if (i < len) return jsNumber(exec, s.data()[i]); return jsNaN(exec); } - double dpos = a0->toInteger(exec); + double dpos = a0.toInteger(exec); if (dpos >= 0 && dpos < len) return jsNumber(exec, s[static_cast<int>(dpos)]); return jsNaN(exec); } -JSValuePtr stringProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); ArgList::const_iterator end = args.end(); for (ArgList::const_iterator it = args.begin(); it != end; ++it) - s += (*it).jsValue(exec)->toString(exec); + s += (*it).toString(exec); return jsString(exec, s); } -JSValuePtr stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); int len = s.size(); - JSValuePtr a0 = args.at(exec, 0); - JSValuePtr a1 = args.at(exec, 1); - UString u2 = a0->toString(exec); - double dpos = a1->toInteger(exec); - if (dpos < 0) - dpos = 0; - else if (dpos > len) - dpos = len; - return jsNumber(exec, s.find(u2, static_cast<int>(dpos))); + JSValue a0 = args.at(0); + JSValue a1 = args.at(1); + UString u2 = a0.toString(exec); + int pos; + if (a1.isUndefined()) + pos = 0; + else if (a1.isUInt32Fast()) + pos = min<uint32_t>(a1.getUInt32Fast(), len); + else { + double dpos = a1.toInteger(exec); + if (dpos < 0) + dpos = 0; + else if (dpos > len) + dpos = len; + pos = static_cast<int>(dpos); + } + + return jsNumber(exec, s.find(u2, pos)); } -JSValuePtr stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); int len = s.size(); - JSValuePtr a0 = args.at(exec, 0); - JSValuePtr a1 = args.at(exec, 1); + JSValue a0 = args.at(0); + JSValue a1 = args.at(1); - UString u2 = a0->toString(exec); - double dpos = a1->toIntegerPreserveNaN(exec); + UString u2 = a0.toString(exec); + double dpos = a1.toIntegerPreserveNaN(exec); if (dpos < 0) dpos = 0; else if (!(dpos <= len)) // true for NaN @@ -400,16 +456,16 @@ JSValuePtr stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thi return jsNumber(exec, s.rfind(u2, static_cast<int>(dpos))); } -JSValuePtr stringProtoFuncMatch(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); - JSValuePtr a0 = args.at(exec, 0); + JSValue a0 = args.at(0); UString u = s; RefPtr<RegExp> reg; RegExpObject* imp = 0; - if (a0->isObject(&RegExpObject::info)) + if (a0.isObject(&RegExpObject::info)) reg = asRegExpObject(a0)->regExp(); else { /* @@ -417,7 +473,7 @@ JSValuePtr stringProtoFuncMatch(ExecState* exec, JSObject*, JSValuePtr thisValue * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ - reg = RegExp::create(&exec->globalData(), a0->toString(exec)); + reg = RegExp::create(&exec->globalData(), a0.toString(exec)); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; @@ -431,7 +487,7 @@ JSValuePtr stringProtoFuncMatch(ExecState* exec, JSObject*, JSValuePtr thisValue } // return array of matches - ArgList list; + MarkedArgumentBuffer list; int lastIndex = 0; while (pos >= 0) { list.append(jsSubstring(exec, u, pos, matchLength)); @@ -451,15 +507,15 @@ JSValuePtr stringProtoFuncMatch(ExecState* exec, JSObject*, JSValuePtr thisValue return constructArray(exec, list); } -JSValuePtr stringProtoFuncSearch(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); - JSValuePtr a0 = args.at(exec, 0); + JSValue a0 = args.at(0); UString u = s; RefPtr<RegExp> reg; - if (a0->isObject(&RegExpObject::info)) + if (a0.isObject(&RegExpObject::info)) reg = asRegExpObject(a0)->regExp(); else { /* @@ -467,7 +523,7 @@ JSValuePtr stringProtoFuncSearch(ExecState* exec, JSObject*, JSValuePtr thisValu * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ - reg = RegExp::create(&exec->globalData(), a0->toString(exec)); + reg = RegExp::create(&exec->globalData(), a0.toString(exec)); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; @@ -476,17 +532,17 @@ JSValuePtr stringProtoFuncSearch(ExecState* exec, JSObject*, JSValuePtr thisValu return jsNumber(exec, pos); } -JSValuePtr stringProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); int len = s.size(); - JSValuePtr a0 = args.at(exec, 0); - JSValuePtr a1 = args.at(exec, 1); + JSValue a0 = args.at(0); + JSValue a1 = args.at(1); // The arg processing is very much like ArrayProtoFunc::Slice - double start = a0->toInteger(exec); - double end = a1->isUndefined() ? len : a1->toInteger(exec); + double start = a0.toInteger(exec); + double end = a1.isUndefined() ? len : a1.toInteger(exec); double from = start < 0 ? len + start : start; double to = end < 0 ? len + end : end; if (to > from && to > 0 && from < len) { @@ -500,18 +556,18 @@ JSValuePtr stringProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue return jsEmptyString(exec); } -JSValuePtr stringProtoFuncSplit(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); - JSValuePtr a0 = args.at(exec, 0); - JSValuePtr a1 = args.at(exec, 1); + JSValue a0 = args.at(0); + JSValue a1 = args.at(1); JSArray* result = constructEmptyArray(exec); unsigned i = 0; int p0 = 0; - unsigned limit = a1->isUndefined() ? 0xFFFFFFFFU : a1->toUInt32(exec); - if (a0->isObject(&RegExpObject::info)) { + unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec); + if (a0.isObject(&RegExpObject::info)) { RegExp* reg = asRegExpObject(a0)->regExp(); if (s.isEmpty() && reg->match(s, 0) >= 0) { // empty string matched by regexp -> empty array @@ -538,7 +594,7 @@ JSValuePtr stringProtoFuncSplit(ExecState* exec, JSObject*, JSValuePtr thisValue } } } else { - UString u2 = a0->toString(exec); + UString u2 = a0.toString(exec); if (u2.isEmpty()) { if (s.isEmpty()) { // empty separator matches empty string -> empty array @@ -562,16 +618,16 @@ JSValuePtr stringProtoFuncSplit(ExecState* exec, JSObject*, JSValuePtr thisValue return result; } -JSValuePtr stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); int len = s.size(); - JSValuePtr a0 = args.at(exec, 0); - JSValuePtr a1 = args.at(exec, 1); + JSValue a0 = args.at(0); + JSValue a1 = args.at(1); - double start = a0->toInteger(exec); - double length = a1->isUndefined() ? len : a1->toInteger(exec); + double start = a0.toInteger(exec); + double length = a1.isUndefined() ? len : a1.toInteger(exec); if (start >= len || length <= 0) return jsEmptyString(exec); if (start < 0) { @@ -584,16 +640,16 @@ JSValuePtr stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValuePtr thisValu return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(length)); } -JSValuePtr stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); int len = s.size(); - JSValuePtr a0 = args.at(exec, 0); - JSValuePtr a1 = args.at(exec, 1); + JSValue a0 = args.at(0); + JSValue a1 = args.at(1); - double start = a0->toNumber(exec); - double end = a1->toNumber(exec); + double start = a0.toNumber(exec); + double end = a1.toNumber(exec); if (isnan(start)) start = 0; if (isnan(end)) @@ -606,7 +662,7 @@ JSValuePtr stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValuePtr thisV start = len; if (end > len) end = len; - if (a1->isUndefined()) + if (a1.isUndefined()) end = len; if (start > end) { double temp = end; @@ -616,9 +672,9 @@ JSValuePtr stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValuePtr thisV return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(end) - static_cast<unsigned>(start)); } -JSValuePtr stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - JSString* sVal = thisValue->toThisJSString(exec); + JSString* sVal = thisValue.toThisJSString(exec); const UString& s = sVal->value(); int sSize = s.size(); @@ -650,9 +706,9 @@ JSValuePtr stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValuePtr thi return jsString(exec, UString(buffer.releaseBuffer(), length, false)); } -JSValuePtr stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - JSString* sVal = thisValue->toThisJSString(exec); + JSString* sVal = thisValue.toThisJSString(exec); const UString& s = sVal->value(); int sSize = s.size(); @@ -684,96 +740,155 @@ JSValuePtr stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValuePtr thi return jsString(exec, UString(buffer.releaseBuffer(), length, false)); } -JSValuePtr stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { if (args.size() < 1) return jsNumber(exec, 0); - UString s = thisValue->toThisString(exec); - JSValuePtr a0 = args.at(exec, 0); - return jsNumber(exec, localeCompare(s, a0->toString(exec))); + UString s = thisValue.toThisString(exec); + JSValue a0 = args.at(0); + return jsNumber(exec, localeCompare(s, a0.toString(exec))); } -JSValuePtr stringProtoFuncBig(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<big>" + s + "</big>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<big>" + s + "</big>"); } -JSValuePtr stringProtoFuncSmall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<small>" + s + "</small>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<small>" + s + "</small>"); } -JSValuePtr stringProtoFuncBlink(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<blink>" + s + "</blink>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<blink>" + s + "</blink>"); } -JSValuePtr stringProtoFuncBold(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<b>" + s + "</b>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<b>" + s + "</b>"); } -JSValuePtr stringProtoFuncFixed(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); + UString s = thisValue.toThisString(exec); return jsString(exec, "<tt>" + s + "</tt>"); } -JSValuePtr stringProtoFuncItalics(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<i>" + s + "</i>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<i>" + s + "</i>"); } -JSValuePtr stringProtoFuncStrike(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<strike>" + s + "</strike>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<strike>" + s + "</strike>"); } -JSValuePtr stringProtoFuncSub(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<sub>" + s + "</sub>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<sub>" + s + "</sub>"); } -JSValuePtr stringProtoFuncSup(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&) +JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - UString s = thisValue->toThisString(exec); - return jsString(exec, "<sup>" + s + "</sup>"); + UString s = thisValue.toThisString(exec); + return jsNontrivialString(exec, "<sup>" + s + "</sup>"); } -JSValuePtr stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); - JSValuePtr a0 = args.at(exec, 0); - return jsString(exec, "<font color=\"" + a0->toString(exec) + "\">" + s + "</font>"); + UString s = thisValue.toThisString(exec); + JSValue a0 = args.at(0); + return jsNontrivialString(exec, "<font color=\"" + a0.toString(exec) + "\">" + s + "</font>"); } -JSValuePtr stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) +JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue->toThisString(exec); - JSValuePtr a0 = args.at(exec, 0); - return jsString(exec, "<font size=\"" + a0->toString(exec) + "\">" + s + "</font>"); -} + UString s = thisValue.toThisString(exec); + JSValue a0 = args.at(0); -JSValuePtr stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) -{ - UString s = thisValue->toThisString(exec); - JSValuePtr a0 = args.at(exec, 0); - return jsString(exec, "<a name=\"" + a0->toString(exec) + "\">" + s + "</a>"); -} + uint32_t smallInteger; + if (a0.getUInt32(smallInteger) && smallInteger <= 9) { + unsigned stringSize = s.size(); + unsigned bufferSize = 22 + stringSize; + UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar))); + if (!buffer) + return jsUndefined(); + buffer[0] = '<'; + buffer[1] = 'f'; + buffer[2] = 'o'; + buffer[3] = 'n'; + buffer[4] = 't'; + buffer[5] = ' '; + buffer[6] = 's'; + buffer[7] = 'i'; + buffer[8] = 'z'; + buffer[9] = 'e'; + buffer[10] = '='; + buffer[11] = '"'; + buffer[12] = '0' + smallInteger; + buffer[13] = '"'; + buffer[14] = '>'; + memcpy(&buffer[15], s.data(), stringSize * sizeof(UChar)); + buffer[15 + stringSize] = '<'; + buffer[16 + stringSize] = '/'; + buffer[17 + stringSize] = 'f'; + buffer[18 + stringSize] = 'o'; + buffer[19 + stringSize] = 'n'; + buffer[20 + stringSize] = 't'; + buffer[21 + stringSize] = '>'; + return jsNontrivialString(exec, UString(buffer, bufferSize, false)); + } -JSValuePtr stringProtoFuncLink(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args) -{ - UString s = thisValue->toThisString(exec); - JSValuePtr a0 = args.at(exec, 0); - return jsString(exec, "<a href=\"" + a0->toString(exec) + "\">" + s + "</a>"); + return jsNontrivialString(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, "<a name=\"" + a0.toString(exec) + "\">" + s + "</a>"); +} + +JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UString s = thisValue.toThisString(exec); + JSValue a0 = args.at(0); + UString linkText = a0.toString(exec); + + unsigned linkTextSize = linkText.size(); + unsigned stringSize = s.size(); + unsigned bufferSize = 15 + linkTextSize + stringSize; + UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar))); + if (!buffer) + return jsUndefined(); + buffer[0] = '<'; + buffer[1] = 'a'; + buffer[2] = ' '; + buffer[3] = 'h'; + buffer[4] = 'r'; + buffer[5] = 'e'; + buffer[6] = 'f'; + buffer[7] = '='; + buffer[8] = '"'; + memcpy(&buffer[9], linkText.data(), linkTextSize * sizeof(UChar)); + buffer[9 + linkTextSize] = '"'; + buffer[10 + linkTextSize] = '>'; + memcpy(&buffer[11 + linkTextSize], s.data(), stringSize * sizeof(UChar)); + buffer[11 + linkTextSize + stringSize] = '<'; + buffer[12 + linkTextSize + stringSize] = '/'; + buffer[13 + linkTextSize + stringSize] = 'a'; + buffer[14 + linkTextSize + stringSize] = '>'; + return jsNontrivialString(exec, UString(buffer, bufferSize, false)); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp index 5fcde7b..3597a5c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp @@ -65,15 +65,15 @@ static const unsigned newTableSize = 16; static WTF::RefCountedLeakCounter structureCounter("Structure"); #if ENABLE(JSC_MULTIPLE_THREADS) -static Mutex ignoreSetMutex; +static Mutex& ignoreSetMutex = *(new Mutex); #endif static bool shouldIgnoreLeaks; -static HashSet<Structure*> ignoreSet; +static HashSet<Structure*>& ignoreSet = *(new HashSet<Structure*>); #endif #if DUMP_STRUCTURE_ID_STATISTICS -static HashSet<Structure*> liveStructureSet; +static HashSet<Structure*>& liveStructureSet = *(new HashSet<Structure*>); #endif void Structure::dumpStatistics() @@ -120,12 +120,10 @@ void Structure::dumpStatistics() #endif } -Structure::Structure(JSValuePtr prototype, const TypeInfo& typeInfo) +Structure::Structure(JSValue prototype, const TypeInfo& typeInfo) : m_typeInfo(typeInfo) , m_prototype(prototype) - , m_cachedPrototypeChain(0) - , m_previous(0) - , m_nameInPrevious(0) + , m_specificValueInPrevious(0) , m_propertyTable(0) , m_propertyStorageCapacity(JSObject::inlineStorageCapacity) , m_offset(noOffset) @@ -136,7 +134,7 @@ Structure::Structure(JSValuePtr prototype, const TypeInfo& typeInfo) , m_attributesInPrevious(0) { ASSERT(m_prototype); - ASSERT(m_prototype->isObject() || m_prototype->isNull()); + ASSERT(m_prototype.isObject() || m_prototype.isNull()); m_transitions.singleTransition = 0; @@ -161,8 +159,8 @@ Structure::~Structure() if (m_previous->m_usingSingleTransitionSlot) { m_previous->m_transitions.singleTransition = 0; } else { - ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), m_attributesInPrevious))); - m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious)); + ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), make_pair(m_attributesInPrevious, m_specificValueInPrevious)))); + m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), make_pair(m_attributesInPrevious, m_specificValueInPrevious))); } } @@ -178,6 +176,8 @@ Structure::~Structure() if (UString::Rep* key = m_propertyTable->entries()[i].key) key->deref(); } + + delete m_propertyTable->deletedOffsets; fastFree(m_propertyTable); } @@ -280,59 +280,34 @@ void Structure::materializePropertyMap() for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) { structure = structures[i]; structure->m_nameInPrevious->ref(); - PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, ++m_propertyTable->lastIndexUsed); + PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed); insertIntoPropertyMapHashTable(entry); } } void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject) { - bool shouldCache = propertyNames.cacheable() && !(propertyNames.size() || m_isDictionary); + bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary); - if (shouldCache) { - if (m_cachedPropertyNameArrayData) { - if (structureChainsAreEqual(m_cachedPropertyNameArrayData->cachedPrototypeChain(), cachedPrototypeChain())) { - propertyNames.setData(m_cachedPropertyNameArrayData); - return; - } + if (shouldCache && m_cachedPropertyNameArrayData) { + if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) { + propertyNames.setData(m_cachedPropertyNameArrayData); + return; } - propertyNames.setCacheable(false); + clearEnumerationCache(); } - getEnumerablePropertyNamesInternal(propertyNames); + getEnumerableNamesFromPropertyTable(propertyNames); + getEnumerableNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames); - // Add properties from the static hashtables of properties - for (const ClassInfo* info = baseObject->classInfo(); info; info = info->parentClass) { - const HashTable* table = info->propHashTable(exec); - if (!table) - continue; - table->initializeIfNeeded(exec); - ASSERT(table->table); -#if ENABLE(PERFECT_HASH_SIZE) - int hashSizeMask = table->hashSizeMask; -#else - int hashSizeMask = table->compactSize - 1; -#endif - const HashEntry* entry = table->table; - for (int i = 0; i <= hashSizeMask; ++i, ++entry) { - if (entry->key() && !(entry->attributes() & DontEnum)) - propertyNames.add(entry->key()); - } - } - - if (m_prototype->isObject()) + if (m_prototype.isObject()) { + propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly. asObject(m_prototype)->getPropertyNames(exec, propertyNames); + } if (shouldCache) { - if (m_cachedPropertyNameArrayData) - m_cachedPropertyNameArrayData->setCachedStructure(0); - m_cachedPropertyNameArrayData = propertyNames.data(); - - StructureChain* chain = cachedPrototypeChain(); - if (!chain) - chain = createCachedPrototypeChain(); - m_cachedPropertyNameArrayData->setCachedPrototypeChain(chain); + m_cachedPropertyNameArrayData->setCachedPrototypeChain(prototypeChain(exec)); m_cachedPropertyNameArrayData->setCachedStructure(this); } } @@ -352,20 +327,69 @@ void Structure::growPropertyStorageCapacity() m_propertyStorageCapacity *= 2; } -PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset) +void Structure::despecifyDictionaryFunction(const Identifier& propertyName) +{ + const UString::Rep* rep = propertyName._ustring.rep(); + + materializePropertyMapIfNecessary(); + + ASSERT(m_isDictionary); + ASSERT(m_propertyTable); + + unsigned i = rep->computedHash(); + +#if DUMP_PROPERTYMAP_STATS + ++numProbes; +#endif + + unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask]; + ASSERT(entryIndex != emptyEntryIndex); + + if (rep == m_propertyTable->entries()[entryIndex - 1].key) { + m_propertyTable->entries()[entryIndex - 1].specificValue = 0; + return; + } + +#if DUMP_PROPERTYMAP_STATS + ++numCollisions; +#endif + + unsigned k = 1 | doubleHash(rep->computedHash()); + + while (1) { + i += k; + +#if DUMP_PROPERTYMAP_STATS + ++numRehashes; +#endif + + entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask]; + ASSERT(entryIndex != emptyEntryIndex); + + if (rep == m_propertyTable->entries()[entryIndex - 1].key) { + m_propertyTable->entries()[entryIndex - 1].specificValue = 0; + return; + } + } +} + +PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset) { ASSERT(!structure->m_isDictionary); ASSERT(structure->typeInfo().type() == ObjectType); if (structure->m_usingSingleTransitionSlot) { Structure* existingTransition = structure->m_transitions.singleTransition; - if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep() && existingTransition->m_attributesInPrevious == attributes) { + if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep() + && existingTransition->m_attributesInPrevious == attributes + && existingTransition->m_specificValueInPrevious == specificValue) { + ASSERT(structure->m_transitions.singleTransition->m_offset != noOffset); offset = structure->m_transitions.singleTransition->m_offset; return existingTransition; } } else { - if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes))) { + if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), make_pair(attributes, specificValue)))) { ASSERT(existingTransition->m_offset != noOffset); offset = existingTransition->m_offset; return existingTransition; @@ -375,25 +399,27 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct return 0; } -PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset) +PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset) { ASSERT(!structure->m_isDictionary); ASSERT(structure->typeInfo().type() == ObjectType); - ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, offset)); + ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset)); if (structure->transitionCount() > s_maxTransitionLength) { RefPtr<Structure> transition = toDictionaryTransition(structure); - offset = transition->put(propertyName, attributes); + offset = transition->put(propertyName, attributes, specificValue); if (transition->propertyStorageSize() > transition->propertyStorageCapacity()) transition->growPropertyStorageCapacity(); return transition.release(); } RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo()); + transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain; transition->m_previous = structure; transition->m_nameInPrevious = propertyName.ustring().rep(); transition->m_attributesInPrevious = attributes; + transition->m_specificValueInPrevious = specificValue; transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; @@ -411,7 +437,7 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con transition->createPropertyMapHashTable(); } - offset = transition->put(propertyName, attributes); + offset = transition->put(propertyName, attributes, specificValue); if (transition->propertyStorageSize() > transition->propertyStorageCapacity()) transition->growPropertyStorageCapacity(); @@ -427,9 +453,9 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con structure->m_usingSingleTransitionSlot = false; StructureTransitionTable* transitionTable = new StructureTransitionTable; structure->m_transitions.table = transitionTable; - transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition); + transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), make_pair(existingTransition->m_attributesInPrevious, existingTransition->m_specificValueInPrevious)), existingTransition); } - structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get()); + structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), make_pair(attributes, specificValue)), transition.get()); return transition.release(); } @@ -444,7 +470,7 @@ PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, return transition.release(); } -PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValuePtr prototype) +PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype) { RefPtr<Structure> transition = create(prototype, structure->typeInfo()); @@ -460,6 +486,25 @@ PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, return transition.release(); } +PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction) +{ + RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo()); + + transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; + transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; + + // Don't set m_offset, as one can not transition to this. + + structure->materializePropertyMapIfNecessary(); + transition->m_propertyTable = structure->copyPropertyTable(); + transition->m_isPinnedPropertyTable = true; + + bool removed = transition->despecifyFunction(replaceFunction); + ASSERT_UNUSED(removed, removed); + + return transition.release(); +} + PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure) { RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo()); @@ -507,14 +552,14 @@ PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure) return structure; } -size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes) +size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue) { ASSERT(!m_transitions.singleTransition); materializePropertyMapIfNecessary(); m_isPinnedPropertyTable = true; - size_t offset = put(propertyName, attributes); + size_t offset = put(propertyName, attributes, specificValue); if (propertyStorageSize() > propertyStorageCapacity()) growPropertyStorageCapacity(); clearEnumerationCache(); @@ -534,20 +579,6 @@ size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName return offset; } -StructureChain* Structure::createCachedPrototypeChain() -{ - ASSERT(typeInfo().type() == ObjectType); - ASSERT(!m_cachedPrototypeChain); - - JSValuePtr prototype = storedPrototype(); - if (JSImmediate::isImmediate(prototype)) - return 0; - - RefPtr<StructureChain> chain = StructureChain::create(asObject(prototype)->structure()); - setCachedPrototypeChain(chain.release()); - return cachedPrototypeChain(); -} - #if DUMP_PROPERTYMAP_STATS static int numProbes; @@ -604,16 +635,12 @@ PropertyMapHashTable* Structure::copyPropertyTable() return newTable; } -size_t Structure::get(const Identifier& propertyName, unsigned& attributes) +size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue) { - ASSERT(!propertyName.isNull()); - materializePropertyMapIfNecessary(); if (!m_propertyTable) return notFound; - UString::Rep* rep = propertyName._ustring.rep(); - unsigned i = rep->computedHash(); #if DUMP_PROPERTYMAP_STATS @@ -626,6 +653,7 @@ size_t Structure::get(const Identifier& propertyName, unsigned& attributes) if (rep == m_propertyTable->entries()[entryIndex - 1].key) { attributes = m_propertyTable->entries()[entryIndex - 1].attributes; + specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue; return m_propertyTable->entries()[entryIndex - 1].offset; } @@ -648,12 +676,64 @@ size_t Structure::get(const Identifier& propertyName, unsigned& attributes) if (rep == m_propertyTable->entries()[entryIndex - 1].key) { attributes = m_propertyTable->entries()[entryIndex - 1].attributes; + specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue; return m_propertyTable->entries()[entryIndex - 1].offset; } } } -size_t Structure::put(const Identifier& propertyName, unsigned attributes) +bool Structure::despecifyFunction(const Identifier& propertyName) +{ + ASSERT(!propertyName.isNull()); + + materializePropertyMapIfNecessary(); + if (!m_propertyTable) + return false; + + UString::Rep* rep = propertyName._ustring.rep(); + + unsigned i = rep->computedHash(); + +#if DUMP_PROPERTYMAP_STATS + ++numProbes; +#endif + + unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask]; + if (entryIndex == emptyEntryIndex) + return false; + + if (rep == m_propertyTable->entries()[entryIndex - 1].key) { + ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue); + m_propertyTable->entries()[entryIndex - 1].specificValue = 0; + return true; + } + +#if DUMP_PROPERTYMAP_STATS + ++numCollisions; +#endif + + unsigned k = 1 | doubleHash(rep->computedHash()); + + while (1) { + i += k; + +#if DUMP_PROPERTYMAP_STATS + ++numRehashes; +#endif + + entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask]; + if (entryIndex == emptyEntryIndex) + return false; + + if (rep == m_propertyTable->entries()[entryIndex - 1].key) { + ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue); + m_propertyTable->entries()[entryIndex - 1].specificValue = 0; + return true; + } + } +} + +size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue) { ASSERT(!propertyName.isNull()); ASSERT(get(propertyName) == notFound); @@ -723,6 +803,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes) rep->ref(); m_propertyTable->entries()[entryIndex - 1].key = rep; m_propertyTable->entries()[entryIndex - 1].attributes = attributes; + m_propertyTable->entries()[entryIndex - 1].specificValue = specificValue; m_propertyTable->entries()[entryIndex - 1].index = ++m_propertyTable->lastIndexUsed; unsigned newOffset; @@ -795,6 +876,7 @@ size_t Structure::remove(const Identifier& propertyName) key->deref(); m_propertyTable->entries()[entryIndex - 1].key = 0; m_propertyTable->entries()[entryIndex - 1].attributes = 0; + m_propertyTable->entries()[entryIndex - 1].specificValue = 0; m_propertyTable->entries()[entryIndex - 1].offset = 0; if (!m_propertyTable->deletedOffsets) @@ -922,7 +1004,7 @@ static int comparePropertyMapEntryIndices(const void* a, const void* b) return 0; } -void Structure::getEnumerablePropertyNamesInternal(PropertyNameArray& propertyNames) +void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyNames) { materializePropertyMapIfNecessary(); if (!m_propertyTable) @@ -979,6 +1061,25 @@ void Structure::getEnumerablePropertyNamesInternal(PropertyNameArray& propertyNa } } +void Structure::getEnumerableNamesFromClassInfoTable(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames) +{ + // Add properties from the static hashtables of properties + for (; classInfo; classInfo = classInfo->parentClass) { + const HashTable* table = classInfo->propHashTable(exec); + if (!table) + continue; + table->initializeIfNeeded(exec); + ASSERT(table->table); + + int hashSizeMask = table->compactSize - 1; + const HashEntry* entry = table->table; + for (int i = 0; i <= hashSizeMask; ++i, ++entry) { + if (entry->key() && !(entry->attributes() & DontEnum)) + propertyNames.add(entry->key()); + } + } +} + #if DO_PROPERTYMAP_CONSTENCY_CHECK void Structure::checkConsistency() diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h index c326b3f..866999d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h @@ -51,7 +51,7 @@ namespace JSC { class Structure : public RefCounted<Structure> { public: friend class JIT; - static PassRefPtr<Structure> create(JSValuePtr prototype, const TypeInfo& typeInfo) + static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo) { return adoptRef(new Structure(prototype, typeInfo)); } @@ -61,10 +61,11 @@ namespace JSC { static void dumpStatistics(); - static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, size_t& offset); - static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, size_t& offset); + static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); + static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset); - static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValuePtr prototype); + static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype); + static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&); static PassRefPtr<Structure> getterSetterTransition(Structure*); static PassRefPtr<Structure> toDictionaryTransition(Structure*); static PassRefPtr<Structure> fromDictionaryTransition(Structure*); @@ -73,34 +74,38 @@ namespace JSC { void mark() { - if (!m_prototype->marked()) - m_prototype->mark(); + if (!m_prototype.marked()) + m_prototype.mark(); } // These should be used with caution. - size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes); + size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue); size_t removePropertyWithoutTransition(const Identifier& propertyName); - void setPrototypeWithoutTransition(JSValuePtr prototype) { m_prototype = prototype; } + void setPrototypeWithoutTransition(JSValue prototype) { m_prototype = prototype; } bool isDictionary() const { return m_isDictionary; } const TypeInfo& typeInfo() const { return m_typeInfo; } - JSValuePtr storedPrototype() const { return m_prototype; } - JSValuePtr prototypeForLookup(ExecState*); + JSValue storedPrototype() const { return m_prototype; } + JSValue prototypeForLookup(ExecState*) const; + StructureChain* prototypeChain(ExecState*) const; Structure* previousID() const { return m_previous.get(); } - StructureChain* createCachedPrototypeChain(); - void setCachedPrototypeChain(PassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } - StructureChain* cachedPrototypeChain() const { return m_cachedPrototypeChain.get(); } - void growPropertyStorageCapacity(); size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; } size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; } + bool isUsingInlineStorage() const; size_t get(const Identifier& propertyName); - size_t get(const Identifier& propertyName, unsigned& attributes); + size_t get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue); + size_t get(const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue) + { + ASSERT(!propertyName.isNull()); + return get(propertyName._ustring.rep(), attributes, specificValue); + } + void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*); bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; } @@ -108,12 +113,16 @@ namespace JSC { bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; } + JSCell* specificValue() { return m_specificValueInPrevious; } + void despecifyDictionaryFunction(const Identifier& propertyName); + private: - Structure(JSValuePtr prototype, const TypeInfo&); + Structure(JSValue prototype, const TypeInfo&); - size_t put(const Identifier& propertyName, unsigned attributes); + size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue); size_t remove(const Identifier& propertyName); - void getEnumerablePropertyNamesInternal(PropertyNameArray&); + void getEnumerableNamesFromPropertyTable(PropertyNameArray&); + void getEnumerableNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&); void expandPropertyMapHashTable(); void rehashPropertyMapHashTable(); @@ -123,6 +132,8 @@ namespace JSC { void insertIntoPropertyMapHashTable(const PropertyMapEntry&); void checkConsistency(); + bool despecifyFunction(const Identifier&); + PropertyMapHashTable* copyPropertyTable(); void materializePropertyMap(); void materializePropertyMapIfNecessary() @@ -134,16 +145,13 @@ namespace JSC { void clearEnumerationCache(); - void* addressOfCount() - { - return &m_refCount; - } - signed char transitionCount() const { // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both. return m_offset == noOffset ? 0 : m_offset + 1; } + + bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const; static const unsigned emptyEntryIndex = 0; @@ -153,8 +161,8 @@ namespace JSC { TypeInfo m_typeInfo; - JSValuePtr m_prototype; - RefPtr<StructureChain> m_cachedPrototypeChain; + JSValue m_prototype; + mutable RefPtr<StructureChain> m_cachedPrototypeChain; RefPtr<Structure> m_previous; RefPtr<UString::Rep> m_nameInPrevious; @@ -163,6 +171,7 @@ namespace JSC { Structure* singleTransition; StructureTransitionTable* table; } m_transitions; + JSCell* m_specificValueInPrevious; RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData; @@ -175,7 +184,7 @@ namespace JSC { bool m_isPinnedPropertyTable : 1; bool m_hasGetterSetterProperties : 1; bool m_usingSingleTransitionSlot : 1; - unsigned m_attributesInPrevious : 5; + unsigned m_attributesInPrevious : 7; }; inline size_t Structure::get(const Identifier& propertyName) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.cpp index 84c67c3..085876c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.cpp @@ -32,42 +32,18 @@ namespace JSC { -StructureChain::StructureChain(Structure* structure) +StructureChain::StructureChain(Structure* head) { - size_t size = 1; - - Structure* tmp = structure; - while (!tmp->storedPrototype()->isNull()) { + size_t size = 0; + for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure()) ++size; - tmp = asCell(tmp->storedPrototype())->structure(); - } m_vector.set(new RefPtr<Structure>[size + 1]); - size_t i; - for (i = 0; i < size - 1; ++i) { - m_vector[i] = structure; - structure = asObject(structure->storedPrototype())->structure(); - } - m_vector[i] = structure; - m_vector[i + 1] = 0; -} - -bool structureChainsAreEqual(StructureChain* chainA, StructureChain* chainB) -{ - if (!chainA || !chainB) - return false; - - RefPtr<Structure>* a = chainA->head(); - RefPtr<Structure>* b = chainB->head(); - while (1) { - if (*a != *b) - return false; - if (!*a) - return true; - a++; - b++; - } + size_t i = 0; + for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure()) + m_vector[i++] = current; + m_vector[i] = 0; } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.h b/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.h index a3a1be2..795e649 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StructureChain.h @@ -37,18 +37,15 @@ namespace JSC { class StructureChain : public RefCounted<StructureChain> { public: - static PassRefPtr<StructureChain> create(Structure* structure) { return adoptRef(new StructureChain(structure)); } - + static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); } RefPtr<Structure>* head() { return m_vector.get(); } private: - StructureChain(Structure* structure); + StructureChain(Structure* head); OwnArrayPtr<RefPtr<Structure> > m_vector; }; - bool structureChainsAreEqual(StructureChain*, StructureChain*); - } // namespace JSC #endif // StructureChain_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StructureTransitionTable.h b/src/3rdparty/webkit/JavaScriptCore/runtime/StructureTransitionTable.h index 1543049..804cbeb 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/StructureTransitionTable.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StructureTransitionTable.h @@ -37,7 +37,7 @@ namespace JSC { class Structure; struct StructureTransitionTableHash { - typedef std::pair<RefPtr<UString::Rep>, unsigned> Key; + typedef std::pair<RefPtr<UString::Rep>, std::pair<unsigned, JSCell*> > Key; static unsigned hash(const Key& p) { return p.first->computedHash(); @@ -53,13 +53,14 @@ namespace JSC { struct StructureTransitionTableHashTraits { typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits; - typedef WTF::GenericHashTraits<unsigned> SecondTraits; - typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType; + typedef WTF::GenericHashTraits<unsigned> SecondFirstTraits; + typedef WTF::GenericHashTraits<JSCell*> SecondSecondTraits; + typedef std::pair<FirstTraits::TraitType, std::pair<SecondFirstTraits::TraitType, SecondSecondTraits::TraitType> > TraitType; - static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; - static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } + static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondFirstTraits::emptyValueIsZero && SecondSecondTraits::emptyValueIsZero; + static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), std::make_pair(SecondFirstTraits::emptyValue(), SecondSecondTraits::emptyValue())); } - static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; + static const bool needsDestruction = FirstTraits::needsDestruction || SecondFirstTraits::needsDestruction || SecondSecondTraits::needsDestruction; static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); } static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.cpp new file mode 100644 index 0000000..30ba6e9 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> + * + * 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. + */ + +#include "config.h" +#include "TimeoutChecker.h" + +#include "CallFrame.h" +#include "JSGlobalObject.h" + +#if PLATFORM(DARWIN) +#include <mach/mach.h> +#endif + +#if HAVE(SYS_TIME_H) +#include <sys/time.h> +#endif + +#if PLATFORM(WIN_OS) +#include <windows.h> +#endif + +#if PLATFORM(QT) +#include <QDateTime> +#endif + +using namespace std; + +namespace JSC { + +// Number of ticks before the first timeout check is done. +static const int ticksUntilFirstCheck = 1024; + +// Number of milliseconds between each timeout check. +static const int intervalBetweenChecks = 1000; + +// Returns the time the current thread has spent executing, in milliseconds. +static inline unsigned getCPUTime() +{ +#if PLATFORM(DARWIN) + mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT; + thread_basic_info_data_t info; + + // Get thread information + mach_port_t threadPort = mach_thread_self(); + thread_info(threadPort, THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount); + mach_port_deallocate(mach_task_self(), threadPort); + + unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000; + time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000; + + return time; +#elif HAVE(SYS_TIME_H) + // FIXME: This should probably use getrusage with the RUSAGE_THREAD flag. + struct timeval tv; + gettimeofday(&tv, 0); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +#elif PLATFORM(QT) + QDateTime t = QDateTime::currentDateTime(); + return t.toTime_t() * 1000 + t.time().msec(); +#elif PLATFORM(WIN_OS) + union { + FILETIME fileTime; + unsigned long long fileTimeAsLong; + } userTime, kernelTime; + + // GetThreadTimes won't accept NULL arguments so we pass these even though + // they're not used. + FILETIME creationTime, exitTime; + + GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime); + + return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000; +#else +#error Platform does not have getCurrentTime function +#endif +} + +TimeoutChecker::TimeoutChecker() + : m_timeoutInterval(0) + , m_startCount(0) +{ + reset(); +} + +void TimeoutChecker::reset() +{ + m_ticksUntilNextCheck = ticksUntilFirstCheck; + m_timeAtLastCheck = 0; + m_timeExecuting = 0; +} + +bool TimeoutChecker::didTimeOut(ExecState* exec) +{ + unsigned currentTime = getCPUTime(); + + if (!m_timeAtLastCheck) { + // Suspicious amount of looping in a script -- start timing it + m_timeAtLastCheck = currentTime; + return false; + } + + unsigned timeDiff = currentTime - m_timeAtLastCheck; + + if (timeDiff == 0) + timeDiff = 1; + + m_timeExecuting += timeDiff; + m_timeAtLastCheck = currentTime; + + // Adjust the tick threshold so we get the next checkTimeout call in the + // interval specified in intervalBetweenChecks. + m_ticksUntilNextCheck = static_cast<unsigned>((static_cast<float>(intervalBetweenChecks) / timeDiff) * m_ticksUntilNextCheck); + // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the + // preferred script check time interval. + if (m_ticksUntilNextCheck == 0) + m_ticksUntilNextCheck = ticksUntilFirstCheck; + + if (m_timeoutInterval && m_timeExecuting > m_timeoutInterval) { + if (exec->dynamicGlobalObject()->shouldInterruptScript()) + return true; + + reset(); + } + + return false; +} + +} // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.h b/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.h new file mode 100644 index 0000000..7bfa6d0 --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2008 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. + * 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 TimeoutChecker_h +#define TimeoutChecker_h + +#include <wtf/Assertions.h> + +namespace JSC { + + class ExecState; + + class TimeoutChecker { + public: + TimeoutChecker(); + + void setTimeoutInterval(unsigned timeoutInterval) { m_timeoutInterval = timeoutInterval; } + + unsigned ticksUntilNextCheck() { return m_ticksUntilNextCheck; } + + void start() + { + if (!m_startCount) + reset(); + ++m_startCount; + } + + void stop() + { + ASSERT(m_startCount); + --m_startCount; + } + + void reset(); + + bool didTimeOut(ExecState*); + + private: + unsigned m_timeoutInterval; + unsigned m_timeAtLastCheck; + unsigned m_timeExecuting; + unsigned m_startCount; + unsigned m_ticksUntilNextCheck; + }; + +} // namespace JSC + +#endif // TimeoutChecker_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/TypeInfo.h b/src/3rdparty/webkit/JavaScriptCore/runtime/TypeInfo.h index 52da347..70aeed3 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/TypeInfo.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/TypeInfo.h @@ -35,13 +35,22 @@ namespace JSC { static const unsigned MasqueradesAsUndefined = 1; static const unsigned ImplementsHasInstance = 1 << 1; static const unsigned OverridesHasInstance = 1 << 2; - static const unsigned NeedsThisConversion = 1 << 3; - static const unsigned HasStandardGetOwnPropertySlot = 1 << 4; + static const unsigned ImplementsDefaultHasInstance = 1 << 3; + static const unsigned NeedsThisConversion = 1 << 4; + static const unsigned HasStandardGetOwnPropertySlot = 1 << 5; class TypeInfo { friend class JIT; public: - TypeInfo(JSType type, unsigned flags = 0) : m_type(type), m_flags(flags) { } + TypeInfo(JSType type, unsigned flags = 0) + : m_type(type) + { + // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance) + if ((flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance) + m_flags = flags | ImplementsDefaultHasInstance; + else + m_flags = flags; + } JSType type() const { return m_type; } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/UString.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/UString.cpp index 45df248..0eb46da 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/UString.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/UString.cpp @@ -1,7 +1,8 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) + * Copyright (C) 2009 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -61,6 +62,9 @@ namespace JSC { extern const double NaN; extern const double Inf; +// This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. +static const int minLengthToShare = 30; + static inline size_t overflowIndicator() { return std::numeric_limits<size_t>::max(); } static inline size_t maxUChars() { return std::numeric_limits<size_t>::max() / sizeof(UChar); } @@ -92,7 +96,7 @@ static inline void copyChars(UChar* destination, const UChar* source, unsigned n memcpy(destination, source, numCharacters * sizeof(UChar)); } -COMPILE_ASSERT(sizeof(UChar) == 2, uchar_is_2_bytes) +COMPILE_ASSERT(sizeof(UChar) == 2, uchar_is_2_bytes); CString::CString(const char* c) : m_length(strlen(c)) @@ -186,86 +190,59 @@ bool operator==(const CString& c1, const CString& c2) // 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; -UString::Rep UString::Rep::null = { 0, 0, INT_MAX / 2, 0, 1, &UString::Rep::null, 0, 0, 0, 0, 0, 0 }; -UString::Rep UString::Rep::empty = { 0, 0, INT_MAX / 2, 0, 1, &UString::Rep::empty, 0, &sharedEmptyChar, 0, 0, 0, 0 }; - -static char* statBuffer = 0; // Only used for debugging via UString::ascii(). +UString::BaseString* UString::Rep::nullBaseString; +UString::BaseString* UString::Rep::emptyBaseString; +UString* UString::nullUString; -PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar* d, int l) +static void initializeStaticBaseString(UString::BaseString& base) { - UChar* copyD = static_cast<UChar*>(fastMalloc(l * sizeof(UChar))); - copyChars(copyD, d, l); - return create(copyD, l); + base.rc = INT_MAX / 2; + base.m_identifierTableAndFlags.setFlag(UString::Rep::StaticFlag); + base.checkConsistency(); } -PassRefPtr<UString::Rep> UString::Rep::create(UChar* d, int l) +void initializeUString() { - Rep* r = new Rep; - r->offset = 0; - r->len = l; - r->rc = 1; - r->_hash = 0; - r->m_identifierTable = 0; - r->baseString = r; - r->reportedCost = 0; - r->buf = d; - r->usedCapacity = l; - r->capacity = l; - r->usedPreCapacity = 0; - r->preCapacity = 0; + UString::Rep::nullBaseString = new UString::BaseString(0, 0); + initializeStaticBaseString(*UString::Rep::nullBaseString); - r->checkConsistency(); + UString::Rep::emptyBaseString = new UString::BaseString(&sharedEmptyChar, 0); + initializeStaticBaseString(*UString::Rep::emptyBaseString); - // steal the single reference this Rep was created with - return adoptRef(r); + UString::nullUString = new UString; } -PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, int length) -{ - ASSERT(base); - base->checkConsistency(); - - int baseOffset = base->offset; - - base = base->baseString; - - ASSERT(-(offset + baseOffset) <= base->usedPreCapacity); - ASSERT(offset + baseOffset + length <= base->usedCapacity); - - Rep* r = new Rep; - r->offset = baseOffset + offset; - r->len = length; - r->rc = 1; - r->_hash = 0; - r->m_identifierTable = 0; - r->baseString = base.releaseRef(); - r->reportedCost = 0; - r->buf = 0; - r->usedCapacity = 0; - r->capacity = 0; - r->usedPreCapacity = 0; - r->preCapacity = 0; - - r->checkConsistency(); +static char* statBuffer = 0; // Only used for debugging via UString::ascii(). - // steal the single reference this Rep was created with - return adoptRef(r); +PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar* d, int l) +{ + UChar* copyD = static_cast<UChar*>(fastMalloc(l * sizeof(UChar))); + copyChars(copyD, d, l); + return create(copyD, l); } PassRefPtr<UString::Rep> UString::Rep::createFromUTF8(const char* string) { if (!string) - return &UString::Rep::null; + return &UString::Rep::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::Rep::null; + return &UString::Rep::null(); return UString::Rep::createCopying(buffer.data(), p - buffer.data()); } +PassRefPtr<UString::Rep> UString::Rep::create(UChar* string, int length, PassRefPtr<UString::SharedUChar> sharedBuffer) +{ + PassRefPtr<UString::Rep> rep = create(string, length); + rep->baseString()->setSharedBuffer(sharedBuffer); + rep->checkConsistency(); + return rep; +} + void UString::Rep::destroy() { checkConsistency(); @@ -275,10 +252,15 @@ void UString::Rep::destroy() if (!isStatic()) { if (identifierTable()) Identifier::remove(this); - if (baseString == this) - fastFree(buf); - else - baseString->deref(); + + UString::BaseString* base = baseString(); + if (base == this) { + if (m_sharedBuffer) + m_sharedBuffer->deref(); + else + fastFree(base->buf); + } else + base->deref(); delete this; } @@ -380,17 +362,10 @@ unsigned UString::Rep::computeHash(const char* s, int l) #ifndef NDEBUG void UString::Rep::checkConsistency() const { - // Only base strings have non-zero shared data. - if (this != baseString) { - ASSERT(!buf); - ASSERT(!usedCapacity); - ASSERT(!capacity); - ASSERT(!usedPreCapacity); - ASSERT(!preCapacity); - } + const UString::BaseString* base = baseString(); // There is no recursion for base strings. - ASSERT(baseString == baseString->baseString); + ASSERT(base == base->baseString()); if (isStatic()) { // There are only two static strings: null and empty. @@ -401,63 +376,148 @@ void UString::Rep::checkConsistency() const } // The string fits in buffer. - ASSERT(baseString->usedPreCapacity <= baseString->preCapacity); - ASSERT(baseString->usedCapacity <= baseString->capacity); - ASSERT(-offset <= baseString->usedPreCapacity); - ASSERT(offset + len <= baseString->usedCapacity); + ASSERT(base->usedPreCapacity <= base->preCapacity); + ASSERT(base->usedCapacity <= base->capacity); + ASSERT(-offset <= base->usedPreCapacity); + ASSERT(offset + len <= base->usedCapacity); } #endif -// put these early so they can be inlined -static inline size_t expandedSize(size_t size, size_t otherSize) +UString::SharedUChar* UString::BaseString::sharedBuffer() { - // Do the size calculation in two parts, returning overflowIndicator if - // we overflow the maximum value that we can handle. - if (size > maxUChars()) - return overflowIndicator(); - - size_t expandedSize = ((size + 10) / 10 * 11) + 1; - if (maxUChars() - expandedSize < otherSize) - return overflowIndicator(); + if (len < minLengthToShare) + return 0; - return expandedSize + otherSize; + if (!m_sharedBuffer) + setSharedBuffer(SharedUChar::create(new OwnFastMallocPtr<UChar>(buf))); + return m_sharedBuffer; } -inline int UString::usedCapacity() const +void UString::BaseString::setSharedBuffer(PassRefPtr<UString::SharedUChar> sharedBuffer) { - return m_rep->baseString->usedCapacity; + // The manual steps below are because m_sharedBuffer can't be a RefPtr. m_sharedBuffer + // is in a union with another variable to avoid making BaseString any larger. + if (m_sharedBuffer) + m_sharedBuffer->deref(); + m_sharedBuffer = sharedBuffer.releaseRef(); } -inline int UString::usedPreCapacity() const +bool UString::BaseString::slowIsBufferReadOnly() { - return m_rep->baseString->usedPreCapacity; + // The buffer may not be modified as soon as the underlying data has been shared with another class. + if (m_sharedBuffer->isShared()) + return true; + + // At this point, we know it that the underlying buffer isn't shared outside of this base class, + // so get rid of m_sharedBuffer. + OwnPtr<OwnFastMallocPtr<UChar> > mallocPtr(m_sharedBuffer->release()); + UChar* unsharedBuf = const_cast<UChar*>(mallocPtr->release()); + setSharedBuffer(0); + preCapacity += (buf - unsharedBuf); + buf = unsharedBuf; + return false; } +// Put these early so they can be inlined. +static inline size_t expandedSize(size_t capacitySize, size_t precapacitySize) +{ + // Combine capacitySize & precapacitySize to produce a single size to allocate, + // check that doing so does not result in overflow. + size_t size = capacitySize + precapacitySize; + if (size < capacitySize) + return overflowIndicator(); + + // Small Strings (up to 4 pages): + // Expand the allocation size to 112.5% of the amount requested. This is largely sicking + // to our previous policy, however 112.5% is cheaper to calculate. + if (size < 0x4000) { + size_t expandedSize = ((size + (size >> 3)) | 15) + 1; + // Given the limited range within which we calculate the expansion in this + // fashion the above calculation should never overflow. + ASSERT(expandedSize >= size); + ASSERT(expandedSize < maxUChars()); + return expandedSize; + } + + // Medium Strings (up to 128 pages): + // For pages covering multiple pages over-allocation is less of a concern - any unused + // space will not be paged in if it is not used, so this is purely a VM overhead. For + // these strings allocate 2x the requested size. + if (size < 0x80000) { + size_t expandedSize = ((size + size) | 0xfff) + 1; + // Given the limited range within which we calculate the expansion in this + // fashion the above calculation should never overflow. + ASSERT(expandedSize >= size); + ASSERT(expandedSize < maxUChars()); + return expandedSize; + } + + // Large Strings (to infinity and beyond!): + // Revert to our 112.5% policy - probably best to limit the amount of unused VM we allow + // any individual string be responsible for. + size_t expandedSize = ((size + (size >> 3)) | 0xfff) + 1; + + // Check for overflow - any result that is at least as large as requested (but + // still below the limit) is okay. + if ((expandedSize >= size) && (expandedSize < maxUChars())) + return expandedSize; + return overflowIndicator(); +} static inline bool expandCapacity(UString::Rep* rep, int requiredLength) { rep->checkConsistency(); + ASSERT(!rep->baseString()->isBufferReadOnly()); - UString::Rep* r = rep->baseString; + UString::BaseString* base = rep->baseString(); - if (requiredLength > r->capacity) { - size_t newCapacity = expandedSize(requiredLength, r->preCapacity); - UChar* oldBuf = r->buf; - r->buf = reallocChars(r->buf, newCapacity); - if (!r->buf) { - r->buf = oldBuf; + if (requiredLength > base->capacity) { + size_t newCapacity = expandedSize(requiredLength, base->preCapacity); + UChar* oldBuf = base->buf; + base->buf = reallocChars(base->buf, newCapacity); + if (!base->buf) { + base->buf = oldBuf; return false; } - r->capacity = newCapacity - r->preCapacity; + base->capacity = newCapacity - base->preCapacity; } - if (requiredLength > r->usedCapacity) - r->usedCapacity = requiredLength; + if (requiredLength > base->usedCapacity) + base->usedCapacity = requiredLength; rep->checkConsistency(); return true; } +bool UString::Rep::reserveCapacity(int capacity) +{ + // If this is an empty string there is no point 'growing' it - just allocate a new one. + // If the BaseString is shared with another string that is using more capacity than this + // string is, then growing the buffer won't help. + // If the BaseString's buffer is readonly, then it isn't allowed to grow. + UString::BaseString* base = baseString(); + if (!base->buf || !base->capacity || (offset + len) != base->usedCapacity || base->isBufferReadOnly()) + return false; + + // If there is already sufficient capacity, no need to grow! + if (capacity <= base->capacity) + return true; + + checkConsistency(); + + size_t newCapacity = expandedSize(capacity, base->preCapacity); + UChar* oldBuf = base->buf; + base->buf = reallocChars(base->buf, newCapacity); + if (!base->buf) { + base->buf = oldBuf; + return false; + } + base->capacity = newCapacity - base->preCapacity; + + checkConsistency(); + return true; +} + void UString::expandCapacity(int requiredLength) { if (!JSC::expandCapacity(m_rep.get(), requiredLength)) @@ -467,42 +527,43 @@ void UString::expandCapacity(int requiredLength) void UString::expandPreCapacity(int requiredPreCap) { m_rep->checkConsistency(); + ASSERT(!m_rep->baseString()->isBufferReadOnly()); - Rep* r = m_rep->baseString; + BaseString* base = m_rep->baseString(); - if (requiredPreCap > r->preCapacity) { - size_t newCapacity = expandedSize(requiredPreCap, r->capacity); - int delta = newCapacity - r->capacity - r->preCapacity; + if (requiredPreCap > base->preCapacity) { + size_t newCapacity = expandedSize(requiredPreCap, base->capacity); + int delta = newCapacity - base->capacity - base->preCapacity; UChar* newBuf = allocChars(newCapacity); if (!newBuf) { makeNull(); return; } - copyChars(newBuf + delta, r->buf, r->capacity + r->preCapacity); - fastFree(r->buf); - r->buf = newBuf; + copyChars(newBuf + delta, base->buf, base->capacity + base->preCapacity); + fastFree(base->buf); + base->buf = newBuf; - r->preCapacity = newCapacity - r->capacity; + base->preCapacity = newCapacity - base->capacity; } - if (requiredPreCap > r->usedPreCapacity) - r->usedPreCapacity = requiredPreCap; + if (requiredPreCap > base->usedPreCapacity) + base->usedPreCapacity = requiredPreCap; m_rep->checkConsistency(); } -PassRefPtr<UString::Rep> createRep(const char* c) +static PassRefPtr<UString::Rep> createRep(const char* c) { if (!c) - return &UString::Rep::null; + return &UString::Rep::null(); if (!c[0]) - return &UString::Rep::empty; + return &UString::Rep::empty(); size_t length = strlen(c); UChar* d = allocChars(length); if (!d) - return &UString::Rep::null; + return &UString::Rep::null(); else { 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 @@ -519,7 +580,7 @@ UString::UString(const char* c) UString::UString(const UChar* c, int length) { if (length == 0) - m_rep = &Rep::empty; + m_rep = &Rep::empty(); else m_rep = Rep::createCopying(c, length); } @@ -527,7 +588,7 @@ UString::UString(const UChar* c, int length) UString::UString(UChar* c, int length, bool copy) { if (length == 0) - m_rep = &Rep::empty; + m_rep = &Rep::empty(); else if (copy) m_rep = Rep::createCopying(c, length); else @@ -537,11 +598,22 @@ UString::UString(UChar* c, int length, bool copy) UString::UString(const Vector<UChar>& buffer) { if (!buffer.size()) - m_rep = &Rep::empty; + m_rep = &Rep::empty(); else m_rep = Rep::createCopying(buffer.data(), buffer.size()); } +static ALWAYS_INLINE int newCapacityWithOverflowCheck(const int currentCapacity, const int extendLength, const bool plusOne = false) +{ + ASSERT_WITH_MESSAGE(extendLength >= 0, "extendedLength = %d", extendLength); + + const int plusLength = plusOne ? 1 : 0; + if (currentCapacity > std::numeric_limits<int>::max() - extendLength - plusLength) + CRASH(); + + return currentCapacity + extendLength + plusLength; +} + static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Rep> r, const UChar* tData, int tSize) { RefPtr<UString::Rep> rep = r; @@ -551,6 +623,7 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re int thisSize = rep->size(); int thisOffset = rep->offset; int length = thisSize + tSize; + UString::BaseString* base = rep->baseString(); // possible cases: if (tSize == 0) { @@ -558,34 +631,34 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re } else if (thisSize == 0) { // this is empty rep = UString::Rep::createCopying(tData, tSize); - } else if (rep->baseIsSelf() && rep->rc == 1) { + } else if (rep == base && !base->isShared()) { // this is direct and has refcount of 1 (so we can just alter it directly) - if (!expandCapacity(rep.get(), thisOffset + length)) - rep = &UString::Rep::null; + if (!expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length))) + rep = &UString::Rep::null(); if (rep->data()) { copyChars(rep->data() + thisSize, tData, tSize); rep->len = length; rep->_hash = 0; } - } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) { + } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) { // this reaches the end of the buffer - extend it if it's long enough to append to - if (!expandCapacity(rep.get(), thisOffset + length)) - rep = &UString::Rep::null; + if (!expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length))) + rep = &UString::Rep::null(); if (rep->data()) { copyChars(rep->data() + thisSize, tData, tSize); rep = UString::Rep::create(rep, 0, length); } } else { - // this is shared with someone using more capacity, gotta make a whole new string + // This is shared in some way that prevents us from modifying base, so we must make a whole new string. size_t newCapacity = expandedSize(length, 0); UChar* d = allocChars(newCapacity); if (!d) - rep = &UString::Rep::null; + rep = &UString::Rep::null(); else { copyChars(d, rep->data(), thisSize); copyChars(d + thisSize, tData, tSize); rep = UString::Rep::create(d, length); - rep->capacity = newCapacity; + rep->baseString()->capacity = newCapacity; } } @@ -604,6 +677,7 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re int thisOffset = rep->offset; int tSize = static_cast<int>(strlen(t)); int length = thisSize + tSize; + UString::BaseString* base = rep->baseString(); // possible cases: if (thisSize == 0) { @@ -611,9 +685,9 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re rep = createRep(t); } else if (tSize == 0) { // t is empty, we'll just return *this below. - } else if (rep->baseIsSelf() && rep->rc == 1) { + } else if (rep == base && !base->isShared()) { // this is direct and has refcount of 1 (so we can just alter it directly) - expandCapacity(rep.get(), thisOffset + length); + expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length)); UChar* d = rep->data(); if (d) { for (int i = 0; i < tSize; ++i) @@ -621,9 +695,9 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re rep->len = length; rep->_hash = 0; } - } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) { + } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) { // this string reaches the end of the buffer - extend it - expandCapacity(rep.get(), thisOffset + length); + expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length)); UChar* d = rep->data(); if (d) { for (int i = 0; i < tSize; ++i) @@ -631,17 +705,17 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re rep = UString::Rep::create(rep, 0, length); } } else { - // this is shared with someone using more capacity, gotta make a whole new string + // This is shared in some way that prevents us from modifying base, so we must make a whole new string. size_t newCapacity = expandedSize(length, 0); UChar* d = allocChars(newCapacity); if (!d) - rep = &UString::Rep::null; + rep = &UString::Rep::null(); else { copyChars(d, rep->data(), thisSize); for (int i = 0; i < tSize; ++i) d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend rep = UString::Rep::create(d, length); - rep->capacity = newCapacity; + rep->baseString()->capacity = newCapacity; } } @@ -656,13 +730,19 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b) b->checkConsistency(); int aSize = a->size(); - int aOffset = a->offset; int bSize = b->size(); - int bOffset = b->offset; - int length = aSize + bSize; + int aOffset = a->offset; // possible cases: + UString::BaseString* aBase = a->baseString(); + if (bSize == 1 && aOffset + aSize == aBase->usedCapacity && aOffset + aSize < aBase->capacity && !aBase->isBufferReadOnly()) { + // b is a single character (common fast case) + ++aBase->usedCapacity; + a->data()[aSize] = b->data()[0]; + return UString::Rep::create(a, 0, aSize + 1); + } + // a is empty if (aSize == 0) return b; @@ -670,21 +750,19 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b) if (bSize == 0) return a; - if (bSize == 1 && aOffset + aSize == a->baseString->usedCapacity && aOffset + length <= a->baseString->capacity) { - // b is a single character (common fast case) - a->baseString->usedCapacity = aOffset + length; - a->data()[aSize] = b->data()[0]; - return UString::Rep::create(a, 0, length); - } + int bOffset = b->offset; + int length = aSize + bSize; - if (aOffset + aSize == a->baseString->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize && - (-bOffset != b->baseString->usedPreCapacity || aSize >= bSize)) { + UString::BaseString* bBase = b->baseString(); + if (aOffset + aSize == aBase->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize + && (-bOffset != bBase->usedPreCapacity || aSize >= bSize) && !aBase->isBufferReadOnly()) { // - a reaches the end of its buffer so it qualifies for shared append // - also, it's at least a quarter the length of b - appending to a much shorter // string does more harm than good // - however, if b qualifies for prepend and is longer than a, we'd rather prepend + UString x(a); - x.expandCapacity(aOffset + length); + x.expandCapacity(newCapacityWithOverflowCheck(aOffset, length)); if (!a->data() || !x.data()) return 0; copyChars(a->data() + aSize, b->data(), bSize); @@ -697,7 +775,7 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b) return result; } - if (-bOffset == b->baseString->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) { + if (-bOffset == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize && !bBase->isBufferReadOnly()) { // - b reaches the beginning of its buffer so it qualifies for shared prepend // - also, it's at least a quarter the length of a - prepending to a much shorter // string does more harm than good @@ -723,7 +801,7 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b) copyChars(d, a->data(), aSize); copyChars(d + aSize, b->data(), bSize); PassRefPtr<UString::Rep> result = UString::Rep::create(d, length); - result->capacity = newCapacity; + result->baseString()->capacity = newCapacity; a->checkConsistency(); b->checkConsistency(); @@ -775,7 +853,8 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, double d) int decimalPoint; int sign; - char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL); + char result[80]; + WTF::dtoa(result, d, 0, &decimalPoint, &sign, NULL); int length = static_cast<int>(strlen(result)); int i = 0; @@ -826,15 +905,7 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, double d) buf[i++] = '\0'; } - WTF::freedtoa(result); - - return concatenate(rep, buf); -} - -const UString& UString::null() -{ - static UString* n = new UString; // Should be called from main thread at least once to be safely initialized. - return *n; + return concatenate(rep, buf); } UString UString::from(int i) @@ -922,8 +993,9 @@ UString UString::from(double d) char buf[80]; int decimalPoint; int sign; - - char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL); + + char result[80]; + WTF::dtoa(result, d, 0, &decimalPoint, &sign, NULL); int length = static_cast<int>(strlen(result)); int i = 0; @@ -974,9 +1046,7 @@ UString UString::from(double d) buf[i++] = '\0'; } - WTF::freedtoa(result); - - return UString(buf); + return UString(buf); } UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const @@ -1021,6 +1091,28 @@ UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, in return UString::Rep::create(buffer, totalLength); } +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 = allocChars(totalLength); + if (!buffer) + return null(); + + copyChars(buffer, data(), rangeStart); + copyChars(buffer + rangeStart, replacement.data(), replacementLength); + int rangeEnd = rangeStart + rangeLength; + copyChars(buffer + rangeStart + replacementLength, data() + rangeEnd, size() - rangeEnd); + + return UString::Rep::create(buffer, totalLength); +} + + UString& UString::append(const UString &t) { m_rep->checkConsistency(); @@ -1030,6 +1122,7 @@ UString& UString::append(const UString &t) int thisOffset = m_rep->offset; int tSize = t.size(); int length = thisSize + tSize; + BaseString* base = m_rep->baseString(); // possible cases: if (thisSize == 0) { @@ -1037,23 +1130,23 @@ UString& UString::append(const UString &t) *this = t; } else if (tSize == 0) { // t is empty - } else if (m_rep->baseIsSelf() && m_rep->rc == 1) { + } else if (m_rep == base && !base->isShared()) { // this is direct and has refcount of 1 (so we can just alter it directly) - expandCapacity(thisOffset + length); + expandCapacity(newCapacityWithOverflowCheck(thisOffset, length)); if (data()) { copyChars(m_rep->data() + thisSize, t.data(), tSize); m_rep->len = length; m_rep->_hash = 0; } - } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) { + } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) { // this reaches the end of the buffer - extend it if it's long enough to append to - expandCapacity(thisOffset + length); + expandCapacity(newCapacityWithOverflowCheck(thisOffset, length)); if (data()) { copyChars(m_rep->data() + thisSize, t.data(), tSize); m_rep = Rep::create(m_rep, 0, length); } } else { - // this is shared with someone using more capacity, gotta make a whole new string + // This is shared in some way that prevents us from modifying base, so we must make a whole new string. size_t newCapacity = expandedSize(length, 0); UChar* d = allocChars(newCapacity); if (!d) @@ -1062,7 +1155,7 @@ UString& UString::append(const UString &t) copyChars(d, data(), thisSize); copyChars(d + thisSize, t.data(), tSize); m_rep = Rep::create(d, length); - m_rep->capacity = newCapacity; + m_rep->baseString()->capacity = newCapacity; } } @@ -1078,6 +1171,18 @@ UString& UString::append(const UChar* tData, int tSize) return *this; } +UString& UString::appendNumeric(int i) +{ + m_rep = concatenate(rep(), i); + return *this; +} + +UString& UString::appendNumeric(double d) +{ + m_rep = concatenate(rep(), d); + return *this; +} + UString& UString::append(const char* t) { m_rep = concatenate(m_rep.release(), t); @@ -1090,6 +1195,7 @@ UString& UString::append(UChar c) int thisOffset = m_rep->offset; int length = size(); + BaseString* base = m_rep->baseString(); // possible cases: if (length == 0) { @@ -1101,27 +1207,27 @@ UString& UString::append(UChar c) else { d[0] = c; m_rep = Rep::create(d, 1); - m_rep->capacity = newCapacity; + m_rep->baseString()->capacity = newCapacity; } - } else if (m_rep->baseIsSelf() && m_rep->rc == 1) { + } else if (m_rep == base && !base->isShared()) { // this is direct and has refcount of 1 (so we can just alter it directly) - expandCapacity(thisOffset + length + 1); + expandCapacity(newCapacityWithOverflowCheck(thisOffset, length, true)); UChar* d = m_rep->data(); if (d) { d[length] = c; m_rep->len = length + 1; m_rep->_hash = 0; } - } else if (thisOffset + length == usedCapacity() && length >= minShareSize) { + } else if (thisOffset + length == base->usedCapacity && length >= minShareSize && !base->isBufferReadOnly()) { // this reaches the end of the string - extend it and share - expandCapacity(thisOffset + length + 1); + expandCapacity(newCapacityWithOverflowCheck(thisOffset, length, true)); UChar* d = m_rep->data(); if (d) { d[length] = c; m_rep = Rep::create(m_rep, 0, length + 1); } } else { - // this is shared with someone using more capacity, gotta make a whole new string + // This is shared in some way that prevents us from modifying base, so we must make a whole new string. size_t newCapacity = expandedSize(length + 1, 0); UChar* d = allocChars(newCapacity); if (!d) @@ -1130,7 +1236,7 @@ UString& UString::append(UChar c) copyChars(d, data(), length); d[length] = c; m_rep = Rep::create(d, length + 1); - m_rep->capacity = newCapacity; + m_rep->baseString()->capacity = newCapacity; } } @@ -1185,19 +1291,20 @@ char* UString::ascii() const UString& UString::operator=(const char* c) { if (!c) { - m_rep = &Rep::null; + m_rep = &Rep::null(); return *this; } if (!c[0]) { - m_rep = &Rep::empty; + m_rep = &Rep::empty(); return *this; } int l = static_cast<int>(strlen(c)); UChar* d; - if (m_rep->rc == 1 && l <= m_rep->capacity && m_rep->baseIsSelf() && m_rep->offset == 0 && m_rep->preCapacity == 0) { - d = m_rep->buf; + BaseString* base = m_rep->baseString(); + if (!base->isShared() && l <= base->capacity && m_rep == base && m_rep->offset == 0 && base->preCapacity == 0) { + d = base->buf; m_rep->_hash = 0; m_rep->len = l; } else { @@ -1413,12 +1520,24 @@ uint32_t UString::toStrictUInt32(bool* ok) const int UString::find(const UString& f, int pos) const { - int sz = size(); int fsz = f.size(); - if (sz < fsz) - return -1; + if (pos < 0) pos = 0; + + if (fsz == 1) { + UChar ch = f[0]; + const UChar* end = data() + size(); + for (const UChar* c = data() + pos; c < end; c++) { + if (*c == ch) + return static_cast<int>(c - data()); + } + return -1; + } + + int sz = size(); + if (sz < fsz) + return -1; if (fsz == 0) return pos; const UChar* end = data() + sz - fsz; @@ -1502,19 +1621,6 @@ UString UString::substr(int pos, int len) const return UString(Rep::create(m_rep, pos, len)); } -bool operator==(const UString& s1, const UString& s2) -{ - int size = s1.size(); - switch (size) { - case 0: - return !s2.size(); - case 1: - return s2.size() == 1 && s1.data()[0] == s2.data()[0]; - default: - return s2.size() == size && memcmp(s1.data(), s2.data(), size * sizeof(UChar)) == 0; - } -} - bool operator==(const UString& s1, const char *s2) { if (s2 == 0) @@ -1626,13 +1732,13 @@ CString UString::UTF8String(bool strict) const // 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; + 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; + return &Rep::null(); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/UString.h b/src/3rdparty/webkit/JavaScriptCore/runtime/UString.h index 75403c0..6852d91 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/UString.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/UString.h @@ -1,6 +1,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,8 +27,10 @@ #include <stdint.h> #include <string.h> #include <wtf/Assertions.h> -#include <wtf/FastMalloc.h> +#include <wtf/CrossThreadRefCounted.h> +#include <wtf/OwnFastMallocPtr.h> #include <wtf/PassRefPtr.h> +#include <wtf/PtrAndFlags.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> #include <wtf/unicode/Unicode.h> @@ -74,10 +77,26 @@ namespace JSC { friend class JIT; public: - struct Rep { + typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; + struct BaseString; + struct Rep : Noncopyable { friend class JIT; - static PassRefPtr<Rep> create(UChar*, int); + static PassRefPtr<Rep> create(UChar* buffer, int length) + { + return adoptRef(new BaseString(buffer, length)); + } + + static PassRefPtr<Rep> createEmptyBuffer(size_t size) + { + // Guard against integer overflow + if (size < (std::numeric_limits<size_t>::max() / sizeof(UChar))) { + if (void * buf = tryFastMalloc(size * sizeof(UChar))) + return adoptRef(new BaseString(static_cast<UChar*>(buf), 0, size)); + } + return adoptRef(new BaseString(0, 0, 0)); + } + static PassRefPtr<Rep> createCopying(const UChar*, int); static PassRefPtr<Rep> create(PassRefPtr<Rep> base, int offset, int length); @@ -85,10 +104,13 @@ namespace JSC { // Returns UString::Rep::null for null input or conversion failure. static PassRefPtr<Rep> createFromUTF8(const char*); + // Uses SharedUChar to have joint ownership over the UChar*. + static PassRefPtr<Rep> create(UChar*, int, PassRefPtr<SharedUChar>); + void destroy(); - bool baseIsSelf() const { return baseString == this; } - UChar* data() const { return baseString->buf + baseString->preCapacity + offset; } + bool baseIsSelf() const { return m_identifierTableAndFlags.isFlagSet(BaseStringFlag); } + UChar* data() const; int size() const { return len; } unsigned hash() const { if (_hash == 0) _hash = computeHash(data(), len); return _hash; } @@ -98,35 +120,115 @@ namespace JSC { static unsigned computeHash(const char*, int length); static unsigned computeHash(const char* s) { return computeHash(s, strlen(s)); } - IdentifierTable* identifierTable() const { return reinterpret_cast<IdentifierTable*>(m_identifierTable & ~static_cast<uintptr_t>(1)); } - void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTable = reinterpret_cast<intptr_t>(table); } + IdentifierTable* identifierTable() const { return m_identifierTableAndFlags.get(); } + void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTableAndFlags.set(table); } - bool isStatic() const { return m_identifierTable & 1; } - void setStatic(bool v) { ASSERT(!identifierTable()); m_identifierTable = v; } + bool isStatic() const { return m_identifierTableAndFlags.isFlagSet(StaticFlag); } + void setStatic(bool); + void setBaseString(PassRefPtr<BaseString>); + BaseString* baseString(); + const BaseString* baseString() const; Rep* ref() { ++rc; return this; } ALWAYS_INLINE void deref() { if (--rc == 0) destroy(); } void checkConsistency() const; + enum UStringFlags { + StaticFlag, + BaseStringFlag + }; // unshared data int offset; int len; int rc; // For null and empty static strings, this field does not reflect a correct count, because ref/deref are not thread-safe. A special case in destroy() guarantees that these do not get deleted. mutable unsigned _hash; - intptr_t m_identifierTable; // A pointer to identifier table. The lowest bit is used to indicate whether the string is static (null or empty). - UString::Rep* baseString; - size_t reportedCost; + PtrAndFlags<IdentifierTable, UStringFlags> m_identifierTableAndFlags; + + static BaseString& null() { return *nullBaseString; } + static BaseString& empty() { return *emptyBaseString; } - // potentially shared data. 0 if backed up by a base string. + bool reserveCapacity(int capacity); + + protected: + // Constructor for use by BaseString subclass; they use the union with m_baseString for another purpose. + Rep(int length) + : offset(0) + , len(length) + , rc(1) + , _hash(0) + , m_baseString(0) + { + } + + Rep(PassRefPtr<BaseString> base, int offsetInBase, int length) + : offset(offsetInBase) + , len(length) + , rc(1) + , _hash(0) + , m_baseString(base.releaseRef()) + { + checkConsistency(); + } + + union { + // If !baseIsSelf() + BaseString* m_baseString; + // If baseIsSelf() + SharedUChar* m_sharedBuffer; + }; + + private: + // For SmallStringStorage which allocates an array and does initialization manually. + Rep() { } + + friend class SmallStringsStorage; + friend void initializeUString(); + JS_EXPORTDATA static BaseString* nullBaseString; + JS_EXPORTDATA static BaseString* emptyBaseString; + }; + + + struct BaseString : public Rep { + bool isShared() { return rc != 1 || isBufferReadOnly(); } + void setSharedBuffer(PassRefPtr<SharedUChar>); + SharedUChar* sharedBuffer(); + + bool isBufferReadOnly() + { + if (!m_sharedBuffer) + return false; + return slowIsBufferReadOnly(); + } + + // potentially shared data. UChar* buf; - int usedCapacity; - int capacity; - int usedPreCapacity; int preCapacity; + int usedPreCapacity; + int capacity; + int usedCapacity; + + size_t reportedCost; + + private: + BaseString(UChar* buffer, int length, int additionalCapacity = 0) + : Rep(length) + , buf(buffer) + , preCapacity(0) + , usedPreCapacity(0) + , capacity(length + additionalCapacity) + , usedCapacity(length) + , reportedCost(0) + { + m_identifierTableAndFlags.setFlag(BaseStringFlag); + checkConsistency(); + } + + bool slowIsBufferReadOnly(); - static Rep null; - static Rep empty; + friend struct Rep; + friend class SmallStringsStorage; + friend void initializeUString(); }; public: @@ -175,11 +277,15 @@ namespace JSC { UString spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const; + UString replaceRange(int rangeStart, int RangeEnd, const UString& replacement) const; + UString& append(const UString&); UString& append(const char*); UString& append(UChar); UString& append(char c) { return append(static_cast<UChar>(static_cast<unsigned char>(c))); } UString& append(const UChar*, int size); + UString& appendNumeric(int); + UString& appendNumeric(double); bool getCString(CStringBuffer&) const; @@ -204,7 +310,7 @@ namespace JSC { const UChar* data() const { return m_rep->data(); } - bool isNull() const { return (m_rep == &Rep::null); } + bool isNull() const { return (m_rep == &Rep::null()); } bool isEmpty() const { return (!m_rep->len); } bool is8Bit() const; @@ -230,7 +336,7 @@ namespace JSC { UString substr(int pos = 0, int len = -1) const; - static const UString& null(); + static const UString& null() { return *nullUString; } Rep* rep() const { return m_rep.get(); } static Rep* nullRep(); @@ -243,15 +349,26 @@ namespace JSC { size_t cost() const; + // Attempt to grow this string such that it can grow to a total length of 'capacity' + // without reallocation. This may fail a number of reasons - if the BasicString is + // shared and another string is using part of the capacity beyond our end point, if + // the realloc fails, or if this string is empty and has no storage. + // + // This method returns a boolean indicating success. + bool reserveCapacity(int capacity) + { + return m_rep->reserveCapacity(capacity); + } + private: - int usedCapacity() const; - int usedPreCapacity() const; void expandCapacity(int requiredLength); void expandPreCapacity(int requiredPreCap); void makeNull(); RefPtr<Rep> m_rep; + static UString* nullUString; + friend void initializeUString(); friend bool operator==(const UString&, const UString&); friend PassRefPtr<Rep> concatenate(Rep*, Rep*); // returns 0 if out of memory }; @@ -259,7 +376,26 @@ namespace JSC { PassRefPtr<UString::Rep> concatenate(UString::Rep*, int); PassRefPtr<UString::Rep> concatenate(UString::Rep*, double); - bool operator==(const UString&, const UString&); + inline bool operator==(const UString& s1, const UString& s2) + { + int size = s1.size(); + switch (size) { + case 0: + return !s2.size(); + case 1: + return s2.size() == 1 && s1.data()[0] == s2.data()[0]; + case 2: { + if (s2.size() != 2) + return false; + const UChar* d1 = s1.data(); + const UChar* d2 = s2.data(); + return (d1[0] == d2[0]) & (d1[1] == d2[1]); + } + default: + return s2.size() == size && memcmp(s1.data(), s2.data(), size * sizeof(UChar)) == 0; + } + } + inline bool operator!=(const UString& s1, const UString& s2) { @@ -298,6 +434,54 @@ namespace JSC { bool equal(const UString::Rep*, const UString::Rep*); + inline PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<UString::Rep> rep, int offset, int length) + { + ASSERT(rep); + rep->checkConsistency(); + + int repOffset = rep->offset; + + PassRefPtr<BaseString> base = rep->baseString(); + + ASSERT(-(offset + repOffset) <= base->usedPreCapacity); + ASSERT(offset + repOffset + length <= base->usedCapacity); + + // Steal the single reference this Rep was created with. + return adoptRef(new Rep(base, repOffset + offset, length)); + } + + inline UChar* UString::Rep::data() const + { + const BaseString* base = baseString(); + return base->buf + base->preCapacity + offset; + } + + inline void UString::Rep::setStatic(bool v) + { + ASSERT(!identifierTable()); + if (v) + m_identifierTableAndFlags.setFlag(StaticFlag); + else + m_identifierTableAndFlags.clearFlag(StaticFlag); + } + + inline void UString::Rep::setBaseString(PassRefPtr<BaseString> base) + { + ASSERT(base != this); + ASSERT(!baseIsSelf()); + m_baseString = base.releaseRef(); + } + + inline UString::BaseString* UString::Rep::baseString() + { + return !baseIsSelf() ? m_baseString : reinterpret_cast<BaseString*>(this) ; + } + + inline const UString::BaseString* UString::Rep::baseString() const + { + return const_cast<Rep*>(this)->baseString(); + } + #ifdef NDEBUG inline void UString::Rep::checkConsistency() const { @@ -305,7 +489,7 @@ namespace JSC { #endif inline UString::UString() - : m_rep(&Rep::null) + : m_rep(&Rep::null()) { } @@ -328,8 +512,9 @@ namespace JSC { inline size_t UString::cost() const { - size_t capacity = (m_rep->baseString->capacity + m_rep->baseString->preCapacity) * sizeof(UChar); - size_t reportedCost = m_rep->baseString->reportedCost; + BaseString* base = m_rep->baseString(); + size_t capacity = (base->capacity + base->preCapacity) * sizeof(UChar); + size_t reportedCost = base->reportedCost; ASSERT(capacity >= reportedCost); size_t capacityDelta = capacity - reportedCost; @@ -337,7 +522,7 @@ namespace JSC { if (capacityDelta < static_cast<size_t>(minShareSize)) return 0; - m_rep->baseString->reportedCost = capacity; + base->reportedCost = capacity; return capacityDelta; } @@ -347,6 +532,7 @@ namespace JSC { static unsigned hash(JSC::UString::Rep* key) { return key->computedHash(); } }; + void initializeUString(); } // namespace JSC namespace WTF { |