Title: [237937] tags/Safari-607.1.13/Source/_javascript_Core
Revision
237937
Author
alanc...@apple.com
Date
2018-11-07 12:55:45 -0800 (Wed, 07 Nov 2018)

Log Message

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

Modified Paths

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;
             }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to