Changeset 245194 in webkit
- Timestamp:
- May 10, 2019 1:49:35 PM (5 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r245192 r245194 1 2019-05-10 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] String substring operation should return ropes consistently 4 https://bugs.webkit.org/show_bug.cgi?id=197765 5 <rdar://problem/37689944> 6 7 Reviewed by Michael Saboff. 8 9 Currently we have different policies per string substring operation function. 10 11 1. String#slice returns the resolved non-rope string 12 2. String#substring returns rope string 13 3. String#substr returns rope string in runtime function, non-rope string in DFG and FTL 14 15 Due to (3), we see large memory use in the tested web page[1]. Non rope substring have a problem. 16 First of all, that returned string seems not used immediately. It is possible that the resulted 17 string is used as a part of the other ropes (like, xxx.substring(...) + "Hello"). To avoid the 18 eager materialization of the string, we are using StringImpl::createSubstringSharingImpl for the 19 resulted non rope string. StringImpl::createSubstringSharingImpl is StringImpl's substring feature: the 20 substring is pointing the owner StringImpl. While this has memory saving benefit, it can retain owner 21 StringImpl so long, and it could keep very large owner StringImpl alive. 22 23 The problem we are attempting to solve with StringImpl::createSubstringSharingImpl can be solved by 24 the rope string simply. Rope string can share the underlying string. And good feature of the rope 25 string is that, when resolving rope string, the rope string always create a new StringImpl instead of 26 using StringImpl::createSubstringSharingImpl. So we allow the owner StringImpl to be destroyed. And this 27 resolving only happens when we actually want to use the content of the rope string. In addition, we recently 28 shrunk the sizeof(JSRopeString) from 48 to 32, so JSRopeString is cheap. 29 30 In this patch, we change (2) and (3) to (1), using rope String as a result of substring operations. 31 32 RAMification and JetStream2 are neutral. The web page[1] shows large memory footprint improvement from 776MB to 681MB. 33 34 [1]: https://beta.observablehq.com/@ldgardner/assignment-4-visualizations-and-multiple-views 35 36 * dfg/DFGOperations.cpp: 37 * runtime/StringPrototype.cpp: 38 (JSC::stringProtoFuncSlice): 39 * runtime/StringPrototypeInlines.h: 40 (JSC::stringSlice): 41 1 42 2019-05-10 Robin Morisset <rmorisset@apple.com> 2 43 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r245064 r245194 2198 2198 VM& vm = exec->vm(); 2199 2199 NativeCallFrameTracer tracer(&vm, exec); 2200 auto scope = DECLARE_THROW_SCOPE(vm); 2201 2202 auto string = jsCast<JSString*>(cell)->value(exec); 2203 RETURN_IF_EXCEPTION(scope, nullptr); 2204 return jsSubstring(&vm, string, from, span); 2200 2201 return jsSubstring(vm, exec, jsCast<JSString*>(cell), from, span); 2205 2202 } 2206 2203 … … 2209 2206 VM& vm = exec->vm(); 2210 2207 NativeCallFrameTracer tracer(&vm, exec); 2211 auto scope = DECLARE_THROW_SCOPE(vm); 2212 2213 auto string = jsCast<JSString*>(cell)->value(exec); 2214 RETURN_IF_EXCEPTION(scope, nullptr); 2208 2209 JSString* string = asString(cell); 2215 2210 static_assert(static_cast<uint64_t>(JSString::MaxLength) <= static_cast<uint64_t>(std::numeric_limits<int32_t>::max()), ""); 2216 2217 return stringSlice(vm, WTFMove(string), start, end); 2211 return stringSlice(exec, vm, string, string->length(), start, end); 2218 2212 } 2219 2213 -
trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp
r245082 r245194 1144 1144 if (!checkObjectCoercible(thisValue)) 1145 1145 return throwVMTypeError(exec, scope); 1146 String s = thisValue.toWTFString(exec);1146 JSString* string = thisValue.toString(exec); 1147 1147 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 1148 1148 … … 1150 1150 JSValue a1 = exec->argument(1); 1151 1151 1152 int len = s.length();1153 RELEASE_ASSERT(len >= 0);1152 int length = string->length(); 1153 RELEASE_ASSERT(length >= 0); 1154 1154 1155 1155 // The arg processing is very much like ArrayProtoFunc::Slice 1156 1156 double start = a0.toInteger(exec); 1157 1157 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 1158 double end = a1.isUndefined() ? len : a1.toInteger(exec);1159 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 1160 return JSValue::encode(stringSlice(vm, WTFMove(s), start, end));1158 double end = a1.isUndefined() ? length : a1.toInteger(exec); 1159 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 1160 RELEASE_AND_RETURN(scope, JSValue::encode(stringSlice(exec, vm, string, length, start, end))); 1161 1161 } 1162 1162 -
trunk/Source/JavaScriptCore/runtime/StringPrototypeInlines.h
r243081 r245194 31 31 32 32 template<typename NumberType> 33 ALWAYS_INLINE JSString* stringSlice( VM& vm, String&& string, NumberType start, NumberType end)33 ALWAYS_INLINE JSString* stringSlice(ExecState* exec, VM& vm, JSString* string, int32_t length, NumberType start, NumberType end) 34 34 { 35 int32_t length = string.length();36 35 NumberType from = start < 0 ? length + start : start; 37 36 NumberType to = end < 0 ? length + end : end; … … 41 40 if (to > length) 42 41 to = length; 43 return jsSubstring( &vm, WTFMove(string), static_cast<unsigned>(from), static_cast<unsigned>(to) - static_cast<unsigned>(from));42 return jsSubstring(vm, exec, string, static_cast<unsigned>(from), static_cast<unsigned>(to) - static_cast<unsigned>(from)); 44 43 } 45 44 return jsEmptyString(&vm);
Note: See TracChangeset
for help on using the changeset viewer.