Diff
Modified: trunk/JSTests/ChangeLog (217061 => 217062)
--- trunk/JSTests/ChangeLog 2017-05-18 19:40:48 UTC (rev 217061)
+++ trunk/JSTests/ChangeLog 2017-05-18 19:55:01 UTC (rev 217062)
@@ -1,3 +1,20 @@
+2017-05-18 Filip Pizlo <[email protected]>
+
+ Constructor calls set this too early
+ https://bugs.webkit.org/show_bug.cgi?id=172302
+
+ Reviewed by Saam Barati.
+
+ This tests all three kinds of constructs in BytecodeGenerator. All three were previously
+ wrong.
+
+ * stress/construct-overwritten-variable.js: Added.
+ (new.x.x):
+ * stress/construct-spread-overwritten-variable-2.js: Added.
+ (new.x.x):
+ * stress/construct-spread-overwritten-variable.js: Added.
+ (new.x.x):
+
2017-05-18 Saam Barati <[email protected]>
WebAssembly: perform stack checks
Added: trunk/JSTests/stress/construct-overwritten-variable.js (0 => 217062)
--- trunk/JSTests/stress/construct-overwritten-variable.js (rev 0)
+++ trunk/JSTests/stress/construct-overwritten-variable.js 2017-05-18 19:55:01 UTC (rev 217062)
@@ -0,0 +1,6 @@
+//@ runDefault
+
+(function(){
+ var x = 42;
+ new x(x = function(){ });
+})();
Added: trunk/JSTests/stress/construct-spread-overwritten-variable-2.js (0 => 217062)
--- trunk/JSTests/stress/construct-spread-overwritten-variable-2.js (rev 0)
+++ trunk/JSTests/stress/construct-spread-overwritten-variable-2.js 2017-05-18 19:55:01 UTC (rev 217062)
@@ -0,0 +1,6 @@
+//@ runDefault
+
+(function(){
+ var x = 42;
+ new x(...[x = function(){ }]);
+})();
Added: trunk/JSTests/stress/construct-spread-overwritten-variable.js (0 => 217062)
--- trunk/JSTests/stress/construct-spread-overwritten-variable.js (rev 0)
+++ trunk/JSTests/stress/construct-spread-overwritten-variable.js 2017-05-18 19:55:01 UTC (rev 217062)
@@ -0,0 +1,7 @@
+//@ runDefault
+
+(function(){
+ var x = 42;
+ var a = [1, 2, 3];
+ new x(x = function(){ }, ...a);
+})();
Modified: trunk/Source/_javascript_Core/ChangeLog (217061 => 217062)
--- trunk/Source/_javascript_Core/ChangeLog 2017-05-18 19:40:48 UTC (rev 217061)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-05-18 19:55:01 UTC (rev 217062)
@@ -1,3 +1,25 @@
+2017-05-18 Filip Pizlo <[email protected]>
+
+ Constructor calls set this too early
+ https://bugs.webkit.org/show_bug.cgi?id=172302
+
+ Reviewed by Saam Barati.
+
+ We were setting this before evaluating the arguments, so this code:
+
+ var x = 42;
+ new x(x = function() { });
+
+ Would crash because we would pass 42 as this, and create_this would treat it as a cell.
+ Dereferencing a non-cell is guaranteed to crash.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitConstruct):
+ * bytecompiler/BytecodeGenerator.h:
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::NewExprNode::emitBytecode):
+ (JSC::FunctionCallValueNode::emitBytecode):
+
2017-05-18 Saam Barati <[email protected]>
WebAssembly: perform stack checks
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (217061 => 217062)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-05-18 19:40:48 UTC (rev 217061)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-05-18 19:55:01 UTC (rev 217062)
@@ -3638,7 +3638,7 @@
return src;
}
-RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, RegisterID* lazyThis, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
{
ASSERT(func->refCount());
@@ -3659,6 +3659,7 @@
instructions().append(argumentRegister.get()->index());
instructions().append(argumentRegister.get()->index());
+ emitMove(callArguments.thisRegister(), lazyThis);
RefPtr<RegisterID> thisRegister = emitMove(newTemporary(), callArguments.thisRegister());
return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, DebuggableCall::No);
}
@@ -3665,6 +3666,7 @@
}
RefPtr<RegisterID> argumentRegister;
argumentRegister = _expression_->emitBytecode(*this, callArguments.argumentRegister(0));
+ emitMove(callArguments.thisRegister(), lazyThis);
return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, DebuggableCall::No);
}
@@ -3671,7 +3673,9 @@
for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
emitNode(callArguments.argumentRegister(argument++), n);
}
-
+
+ emitMove(callArguments.thisRegister(), lazyThis);
+
// Reserve space for call frame.
Vector<RefPtr<RegisterID>, CallFrame::headerSizeInRegisters, UnsafeVectorOverflow> callFrame;
for (int i = 0; i < CallFrame::headerSizeInRegisters; ++i)
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (217061 => 217062)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2017-05-18 19:40:48 UTC (rev 217061)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2017-05-18 19:55:01 UTC (rev 217062)
@@ -683,7 +683,7 @@
RegisterID* emitReturn(RegisterID* src, ReturnFrom = ReturnFrom::Normal);
RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
- RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+ RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, RegisterID* lazyThis, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
void emitToPrimitive(RegisterID* dst, RegisterID* src);
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (217061 => 217062)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2017-05-18 19:40:48 UTC (rev 217061)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2017-05-18 19:55:01 UTC (rev 217062)
@@ -733,8 +733,7 @@
RefPtr<RegisterID> func = generator.emitNode(m_expr);
RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
CallArguments callArguments(generator, m_args);
- generator.emitMove(callArguments.thisRegister(), func.get());
- return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ return generator.emitConstruct(returnValue.get(), func.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
}
CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
@@ -816,8 +815,7 @@
ASSERT(generator.isConstructor() || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
ASSERT(generator.constructorKind() == ConstructorKind::Extends || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
- generator.emitMove(callArguments.thisRegister(), generator.newTarget());
- RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), generator.newTarget(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Extends;
bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext();