[ES6] Add DFG/FTL support for accessor put operations
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Oct 2015 18:05:57 +0000 (18:05 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Oct 2015 18:05:57 +0000 (18:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=148860

Reviewed by Geoffrey Garen.

This patch introduces accessor defining ops into DFG and FTL.
The following DFG nodes are introduced.

    op_put_getter_by_id  => PutGetterById
    op_put_setter_by_id  => PutSetterById
    op_put_getter_setter => PutGetterSetterById
    op_put_getter_by_val => PutGetterByVal
    op_put_setter_by_val => PutSetterByVal

These DFG nodes just call operations. But it does not prevent compiling in DFG/FTL.

To use operations defined for baseline JIT, we clean up existing operations.
And reuse these operations in DFG and FTL.

* 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):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasIdentifier):
(JSC::DFG::Node::hasAccessorAttributes):
(JSC::DFG::Node::accessorAttributes):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compilePutAccessorById):
(JSC::DFG::SpeculativeJIT::compilePutGetterSetterById):
(JSC::DFG::SpeculativeJIT::compilePutAccessorByVal):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLIntrinsicRepository.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
(JSC::FTL::DFG::LowerDFGToLLVM::compilePutAccessorById):
(JSC::FTL::DFG::LowerDFGToLLVM::compilePutGetterSetterById):
(JSC::FTL::DFG::LowerDFGToLLVM::compilePutAccessorByVal):
* jit/JIT.h:
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_put_getter_by_id):
(JSC::JIT::emit_op_put_setter_by_id):
(JSC::JIT::emit_op_put_getter_setter):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_put_getter_by_id):
(JSC::JIT::emit_op_put_setter_by_id):
(JSC::JIT::emit_op_put_getter_setter):
* tests/stress/dfg-put-accessors-by-id-class.js: Added.
(shouldBe):
(testAttribute):
(getter.Cocoa.prototype.get hello):
(getter.Cocoa):
(getter):
(setter.Cocoa):
(setter.Cocoa.prototype.set hello):
(setter):
(accessors.Cocoa):
(accessors.Cocoa.prototype.get hello):
(accessors.Cocoa.prototype.set hello):
(accessors):
* tests/stress/dfg-put-accessors-by-id.js: Added.
(shouldBe):
(testAttribute):
(getter.object.get hello):
(getter):
(setter.object.set hello):
(setter):
(accessors.object.get hello):
(accessors.object.set hello):
(accessors):
* tests/stress/dfg-put-getter-by-id-class.js: Added.
(shouldBe):
(testAttribute):
(getter.Cocoa):
(getter.Cocoa.prototype.get hello):
(getter.Cocoa.prototype.get name):
(getter):
* tests/stress/dfg-put-getter-by-id.js: Added.
(shouldBe):
(testAttribute):
(getter.object.get hello):
(getter):
* tests/stress/dfg-put-getter-by-val-class.js: Added.
(shouldBe):
(testAttribute):
(getter.Cocoa):
(getter.Cocoa.prototype.get name):
(getter):
* tests/stress/dfg-put-getter-by-val.js: Added.
(shouldBe):
(testAttribute):
(getter.object.get name):
(getter):
* tests/stress/dfg-put-setter-by-id-class.js: Added.
(shouldBe):
(testAttribute):
(getter.Cocoa):
(getter.Cocoa.prototype.set hello):
(getter.Cocoa.prototype.get name):
(getter):
* tests/stress/dfg-put-setter-by-id.js: Added.
(shouldBe):
(testAttribute):
(setter.object.set hello):
(setter):
* tests/stress/dfg-put-setter-by-val-class.js: Added.
(shouldBe):
(testAttribute):
(setter.Cocoa):
(setter.Cocoa.prototype.set name):
(setter):
* tests/stress/dfg-put-setter-by-val.js: Added.
(shouldBe):
(testAttribute):
(setter.object.set name):
(setter):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@191500 268f45cc-cd09-0410-ab3c-d52691b4dbfc

34 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.cpp
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITInlines.h
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jit/JITOperations.h
Source/JavaScriptCore/jit/JITPropertyAccess.cpp
Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
Source/JavaScriptCore/tests/stress/dfg-put-accessors-by-id-class.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/dfg-put-accessors-by-id.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/dfg-put-getter-by-id-class.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/dfg-put-getter-by-id.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/dfg-put-getter-by-val-class.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/dfg-put-getter-by-val.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/dfg-put-setter-by-id-class.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/dfg-put-setter-by-id.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/dfg-put-setter-by-val-class.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/dfg-put-setter-by-val.js [new file with mode: 0644]

index 046c177..7d16a65 100644 (file)
@@ -1,3 +1,146 @@
+2015-10-23  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Add DFG/FTL support for accessor put operations
+        https://bugs.webkit.org/show_bug.cgi?id=148860
+
+        Reviewed by Geoffrey Garen.
+
+        This patch introduces accessor defining ops into DFG and FTL.
+        The following DFG nodes are introduced.
+
+            op_put_getter_by_id  => PutGetterById
+            op_put_setter_by_id  => PutSetterById
+            op_put_getter_setter => PutGetterSetterById
+            op_put_getter_by_val => PutGetterByVal
+            op_put_setter_by_val => PutSetterByVal
+
+        These DFG nodes just call operations. But it does not prevent compiling in DFG/FTL.
+
+        To use operations defined for baseline JIT, we clean up existing operations.
+        And reuse these operations in DFG and FTL.
+
+        * 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):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasIdentifier):
+        (JSC::DFG::Node::hasAccessorAttributes):
+        (JSC::DFG::Node::accessorAttributes):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compilePutAccessorById):
+        (JSC::DFG::SpeculativeJIT::compilePutGetterSetterById):
+        (JSC::DFG::SpeculativeJIT::compilePutAccessorByVal):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLIntrinsicRepository.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compilePutAccessorById):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compilePutGetterSetterById):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compilePutAccessorByVal):
+        * jit/JIT.h:
+        * jit/JITInlines.h:
+        (JSC::JIT::callOperation):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_put_getter_by_id):
+        (JSC::JIT::emit_op_put_setter_by_id):
+        (JSC::JIT::emit_op_put_getter_setter):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emit_op_put_getter_by_id):
+        (JSC::JIT::emit_op_put_setter_by_id):
+        (JSC::JIT::emit_op_put_getter_setter):
+        * tests/stress/dfg-put-accessors-by-id-class.js: Added.
+        (shouldBe):
+        (testAttribute):
+        (getter.Cocoa.prototype.get hello):
+        (getter.Cocoa):
+        (getter):
+        (setter.Cocoa):
+        (setter.Cocoa.prototype.set hello):
+        (setter):
+        (accessors.Cocoa):
+        (accessors.Cocoa.prototype.get hello):
+        (accessors.Cocoa.prototype.set hello):
+        (accessors):
+        * tests/stress/dfg-put-accessors-by-id.js: Added.
+        (shouldBe):
+        (testAttribute):
+        (getter.object.get hello):
+        (getter):
+        (setter.object.set hello):
+        (setter):
+        (accessors.object.get hello):
+        (accessors.object.set hello):
+        (accessors):
+        * tests/stress/dfg-put-getter-by-id-class.js: Added.
+        (shouldBe):
+        (testAttribute):
+        (getter.Cocoa):
+        (getter.Cocoa.prototype.get hello):
+        (getter.Cocoa.prototype.get name):
+        (getter):
+        * tests/stress/dfg-put-getter-by-id.js: Added.
+        (shouldBe):
+        (testAttribute):
+        (getter.object.get hello):
+        (getter):
+        * tests/stress/dfg-put-getter-by-val-class.js: Added.
+        (shouldBe):
+        (testAttribute):
+        (getter.Cocoa):
+        (getter.Cocoa.prototype.get name):
+        (getter):
+        * tests/stress/dfg-put-getter-by-val.js: Added.
+        (shouldBe):
+        (testAttribute):
+        (getter.object.get name):
+        (getter):
+        * tests/stress/dfg-put-setter-by-id-class.js: Added.
+        (shouldBe):
+        (testAttribute):
+        (getter.Cocoa):
+        (getter.Cocoa.prototype.set hello):
+        (getter.Cocoa.prototype.get name):
+        (getter):
+        * tests/stress/dfg-put-setter-by-id.js: Added.
+        (shouldBe):
+        (testAttribute):
+        (setter.object.set hello):
+        (setter):
+        * tests/stress/dfg-put-setter-by-val-class.js: Added.
+        (shouldBe):
+        (testAttribute):
+        (setter.Cocoa):
+        (setter.Cocoa.prototype.set name):
+        (setter):
+        * tests/stress/dfg-put-setter-by-val.js: Added.
+        (shouldBe):
+        (testAttribute):
+        (setter.object.set name):
+        (setter):
+
 2015-10-22  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Remove unused Timeline GCEvent Record type
index f28cc7a..6868aa3 100644 (file)
@@ -2363,6 +2363,15 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         clobberWorld(node->origin.semantic, clobberLimit);
         break;
     }
+
+    case PutGetterById:
+    case PutSetterById:
+    case PutGetterSetterById:
+    case PutGetterByVal:
+    case PutSetterByVal: {
+        clobberWorld(node->origin.semantic, clobberLimit);
+        break;
+    }
         
     case In: {
         // FIXME: We can determine when the property definitely exists based on abstract
index 69f54f1..a7fcb2a 100644 (file)
@@ -3749,6 +3749,38 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             NEXT_OPCODE(op_put_by_id);
         }
 
+        case op_put_getter_by_id:
+        case op_put_setter_by_id: {
+            Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
+            unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
+            unsigned attributes = currentInstruction[3].u.operand;
+            Node* accessor = get(VirtualRegister(currentInstruction[4].u.operand));
+            NodeType op = (opcodeID == op_put_getter_by_id) ? PutGetterById : PutSetterById;
+            addToGraph(op, OpInfo(identifierNumber), OpInfo(attributes), base, accessor);
+            NEXT_OPCODE(op_put_getter_by_id);
+        }
+
+        case op_put_getter_setter: {
+            Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
+            unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
+            unsigned attributes = currentInstruction[3].u.operand;
+            Node* getter = get(VirtualRegister(currentInstruction[4].u.operand));
+            Node* setter = get(VirtualRegister(currentInstruction[5].u.operand));
+            addToGraph(PutGetterSetterById, OpInfo(identifierNumber), OpInfo(attributes), base, getter, setter);
+            NEXT_OPCODE(op_put_getter_setter);
+        }
+
+        case op_put_getter_by_val:
+        case op_put_setter_by_val: {
+            Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
+            Node* subscript = get(VirtualRegister(currentInstruction[2].u.operand));
+            unsigned attributes = currentInstruction[3].u.operand;
+            Node* accessor = get(VirtualRegister(currentInstruction[4].u.operand));
+            NodeType op = (opcodeID == op_put_getter_by_val) ? PutGetterByVal : PutSetterByVal;
+            addToGraph(op, OpInfo(attributes), base, subscript, accessor);
+            NEXT_OPCODE(op_put_getter_by_val);
+        }
+
         case op_profile_type: {
             Node* valueToProfile = get(VirtualRegister(currentInstruction[1].u.operand));
             addToGraph(ProfileType, OpInfo(currentInstruction[2].u.location), valueToProfile);
index dafe5e8..9788a48 100644 (file)
@@ -154,6 +154,11 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruc
     case op_get_by_id:
     case op_get_array_length:
     case op_put_by_id:
+    case op_put_getter_by_id:
+    case op_put_setter_by_id:
+    case op_put_getter_setter:
+    case op_put_getter_by_val:
+    case op_put_setter_by_val:
     case op_jmp:
     case op_jtrue:
     case op_jfalse:
index 6c85d59..6ff4456 100644 (file)
@@ -379,6 +379,11 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
     case PutById:
     case PutByIdFlush:
     case PutByIdDirect:
+    case PutGetterById:
+    case PutSetterById:
+    case PutGetterSetterById:
+    case PutGetterByVal:
+    case PutSetterByVal:
     case ArrayPush:
     case ArrayPop:
     case Call:
index 5c57e02..0e9e1d8 100644 (file)
@@ -95,6 +95,11 @@ bool doesGC(Graph& graph, Node* node)
     case PutById:
     case PutByIdFlush:
     case PutByIdDirect:
+    case PutGetterById:
+    case PutSetterById:
+    case PutGetterSetterById:
+    case PutGetterByVal:
+    case PutSetterByVal:
     case CheckStructure:
     case GetExecutable:
     case GetButterfly:
index eb6415b..491fbc1 100644 (file)
@@ -1057,6 +1057,25 @@ private:
             break;
         }
 
+        case PutGetterById:
+        case PutSetterById: {
+            fixEdge<KnownCellUse>(node->child1());
+            fixEdge<KnownCellUse>(node->child2());
+            break;
+        }
+
+        case PutGetterSetterById: {
+            fixEdge<KnownCellUse>(node->child1());
+            break;
+        }
+
+        case PutGetterByVal:
+        case PutSetterByVal: {
+            fixEdge<KnownCellUse>(node->child1());
+            fixEdge<KnownCellUse>(node->child3());
+            break;
+        }
+
         case GetExecutable: {
             fixEdge<FunctionUse>(node->child1());
             break;
index ac1a757..94adbe6 100644 (file)
@@ -853,6 +853,9 @@ struct Node {
         case PutById:
         case PutByIdFlush:
         case PutByIdDirect:
+        case PutGetterById:
+        case PutSetterById:
+        case PutGetterSetterById:
             return true;
         default:
             return false;
@@ -864,6 +867,37 @@ struct Node {
         ASSERT(hasIdentifier());
         return m_opInfo;
     }
+
+    bool hasAccessorAttributes()
+    {
+        switch (op()) {
+        case PutGetterById:
+        case PutSetterById:
+        case PutGetterSetterById:
+        case PutGetterByVal:
+        case PutSetterByVal:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    int32_t accessorAttributes()
+    {
+        ASSERT(hasAccessorAttributes());
+        switch (op()) {
+        case PutGetterById:
+        case PutSetterById:
+        case PutGetterSetterById:
+            return m_opInfo2;
+        case PutGetterByVal:
+        case PutSetterByVal:
+            return m_opInfo;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return 0;
+        }
+    }
     
     bool hasPromotedLocationDescriptor()
     {
index 1349a5d..c0498ae 100644 (file)
@@ -179,8 +179,13 @@ namespace JSC { namespace DFG {
     macro(GetById, NodeResultJS | NodeMustGenerate) \
     macro(GetByIdFlush, NodeResultJS | NodeMustGenerate) \
     macro(PutById, NodeMustGenerate) \
-    macro(PutByIdFlush, NodeMustGenerate | NodeMustGenerate) \
+    macro(PutByIdFlush, NodeMustGenerate) \
     macro(PutByIdDirect, NodeMustGenerate) \
+    macro(PutGetterById, NodeMustGenerate) \
+    macro(PutSetterById, NodeMustGenerate) \
+    macro(PutGetterSetterById, NodeMustGenerate) \
+    macro(PutGetterByVal, NodeMustGenerate) \
+    macro(PutSetterByVal, NodeMustGenerate) \
     macro(CheckStructure, NodeMustGenerate) \
     macro(GetExecutable, NodeResultJS) \
     macro(PutStructure, NodeMustGenerate) \
index a415075..d72da97 100644 (file)
@@ -651,6 +651,11 @@ private:
         case PutByIdDirect:
         case PutByOffset:
         case MultiPutByOffset:
+        case PutGetterById:
+        case PutSetterById:
+        case PutGetterSetterById:
+        case PutGetterByVal:
+        case PutSetterByVal:
         case DFG::Jump:
         case Branch:
         case Switch:
index 9e3580e..42abad0 100644 (file)
@@ -188,6 +188,11 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
     case PutById:
     case PutByIdFlush:
     case PutByIdDirect:
+    case PutGetterById:
+    case PutSetterById:
+    case PutGetterSetterById:
+    case PutGetterByVal:
+    case PutSetterByVal:
     case CheckStructure:
     case GetExecutable:
     case GetButterfly:
index eb2585d..f0bbbba 100755 (executable)
@@ -6741,6 +6741,61 @@ void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg scratch1, GPRReg scrat
     ownerIsRememberedOrInEden.link(&m_jit);
 }
 
+void SpeculativeJIT::compilePutAccessorById(Node* node)
+{
+    SpeculateCellOperand base(this, node->child1());
+    SpeculateCellOperand accessor(this, node->child2());
+
+    flushRegisters();
+    callOperation(node->op() == PutGetterById ? operationPutGetterById : operationPutSetterById, NoResult, base.gpr(), identifierUID(node->identifierNumber()), node->accessorAttributes(), accessor.gpr());
+    m_jit.exceptionCheck();
+
+    noResult(node);
+}
+
+void SpeculativeJIT::compilePutGetterSetterById(Node* node)
+{
+    SpeculateCellOperand base(this, node->child1());
+    JSValueOperand getter(this, node->child2());
+    JSValueOperand setter(this, node->child3());
+
+    flushRegisters();
+#if USE(JSVALUE64)
+    callOperation(operationPutGetterSetter, NoResult, base.gpr(), identifierUID(node->identifierNumber()), node->accessorAttributes(), getter.gpr(), setter.gpr());
+#else
+    // These JSValues may be JSUndefined OR JSFunction*.
+    // At that time,
+    // 1. If the JSValue is JSUndefined, its payload becomes nullptr.
+    // 2. If the JSValue is JSFunction*, its payload becomes JSFunction*.
+    // So extract payload and pass it to operationPutGetterSetter. This hack is used as the same way in baseline JIT.
+    JSValueRegs getterRegs = getter.jsValueRegs();
+    JSValueRegs setterRegs = setter.jsValueRegs();
+    callOperation(operationPutGetterSetter, NoResult, base.gpr(), identifierUID(node->identifierNumber()), node->accessorAttributes(), getterRegs.payloadGPR(), setterRegs.payloadGPR());
+#endif
+    m_jit.exceptionCheck();
+
+    noResult(node);
+}
+
+void SpeculativeJIT::compilePutAccessorByVal(Node* node)
+{
+    SpeculateCellOperand base(this, node->child1());
+    JSValueOperand subscript(this, node->child2());
+    SpeculateCellOperand accessor(this, node->child3());
+
+    flushRegisters();
+    auto operation = node->op() == PutGetterByVal ? operationPutGetterByVal : operationPutSetterByVal;
+#if USE(JSVALUE64)
+    callOperation(operation, NoResult, base.gpr(), subscript.gpr(), node->accessorAttributes(), accessor.gpr());
+#else
+    JSValueRegs subscriptRegs = subscript.jsValueRegs();
+    callOperation(operation, NoResult, base.gpr(), subscriptRegs.tagGPR(), subscriptRegs.payloadGPR(), node->accessorAttributes(), accessor.gpr());
+#endif
+    m_jit.exceptionCheck();
+
+    noResult(node);
+}
+
 } } // namespace JSC::DFG
 
 #endif
index 4588b5c..dae0c69 100755 (executable)
@@ -1155,35 +1155,16 @@ public:
         return appendCallSetResult(operation, result);
     }
 
-    template<typename FunctionType>
-    JITCompiler::Call callOperation(FunctionType operation, NoResultTag)
-    {
-        return callOperation(operation);
-    }
-    template<typename FunctionType, typename ArgumentType1>
-    JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1)
-    {
-        return callOperation(operation, arg1);
-    }
-    template<typename FunctionType, typename ArgumentType1, typename ArgumentType2>
-    JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2)
+    JITCompiler::Call callOperation(V_JITOperation_ECIZC operation, GPRReg regOp1, UniquedStringImpl* identOp2, int32_t op3, GPRReg regOp4)
     {
-        return callOperation(operation, arg1, arg2);
-    }
-    template<typename FunctionType, typename ArgumentType1, typename ArgumentType2, typename ArgumentType3>
-    JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2, ArgumentType3 arg3)
-    {
-        return callOperation(operation, arg1, arg2, arg3);
-    }
-    template<typename FunctionType, typename ArgumentType1, typename ArgumentType2, typename ArgumentType3, typename ArgumentType4>
-    JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2, ArgumentType3 arg3, ArgumentType4 arg4)
-    {
-        return callOperation(operation, arg1, arg2, arg3, arg4);
+        m_jit.setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), TrustedImm32(op3), regOp4);
+        return appendCall(operation);
     }
-    template<typename FunctionType, typename ArgumentType1, typename ArgumentType2, typename ArgumentType3, typename ArgumentType4, typename ArgumentType5>
-    JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2, ArgumentType3 arg3, ArgumentType4 arg4, ArgumentType5 arg5)
+
+    template<typename FunctionType, typename... Args>
+    JITCompiler::Call callOperation(FunctionType operation, NoResultTag, Args... args)
     {
-        return callOperation(operation, arg1, arg2, arg3, arg4, arg5);
+        return callOperation(operation, args...);
     }
 
     JITCompiler::Call callOperation(D_JITOperation_ZZ operation, FPRReg result, GPRReg arg1, GPRReg arg2)
@@ -1534,6 +1515,16 @@ public:
         m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), arg2, TrustedImm32(arg3), arg4, TrustedImm32(arg5));
         return appendCall(operation);
     }
+    JITCompiler::Call callOperation(V_JITOperation_ECJZC operation, GPRReg regOp1, GPRReg regOp2, int32_t op3, GPRReg regOp4)
+    {
+        m_jit.setupArgumentsWithExecState(regOp1, regOp2, TrustedImm32(op3), regOp4);
+        return appendCall(operation);
+    }
+    JITCompiler::Call callOperation(V_JITOperation_ECIZJJ operation, GPRReg regOp1, UniquedStringImpl* identOp2, int32_t op3, GPRReg regOp4, GPRReg regOp5)
+    {
+        m_jit.setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), TrustedImm32(op3), regOp4, regOp5);
+        return appendCall(operation);
+    }
 #else // USE(JSVALUE32_64)
 
 // EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]).
@@ -1855,6 +1846,16 @@ public:
         m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), arg2Payload, arg2Tag, TrustedImm32(arg3), arg4, TrustedImm32(arg5));
         return appendCall(operation);
     }
+    JITCompiler::Call callOperation(V_JITOperation_ECJZC operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, int32_t arg3, GPRReg arg4)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, TrustedImm32(arg3), arg4);
+        return appendCall(operation);
+    }
+    JITCompiler::Call callOperation(V_JITOperation_ECIZCC operation, GPRReg arg1, UniquedStringImpl* identOp2, int32_t op3, GPRReg arg4, GPRReg arg5)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identOp2), TrustedImm32(op3), arg4, arg5);
+        return appendCall(operation);
+    }
 #undef EABI_32BIT_DUMMY_ARG
 #undef SH4_32BIT_DUMMY_ARG
     
@@ -2243,6 +2244,9 @@ public:
     void compileTypeOf(Node*);
     void compileCheckStructure(Node*, GPRReg cellGPR, GPRReg tempGPR);
     void compileCheckStructure(Node*);
+    void compilePutAccessorById(Node*);
+    void compilePutGetterSetterById(Node*);
+    void compilePutAccessorByVal(Node*);
     
     void moveTrueTo(GPRReg);
     void moveFalseTo(GPRReg);
index a44157b..2959003 100644 (file)
@@ -4170,6 +4170,23 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
 
+    case PutGetterById:
+    case PutSetterById: {
+        compilePutAccessorById(node);
+        break;
+    }
+
+    case PutGetterSetterById: {
+        compilePutGetterSetterById(node);
+        break;
+    }
+
+    case PutGetterByVal:
+    case PutSetterByVal: {
+        compilePutAccessorByVal(node);
+        break;
+    }
+
     case GetGlobalLexicalVariable:
     case GetGlobalVar: {
         GPRTemporary resultPayload(this);
index c43ef84..99aaddf 100644 (file)
@@ -4162,6 +4162,23 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
 
+    case PutGetterById:
+    case PutSetterById: {
+        compilePutAccessorById(node);
+        break;
+    }
+
+    case PutGetterSetterById: {
+        compilePutGetterSetterById(node);
+        break;
+    }
+
+    case PutGetterByVal:
+    case PutSetterByVal: {
+        compilePutAccessorByVal(node);
+        break;
+    }
+
     case GetGlobalLexicalVariable:
     case GetGlobalVar: {
         GPRTemporary result(this);
index 2a04218..5dd7632 100644 (file)
@@ -204,6 +204,11 @@ inline CapabilityLevel canCompile(Node* node)
     case ForwardVarargs:
     case Switch:
     case TypeOf:
+    case PutGetterById:
+    case PutSetterById:
+    case PutGetterSetterById:
+    case PutGetterByVal:
+    case PutSetterByVal:
         // These are OK.
         break;
     case ArithSub:
index 43ddfc3..8e33522 100644 (file)
@@ -118,6 +118,9 @@ namespace JSC { namespace FTL {
     macro(V_JITOperation_J, functionType(voidType, int64)) \
     macro(V_JITOperation_Z, functionType(voidType, int32)) \
     macro(V_JITOperation_E, functionType(voidType, intPtr)) \
+    macro(V_JITOperation_ECIZC, functionType(voidType, intPtr, intPtr, intPtr, int32, intPtr)) \
+    macro(V_JITOperation_ECIZJJ, functionType(voidType, intPtr, intPtr, intPtr, int32, int64, int64)) \
+    macro(V_JITOperation_ECJZC, functionType(voidType, intPtr, intPtr, int64, int32, intPtr)) \
     macro(Z_JITOperation_D, functionType(int32, doubleType)) \
     macro(Z_JITOperation_EC, functionType(int32, intPtr, intPtr)) \
     macro(Z_JITOperation_EGC, functionType(int32, intPtr, intPtr, intPtr)) \
index 45b45f5..78a0fd8 100644 (file)
@@ -565,6 +565,17 @@ private:
         case PutByIdFlush:
             compilePutById();
             break;
+        case PutGetterById:
+        case PutSetterById:
+            compilePutAccessorById();
+            break;
+        case PutGetterSetterById:
+            compilePutGetterSetterById();
+            break;
+        case PutGetterByVal:
+        case PutSetterByVal:
+            compilePutAccessorByVal();
+            break;
         case GetButterfly:
             compileGetButterfly();
             break;
@@ -2999,6 +3010,38 @@ private:
             break;
         }
     }
+
+    void compilePutAccessorById()
+    {
+        LValue base = lowCell(m_node->child1());
+        LValue accessor = lowCell(m_node->child2());
+        auto uid = m_graph.identifiers()[m_node->identifierNumber()];
+        vmCall(
+            m_out.operation(m_node->op() == PutGetterById ? operationPutGetterById : operationPutSetterById),
+            m_callFrame, base, m_out.constIntPtr(uid), m_out.constInt32(m_node->accessorAttributes()), accessor);
+    }
+
+    void compilePutGetterSetterById()
+    {
+        LValue base = lowCell(m_node->child1());
+        LValue getter = lowJSValue(m_node->child2());
+        LValue setter = lowJSValue(m_node->child3());
+        auto uid = m_graph.identifiers()[m_node->identifierNumber()];
+        vmCall(
+            m_out.operation(operationPutGetterSetter),
+            m_callFrame, base, m_out.constIntPtr(uid), m_out.constInt32(m_node->accessorAttributes()), getter, setter);
+
+    }
+
+    void compilePutAccessorByVal()
+    {
+        LValue base = lowCell(m_node->child1());
+        LValue subscript = lowJSValue(m_node->child2());
+        LValue accessor = lowCell(m_node->child3());
+        vmCall(
+            m_out.operation(m_node->op() == PutGetterByVal ? operationPutGetterByVal : operationPutSetterByVal),
+            m_callFrame, base, subscript, m_out.constInt32(m_node->accessorAttributes()), accessor);
+    }
     
     void compileArrayPush()
     {
index 920dae2..410a8cb 100755 (executable)
@@ -762,9 +762,13 @@ namespace JSC {
         MacroAssembler::Call callOperation(V_JITOperation_E);
         MacroAssembler::Call callOperation(V_JITOperation_EC, RegisterID);
         MacroAssembler::Call callOperation(V_JITOperation_ECC, RegisterID, RegisterID);
-        MacroAssembler::Call callOperation(V_JITOperation_ECIZC, RegisterID, const Identifier*, int32_t, RegisterID);
-        MacroAssembler::Call callOperation(V_JITOperation_ECIZCC, RegisterID, const Identifier*, int32_t, RegisterID, RegisterID);
+        MacroAssembler::Call callOperation(V_JITOperation_ECIZC, RegisterID, UniquedStringImpl*, int32_t, RegisterID);
+        MacroAssembler::Call callOperation(V_JITOperation_ECIZCC, RegisterID, UniquedStringImpl*, int32_t, RegisterID, RegisterID);
+#if USE(JSVALUE64)
+        MacroAssembler::Call callOperation(V_JITOperation_ECJZC, RegisterID, RegisterID, int32_t, RegisterID);
+#else
         MacroAssembler::Call callOperation(V_JITOperation_ECJZC, RegisterID, RegisterID, RegisterID, int32_t, RegisterID);
+#endif
         MacroAssembler::Call callOperation(J_JITOperation_EE, RegisterID);
         MacroAssembler::Call callOperation(V_JITOperation_EZSymtabJ, int, SymbolTable*, RegisterID);
         MacroAssembler::Call callOperation(J_JITOperation_EZSymtabJ, int, SymbolTable*, RegisterID);
@@ -775,12 +779,10 @@ namespace JSC {
 #else
         MacroAssembler::Call callOperationNoExceptionCheck(V_JITOperation_EJ, RegisterID, RegisterID);
 #endif
-        MacroAssembler::Call callOperation(V_JITOperation_EJIdZJ, RegisterID, const Identifier*, int32_t, RegisterID);
-        MacroAssembler::Call callOperation(V_JITOperation_EJIdZJJ, RegisterID, const Identifier*, int32_t, RegisterID, RegisterID);
-        MacroAssembler::Call callOperation(V_JITOperation_EJJZJ, RegisterID, RegisterID, int32_t, RegisterID);
 #if USE(JSVALUE64)
         MacroAssembler::Call callOperation(F_JITOperation_EFJZZ, RegisterID, RegisterID, int32_t, RegisterID);
         MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, UniquedStringImpl*);
+        MacroAssembler::Call callOperation(V_JITOperation_ECIZJJ, RegisterID, UniquedStringImpl*, int32_t, RegisterID, RegisterID);
 #else
         MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, RegisterID, RegisterID, UniquedStringImpl*);
 #endif
index a34b7a0..b5ea081 100755 (executable)
@@ -406,6 +406,11 @@ ALWAYS_INLINE MacroAssembler::Call JIT::callOperationWithCallFrameRollbackOnExce
     return appendCallWithCallFrameRollbackOnException(operation);
 }
 
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECIZC operation, RegisterID regOp1, UniquedStringImpl* identOp2, int32_t op3, RegisterID regOp4)
+{
+    setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), TrustedImm32(op3), regOp4);
+    return appendCallWithExceptionCheck(operation);
+}
 
 #if USE(JSVALUE64)
 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJZZ operation, GPRReg arg1, int32_t arg2, int32_t arg3)
@@ -541,19 +546,13 @@ ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJ operatio
     return appendCallWithExceptionCheck(operation);
 }
 
-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJIdZJ operation, RegisterID regOp1, const Identifier* identOp2, int32_t op3, RegisterID regOp4)
-{
-    setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), TrustedImm32(op3), regOp4);
-    return appendCallWithExceptionCheck(operation);
-}
-
-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJIdZJJ operation, RegisterID regOp1, const Identifier* identOp2, int32_t op3, RegisterID regOp4, RegisterID regOp5)
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECIZJJ operation, RegisterID regOp1, UniquedStringImpl* identOp2, int32_t op3, RegisterID regOp4, RegisterID regOp5)
 {
     setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), TrustedImm32(op3), regOp4, regOp5);
     return appendCallWithExceptionCheck(operation);
 }
 
-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJZJ operation, RegisterID regOp1, RegisterID regOp2, int32_t op3, RegisterID regOp4)
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECJZC operation, RegisterID regOp1, RegisterID regOp2, int32_t op3, RegisterID regOp4)
 {
     setupArgumentsWithExecState(regOp1, regOp2, TrustedImm32(op3), regOp4);
     return appendCallWithExceptionCheck(operation);
@@ -675,13 +674,7 @@ ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EJJ operati
     return appendCallWithExceptionCheck(operation);
 }
 
-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECIZC operation, RegisterID regOp1, const Identifier* identOp2, int32_t op3, RegisterID regOp4)
-{
-    setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), TrustedImm32(op3), regOp4);
-    return appendCallWithExceptionCheck(operation);
-}
-
-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECIZCC operation, RegisterID regOp1, const Identifier* identOp2, int32_t op3, RegisterID regOp4, RegisterID regOp5)
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECIZCC operation, RegisterID regOp1, UniquedStringImpl* identOp2, int32_t op3, RegisterID regOp4, RegisterID regOp5)
 {
     setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), TrustedImm32(op3), regOp4, regOp5);
     return appendCallWithExceptionCheck(operation);
index 2b530f5..1f84d66 100644 (file)
@@ -1353,109 +1353,78 @@ static void putAccessorByVal(ExecState* exec, JSObject* base, JSValue subscript,
         base->putSetter(exec, propertyKey, accessor, attribute);
 }
 
-#if USE(JSVALUE64)
-void JIT_OPERATION operationPutGetterById(ExecState* exec, EncodedJSValue encodedObjectValue, Identifier* identifier, int32_t options, EncodedJSValue encodedGetterValue)
+void JIT_OPERATION operationPutGetterById(ExecState* exec, JSCell* object, UniquedStringImpl* uid, int32_t options, JSCell* getter)
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
 
-    ASSERT(JSValue::decode(encodedObjectValue).isObject());
-    JSObject* baseObj = asObject(JSValue::decode(encodedObjectValue));
+    ASSERT(object && object->isObject());
+    JSObject* baseObj = object->getObject();
 
-    JSValue getter = JSValue::decode(encodedGetterValue);
-    ASSERT(getter.isObject());
-    baseObj->putGetter(exec, *identifier, asObject(getter), options);
+    ASSERT(getter->isObject());
+    baseObj->putGetter(exec, uid, getter, options);
 }
 
-void JIT_OPERATION operationPutSetterById(ExecState* exec, EncodedJSValue encodedObjectValue, Identifier* identifier, int32_t options, EncodedJSValue encodedSetterValue)
+void JIT_OPERATION operationPutSetterById(ExecState* exec, JSCell* object, UniquedStringImpl* uid, int32_t options, JSCell* setter)
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
 
-    ASSERT(JSValue::decode(encodedObjectValue).isObject());
-    JSObject* baseObj = asObject(JSValue::decode(encodedObjectValue));
+    ASSERT(object && object->isObject());
+    JSObject* baseObj = object->getObject();
 
-    JSValue setter = JSValue::decode(encodedSetterValue);
-    ASSERT(setter.isObject());
-    baseObj->putSetter(exec, *identifier, asObject(setter), options);
+    ASSERT(setter->isObject());
+    baseObj->putSetter(exec, uid, setter, options);
 }
 
-void JIT_OPERATION operationPutGetterSetter(ExecState* exec, EncodedJSValue encodedObjectValue, Identifier* identifier, int32_t attribute,
-    EncodedJSValue encodedGetterValue, EncodedJSValue encodedSetterValue)
+void JIT_OPERATION operationPutGetterByVal(ExecState* exec, JSCell* base, EncodedJSValue encodedSubscript, int32_t attribute, JSCell* getter)
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
 
-    ASSERT(JSValue::decode(encodedObjectValue).isObject());
-    JSObject* baseObj = asObject(JSValue::decode(encodedObjectValue));
-
-    GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
-
-    JSValue getter = JSValue::decode(encodedGetterValue);
-    JSValue setter = JSValue::decode(encodedSetterValue);
-    ASSERT(getter.isObject() || getter.isUndefined());
-    ASSERT(setter.isObject() || setter.isUndefined());
-    ASSERT(getter.isObject() || setter.isObject());
-
-    if (!getter.isUndefined())
-        accessor->setGetter(vm, exec->lexicalGlobalObject(), asObject(getter));
-    if (!setter.isUndefined())
-        accessor->setSetter(vm, exec->lexicalGlobalObject(), asObject(setter));
-    baseObj->putDirectAccessor(exec, *identifier, accessor, attribute);
+    putAccessorByVal(exec, asObject(base), JSValue::decode(encodedSubscript), attribute, asObject(getter), AccessorType::Getter);
 }
 
-void JIT_OPERATION operationPutGetterByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, int32_t attribute, EncodedJSValue encodedGetter)
+void JIT_OPERATION operationPutSetterByVal(ExecState* exec, JSCell* base, EncodedJSValue encodedSubscript, int32_t attribute, JSCell* setter)
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
-    JSObject* base = asObject(JSValue::decode(encodedBase));
-    JSValue subscript = JSValue::decode(encodedSubscript);
-    JSObject* getter = asObject(JSValue::decode(encodedGetter));
-    putAccessorByVal(exec, base, subscript, attribute, getter, AccessorType::Getter);
-}
 
-void JIT_OPERATION operationPutSetterByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, int32_t attribute, EncodedJSValue encodedSetter)
-{
-    VM& vm = exec->vm();
-    NativeCallFrameTracer tracer(&vm, exec);
-    JSObject* base = asObject(JSValue::decode(encodedBase));
-    JSValue subscript = JSValue::decode(encodedSubscript);
-    JSObject* setter = asObject(JSValue::decode(encodedSetter));
-    putAccessorByVal(exec, base, subscript, attribute, setter, AccessorType::Setter);
+    putAccessorByVal(exec, asObject(base), JSValue::decode(encodedSubscript), attribute, asObject(setter), AccessorType::Setter);
 }
 
-#else
-void JIT_OPERATION operationPutGetterById(ExecState* exec, JSCell* object, Identifier* identifier, int32_t options, JSCell* getter)
+#if USE(JSVALUE64)
+void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, UniquedStringImpl* uid, int32_t attribute, EncodedJSValue encodedGetterValue, EncodedJSValue encodedSetterValue)
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
 
     ASSERT(object && object->isObject());
-    JSObject* baseObj = object->getObject();
+    JSObject* baseObj = asObject(object);
 
-    ASSERT(getter->isObject());
-    baseObj->putGetter(exec, *identifier, getter, options);
-}
-
-void JIT_OPERATION operationPutSetterById(ExecState* exec, JSCell* object, Identifier* identifier, int32_t options, JSCell* setter)
-{
-    VM& vm = exec->vm();
-    NativeCallFrameTracer tracer(&vm, exec);
+    GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
 
-    ASSERT(object && object->isObject());
-    JSObject* baseObj = object->getObject();
+    JSValue getter = JSValue::decode(encodedGetterValue);
+    JSValue setter = JSValue::decode(encodedSetterValue);
+    ASSERT(getter.isObject() || getter.isUndefined());
+    ASSERT(setter.isObject() || setter.isUndefined());
+    ASSERT(getter.isObject() || setter.isObject());
 
-    ASSERT(setter->isObject());
-    baseObj->putSetter(exec, *identifier, setter, options);
+    if (!getter.isUndefined())
+        accessor->setGetter(vm, exec->lexicalGlobalObject(), asObject(getter));
+    if (!setter.isUndefined())
+        accessor->setSetter(vm, exec->lexicalGlobalObject(), asObject(setter));
+    baseObj->putDirectAccessor(exec, uid, accessor, attribute);
 }
 
-void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, Identifier* identifier, int32_t attribute, JSCell* getter, JSCell* setter)
+#else
+void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, UniquedStringImpl* uid, int32_t attribute, JSCell* getter, JSCell* setter)
 {
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
 
     ASSERT(object && object->isObject());
-    JSObject* baseObj = object->getObject();
+    JSObject* baseObj = asObject(object);
 
     GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
 
@@ -1467,25 +1436,8 @@ void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, Ide
         accessor->setGetter(vm, exec->lexicalGlobalObject(), getter->getObject());
     if (setter)
         accessor->setSetter(vm, exec->lexicalGlobalObject(), setter->getObject());
-    baseObj->putDirectAccessor(exec, *identifier, accessor, attribute);
-}
-
-void JIT_OPERATION operationPutGetterByVal(ExecState* exec, JSCell* base, EncodedJSValue encodedSubscript, int32_t attribute, JSCell* getter)
-{
-    VM& vm = exec->vm();
-    NativeCallFrameTracer tracer(&vm, exec);
-
-    putAccessorByVal(exec, asObject(base), JSValue::decode(encodedSubscript), attribute, asObject(getter), AccessorType::Getter);
+    baseObj->putDirectAccessor(exec, uid, accessor, attribute);
 }
-
-void JIT_OPERATION operationPutSetterByVal(ExecState* exec, JSCell* base, EncodedJSValue encodedSubscript, int32_t attribute, JSCell* setter)
-{
-    VM& vm = exec->vm();
-    NativeCallFrameTracer tracer(&vm, exec);
-
-    putAccessorByVal(exec, asObject(base), JSValue::decode(encodedSubscript), attribute, asObject(setter), AccessorType::Setter);
-}
-
 #endif
 
 void JIT_OPERATION operationPopScope(ExecState* exec, int32_t scopeReg)
index aaca35a..f6c57f3 100644 (file)
@@ -189,8 +189,9 @@ typedef void JIT_OPERATION (*V_JITOperation_EC)(ExecState*, JSCell*);
 typedef void JIT_OPERATION (*V_JITOperation_ECb)(ExecState*, CodeBlock*);
 typedef void JIT_OPERATION (*V_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
 typedef void JIT_OPERATION (*V_JITOperation_ECIcf)(ExecState*, JSCell*, InlineCallFrame*);
-typedef void JIT_OPERATION (*V_JITOperation_ECIZC)(ExecState*, JSCell*, Identifier*, int32_t, JSCell*);
-typedef void JIT_OPERATION (*V_JITOperation_ECIZCC)(ExecState*, JSCell*, Identifier*, int32_t, JSCell*, JSCell*);
+typedef void JIT_OPERATION (*V_JITOperation_ECIZC)(ExecState*, JSCell*, UniquedStringImpl*, int32_t, JSCell*);
+typedef void JIT_OPERATION (*V_JITOperation_ECIZCC)(ExecState*, JSCell*, UniquedStringImpl*, int32_t, JSCell*, JSCell*);
+typedef void JIT_OPERATION (*V_JITOperation_ECIZJJ)(ExecState*, JSCell*, UniquedStringImpl*, int32_t, EncodedJSValue, EncodedJSValue);
 typedef void JIT_OPERATION (*V_JITOperation_ECJZC)(ExecState*, JSCell*, EncodedJSValue, int32_t, JSCell*);
 typedef void JIT_OPERATION (*V_JITOperation_ECCIcf)(ExecState*, JSCell*, JSCell*, InlineCallFrame*);
 typedef void JIT_OPERATION (*V_JITOperation_ECJJ)(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue);
@@ -200,9 +201,6 @@ typedef void JIT_OPERATION (*V_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
 typedef void JIT_OPERATION (*V_JITOperation_EZSymtabJ)(ExecState*, int32_t, SymbolTable*, EncodedJSValue);
 typedef void JIT_OPERATION (*V_JITOperation_EJ)(ExecState*, EncodedJSValue);
 typedef void JIT_OPERATION (*V_JITOperation_EJCI)(ExecState*, EncodedJSValue, JSCell*, UniquedStringImpl*);
-typedef void JIT_OPERATION (*V_JITOperation_EJIdZJ)(ExecState*, EncodedJSValue, Identifier*, int32_t, EncodedJSValue);
-typedef void JIT_OPERATION (*V_JITOperation_EJIdZJJ)(ExecState*, EncodedJSValue, Identifier*, int32_t, EncodedJSValue, EncodedJSValue);
-typedef void JIT_OPERATION (*V_JITOperation_EJJZJ)(ExecState*, EncodedJSValue, EncodedJSValue, int32_t, EncodedJSValue);
 typedef void JIT_OPERATION (*V_JITOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
 typedef void JIT_OPERATION (*V_JITOperation_EJJJAp)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*);
 typedef void JIT_OPERATION (*V_JITOperation_EJJJBy)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*);
@@ -313,18 +311,14 @@ void JIT_OPERATION operationDebug(ExecState*, int32_t) WTF_INTERNAL;
 SlowPathReturnType JIT_OPERATION operationOptimize(ExecState*, int32_t) WTF_INTERNAL;
 #endif
 void JIT_OPERATION operationPutByIndex(ExecState*, EncodedJSValue, int32_t, EncodedJSValue);
-#if USE(JSVALUE64)
-void JIT_OPERATION operationPutGetterById(ExecState*, EncodedJSValue, Identifier*, int32_t options, EncodedJSValue) WTF_INTERNAL;
-void JIT_OPERATION operationPutSetterById(ExecState*, EncodedJSValue, Identifier*, int32_t options, EncodedJSValue) WTF_INTERNAL;
-void JIT_OPERATION operationPutGetterSetter(ExecState*, EncodedJSValue, Identifier*, int32_t attribute, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
-void JIT_OPERATION operationPutGetterByVal(ExecState*, EncodedJSValue, EncodedJSValue, int32_t attribute, EncodedJSValue) WTF_INTERNAL;
-void JIT_OPERATION operationPutSetterByVal(ExecState*, EncodedJSValue, EncodedJSValue, int32_t attribute, EncodedJSValue) WTF_INTERNAL;
-#else
-void JIT_OPERATION operationPutGetterById(ExecState*, JSCell*, Identifier*, int32_t options, JSCell*) WTF_INTERNAL;
-void JIT_OPERATION operationPutSetterById(ExecState*, JSCell*, Identifier*, int32_t options, JSCell*) WTF_INTERNAL;
-void JIT_OPERATION operationPutGetterSetter(ExecState*, JSCell*, Identifier*, int32_t attribute, JSCell*, JSCell*) WTF_INTERNAL;
+void JIT_OPERATION operationPutGetterById(ExecState*, JSCell*, UniquedStringImpl*, int32_t options, JSCell*) WTF_INTERNAL;
+void JIT_OPERATION operationPutSetterById(ExecState*, JSCell*, UniquedStringImpl*, int32_t options, JSCell*) WTF_INTERNAL;
 void JIT_OPERATION operationPutGetterByVal(ExecState*, JSCell*, EncodedJSValue, int32_t attribute, JSCell*) WTF_INTERNAL;
 void JIT_OPERATION operationPutSetterByVal(ExecState*, JSCell*, EncodedJSValue, int32_t attribute, JSCell*) WTF_INTERNAL;
+#if USE(JSVALUE64)
+void JIT_OPERATION operationPutGetterSetter(ExecState*, JSCell*, UniquedStringImpl*, int32_t attribute, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
+#else
+void JIT_OPERATION operationPutGetterSetter(ExecState*, JSCell*, UniquedStringImpl*, int32_t attribute, JSCell*, JSCell*) WTF_INTERNAL;
 #endif
 void JIT_OPERATION operationPushFunctionNameScope(ExecState*, int32_t, SymbolTable*, EncodedJSValue) WTF_INTERNAL;
 void JIT_OPERATION operationPopScope(ExecState*, int32_t) WTF_INTERNAL;
index b146b20..3179f98 100644 (file)
@@ -492,7 +492,7 @@ void JIT::emit_op_put_getter_by_id(Instruction* currentInstruction)
     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
     int32_t options = currentInstruction[3].u.operand;
     emitGetVirtualRegister(currentInstruction[4].u.operand, regT1);
-    callOperation(operationPutGetterById, regT0, &m_codeBlock->identifier(currentInstruction[2].u.operand), options, regT1);
+    callOperation(operationPutGetterById, regT0, m_codeBlock->identifier(currentInstruction[2].u.operand).impl(), options, regT1);
 }
 
 void JIT::emit_op_put_setter_by_id(Instruction* currentInstruction)
@@ -500,7 +500,7 @@ void JIT::emit_op_put_setter_by_id(Instruction* currentInstruction)
     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
     int32_t options = currentInstruction[3].u.operand;
     emitGetVirtualRegister(currentInstruction[4].u.operand, regT1);
-    callOperation(operationPutSetterById, regT0, &m_codeBlock->identifier(currentInstruction[2].u.operand), options, regT1);
+    callOperation(operationPutSetterById, regT0, m_codeBlock->identifier(currentInstruction[2].u.operand).impl(), options, regT1);
 }
 
 void JIT::emit_op_put_getter_setter(Instruction* currentInstruction)
@@ -509,7 +509,7 @@ void JIT::emit_op_put_getter_setter(Instruction* currentInstruction)
     int32_t attribute = currentInstruction[3].u.operand;
     emitGetVirtualRegister(currentInstruction[4].u.operand, regT1);
     emitGetVirtualRegister(currentInstruction[5].u.operand, regT2);
-    callOperation(operationPutGetterSetter, regT0, &m_codeBlock->identifier(currentInstruction[2].u.operand), attribute, regT1, regT2);
+    callOperation(operationPutGetterSetter, regT0, m_codeBlock->identifier(currentInstruction[2].u.operand).impl(), attribute, regT1, regT2);
 }
 
 void JIT::emit_op_put_getter_by_val(Instruction* currentInstruction)
index d0477fd..6892e09 100644 (file)
@@ -66,7 +66,7 @@ void JIT::emit_op_put_getter_by_id(Instruction* currentInstruction)
 
     emitLoadPayload(base, regT1);
     emitLoadPayload(getter, regT3);
-    callOperation(operationPutGetterById, regT1, &m_codeBlock->identifier(property), options, regT3);
+    callOperation(operationPutGetterById, regT1, m_codeBlock->identifier(property).impl(), options, regT3);
 }
 
 void JIT::emit_op_put_setter_by_id(Instruction* currentInstruction)
@@ -78,7 +78,7 @@ void JIT::emit_op_put_setter_by_id(Instruction* currentInstruction)
 
     emitLoadPayload(base, regT1);
     emitLoadPayload(setter, regT3);
-    callOperation(operationPutSetterById, regT1, &m_codeBlock->identifier(property), options, regT3);
+    callOperation(operationPutSetterById, regT1, m_codeBlock->identifier(property).impl(), options, regT3);
 }
 
 void JIT::emit_op_put_getter_setter(Instruction* currentInstruction)
@@ -92,7 +92,7 @@ void JIT::emit_op_put_getter_setter(Instruction* currentInstruction)
     emitLoadPayload(base, regT1);
     emitLoadPayload(getter, regT3);
     emitLoadPayload(setter, regT4);
-    callOperation(operationPutGetterSetter, regT1, &m_codeBlock->identifier(property), attribute, regT3, regT4);
+    callOperation(operationPutGetterSetter, regT1, m_codeBlock->identifier(property).impl(), attribute, regT3, regT4);
 }
 
 void JIT::emit_op_put_getter_by_val(Instruction* currentInstruction)
diff --git a/Source/JavaScriptCore/tests/stress/dfg-put-accessors-by-id-class.js b/Source/JavaScriptCore/tests/stress/dfg-put-accessors-by-id-class.js
new file mode 100644 (file)
index 0000000..3b7ac5b
--- /dev/null
@@ -0,0 +1,82 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testAttribute(object, name, type) {
+    shouldBe(Reflect.has(object, name), true);
+    let desc = Reflect.getOwnPropertyDescriptor(object, name);
+    shouldBe(desc.configurable, true);
+    shouldBe(desc.enumerable, false);
+    if (type === 'get') {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'undefined');
+    } else if (type === 'set') {
+        shouldBe(typeof desc.get, 'undefined');
+        shouldBe(typeof desc.set, 'function');
+    } else {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'function');
+    }
+}
+noInline(testAttribute);
+
+function getter()
+{
+    class Cocoa {
+        get hello() {
+            return 42;
+        }
+    }
+
+    let object = new Cocoa();
+    testAttribute(object.__proto__, 'hello', 'get');
+    return object.hello;
+}
+noInline(getter);
+
+function setter()
+{
+    class Cocoa {
+        constructor() {
+            this.value = 0;
+        }
+        set hello(value) {
+            this.value = value;
+        }
+    }
+
+    let object = new Cocoa();
+    testAttribute(object.__proto__, 'hello', 'set');
+    object.hello = 42;
+    return object.value;
+
+}
+noInline(setter);
+
+function accessors()
+{
+    class Cocoa {
+        constructor() {
+            this.value = 0;
+        }
+        get hello() {
+            return this.value;
+        }
+        set hello(value) {
+            this.value = value;
+        }
+    }
+
+    let object = new Cocoa();
+    testAttribute(object.__proto__, 'hello', 'getset');
+    object.hello = 42;
+    return object.hello;
+}
+noInline(accessors);
+
+for (var i = 0; i < 10000; ++i) {
+    shouldBe(getter(), 42);
+    shouldBe(setter(), 42);
+    shouldBe(accessors(), 42);
+}
diff --git a/Source/JavaScriptCore/tests/stress/dfg-put-accessors-by-id.js b/Source/JavaScriptCore/tests/stress/dfg-put-accessors-by-id.js
new file mode 100644 (file)
index 0000000..b46dc78
--- /dev/null
@@ -0,0 +1,75 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testAttribute(object, name, type) {
+    shouldBe(Reflect.has(object, name), true);
+    let desc = Reflect.getOwnPropertyDescriptor(object, name);
+    shouldBe(desc.configurable, true);
+    shouldBe(desc.enumerable, true);
+    if (type === 'get') {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'undefined');
+    } else if (type === 'set') {
+        shouldBe(typeof desc.get, 'undefined');
+        shouldBe(typeof desc.set, 'function');
+    } else {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'function');
+    }
+}
+noInline(testAttribute);
+
+function getter()
+{
+    var object = {
+        get hello() {
+            return 42;
+        }
+    };
+
+    testAttribute(object, 'hello', 'get');
+    return object.hello;
+}
+noInline(getter);
+
+function setter()
+{
+    var object = {
+        value: 0,
+        set hello(value) {
+            this.value = value;
+        }
+    };
+
+    testAttribute(object, 'hello', 'set');
+    object.hello = 42;
+    return object.value;
+
+}
+noInline(setter);
+
+function accessors()
+{
+    var object = {
+        value: 0,
+        get hello() {
+            return this.value;
+        },
+        set hello(value) {
+            this.value = value;
+        }
+    };
+
+    testAttribute(object, 'hello', 'getset');
+    object.hello = 42;
+    return object.hello;
+}
+noInline(accessors);
+
+for (var i = 0; i < 10000; ++i) {
+    shouldBe(getter(), 42);
+    shouldBe(setter(), 42);
+    shouldBe(accessors(), 42);
+}
diff --git a/Source/JavaScriptCore/tests/stress/dfg-put-getter-by-id-class.js b/Source/JavaScriptCore/tests/stress/dfg-put-getter-by-id-class.js
new file mode 100644 (file)
index 0000000..7f4d6e6
--- /dev/null
@@ -0,0 +1,45 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testAttribute(object, name, type) {
+    shouldBe(Reflect.has(object, name), true);
+    let desc = Reflect.getOwnPropertyDescriptor(object, name);
+    shouldBe(desc.configurable, true);
+    shouldBe(desc.enumerable, false);
+    if (type === 'get') {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'undefined');
+    } else if (type === 'set') {
+        shouldBe(typeof desc.get, 'undefined');
+        shouldBe(typeof desc.set, 'function');
+    } else {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'function');
+    }
+}
+noInline(testAttribute);
+
+function getter(name)
+{
+    class Cocoa {
+        constructor() {
+            this.ok = 42;
+        }
+        get hello() {
+            return this.ok;
+        }
+        get [name]() {
+        }
+    }
+
+    let object = new Cocoa();
+    testAttribute(object.__proto__, 'hello', 'get');
+    testAttribute(object.__proto__, 'dummy', 'get');
+    return object.hello;
+}
+noInline(getter);
+
+for (var i = 0; i < 10000; ++i)
+    shouldBe(getter('dummy'), 42);
diff --git a/Source/JavaScriptCore/tests/stress/dfg-put-getter-by-id.js b/Source/JavaScriptCore/tests/stress/dfg-put-getter-by-id.js
new file mode 100644 (file)
index 0000000..45893e7
--- /dev/null
@@ -0,0 +1,39 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testAttribute(object, name, type) {
+    shouldBe(Reflect.has(object, name), true);
+    let desc = Reflect.getOwnPropertyDescriptor(object, name);
+    shouldBe(desc.configurable, true);
+    shouldBe(desc.enumerable, true);
+    if (type === 'get') {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'undefined');
+    } else if (type === 'set') {
+        shouldBe(typeof desc.get, 'undefined');
+        shouldBe(typeof desc.set, 'function');
+    } else {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'function');
+    }
+}
+noInline(testAttribute);
+
+function getter(name)
+{
+    var object = {
+        get hello() {
+            return this.ok;
+        },
+        [name]: 42
+    };
+
+    testAttribute(object, 'hello', 'get');
+    return object.hello;
+}
+noInline(getter);
+
+for (var i = 0; i < 10000; ++i)
+    shouldBe(getter('ok'), 42);
diff --git a/Source/JavaScriptCore/tests/stress/dfg-put-getter-by-val-class.js b/Source/JavaScriptCore/tests/stress/dfg-put-getter-by-val-class.js
new file mode 100644 (file)
index 0000000..0eb5c41
--- /dev/null
@@ -0,0 +1,42 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testAttribute(object, name, type) {
+    shouldBe(Reflect.has(object, name), true);
+    let desc = Reflect.getOwnPropertyDescriptor(object, name);
+    shouldBe(desc.configurable, true);
+    shouldBe(desc.enumerable, false);
+    if (type === 'get') {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'undefined');
+    } else if (type === 'set') {
+        shouldBe(typeof desc.get, 'undefined');
+        shouldBe(typeof desc.set, 'function');
+    } else {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'function');
+    }
+}
+noInline(testAttribute);
+
+function getter(name)
+{
+    class Cocoa {
+        constructor() {
+            this.ok = 42;
+        }
+        get [name]() {
+            return this.ok;
+        }
+    }
+
+    let object = new Cocoa();
+    testAttribute(object.__proto__, 'hello', 'get');
+    return object.hello;
+}
+noInline(getter);
+
+for (var i = 0; i < 10000; ++i)
+    shouldBe(getter('hello'), 42);
diff --git a/Source/JavaScriptCore/tests/stress/dfg-put-getter-by-val.js b/Source/JavaScriptCore/tests/stress/dfg-put-getter-by-val.js
new file mode 100644 (file)
index 0000000..74b614a
--- /dev/null
@@ -0,0 +1,39 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testAttribute(object, name, type) {
+    shouldBe(Reflect.has(object, name), true);
+    let desc = Reflect.getOwnPropertyDescriptor(object, name);
+    shouldBe(desc.configurable, true);
+    shouldBe(desc.enumerable, true);
+    if (type === 'get') {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'undefined');
+    } else if (type === 'set') {
+        shouldBe(typeof desc.get, 'undefined');
+        shouldBe(typeof desc.set, 'function');
+    } else {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'function');
+    }
+}
+noInline(testAttribute);
+
+function getter(name)
+{
+    var object = {
+        ok: 42,
+        get [name]() {
+            return this.ok;
+        }
+    };
+
+    testAttribute(object, 'hello', 'get');
+    return object.hello;
+}
+noInline(getter);
+
+for (var i = 0; i < 10000; ++i)
+    shouldBe(getter('hello'), 42);
diff --git a/Source/JavaScriptCore/tests/stress/dfg-put-setter-by-id-class.js b/Source/JavaScriptCore/tests/stress/dfg-put-setter-by-id-class.js
new file mode 100644 (file)
index 0000000..bb5b79d
--- /dev/null
@@ -0,0 +1,46 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testAttribute(object, name, type) {
+    shouldBe(Reflect.has(object, name), true);
+    let desc = Reflect.getOwnPropertyDescriptor(object, name);
+    shouldBe(desc.configurable, true);
+    shouldBe(desc.enumerable, false);
+    if (type === 'get') {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'undefined');
+    } else if (type === 'set') {
+        shouldBe(typeof desc.get, 'undefined');
+        shouldBe(typeof desc.set, 'function');
+    } else {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'function');
+    }
+}
+noInline(testAttribute);
+
+function getter(name)
+{
+    class Cocoa {
+        constructor() {
+            this.ok = 0;
+        }
+        set hello(value) {
+            this.ok = value;
+        }
+        get [name]() {
+        }
+    }
+
+    let object = new Cocoa();
+    testAttribute(object.__proto__, 'hello', 'set');
+    testAttribute(object.__proto__, 'dummy', 'get');
+    object.hello = 42;
+    return object.ok;
+}
+noInline(getter);
+
+for (var i = 0; i < 10000; ++i)
+    shouldBe(getter('dummy'), 42);
diff --git a/Source/JavaScriptCore/tests/stress/dfg-put-setter-by-id.js b/Source/JavaScriptCore/tests/stress/dfg-put-setter-by-id.js
new file mode 100644 (file)
index 0000000..8f6f3b9
--- /dev/null
@@ -0,0 +1,41 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testAttribute(object, name, type) {
+    shouldBe(Reflect.has(object, name), true);
+    let desc = Reflect.getOwnPropertyDescriptor(object, name);
+    shouldBe(desc.configurable, true);
+    shouldBe(desc.enumerable, true);
+    if (type === 'get') {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'undefined');
+    } else if (type === 'set') {
+        shouldBe(typeof desc.get, 'undefined');
+        shouldBe(typeof desc.set, 'function');
+    } else {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'function');
+    }
+}
+noInline(testAttribute);
+
+function setter(name)
+{
+    var object = {
+        set hello(value) {
+            this.ok = value;
+        },
+        [name]: 0
+    };
+
+    testAttribute(object, 'hello', 'set');
+    object.hello = 42;
+    return object.ok;
+
+}
+noInline(setter);
+
+for (var i = 0; i < 10000; ++i)
+    shouldBe(setter('ok'), 42);
diff --git a/Source/JavaScriptCore/tests/stress/dfg-put-setter-by-val-class.js b/Source/JavaScriptCore/tests/stress/dfg-put-setter-by-val-class.js
new file mode 100644 (file)
index 0000000..f29c9ec
--- /dev/null
@@ -0,0 +1,44 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testAttribute(object, name, type) {
+    shouldBe(Reflect.has(object, name), true);
+    let desc = Reflect.getOwnPropertyDescriptor(object, name);
+    shouldBe(desc.configurable, true);
+    shouldBe(desc.enumerable, false);
+    if (type === 'get') {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'undefined');
+    } else if (type === 'set') {
+        shouldBe(typeof desc.get, 'undefined');
+        shouldBe(typeof desc.set, 'function');
+    } else {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'function');
+    }
+}
+noInline(testAttribute);
+
+function setter(name)
+{
+    class Cocoa {
+        constructor() {
+            this.ok = 0;
+        }
+        set [name](value) {
+            this.ok = value;
+        }
+    }
+
+    let object = new Cocoa();
+    testAttribute(object.__proto__, 'hello', 'set');
+    object.hello = 42;
+    return object.ok;
+
+}
+noInline(setter);
+
+for (var i = 0; i < 10000; ++i)
+    shouldBe(setter('hello'), 42);
diff --git a/Source/JavaScriptCore/tests/stress/dfg-put-setter-by-val.js b/Source/JavaScriptCore/tests/stress/dfg-put-setter-by-val.js
new file mode 100644 (file)
index 0000000..2a3546b
--- /dev/null
@@ -0,0 +1,41 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function testAttribute(object, name, type) {
+    shouldBe(Reflect.has(object, name), true);
+    let desc = Reflect.getOwnPropertyDescriptor(object, name);
+    shouldBe(desc.configurable, true);
+    shouldBe(desc.enumerable, true);
+    if (type === 'get') {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'undefined');
+    } else if (type === 'set') {
+        shouldBe(typeof desc.get, 'undefined');
+        shouldBe(typeof desc.set, 'function');
+    } else {
+        shouldBe(typeof desc.get, 'function');
+        shouldBe(typeof desc.set, 'function');
+    }
+}
+noInline(testAttribute);
+
+function setter(name)
+{
+    var object = {
+        ok: 0,
+        set [name](value) {
+            this.ok = value;
+        }
+    };
+
+    testAttribute(object, 'hello', 'set');
+    object.hello = 42;
+    return object.ok;
+
+}
+noInline(setter);
+
+for (var i = 0; i < 10000; ++i)
+    shouldBe(setter('hello'), 42);