Changeset 200102 in webkit
- Timestamp:
- Apr 26, 2016 11:40:41 AM (8 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 29 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r200084 r200102 1 2016-04-26 Skachkov Oleksandr <gskachkov@gmail.com> 2 3 calling super() a second time in a constructor should throw 4 https://bugs.webkit.org/show_bug.cgi?id=151113 5 6 Reviewed by Saam Barati and Keith Miller. 7 8 * js/class-syntax-super-expected.txt: 9 * js/script-tests/class-syntax-super.js: 10 1 11 2016-04-26 Commit Queue <commit-queue@webkit.org> 2 12 -
trunk/LayoutTests/js/class-syntax-super-expected.txt
r200084 r200102 50 50 PASS new (class { constructor() { (function () { eval("super()");})(); } }):::SyntaxError: super is not valid in this context. 51 51 PASS (new (class { method() { (function () { eval("super.method()");})(); }})).method():::SyntaxError: super is not valid in this context. 52 PASS new (class extends Base { constructor() { super(); super();}}):::ReferenceError: 'super()' can't be called more than once in a constructor. 52 53 PASS successfullyParsed 53 54 -
trunk/LayoutTests/js/script-tests/class-syntax-super.js
r200084 r200102 136 136 shouldThrow('(new (class { method() { (function () { eval("super.method()");})(); }})).method()', '"SyntaxError: super is not valid in this context."'); 137 137 138 shouldThrow('new (class extends Base { constructor() { super(); super();}})', '"ReferenceError: \'super()\' can\'t be called more than once in a constructor."'); 138 139 var successfullyParsed = true; -
trunk/Source/JavaScriptCore/ChangeLog
r200101 r200102 1 2016-04-26 Skachkov Oleksandr <gskachkov@gmail.com> 2 3 calling super() a second time in a constructor should throw 4 https://bugs.webkit.org/show_bug.cgi?id=151113 5 6 Reviewed by Saam Barati. 7 8 Currently, our implementation checks if 'super()' was called in a constructor more 9 than once and raises a RuntimeError before the second call. According to the spec 10 we need to raise an error just after the second super() is finished and before 11 the new 'this' is assigned https://esdiscuss.org/topic/duplicate-super-call-behaviour. 12 To implement this behavior this patch adds a new op code, op_is_empty, that is used 13 to check if 'this' is empty. 14 15 * bytecode/BytecodeList.json: 16 * bytecode/BytecodeUseDef.h: 17 (JSC::computeUsesForBytecodeOffset): 18 (JSC::computeDefsForBytecodeOffset): 19 * bytecode/CodeBlock.cpp: 20 (JSC::CodeBlock::dumpBytecode): 21 * bytecompiler/BytecodeGenerator.cpp: 22 (JSC::BytecodeGenerator::emitIsEmpty): 23 * bytecompiler/BytecodeGenerator.h: 24 * bytecompiler/NodesCodegen.cpp: 25 (JSC::FunctionCallValueNode::emitBytecode): 26 * dfg/DFGAbstractInterpreterInlines.h: 27 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 28 * dfg/DFGByteCodeParser.cpp: 29 (JSC::DFG::ByteCodeParser::parseBlock): 30 * dfg/DFGCapabilities.cpp: 31 (JSC::DFG::capabilityLevel): 32 * dfg/DFGClobberize.h: 33 (JSC::DFG::clobberize): 34 * dfg/DFGDoesGC.cpp: 35 (JSC::DFG::doesGC): 36 * dfg/DFGFixupPhase.cpp: 37 (JSC::DFG::FixupPhase::fixupNode): 38 * dfg/DFGNodeType.h: 39 * dfg/DFGPredictionPropagationPhase.cpp: 40 * dfg/DFGSafeToExecute.h: 41 (JSC::DFG::safeToExecute): 42 * dfg/DFGSpeculativeJIT32_64.cpp: 43 (JSC::DFG::SpeculativeJIT::compile): 44 * dfg/DFGSpeculativeJIT64.cpp: 45 (JSC::DFG::SpeculativeJIT::compile): 46 * ftl/FTLCapabilities.cpp: 47 (JSC::FTL::canCompile): 48 * ftl/FTLLowerDFGToB3.cpp: 49 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 50 (JSC::FTL::DFG::LowerDFGToB3::compileIsEmpty): 51 * jit/JIT.cpp: 52 (JSC::JIT::privateCompileMainPass): 53 * jit/JIT.h: 54 * jit/JITOpcodes.cpp: 55 (JSC::JIT::emit_op_is_empty): 56 * jit/JITOpcodes32_64.cpp: 57 (JSC::JIT::emit_op_is_empty): 58 * llint/LowLevelInterpreter32_64.asm: 59 * llint/LowLevelInterpreter64.asm: 60 * tests/stress/class-syntax-double-constructor.js: Added. 61 1 62 2016-04-26 Mark Lam <mark.lam@apple.com> 2 63 -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.json
r200084 r200102 50 50 { "name" : "op_instanceof_custom", "length" : 5 }, 51 51 { "name" : "op_typeof", "length" : 3 }, 52 { "name" : "op_is_empty", "length" : 3 }, 52 53 { "name" : "op_is_undefined", "length" : 3 }, 53 54 { "name" : "op_is_boolean", "length" : 3 }, -
trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h
r200084 r200102 148 148 case op_get_array_length: 149 149 case op_typeof: 150 case op_is_empty: 150 151 case op_is_undefined: 151 152 case op_is_boolean: … … 377 378 case op_get_by_val: 378 379 case op_typeof: 380 case op_is_empty: 379 381 case op_is_undefined: 380 382 case op_is_boolean: -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r200084 r200102 1065 1065 case op_typeof: { 1066 1066 printUnaryOp(out, exec, location, it, "typeof"); 1067 break; 1068 } 1069 case op_is_empty: { 1070 printUnaryOp(out, exec, location, it, "is_empty"); 1067 1071 break; 1068 1072 } -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r200084 r200102 4119 4119 } 4120 4120 4121 RegisterID* BytecodeGenerator::emitIsEmpty(RegisterID* dst, RegisterID* src) 4122 { 4123 emitOpcode(op_is_empty); 4124 instructions().append(dst->index()); 4125 instructions().append(src->index()); 4126 return dst; 4127 } 4128 4121 4129 RegisterID* BytecodeGenerator::emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node) 4122 4130 { -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r200084 r200102 627 627 RegisterID* emitIsObject(RegisterID* dst, RegisterID* src); 628 628 RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src); 629 RegisterID* emitIsEmpty(RegisterID* dst, RegisterID* src); 629 630 void emitRequireObjectCoercible(RegisterID* value, const String& error); 630 631 -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r200084 r200102 764 764 generator.emitMove(callArguments.thisRegister(), generator.newTarget()); 765 765 RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); 766 767 bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Derived; 768 bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext(); 769 770 if (generator.isDerivedConstructorContext() || (doWeUseArrowFunctionInConstructor && generator.isSuperCallUsedInInnerArrowFunction())) 771 generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); 772 773 RefPtr<Label> thisIsEmptyLabel = generator.newLabel(); 774 generator.emitJumpIfTrue(generator.emitIsEmpty(generator.newTemporary(), generator.thisRegister()), thisIsEmptyLabel.get()); 775 generator.emitThrowReferenceError(ASCIILiteral("'super()' can't be called more than once in a constructor.")); 776 generator.emitLabel(thisIsEmptyLabel.get()); 777 766 778 generator.emitMove(generator.thisRegister(), ret); 767 779 768 bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Derived; 769 if (generator.isDerivedConstructorContext() || (isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext())) 780 if (generator.isDerivedConstructorContext() || doWeUseArrowFunctionInConstructor) 770 781 generator.emitPutThisToArrowFunctionContextScope(); 771 782 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r200096 r200102 997 997 } 998 998 999 case IsEmpty: 999 1000 case IsArrayObject: 1000 1001 case IsJSArray: … … 1085 1086 setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == RegExpObjectType)); 1086 1087 break; 1088 case IsEmpty: 1089 setConstant(node, jsBoolean(child.value().isEmpty())); 1090 break; 1087 1091 default: 1088 1092 constantWasSet = false; … … 1115 1119 1116 1120 break; 1121 case IsEmpty: { 1122 if (child.m_type && !(child.m_type & SpecEmpty)) { 1123 setConstant(node, jsBoolean(false)); 1124 constantWasSet = true; 1125 break; 1126 } 1127 1128 if (child.m_type && !(child.m_type & ~SpecEmpty)) { 1129 setConstant(node, jsBoolean(true)); 1130 constantWasSet = true; 1131 break; 1132 } 1133 1134 break; 1135 } 1117 1136 case IsUndefined: 1118 1137 // FIXME: Use the masquerades-as-undefined watchpoint thingy. -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r200084 r200102 3722 3722 NEXT_OPCODE(op_instanceof_custom); 3723 3723 } 3724 3724 case op_is_empty: { 3725 Node* value = get(VirtualRegister(currentInstruction[2].u.operand)); 3726 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsEmpty, value)); 3727 NEXT_OPCODE(op_is_empty); 3728 } 3725 3729 case op_is_undefined: { 3726 3730 Node* value = get(VirtualRegister(currentInstruction[2].u.operand)); -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
r200084 r200102 133 133 case op_instanceof: 134 134 case op_instanceof_custom: 135 case op_is_empty: 135 136 case op_is_undefined: 136 137 case op_is_boolean: -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r200084 r200102 156 156 case IsJSArray: 157 157 case IsArrayConstructor: 158 case IsEmpty: 158 159 case IsUndefined: 159 160 case IsBoolean: -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r200084 r200102 157 157 case IsJSArray: 158 158 case IsArrayConstructor: 159 case IsEmpty: 159 160 case IsUndefined: 160 161 case IsBoolean: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r200084 r200102 1531 1531 case IsJSArray: 1532 1532 case IsArrayConstructor: 1533 case IsEmpty: 1533 1534 case IsUndefined: 1534 1535 case IsBoolean: -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r200084 r200102 308 308 macro(IsJSArray, NodeResultBoolean) \ 309 309 macro(IsArrayConstructor, NodeResultBoolean) \ 310 macro(IsEmpty, NodeResultBoolean) \ 310 311 macro(IsUndefined, NodeResultBoolean) \ 311 312 macro(IsBoolean, NodeResultBoolean) \ -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r200034 r200102 765 765 case IsJSArray: 766 766 case IsArrayConstructor: 767 case IsEmpty: 767 768 case IsUndefined: 768 769 case IsBoolean: -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r200084 r200102 257 257 case IsJSArray: 258 258 case IsArrayConstructor: 259 case IsEmpty: 259 260 case IsUndefined: 260 261 case IsBoolean: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r200084 r200102 4414 4414 } 4415 4415 4416 case IsEmpty: { 4417 JSValueOperand value(this, node->child1()); 4418 GPRTemporary result(this, Reuse, value, TagWord); 4419 m_jit.comparePtr(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::EmptyValueTag), result.gpr()); 4420 booleanResult(result.gpr(), node); 4421 break; 4422 } 4423 4416 4424 case IsUndefined: { 4417 4425 JSValueOperand value(this, node->child1()); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r200084 r200102 4433 4433 break; 4434 4434 } 4435 4436 case IsEmpty: { 4437 JSValueOperand value(this, node->child1()); 4438 GPRTemporary result(this, Reuse, value); 4439 4440 m_jit.comparePtr(JITCompiler::Equal, value.gpr(), TrustedImm32(JSValue::encode(JSValue())), result.gpr()); 4441 m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); 4442 4443 jsValueResult(result.gpr(), node, DataFormatJSBoolean); 4444 break; 4445 } 4435 4446 4436 4447 case IsUndefined: { -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r200084 r200102 180 180 case IsJSArray: 181 181 case IsArrayConstructor: 182 case IsEmpty: 182 183 case IsUndefined: 183 184 case IsBoolean: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r200096 r200102 842 842 case InvalidationPoint: 843 843 compileInvalidationPoint(); 844 break; 845 case IsEmpty: 846 compileIsEmpty(); 844 847 break; 845 848 case IsUndefined: … … 5759 5762 // When this abruptly terminates, it could read any heap location. 5760 5763 patchpoint->effects.reads = HeapRange::top(); 5764 } 5765 5766 void compileIsEmpty() 5767 { 5768 setBoolean(m_out.isZero64(lowJSValue(m_node->child1()))); 5761 5769 } 5762 5770 -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r200084 r200102 236 236 DEFINE_OP(op_instanceof) 237 237 DEFINE_OP(op_instanceof_custom) 238 DEFINE_OP(op_is_empty) 238 239 DEFINE_OP(op_is_undefined) 239 240 DEFINE_OP(op_is_boolean) -
trunk/Source/JavaScriptCore/jit/JIT.h
r200084 r200102 512 512 void emit_op_instanceof(Instruction*); 513 513 void emit_op_instanceof_custom(Instruction*); 514 void emit_op_is_empty(Instruction*); 514 515 void emit_op_is_undefined(Instruction*); 515 516 void emit_op_is_boolean(Instruction*); -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r200084 r200102 176 176 addSlowCase(jump()); 177 177 } 178 179 void JIT::emit_op_is_empty(Instruction* currentInstruction) 180 { 181 int dst = currentInstruction[1].u.operand; 182 int value = currentInstruction[2].u.operand; 183 184 emitGetVirtualRegister(value, regT0); 185 compare64(Equal, regT0, TrustedImm32(JSValue::encode(JSValue())), regT0); 186 187 emitTagBool(regT0); 188 emitPutVirtualRegister(dst); 189 } 178 190 179 191 void JIT::emit_op_is_undefined(Instruction* currentInstruction) -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r200084 r200102 291 291 emitStoreBool(dst, returnValueGPR); 292 292 } 293 294 void JIT::emit_op_is_empty(Instruction* currentInstruction) 295 { 296 int dst = currentInstruction[1].u.operand; 297 int value = currentInstruction[2].u.operand; 298 299 emitLoad(value, regT1, regT0); 300 compare32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag), regT0); 301 302 emitStoreBool(dst, regT0); 303 } 293 304 294 305 void JIT::emit_op_is_undefined(Instruction* currentInstruction) -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r200084 r200102 1211 1211 callSlowPath(_llint_slow_path_instanceof_custom) 1212 1212 dispatch(5) 1213 1214 1215 _llint_op_is_empty: 1216 traceExecution() 1217 loadi 8[PC], t1 1218 loadi 4[PC], t0 1219 loadConstantOrVariable(t1, t2, t3) 1220 cieq t2, EmptyValueTag, t3 1221 storei BooleanTag, TagOffset[cfr, t0, 8] 1222 storei t3, PayloadOffset[cfr, t0, 8] 1223 dispatch(3) 1213 1224 1214 1225 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r200084 r200102 1099 1099 dispatch(5) 1100 1100 1101 1102 _llint_op_is_empty: 1103 traceExecution() 1104 loadisFromInstruction(2, t1) 1105 loadisFromInstruction(1, t2) 1106 loadConstantOrVariable(t1, t0) 1107 cqeq t0, ValueEmpty, t3 1108 orq ValueFalse, t3 1109 storeq t3, [cfr, t2, 8] 1110 dispatch(3) 1111 1112 1101 1113 _llint_op_is_undefined: 1102 1114 traceExecution()
Note: See TracChangeset
for help on using the changeset viewer.