diff options
author | Jocelyn Turcotte <jocelyn.turcotte@nokia.com> | 2010-04-06 10:36:47 (GMT) |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@nokia.com> | 2010-04-06 10:36:47 (GMT) |
commit | bb35b65bbfba82e0dd0ac306d3dab54436cdaff6 (patch) | |
tree | 8174cb262a960ff7b2e4aa8f1aaf154db71d2636 /src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h | |
parent | 4b27d0d887269583a0f76e922948f8c25e96ab88 (diff) | |
download | Qt-bb35b65bbfba82e0dd0ac306d3dab54436cdaff6.zip Qt-bb35b65bbfba82e0dd0ac306d3dab54436cdaff6.tar.gz Qt-bb35b65bbfba82e0dd0ac306d3dab54436cdaff6.tar.bz2 |
Update src/3rdparty/webkit from trunk.
Imported from 839d8709327f925aacb3b6362c06152594def97e
in branch qtwebkit-2.0 of repository
git://gitorious.org/+qtwebkit-developers/webkit/qtwebkit.git
Rubber-stamped-by: Simon Hausmann
Diffstat (limited to 'src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h')
-rw-r--r-- | src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h | 271 |
1 files changed, 189 insertions, 82 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h index 1aa68b3..cc0d603 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h @@ -22,6 +22,7 @@ #ifndef Operations_h #define Operations_h +#include "ExceptionHelpers.h" #include "Interpreter.h" #include "JSImmediate.h" #include "JSNumberCell.h" @@ -29,12 +30,176 @@ namespace JSC { - NEVER_INLINE JSValue throwOutOfMemoryError(ExecState*); NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue); JSValue jsTypeStringForValue(CallFrame*, JSValue); bool jsIsObjectType(JSValue); bool jsIsFunctionType(JSValue); + ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2) + { + unsigned length1 = s1->length(); + if (!length1) + return s2; + unsigned length2 = s2->length(); + if (!length2) + return s1; + if ((length1 + length2) < length1) + return throwOutOfMemoryError(exec); + + unsigned fiberCount = s1->fiberCount() + s2->fiberCount(); + JSGlobalData* globalData = &exec->globalData(); + + if (fiberCount <= JSString::s_maxInternalRopeLength) + return new (globalData) JSString(globalData, fiberCount, s1, s2); + + JSString::RopeBuilder ropeBuilder(fiberCount); + if (UNLIKELY(ropeBuilder.isOutOfMemory())) + return throwOutOfMemoryError(exec); + ropeBuilder.append(s1); + ropeBuilder.append(s2); + return new (globalData) JSString(globalData, ropeBuilder.release()); + } + + ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, JSString* s2) + { + unsigned length1 = u1.size(); + if (!length1) + return s2; + unsigned length2 = s2->length(); + if (!length2) + return jsString(exec, u1); + if ((length1 + length2) < length1) + return throwOutOfMemoryError(exec); + + unsigned fiberCount = 1 + s2->fiberCount(); + JSGlobalData* globalData = &exec->globalData(); + + if (fiberCount <= JSString::s_maxInternalRopeLength) + return new (globalData) JSString(globalData, fiberCount, u1, s2); + + JSString::RopeBuilder ropeBuilder(fiberCount); + if (UNLIKELY(ropeBuilder.isOutOfMemory())) + return throwOutOfMemoryError(exec); + ropeBuilder.append(u1); + ropeBuilder.append(s2); + return new (globalData) JSString(globalData, ropeBuilder.release()); + } + + ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, const UString& u2) + { + unsigned length1 = s1->length(); + if (!length1) + return jsString(exec, u2); + unsigned length2 = u2.size(); + if (!length2) + return s1; + if ((length1 + length2) < length1) + return throwOutOfMemoryError(exec); + + unsigned fiberCount = s1->fiberCount() + 1; + JSGlobalData* globalData = &exec->globalData(); + + if (fiberCount <= JSString::s_maxInternalRopeLength) + return new (globalData) JSString(globalData, fiberCount, s1, u2); + + JSString::RopeBuilder ropeBuilder(fiberCount); + if (UNLIKELY(ropeBuilder.isOutOfMemory())) + return throwOutOfMemoryError(exec); + ropeBuilder.append(s1); + ropeBuilder.append(u2); + return new (globalData) JSString(globalData, ropeBuilder.release()); + } + + ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count) + { + ASSERT(count >= 3); + + unsigned fiberCount = 0; + for (unsigned i = 0; i < count; ++i) { + JSValue v = strings[i].jsValue(); + if (LIKELY(v.isString())) + fiberCount += asString(v)->fiberCount(); + else + ++fiberCount; + } + + JSGlobalData* globalData = &exec->globalData(); + if (fiberCount == 3) + return new (globalData) JSString(exec, strings[0].jsValue(), strings[1].jsValue(), strings[2].jsValue()); + + JSString::RopeBuilder ropeBuilder(fiberCount); + if (UNLIKELY(ropeBuilder.isOutOfMemory())) + return throwOutOfMemoryError(exec); + + unsigned length = 0; + bool overflow = false; + + for (unsigned i = 0; i < count; ++i) { + JSValue v = strings[i].jsValue(); + if (LIKELY(v.isString())) + ropeBuilder.append(asString(v)); + else + ropeBuilder.append(v.toString(exec)); + + unsigned newLength = ropeBuilder.length(); + if (newLength < length) + overflow = true; + length = newLength; + } + + if (overflow) + return throwOutOfMemoryError(exec); + + return new (globalData) JSString(globalData, ropeBuilder.release()); + } + + ALWAYS_INLINE JSValue jsString(ExecState* exec, JSValue thisValue, const ArgList& args) + { + unsigned fiberCount = 0; + if (LIKELY(thisValue.isString())) + fiberCount += asString(thisValue)->fiberCount(); + else + ++fiberCount; + for (unsigned i = 0; i < args.size(); ++i) { + JSValue v = args.at(i); + if (LIKELY(v.isString())) + fiberCount += asString(v)->fiberCount(); + else + ++fiberCount; + } + + JSString::RopeBuilder ropeBuilder(fiberCount); + if (UNLIKELY(ropeBuilder.isOutOfMemory())) + return throwOutOfMemoryError(exec); + + if (LIKELY(thisValue.isString())) + ropeBuilder.append(asString(thisValue)); + else + ropeBuilder.append(thisValue.toString(exec)); + + unsigned length = 0; + bool overflow = false; + + for (unsigned i = 0; i < args.size(); ++i) { + JSValue v = args.at(i); + if (LIKELY(v.isString())) + ropeBuilder.append(asString(v)); + else + ropeBuilder.append(v.toString(exec)); + + unsigned newLength = ropeBuilder.length(); + if (newLength < length) + overflow = true; + length = newLength; + } + + if (overflow) + return throwOutOfMemoryError(exec); + + JSGlobalData* globalData = &exec->globalData(); + return new (globalData) JSString(globalData, ropeBuilder.release()); + } + // ECMA 11.9.3 inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2) { @@ -53,7 +218,7 @@ namespace JSC { bool s1 = v1.isString(); bool s2 = v2.isString(); if (s1 && s2) - return asString(v1)->value() == asString(v2)->value(); + return asString(v1)->value(exec) == asString(v2)->value(exec); if (v1.isUndefinedOrNull()) { if (v2.isUndefinedOrNull()) @@ -110,17 +275,17 @@ namespace JSC { } // ECMA 11.9.3 - ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(JSValue v1, JSValue v2) + ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2) { ASSERT(v1.isCell() && v2.isCell()); if (v1.asCell()->isString() && v2.asCell()->isString()) - return asString(v1)->value() == asString(v2)->value(); + return asString(v1)->value(exec) == asString(v2)->value(exec); return v1 == v2; } - inline bool JSValue::strictEqual(JSValue v1, JSValue v2) + inline bool JSValue::strictEqual(ExecState* exec, JSValue v1, JSValue v2) { if (v1.isInt32() && v2.isInt32()) return v1 == v2; @@ -131,10 +296,10 @@ namespace JSC { if (!v1.isCell() || !v2.isCell()) return v1 == v2; - return strictEqualSlowCaseInline(v1, v2); + return strictEqualSlowCaseInline(exec, v1, v2); } - inline bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2) + ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2) { if (v1.isInt32() && v2.isInt32()) return v1.asInt32() < v2.asInt32(); @@ -146,7 +311,7 @@ namespace JSC { JSGlobalData* globalData = &callFrame->globalData(); if (isJSString(globalData, v1) && isJSString(globalData, v2)) - return asString(v1)->value() < asString(v2)->value(); + return asString(v1)->value(callFrame) < asString(v2)->value(callFrame); JSValue p1; JSValue p2; @@ -156,7 +321,7 @@ namespace JSC { if (wasNotString1 | wasNotString2) return n1 < n2; - return asString(p1)->value() < asString(p2)->value(); + return asString(p1)->value(callFrame) < asString(p2)->value(callFrame); } inline bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2) @@ -171,7 +336,7 @@ namespace JSC { JSGlobalData* globalData = &callFrame->globalData(); if (isJSString(globalData, v1) && isJSString(globalData, v2)) - return !(asString(v2)->value() < asString(v1)->value()); + return !(asString(v2)->value(callFrame) < asString(v1)->value(callFrame)); JSValue p1; JSValue p2; @@ -181,7 +346,7 @@ namespace JSC { if (wasNotString1 | wasNotString2) return n1 <= n2; - return !(asString(p2)->value() < asString(p1)->value()); + return !(asString(p2)->value(callFrame) < asString(p1)->value(callFrame)); } // Fast-path choices here are based on frequency data from SunSpider: @@ -195,36 +360,21 @@ namespace JSC { 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)) + double left = 0.0, right; + if (v1.getNumber(left) && v2.getNumber(right)) 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.isInt32() ? - concatenate(asString(v1)->value().rep(), v2.asInt32()) : - concatenate(asString(v1)->value().rep(), right); - - if (!value) - return throwOutOfMemoryError(callFrame); - return jsString(callFrame, value.release()); + if (v1.isString()) { + return v2.isString() + ? jsString(callFrame, asString(v1), asString(v2)) + : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame)); } // All other cases are pretty uncommon return jsAddSlowCase(callFrame, v1, v2); } - inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase) + inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, size_t& slotOffset) { JSCell* cell = asCell(base); size_t count = 0; @@ -242,8 +392,11 @@ namespace JSC { // 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())); + if (cell->structure()->isDictionary()) { + asObject(cell)->flattenDictionaryObject(); + if (slotBase == cell) + slotOffset = cell->structure()->get(propertyName); + } ++count; } @@ -265,7 +418,7 @@ namespace JSC { // Since we're accessing a prototype in a loop, it's a good bet that it // should not be treated as a dictionary. if (base->structure()->isDictionary()) - asObject(base)->setStructure(Structure::fromDictionaryTransition(base->structure())); + asObject(base)->flattenDictionaryObject(); ++count; } @@ -293,52 +446,6 @@ namespace JSC { 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 operands, 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 - result.append(v.toString(callFrame)); - } - - return jsString(callFrame, result); - } - } // namespace JSC #endif // Operations_h |