Diff
Modified: branches/safari-603-branch/JSTests/ChangeLog (211115 => 211116)
--- branches/safari-603-branch/JSTests/ChangeLog 2017-01-24 23:29:25 UTC (rev 211115)
+++ branches/safari-603-branch/JSTests/ChangeLog 2017-01-24 23:29:30 UTC (rev 211116)
@@ -1,3 +1,24 @@
+2017-01-24 Matthew Hanson <matthew_han...@apple.com>
+
+ Merge r211070. rdar://problem/30121809
+
+ 2017-01-23 Saam Barati <sbar...@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=167247
+ JSC: operationSpreadGeneric uses the wrong global object for the builtin function and slow_path_spread consults the wrong global object to prove if the iterator protocol is unobservable
+ <rdar://problem/30121809>
+
+ Reviewed by Filip Pizlo.
+
+ * stress/spread-consults-correct-global-object.js: Added.
+ (assert):
+ (spread):
+ * stress/spread-correct-global-object-on-exception.js: Added.
+ (assert):
+ (spread):
+ (const.objectText.let.o.Symbol.iterator):
+ (catch):
+
2017-01-18 Matthew Hanson <matthew_han...@apple.com>
Merge r210844. rdar://problem/29993906
Added: branches/safari-603-branch/JSTests/stress/spread-consults-correct-global-object.js (0 => 211116)
--- branches/safari-603-branch/JSTests/stress/spread-consults-correct-global-object.js (rev 0)
+++ branches/safari-603-branch/JSTests/stress/spread-consults-correct-global-object.js 2017-01-24 23:29:30 UTC (rev 211116)
@@ -0,0 +1,18 @@
+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion");
+}
+function spread(a) {
+ return [...a];
+}
+noInline(spread);
+
+const foo = {};
+
+let secondGlobalObject = createGlobalObject();
+secondGlobalObject.Array.prototype[0] = foo;
+let x = secondGlobalObject.Function("return [, 20];")();
+let result = spread(x);
+assert(result.length === 2);
+assert(result[0] === foo);
+assert(result[1] === 20);
Added: branches/safari-603-branch/JSTests/stress/spread-correct-global-object-on-exception.js (0 => 211116)
--- branches/safari-603-branch/JSTests/stress/spread-correct-global-object-on-exception.js (rev 0)
+++ branches/safari-603-branch/JSTests/stress/spread-correct-global-object-on-exception.js 2017-01-24 23:29:30 UTC (rev 211116)
@@ -0,0 +1,43 @@
+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion");
+}
+function spread(a) {
+ return [...a];
+}
+noInline(spread);
+
+const objectText = `
+ let o = {
+ [Symbol.iterator]() {
+ return {
+ next() {
+ return {done: true};
+ }
+ };
+ }
+ };
+ o;
+`;
+
+let o = eval(objectText);
+for (let i = 0; i < 1000; i++) {
+ if (i % 23 === 0)
+ o = eval(objectText);
+ spread(o);
+}
+
+let myGlobalObject = globalObjectForObject(new Object);
+
+let secondGlobalObject = createGlobalObject();
+let o2 = secondGlobalObject.Function("return {};")();
+
+let error = null;
+try {
+ spread(o2);
+} catch(e) {
+ error = e;
+}
+
+assert(error);
+assert(globalObjectForObject(error) === myGlobalObject);
Modified: branches/safari-603-branch/Source/_javascript_Core/ChangeLog (211115 => 211116)
--- branches/safari-603-branch/Source/_javascript_Core/ChangeLog 2017-01-24 23:29:25 UTC (rev 211115)
+++ branches/safari-603-branch/Source/_javascript_Core/ChangeLog 2017-01-24 23:29:30 UTC (rev 211116)
@@ -1,5 +1,48 @@
2017-01-24 Matthew Hanson <matthew_han...@apple.com>
+ Merge r211070. rdar://problem/30121809
+
+ 2017-01-23 Saam Barati <sbar...@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=167247
+ JSC: operationSpreadGeneric uses the wrong global object for the builtin function and slow_path_spread consults the wrong global object to prove if the iterator protocol is unobservable
+ <rdar://problem/30121809>
+
+ Reviewed by Filip Pizlo.
+
+ There were two bugs in the different tiers with respect to how
+ spread handled global objects.
+
+ The first was in the LLInt/baseline inside slow_path_spread:
+
+ We consulted the lexical global object instead of the thing we're
+ spreading's global object to determine if the array iterator protocol
+ is unobservable. This is wrong if the incoming array is from a different
+ global object. We must consult the incoming array's global object
+ to determine if it can be spread using the fast path.
+
+ The second was in operationSpreadGeneric in the DFG/FTL:
+
+ We were always using the incoming array's global object, even
+ when going down the slow path. This is wrong because we were
+ fetching the builtin iteration function helper from the incoming
+ array's global object, which meant that if the iterator function
+ were to throw an exception, it could leak objects from a different
+ global object. We should be executing the iterator function with
+ the lexical global object.
+
+ * dfg/DFGOperations.cpp:
+ * jsc.cpp:
+ (GlobalObject::finishCreation):
+ (functionGlobalObjectForObject):
+ * runtime/CommonSlowPaths.cpp:
+ (JSC::SLOW_PATH_DECL):
+ * runtime/JSArray.h:
+ * runtime/JSArrayInlines.h:
+ (JSC::JSArray::isIteratorProtocolFastAndNonObservable):
+
+2017-01-24 Matthew Hanson <matthew_han...@apple.com>
+
Merge r211069. rdar://problem/30173274
2017-01-22 Filip Pizlo <fpi...@apple.com>
Modified: branches/safari-603-branch/Source/_javascript_Core/dfg/DFGOperations.cpp (211115 => 211116)
--- branches/safari-603-branch/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-01-24 23:29:25 UTC (rev 211115)
+++ branches/safari-603-branch/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-01-24 23:29:30 UTC (rev 211116)
@@ -47,6 +47,7 @@
#include "Interpreter.h"
#include "JIT.h"
#include "JITExceptions.h"
+#include "JSArrayInlines.h"
#include "JSCInlines.h"
#include "JSFixedArray.h"
#include "JSGenericTypedArrayViewConstructorInlines.h"
@@ -1984,19 +1985,18 @@
auto throwScope = DECLARE_THROW_SCOPE(vm);
- JSGlobalObject* globalObject = iterable->structure(vm)->globalObject();
- if (!globalObject)
- globalObject = exec->lexicalGlobalObject();
-
- if (isJSArray(iterable) && globalObject->isArrayIteratorProtocolFastAndNonObservable()) {
+ if (isJSArray(iterable)) {
JSArray* array = jsCast<JSArray*>(iterable);
- throwScope.release();
- return JSFixedArray::createFromArray(exec, vm, array);
+ if (array->isIteratorProtocolFastAndNonObservable()) {
+ throwScope.release();
+ return JSFixedArray::createFromArray(exec, vm, array);
+ }
}
// FIXME: we can probably make this path faster by having our caller JS code call directly into
// the iteration protocol builtin: https://bugs.webkit.org/show_bug.cgi?id=164520
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
JSArray* array;
{
JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
@@ -2022,7 +2022,7 @@
ASSERT(isJSArray(cell));
JSArray* array = jsCast<JSArray*>(cell);
- ASSERT(array->globalObject()->isArrayIteratorProtocolFastAndNonObservable());
+ ASSERT(array->isIteratorProtocolFastAndNonObservable());
return JSFixedArray::createFromArray(exec, vm, array);
}
Modified: branches/safari-603-branch/Source/_javascript_Core/jsc.cpp (211115 => 211116)
--- branches/safari-603-branch/Source/_javascript_Core/jsc.cpp 2017-01-24 23:29:25 UTC (rev 211115)
+++ branches/safari-603-branch/Source/_javascript_Core/jsc.cpp 2017-01-24 23:29:30 UTC (rev 211116)
@@ -1007,6 +1007,7 @@
static EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState*);
struct Script {
enum class StrictMode {
@@ -1231,6 +1232,8 @@
addFunction(vm, "setRandomSeed", functionSetRandomSeed, 1);
addFunction(vm, "isRope", functionIsRope, 1);
+ addFunction(vm, "globalObjectForObject", functionGlobalObjectForObject, 1);
+
addFunction(vm, "is32BitPlatform", functionIs32BitPlatform, 0);
addFunction(vm, "loadModule", functionLoadModule, 1);
@@ -2104,6 +2107,15 @@
return JSValue::encode(jsBoolean(!impl));
}
+EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState* exec)
+{
+ JSValue value = exec->argument(0);
+ RELEASE_ASSERT(value.isObject());
+ JSGlobalObject* globalObject = jsCast<JSObject*>(value)->globalObject();
+ RELEASE_ASSERT(globalObject);
+ return JSValue::encode(globalObject);
+}
+
EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
{
Vector<char, 256> line;
Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (211115 => 211116)
--- branches/safari-603-branch/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2017-01-24 23:29:25 UTC (rev 211115)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2017-01-24 23:29:30 UTC (rev 211116)
@@ -43,6 +43,7 @@
#include "Interpreter.h"
#include "IteratorOperations.h"
#include "JIT.h"
+#include "JSArrayInlines.h"
#include "JSCInlines.h"
#include "JSCJSValue.h"
#include "JSFixedArray.h"
@@ -1034,16 +1035,18 @@
JSValue iterable = OP_C(2).jsValue();
- JSGlobalObject* globalObject = exec->lexicalGlobalObject();
-
- if (iterable.isCell() && isJSArray(iterable.asCell()) && globalObject->isArrayIteratorProtocolFastAndNonObservable()) {
- // JSFixedArray::createFromArray does not consult the prototype chain,
- // so we must be sure that not consulting the prototype chain would
- // produce the same value during iteration.
+ if (iterable.isCell() && isJSArray(iterable.asCell())) {
JSArray* array = jsCast<JSArray*>(iterable);
- RETURN(JSFixedArray::createFromArray(exec, vm, array));
+ if (array->isIteratorProtocolFastAndNonObservable()) {
+ // JSFixedArray::createFromArray does not consult the prototype chain,
+ // so we must be sure that not consulting the prototype chain would
+ // produce the same value during iteration.
+ RETURN(JSFixedArray::createFromArray(exec, vm, array));
+ }
}
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+
JSArray* array;
{
JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/JSArray.h (211115 => 211116)
--- branches/safari-603-branch/Source/_javascript_Core/runtime/JSArray.h 2017-01-24 23:29:25 UTC (rev 211115)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/JSArray.h 2017-01-24 23:29:30 UTC (rev 211116)
@@ -150,6 +150,8 @@
JS_EXPORT_PRIVATE void fillArgList(ExecState*, MarkedArgumentBuffer&);
JS_EXPORT_PRIVATE void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
+ bool isIteratorProtocolFastAndNonObservable();
+
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
{
return Structure::create(vm, globalObject, prototype, TypeInfo(ArrayType, StructureFlags), info(), indexingType);
Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/JSArrayInlines.h (211115 => 211116)
--- branches/safari-603-branch/Source/_javascript_Core/runtime/JSArrayInlines.h 2017-01-24 23:29:25 UTC (rev 211115)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/JSArrayInlines.h 2017-01-24 23:29:30 UTC (rev 211116)
@@ -93,4 +93,9 @@
return lengthValue.toLength(exec);
}
+ALWAYS_INLINE bool JSArray::isIteratorProtocolFastAndNonObservable()
+{
+ return globalObject()->isArrayIteratorProtocolFastAndNonObservable();
+}
+
} // namespace JSC