Changeset 51671 in webkit for trunk/JavaScriptCore/runtime/JSString.cpp
- Timestamp:
- Dec 3, 2009, 6:15:18 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/JSString.cpp
r49365 r51671 31 31 namespace JSC { 32 32 33 JSString::Rope::~Rope() 34 { 35 for (unsigned i = 0; i < m_ropeLength; ++i) { 36 Fiber& fiber = m_fibers[i]; 37 if (fiber.isRope()) 38 fiber.rope()->deref(); 39 else 40 fiber.string()->deref(); 41 } 42 } 43 44 #define ROPE_COPY_CHARS_INLINE_CUTOFF 20 45 46 static inline void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) 47 { 48 #ifdef ROPE_COPY_CHARS_INLINE_CUTOFF 49 if (numCharacters <= ROPE_COPY_CHARS_INLINE_CUTOFF) { 50 for (unsigned i = 0; i < numCharacters; ++i) 51 destination[i] = source[i]; 52 return; 53 } 54 #endif 55 memcpy(destination, source, numCharacters * sizeof(UChar)); 56 } 57 58 // Overview: this methods converts a JSString from holding a string in rope form 59 // down to a simple UString representation. It does so by building up the string 60 // backwards, since we want to avoid recursion, we expect that the tree structure 61 // representing the rope is likely imbalanced with more nodes down the left side 62 // (since appending to the string is likely more common) - and as such resolving 63 // in this fashion should minimize work queue size. (If we built the queue forwards 64 // we would likely have to place all of the constituent UString::Reps into the 65 // Vector before performing any concatenation, but by working backwards we likely 66 // only fill the queue with the number of substrings at any given level in a 67 // rope-of-ropes.) 68 void JSString::resolveRope() const 69 { 70 ASSERT(isRope()); 71 72 // Allocate the buffer to hold the final string, position initially points to the end. 73 UChar* buffer = static_cast<UChar*>(fastMalloc(m_length * sizeof(UChar))); 74 UChar* position = buffer + m_length; 75 76 // Start with the current Rope. 77 Vector<Rope::Fiber, 32> workQueue; 78 Rope* rope = m_rope.get(); 79 while (true) { 80 // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber' 81 // (we will be working backwards over the rope). 82 unsigned ropeLengthMinusOne = rope->ropeLength() - 1; 83 for (unsigned i = 0; i < ropeLengthMinusOne; ++i) 84 workQueue.append(rope->fibers(i)); 85 Rope::Fiber currentFiber = rope->fibers(ropeLengthMinusOne); 86 87 // Spin backwards over the workQueue (starting with currentFiber), 88 // writing the strings into the buffer. 89 while (currentFiber.isString()) { 90 UString::Rep* string = currentFiber.string(); 91 unsigned length = string->len; 92 position -= length; 93 copyChars(position, string->data(), length); 94 95 // Was this the last item in the work queue? 96 if (workQueue.isEmpty()) 97 goto breakOutOfTwoLoops; 98 // No! - set the next item up to process. 99 currentFiber = workQueue.last(); 100 workQueue.removeLast(); 101 } 102 103 // If we get here we fell out of the loop concatenating strings - currentFiber is a rope. 104 // set the 'rope' variable, and continue around the loop. 105 ASSERT(currentFiber.isRope()); 106 rope = currentFiber.rope(); 107 } 108 breakOutOfTwoLoops: 109 110 // Create a string from the UChar buffer, clear the rope RefPtr. 111 ASSERT(buffer == position); 112 m_value = UString::Rep::create(buffer, m_length, false); 113 m_rope.clear(); 114 115 ASSERT(!isRope()); 116 } 117 33 118 JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const 34 119 { … … 36 121 } 37 122 38 bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValue& value)39 { 40 value= this;41 number = m_value.toDouble();123 bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValue& result) 124 { 125 result = this; 126 number = value().toDouble(); 42 127 return false; 43 128 } … … 45 130 bool JSString::toBoolean(ExecState*) const 46 131 { 47 return !m_value.isEmpty();132 return m_length; 48 133 } 49 134 50 135 double JSString::toNumber(ExecState*) const 51 136 { 52 return m_value.toDouble();137 return value().toDouble(); 53 138 } 54 139 55 140 UString JSString::toString(ExecState*) const 56 141 { 57 return m_value;142 return value(); 58 143 } 59 144 60 145 UString JSString::toThisString(ExecState*) const 61 146 { 62 return m_value;147 return value(); 63 148 } 64 149 … … 107 192 { 108 193 if (propertyName == exec->propertyNames().length) { 109 descriptor.setDescriptor(jsNumber(exec, m_ value.size()), DontEnum | DontDelete | ReadOnly);194 descriptor.setDescriptor(jsNumber(exec, m_length), DontEnum | DontDelete | ReadOnly); 110 195 return true; 111 196 } … … 113 198 bool isStrictUInt32; 114 199 unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); 115 if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) {116 descriptor.setDescriptor(jsSingleCharacterSubstring(exec, m_value, i), DontDelete | ReadOnly);200 if (isStrictUInt32 && i < m_length) { 201 descriptor.setDescriptor(jsSingleCharacterSubstring(exec, value(), i), DontDelete | ReadOnly); 117 202 return true; 118 203 }
Note:
See TracChangeset
for help on using the changeset viewer.