summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@nokia.com>2010-04-06 10:36:47 (GMT)
committerJocelyn Turcotte <jocelyn.turcotte@nokia.com>2010-04-06 10:36:47 (GMT)
commitbb35b65bbfba82e0dd0ac306d3dab54436cdaff6 (patch)
tree8174cb262a960ff7b2e4aa8f1aaf154db71d2636 /src/3rdparty/webkit/JavaScriptCore/runtime/Operations.h
parent4b27d0d887269583a0f76e922948f8c25e96ab88 (diff)
downloadQt-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.h271
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