Modified: trunk/Source/_javascript_Core/ChangeLog (185485 => 185486)
--- trunk/Source/_javascript_Core/ChangeLog 2015-06-12 02:59:59 UTC (rev 185485)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-06-12 04:09:11 UTC (rev 185486)
@@ -1,3 +1,22 @@
+2015-06-11 Andreas Kling <[email protected]>
+
+ jsSubstring() should support creating substrings from substrings.
+ <https://webkit.org/b/145427>
+
+ Reviewed by Geoffrey Garen
+
+ Tweak jsSubstring() to support base strings that are themselves substrings.
+ They will now share the same grandparent base. This avoids creating a new StringImpl.
+
+ * runtime/JSString.h:
+ (JSC::jsSubstring): Don't force rope resolution here. Instead do that in finishCreation()
+ if the base string is a non-substring rope. Note that resolveRope() is the very last thing
+ called, since it may allocate and the JSRopeString needs to be ready for marking.
+
+ (JSC::JSString::isSubstring): Added a helper to find out if a JSString is
+ a substring. This is just for internal use, so you don't have to cast to
+ JSRopeString for the real substringness flag.
+
2015-06-11 Commit Queue <[email protected]>
Unreviewed, rolling out r185465.
Modified: trunk/Source/_javascript_Core/runtime/JSString.h (185485 => 185486)
--- trunk/Source/_javascript_Core/runtime/JSString.h 2015-06-12 02:59:59 UTC (rev 185485)
+++ trunk/Source/_javascript_Core/runtime/JSString.h 2015-06-12 04:09:11 UTC (rev 185486)
@@ -186,6 +186,7 @@
friend class JSValue;
bool isRope() const { return m_value.isNull(); }
+ bool isSubstring() const;
bool is8Bit() const { return m_flags & Is8Bit; }
void setIs8Bit(bool flag) const
{
@@ -291,17 +292,29 @@
fiber(2).set(vm, this, s3);
}
- void finishCreation(VM& vm, JSString* base, unsigned offset, unsigned length)
+ void finishCreation(ExecState& exec, JSString& base, unsigned offset, unsigned length)
{
+ VM& vm = exec.vm();
Base::finishCreation(vm);
- ASSERT(!base->isRope());
ASSERT(!sumOverflows<int32_t>(offset, length));
- ASSERT(offset + length <= base->length());
+ ASSERT(offset + length <= base.length());
m_length = length;
- setIs8Bit(base->is8Bit());
+ setIs8Bit(base.is8Bit());
setIsSubstring(true);
- substringBase().set(vm, this, base);
- substringOffset() = offset;
+ if (base.isSubstring()) {
+ JSRopeString& baseRope = static_cast<JSRopeString&>(base);
+ substringBase().set(vm, this, baseRope.substringBase().get());
+ substringOffset() = baseRope.substringOffset() + offset;
+ } else {
+ substringBase().set(vm, this, &base);
+ substringOffset() = offset;
+
+ // For now, let's not allow substrings with a rope base.
+ // Resolve non-substring rope bases so we don't have to deal with it.
+ // FIXME: Evaluate if this would be worth adding more branches.
+ if (base.isRope())
+ static_cast<JSRopeString&>(base).resolveRope(&exec);
+ }
}
void finishCreation(VM& vm)
@@ -342,10 +355,10 @@
return newString;
}
- static JSString* create(VM& vm, JSString* base, unsigned offset, unsigned length)
+ static JSString* create(ExecState& exec, JSString& base, unsigned offset, unsigned length)
{
- JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
- newString->finishCreation(vm, base, offset, length);
+ JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(exec.vm().heap)) JSRopeString(exec.vm());
+ newString->finishCreation(exec, base, offset, length);
return newString;
}
@@ -515,8 +528,7 @@
VM& vm = exec->vm();
if (!length)
return vm.smallStrings.emptyString();
- s->value(exec); // For effect. We need to ensure that any string that is used as a substring base is not a rope.
- return JSRopeString::create(vm, s, offset, length);
+ return JSRopeString::create(*exec, *s, offset, length);
}
inline JSString* jsSubstring8(VM* vm, const String& s, unsigned offset, unsigned length)
@@ -703,6 +715,11 @@
return StringView(m_value);
}
+inline bool JSString::isSubstring() const
+{
+ return isRope() && static_cast<const JSRopeString*>(this)->isSubstring();
+}
+
} // namespace JSC
#endif // JSString_h