Title: [270874] trunk
Revision
270874
Author
[email protected]
Date
2020-12-15 16:33:34 -0800 (Tue, 15 Dec 2020)

Log Message

Non-enumerable property fails to shadow inherited enumerable property from for-in
https://bugs.webkit.org/show_bug.cgi?id=38970

Reviewed by Keith Miller.

JSTests:

* stress/arguments-bizarre-behaviour-disable-enumerability.js:
* stress/for-in-redefine-enumerable.js: Added.
* stress/for-in-shadow-non-enumerable.js: Added.
* test262/expectations.yaml: Mark 4 test cases as passing.

Source/_javascript_Core:

While for/in was initially specified with notion of "shadowing", it wasn't clarified
until ES5 that [[Enumerable]] attributes are ignored when determining if a property
has already been processed. Recently, for/in spec was expanded [1] to pin down common
case enumeration as it's currently implemented by V8 and SpiderMonkey.

Since keeping track of DontEnum properties is a massive slowdown for uncached runs
(with any data structure used), this patch simply adds [[Enumerable]] check to
has_{indexed,structure,generic}_property bytecode ops and does renaming chores.

Common code is now shared between HasIndexedProperty (emitted for `0 in arr`) and
HasEnumerableIndexedProperty DFG nodes via passing different slow path ops rather
than having OpInfo with PropertySlot::InternalMethodType, which is a nice refactor.

While this change aligns common case for/in enumeration with the spec and other
engines, it also introduces a few observable discrepancies from V8 and SpiderMonkey,
which are permitted by the spec [2]:
a) properties that have been redefined as DontEnum within loop body are skipped,
   which matches the spec [3] and seems like expected behavior;
b) "shadowing" is broken if a DontEnum property of already visited object is
   added / deleted / redefined within loop body, which (pretty much) never happens.

This patch introduces a new invariant: all properties getOwn*PropertyNames() returns
in DontEnumPropertiesMode::Exclude should be reported as [[Enumerable]] by
getOwnPropertySlot(). JSCallbackObject and RuntimeArray are fixed to follow it.

for/in and Object.keys microbenchmarks are neutral. This change does not affect
JSPropertyNameEnumerator caching, nor fast paths of its bytecodes.

[1]: https://github.com/tc39/ecma262/pull/1791
[2]: https://tc39.es/ecma262/#sec-enumerate-object-properties (last paragraph)
[3]: https://tc39.es/ecma262/#sec-%foriniteratorprototype%.next (step 7.b.iii)

* API/JSCallbackObjectFunctions.h:
(JSC::JSCallbackObject<Parent>::getOwnPropertySlot):
* API/tests/testapi.c:
* API/tests/testapiScripts/testapi.js:
* bytecode/BytecodeList.rb:
* bytecode/BytecodeUseDef.cpp:
(JSC::computeUsesForBytecodeIndexImpl):
(JSC::computeDefsForBytecodeIndexImpl):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
* bytecode/Opcode.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitHasEnumerableIndexedProperty):
(JSC::BytecodeGenerator::emitHasEnumerableStructureProperty):
(JSC::BytecodeGenerator::emitHasEnumerableProperty):
(JSC::BytecodeGenerator::emitHasGenericProperty): Deleted.
(JSC::BytecodeGenerator::emitHasIndexedProperty): Deleted.
(JSC::BytecodeGenerator::emitHasStructureProperty): Deleted.
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ForInNode::emitBytecode):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::convertToHasIndexedProperty):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasArrayMode):
(JSC::DFG::Node::hasInternalMethodType const): Deleted.
(JSC::DFG::Node::internalMethodType const): Deleted.
(JSC::DFG::Node::setInternalMethodType): Deleted.
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSSALoweringPhase.cpp:
(JSC::DFG::SSALoweringPhase::handleNode):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileHasEnumerableProperty):
(JSC::DFG::SpeculativeJIT::compileHasEnumerableStructureProperty):
(JSC::DFG::SpeculativeJIT::compileHasIndexedProperty):
(JSC::DFG::SpeculativeJIT::compileHasGenericProperty): Deleted.
(JSC::DFG::SpeculativeJIT::compileHasStructureProperty): Deleted.
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileHasIndexedProperty):
(JSC::FTL::DFG::LowerDFGToB3::compileHasEnumerableProperty):
(JSC::FTL::DFG::LowerDFGToB3::compileHasEnumerableStructureProperty):
(JSC::FTL::DFG::LowerDFGToB3::compileHasGenericProperty): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::compileHasStructureProperty): Deleted.
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_has_enumerable_structure_property):
(JSC::JIT::emit_op_has_enumerable_indexed_property):
(JSC::JIT::emitSlow_op_has_enumerable_indexed_property):
(JSC::JIT::emit_op_has_structure_property): Deleted.
(JSC::JIT::emit_op_has_indexed_property): Deleted.
(JSC::JIT::emitSlow_op_has_indexed_property): Deleted.
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_has_enumerable_structure_property):
(JSC::JIT::emit_op_has_enumerable_indexed_property):
(JSC::JIT::emitSlow_op_has_enumerable_indexed_property):
(JSC::JIT::emit_op_has_structure_property): Deleted.
(JSC::JIT::emit_op_has_indexed_property): Deleted.
(JSC::JIT::emitSlow_op_has_indexed_property): Deleted.
* jit/JITOperations.cpp:
(JSC::JSC_DEFINE_JIT_OPERATION):
* jit/JITOperations.h:
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::JSC_DEFINE_COMMON_SLOW_PATH):
* runtime/CommonSlowPaths.h:
* runtime/JSObject.cpp:
(JSC::JSObject::hasProperty const):
(JSC::JSObject::hasEnumerableProperty const):
(JSC::JSObject::hasPropertyGeneric const): Deleted.
* runtime/JSObject.h:

Source/WebCore:

Report RuntimeArray indices as [[Enumerable]].

Test: platform/mac/fast/dom/wrapper-classes-objc.html

* bridge/runtime_array.cpp:
(JSC::RuntimeArray::getOwnPropertySlot):
(JSC::RuntimeArray::getOwnPropertySlotByIndex):

LayoutTests:

* platform/mac/fast/dom/wrapper-classes-objc-expected.txt:
* platform/mac/fast/dom/wrapper-classes-objc.html:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (270873 => 270874)


--- trunk/JSTests/ChangeLog	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/JSTests/ChangeLog	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1,3 +1,15 @@
+2020-12-15  Alexey Shvayka  <[email protected]>
+
+        Non-enumerable property fails to shadow inherited enumerable property from for-in
+        https://bugs.webkit.org/show_bug.cgi?id=38970
+
+        Reviewed by Keith Miller.
+
+        * stress/arguments-bizarre-behaviour-disable-enumerability.js:
+        * stress/for-in-redefine-enumerable.js: Added.
+        * stress/for-in-shadow-non-enumerable.js: Added.
+        * test262/expectations.yaml: Mark 4 test cases as passing.
+
 2020-12-15  Yusuke Suzuki  <[email protected]>
 
         Suppress noise from JSTests/stress/lars-sab-workers.js

Modified: trunk/JSTests/stress/arguments-bizarre-behaviour-disable-enumerability.js (270873 => 270874)


--- trunk/JSTests/stress/arguments-bizarre-behaviour-disable-enumerability.js	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/JSTests/stress/arguments-bizarre-behaviour-disable-enumerability.js	2020-12-16 00:33:34 UTC (rev 270874)
@@ -18,7 +18,7 @@
 for (var s in result[2])
     array.push(s);
 
-if (array.join(",") != "0")
+if (array.join(",") != "")
     throw new Error();
 
 if (Object.keys(result[2]).join(",") != "0")

Added: trunk/JSTests/stress/for-in-redefine-enumerable.js (0 => 270874)


--- trunk/JSTests/stress/for-in-redefine-enumerable.js	                        (rev 0)
+++ trunk/JSTests/stress/for-in-redefine-enumerable.js	2020-12-16 00:33:34 UTC (rev 270874)
@@ -0,0 +1,107 @@
+function assert(x) {
+    if (!x)
+        throw new Error("Bad assertion!");
+}
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error(`Bad value: ${actual}.`);
+}
+
+const enumDesc = { value: 0, writable: true, enumerable: true, configurable: true };
+const dontEnumDesc = { value: 0, writable: true, enumerable: false, configurable: true };
+
+// indexed property
+(() => {
+    function test() {
+        var arr = Object.defineProperties([0, 0, 0], { 1: dontEnumDesc });
+        for (var i in arr) {
+            assert(i in arr);
+            shouldBe(arr[i], 0);
+            ++arr[i];
+            if (i === "0")
+                Object.defineProperties(arr, { 1: enumDesc, 2: dontEnumDesc });
+        }
+        shouldBe(arr[0], 1);
+        shouldBe(arr[1], 0);
+        shouldBe(arr[2], 0);
+    }
+
+    for (var i = 0; i < 1e5; ++i)
+        test();
+})();
+
+// structure property
+(() => {
+    function test() {
+        var obj = Object.create(null, { a: enumDesc, b: enumDesc, c: dontEnumDesc });
+        for (var key in obj) {
+            assert(key in obj);
+            shouldBe(obj[key], 0);
+            ++obj[key];
+            if (key === "a")
+                Object.defineProperties(obj, { b: dontEnumDesc, c: enumDesc });
+        }
+        shouldBe(obj.a, 1);
+        shouldBe(obj.b, 0);
+        shouldBe(obj.c, 0);
+    }
+
+    for (var i = 0; i < 1e5; ++i)
+        test();
+})();
+
+// generic property (Proxy)
+(() => {
+    function test() {
+        var target = { a: 0, b: 0, c: 0 };
+        var enumMap = { a: true, b: true, c: false };
+        var proxy = new Proxy(target, {
+            getOwnPropertyDescriptor: (_, key) => {
+                return { value: target[key], writable: true, enumerable: enumMap[key], configurable: true };
+            },
+        });
+
+        for (var key in proxy) {
+            assert(key in proxy);
+            shouldBe(proxy[key], 0);
+            ++target[key];
+            if (key === "a") {
+                enumMap.b = false;
+                enumMap.c = true;
+            }
+        }
+        shouldBe(target.a, 1);
+        shouldBe(target.b, 0);
+        shouldBe(target.c, 0);
+    }
+
+    for (var i = 0; i < 1e5; ++i)
+        test();
+})();
+
+// generic property (in prototype)
+(() => {
+    function test() {
+        var seen = {};
+        var proto = Object.create(null, { b: enumDesc, c: dontEnumDesc, d: enumDesc, e: enumDesc });
+        var heir = Object.create(proto, { a: enumDesc, e: dontEnumDesc });
+        for (var key in heir) {
+            assert(key in heir);
+            shouldBe(heir[key], 0);
+            seen[key] = true;
+            if (key === "a")
+                Object.defineProperties(proto, { b: dontEnumDesc, c: enumDesc });
+            if (key === "d")
+                Object.defineProperties(heir, { e: enumDesc });
+        }
+        assert(seen.a);
+        assert(!seen.b);
+        assert(!seen.c);
+        assert(seen.d);
+        assert(seen.e);
+    }
+
+    for (var i = 0; i < 1e5; ++i)
+        test();
+})();

Added: trunk/JSTests/stress/for-in-shadow-non-enumerable.js (0 => 270874)


--- trunk/JSTests/stress/for-in-shadow-non-enumerable.js	                        (rev 0)
+++ trunk/JSTests/stress/for-in-shadow-non-enumerable.js	2020-12-16 00:33:34 UTC (rev 270874)
@@ -0,0 +1,174 @@
+const dontEnumDesc = { value: 1, writable: true, enumerable: false, configurable: true };
+const testCases = [
+  {
+    name: "Object",
+    createObject: () => Object.create(null, { foo: dontEnumDesc, bar: dontEnumDesc }),
+    dontEnumKeys: ["foo", "bar"],
+  },
+  {
+    name: "Error",
+    createObject: () => new Error(),
+    dontEnumKeys: ["line", "column", "sourceURL", "stack"],
+  },
+  {
+    name: "Array (empty)",
+    createObject: () => [],
+    dontEnumKeys: ["length"],
+  },
+  {
+    name: "Array (sparse)",
+    createObject: () => Object.defineProperties([0, 1, 2], { 0: dontEnumDesc, 2: dontEnumDesc }),
+    dontEnumKeys: ["0", "2", "length"],
+  },
+  {
+    name: "Function (strict)",
+    createObject: () => function() { "use strict"; },
+    dontEnumKeys: ["length", "name", "prototype"],
+  },
+  {
+    name: "Function (non-strict)",
+    createObject: () => function() {},
+    dontEnumKeys: ["arguments", "caller", "length", "name", "prototype"],
+  },
+  {
+    name: "RegExp",
+    createObject: () => /(?:)/g,
+    dontEnumKeys: ["lastIndex"],
+  },
+  {
+    name: "String",
+    createObject: () => new String("foo"),
+    dontEnumKeys: ["length"],
+  },
+  {
+    name: "Arguments (strict)",
+    createObject: function(foo) { "use strict"; return arguments; },
+    dontEnumKeys: ["length", "callee"],
+  },
+  {
+    name: "Arguments (non-strict)",
+    createObject: function(foo) { return arguments; },
+    dontEnumKeys: ["length", "callee"],
+  },
+  {
+    name: "Reflect",
+    createObject: () => $vm.createGlobalObject().Reflect,
+    dontEnumKeys: ["apply", "get", "has", "set"],
+  },
+  {
+    name: "Date.prototype",
+    createObject: () => $vm.createGlobalObject().Date.prototype,
+    dontEnumKeys: ["toISOString", "getTime", "setYear"],
+  },
+];
+
+// basic tests
+for (const t of testCases) {
+  assert(!contains(forIn(t.createObject()), t.dontEnumKeys), t.name);
+  assert(!contains(Object.keys(t.createObject()), t.dontEnumKeys), t.name);
+
+  assert(contains(Object.getOwnPropertyNames(t.createObject()), t.dontEnumKeys), t.name);
+  assert(contains(Reflect.ownKeys(t.createObject()), t.dontEnumKeys), t.name);
+}
+
+// shadowing: DontEnum => Enum
+for (const t of testCases) {
+  assert(
+    !contains(
+      forIn(makePrototypeChain(t.createObject(), makeObject(t.dontEnumKeys))),
+      t.dontEnumKeys,
+    ),
+    t.name,
+  );
+}
+
+// shadowing: {} => DontEnum => {} => Enum
+for (const t of testCases) {
+  assert(
+    !contains(
+      forIn(makePrototypeChain({}, t.createObject(), {}, makeObject(t.dontEnumKeys))),
+      t.dontEnumKeys,
+    ),
+    t.name,
+  );
+}
+
+// shadowing: DontEnum => {} => Enum => {} => Enum
+for (const t of testCases) {
+  assert(
+    !contains(
+      forIn(makePrototypeChain(t.createObject(), {}, makeObject(t.dontEnumKeys), {}, makeObject(t.dontEnumKeys))),
+      t.dontEnumKeys,
+    ),
+    t.name,
+  );
+}
+
+// shadowing: {} => DontEnum (enumerable: true => false) => {} => Enum
+for (const t of testCases) {
+  const dontEnumObject = t.createObject();
+  const target = makePrototypeChain({}, dontEnumObject, {}, makeObject(t.dontEnumKeys));
+  assert(!contains(forIn(target), t.dontEnumKeys), t.name);
+
+  const enumKeys = t.dontEnumKeys.filter(key => Reflect.defineProperty(dontEnumObject, key, { enumerable: true }));
+  assert(contains(forIn(target), enumKeys), t.name);
+}
+
+// shadowing: {} => DontEnum (delete non-enumerable keys) => {} => Enum
+for (const t of testCases) {
+  const dontEnumObject = t.createObject();
+  const target = makePrototypeChain({}, dontEnumObject, {}, makeObject(t.dontEnumKeys));
+  assert(!contains(forIn(target), t.dontEnumKeys), t.name);
+
+  const enumKeys = t.dontEnumKeys.filter(key => Reflect.deleteProperty(dontEnumObject, key));
+  assert(contains(forIn(target), enumKeys), t.name);
+}
+
+// shadowing: {} => DontEnum (materialized) => {} => Enum
+for (const t of testCases) {
+  const dontEnumObject = t.createObject();
+  const target = makePrototypeChain({}, dontEnumObject, {}, makeObject(t.dontEnumKeys));
+  assert(!contains(forIn(target), t.dontEnumKeys), t.name);
+
+  const dontEnumKeys = t.dontEnumKeys.filter(key => {
+    const desc = Object.getOwnPropertyDescriptor(dontEnumObject, key);
+    if (!Reflect.deleteProperty(dontEnumObject, key)) return false;
+    Object.defineProperty(dontEnumObject, key, desc);
+    return true;
+  });
+
+  if (dontEnumKeys.length)
+    assert(!contains(forIn(target), dontEnumKeys), t.name);
+}
+
+// helpers
+function assert(value, name) {
+  if (!value)
+    throw new Error(`Bad value: ${value}. Test case: ${name}.`);
+}
+
+function contains(array, subarray) {
+  return subarray.every(item => array.includes(item));
+}
+
+function forIn(object) {
+  const keys = [];
+  for (const key in object)
+    keys.push(key);
+  return keys;
+}
+
+function makePrototypeChain(...objects) {
+  objects.reduce((object, prototype) => {
+    Object.setPrototypeOf(object, prototype);
+    return prototype;
+  });
+  return objects[0];
+}
+
+function makeObject(keys) {
+  const object = {};
+  for (const key of keys)
+    object[key] = key;
+  return object;
+}

Modified: trunk/JSTests/test262/expectations.yaml (270873 => 270874)


--- trunk/JSTests/test262/expectations.yaml	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/JSTests/test262/expectations.yaml	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1858,16 +1858,10 @@
 test/language/statements/for-await-of/ticks-with-sync-iter-resolved-promise-and-constructor-lookup.js:
   default: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected [pre, tick 1, constructor, constructor, tick 2, tick 3, loop, tick 4, constructor] and [pre, constructor, constructor, tick 1, tick 2, loop, constructor, tick 3, tick 4, post] to have the same contents. Ticks and constructor lookups'
   strict mode: 'Test262:AsyncTestFailure:Test262Error: Test262Error: Expected [pre, tick 1, constructor, constructor, tick 2, tick 3, loop, tick 4, constructor] and [pre, constructor, constructor, tick 1, tick 2, loop, constructor, tick 3, tick 4, post] to have the same contents. Ticks and constructor lookups'
-test/language/statements/for-in/12.6.4-2.js:
-  default: 'Test262Error: accessedProp Expected SameValue(«true», «false») to be true'
-  strict mode: 'Test262Error: accessedProp Expected SameValue(«true», «false») to be true'
 test/language/statements/for-in/head-lhs-let.js:
   default: "SyntaxError: Cannot use the keyword 'in' as a lexical variable name."
 test/language/statements/for-in/identifier-let-allowed-as-lefthandside-_expression_-not-strict.js:
   default: "SyntaxError: Cannot use the keyword 'in' as a lexical variable name."
-test/language/statements/for-in/order-enumerable-shadowed.js:
-  default: 'Test262Error: Expected [p1, p2] and [p1] to have the same contents. '
-  strict mode: 'Test262Error: Expected [p1, p2] and [p1] to have the same contents. '
 test/language/statements/for-in/scope-body-lex-open.js:
   default: 'Test262Error: Expected a ReferenceError to be thrown but no exception was thrown at all'
   strict mode: 'Test262Error: Expected a ReferenceError to be thrown but no exception was thrown at all'

Modified: trunk/LayoutTests/ChangeLog (270873 => 270874)


--- trunk/LayoutTests/ChangeLog	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/LayoutTests/ChangeLog	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1,3 +1,13 @@
+2020-12-15  Alexey Shvayka  <[email protected]>
+
+        Non-enumerable property fails to shadow inherited enumerable property from for-in
+        https://bugs.webkit.org/show_bug.cgi?id=38970
+
+        Reviewed by Keith Miller.
+
+        * platform/mac/fast/dom/wrapper-classes-objc-expected.txt:
+        * platform/mac/fast/dom/wrapper-classes-objc.html:
+
 2020-12-15  Alex Christensen  <[email protected]>
 
         REGRESSION: [macOS] http/tests/inspector/network/resource-response-service-worker.html is a flaky failure

Modified: trunk/LayoutTests/platform/mac/fast/dom/wrapper-classes-objc-expected.txt (270873 => 270874)


--- trunk/LayoutTests/platform/mac/fast/dom/wrapper-classes-objc-expected.txt	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/LayoutTests/platform/mac/fast/dom/wrapper-classes-objc-expected.txt	2020-12-16 00:33:34 UTC (rev 270874)
@@ -189,6 +189,7 @@
 PASS typeof objCObjectOfClass('WebScriptObject') is 'object'
 PASS objCObjectOfClass('NSArray') instanceof Array is true
 PASS concatenateArray(objCArrayOfString()) is 'onetwothree'
+PASS objCArrayOfString().every((_, i, arr) => arr.propertyIsEnumerable(i)) is true
 PASS let arr = objCArrayOfString(); arr.length is 3
 PASS let arr = objCArrayOfString(); arr.length = 0 threw exception RangeError: Range error.
 PASS let arr = objCArrayOfString(); arr.length = 5 threw exception RangeError: Range error.

Modified: trunk/LayoutTests/platform/mac/fast/dom/wrapper-classes-objc.html (270873 => 270874)


--- trunk/LayoutTests/platform/mac/fast/dom/wrapper-classes-objc.html	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/LayoutTests/platform/mac/fast/dom/wrapper-classes-objc.html	2020-12-16 00:33:34 UTC (rev 270874)
@@ -286,6 +286,7 @@
     shouldBeTrue("objCObjectOfClass('NSArray') instanceof Array");
 
     shouldBe("concatenateArray(objCArrayOfString())", "'onetwothree'");
+    shouldBeTrue("objCArrayOfString().every((_, i, arr) => arr.propertyIsEnumerable(i))");
 
     shouldBe("let arr = objCArrayOfString(); arr.length", "3");
     shouldThrow("let arr = objCArrayOfString(); arr.length = 0");

Modified: trunk/Source/_javascript_Core/API/JSCallbackObjectFunctions.h (270873 => 270874)


--- trunk/Source/_javascript_Core/API/JSCallbackObjectFunctions.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/API/JSCallbackObjectFunctions.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -162,6 +162,9 @@
     RefPtr<OpaqueJSString> propertyNameRef;
     
     if (StringImpl* name = propertyName.uid()) {
+        // FIXME: Set ReadOnly conditionally, based on setProperty presence in class inheritance chain.
+        // https://bugs.webkit.org/show_bug.cgi?id=219924
+        unsigned attributes = static_cast<unsigned>(PropertyAttribute::ReadOnly);
         for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
             // optional optimization to bypass getProperty in cases when we only need to know if the property exists
             if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
@@ -169,7 +172,7 @@
                     propertyNameRef = OpaqueJSString::tryCreate(name);
                 JSLock::DropAllLocks dropAllLocks(globalObject);
                 if (hasProperty(ctx, thisRef, propertyNameRef.get())) {
-                    slot.setCustom(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, getCallbackGetter());
+                    slot.setCustom(thisObject, attributes, getCallbackGetter());
                     return true;
                 }
             } else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
@@ -183,21 +186,23 @@
                 }
                 if (exception) {
                     throwException(globalObject, scope, toJS(globalObject, exception));
-                    slot.setValue(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, jsUndefined());
+                    slot.setValue(thisObject, attributes, jsUndefined());
                     return true;
                 }
                 if (value) {
-                    slot.setValue(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, toJS(globalObject, value));
+                    slot.setValue(thisObject, attributes, toJS(globalObject, value));
                     return true;
                 }
             }
             
             if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(globalObject)) {
-                if (staticValues->contains(name)) {
+                if (StaticValueEntry* entry = staticValues->get(name)) {
+                    // FIXME: getStaticValue() performs the same loop & checks just to acquire `entry`.
+                    // https://bugs.webkit.org/show_bug.cgi?id=219925
                     JSValue value = thisObject->getStaticValue(globalObject, propertyName);
                     RETURN_IF_EXCEPTION(scope, false);
                     if (value) {
-                        slot.setValue(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, value);
+                        slot.setValue(thisObject, entry->attributes, value);
                         return true;
                     }
                 }
@@ -204,8 +209,8 @@
             }
             
             if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(globalObject)) {
-                if (staticFunctions->contains(name)) {
-                    slot.setCustom(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, getStaticFunctionGetter());
+                if (StaticFunctionEntry* entry = staticFunctions->get(name)) {
+                    slot.setCustom(thisObject, entry->attributes, getStaticFunctionGetter());
                     return true;
                 }
             }

Modified: trunk/Source/_javascript_Core/API/tests/testapi.c (270873 => 270874)


--- trunk/Source/_javascript_Core/API/tests/testapi.c	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/API/tests/testapi.c	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1017,6 +1017,7 @@
 
 static JSStaticValue globalObject_staticValues[] = {
     { "globalStaticValue", globalObject_get, globalObject_set, kJSPropertyAttributeNone },
+    { "globalStaticValue2", globalObject_get, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum },
     { 0, 0, 0, 0 }
 };
 
@@ -1023,6 +1024,7 @@
 static JSStaticFunction globalObject_staticFunctions[] = {
     { "globalStaticFunction", globalObject_call, kJSPropertyAttributeNone },
     { "globalStaticFunction2", globalObject_call, kJSPropertyAttributeNone },
+    { "globalStaticFunction3", globalObject_call, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum },
     { "gc", functionGC, kJSPropertyAttributeNone },
     { 0, 0, 0 }
 };

Modified: trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi.js (270873 => 270874)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi.js	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi.js	2020-12-16 00:33:34 UTC (rev 270874)
@@ -84,6 +84,16 @@
 shouldBe("globalStaticFunction2();", 20);
 shouldBe("this.globalStaticFunction2();", 20);
 
+var globalStaticValue2Descriptor = Object.getOwnPropertyDescriptor(this, "globalStaticValue2");
+shouldBe('typeof globalStaticValue2Descriptor', "object");
+shouldBe('globalStaticValue2Descriptor.writable', false);
+shouldBe('globalStaticValue2Descriptor.enumerable', false);
+
+var globalStaticFunction3Descriptor = Object.getOwnPropertyDescriptor(this, "globalStaticFunction3");
+shouldBe('typeof globalStaticFunction3Descriptor', "object");
+shouldBe('globalStaticFunction3Descriptor.writable', false);
+shouldBe('globalStaticFunction3Descriptor.enumerable', false);
+
 function iAmNotAStaticFunction() { return 10; }
 shouldBe("iAmNotAStaticFunction();", 10);
 this.iAmNotAStaticFunction = function() { return 20; }
@@ -134,12 +144,12 @@
 shouldBe('typeof alwaysOneDescriptor', "object");
 shouldBe('alwaysOneDescriptor.value', MyObject.alwaysOne);
 shouldBe('alwaysOneDescriptor.configurable', true);
-shouldBe('alwaysOneDescriptor.enumerable', false); // Actually it is.
+shouldBe('alwaysOneDescriptor.enumerable', true);
 var cantFindDescriptor = Object.getOwnPropertyDescriptor(MyObject, "cantFind");
 shouldBe('typeof cantFindDescriptor', "object");
 shouldBe('cantFindDescriptor.value', MyObject.cantFind);
 shouldBe('cantFindDescriptor.configurable', true);
-shouldBe('cantFindDescriptor.enumerable', false);
+shouldBe('cantFindDescriptor.enumerable', true);
 try {
     // If getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
     Object.getOwnPropertyDescriptor(MyObject, "throwOnGet");
@@ -150,7 +160,7 @@
 shouldBe('typeof myPropertyNameDescriptor', "object");
 shouldBe('myPropertyNameDescriptor.value', MyObject.myPropertyName);
 shouldBe('myPropertyNameDescriptor.configurable', true);
-shouldBe('myPropertyNameDescriptor.enumerable', false); // Actually it is.
+shouldBe('myPropertyNameDescriptor.enumerable', true);
 try {
     // if getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
     Object.getOwnPropertyDescriptor(MyObject, "hasPropertyLie");
@@ -237,23 +247,23 @@
 shouldBe('typeof baseDupDescriptor', "object");
 shouldBe('baseDupDescriptor.value', derived.baseDup);
 shouldBe('baseDupDescriptor.configurable', true);
-shouldBe('baseDupDescriptor.enumerable', false);
+shouldBe('baseDupDescriptor.enumerable', true);
 var baseOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "baseOnly");
 shouldBe('typeof baseOnlyDescriptor', "object");
 shouldBe('baseOnlyDescriptor.value', derived.baseOnly);
 shouldBe('baseOnlyDescriptor.configurable', true);
-shouldBe('baseOnlyDescriptor.enumerable', false);
+shouldBe('baseOnlyDescriptor.enumerable', true);
 shouldBe('Object.getOwnPropertyDescriptor(derived, "protoOnly")', undefined);
 var protoDupDescriptor = Object.getOwnPropertyDescriptor(derived, "protoDup");
 shouldBe('typeof protoDupDescriptor', "object");
 shouldBe('protoDupDescriptor.value', derived.protoDup);
 shouldBe('protoDupDescriptor.configurable', true);
-shouldBe('protoDupDescriptor.enumerable', false);
+shouldBe('protoDupDescriptor.enumerable', true);
 var derivedOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "derivedOnly");
 shouldBe('typeof derivedOnlyDescriptor', "object");
 shouldBe('derivedOnlyDescriptor.value', derived.derivedOnly);
 shouldBe('derivedOnlyDescriptor.configurable', true);
-shouldBe('derivedOnlyDescriptor.enumerable', false);
+shouldBe('derivedOnlyDescriptor.enumerable', true);
 
 shouldBe("undefined instanceof MyObject", false);
 EvilExceptionObject.hasInstance = function f() { return f(); };

Modified: trunk/Source/_javascript_Core/ChangeLog (270873 => 270874)


--- trunk/Source/_javascript_Core/ChangeLog	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1,3 +1,142 @@
+2020-12-15  Alexey Shvayka  <[email protected]>
+
+        Non-enumerable property fails to shadow inherited enumerable property from for-in
+        https://bugs.webkit.org/show_bug.cgi?id=38970
+
+        Reviewed by Keith Miller.
+
+        While for/in was initially specified with notion of "shadowing", it wasn't clarified
+        until ES5 that [[Enumerable]] attributes are ignored when determining if a property
+        has already been processed. Recently, for/in spec was expanded [1] to pin down common
+        case enumeration as it's currently implemented by V8 and SpiderMonkey.
+
+        Since keeping track of DontEnum properties is a massive slowdown for uncached runs
+        (with any data structure used), this patch simply adds [[Enumerable]] check to
+        has_{indexed,structure,generic}_property bytecode ops and does renaming chores.
+
+        Common code is now shared between HasIndexedProperty (emitted for `0 in arr`) and
+        HasEnumerableIndexedProperty DFG nodes via passing different slow path ops rather
+        than having OpInfo with PropertySlot::InternalMethodType, which is a nice refactor.
+
+        While this change aligns common case for/in enumeration with the spec and other
+        engines, it also introduces a few observable discrepancies from V8 and SpiderMonkey,
+        which are permitted by the spec [2]:
+        a) properties that have been redefined as DontEnum within loop body are skipped,
+           which matches the spec [3] and seems like expected behavior;
+        b) "shadowing" is broken if a DontEnum property of already visited object is
+           added / deleted / redefined within loop body, which (pretty much) never happens.
+
+        This patch introduces a new invariant: all properties getOwn*PropertyNames() returns
+        in DontEnumPropertiesMode::Exclude should be reported as [[Enumerable]] by
+        getOwnPropertySlot(). JSCallbackObject and RuntimeArray are fixed to follow it.
+
+        for/in and Object.keys microbenchmarks are neutral. This change does not affect
+        JSPropertyNameEnumerator caching, nor fast paths of its bytecodes.
+
+        [1]: https://github.com/tc39/ecma262/pull/1791
+        [2]: https://tc39.es/ecma262/#sec-enumerate-object-properties (last paragraph)
+        [3]: https://tc39.es/ecma262/#sec-%foriniteratorprototype%.next (step 7.b.iii)
+
+        * API/JSCallbackObjectFunctions.h:
+        (JSC::JSCallbackObject<Parent>::getOwnPropertySlot):
+        * API/tests/testapi.c:
+        * API/tests/testapiScripts/testapi.js:
+        * bytecode/BytecodeList.rb:
+        * bytecode/BytecodeUseDef.cpp:
+        (JSC::computeUsesForBytecodeIndexImpl):
+        (JSC::computeDefsForBytecodeIndexImpl):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        * bytecode/Opcode.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitHasEnumerableIndexedProperty):
+        (JSC::BytecodeGenerator::emitHasEnumerableStructureProperty):
+        (JSC::BytecodeGenerator::emitHasEnumerableProperty):
+        (JSC::BytecodeGenerator::emitHasGenericProperty): Deleted.
+        (JSC::BytecodeGenerator::emitHasIndexedProperty): Deleted.
+        (JSC::BytecodeGenerator::emitHasStructureProperty): Deleted.
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ForInNode::emitBytecode):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::convertToHasIndexedProperty):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasArrayMode):
+        (JSC::DFG::Node::hasInternalMethodType const): Deleted.
+        (JSC::DFG::Node::internalMethodType const): Deleted.
+        (JSC::DFG::Node::setInternalMethodType): Deleted.
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSSALoweringPhase.cpp:
+        (JSC::DFG::SSALoweringPhase::handleNode):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileHasEnumerableProperty):
+        (JSC::DFG::SpeculativeJIT::compileHasEnumerableStructureProperty):
+        (JSC::DFG::SpeculativeJIT::compileHasIndexedProperty):
+        (JSC::DFG::SpeculativeJIT::compileHasGenericProperty): Deleted.
+        (JSC::DFG::SpeculativeJIT::compileHasStructureProperty): Deleted.
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileHasIndexedProperty):
+        (JSC::FTL::DFG::LowerDFGToB3::compileHasEnumerableProperty):
+        (JSC::FTL::DFG::LowerDFGToB3::compileHasEnumerableStructureProperty):
+        (JSC::FTL::DFG::LowerDFGToB3::compileHasGenericProperty): Deleted.
+        (JSC::FTL::DFG::LowerDFGToB3::compileHasStructureProperty): Deleted.
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_has_enumerable_structure_property):
+        (JSC::JIT::emit_op_has_enumerable_indexed_property):
+        (JSC::JIT::emitSlow_op_has_enumerable_indexed_property):
+        (JSC::JIT::emit_op_has_structure_property): Deleted.
+        (JSC::JIT::emit_op_has_indexed_property): Deleted.
+        (JSC::JIT::emitSlow_op_has_indexed_property): Deleted.
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_has_enumerable_structure_property):
+        (JSC::JIT::emit_op_has_enumerable_indexed_property):
+        (JSC::JIT::emitSlow_op_has_enumerable_indexed_property):
+        (JSC::JIT::emit_op_has_structure_property): Deleted.
+        (JSC::JIT::emit_op_has_indexed_property): Deleted.
+        (JSC::JIT::emitSlow_op_has_indexed_property): Deleted.
+        * jit/JITOperations.cpp:
+        (JSC::JSC_DEFINE_JIT_OPERATION):
+        * jit/JITOperations.h:
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::JSC_DEFINE_COMMON_SLOW_PATH):
+        * runtime/CommonSlowPaths.h:
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::hasProperty const):
+        (JSC::JSObject::hasEnumerableProperty const):
+        (JSC::JSObject::hasPropertyGeneric const): Deleted.
+        * runtime/JSObject.h:
+
 2020-12-15  Saam Barati  <[email protected]>
 
         Switch to using a linked list for the TDZ environment instead of a Vector

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.rb (270873 => 270874)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.rb	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.rb	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1125,7 +1125,7 @@
         base: VirtualRegister,
     }
 
-op :has_indexed_property,
+op :has_enumerable_indexed_property,
     args: {
         dst: VirtualRegister,
         base: VirtualRegister,
@@ -1135,7 +1135,7 @@
         arrayProfile: ArrayProfile,
     }
 
-op :has_structure_property,
+op :has_enumerable_structure_property,
     args: {
         dst: VirtualRegister,
         base: VirtualRegister,
@@ -1159,7 +1159,7 @@
         enumerator: VirtualRegister,
     }
 
-op :has_generic_property,
+op :has_enumerable_property,
     args: {
         dst: VirtualRegister,
         base: VirtualRegister,

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -221,8 +221,9 @@
     USES(OpGetFromArguments, arguments)
     USES(OpNewArrayBuffer, immutableButterfly)
 
-    USES(OpHasGenericProperty, base, property)
-    USES(OpHasIndexedProperty, base, property)
+    USES(OpHasEnumerableIndexedProperty, base, property)
+    USES(OpHasEnumerableStructureProperty, base, property, enumerator)
+    USES(OpHasEnumerableProperty, base, property)
     USES(OpEnumeratorStructurePname, enumerator, index)
     USES(OpEnumeratorGenericPname, enumerator, index)
     USES(OpGetByVal, base, property)
@@ -260,7 +261,6 @@
 
     USES(OpGetByValWithThis, base, thisValue, property)
     USES(OpInstanceofCustom, value, constructor, hasInstanceValue)
-    USES(OpHasStructureProperty, base, property, enumerator)
     USES(OpHasOwnStructureProperty, base, property, enumerator)
     USES(OpInStructureProperty, base, property, enumerator)
 
@@ -420,11 +420,11 @@
     DEFS(OpArgumentCount, dst)
     DEFS(OpToIndexString, dst)
     DEFS(OpGetEnumerableLength, dst)
-    DEFS(OpHasIndexedProperty, dst)
-    DEFS(OpHasStructureProperty, dst)
+    DEFS(OpHasEnumerableIndexedProperty, dst)
+    DEFS(OpHasEnumerableStructureProperty, dst)
+    DEFS(OpHasEnumerableProperty, dst)
     DEFS(OpHasOwnStructureProperty, dst)
     DEFS(OpInStructureProperty, dst)
-    DEFS(OpHasGenericProperty, dst)
     DEFS(OpGetDirectPname, dst)
     DEFS(OpGetPropertyEnumerator, dst)
     DEFS(OpEnumeratorStructurePname, dst)

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -503,7 +503,7 @@
         OpcodeID opcodeID = instruction->opcodeID();
         m_bytecodeCost += opcodeLengths[opcodeID];
         switch (opcodeID) {
-        LINK(OpHasIndexedProperty)
+        LINK(OpHasEnumerableIndexedProperty)
 
         LINK(OpCallVarargs, profile)
         LINK(OpTailCallVarargs, profile)

Modified: trunk/Source/_javascript_Core/bytecode/Opcode.h (270873 => 270874)


--- trunk/Source/_javascript_Core/bytecode/Opcode.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -126,7 +126,7 @@
     macro(OpRshift) \
 
 #define FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(macro) \
-    macro(OpHasIndexedProperty) \
+    macro(OpHasEnumerableIndexedProperty) \
     macro(OpCallVarargs) \
     macro(OpTailCallVarargs) \
     macro(OpTailCallForwardArguments) \

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -4365,21 +4365,21 @@
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
+RegisterID* BytecodeGenerator::emitHasEnumerableIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
 {
-    OpHasGenericProperty::emit(this, dst, base, propertyName);
+    OpHasEnumerableIndexedProperty::emit(this, dst, base, propertyName);
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
+RegisterID* BytecodeGenerator::emitHasEnumerableStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator)
 {
-    OpHasIndexedProperty::emit(this, dst, base, propertyName);
+    OpHasEnumerableStructureProperty::emit(this, dst, base, propertyName, enumerator);
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator)
+RegisterID* BytecodeGenerator::emitHasEnumerableProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
 {
-    OpHasStructureProperty::emit(this, dst, base, propertyName, enumerator);
+    OpHasEnumerableProperty::emit(this, dst, base, propertyName);
     return dst;
 }
 

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (270873 => 270874)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -902,10 +902,10 @@
         void emitEnter();
         void emitCheckTraps();
 
-        RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
-        RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
+        RegisterID* emitHasEnumerableIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
+        RegisterID* emitHasEnumerableStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
+        RegisterID* emitHasEnumerableProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
         RegisterID* emitHasOwnStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
-        RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
         RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base);
         RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
         RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -3962,7 +3962,7 @@
 
         RefPtr<RegisterID> result = generator.emitEqualityOp<OpLess>(generator.newTemporary(), i.get(), length.get());
         generator.emitJumpIfFalse(result.get(), loopEnd.get());
-        generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
+        generator.emitHasEnumerableIndexedProperty(result.get(), base.get(), i.get());
         generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
 
         generator.emitToIndexString(propertyName.get(), i.get());
@@ -4003,7 +4003,7 @@
 
         RefPtr<RegisterID> result = generator.emitIsNull(generator.newTemporary(), propertyName.get());
         generator.emitJumpIfTrue(result.get(), loopEnd.get());
-        generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
+        generator.emitHasEnumerableStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
         generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
 
         this->emitLoopHeader(generator, propertyName.get());
@@ -4045,7 +4045,7 @@
         RefPtr<RegisterID> result = generator.emitIsNull(generator.newTemporary(), propertyName.get());
         generator.emitJumpIfTrue(result.get(), loopEnd.get());
 
-        generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
+        generator.emitHasEnumerableProperty(result.get(), base.get(), propertyName.get());
         generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
 
         this->emitLoopHeader(generator, propertyName.get());

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -4155,7 +4155,7 @@
         setNonCellTypeForNode(node, SpecInt32Only);
         break;
     }
-    case HasGenericProperty: {
+    case HasEnumerableProperty: {
         setNonCellTypeForNode(node, SpecBoolean);
         clobberWorld();
         break;
@@ -4162,12 +4162,13 @@
     }
     case InStructureProperty:
     case HasOwnStructureProperty:
-    case HasStructureProperty: {
+    case HasEnumerableStructureProperty: {
         setNonCellTypeForNode(node, SpecBoolean);
         clobberWorld();
         break;
     }
-    case HasIndexedProperty: {
+    case HasIndexedProperty:
+    case HasEnumerableIndexedProperty: {
         ArrayMode mode = node->arrayMode();
         switch (mode.type()) {
         case Array::Int32:

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -8139,21 +8139,21 @@
             NEXT_OPCODE(op_get_enumerable_length);
         }
 
-        case op_has_generic_property: {
-            auto bytecode = currentInstruction->as<OpHasGenericProperty>();
-            set(bytecode.m_dst, addToGraph(HasGenericProperty, get(bytecode.m_base), get(bytecode.m_property)));
-            NEXT_OPCODE(op_has_generic_property);
-        }
-
-        case op_has_structure_property: {
-            auto bytecode = currentInstruction->as<OpHasStructureProperty>();
-            set(bytecode.m_dst, addToGraph(HasStructureProperty,
+        case op_has_enumerable_structure_property: {
+            auto bytecode = currentInstruction->as<OpHasEnumerableStructureProperty>();
+            set(bytecode.m_dst, addToGraph(HasEnumerableStructureProperty,
                 get(bytecode.m_base),
                 get(bytecode.m_property),
                 get(bytecode.m_enumerator)));
-            NEXT_OPCODE(op_has_structure_property);
+            NEXT_OPCODE(op_has_enumerable_structure_property);
         }
 
+        case op_has_enumerable_property: {
+            auto bytecode = currentInstruction->as<OpHasEnumerableProperty>();
+            set(bytecode.m_dst, addToGraph(HasEnumerableProperty, get(bytecode.m_base), get(bytecode.m_property)));
+            NEXT_OPCODE(op_has_enumerable_property);
+        }
+
         case op_has_own_structure_property: {
             auto bytecode = currentInstruction->as<OpHasOwnStructureProperty>();
             set(bytecode.m_dst, addToGraph(HasOwnStructureProperty,
@@ -8172,8 +8172,8 @@
             NEXT_OPCODE(op_in_structure_property);
         }
 
-        case op_has_indexed_property: {
-            auto bytecode = currentInstruction->as<OpHasIndexedProperty>();
+        case op_has_enumerable_indexed_property: {
+            auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();
             Node* base = get(bytecode.m_base);
             ArrayMode arrayMode = getArrayMode(bytecode.metadata(codeBlock).m_arrayProfile, Array::Read);
             Node* property = get(bytecode.m_property);
@@ -8180,10 +8180,10 @@
             addVarArgChild(base);
             addVarArgChild(property);
             addVarArgChild(nullptr);
-            Node* hasIterableProperty = addToGraph(Node::VarArg, HasIndexedProperty, OpInfo(arrayMode.asWord()), OpInfo(static_cast<uint32_t>(PropertySlot::InternalMethodType::GetOwnProperty)));
+            Node* hasIterableProperty = addToGraph(Node::VarArg, HasEnumerableIndexedProperty, OpInfo(arrayMode.asWord()));
             m_exitOK = false; // HasIndexedProperty must be treated as if it clobbers exit state, since FixupPhase may make it generic.
             set(bytecode.m_dst, hasIterableProperty);
-            NEXT_OPCODE(op_has_indexed_property);
+            NEXT_OPCODE(op_has_enumerable_indexed_property);
         }
 
         case op_get_direct_pname: {

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -253,11 +253,11 @@
     case op_get_scope:
     case op_get_from_scope:
     case op_get_enumerable_length:
-    case op_has_generic_property:
-    case op_has_structure_property:
+    case op_has_enumerable_indexed_property:
+    case op_has_enumerable_structure_property:
+    case op_has_enumerable_property:
     case op_has_own_structure_property:
     case op_in_structure_property:
-    case op_has_indexed_property:
     case op_get_direct_pname:
     case op_get_property_enumerator:
     case op_enumerator_structure_pname:

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -164,6 +164,7 @@
         case ArrayPop:
         case ArrayIndexOf:
         case HasIndexedProperty:
+        case HasEnumerableIndexedProperty:
         case AtomicsAdd:
         case AtomicsAnd:
         case AtomicsCompareExchange:
@@ -348,7 +349,8 @@
         return;
     }
 
-    case HasIndexedProperty: {
+    case HasIndexedProperty:
+    case HasEnumerableIndexedProperty: {
         read(JSObject_butterfly);
         ArrayMode mode = node->arrayMode();
         switch (mode.type()) {
@@ -705,8 +707,8 @@
     case ResolveScopeForHoistingFuncDeclInEval:
     case ResolveScope:
     case ToObject:
-    case HasGenericProperty:
-    case HasStructureProperty:
+    case HasEnumerableStructureProperty:
+    case HasEnumerableProperty:
     case HasOwnStructureProperty:
     case InStructureProperty:
     case GetPropertyEnumerator:

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -295,10 +295,11 @@
     case GetDirectPname:
     case GetDynamicVar:
     case GetMapBucket:
-    case HasGenericProperty:
     case HasIndexedProperty:
+    case HasEnumerableIndexedProperty:
+    case HasEnumerableStructureProperty:
+    case HasEnumerableProperty:
     case HasOwnProperty:
-    case HasStructureProperty:
     case HasOwnStructureProperty:
     case InStructureProperty:
     case InById:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -2204,11 +2204,11 @@
             fixEdge<CellUse>(node->child1());
             break;
         }
-        case HasGenericProperty: {
+        case HasEnumerableProperty: {
             fixEdge<CellUse>(node->child2());
             break;
         }
-        case HasStructureProperty: {
+        case HasEnumerableStructureProperty: {
             fixEdge<StringUse>(node->child2());
             fixEdge<KnownCellUse>(node->child3());
             break;
@@ -2220,7 +2220,8 @@
             fixEdge<KnownCellUse>(node->child3());
             break;
         }
-        case HasIndexedProperty: {
+        case HasIndexedProperty:
+        case HasEnumerableIndexedProperty: {
             node->setArrayMode(
                 node->arrayMode().refine(
                     m_graph, node,
@@ -3988,7 +3989,6 @@
                 m_graph.varArgChild(node, 0)->prediction(),
                 m_graph.varArgChild(node, 1)->prediction(),
                 SpecNone));
-        node->setInternalMethodType(PropertySlot::InternalMethodType::HasProperty);
 
         blessArrayOperation(m_graph.varArgChild(node, 0), m_graph.varArgChild(node, 1), m_graph.varArgChild(node, 2));
         auto arrayMode = node->arrayMode();

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -2214,6 +2214,7 @@
         case ArrayPop:
         case ArrayIndexOf:
         case HasIndexedProperty:
+        case HasEnumerableIndexedProperty:
         case AtomicsAdd:
         case AtomicsAnd:
         case AtomicsCompareExchange:
@@ -3003,23 +3004,6 @@
         return nullptr;
     }
 
-    bool hasInternalMethodType() const
-    {
-        return op() == HasIndexedProperty;
-    }
-
-    PropertySlot::InternalMethodType internalMethodType() const
-    {
-        ASSERT(hasInternalMethodType());
-        return static_cast<PropertySlot::InternalMethodType>(m_opInfo2.as<uint32_t>());
-    }
-
-    void setInternalMethodType(PropertySlot::InternalMethodType type)
-    {
-        ASSERT(hasInternalMethodType());
-        m_opInfo2 = static_cast<uint32_t>(type);
-    }
-
     Node* replacement() const
     {
         return m_misc.replacement;

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -498,10 +498,11 @@
     macro(GetEnumerableLength, NodeMustGenerate | NodeResultJS) \
     /* Must generate because of Proxies on the prototype chain */ \
     macro(HasIndexedProperty, NodeMustGenerate | NodeResultBoolean | NodeHasVarArgs) \
-    macro(HasStructureProperty, NodeResultBoolean) \
+    macro(HasEnumerableIndexedProperty, NodeMustGenerate | NodeResultBoolean | NodeHasVarArgs) \
+    macro(HasEnumerableStructureProperty, NodeResultBoolean) \
+    macro(HasEnumerableProperty, NodeResultBoolean) \
     macro(HasOwnStructureProperty, NodeResultBoolean | NodeMustGenerate) \
     macro(InStructureProperty, NodeMustGenerate | NodeResultBoolean) \
-    macro(HasGenericProperty, NodeResultBoolean) \
     macro(GetDirectPname, NodeMustGenerate | NodeHasVarArgs | NodeResultJS) \
     macro(GetPropertyEnumerator, NodeMustGenerate | NodeResultJS) \
     macro(GetEnumeratorStructurePname, NodeMustGenerate | NodeResultJS) \

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -2258,7 +2258,7 @@
     return result;
 }
 
-JSC_DEFINE_JIT_OPERATION(operationHasGenericProperty, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, JSCell* property))
+JSC_DEFINE_JIT_OPERATION(operationHasEnumerableProperty, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, JSCell* property))
 {
     VM& vm = globalObject->vm();
     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
@@ -2275,7 +2275,7 @@
         return JSValue::encode(JSValue());
     auto propertyName = asString(property)->toIdentifier(globalObject);
     RETURN_IF_EXCEPTION(scope, { });
-    RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(base->hasPropertyGeneric(globalObject, propertyName, PropertySlot::InternalMethodType::GetOwnProperty))));
+    RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(base->hasEnumerableProperty(globalObject, propertyName))));
 }
 
 JSC_DEFINE_JIT_OPERATION(operationInStructureProperty, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, JSString* property))
@@ -2300,7 +2300,7 @@
     return JSValue::encode(jsBoolean(objectPrototypeHasOwnProperty(globalObject, base, propertyName)));
 }
 
-JSC_DEFINE_JIT_OPERATION(operationHasIndexedPropertyByInt, size_t, (JSGlobalObject* globalObject, JSCell* baseCell, int32_t subscript, int32_t internalMethodType))
+JSC_DEFINE_JIT_OPERATION(operationHasIndexedProperty, size_t, (JSGlobalObject* globalObject, JSCell* baseCell, int32_t subscript))
 {
     VM& vm = globalObject->vm();
     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
@@ -2308,11 +2308,24 @@
     JSObject* object = baseCell->toObject(globalObject);
     if (UNLIKELY(subscript < 0)) {
         // Go the slowest way possible because negative indices don't use indexed storage.
-        return object->hasPropertyGeneric(globalObject, Identifier::from(vm, subscript), static_cast<PropertySlot::InternalMethodType>(internalMethodType));
+        return object->hasProperty(globalObject, Identifier::from(vm, subscript));
     }
-    return object->hasPropertyGeneric(globalObject, subscript, static_cast<PropertySlot::InternalMethodType>(internalMethodType));
+    return object->hasProperty(globalObject, static_cast<unsigned>(subscript));
 }
 
+JSC_DEFINE_JIT_OPERATION(operationHasEnumerableIndexedProperty, size_t, (JSGlobalObject* globalObject, JSCell* baseCell, int32_t subscript))
+{
+    VM& vm = globalObject->vm();
+    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+    JSObject* object = baseCell->toObject(globalObject);
+    if (UNLIKELY(subscript < 0)) {
+        // Go the slowest way possible because negative indices don't use indexed storage.
+        return object->hasEnumerableProperty(globalObject, Identifier::from(vm, subscript));
+    }
+    return object->hasEnumerableProperty(globalObject, subscript);
+}
+
 JSC_DEFINE_JIT_OPERATION(operationGetPropertyEnumerator, JSCell*, (JSGlobalObject* globalObject, EncodedJSValue encodedBase))
 {
     VM& vm = globalObject->vm();

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -99,10 +99,11 @@
 JSC_DECLARE_JIT_OPERATION(operationGetByValWithThis, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue));
 JSC_DECLARE_JIT_OPERATION(operationGetPrototypeOf, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
 JSC_DECLARE_JIT_OPERATION(operationGetPrototypeOfObject, EncodedJSValue, (JSGlobalObject*, JSObject*));
-JSC_DECLARE_JIT_OPERATION(operationHasGenericProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, JSCell*));
+JSC_DECLARE_JIT_OPERATION(operationHasIndexedProperty, size_t, (JSGlobalObject*, JSCell*, int32_t));
+JSC_DECLARE_JIT_OPERATION(operationHasEnumerableIndexedProperty, size_t, (JSGlobalObject*, JSCell*, int32_t));
+JSC_DECLARE_JIT_OPERATION(operationHasEnumerableProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, JSCell*));
 JSC_DECLARE_JIT_OPERATION(operationHasOwnStructureProperty, EncodedJSValue, (JSGlobalObject*, JSCell*, JSString*));
 JSC_DECLARE_JIT_OPERATION(operationInStructureProperty, EncodedJSValue, (JSGlobalObject*, JSCell*, JSString*));
-JSC_DECLARE_JIT_OPERATION(operationHasIndexedPropertyByInt, size_t, (JSGlobalObject*, JSCell*, int32_t, int32_t));
 JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumerator, JSCell*, (JSGlobalObject*, EncodedJSValue));
 JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumeratorCell, JSCell*, (JSGlobalObject*, JSCell*));
 JSC_DECLARE_JIT_OPERATION(operationToIndexString, JSCell*, (JSGlobalObject*, int32_t));

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1212,11 +1212,12 @@
             setPrediction(SpecInt32Only);
             break;
         }
-        case HasGenericProperty:
-        case HasStructureProperty:
         case HasOwnStructureProperty:
         case InStructureProperty:
-        case HasIndexedProperty: {
+        case HasIndexedProperty:
+        case HasEnumerableIndexedProperty:
+        case HasEnumerableStructureProperty:
+        case HasEnumerableProperty: {
             setPrediction(SpecBoolean);
             break;
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGSSALoweringPhase.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGSSALoweringPhase.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGSSALoweringPhase.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -82,6 +82,7 @@
         }
 
         case HasIndexedProperty:
+        case HasEnumerableIndexedProperty:
             lowerBoundsCheck(m_graph.child(m_node, 0), m_graph.child(m_node, 1), m_graph.child(m_node, 2));
             break;
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -292,6 +292,7 @@
     case BooleanToNumber:
     case FiatInt52:
     case HasIndexedProperty:
+    case HasEnumerableIndexedProperty:
     case GetEnumeratorStructurePname:
     case GetEnumeratorGenericPname:
     case ToIndexString:
@@ -628,8 +629,8 @@
     case MultiPutByOffset:
     case MultiDeleteByOffset:
     case GetEnumerableLength:
-    case HasGenericProperty:
-    case HasStructureProperty:
+    case HasEnumerableStructureProperty:
+    case HasEnumerableProperty:
     case HasOwnStructureProperty:
     case InStructureProperty:
     case GetDirectPname:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -12838,7 +12838,7 @@
     strictInt32Result(resultGPR, node);
 }
 
-void SpeculativeJIT::compileHasGenericProperty(Node* node)
+void SpeculativeJIT::compileHasEnumerableProperty(Node* node)
 {
     JSValueOperand base(this, node->child1());
     SpeculateCellOperand property(this, node->child2());
@@ -12849,7 +12849,7 @@
     flushRegisters();
     JSValueRegsFlushedCallResult result(this);
     JSValueRegs resultRegs = result.regs();
-    callOperation(operationHasGenericProperty, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyGPR);
+    callOperation(operationHasEnumerableProperty, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyGPR);
     m_jit.exceptionCheck();
     blessedBooleanResult(resultRegs.payloadGPR(), node);
 }
@@ -12989,7 +12989,7 @@
     blessedBooleanResult(tempGPR, node);
 }
 
-void SpeculativeJIT::compileHasStructureProperty(Node* node)
+void SpeculativeJIT::compileHasEnumerableStructureProperty(Node* node)
 {
     JSValueOperand base(this, node->child1());
     SpeculateCellOperand property(this, node->child2());
@@ -13011,7 +13011,7 @@
 
     moveTrueTo(resultRegs.payloadGPR());
 
-    addSlowPathGenerator(slowPathCall(wrongStructure, this, operationHasGenericProperty, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyGPR));
+    addSlowPathGenerator(slowPathCall(wrongStructure, this, operationHasEnumerableProperty, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyGPR));
     blessedBooleanResult(resultRegs.payloadGPR(), node);
 }
 
@@ -14267,7 +14267,7 @@
         sizeGPR, storageGPR));
 }
 
-void SpeculativeJIT::compileHasIndexedProperty(Node* node)
+void SpeculativeJIT::compileHasIndexedProperty(Node* node, S_JITOperation_GCZ slowPathOperation)
 {
     SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
     SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
@@ -14383,7 +14383,7 @@
     }
     }
 
-    addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedPropertyByInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, indexGPR, static_cast<int32_t>(node->internalMethodType())));
+    addSlowPathGenerator(slowPathCall(slowCases, this, slowPathOperation, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, indexGPR));
 
     unblessedBooleanResult(resultGPR, node);
 }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1446,13 +1446,13 @@
     void compileThrow(Node*);
     void compileThrowStaticError(Node*);
     void compileGetEnumerableLength(Node*);
-    void compileHasGenericProperty(Node*);
+    void compileHasEnumerableStructureProperty(Node*);
+    void compileHasEnumerableProperty(Node*);
     void compileToIndexString(Node*);
     void compilePutByIdFlush(Node*);
     void compilePutById(Node*);
     void compilePutByIdDirect(Node*);
     void compilePutByIdWithThis(Node*);
-    void compileHasStructureProperty(Node*);
     template <typename Function>
     void compileHasOwnStructurePropertyImpl(Node*, Function);
     void compileHasOwnStructureProperty(Node*);
@@ -1488,7 +1488,7 @@
     void compileCallNumberConstructor(Node*);
     void compileLogShadowChickenPrologue(Node*);
     void compileLogShadowChickenTail(Node*);
-    void compileHasIndexedProperty(Node*);
+    void compileHasIndexedProperty(Node*, S_JITOperation_GCZ);
     void compileExtractCatchLocal(Node*);
     void compileClearCatchLocals(Node*);
     void compileProfileType(Node*);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -4073,12 +4073,12 @@
         compileGetEnumerableLength(node);
         break;
     }
-    case HasGenericProperty: {
-        compileHasGenericProperty(node);
+    case HasEnumerableStructureProperty: {
+        compileHasEnumerableStructureProperty(node);
         break;
     }
-    case HasStructureProperty: {
-        compileHasStructureProperty(node);
+    case HasEnumerableProperty: {
+        compileHasEnumerableProperty(node);
         break;
     }
     case HasOwnStructureProperty: {
@@ -4090,9 +4090,13 @@
         break;
     }
     case HasIndexedProperty: {
-        compileHasIndexedProperty(node);
+        compileHasIndexedProperty(node, operationHasIndexedProperty);
         break;
     }
+    case HasEnumerableIndexedProperty: {
+        compileHasIndexedProperty(node, operationHasEnumerableIndexedProperty);
+        break;
+    }
     case GetDirectPname: {
         compileGetDirectPname(node);
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -5120,12 +5120,12 @@
         compileGetEnumerableLength(node);
         break;
     }
-    case HasGenericProperty: {
-        compileHasGenericProperty(node);
+    case HasEnumerableStructureProperty: {
+        compileHasEnumerableStructureProperty(node);
         break;
     }
-    case HasStructureProperty: {
-        compileHasStructureProperty(node);
+    case HasEnumerableProperty: {
+        compileHasEnumerableProperty(node);
         break;
     }
     case HasOwnStructureProperty: {
@@ -5137,9 +5137,13 @@
         break;
     }
     case HasIndexedProperty: {
-        compileHasIndexedProperty(node);
+        compileHasIndexedProperty(node, operationHasIndexedProperty);
         break;
     }
+    case HasEnumerableIndexedProperty: {
+        compileHasIndexedProperty(node, operationHasEnumerableIndexedProperty);
+        break;
+    }
     case GetDirectPname: {
         compileGetDirectPname(node);
         break;

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -280,11 +280,12 @@
     case DoubleConstant:
     case Int52Constant:
     case BooleanToNumber:
-    case HasGenericProperty:
-    case HasStructureProperty:
+    case HasIndexedProperty:
+    case HasEnumerableIndexedProperty:
+    case HasEnumerableStructureProperty:
+    case HasEnumerableProperty:
     case HasOwnStructureProperty:
     case InStructureProperty:
-    case HasIndexedProperty:
     case GetDirectPname:
     case GetEnumerableLength:
     case GetIndexedPropertyStorage:

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1500,14 +1500,17 @@
             compileStoreBarrier();
             break;
         case HasIndexedProperty:
-            compileHasIndexedProperty();
+            compileHasIndexedProperty(operationHasIndexedProperty);
             break;
-        case HasGenericProperty:
-            compileHasGenericProperty();
+        case HasEnumerableIndexedProperty:
+            compileHasIndexedProperty(operationHasEnumerableIndexedProperty);
             break;
-        case HasStructureProperty:
-            compileHasStructureProperty();
+        case HasEnumerableStructureProperty:
+            compileHasEnumerableStructureProperty();
             break;
+        case HasEnumerableProperty:
+            compileHasEnumerableProperty();
+            break;
         case HasOwnStructureProperty:
             compileHasOwnStructureProperty();
             break;
@@ -12492,7 +12495,7 @@
         emitStoreBarrier(lowCell(m_node->child1()), m_node->op() == FencedStoreBarrier);
     }
     
-    void compileHasIndexedProperty()
+    void compileHasIndexedProperty(S_JITOperation_GCZ slowPathOperation)
     {
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
         LValue base = lowCell(m_graph.varArgChild(m_node, 0));
@@ -12503,7 +12506,6 @@
         case Array::Int32:
         case Array::Contiguous: {
             LValue storage = lowStorage(m_graph.varArgChild(m_node, 2));
-            LValue internalMethodType = m_out.constInt32(static_cast<int32_t>(m_node->internalMethodType()));
 
             IndexedAbstractHeap& heap = mode.type() == Array::Int32 ?
                 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties;
@@ -12534,7 +12536,7 @@
 
             m_out.appendTo(slowCase, continuation);
             ValueFromBlock slowResult = m_out.anchor(
-                m_out.notZero64(vmCall(Int64, operationHasIndexedPropertyByInt, weakPointer(globalObject), base, index, internalMethodType)));
+                m_out.notZero64(vmCall(Int64, slowPathOperation, weakPointer(globalObject), base, index)));
             m_out.jump(continuation);
 
             m_out.appendTo(continuation, lastNext);
@@ -12543,7 +12545,6 @@
         }
         case Array::Double: {
             LValue storage = lowStorage(m_graph.varArgChild(m_node, 2));
-            LValue internalMethodType = m_out.constInt32(static_cast<int32_t>(m_node->internalMethodType()));
             
             IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties;
             
@@ -12573,7 +12574,7 @@
             
             m_out.appendTo(slowCase, continuation);
             ValueFromBlock slowResult = m_out.anchor(
-                m_out.notZero64(vmCall(Int64, operationHasIndexedPropertyByInt, weakPointer(globalObject), base, index, internalMethodType)));
+                m_out.notZero64(vmCall(Int64, slowPathOperation, weakPointer(globalObject), base, index)));
             m_out.jump(continuation);
             
             m_out.appendTo(continuation, lastNext);
@@ -12583,7 +12584,6 @@
 
         case Array::ArrayStorage: {
             LValue storage = lowStorage(m_graph.varArgChild(m_node, 2));
-            LValue internalMethodType = m_out.constInt32(static_cast<int32_t>(m_node->internalMethodType()));
 
             LBasicBlock slowCase = m_out.newBlock();
             LBasicBlock continuation = m_out.newBlock();
@@ -12611,7 +12611,7 @@
 
             m_out.appendTo(slowCase, continuation);
             ValueFromBlock slowResult = m_out.anchor(
-                m_out.notZero64(vmCall(Int64, operationHasIndexedPropertyByInt, weakPointer(globalObject), base, index, internalMethodType)));
+                m_out.notZero64(vmCall(Int64, slowPathOperation, weakPointer(globalObject), base, index)));
             m_out.jump(continuation);
 
             m_out.appendTo(continuation, lastNext);
@@ -12620,19 +12620,18 @@
         }
 
         default: {
-            LValue internalMethodType = m_out.constInt32(static_cast<int32_t>(m_node->internalMethodType()));
-            setBoolean(m_out.notZero64(vmCall(Int64, operationHasIndexedPropertyByInt, weakPointer(globalObject), base, index, internalMethodType)));
+            setBoolean(m_out.notZero64(vmCall(Int64, slowPathOperation, weakPointer(globalObject), base, index)));
             break;
         }
         }
     }
 
-    void compileHasGenericProperty()
+    void compileHasEnumerableProperty()
     {
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
         LValue base = lowJSValue(m_node->child1());
         LValue property = lowCell(m_node->child2());
-        setJSValue(vmCall(Int64, operationHasGenericProperty, weakPointer(globalObject), base, property));
+        setJSValue(vmCall(Int64, operationHasEnumerableProperty, weakPointer(globalObject), base, property));
     }
 
     template <typename SlowPathCall>
@@ -12672,9 +12671,9 @@
         setBoolean(m_out.phi(Int32, correctStructureResult, slowPathResult));
     }
 
-    void compileHasStructureProperty()
+    void compileHasEnumerableStructureProperty()
     {
-        compileHasStructurePropertyImpl(lowJSValue(m_node->child1()), operationHasGenericProperty);
+        compileHasStructurePropertyImpl(lowJSValue(m_node->child1()), operationHasEnumerableProperty);
     }
 
     void compileHasOwnStructureProperty()

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -304,7 +304,7 @@
         DEFINE_SLOW_OP(new_array_buffer)
         DEFINE_SLOW_OP(spread)
         DEFINE_SLOW_OP(get_enumerable_length)
-        DEFINE_SLOW_OP(has_generic_property)
+        DEFINE_SLOW_OP(has_enumerable_property)
         DEFINE_SLOW_OP(get_property_enumerator)
         DEFINE_SLOW_OP(to_index_string)
         DEFINE_SLOW_OP(create_direct_arguments)
@@ -463,10 +463,10 @@
         DEFINE_OP(op_get_from_arguments)
         DEFINE_OP(op_put_to_arguments)
 
-        DEFINE_OP(op_has_structure_property)
+        DEFINE_OP(op_has_enumerable_indexed_property)
+        DEFINE_OP(op_has_enumerable_structure_property)
         DEFINE_OP(op_has_own_structure_property)
         DEFINE_OP(op_in_structure_property)
-        DEFINE_OP(op_has_indexed_property)
         DEFINE_OP(op_get_direct_pname)
         DEFINE_OP(op_enumerator_structure_pname)
         DEFINE_OP(op_enumerator_generic_pname)
@@ -592,7 +592,7 @@
         DEFINE_SLOWCASE_OP(op_del_by_val)
         DEFINE_SLOWCASE_OP(op_del_by_id)
         DEFINE_SLOWCASE_OP(op_sub)
-        DEFINE_SLOWCASE_OP(op_has_indexed_property)
+        DEFINE_SLOWCASE_OP(op_has_enumerable_indexed_property)
         DEFINE_SLOWCASE_OP(op_get_from_scope)
         DEFINE_SLOWCASE_OP(op_put_to_scope)
 
@@ -625,7 +625,7 @@
         DEFINE_SLOWCASE_SLOW_OP(nstricteq)
         DEFINE_SLOWCASE_SLOW_OP(get_direct_pname)
         DEFINE_SLOWCASE_SLOW_OP(get_prototype_of)
-        DEFINE_SLOWCASE_SLOW_OP(has_structure_property)
+        DEFINE_SLOWCASE_SLOW_OP(has_enumerable_structure_property)
         DEFINE_SLOWCASE_SLOW_OP(has_own_structure_property)
         DEFINE_SLOWCASE_SLOW_OP(in_structure_property)
         DEFINE_SLOWCASE_SLOW_OP(resolve_scope)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (270873 => 270874)


--- trunk/Source/_javascript_Core/jit/JIT.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -665,10 +665,10 @@
         void emit_op_urshift(const Instruction*);
         template <typename OpCodeType>
         void emit_op_has_structure_propertyImpl(const Instruction*);
-        void emit_op_has_structure_property(const Instruction*);
+        void emit_op_has_enumerable_indexed_property(const Instruction*);
+        void emit_op_has_enumerable_structure_property(const Instruction*);
         void emit_op_has_own_structure_property(const Instruction*);
         void emit_op_in_structure_property(const Instruction*);
-        void emit_op_has_indexed_property(const Instruction*);
         void emit_op_get_direct_pname(const Instruction*);
         void emit_op_enumerator_structure_pname(const Instruction*);
         void emit_op_enumerator_generic_pname(const Instruction*);
@@ -723,7 +723,7 @@
         void emitSlow_op_put_by_val(const Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_put_private_name(const Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_sub(const Instruction*, Vector<SlowCaseEntry>::iterator&);
-        void emitSlow_op_has_indexed_property(const Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_has_enumerable_indexed_property(const Instruction*, Vector<SlowCaseEntry>::iterator&);
 
         void emit_op_resolve_scope(const Instruction*);
         void emit_op_get_from_scope(const Instruction*);

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1392,9 +1392,9 @@
     emitPutVirtualRegister(dst);
 }
 
-void JIT::emit_op_has_structure_property(const Instruction* currentInstruction)
+void JIT::emit_op_has_enumerable_structure_property(const Instruction* currentInstruction)
 {
-    emit_op_has_structure_propertyImpl<OpHasStructureProperty>(currentInstruction);
+    emit_op_has_structure_propertyImpl<OpHasEnumerableStructureProperty>(currentInstruction);
 }
 
 void JIT::emit_op_has_own_structure_property(const Instruction* currentInstruction)
@@ -1434,9 +1434,9 @@
     MacroAssembler::repatchCall(CodeLocationCall<NoPtrTag>(MacroAssemblerCodePtr<NoPtrTag>(returnAddress)), FunctionPtr<OperationPtrTag>(operationHasIndexedPropertyGeneric));
 }
 
-void JIT::emit_op_has_indexed_property(const Instruction* currentInstruction)
+void JIT::emit_op_has_enumerable_indexed_property(const Instruction* currentInstruction)
 {
-    auto bytecode = currentInstruction->as<OpHasIndexedProperty>();
+    auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();
     auto& metadata = bytecode.metadata(m_codeBlock);
     VirtualRegister dst = bytecode.m_dst;
     VirtualRegister base = bytecode.m_base;
@@ -1481,11 +1481,11 @@
     m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeIndex, PatchableJump(), badType, mode, profile, done, nextHotPath));
 }
 
-void JIT::emitSlow_op_has_indexed_property(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+void JIT::emitSlow_op_has_enumerable_indexed_property(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     linkAllSlowCases(iter);
 
-    auto bytecode = currentInstruction->as<OpHasIndexedProperty>();
+    auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();
     VirtualRegister dst = bytecode.m_dst;
     VirtualRegister base = bytecode.m_base;
     VirtualRegister property = bytecode.m_property;

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1151,9 +1151,9 @@
     emitStoreBool(dst, regT0);
 }
 
-void JIT::emit_op_has_structure_property(const Instruction* currentInstruction)
+void JIT::emit_op_has_enumerable_structure_property(const Instruction* currentInstruction)
 {
-    emit_op_has_structure_propertyImpl<OpHasStructureProperty>(currentInstruction);
+    emit_op_has_structure_propertyImpl<OpHasEnumerableStructureProperty>(currentInstruction);
 }
 
 void JIT::emit_op_has_own_structure_property(const Instruction* currentInstruction)
@@ -1193,9 +1193,9 @@
     MacroAssembler::repatchCall(CodeLocationCall<NoPtrTag>(MacroAssemblerCodePtr<NoPtrTag>(returnAddress)), FunctionPtr<OperationPtrTag>(operationHasIndexedPropertyGeneric));
 }
 
-void JIT::emit_op_has_indexed_property(const Instruction* currentInstruction)
+void JIT::emit_op_has_enumerable_indexed_property(const Instruction* currentInstruction)
 {
-    auto bytecode = currentInstruction->as<OpHasIndexedProperty>();
+    auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();
     auto& metadata = bytecode.metadata(m_codeBlock);
     VirtualRegister dst = bytecode.m_dst;
     VirtualRegister base = bytecode.m_base;
@@ -1240,11 +1240,11 @@
     m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeIndex, PatchableJump(), badType, mode, profile, done, nextHotPath));
 }
 
-void JIT::emitSlow_op_has_indexed_property(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+void JIT::emitSlow_op_has_enumerable_indexed_property(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     linkAllSlowCases(iter);
 
-    auto bytecode = currentInstruction->as<OpHasIndexedProperty>();
+    auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();
     VirtualRegister dst = bytecode.m_dst;
     VirtualRegister base = bytecode.m_base;
     VirtualRegister property = bytecode.m_property;

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -2445,7 +2445,7 @@
 
     if (!CommonSlowPaths::canAccessArgumentIndexQuickly(*object, index))
         byValInfo->arrayProfile->setOutOfBounds();
-    return JSValue::encode(jsBoolean(object->hasPropertyGeneric(globalObject, index, PropertySlot::InternalMethodType::GetOwnProperty)));
+    return JSValue::encode(jsBoolean(object->hasEnumerableProperty(globalObject, index)));
 }
     
 JSC_DEFINE_JIT_OPERATION(operationHasIndexedPropertyGeneric, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo))
@@ -2466,7 +2466,7 @@
 
     if (!CommonSlowPaths::canAccessArgumentIndexQuickly(*object, index))
         byValInfo->arrayProfile->setOutOfBounds();
-    return JSValue::encode(jsBoolean(object->hasPropertyGeneric(globalObject, index, PropertySlot::InternalMethodType::GetOwnProperty)));
+    return JSValue::encode(jsBoolean(object->hasEnumerableProperty(globalObject, index)));
 }
     
 static bool deleteById(JSGlobalObject* globalObject, VM& vm, DeletePropertySlot& slot, JSValue base, const Identifier& ident, ECMAMode ecmaMode)

Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (270873 => 270874)


--- trunk/Source/_javascript_Core/jit/JITOperations.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -138,6 +138,7 @@
 using C_JITOperation_TT = uintptr_t(JIT_OPERATION_ATTRIBUTES *)(StringImpl*, StringImpl*);
 using C_JITOperation_B_GJssJss = uintptr_t(JIT_OPERATION_ATTRIBUTES *)(JSGlobalObject*, JSString*, JSString*);
 using S_JITOperation_GC = size_t(JIT_OPERATION_ATTRIBUTES *)(JSGlobalObject*, JSCell*);
+using S_JITOperation_GCZ = size_t(JIT_OPERATION_ATTRIBUTES *)(JSGlobalObject*, JSCell*, int32_t);
 using S_JITOperation_GJJ = size_t(JIT_OPERATION_ATTRIBUTES *)(JSGlobalObject*, EncodedJSValue, EncodedJSValue);
 using V_JITOperation_GJJJ = void(JIT_OPERATION_ATTRIBUTES *)(JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
 using J_JITOperation_GSsiJJ = EncodedJSValue(JIT_OPERATION_ATTRIBUTES *)(JSGlobalObject*, StructureStubInfo*, EncodedJSValue, EncodedJSValue);

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (270873 => 270874)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1972,11 +1972,11 @@
 slowPathOp(get_property_enumerator)
 slowPathOp(greater)
 slowPathOp(greatereq)
-slowPathOp(has_generic_property)
-slowPathOp(has_indexed_property)
+slowPathOp(has_enumerable_indexed_property)
+slowPathOp(has_enumerable_property)
 
 if not JSVALUE64
-    slowPathOp(has_structure_property)
+    slowPathOp(has_enumerable_structure_property)
     slowPathOp(has_own_structure_property)
     slowPathOp(in_structure_property)
     slowPathOp(get_prototype_of)

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (270873 => 270874)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2020-12-16 00:33:34 UTC (rev 270874)
@@ -3041,8 +3041,8 @@
     dispatch()
 end
 
-llintOpWithReturn(op_has_structure_property, OpHasStructureProperty, macro (size, get, dispatch, return)
-    hasStructurePropertyImpl(size, get, dispatch,  return, _slow_path_has_structure_property)
+llintOpWithReturn(op_has_enumerable_structure_property, OpHasEnumerableStructureProperty, macro (size, get, dispatch, return)
+    hasStructurePropertyImpl(size, get, dispatch,  return, _slow_path_has_enumerable_structure_property)
 end)
 
 llintOpWithReturn(op_has_own_structure_property, OpHasOwnStructureProperty, macro (size, get, dispatch, return)

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1040,10 +1040,10 @@
     RETURN(jsNumber(enumerator->indexedLength()));
 }
 
-JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_indexed_property)
+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_enumerable_indexed_property)
 {
     BEGIN();
-    auto bytecode = pc->as<OpHasIndexedProperty>();
+    auto bytecode = pc->as<OpHasEnumerableIndexedProperty>();
     auto& metadata = bytecode.metadata(codeBlock);
     JSObject* base = GET_C(bytecode.m_base).jsValue().toObject(globalObject);
     CHECK_EXCEPTION();
@@ -1050,13 +1050,13 @@
     JSValue property = GET(bytecode.m_property).jsValue();
     metadata.m_arrayProfile.observeStructure(base->structure(vm));
     ASSERT(property.isUInt32AsAnyInt());
-    RETURN(jsBoolean(base->hasPropertyGeneric(globalObject, property.asUInt32AsAnyInt(), PropertySlot::InternalMethodType::GetOwnProperty)));
+    RETURN(jsBoolean(base->hasEnumerableProperty(globalObject, property.asUInt32AsAnyInt())));
 }
 
-JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_structure_property)
+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_enumerable_structure_property)
 {
     BEGIN();
-    auto bytecode = pc->as<OpHasStructureProperty>();
+    auto bytecode = pc->as<OpHasEnumerableStructureProperty>();
     JSObject* base = GET_C(bytecode.m_base).jsValue().toObject(globalObject);
     CHECK_EXCEPTION();
     JSValue property = GET(bytecode.m_property).jsValue();
@@ -1069,7 +1069,7 @@
     JSString* string = asString(property);
     auto propertyName = string->toIdentifier(globalObject);
     CHECK_EXCEPTION();
-    RETURN(jsBoolean(base->hasPropertyGeneric(globalObject, propertyName, PropertySlot::InternalMethodType::GetOwnProperty)));
+    RETURN(jsBoolean(base->hasEnumerableProperty(globalObject, propertyName)));
 }
 
 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_own_structure_property)
@@ -1108,10 +1108,10 @@
     RETURN(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, asString(property))));
 }
 
-JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_generic_property)
+JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_enumerable_property)
 {
     BEGIN();
-    auto bytecode = pc->as<OpHasGenericProperty>();
+    auto bytecode = pc->as<OpHasEnumerableProperty>();
     JSObject* base = GET_C(bytecode.m_base).jsValue().toObject(globalObject);
     CHECK_EXCEPTION();
     JSValue property = GET(bytecode.m_property).jsValue();
@@ -1119,7 +1119,7 @@
     JSString* string = asString(property);
     auto propertyName = string->toIdentifier(globalObject);
     CHECK_EXCEPTION();
-    RETURN(jsBoolean(base->hasPropertyGeneric(globalObject, propertyName, PropertySlot::InternalMethodType::GetOwnProperty)));
+    RETURN(jsBoolean(base->hasEnumerableProperty(globalObject, propertyName)));
 }
 
 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_get_direct_pname)

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h (270873 => 270874)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -259,11 +259,11 @@
 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_to_primitive);
 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_to_property_key);
 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_get_enumerable_length);
-JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_generic_property);
-JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_structure_property);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_enumerable_indexed_property);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_enumerable_structure_property);
+JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_enumerable_property);
 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_own_structure_property);
 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_in_structure_property);
-JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_indexed_property);
 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_get_direct_pname);
 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_get_property_enumerator);
 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_structure_pname);

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (270873 => 270874)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1987,16 +1987,17 @@
     structure->setHasGetterSetterPropertiesWithProtoCheck(propertyName == vm.propertyNames->underscoreProto);
 }
 
-// HasProperty(O, P) from Section 7.3.10 of the spec.
-// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-hasproperty
+// https://tc39.es/ecma262/#sec-hasproperty
 bool JSObject::hasProperty(JSGlobalObject* globalObject, PropertyName propertyName) const
 {
-    return hasPropertyGeneric(globalObject, propertyName, PropertySlot::InternalMethodType::HasProperty);
+    PropertySlot slot(this, PropertySlot::InternalMethodType::HasProperty);
+    return const_cast<JSObject*>(this)->getPropertySlot(globalObject, propertyName, slot);
 }
 
 bool JSObject::hasProperty(JSGlobalObject* globalObject, unsigned propertyName) const
 {
-    return hasPropertyGeneric(globalObject, propertyName, PropertySlot::InternalMethodType::HasProperty);
+    PropertySlot slot(this, PropertySlot::InternalMethodType::HasProperty);
+    return const_cast<JSObject*>(this)->getPropertySlot(globalObject, propertyName, slot);
 }
 
 bool JSObject::hasProperty(JSGlobalObject* globalObject, uint64_t propertyName) const
@@ -2007,16 +2008,24 @@
     return hasProperty(globalObject, Identifier::from(globalObject->vm(), propertyName));
 }
 
-bool JSObject::hasPropertyGeneric(JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot::InternalMethodType internalMethodType) const
+bool JSObject::hasEnumerableProperty(JSGlobalObject* globalObject, PropertyName propertyName) const
 {
-    PropertySlot slot(this, internalMethodType);
-    return const_cast<JSObject*>(this)->getPropertySlot(globalObject, propertyName, slot);
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    PropertySlot slot(this, PropertySlot::InternalMethodType::GetOwnProperty);
+    bool hasProperty = const_cast<JSObject*>(this)->getPropertySlot(globalObject, propertyName, slot);
+    RETURN_IF_EXCEPTION(scope, false);
+    return hasProperty && !(slot.attributes() & PropertyAttribute::DontEnum);
 }
 
-bool JSObject::hasPropertyGeneric(JSGlobalObject* globalObject, unsigned propertyName, PropertySlot::InternalMethodType internalMethodType) const
+bool JSObject::hasEnumerableProperty(JSGlobalObject* globalObject, unsigned propertyName) const
 {
-    PropertySlot slot(this, internalMethodType);
-    return const_cast<JSObject*>(this)->getPropertySlot(globalObject, propertyName, slot);
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    PropertySlot slot(this, PropertySlot::InternalMethodType::GetOwnProperty);
+    bool hasProperty = const_cast<JSObject*>(this)->getPropertySlot(globalObject, propertyName, slot);
+    RETURN_IF_EXCEPTION(scope, false);
+    return hasProperty && !(slot.attributes() & PropertyAttribute::DontEnum);
 }
 
 // ECMA 8.6.2.5
@@ -2371,6 +2380,8 @@
     return JSValue::encode(jsBoolean(JSObject::defaultHasInstance(globalObject, value, proto)));
 }
 
+// FIXME: Assert that properties returned by getOwnPropertyNames() are reported enumerable by getOwnPropertySlot().
+// https://bugs.webkit.org/show_bug.cgi?id=219926
 void JSObject::getPropertyNames(JSObject* object, JSGlobalObject* globalObject, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     VM& vm = globalObject->vm();

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (270873 => 270874)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2020-12-16 00:33:34 UTC (rev 270874)
@@ -655,8 +655,8 @@
     JS_EXPORT_PRIVATE bool hasProperty(JSGlobalObject*, PropertyName) const;
     JS_EXPORT_PRIVATE bool hasProperty(JSGlobalObject*, unsigned propertyName) const;
     bool hasProperty(JSGlobalObject*, uint64_t propertyName) const;
-    bool hasPropertyGeneric(JSGlobalObject*, PropertyName, PropertySlot::InternalMethodType) const;
-    bool hasPropertyGeneric(JSGlobalObject*, unsigned propertyName, PropertySlot::InternalMethodType) const;
+    bool hasEnumerableProperty(JSGlobalObject*, PropertyName) const;
+    bool hasEnumerableProperty(JSGlobalObject*, unsigned propertyName) const;
     bool hasOwnProperty(JSGlobalObject*, PropertyName, PropertySlot&) const;
     bool hasOwnProperty(JSGlobalObject*, PropertyName) const;
     bool hasOwnProperty(JSGlobalObject*, unsigned) const;

Modified: trunk/Source/WebCore/ChangeLog (270873 => 270874)


--- trunk/Source/WebCore/ChangeLog	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/WebCore/ChangeLog	2020-12-16 00:33:34 UTC (rev 270874)
@@ -1,3 +1,18 @@
+2020-12-15  Alexey Shvayka  <[email protected]>
+
+        Non-enumerable property fails to shadow inherited enumerable property from for-in
+        https://bugs.webkit.org/show_bug.cgi?id=38970
+
+        Reviewed by Keith Miller.
+
+        Report RuntimeArray indices as [[Enumerable]].
+
+        Test: platform/mac/fast/dom/wrapper-classes-objc.html
+
+        * bridge/runtime_array.cpp:
+        (JSC::RuntimeArray::getOwnPropertySlot):
+        (JSC::RuntimeArray::getOwnPropertySlotByIndex):
+
 2020-12-15  Jer Noble  <[email protected]>
 
         [Cocoa] Adopt -externalContentProtectionStatus

Modified: trunk/Source/WebCore/bridge/runtime_array.cpp (270873 => 270874)


--- trunk/Source/WebCore/bridge/runtime_array.cpp	2020-12-16 00:06:21 UTC (rev 270873)
+++ trunk/Source/WebCore/bridge/runtime_array.cpp	2020-12-16 00:33:34 UTC (rev 270874)
@@ -100,7 +100,7 @@
     
     Optional<uint32_t> index = parseIndex(propertyName);
     if (index && index.value() < thisObject->getLength()) {
-        slot.setValue(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::DontEnum,
+        slot.setValue(thisObject, static_cast<unsigned>(PropertyAttribute::DontDelete),
             thisObject->getConcreteArray()->valueAt(lexicalGlobalObject, index.value()));
         return true;
     }
@@ -112,7 +112,7 @@
 {
     RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
     if (index < thisObject->getLength()) {
-        slot.setValue(thisObject, PropertyAttribute::DontDelete | PropertyAttribute::DontEnum,
+        slot.setValue(thisObject, static_cast<unsigned>(PropertyAttribute::DontDelete),
             thisObject->getConcreteArray()->valueAt(lexicalGlobalObject, index));
         return true;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to