Skip to content

Commit f8c4ae8

Browse files
7601.6.13
1 parent fbefdc1 commit f8c4ae8

File tree

5 files changed

+59
-20
lines changed

5 files changed

+59
-20
lines changed

ChangeLog

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
1+
2016-03-24 Matthew Hanson <matthew_hanson@apple.com>
2+
3+
Merge r198592. rdar://problem/25332806
4+
5+
2016-03-23 Michael Saboff <msaboff@apple.com>
6+
7+
JavaScriptCore ArrayPrototype::join shouldn't cache butterfly when it makes effectful calls
8+
https://bugs.webkit.org/show_bug.cgi?id=155776
9+
10+
Reviewed by Saam Barati.
11+
12+
Array.join ends up calling toString, possibly on some object. Since these calls
13+
could be effectful and could change the array itself, we can't hold the butterfly
14+
pointer while making effectful calls. Changed the code to fall back to the general
15+
case when an effectful toString() call might be made.
16+
17+
* runtime/ArrayPrototype.cpp:
18+
(JSC::join):
19+
* runtime/JSStringJoiner.h:
20+
(JSC::JSStringJoiner::appendWithoutSideEffects): New helper that doesn't make effectful
21+
toString() calls.
22+
(JSC::JSStringJoiner::append): Built upon appendWithoutSideEffects.
23+
24+
2016-02-26 Babak Shafiei <bshafiei@apple.com>
25+
26+
Merge patch for rdar://problem/24826901.
27+
128
2016-02-12 Babak Shafiei <bshafiei@apple.com>
229

330
Merge patch for rdar://problem/24626412.

Configurations/FeatureDefines.xcconfig

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,11 @@ ENABLE_IOS_GESTURE_EVENTS[sdk=iphone*] = $(ENABLE_IOS_GESTURE_EVENTS_ios_WITH_IN
123123
ENABLE_IOS_GESTURE_EVENTS_ios_WITH_INTERNAL_SDK_YES = ENABLE_IOS_GESTURE_EVENTS;
124124

125125
ENABLE_MAC_GESTURE_EVENTS = ;
126-
ENABLE_MAC_GESTURE_EVENTS[sdk=macosx*] = $(ENABLE_MAC_GESTURE_EVENTS_macosx_WITH_INTERNAL_SDK_$(USE_INTERNAL_SDK));
127-
ENABLE_MAC_GESTURE_EVENTS_macosx_WITH_INTERNAL_SDK_YES = ENABLE_MAC_GESTURE_EVENTS;
126+
ENABLE_MAC_GESTURE_EVENTS[sdk=macosx*] = $(ENABLE_MAC_GESTURE_EVENTS_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR)_WITH_INTERNAL_SDK_$(USE_INTERNAL_SDK));
127+
ENABLE_MAC_GESTURE_EVENTS_macosx_1090_WITH_INTERNAL_SDK_YES = ;
128+
ENABLE_MAC_GESTURE_EVENTS_macosx_101000_WITH_INTERNAL_SDK_YES = ENABLE_MAC_GESTURE_EVENTS;
129+
ENABLE_MAC_GESTURE_EVENTS_macosx_101100_WITH_INTERNAL_SDK_YES = ENABLE_MAC_GESTURE_EVENTS;
130+
ENABLE_MAC_GESTURE_EVENTS_macosx_101200_WITH_INTERNAL_SDK_YES = ENABLE_MAC_GESTURE_EVENTS;
128131

129132
ENABLE_IOS_TEXT_AUTOSIZING[sdk=iphone*] = ENABLE_IOS_TEXT_AUTOSIZING;
130133

Configurations/Version.xcconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2323

2424
MAJOR_VERSION = 601;
25-
MINOR_VERSION = 5;
26-
TINY_VERSION = 17;
25+
MINOR_VERSION = 6;
26+
TINY_VERSION = 13;
2727
MICRO_VERSION = 0;
2828
NANO_VERSION = 0;
2929
FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(TINY_VERSION);

runtime/ArrayPrototype.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,8 @@ static inline JSValue join(ExecState& state, JSObject* thisObject, StringView se
404404
bool holesKnownToBeOK = false;
405405
for (unsigned i = 0; i < length; ++i) {
406406
if (JSValue value = data[i].get()) {
407-
joiner.append(state, value);
408-
if (state.hadException())
409-
return jsUndefined();
407+
if (!joiner.appendWithoutSideEffects(state, value))
408+
goto generalCase;
410409
} else {
411410
if (!holesKnownToBeOK) {
412411
if (holesMustForwardToPrototype(state, thisObject))
@@ -454,9 +453,8 @@ static inline JSValue join(ExecState& state, JSObject* thisObject, StringView se
454453
auto data = storage.vector().data();
455454
for (unsigned i = 0; i < length; ++i) {
456455
if (JSValue value = data[i].get()) {
457-
joiner.append(state, value);
458-
if (state.hadException())
459-
return jsUndefined();
456+
if (!joiner.appendWithoutSideEffects(state, value))
457+
goto generalCase;
460458
} else
461459
joiner.appendEmptyString();
462460
}

runtime/JSStringJoiner.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class JSStringJoiner {
3737
JSStringJoiner(ExecState&, StringView separator, unsigned stringCount);
3838

3939
void append(ExecState&, JSValue);
40+
bool appendWithoutSideEffects(ExecState&, JSValue);
4041
void appendEmptyString();
4142

4243
JSValue join(ExecState&);
@@ -96,42 +97,52 @@ ALWAYS_INLINE void JSStringJoiner::appendEmptyString()
9697
m_strings.uncheckedAppend({ { }, { } });
9798
}
9899

99-
ALWAYS_INLINE void JSStringJoiner::append(ExecState& state, JSValue value)
100+
ALWAYS_INLINE bool JSStringJoiner::appendWithoutSideEffects(ExecState& state, JSValue value)
100101
{
101102
// The following code differs from using the result of JSValue::toString in the following ways:
102103
// 1) It's inlined more than JSValue::toString is.
103104
// 2) It includes conversion to WTF::String in a way that avoids allocating copies of substrings.
104105
// 3) It doesn't create a JSString for numbers, true, or false.
105106
// 4) It turns undefined and null into the empty string instead of "undefined" and "null".
106107
// 5) It uses optimized code paths for all the cases known to be 8-bit and for the empty string.
108+
// If we might make an effectful calls, return false. Otherwise return true.
107109

108110
if (value.isCell()) {
109-
if (value.asCell()->isString()) {
110-
append(asString(value)->viewWithUnderlyingString(state));
111-
return;
112-
}
111+
JSString* jsString;
112+
if (!value.asCell()->isString())
113+
return false;
114+
jsString = asString(value);
113115
append(value.toString(&state)->viewWithUnderlyingString(state));
114-
return;
116+
return true;
115117
}
116118

117119
if (value.isInt32()) {
118120
append8Bit(state.vm().numericStrings.add(value.asInt32()));
119-
return;
121+
return true;
120122
}
121123
if (value.isDouble()) {
122124
append8Bit(state.vm().numericStrings.add(value.asDouble()));
123-
return;
125+
return true;
124126
}
125127
if (value.isTrue()) {
126128
append8Bit(state.vm().propertyNames->trueKeyword.string());
127-
return;
129+
return true;
128130
}
129131
if (value.isFalse()) {
130132
append8Bit(state.vm().propertyNames->falseKeyword.string());
131-
return;
133+
return true;
132134
}
133135
ASSERT(value.isUndefinedOrNull());
134136
appendEmptyString();
137+
return true;
138+
}
139+
140+
ALWAYS_INLINE void JSStringJoiner::append(ExecState& state, JSValue value)
141+
{
142+
if (!appendWithoutSideEffects(state, value)) {
143+
JSString* jsString = value.toString(&state);
144+
append(jsString->viewWithUnderlyingString(state));
145+
}
135146
}
136147

137148
}

0 commit comments

Comments
 (0)