Title: [200459] trunk/Source/_javascript_Core
Revision
200459
Author
[email protected]
Date
2016-05-05 10:30:02 -0700 (Thu, 05 May 2016)

Log Message

Add support for delete by value to the DFG
https://bugs.webkit.org/show_bug.cgi?id=157372

Reviewed by Filip Pizlo.

This patch adds basic support for delete by value to the DFG. delete by value
just calls out to a C++ operation on each execution. Additionally, this patch
fixes an issue with delete by id where we would crash if the base was null
or undefined.

* 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/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileDeleteById):
(JSC::DFG::SpeculativeJIT::compileDeleteByVal):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_del_by_val):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_del_by_val):
* tests/stress/delete-by-val.js: Added.
(assert):
(test):
* tests/stress/delete-to-object-exception.js: Added.
(assert):
(test):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (200458 => 200459)


--- trunk/Source/_javascript_Core/ChangeLog	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-05-05 17:30:02 UTC (rev 200459)
@@ -1,3 +1,56 @@
+2016-05-05  Keith Miller  <[email protected]>
+
+        Add support for delete by value to the DFG
+        https://bugs.webkit.org/show_bug.cgi?id=157372
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds basic support for delete by value to the DFG. delete by value
+        just calls out to a C++ operation on each execution. Additionally, this patch
+        fixes an issue with delete by id where we would crash if the base was null
+        or undefined.
+
+        * 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/DFGNodeType.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileDeleteById):
+        (JSC::DFG::SpeculativeJIT::compileDeleteByVal):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_del_by_val):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emit_op_del_by_val):
+        * tests/stress/delete-by-val.js: Added.
+        (assert):
+        (test):
+        * tests/stress/delete-to-object-exception.js: Added.
+        (assert):
+        (test):
+
 2016-05-05  Michael Saboff  <[email protected]>
 
         Unreviewed build fix after change set r200447.

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-05-05 17:30:02 UTC (rev 200459)
@@ -2191,7 +2191,8 @@
         break;
     }
 
-    case DeleteById: {
+    case DeleteById:
+    case DeleteByVal: {
         // FIXME: This could decide if the delete will be successful based on the set of structures that
         // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611
         clobberWorld(node->origin.semantic, clobberLimit);

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -4160,6 +4160,14 @@
             NEXT_OPCODE(op_del_by_id);
         }
 
+        case op_del_by_val: {
+            int dst = currentInstruction[1].u.operand;
+            Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* key = get(VirtualRegister(currentInstruction[3].u.operand));
+            set(VirtualRegister(dst), addToGraph(DeleteByVal, base, key));
+            NEXT_OPCODE(op_del_by_val);
+        }
+
         case op_profile_type: {
             Node* valueToProfile = get(VirtualRegister(currentInstruction[1].u.operand));
             addToGraph(ProfileType, OpInfo(currentInstruction[2].u.location), valueToProfile);

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -164,6 +164,7 @@
     case op_put_getter_by_val:
     case op_put_setter_by_val:
     case op_del_by_id:
+    case op_del_by_val:
     case op_jmp:
     case op_jtrue:
     case op_jfalse:

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-05-05 17:30:02 UTC (rev 200459)
@@ -448,6 +448,7 @@
     case PutGetterByVal:
     case PutSetterByVal:
     case DeleteById:
+    case DeleteByVal:
     case ArrayPush:
     case ArrayPop:
     case Call:

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -108,6 +108,7 @@
     case PutGetterByVal:
     case PutSetterByVal:
     case DeleteById:
+    case DeleteByVal:
     case CheckStructure:
     case GetExecutable:
     case GetButterfly:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -1541,6 +1541,7 @@
         case ProfileWillCall:
         case ProfileDidCall:
         case DeleteById:
+        case DeleteByVal:
         case IsArrayObject:
         case IsJSArray:
         case IsArrayConstructor:

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-05-05 17:30:02 UTC (rev 200459)
@@ -195,6 +195,7 @@
     macro(PutGetterByVal, NodeMustGenerate) \
     macro(PutSetterByVal, NodeMustGenerate) \
     macro(DeleteById, NodeResultBoolean | NodeMustGenerate) \
+    macro(DeleteByVal, NodeResultBoolean | NodeMustGenerate) \
     macro(CheckStructure, NodeMustGenerate) \
     macro(GetExecutable, NodeResultJS) \
     macro(PutStructure, NodeMustGenerate) \

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -751,6 +751,7 @@
             setPrediction(SpecDoubleReal);
             break;
         }
+        case DeleteByVal:
         case DeleteById:
         case LogicalNot:
         case CompareLess:

Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-05-05 17:30:02 UTC (rev 200459)
@@ -193,6 +193,7 @@
     case ValueAdd:
     case TryGetById:
     case DeleteById:
+    case DeleteByVal:
     case GetById:
     case GetByIdFlush:
     case PutById:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -1072,6 +1072,26 @@
     unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
 }
 
+void SpeculativeJIT::compileDeleteByVal(Node* node)
+{
+    JSValueOperand base(this, node->child1());
+    JSValueOperand key(this, node->child2());
+    GPRFlushedCallResult result(this);
+
+    JSValueRegs baseRegs = base.jsValueRegs();
+    JSValueRegs keyRegs = key.jsValueRegs();
+    GPRReg resultGPR = result.gpr();
+
+    base.use();
+    key.use();
+
+    flushRegisters();
+    callOperation(operationDeleteByVal, resultGPR, baseRegs, keyRegs);
+    m_jit.exceptionCheck();
+
+    unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
+}
+
 bool SpeculativeJIT::nonSpeculativeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
 {
     unsigned branchIndexInBlock = detectPeepHoleBranch();

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2016-05-05 17:30:02 UTC (rev 200459)
@@ -715,6 +715,7 @@
 #endif
 
     void compileDeleteById(Node*);
+    void compileDeleteByVal(Node*);
     void compileTryGetById(Node*);
     void compileIn(Node*);
     
@@ -1511,6 +1512,10 @@
         m_jit.setupArgumentsWithExecState(arg1, arg2);
         return appendCallSetResult(operation, result);
     }
+    JITCompiler::Call callOperation(S_JITOperation_EJJ operation, GPRReg result,  JSValueRegs arg1, JSValueRegs arg2)
+    {
+        return callOperation(operation, result, arg1.gpr(), arg2.gpr());
+    }
     JITCompiler::Call callOperation(S_JITOperation_EGJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
     {
         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
@@ -1946,6 +1951,12 @@
         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
         return appendCallSetResult(operation, result);
     }
+
+    JITCompiler::Call callOperation(S_JITOperation_EJJ operation, GPRReg result, JSValueRegs arg1, JSValueRegs arg2)
+    {
+        return callOperation(operation, result, arg1.tagGPR(), arg1.payloadGPR(), arg2.tagGPR(), arg2.payloadGPR());
+    }
+
     JITCompiler::Call callOperation(S_JITOperation_EGJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
     {
         m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, SH4_32BIT_DUMMY_ARG arg3Payload, arg3Tag);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -4102,6 +4102,11 @@
         compileDeleteById(node);
         break;
     }
+
+    case DeleteByVal: {
+        compileDeleteByVal(node);
+        break;
+    }
         
     case CheckCell: {
         SpeculateCellOperand cell(this, node->child1());

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -4143,6 +4143,11 @@
         compileDeleteById(node);
         break;
     }
+
+    case DeleteByVal: {
+        compileDeleteByVal(node);
+        break;
+    }
         
     case CheckCell: {
         SpeculateCellOperand cell(this, node->child1());

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -187,7 +187,6 @@
         unsigned bytecodeOffset = m_bytecodeOffset;
 
         switch (opcodeID) {
-        DEFINE_SLOW_OP(del_by_val)
         DEFINE_SLOW_OP(in)
         DEFINE_SLOW_OP(less)
         DEFINE_SLOW_OP(lesseq)
@@ -222,6 +221,7 @@
         DEFINE_OP(op_resume)
         DEFINE_OP(op_debug)
         DEFINE_OP(op_del_by_id)
+        DEFINE_OP(op_del_by_val)
         DEFINE_OP(op_div)
         DEFINE_OP(op_end)
         DEFINE_OP(op_enter)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (200458 => 200459)


--- trunk/Source/_javascript_Core/jit/JIT.h	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2016-05-05 17:30:02 UTC (rev 200459)
@@ -496,6 +496,7 @@
         void emit_op_resume(Instruction*);
         void emit_op_debug(Instruction*);
         void emit_op_del_by_id(Instruction*);
+        void emit_op_del_by_val(Instruction*);
         void emit_op_div(Instruction*);
         void emit_op_end(Instruction*);
         void emit_op_enter(Instruction*);

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -1871,7 +1871,6 @@
     return JSValue::encode(jsBoolean(operationDeleteById(exec, base, uid)));
 }
 
-
 size_t JIT_OPERATION operationDeleteById(ExecState* exec, EncodedJSValue encodedBase, UniquedStringImpl* uid)
 {
     VM& vm = exec->vm();
@@ -1879,13 +1878,45 @@
 
     JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
     if (!baseObj)
-        JSValue::encode(JSValue());
+        return false;
     bool couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, Identifier::fromUid(&vm, uid));
     if (!couldDelete && exec->codeBlock()->isStrictMode())
         vm.throwException(exec, createTypeError(exec, ASCIILiteral("Unable to delete property.")));
     return couldDelete;
 }
 
+EncodedJSValue JIT_OPERATION operationDeleteByValJSResult(ExecState* exec, EncodedJSValue base,  EncodedJSValue key)
+{
+    return JSValue::encode(jsBoolean(operationDeleteByVal(exec, base, key)));
+}
+
+size_t JIT_OPERATION operationDeleteByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedKey)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
+    JSValue key = JSValue::decode(encodedKey);
+    if (!baseObj)
+        return false;
+
+    bool couldDelete;
+    uint32_t index;
+    if (key.getUInt32(index))
+        couldDelete = baseObj->methodTable(vm)->deletePropertyByIndex(baseObj, exec, index);
+    else {
+        if (vm.exception())
+            return false;
+        Identifier property = key.toPropertyKey(exec);
+        if (vm.exception())
+            return false;
+        couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, property);
+    }
+    if (!couldDelete && exec->codeBlock()->isStrictMode())
+        vm.throwException(exec, createTypeError(exec, ASCIILiteral("Unable to delete property.")));
+    return couldDelete;
+}
+
 EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedProto)
 {
     VM& vm = exec->vm();

Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (200458 => 200459)


--- trunk/Source/_javascript_Core/jit/JITOperations.h	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h	2016-05-05 17:30:02 UTC (rev 200459)
@@ -373,6 +373,8 @@
 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationDeleteByIdJSResult(ExecState*, EncodedJSValue base, UniquedStringImpl*) WTF_INTERNAL;
 size_t JIT_OPERATION operationDeleteById(ExecState*, EncodedJSValue base, UniquedStringImpl*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationDeleteByValJSResult(ExecState*, EncodedJSValue base, EncodedJSValue target) WTF_INTERNAL;
+size_t JIT_OPERATION operationDeleteByVal(ExecState*, EncodedJSValue base, EncodedJSValue target) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationGetPNames(ExecState*, JSObject*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState*, EncodedJSValue, EncodedJSValue proto) WTF_INTERNAL;
 int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState*, EncodedJSValue arguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -532,6 +532,16 @@
     callOperation(operationDeleteByIdJSResult, dst, regT0, m_codeBlock->identifier(property).impl());
 }
 
+void JIT::emit_op_del_by_val(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int property = currentInstruction[3].u.operand;
+    emitGetVirtualRegister(base, regT0);
+    emitGetVirtualRegister(property, regT1);
+    callOperation(operationDeleteByValJSResult, dst, regT0, regT1);
+}
+
 void JIT::emit_op_try_get_by_id(Instruction* currentInstruction)
 {
     int resultVReg = currentInstruction[1].u.operand;

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (200458 => 200459)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2016-05-05 17:14:49 UTC (rev 200458)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2016-05-05 17:30:02 UTC (rev 200459)
@@ -130,6 +130,15 @@
     callOperation(operationDeleteByIdJSResult, dst, regT1, regT0, m_codeBlock->identifier(property).impl());
 }
 
+void JIT::emit_op_del_by_val(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int property = currentInstruction[3].u.operand;
+    emitLoad2(base, regT1, regT0, property, regT3, regT2);
+    callOperation(operationDeleteByValJSResult, dst, regT1, regT0, regT3, regT2);
+}
+
 JIT::CodeRef JIT::stringGetByValStubGenerator(VM* vm)
 {
     JSInterfaceJIT jit(vm);

Added: trunk/Source/_javascript_Core/tests/stress/delete-by-val.js (0 => 200459)


--- trunk/Source/_javascript_Core/tests/stress/delete-by-val.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/delete-by-val.js	2016-05-05 17:30:02 UTC (rev 200459)
@@ -0,0 +1,15 @@
+function assert(condition) {
+    if (!condition)
+        throw new Error("assertion failed");
+}
+
+function test(i) {
+    let foo = {};
+    foo["bar" + i] = 1;
+    assert(foo["bar" + i] === 1)
+    assert(delete foo["bar" + i]);
+    assert(!("bar" + i in foo));
+}
+
+for (let i = 0; i < 100000; ++i)
+    test(i);

Added: trunk/Source/_javascript_Core/tests/stress/delete-to-object-exception.js (0 => 200459)


--- trunk/Source/_javascript_Core/tests/stress/delete-to-object-exception.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/delete-to-object-exception.js	2016-05-05 17:30:02 UTC (rev 200459)
@@ -0,0 +1,24 @@
+function assert(condition) {
+    if (!condition)
+        throw new Error("assertion failed");
+}
+
+function test(i) {
+    let value = null;
+    let passed = true;
+
+    try {
+        delete value.bar;
+        passed = false;
+    } catch(e) {}
+    try {
+        delete value["bar" + i];
+        passed = false;
+    } catch(e) {}
+    if (!passed)
+        throw new Error("didn't throw");
+}
+noInline(test);
+
+for (let i = 0; i < 10000; ++i)
+    test();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to