Diff
Modified: tags/Safari-607.1.13/Source/_javascript_Core/ChangeLog (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/ChangeLog 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/ChangeLog 2018-11-07 20:55:45 UTC (rev 237937)
@@ -1,3 +1,144 @@
+2018-11-07 Alan Coon <alanc...@apple.com>
+
+ Cherry-pick r237933. rdar://problem/45739094
+
+ Align wide opcodes in the instruction stream
+ https://bugs.webkit.org/show_bug.cgi?id=191254
+
+ Reviewed by Keith Miller.
+
+ Pad the bytecode with nops to ensure that wide opcodes are 4-byte
+ aligned on platforms that don't like unaligned memory access.
+
+ For that, add a new type to represent jump targets, BoundLabel, which
+ delays computing the offset in case we need to emit nops for padding.
+ Extra padding is also emitted before op_yield and at the of each
+ BytecodeWriter fragment, to ensure that the bytecode remains aligned
+ after the rewriting.
+
+ As a side effect, we can longer guarantee that the point immediately
+ before emitting an opcode is the start of that opcode, since nops
+ might be emitted in between if the opcode needs to be wide. To fix
+ that, we only take the offset of opcodes after they have been emitted,
+ using `m_lastInstruction.offset()`.
+
+ * bytecode/BytecodeDumper.h:
+ (JSC::BytecodeDumper::dumpValue):
+ * bytecode/BytecodeGeneratorification.cpp:
+ (JSC::BytecodeGeneratorification::run):
+ * bytecode/BytecodeList.rb:
+ * bytecode/BytecodeRewriter.h:
+ (JSC::BytecodeRewriter::Fragment::align):
+ (JSC::BytecodeRewriter::insertFragmentBefore):
+ (JSC::BytecodeRewriter::insertFragmentAfter):
+ * bytecode/Fits.h:
+ * bytecode/InstructionStream.h:
+ (JSC::InstructionStreamWriter::ref):
+ * bytecode/PreciseJumpTargetsInlines.h:
+ (JSC::updateStoredJumpTargetsForInstruction):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::Label::setLocation):
+ (JSC::BoundLabel::target):
+ (JSC::BoundLabel::saveTarget):
+ (JSC::BoundLabel::commitTarget):
+ (JSC::BytecodeGenerator::generate):
+ (JSC::BytecodeGenerator::recordOpcode):
+ (JSC::BytecodeGenerator::alignWideOpcode):
+ (JSC::BytecodeGenerator::emitProfileControlFlow):
+ (JSC::BytecodeGenerator::emitResolveScope):
+ (JSC::BytecodeGenerator::emitGetFromScope):
+ (JSC::BytecodeGenerator::emitPutToScope):
+ (JSC::BytecodeGenerator::emitGetById):
+ (JSC::BytecodeGenerator::emitDirectGetById):
+ (JSC::BytecodeGenerator::emitPutById):
+ (JSC::BytecodeGenerator::emitDirectPutById):
+ (JSC::BytecodeGenerator::emitGetByVal):
+ (JSC::BytecodeGenerator::emitCreateThis):
+ (JSC::BytecodeGenerator::beginSwitch):
+ (JSC::BytecodeGenerator::endSwitch):
+ (JSC::BytecodeGenerator::emitRequireObjectCoercible):
+ (JSC::BytecodeGenerator::emitYieldPoint):
+ (JSC::BytecodeGenerator::emitToThis):
+ (JSC::Label::bind): Deleted.
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::recordOpcode): Deleted.
+ * bytecompiler/Label.h:
+ (JSC::BoundLabel::BoundLabel):
+ (JSC::BoundLabel::operator int):
+ (JSC::Label::bind):
+ * generator/Opcode.rb:
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237933 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2018-11-07 Tadeu Zagallo <tzaga...@apple.com>
+
+ Align wide opcodes in the instruction stream
+ https://bugs.webkit.org/show_bug.cgi?id=191254
+
+ Reviewed by Keith Miller.
+
+ Pad the bytecode with nops to ensure that wide opcodes are 4-byte
+ aligned on platforms that don't like unaligned memory access.
+
+ For that, add a new type to represent jump targets, BoundLabel, which
+ delays computing the offset in case we need to emit nops for padding.
+ Extra padding is also emitted before op_yield and at the of each
+ BytecodeWriter fragment, to ensure that the bytecode remains aligned
+ after the rewriting.
+
+ As a side effect, we can longer guarantee that the point immediately
+ before emitting an opcode is the start of that opcode, since nops
+ might be emitted in between if the opcode needs to be wide. To fix
+ that, we only take the offset of opcodes after they have been emitted,
+ using `m_lastInstruction.offset()`.
+
+ * bytecode/BytecodeDumper.h:
+ (JSC::BytecodeDumper::dumpValue):
+ * bytecode/BytecodeGeneratorification.cpp:
+ (JSC::BytecodeGeneratorification::run):
+ * bytecode/BytecodeList.rb:
+ * bytecode/BytecodeRewriter.h:
+ (JSC::BytecodeRewriter::Fragment::align):
+ (JSC::BytecodeRewriter::insertFragmentBefore):
+ (JSC::BytecodeRewriter::insertFragmentAfter):
+ * bytecode/Fits.h:
+ * bytecode/InstructionStream.h:
+ (JSC::InstructionStreamWriter::ref):
+ * bytecode/PreciseJumpTargetsInlines.h:
+ (JSC::updateStoredJumpTargetsForInstruction):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::Label::setLocation):
+ (JSC::BoundLabel::target):
+ (JSC::BoundLabel::saveTarget):
+ (JSC::BoundLabel::commitTarget):
+ (JSC::BytecodeGenerator::generate):
+ (JSC::BytecodeGenerator::recordOpcode):
+ (JSC::BytecodeGenerator::alignWideOpcode):
+ (JSC::BytecodeGenerator::emitProfileControlFlow):
+ (JSC::BytecodeGenerator::emitResolveScope):
+ (JSC::BytecodeGenerator::emitGetFromScope):
+ (JSC::BytecodeGenerator::emitPutToScope):
+ (JSC::BytecodeGenerator::emitGetById):
+ (JSC::BytecodeGenerator::emitDirectGetById):
+ (JSC::BytecodeGenerator::emitPutById):
+ (JSC::BytecodeGenerator::emitDirectPutById):
+ (JSC::BytecodeGenerator::emitGetByVal):
+ (JSC::BytecodeGenerator::emitCreateThis):
+ (JSC::BytecodeGenerator::beginSwitch):
+ (JSC::BytecodeGenerator::endSwitch):
+ (JSC::BytecodeGenerator::emitRequireObjectCoercible):
+ (JSC::BytecodeGenerator::emitYieldPoint):
+ (JSC::BytecodeGenerator::emitToThis):
+ (JSC::Label::bind): Deleted.
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::recordOpcode): Deleted.
+ * bytecompiler/Label.h:
+ (JSC::BoundLabel::BoundLabel):
+ (JSC::BoundLabel::operator int):
+ (JSC::Label::bind):
+ * generator/Opcode.rb:
+
2018-11-07 Tadeu Zagallo <tzaga...@apple.com>
REGRESSION(r237547): Test failures on 32-bit JSC since the JIT was disabled
Modified: tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeDumper.h (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeDumper.h 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeDumper.h 2018-11-07 20:55:45 UTC (rev 237937)
@@ -29,6 +29,7 @@
#include "CallLinkInfo.h"
#include "ICStatusMap.h"
#include "InstructionStream.h"
+#include "Label.h"
#include "StructureStubInfo.h"
namespace JSC {
@@ -52,6 +53,7 @@
}
void dumpValue(VirtualRegister reg) { m_out.printf("%s", registerName(reg.offset()).data()); }
+ void dumpValue(BoundLabel label) { m_out.print(label.target()); }
template<typename T>
void dumpValue(T v) { m_out.print(v); }
Modified: tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp 2018-11-07 20:55:45 UTC (rev 237937)
@@ -37,6 +37,7 @@
#include "JSCInlines.h"
#include "JSCJSValueInlines.h"
#include "JSGeneratorFunction.h"
+#include "Label.h"
#include "StrongInlines.h"
#include "UnlinkedCodeBlock.h"
#include "UnlinkedMetadataTableInlines.h"
@@ -205,7 +206,7 @@
jumpTable.add(i + 1, m_yields[i].point);
rewriter.insertFragmentBefore(nextToEnterPoint, [&](BytecodeRewriter::Fragment& fragment) {
- fragment.appendInstruction<OpSwitchImm>(switchTableIndex, nextToEnterPoint.offset(), state);
+ fragment.appendInstruction<OpSwitchImm>(switchTableIndex, BoundLabel(nextToEnterPoint.offset()), state);
});
}
Modified: tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeList.rb (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeList.rb 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeList.rb 2018-11-07 20:55:45 UTC (rev 237937)
@@ -25,6 +25,7 @@
:VirtualRegister,
:BasicBlockLocation,
+ :BoundLabel,
:DebugHookType,
:ErrorType,
:GetByIdMode,
@@ -591,31 +592,31 @@
op :jmp,
args: {
- target: int,
+ target: BoundLabel,
}
op :jtrue,
args: {
condition: VirtualRegister,
- target: int,
+ target: BoundLabel,
}
op :jfalse,
args: {
condition: VirtualRegister,
- target: int,
+ target: BoundLabel,
}
op :jeq_null,
args: {
value: VirtualRegister,
- target: int,
+ target: BoundLabel,
}
op :jneq_null,
args: {
value: VirtualRegister,
- target: int,
+ target: BoundLabel,
}
op :jneq_ptr,
@@ -622,7 +623,7 @@
args: {
value: VirtualRegister,
specialPointer: Special::Pointer,
- target: int,
+ target: BoundLabel,
},
metadata: {
hasJumped: bool,
@@ -648,7 +649,7 @@
args: {
lhs: VirtualRegister,
rhs: VirtualRegister,
- target: int,
+ target: BoundLabel,
}
op :loop_hint
@@ -661,7 +662,7 @@
],
args: {
tableIndex: unsigned,
- defaultOffset: int,
+ defaultOffset: BoundLabel,
scrutinee: VirtualRegister,
}
Modified: tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeRewriter.h (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeRewriter.h 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/bytecode/BytecodeRewriter.h 2018-11-07 20:55:45 UTC (rev 237937)
@@ -28,6 +28,7 @@
#include "BytecodeGenerator.h"
#include "BytecodeGraph.h"
+#include "BytecodeStructs.h"
#include "Bytecodes.h"
#include "Opcode.h"
#include "UnlinkedCodeBlock.h"
@@ -156,6 +157,16 @@
});
}
+ void align()
+ {
+#if CPU(NEEDS_ALIGNED_ACCESS)
+ m_bytecodeGenerator.withWriter(m_writer, [&] {
+ while (m_bytecodeGenerator.instructions().size() % OpcodeSize::Wide)
+ OpNop::emit<OpcodeSize::Narrow>(&m_bytecodeGenerator);
+ });
+#endif
+ }
+
private:
BytecodeGenerator& m_bytecodeGenerator;
InstructionStreamWriter& m_writer;
@@ -177,6 +188,7 @@
InstructionStreamWriter writer;
Fragment fragment(m_bytecodeGenerator, writer, includeBranch);
function(fragment);
+ fragment.align();
insertImpl(InsertionPoint(instruction.offset(), Position::Before), includeBranch, WTFMove(writer));
}
@@ -187,6 +199,7 @@
InstructionStreamWriter writer;
Fragment fragment(m_bytecodeGenerator, writer, includeBranch);
function(fragment);
+ fragment.align();
insertImpl(InsertionPoint(instruction.offset(), Position::After), includeBranch, WTFMove(writer));
}
Modified: tags/Safari-607.1.13/Source/_javascript_Core/bytecode/Fits.h (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/bytecode/Fits.h 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/bytecode/Fits.h 2018-11-07 20:55:45 UTC (rev 237937)
@@ -27,6 +27,7 @@
#include "GetPutInfo.h"
#include "Interpreter.h"
+#include "Label.h"
#include "OpcodeSize.h"
#include "ProfileTypeBytecodeFlag.h"
#include "ResultType.h"
@@ -293,4 +294,30 @@
}
};
+template<OpcodeSize size>
+struct Fits<BoundLabel, size> : Fits<int, size> {
+ // This is a bit hacky: we need to delay computing jump targets, since we
+ // might have to emit `nop`s to align the instructions stream. Additionally,
+ // we have to compute the target before we start writing to the instruction
+ // stream, since the offset is computed from the start of the bytecode. We
+ // achieve this by computing the target when we `check` and saving it, then
+ // later we use the saved target when we call convert.
+
+ using Base = Fits<int, size>;
+ static bool check(BoundLabel& label)
+ {
+ return Base::check(label.saveTarget());
+ }
+
+ static typename TypeBySize<size>::type convert(BoundLabel& label)
+ {
+ return Base::convert(label.commitTarget());
+ }
+
+ static BoundLabel convert(typename TypeBySize<size>::type target)
+ {
+ return BoundLabel(Base::convert(target));
+ }
+};
+
} // namespace JSC
Modified: tags/Safari-607.1.13/Source/_javascript_Core/bytecode/InstructionStream.h (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/bytecode/InstructionStream.h 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/bytecode/InstructionStream.h 2018-11-07 20:55:45 UTC (rev 237937)
@@ -238,7 +238,7 @@
MutableRef ref()
{
- return MutableRef { m_instructions, m_instructions.size() };
+ return MutableRef { m_instructions, m_position };
}
void swap(InstructionStreamWriter& other)
Modified: tags/Safari-607.1.13/Source/_javascript_Core/bytecode/PreciseJumpTargetsInlines.h (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/bytecode/PreciseJumpTargetsInlines.h 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/bytecode/PreciseJumpTargetsInlines.h 2018-11-07 20:55:45 UTC (rev 237937)
@@ -140,9 +140,9 @@
int32_t target = jumpTargetForInstruction<__op>(codeBlockOrHashMap, instruction); \
int32_t newTarget = function(target); \
if (newTarget != target || finalOffset) { \
- instruction->cast<__op>()->setTarget(newTarget, [&]() { \
+ instruction->cast<__op>()->setTarget(BoundLabel(newTarget), [&]() { \
codeBlock->addOutOfLineJumpTarget(finalOffset + instruction.offset(), newTarget); \
- return 0; \
+ return BoundLabel(); \
}); \
} \
break; \
@@ -161,9 +161,9 @@
int32_t target = jumpTargetForInstruction(codeBlockOrHashMap, instruction, bytecode.defaultOffset); \
int32_t newTarget = function(target); \
if (newTarget != target || finalOffset) { \
- instruction->cast<__op>()->setDefaultOffset(newTarget, [&]() { \
+ instruction->cast<__op>()->setDefaultOffset(BoundLabel(newTarget), [&]() { \
codeBlock->addOutOfLineJumpTarget(finalOffset + instruction.offset(), newTarget); \
- return 0; \
+ return BoundLabel(); \
}); \
} \
} while (false)
Modified: tags/Safari-607.1.13/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2018-11-07 20:55:45 UTC (rev 237937)
@@ -102,9 +102,9 @@
#define CASE(__op) \
case __op::opcodeID: \
- instruction->cast<__op>()->setTarget(target, [&]() { \
+ instruction->cast<__op>()->setTarget(BoundLabel(target), [&]() { \
generator.m_codeBlock->addOutOfLineJumpTarget(instruction.offset(), target); \
- return 0; \
+ return BoundLabel(); \
}); \
break;
@@ -136,11 +136,41 @@
}
}
-int Label::bind(BytecodeGenerator* generator)
+int BoundLabel::target()
{
- return bind(generator->instructions().size());
+ switch (m_type) {
+ case Offset:
+ return m_target;
+ case GeneratorBackward:
+ return m_target - m_generator->m_writer.position();
+ case GeneratorForward:
+ return 0;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
}
+int BoundLabel::saveTarget()
+{
+ if (m_type == GeneratorForward) {
+ m_savedTarget = m_generator->m_writer.position();
+ return 0;
+ }
+
+ m_savedTarget = target();
+ return m_savedTarget;
+}
+
+int BoundLabel::commitTarget()
+{
+ if (m_type == GeneratorForward) {
+ m_label->m_unresolvedJumps.append(m_savedTarget);
+ return 0;
+ }
+
+ return m_savedTarget;
+}
+
void Variable::dump(PrintStream& out) const
{
out.print(
@@ -216,9 +246,12 @@
}
for (auto& tuple : m_catchesToEmit) {
- Ref<Label> realCatchTarget = newEmittedLabel();
+ Ref<Label> realCatchTarget = newLabel();
OpCatch::emit(this, std::get<1>(tuple), std::get<2>(tuple));
+ realCatchTarget->setLocation(*this, m_lastInstruction.offset());
+ m_codeBlock->addJumpTarget(m_lastInstruction.offset());
+
TryData* tryData = std::get<0>(tuple);
emitJump(tryData->target.get());
tryData->target = WTFMove(realCatchTarget);
@@ -1280,6 +1313,24 @@
return label;
}
+void BytecodeGenerator::recordOpcode(OpcodeID opcodeID)
+{
+ ASSERT(m_lastOpcodeID == op_end || (m_lastOpcodeID == m_lastInstruction->opcodeID() && m_writer.position() == m_lastInstruction.offset() + m_lastInstruction->size()));
+ m_lastInstruction = m_writer.ref();
+ m_lastOpcodeID = opcodeID;
+}
+
+void BytecodeGenerator::alignWideOpcode()
+{
+#if CPU(NEEDS_ALIGNED_ACCESS)
+ OpcodeID lastOpcodeID = m_lastOpcodeID;
+ m_lastOpcodeID = op_end;
+ while ((m_writer.position() + 1) % OpcodeSize::Wide)
+ OpNop::emit<OpcodeSize::Narrow>(this);
+ recordOpcode(lastOpcodeID);
+#endif
+}
+
void BytecodeGenerator::emitLabel(Label& l0)
{
unsigned newLabelIndex = instructions().size();
@@ -1778,10 +1829,9 @@
{
if (vm()->controlFlowProfiler()) {
RELEASE_ASSERT(textOffset >= 0);
- size_t bytecodeOffset = instructions().size();
- m_codeBlock->addOpProfileControlFlowBytecodeOffset(bytecodeOffset);
OpProfileControlFlow::emit(this, textOffset);
+ m_codeBlock->addOpProfileControlFlowBytecodeOffset(m_lastInstruction.offset());
}
}
@@ -2395,11 +2445,9 @@
case VarKind::Invalid:
// Indicates non-local resolution.
- m_codeBlock->addPropertyAccessInstruction(instructions().size());
-
- // resolve_scope dst, id, ResolveType, depth
dst = tempDestination(dst);
OpResolveScope::emit(this, kill(dst), scopeRegister(), addConstant(variable.ident()), resolveType(), localScopeDepth());
+ m_codeBlock->addPropertyAccessInstruction(m_lastInstruction.offset());
return dst;
}
@@ -2420,9 +2468,6 @@
case VarKind::Scope:
case VarKind::Invalid: {
- m_codeBlock->addPropertyAccessInstruction(instructions().size());
-
- // get_from_scope dst, scope, id, GetPutInfo, Structure, Operand
OpGetFromScope::emit(
this,
kill(dst),
@@ -2431,6 +2476,7 @@
GetPutInfo(resolveMode, variable.offset().isScope() ? LocalClosureVar : resolveType(), InitializationMode::NotInitialization),
localScopeDepth(),
variable.offset().isScope() ? variable.offset().scopeOffset().offset() : 0);
+ m_codeBlock->addPropertyAccessInstruction(m_lastInstruction.offset());
return dst;
} }
@@ -2450,9 +2496,6 @@
case VarKind::Scope:
case VarKind::Invalid: {
- m_codeBlock->addPropertyAccessInstruction(instructions().size());
-
- // put_to_scope scope, id, value, GetPutInfo, Structure, Operand
GetPutInfo getPutInfo(0);
int scopeDepth;
ScopeOffset offset;
@@ -2466,6 +2509,7 @@
scopeDepth = localScopeDepth();
}
OpPutToScope::emit(this, scope, addConstant(variable.ident()), value, getPutInfo, scopeDepth, !!offset ? offset.offset() : 0);
+ m_codeBlock->addPropertyAccessInstruction(m_lastInstruction.offset());
return value;
} }
@@ -2515,9 +2559,8 @@
{
ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with get_by_val.");
- m_codeBlock->addPropertyAccessInstruction(instructions().size());
-
OpGetById::emit(this, kill(dst), base, addConstant(property));
+ m_codeBlock->addPropertyAccessInstruction(m_lastInstruction.offset());
return dst;
}
@@ -2533,9 +2576,8 @@
{
ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with get_by_val_direct.");
- m_codeBlock->addPropertyAccessInstruction(instructions().size());
-
OpGetByIdDirect::emit(this, kill(dst), base, addConstant(property));
+ m_codeBlock->addPropertyAccessInstruction(m_lastInstruction.offset());
return dst;
}
@@ -2547,9 +2589,8 @@
m_staticPropertyAnalyzer.putById(base, propertyIndex);
- m_codeBlock->addPropertyAccessInstruction(instructions().size());
-
OpPutById::emit(this, base, propertyIndex, value, PutByIdNone); // is not direct
+ m_codeBlock->addPropertyAccessInstruction(m_lastInstruction.offset());
return value;
}
@@ -2573,10 +2614,9 @@
m_staticPropertyAnalyzer.putById(base, propertyIndex);
- m_codeBlock->addPropertyAccessInstruction(instructions().size());
-
PutByIdFlags type = (putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone;
OpPutById::emit(this, base, propertyIndex, value, type);
+ m_codeBlock->addPropertyAccessInstruction(m_lastInstruction.offset());
return value;
}
@@ -2659,33 +2699,26 @@
RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
{
- bool forceWide = false;
for (size_t i = m_forInContextStack.size(); i--; ) {
ForInContext& context = m_forInContextStack[i].get();
if (context.local() != property)
continue;
- unsigned instIndex = instructions().size();
-
if (context.isIndexedForInContext()) {
auto& indexedContext = context.asIndexedForInContext();
- indexedContext.addGetInst(instIndex, property->index());
- property = indexedContext.index();
- forceWide = true;
- break;
+ OpGetByVal::emit<OpcodeSize::Wide>(this, kill(dst), base, indexedContext.index());
+ indexedContext.addGetInst(m_lastInstruction.offset(), property->index());
+ return dst;
}
StructureForInContext& structureContext = context.asStructureForInContext();
OpGetDirectPname::emit<OpcodeSize::Wide>(this, kill(dst), base, property, structureContext.index(), structureContext.enumerator());
- structureContext.addGetInst(instIndex, property->index());
+ structureContext.addGetInst(m_lastInstruction.offset(), property->index());
return dst;
}
- if (forceWide)
- OpGetByVal::emit<OpcodeSize::Wide>(this, kill(dst), base, property);
- else
- OpGetByVal::emit(this, kill(dst), base, property);
+ OpGetByVal::emit(this, kill(dst), base, property);
return dst;
}
@@ -2750,8 +2783,8 @@
{
m_staticPropertyAnalyzer.createThis(dst, m_writer.ref());
- m_codeBlock->addPropertyAccessInstruction(instructions().size());
OpCreateThis::emit(this, dst, dst, 0);
+ m_codeBlock->addPropertyAccessInstruction(m_lastInstruction.offset());
return dst;
}
@@ -3762,24 +3795,23 @@
void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
{
- SwitchInfo info = { static_cast<uint32_t>(instructions().size()), type };
switch (type) {
case SwitchInfo::SwitchImmediate: {
size_t tableIndex = m_codeBlock->numberOfSwitchJumpTables();
m_codeBlock->addSwitchJumpTable();
- OpSwitchImm::emit(this, tableIndex, 0, scrutineeRegister);
+ OpSwitchImm::emit(this, tableIndex, BoundLabel(), scrutineeRegister);
break;
}
case SwitchInfo::SwitchCharacter: {
size_t tableIndex = m_codeBlock->numberOfSwitchJumpTables();
m_codeBlock->addSwitchJumpTable();
- OpSwitchChar::emit(this, tableIndex, 0, scrutineeRegister);
+ OpSwitchChar::emit(this, tableIndex, BoundLabel(), scrutineeRegister);
break;
}
case SwitchInfo::SwitchString: {
size_t tableIndex = m_codeBlock->numberOfStringSwitchJumpTables();
m_codeBlock->addStringSwitchJumpTable();
- OpSwitchString::emit(this, tableIndex, 0, scrutineeRegister);
+ OpSwitchString::emit(this, tableIndex, BoundLabel(), scrutineeRegister);
break;
}
default:
@@ -3786,6 +3818,7 @@
RELEASE_ASSERT_NOT_REACHED();
}
+ SwitchInfo info = { m_lastInstruction.offset(), type };
m_switchContextStack.append(info);
}
@@ -3848,11 +3881,11 @@
SwitchInfo switchInfo = m_switchContextStack.last();
m_switchContextStack.removeLast();
- int defaultTarget = defaultLabel.bind(switchInfo.bytecodeOffset);
+ BoundLabel defaultTarget = defaultLabel.bind(switchInfo.bytecodeOffset);
auto handleSwitch = [&](auto* op, auto bytecode) {
op->setDefaultOffset(defaultTarget, [&]() {
m_codeBlock->addOutOfLineJumpTarget(switchInfo.bytecodeOffset, defaultTarget);
- return 0;
+ return BoundLabel();
});
UnlinkedSimpleJumpTable& jumpTable = m_codeBlock->switchJumpTable(bytecode.tableIndex);
@@ -3877,7 +3910,7 @@
case SwitchInfo::SwitchString: {
ref->cast<OpSwitchString>()->setDefaultOffset(defaultTarget, [&]() {
m_codeBlock->addOutOfLineJumpTarget(switchInfo.bytecodeOffset, defaultTarget);
- return 0;
+ return BoundLabel();
});
UnlinkedStringJumpTable& jumpTable = m_codeBlock->stringSwitchJumpTable(ref->as<OpSwitchString>().tableIndex);
@@ -4360,8 +4393,7 @@
// FIXME: op_jneq_null treats "undetectable" objects as null/undefined. RequireObjectCoercible
// thus incorrectly throws a TypeError for interfaces like HTMLAllCollection.
Ref<Label> target = newLabel();
- size_t begin = instructions().size();
- OpJneqNull::emit(this, value, target->bind(begin));
+ OpJneqNull::emit(this, value, target->bind(this));
emitThrowTypeError(error);
emitLabel(target.get());
}
@@ -4392,6 +4424,13 @@
Vector<TryContext> savedTryContextStack;
m_tryContextStack.swap(savedTryContextStack);
+
+#if CPU(NEEDS_ALIGNED_ACCESS)
+ // conservatively align for the bytecode rewriter: it will delete this yield and
+ // append a fragment, so we make sure that the start of the fragments is aligned
+ while (m_writer.position() % OpcodeSize::Wide)
+ OpNop::emit<OpcodeSize::Narrow>(this);
+#endif
OpYield::emit(this, generatorFrameRegister(), yieldPointIndex, argument);
// Restore the try contexts, which start offset is updated to the merge point.
@@ -4863,8 +4902,8 @@
void BytecodeGenerator::emitToThis()
{
- m_codeBlock->addPropertyAccessInstruction(instructions().size());
OpToThis::emit(this, kill(&m_thisRegister));
+ m_codeBlock->addPropertyAccessInstruction(m_lastInstruction.offset());
}
} // namespace JSC
Modified: tags/Safari-607.1.13/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2018-11-07 20:55:45 UTC (rev 237937)
@@ -363,6 +363,7 @@
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(BytecodeGenerator);
+ friend class BoundLabel;
friend class Label;
friend class IndexedForInContext;
friend class StructureForInContext;
@@ -506,12 +507,7 @@
n->emitBytecode(*this, dst);
}
- void recordOpcode(OpcodeID opcodeID)
- {
- ASSERT(m_lastOpcodeID == op_end || m_writer.size() == m_lastInstruction.offset() + m_lastInstruction->size());
- m_lastInstruction = m_writer.ref();
- m_lastOpcodeID = opcodeID;
- }
+ void recordOpcode(OpcodeID);
ALWAYS_INLINE unsigned addMetadataFor(OpcodeID opcodeID)
{
@@ -1185,6 +1181,7 @@
void write(uint8_t byte) { m_writer.write(byte); }
void write(uint32_t i) { m_writer.write(i); }
+ void alignWideOpcode();
class PreservedTDZStack {
private:
Modified: tags/Safari-607.1.13/Source/_javascript_Core/bytecompiler/Label.h (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/bytecompiler/Label.h 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/bytecompiler/Label.h 2018-11-07 20:55:45 UTC (rev 237937)
@@ -35,7 +35,56 @@
namespace JSC {
class BytecodeGenerator;
+ class Label;
+ class BoundLabel {
+ public:
+ BoundLabel()
+ : m_type(Offset)
+ , m_generator(nullptr)
+ , m_target(0)
+ { }
+
+ explicit BoundLabel(int target)
+ : m_type(Offset)
+ , m_generator(nullptr)
+ , m_target(target)
+ { }
+
+ BoundLabel(BytecodeGenerator* generator, Label* label)
+ : m_type(GeneratorForward)
+ , m_generator(generator)
+ , m_label(label)
+ { }
+
+ BoundLabel(BytecodeGenerator* generator, int offset)
+ : m_type(GeneratorBackward)
+ , m_generator(generator)
+ , m_target(offset)
+ { }
+
+ int target();
+ int saveTarget();
+ int commitTarget();
+
+ operator int() { return target(); }
+
+ private:
+ enum Type : uint8_t {
+ Offset,
+ GeneratorForward,
+ GeneratorBackward,
+ };
+
+ Type m_type;
+ int m_savedTarget { 0 };
+ BytecodeGenerator* m_generator;
+ union {
+ Label* m_label;
+ int m_target;
+ };
+ };
+
class Label {
WTF_MAKE_NONCOPYABLE(Label);
public:
@@ -43,18 +92,24 @@
void setLocation(BytecodeGenerator&, unsigned);
- int bind(BytecodeGenerator*);
+ BoundLabel bind(BytecodeGenerator* generator)
+ {
+ m_bound = true;
+ if (!isForward())
+ return BoundLabel(generator, m_location);
+ return BoundLabel(generator, this);
+ }
- int bind(unsigned offset)
+ BoundLabel bind(unsigned offset)
{
m_bound = true;
if (!isForward())
- return m_location - offset;
+ return BoundLabel(m_location - offset);
m_unresolvedJumps.append(offset);
- return 0;
+ return BoundLabel();
}
- int bind()
+ BoundLabel bind()
{
ASSERT(!isForward());
return bind(0u);
@@ -74,6 +129,8 @@
bool isBound() const { return m_bound; }
private:
+ friend class BoundLabel;
+
typedef Vector<int, 8> JumpVector;
static const unsigned invalidLocation = UINT_MAX;
Modified: tags/Safari-607.1.13/Source/_javascript_Core/generator/Opcode.rb (237936 => 237937)
--- tags/Safari-607.1.13/Source/_javascript_Core/generator/Opcode.rb 2018-11-07 20:50:05 UTC (rev 237936)
+++ tags/Safari-607.1.13/Source/_javascript_Core/generator/Opcode.rb 2018-11-07 20:55:45 UTC (rev 237937)
@@ -118,7 +118,7 @@
{
__generator->recordOpcode(opcodeID);
#{@metadata.create_emitter_local}
- emit<OpcodeSize::Narrow, NoAssert>(__generator#{untyped_args}#{metadata_arg}) || emit<OpcodeSize::Wide>(__generator#{untyped_args}#{metadata_arg});
+ emit<OpcodeSize::Narrow, NoAssert, false>(__generator#{untyped_args}#{metadata_arg}) || emit<OpcodeSize::Wide, Assert, false>(__generator#{untyped_args}#{metadata_arg});
}
#{%{
@@ -125,15 +125,16 @@
template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
static bool emit(BytecodeGenerator* __generator#{typed_args})
{
- __generator->recordOpcode(opcodeID);
#{@metadata.create_emitter_local}
return emit<size, shouldAssert>(__generator#{untyped_args}#{metadata_arg});
}
} unless @metadata.empty?}
- template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
+ template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
static bool emit(BytecodeGenerator* __generator#{typed_args}#{metadata_param})
{
+ if (recordOpcode)
+ __generator->recordOpcode(opcodeID);
bool didEmit = emitImpl<size>(__generator#{untyped_args}#{metadata_arg});
if (shouldAssert == Assert)
ASSERT(didEmit);
@@ -144,10 +145,11 @@
template<OpcodeSize size>
static bool emitImpl(BytecodeGenerator* __generator#{typed_args}#{metadata_param})
{
+ if (size == OpcodeSize::Wide)
+ __generator->alignWideOpcode();
if (#{map_fields_with_size("size", &:fits_check).join " && "} && (size == OpcodeSize::Wide ? #{op_wide.fits_check(Size::Narrow)} : true)) {
- if (size == OpcodeSize::Wide) {
+ if (size == OpcodeSize::Wide)
#{op_wide.fits_write Size::Narrow}
- }
#{map_fields_with_size("size", &:fits_write).join "\n"}
return true;
}