Diff
Modified: trunk/JSTests/ChangeLog (217839 => 217840)
--- trunk/JSTests/ChangeLog 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/JSTests/ChangeLog 2017-06-06 18:08:17 UTC (rev 217840)
@@ -1,3 +1,14 @@
+2017-06-06 Filip Pizlo <[email protected]>
+
+ index out of bound in bytecodebasicblock
+ https://bugs.webkit.org/show_bug.cgi?id=172963
+
+ Reviewed by Saam Barati and Mark Lam.
+
+ * stress/dfg-call-class-constructor.js: Added.
+ (Foo):
+ (i.catch):
+
2017-06-05 Joseph Pecoraro <[email protected]>
Web Inspector: Improve ES6 Class instances in Heap Snapshot instances view
Added: trunk/JSTests/stress/dfg-call-class-constructor.js (0 => 217840)
--- trunk/JSTests/stress/dfg-call-class-constructor.js (rev 0)
+++ trunk/JSTests/stress/dfg-call-class-constructor.js 2017-06-06 18:08:17 UTC (rev 217840)
@@ -0,0 +1,14 @@
+class Foo extends Promise { }
+
+noInline(Foo);
+
+for (var i = 0; i < 10000; ++i) {
+ var completed = false;
+ try {
+ Foo();
+ completed = true;
+ } catch (e) {
+ }
+ if (completed)
+ throw "Error: completed without throwing";
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (217839 => 217840)
--- trunk/Source/_javascript_Core/ChangeLog 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-06-06 18:08:17 UTC (rev 217840)
@@ -1,3 +1,46 @@
+2017-06-06 Filip Pizlo <[email protected]>
+
+ index out of bound in bytecodebasicblock
+ https://bugs.webkit.org/show_bug.cgi?id=172963
+
+ Reviewed by Saam Barati and Mark Lam.
+
+ We were leaving an unterminated basic block when generating CodeForCall for a class
+ constructor. This was mostly benign since that unterminated block was not reachable, but it
+ does cause an ASSERT.
+
+ This fixes the issue by appending op_unreachable to that block. I added op_unreachable because
+ this really is the cleanest and most idiomatic way to solve this problem, so even though it
+ makes the change bigger it's probabably worth it.
+
+ * bytecode/BytecodeDumper.cpp:
+ (JSC::BytecodeDumper<Block>::dumpBytecode):
+ * bytecode/BytecodeList.json:
+ * bytecode/BytecodeUseDef.h:
+ (JSC::computeUsesForBytecodeOffset):
+ (JSC::computeDefsForBytecodeOffset):
+ * bytecode/Opcode.h:
+ (JSC::isTerminal):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::generate):
+ (JSC::BytecodeGenerator::emitUnreachable):
+ * bytecompiler/BytecodeGenerator.h:
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileUnreachable):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * jit/JIT.h:
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_unreachable):
+ * llint/LowLevelInterpreter.asm:
+ * runtime/CommonSlowPaths.cpp:
+ (JSC::SLOW_PATH_DECL):
+ * runtime/CommonSlowPaths.h:
+
2017-06-06 Ryan Haddad <[email protected]>
Unreviewed, rolling out r217812.
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeDumper.cpp (217839 => 217840)
--- trunk/Source/_javascript_Core/bytecode/BytecodeDumper.cpp 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeDumper.cpp 2017-06-06 18:08:17 UTC (rev 217840)
@@ -1568,6 +1568,10 @@
out.printf("%s, %d", registerName(condition).data(), line);
break;
}
+ case op_unreachable: {
+ printLocationAndOp(out, location, it, "unreachable");
+ break;
+ }
case op_end: {
int r0 = (++it)->u.operand;
printLocationOpAndRegisterOperand(out, location, it, "end", r0);
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (217839 => 217840)
--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json 2017-06-06 18:08:17 UTC (rev 217840)
@@ -147,6 +147,7 @@
{ "name" : "op_enumerator_generic_pname", "length" : 4 },
{ "name" : "op_to_index_string", "length" : 3 },
{ "name" : "op_assert", "length" : 3 },
+ { "name" : "op_unreachable", "length" : 1 },
{ "name" : "op_create_rest", "length": 4 },
{ "name" : "op_get_rest_length", "length": 3 },
{ "name" : "op_yield", "length" : 4 },
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (217839 => 217840)
--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2017-06-06 18:08:17 UTC (rev 217840)
@@ -55,6 +55,7 @@
case op_check_traps:
case op_get_argument:
case op_nop:
+ case op_unreachable:
return;
case op_assert:
case op_get_scope:
@@ -366,6 +367,7 @@
case op_log_shadow_chicken_tail:
case op_yield:
case op_nop:
+ case op_unreachable:
#define LLINT_HELPER_OPCODES(opcode, length) case opcode:
FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES);
#undef LLINT_HELPER_OPCODES
Modified: trunk/Source/_javascript_Core/bytecode/Opcode.h (217839 => 217840)
--- trunk/Source/_javascript_Core/bytecode/Opcode.h 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.h 2017-06-06 18:08:17 UTC (rev 217840)
@@ -175,6 +175,7 @@
switch (opcodeID) {
case op_ret:
case op_end:
+ case op_unreachable:
return true;
default:
return false;
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (217839 => 217840)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-06-06 18:08:17 UTC (rev 217840)
@@ -144,6 +144,13 @@
bool callingClassConstructor = constructorKind() != ConstructorKind::None && !isConstructor();
if (!callingClassConstructor)
m_scopeNode->emitBytecode(*this);
+ else {
+ // At this point we would have emitted an unconditional throw followed by some nonsense that's
+ // just an artifact of how this generator is structured. That code never runs, but it confuses
+ // bytecode analyses because it constitutes an unterminated basic block. So, we terminate the
+ // basic block the strongest way possible.
+ emitUnreachable();
+ }
m_staticPropertyAnalyzer.kill();
@@ -2954,6 +2961,11 @@
return condition;
}
+void BytecodeGenerator::emitUnreachable()
+{
+ emitOpcode(op_unreachable);
+}
+
RegisterID* BytecodeGenerator::emitGetArgument(RegisterID* dst, int32_t index)
{
UnlinkedValueProfile profile = ""
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (217839 => 217840)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2017-06-06 18:08:17 UTC (rev 217840)
@@ -685,6 +685,7 @@
RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
RegisterID* emitAssert(RegisterID* condition, int line);
+ void emitUnreachable();
void emitPutGetterById(RegisterID* base, const Identifier& property, unsigned propertyDescriptorOptions, RegisterID* getter);
void emitPutSetterById(RegisterID* base, const Identifier& property, unsigned propertyDescriptorOptions, RegisterID* setter);
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (217839 => 217840)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-06-06 18:08:17 UTC (rev 217840)
@@ -5803,6 +5803,12 @@
}
NEXT_OPCODE(op_log_shadow_chicken_tail);
}
+
+ case op_unreachable: {
+ flushForTerminal();
+ addToGraph(Unreachable);
+ LAST_OPCODE(op_unreachable);
+ }
default:
// Parse failed! This should not happen because the capabilities checker
Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (217839 => 217840)
--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2017-06-06 18:08:17 UTC (rev 217840)
@@ -250,6 +250,7 @@
case op_resolve_scope:
case op_resolve_scope_for_hoisting_func_decl_in_eval:
case op_new_regexp:
+ case op_unreachable:
return CanCompileAndInline;
case op_switch_string: // Don't inline because we don't want to copy string tables in the concurrent JIT.
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (217839 => 217840)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-06-06 18:08:17 UTC (rev 217840)
@@ -10197,6 +10197,10 @@
// after that opcode. You don't have to also prove to AI that your opcode does not return.
// Hence, there is nothing to do here but emit code that will crash, so that we catch
// cases where you said Unreachable but you lied.
+ //
+ // It's also also worth noting that some clients emit this opcode because they're not 100% sure
+ // if the code is unreachable, but they would really prefer if we crashed rather than kept going
+ // if it did turn out to be reachable. Hence, this needs to deterministically crash.
crash();
}
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (217839 => 217840)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2017-06-06 18:08:17 UTC (rev 217840)
@@ -289,6 +289,7 @@
DEFINE_OP(op_get_rest_length)
DEFINE_OP(op_check_tdz)
DEFINE_OP(op_assert)
+ DEFINE_OP(op_unreachable)
DEFINE_OP(op_debug)
DEFINE_OP(op_del_by_id)
DEFINE_OP(op_del_by_val)
Modified: trunk/Source/_javascript_Core/jit/JIT.h (217839 => 217840)
--- trunk/Source/_javascript_Core/jit/JIT.h 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2017-06-06 18:08:17 UTC (rev 217840)
@@ -489,6 +489,7 @@
void emit_op_get_rest_length(Instruction*);
void emit_op_check_tdz(Instruction*);
void emit_op_assert(Instruction*);
+ void emit_op_unreachable(Instruction*);
void emit_op_debug(Instruction*);
void emit_op_del_by_id(Instruction*);
void emit_op_del_by_val(Instruction*);
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (217839 => 217840)
--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2017-06-06 18:08:17 UTC (rev 217840)
@@ -558,6 +558,12 @@
slowPathCall.call();
}
+void JIT::emit_op_unreachable(Instruction* currentInstruction)
+{
+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_unreachable);
+ slowPathCall.call();
+}
+
void JIT::emit_op_create_lexical_environment(Instruction* currentInstruction)
{
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_lexical_environment);
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (217839 => 217840)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2017-06-06 18:08:17 UTC (rev 217840)
@@ -1721,6 +1721,12 @@
dispatch(3)
+_llint_op_unreachable:
+ traceExecution()
+ callOpcodeSlowPath(_slow_path_unreachable)
+ dispatch(1)
+
+
_llint_op_yield:
notSupported()
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (217839 => 217840)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2017-06-06 18:08:17 UTC (rev 217840)
@@ -789,6 +789,13 @@
END();
}
+SLOW_PATH_DECL(slow_path_unreachable)
+{
+ BEGIN();
+ UNREACHABLE_FOR_PLATFORM();
+ END();
+}
+
SLOW_PATH_DECL(slow_path_create_lexical_environment)
{
BEGIN();
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h (217839 => 217840)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2017-06-06 18:08:17 UTC (rev 217840)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2013, 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -254,6 +254,7 @@
SLOW_PATH_HIDDEN_DECL(slow_path_to_index_string);
SLOW_PATH_HIDDEN_DECL(slow_path_profile_type_clear_log);
SLOW_PATH_HIDDEN_DECL(slow_path_assert);
+SLOW_PATH_HIDDEN_DECL(slow_path_unreachable);
SLOW_PATH_HIDDEN_DECL(slow_path_create_lexical_environment);
SLOW_PATH_HIDDEN_DECL(slow_path_push_with_scope);
SLOW_PATH_HIDDEN_DECL(slow_path_resolve_scope);
Modified: trunk/Source/WTF/ChangeLog (217839 => 217840)
--- trunk/Source/WTF/ChangeLog 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/WTF/ChangeLog 2017-06-06 18:08:17 UTC (rev 217840)
@@ -1,3 +1,13 @@
+2017-06-06 Filip Pizlo <[email protected]>
+
+ index out of bound in bytecodebasicblock
+ https://bugs.webkit.org/show_bug.cgi?id=172963
+
+ Reviewed by Saam Barati and Mark Lam.
+
+ * wtf/Assertions.h:
+ (UNREACHABLE_FOR_PLATFORM):
+
2017-06-05 Jer Noble <[email protected]>
Allow clients to specify a list of codecs which should require hardware decode support.
Modified: trunk/Source/WTF/wtf/Assertions.h (217839 => 217840)
--- trunk/Source/WTF/wtf/Assertions.h 2017-06-06 17:41:44 UTC (rev 217839)
+++ trunk/Source/WTF/wtf/Assertions.h 2017-06-06 18:08:17 UTC (rev 217840)
@@ -456,6 +456,8 @@
#pragma clang diagnostic ignored "-Wmissing-noreturn"
static inline void UNREACHABLE_FOR_PLATFORM()
{
+ // This *MUST* be a release assert. We use it in places where it's better to crash than to keep
+ // going.
RELEASE_ASSERT_NOT_REACHED();
}
#pragma clang diagnostic pop