Title: [240501] branches/safari-607-branch
Revision
240501
Author
[email protected]
Date
2019-01-25 13:43:10 -0800 (Fri, 25 Jan 2019)

Log Message

Cherry-pick r239940. rdar://problem/47295340

JSTests:

    2019-01-14  Mark Lam  <[email protected]>

    Fix all CLoop JSC test failures (including some LLInt bugs due to recent bytecode format change).
    https://bugs.webkit.org/show_bug.cgi?id=193402
    <rdar://problem/46012309>

    Reviewed by Keith Miller.

    * stress/regexp-compile-oom.js:
    - Skip this test for !$jitTests because it is tuned for stack usage when the JIT
      is enabled.  As a result, it will fail on cloop builds though there is no bug.

Source/_javascript_Core:

Also picked up a few missing changes in JITPropertyAccess32_64.cpp from the
cherry-pick of r240041.

    2019-01-14  Mark Lam  <[email protected]>

    Fix all CLoop JSC test failures (including some LLInt bugs due to recent bytecode format change).
    https://bugs.webkit.org/show_bug.cgi?id=193402
    <rdar://problem/46012309>

    Reviewed by Keith Miller.

    The CLoop builds via build-jsc were previously completely disabled after our
    change to enable ASM LLInt build without the JIT.  As a result, JSC tests have
    regressed on CLoop builds.  The CLoop builds and tests will be re-enabled when
    the fix for https://bugs.webkit.org/show_bug.cgi?id=192955 lands.  This patch
    fixes all the regressions (and some old bugs) so that the CLoop test bots won't
    be red when CLoop build gets re-enabled.

    In this patch, we do the following:

    1. Change CLoopStack::grow() to set the new CLoop stack top at the maximum
       allocated capacity (after discounting the reserved zone) as opposed to setting
       it only at the level that the client requested.

       This fixes a small performance bug that I happened to noticed when I was
       debugging a stack issue.  It does not affect correctness.

    2. In LowLevelInterpreter32_64.asm:

       1. Fix loadConstantOrVariableTag() to use subi for computing the constant
          index because the VirtualRegister offset and FirstConstantRegisterIndex
          values it is operating on are both signed ints.  This is just to be
          pedantic.  The previous use of subu will still produce a correct value.

       2. Fix llintOpWithReturn() to use getu (instead of get) for reading
          OpIsCellWithType::type because it is of type JSType, which is a uint8_t.

       3. Fix llintOpWithMetadata() to use loadis for loading
          OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t5] because it
          is of type PropertyOffset, which is a signed int.

       4. Fix commonCallOp() to use getu for loading fields argv and argc because they
          are  of type unsigned for OpCall, OpConstruct, and OpTailCall, which are the
          clients of commonCallOp.

       5. Fix llintOpWithMetadata() and getClosureVar() to use loadp for loading
          OpGetFromScope::Metadata::operand because it is of type uintptr_t.

    3. In LowLevelInterpreter64.asm:

       1. Fix llintOpWithReturn() to use getu for reading OpIsCellWithType::type
          because it is of type JSType, which is a uint8_t.

       2. Fix llintOpWithMetadata() to use loadi for loading
          OpGetById::Metadata::modeMetadata.protoLoadMode.structure[t2] because it is
          of type StructureID, which is a uint32_t.

          Fix llintOpWithMetadata() to use loadis for loading
          OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t2] because it
          is of type PropertyOffset, which is a signed int.

       3. commonOp() should reload the metadataTable for op_catch because unlike
          for the ASM LLInt, the exception unwinding code is not able to restore
          "callee saved registers" for the CLoop interpreter because the CLoop uses
          pseudo-registers (see the CLoopRegister class).

          This was the source of many exotic Cloop failures after the bytecode format
          change (which introduced the metadataTable callee saved register).  Hence,
          we fix it by reloading metadataTable's value on re-entry via op_catch for
          exception handling.  We already take care of restoring it in op_ret.

       4. Fix llintOpWithMetadata() and getClosureVar() to use loadp for loading
          OpGetFromScope::Metadata::operand because it is of type uintptr_t.

    4. In LowLevelInterpreter.asm:

       Fix metadata() to use loadi for loading metadataTable offsets because they are
       of type unsigned.  This was also a source of many exotic CLoop test failures.

    5. Change CLoopRegister into a class with a uintptr_t as its storage element.
       Previously, we were using a union to convert between various value types that
       we would store in this pseudo-register.  This method of type conversion is
       undefined behavior according to the C++ spec.  As a result, the C++ compiler
       may choose to elide some CLoop statements, thereby resulting in some exotic
       bugs.

       We fix this by now always using accessor methods and assignment operators to
       ensure that we use bitwise_cast to do the type conversions.  Since bitwise_cast
       uses a memcpy, this ensures that there's no undefined behavior, and that CLoop
       statements won't get elided willy-nilly by the compiler.

       Ditto for the CloopDobleRegisters.

       Similarly, use bitwise_cast for ints2Double() and double2Ints() utility
       functions.

       Also use bitwise_cast (instead of reinterpret_cast) for the CLoop CAST macro.

    6. Fix cloop.rb to use the new CLoopRegister and CLoopDoubleRegister classes.

       Add a clLValue accessor for offlineasm operand types to distinguish
       LValue use of the operands from RValue uses.

       Replace the use of clearHighWord() with simply casting to uint32_t.  This is
       more efficient for the C++ compiler (and help speed up debug build runs).

       Also fix 32-bit arithmetic operations to only set the lower 32-bit value of
       the pseudo registers.  This fixes some CLoop JSC test failures.

    This patch has been manually tested with the JSC tests on the following builds:
    64bit X86 ASM LLLint (without JIT), 64bit and 32bit X86 CLoop, and ARMv7 Cloop.

    * interpreter/CLoopStack.cpp:
    (JSC::CLoopStack::grow):
    * llint/LowLevelInterpreter.asm:
    * llint/LowLevelInterpreter.cpp:
    (JSC::CLoopRegister::i const):
    (JSC::CLoopRegister::u const):
    (JSC::CLoopRegister::i32 const):
    (JSC::CLoopRegister::u32 const):
    (JSC::CLoopRegister::i8 const):
    (JSC::CLoopRegister::u8 const):
    (JSC::CLoopRegister::ip const):
    (JSC::CLoopRegister::i8p const):
    (JSC::CLoopRegister::vp const):
    (JSC::CLoopRegister::cvp const):
    (JSC::CLoopRegister::callFrame const):
    (JSC::CLoopRegister::execState const):
    (JSC::CLoopRegister::instruction const):
    (JSC::CLoopRegister::vm const):
    (JSC::CLoopRegister::cell const):
    (JSC::CLoopRegister::protoCallFrame const):
    (JSC::CLoopRegister::nativeFunc const):
    (JSC::CLoopRegister::i64 const):
    (JSC::CLoopRegister::u64 const):
    (JSC::CLoopRegister::encodedJSValue const):
    (JSC::CLoopRegister::opcode const):
    (JSC::CLoopRegister::operator ExecState*):
    (JSC::CLoopRegister::operator const Instruction*):
    (JSC::CLoopRegister::operator JSCell*):
    (JSC::CLoopRegister::operator ProtoCallFrame*):
    (JSC::CLoopRegister::operator Register*):
    (JSC::CLoopRegister::operator VM*):
    (JSC::CLoopRegister::operator=):
    (JSC::CLoopRegister::bitsAsDouble const):
    (JSC::CLoopRegister::bitsAsInt64 const):
    (JSC::CLoopDoubleRegister::operator T const):
    (JSC::CLoopDoubleRegister::d const):
    (JSC::CLoopDoubleRegister::bitsAsInt64 const):
    (JSC::CLoopDoubleRegister::operator=):
    (JSC::LLInt::ints2Double):
    (JSC::LLInt::double2Ints):
    (JSC::LLInt::decodeResult):
    (JSC::CLoop::execute):
    (JSC::LLInt::Ints2Double): Deleted.
    (JSC::LLInt::Double2Ints): Deleted.
    (JSC::CLoopRegister::CLoopRegister): Deleted.
    (JSC::CLoopRegister::clearHighWord): Deleted.
    * llint/LowLevelInterpreter32_64.asm:
    * llint/LowLevelInterpreter64.asm:
    * offlineasm/cloop.rb:

Modified Paths

Property Changed

Diff

Index: branches/safari-607-branch =================================================================== --- branches/safari-607-branch 2019-01-25 21:40:11 UTC (rev 240500) +++ branches/safari-607-branch 2019-01-25 21:43:10 UTC (rev 240501)

Property changes: branches/safari-607-branch


Modified: svn:mergeinfo

-/trunk:53455 \ No newline at end of property +/trunk:53455,239940 \ No newline at end of property

Modified: branches/safari-607-branch/JSTests/ChangeLog (240500 => 240501)


--- branches/safari-607-branch/JSTests/ChangeLog	2019-01-25 21:40:11 UTC (rev 240500)
+++ branches/safari-607-branch/JSTests/ChangeLog	2019-01-25 21:43:10 UTC (rev 240501)
@@ -1,3 +1,19 @@
+2019-01-25  Mark Lam  <[email protected]>
+
+        Cherry-pick r239940. rdar://problem/47295340
+
+    2019-01-14  Mark Lam  <[email protected]>
+
+            Fix all CLoop JSC test failures (including some LLInt bugs due to recent bytecode format change).
+            https://bugs.webkit.org/show_bug.cgi?id=193402
+            <rdar://problem/46012309>
+
+            Reviewed by Keith Miller.
+
+            * stress/regexp-compile-oom.js:
+            - Skip this test for !$jitTests because it is tuned for stack usage when the JIT
+              is enabled.  As a result, it will fail on cloop builds though there is no bug.
+
 2019-01-23  Alan Coon  <[email protected]>
 
         Cherry-pick r240327. rdar://problem/47494707

Modified: branches/safari-607-branch/JSTests/stress/regexp-compile-oom.js (240500 => 240501)


--- branches/safari-607-branch/JSTests/stress/regexp-compile-oom.js	2019-01-25 21:40:11 UTC (rev 240500)
+++ branches/safari-607-branch/JSTests/stress/regexp-compile-oom.js	2019-01-25 21:43:10 UTC (rev 240501)
@@ -1,4 +1,4 @@
-//@ skip if $hostOS != "darwin" or $architecture == "arm" or $architecture == "x86"
+//@ skip if $hostOS != "darwin" or $architecture == "arm" or $architecture == "x86" or not $jitTests
 // Test that throw an OOM exception when compiling a pathological, but valid nested RegExp.
 
 var failures = [];

Modified: branches/safari-607-branch/Source/_javascript_Core/ChangeLog (240500 => 240501)


--- branches/safari-607-branch/Source/_javascript_Core/ChangeLog	2019-01-25 21:40:11 UTC (rev 240500)
+++ branches/safari-607-branch/Source/_javascript_Core/ChangeLog	2019-01-25 21:43:10 UTC (rev 240501)
@@ -1,3 +1,169 @@
+2019-01-25  Mark Lam  <[email protected]>
+
+        Cherry-pick r239940. rdar://problem/47295340
+
+        Also picked up a few missing changes in JITPropertyAccess32_64.cpp from the
+        cherry-pick of r240041.
+
+    2019-01-14  Mark Lam  <[email protected]>
+
+            Fix all CLoop JSC test failures (including some LLInt bugs due to recent bytecode format change).
+            https://bugs.webkit.org/show_bug.cgi?id=193402
+            <rdar://problem/46012309>
+
+            Reviewed by Keith Miller.
+
+            The CLoop builds via build-jsc were previously completely disabled after our
+            change to enable ASM LLInt build without the JIT.  As a result, JSC tests have
+            regressed on CLoop builds.  The CLoop builds and tests will be re-enabled when
+            the fix for https://bugs.webkit.org/show_bug.cgi?id=192955 lands.  This patch
+            fixes all the regressions (and some old bugs) so that the CLoop test bots won't
+            be red when CLoop build gets re-enabled.
+
+            In this patch, we do the following:
+
+            1. Change CLoopStack::grow() to set the new CLoop stack top at the maximum
+               allocated capacity (after discounting the reserved zone) as opposed to setting
+               it only at the level that the client requested.
+
+               This fixes a small performance bug that I happened to noticed when I was
+               debugging a stack issue.  It does not affect correctness.
+
+            2. In LowLevelInterpreter32_64.asm:
+
+               1. Fix loadConstantOrVariableTag() to use subi for computing the constant
+                  index because the VirtualRegister offset and FirstConstantRegisterIndex
+                  values it is operating on are both signed ints.  This is just to be
+                  pedantic.  The previous use of subu will still produce a correct value.
+
+               2. Fix llintOpWithReturn() to use getu (instead of get) for reading
+                  OpIsCellWithType::type because it is of type JSType, which is a uint8_t.
+
+               3. Fix llintOpWithMetadata() to use loadis for loading
+                  OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t5] because it
+                  is of type PropertyOffset, which is a signed int.
+
+               4. Fix commonCallOp() to use getu for loading fields argv and argc because they
+                  are  of type unsigned for OpCall, OpConstruct, and OpTailCall, which are the
+                  clients of commonCallOp.
+
+               5. Fix llintOpWithMetadata() and getClosureVar() to use loadp for loading
+                  OpGetFromScope::Metadata::operand because it is of type uintptr_t.
+
+            3. In LowLevelInterpreter64.asm:
+
+               1. Fix llintOpWithReturn() to use getu for reading OpIsCellWithType::type
+                  because it is of type JSType, which is a uint8_t.
+
+               2. Fix llintOpWithMetadata() to use loadi for loading
+                  OpGetById::Metadata::modeMetadata.protoLoadMode.structure[t2] because it is
+                  of type StructureID, which is a uint32_t.
+
+                  Fix llintOpWithMetadata() to use loadis for loading
+                  OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t2] because it
+                  is of type PropertyOffset, which is a signed int.
+
+               3. commonOp() should reload the metadataTable for op_catch because unlike
+                  for the ASM LLInt, the exception unwinding code is not able to restore
+                  "callee saved registers" for the CLoop interpreter because the CLoop uses
+                  pseudo-registers (see the CLoopRegister class).
+
+                  This was the source of many exotic Cloop failures after the bytecode format
+                  change (which introduced the metadataTable callee saved register).  Hence,
+                  we fix it by reloading metadataTable's value on re-entry via op_catch for
+                  exception handling.  We already take care of restoring it in op_ret.
+
+               4. Fix llintOpWithMetadata() and getClosureVar() to use loadp for loading
+                  OpGetFromScope::Metadata::operand because it is of type uintptr_t.
+
+            4. In LowLevelInterpreter.asm:
+
+               Fix metadata() to use loadi for loading metadataTable offsets because they are
+               of type unsigned.  This was also a source of many exotic CLoop test failures.
+
+            5. Change CLoopRegister into a class with a uintptr_t as its storage element.
+               Previously, we were using a union to convert between various value types that
+               we would store in this pseudo-register.  This method of type conversion is
+               undefined behavior according to the C++ spec.  As a result, the C++ compiler
+               may choose to elide some CLoop statements, thereby resulting in some exotic
+               bugs.
+
+               We fix this by now always using accessor methods and assignment operators to
+               ensure that we use bitwise_cast to do the type conversions.  Since bitwise_cast
+               uses a memcpy, this ensures that there's no undefined behavior, and that CLoop
+               statements won't get elided willy-nilly by the compiler.
+
+               Ditto for the CloopDobleRegisters.
+
+               Similarly, use bitwise_cast for ints2Double() and double2Ints() utility
+               functions.
+
+               Also use bitwise_cast (instead of reinterpret_cast) for the CLoop CAST macro.
+
+            6. Fix cloop.rb to use the new CLoopRegister and CLoopDoubleRegister classes.
+
+               Add a clLValue accessor for offlineasm operand types to distinguish
+               LValue use of the operands from RValue uses.
+
+               Replace the use of clearHighWord() with simply casting to uint32_t.  This is
+               more efficient for the C++ compiler (and help speed up debug build runs).
+
+               Also fix 32-bit arithmetic operations to only set the lower 32-bit value of
+               the pseudo registers.  This fixes some CLoop JSC test failures.
+
+            This patch has been manually tested with the JSC tests on the following builds:
+            64bit X86 ASM LLLint (without JIT), 64bit and 32bit X86 CLoop, and ARMv7 Cloop.
+
+            * interpreter/CLoopStack.cpp:
+            (JSC::CLoopStack::grow):
+            * llint/LowLevelInterpreter.asm:
+            * llint/LowLevelInterpreter.cpp:
+            (JSC::CLoopRegister::i const):
+            (JSC::CLoopRegister::u const):
+            (JSC::CLoopRegister::i32 const):
+            (JSC::CLoopRegister::u32 const):
+            (JSC::CLoopRegister::i8 const):
+            (JSC::CLoopRegister::u8 const):
+            (JSC::CLoopRegister::ip const):
+            (JSC::CLoopRegister::i8p const):
+            (JSC::CLoopRegister::vp const):
+            (JSC::CLoopRegister::cvp const):
+            (JSC::CLoopRegister::callFrame const):
+            (JSC::CLoopRegister::execState const):
+            (JSC::CLoopRegister::instruction const):
+            (JSC::CLoopRegister::vm const):
+            (JSC::CLoopRegister::cell const):
+            (JSC::CLoopRegister::protoCallFrame const):
+            (JSC::CLoopRegister::nativeFunc const):
+            (JSC::CLoopRegister::i64 const):
+            (JSC::CLoopRegister::u64 const):
+            (JSC::CLoopRegister::encodedJSValue const):
+            (JSC::CLoopRegister::opcode const):
+            (JSC::CLoopRegister::operator ExecState*):
+            (JSC::CLoopRegister::operator const Instruction*):
+            (JSC::CLoopRegister::operator JSCell*):
+            (JSC::CLoopRegister::operator ProtoCallFrame*):
+            (JSC::CLoopRegister::operator Register*):
+            (JSC::CLoopRegister::operator VM*):
+            (JSC::CLoopRegister::operator=):
+            (JSC::CLoopRegister::bitsAsDouble const):
+            (JSC::CLoopRegister::bitsAsInt64 const):
+            (JSC::CLoopDoubleRegister::operator T const):
+            (JSC::CLoopDoubleRegister::d const):
+            (JSC::CLoopDoubleRegister::bitsAsInt64 const):
+            (JSC::CLoopDoubleRegister::operator=):
+            (JSC::LLInt::ints2Double):
+            (JSC::LLInt::double2Ints):
+            (JSC::LLInt::decodeResult):
+            (JSC::CLoop::execute):
+            (JSC::LLInt::Ints2Double): Deleted.
+            (JSC::LLInt::Double2Ints): Deleted.
+            (JSC::CLoopRegister::CLoopRegister): Deleted.
+            (JSC::CLoopRegister::clearHighWord): Deleted.
+            * llint/LowLevelInterpreter32_64.asm:
+            * llint/LowLevelInterpreter64.asm:
+            * offlineasm/cloop.rb:
+
 2019-01-23  Alan Coon  <[email protected]>
 
         Cherry-pick r240327. rdar://problem/47494707

Modified: branches/safari-607-branch/Source/_javascript_Core/interpreter/CLoopStack.cpp (240500 => 240501)


--- branches/safari-607-branch/Source/_javascript_Core/interpreter/CLoopStack.cpp	2019-01-25 21:40:11 UTC (rev 240500)
+++ branches/safari-607-branch/Source/_javascript_Core/interpreter/CLoopStack.cpp	2019-01-25 21:43:10 UTC (rev 240501)
@@ -103,6 +103,7 @@
     m_reservation.commit(newCommitTop, delta);
     addToCommittedByteCount(delta);
     m_commitTop = newCommitTop;
+    newTopOfStack = m_commitTop + m_softReservedZoneSizeInRegisters;
     setCLoopStackLimit(newTopOfStack);
     return true;
 }

Modified: branches/safari-607-branch/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (240500 => 240501)


--- branches/safari-607-branch/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2019-01-25 21:40:11 UTC (rev 240500)
+++ branches/safari-607-branch/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2019-01-25 21:43:10 UTC (rev 240501)
@@ -830,7 +830,7 @@
     case UnresolvedProperty:
     case UnresolvedPropertyWithVarInjectionChecks: {
         JumpList skipToEnd;
-        load32(&metadata.resolveType, regT0);
+        load32(&metadata.m_resolveType, regT0);
 
         Jump notGlobalProperty = branch32(NotEqual, regT0, TrustedImm32(GlobalProperty));
         emitCode(GlobalProperty);
@@ -955,7 +955,7 @@
     case GlobalProperty:
     case GlobalPropertyWithVarInjectionChecks: {
         JumpList skipToEnd;
-        load32(&metadata.getPutInfo, regT0);
+        load32(&metadata.m_getPutInfo, regT0);
         and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
 
         Jump isNotGlobalProperty = branch32(NotEqual, regT0, TrustedImm32(resolveType));
@@ -970,7 +970,7 @@
     case UnresolvedProperty:
     case UnresolvedPropertyWithVarInjectionChecks: {
         JumpList skipToEnd;
-        load32(&metadata.getPutInfo, regT0);
+        load32(&metadata.m_getPutInfo, regT0);
         and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
 
         Jump isGlobalProperty = branch32(Equal, regT0, TrustedImm32(GlobalProperty));
@@ -1110,7 +1110,7 @@
     case GlobalProperty:
     case GlobalPropertyWithVarInjectionChecks: {
         JumpList skipToEnd;
-        load32(&metadata.getPutInfo, regT0);
+        load32(&metadata.m_getPutInfo, regT0);
         and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
 
         Jump isGlobalProperty = branch32(Equal, regT0, TrustedImm32(resolveType));
@@ -1129,7 +1129,7 @@
     case UnresolvedProperty:
     case UnresolvedPropertyWithVarInjectionChecks: {
         JumpList skipToEnd;
-        load32(&metadata.getPutInfo, regT0);
+        load32(&metadata.m_getPutInfo, regT0);
         and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
 
         Jump isGlobalProperty = branch32(Equal, regT0, TrustedImm32(GlobalProperty));

Modified: branches/safari-607-branch/Source/_javascript_Core/llint/LowLevelInterpreter.cpp (240500 => 240501)


--- branches/safari-607-branch/Source/_javascript_Core/llint/LowLevelInterpreter.cpp	2019-01-25 21:40:11 UTC (rev 240500)
+++ branches/safari-607-branch/Source/_javascript_Core/llint/LowLevelInterpreter.cpp	2019-01-25 21:43:10 UTC (rev 240501)
@@ -123,154 +123,124 @@
 
 #define OFFLINE_ASM_LOCAL_LABEL(label) label: TRACE_LABEL("OFFLINE_ASM_LOCAL_LABEL", #label); USE_LABEL(label);
 
+namespace JSC {
 
 //============================================================================
+// CLoopRegister is the storage for an emulated CPU register.
+// It defines the policy of how ints smaller than intptr_t are packed into the
+// pseudo register, as well as hides endianness differences.
+
+class CLoopRegister {
+public:
+    ALWAYS_INLINE intptr_t i() const { return m_value; };
+    ALWAYS_INLINE uintptr_t u() const { return m_value; }
+    ALWAYS_INLINE int32_t i32() const { return m_value; }
+    ALWAYS_INLINE uint32_t u32() const { return m_value; }
+    ALWAYS_INLINE int8_t i8() const { return m_value; }
+    ALWAYS_INLINE uint8_t u8() const { return m_value; }
+
+    ALWAYS_INLINE intptr_t* ip() const { return bitwise_cast<intptr_t*>(m_value); }
+    ALWAYS_INLINE int8_t* i8p() const { return bitwise_cast<int8_t*>(m_value); }
+    ALWAYS_INLINE void* vp() const { return bitwise_cast<void*>(m_value); }
+    ALWAYS_INLINE const void* cvp() const { return bitwise_cast<const void*>(m_value); }
+    ALWAYS_INLINE CallFrame* callFrame() const { return bitwise_cast<CallFrame*>(m_value); }
+    ALWAYS_INLINE ExecState* execState() const { return bitwise_cast<ExecState*>(m_value); }
+    ALWAYS_INLINE const void* instruction() const { return bitwise_cast<const void*>(m_value); }
+    ALWAYS_INLINE VM* vm() const { return bitwise_cast<VM*>(m_value); }
+    ALWAYS_INLINE JSCell* cell() const { return bitwise_cast<JSCell*>(m_value); }
+    ALWAYS_INLINE ProtoCallFrame* protoCallFrame() const { return bitwise_cast<ProtoCallFrame*>(m_value); }
+    ALWAYS_INLINE NativeFunction nativeFunc() const { return bitwise_cast<NativeFunction>(m_value); }
+#if USE(JSVALUE64)
+    ALWAYS_INLINE int64_t i64() const { return m_value; }
+    ALWAYS_INLINE uint64_t u64() const { return m_value; }
+    ALWAYS_INLINE EncodedJSValue encodedJSValue() const { return bitwise_cast<EncodedJSValue>(m_value); }
+#endif
+    ALWAYS_INLINE Opcode opcode() const { return bitwise_cast<Opcode>(m_value); }
+
+    operator ExecState*() { return bitwise_cast<ExecState*>(m_value); }
+    operator const Instruction*() { return bitwise_cast<const Instruction*>(m_value); }
+    operator JSCell*() { return bitwise_cast<JSCell*>(m_value); }
+    operator ProtoCallFrame*() { return bitwise_cast<ProtoCallFrame*>(m_value); }
+    operator Register*() { return bitwise_cast<Register*>(m_value); }
+    operator VM*() { return bitwise_cast<VM*>(m_value); }
+
+    template<typename T, typename = std::enable_if_t<sizeof(T) == sizeof(uintptr_t)>>
+    ALWAYS_INLINE void operator=(T value) { m_value = bitwise_cast<uintptr_t>(value); }
+#if USE(JSVALUE64)
+    ALWAYS_INLINE void operator=(int32_t value) { m_value = static_cast<intptr_t>(value); }
+    ALWAYS_INLINE void operator=(uint32_t value) { m_value = static_cast<uintptr_t>(value); }
+#endif
+    ALWAYS_INLINE void operator=(int16_t value) { m_value = static_cast<intptr_t>(value); }
+    ALWAYS_INLINE void operator=(uint16_t value) { m_value = static_cast<uintptr_t>(value); }
+    ALWAYS_INLINE void operator=(int8_t value) { m_value = static_cast<intptr_t>(value); }
+    ALWAYS_INLINE void operator=(uint8_t value) { m_value = static_cast<uintptr_t>(value); }
+    ALWAYS_INLINE void operator=(bool value) { m_value = static_cast<uintptr_t>(value); }
+
+#if USE(JSVALUE64)
+    ALWAYS_INLINE double bitsAsDouble() const { return bitwise_cast<double>(m_value); }
+    ALWAYS_INLINE int64_t bitsAsInt64() const { return bitwise_cast<int64_t>(m_value); }
+#endif
+
+private:
+    uintptr_t m_value { static_cast<uintptr_t>(0xbadbeef0baddbeef) };
+};
+
+class CLoopDoubleRegister {
+public:
+    template<typename T>
+    explicit operator T() const { return bitwise_cast<T>(m_value); }
+
+    ALWAYS_INLINE double d() const { return m_value; }
+    ALWAYS_INLINE int64_t bitsAsInt64() const { return bitwise_cast<int64_t>(m_value); }
+
+    ALWAYS_INLINE void operator=(double value) { m_value = value; }
+
+    template<typename T, typename = std::enable_if_t<sizeof(T) == sizeof(uintptr_t) && std::is_integral<T>::value>>
+    ALWAYS_INLINE void operator=(T value) { m_value = bitwise_cast<double>(value); }
+
+private:
+    double m_value;
+};
+
+//============================================================================
 // Some utilities:
 //
 
-namespace JSC {
 namespace LLInt {
 
 #if USE(JSVALUE32_64)
-static double Ints2Double(uint32_t lo, uint32_t hi)
+static double ints2Double(uint32_t lo, uint32_t hi)
 {
-    union {
-        double dval;
-        uint64_t ival64;
-    } u;
-    u.ival64 = (static_cast<uint64_t>(hi) << 32) | lo;
-    return u.dval;
+    uint64_t value = (static_cast<uint64_t>(hi) << 32) | lo;
+    return bitwise_cast<double>(value);
 }
 
-static void Double2Ints(double val, uint32_t& lo, uint32_t& hi)
+static void double2Ints(double val, CLoopRegister& lo, CLoopRegister& hi)
 {
-    union {
-        double dval;
-        uint64_t ival64;
-    } u;
-    u.dval = val;
-    hi = static_cast<uint32_t>(u.ival64 >> 32);
-    lo = static_cast<uint32_t>(u.ival64);
+    uint64_t value = bitwise_cast<uint64_t>(val);
+    hi = static_cast<uint32_t>(value >> 32);
+    lo = static_cast<uint32_t>(value);
 }
 #endif // USE(JSVALUE32_64)
 
+static void decodeResult(SlowPathReturnType result, CLoopRegister& t0, CLoopRegister& t1)
+{
+    const void* t0Result;
+    const void* t1Result;
+    JSC::decodeResult(result, t0Result, t1Result);
+    t0 = t0Result;
+    t1 = t1Result;
+}
+
 } // namespace LLint
 
-
 //============================================================================
-// CLoopRegister is the storage for an emulated CPU register.
-// It defines the policy of how ints smaller than intptr_t are packed into the
-// pseudo register, as well as hides endianness differences.
-
-struct CLoopRegister {
-    CLoopRegister() { i = static_cast<intptr_t>(0xbadbeef0baddbeef); }
-    union {
-        intptr_t i;
-        uintptr_t u;
-#if USE(JSVALUE64)
-#if CPU(BIG_ENDIAN)
-        struct {
-            int32_t i32padding;
-            int32_t i32;
-        };
-        struct {
-            uint32_t u32padding;
-            uint32_t u32;
-        };
-        struct {
-            int8_t i8padding[7];
-            int8_t i8;
-        };
-        struct {
-            uint8_t u8padding[7];
-            uint8_t u8;
-        };
-#else // !CPU(BIG_ENDIAN)
-        struct {
-            int32_t i32;
-            int32_t i32padding;
-        };
-        struct {
-            uint32_t u32;
-            uint32_t u32padding;
-        };
-        struct {
-            int8_t i8;
-            int8_t i8padding[7];
-        };
-        struct {
-            uint8_t u8;
-            uint8_t u8padding[7];
-        };
-#endif // !CPU(BIG_ENDIAN)
-#else // !USE(JSVALUE64)
-        int32_t i32;
-        uint32_t u32;
-
-#if CPU(BIG_ENDIAN)
-        struct {
-            int8_t i8padding[3];
-            int8_t i8;
-        };
-        struct {
-            uint8_t u8padding[3];
-            uint8_t u8;
-        };
-
-#else // !CPU(BIG_ENDIAN)
-        struct {
-            int8_t i8;
-            int8_t i8padding[3];
-        };
-        struct {
-            uint8_t u8;
-            uint8_t u8padding[3];
-        };
-#endif // !CPU(BIG_ENDIAN)
-#endif // !USE(JSVALUE64)
-
-        intptr_t* ip;
-        int8_t* i8p;
-        void* vp;
-        const void* cvp;
-        CallFrame* callFrame;
-        ExecState* execState;
-        const void* instruction;
-        VM* vm;
-        JSCell* cell;
-        ProtoCallFrame* protoCallFrame;
-        NativeFunction nativeFunc;
-#if USE(JSVALUE64)
-        int64_t i64;
-        uint64_t u64;
-        EncodedJSValue encodedJSValue;
-        double castToDouble;
-#endif
-        Opcode opcode;
-    };
-
-    operator ExecState*() { return execState; }
-    operator const Instruction*() { return reinterpret_cast<const Instruction*>(instruction); }
-    operator VM*() { return vm; }
-    operator ProtoCallFrame*() { return protoCallFrame; }
-    operator Register*() { return reinterpret_cast<Register*>(vp); }
-    operator JSCell*() { return cell; }
-
-#if USE(JSVALUE64)
-    inline void clearHighWord() { i32padding = 0; }
-#else
-    inline void clearHighWord() { }
-#endif
-};
-
-//============================================================================
 // The llint C++ interpreter loop:
 //
 
 JSValue CLoop::execute(OpcodeID entryOpcodeID, void* executableAddress, VM* vm, ProtoCallFrame* protoCallFrame, bool isInitializationPass)
 {
-    #define CAST reinterpret_cast
-    #define SIGN_BIT32(x) ((x) & 0x80000000)
+#define CAST bitwise_cast
 
     // One-time initialization of our address tables. We have to put this code
     // here because our labels are only in scope inside this function. The
@@ -317,13 +287,6 @@
     // Define the pseudo registers used by the LLINT C Loop backend:
     ASSERT(sizeof(CLoopRegister) == sizeof(intptr_t));
 
-    union CLoopDoubleRegister {
-        double d;
-#if USE(JSVALUE64)
-        int64_t castToInt64;
-#endif
-    };
-
     // The CLoop llint backend is initially based on the ARMv7 backend, and
     // then further enhanced with a few instructions from the x86 backend to
     // support building for X64 targets. Hence, the shape of the generated
@@ -348,7 +311,7 @@
     // 2. 32 bit result values will be in the low 32-bit of t0.
     // 3. 64 bit result values will be in t0.
 
-    CLoopRegister t0, t1, t2, t3, t5, t7, sp, cfr, lr, pc;
+    CLoopRegister t0, t1, t2, t3, t5, sp, cfr, lr, pc;
 #if USE(JSVALUE64)
     CLoopRegister pcBase, tagTypeNumber, tagMask;
 #endif
@@ -374,24 +337,24 @@
     CLoopStack& cloopStack = vm->interpreter->cloopStack();
     StackPointerScope stackPointerScope(cloopStack);
 
-    lr.opcode = getOpcode(llint_return_to_host);
-    sp.vp = cloopStack.currentStackPointer();
-    cfr.callFrame = vm->topCallFrame;
+    lr = getOpcode(llint_return_to_host);
+    sp = cloopStack.currentStackPointer();
+    cfr = vm->topCallFrame;
 #ifndef NDEBUG
-    void* startSP = sp.vp;
-    CallFrame* startCFR = cfr.callFrame;
+    void* startSP = sp.vp();
+    CallFrame* startCFR = cfr.callFrame();
 #endif
 
     // Initialize the incoming args for doVMEntryToJavaScript:
-    t0.vp = executableAddress;
-    t1.vm = vm;
-    t2.protoCallFrame = protoCallFrame;
+    t0 = executableAddress;
+    t1 = vm;
+    t2 = protoCallFrame;
 
 #if USE(JSVALUE64)
     // For the ASM llint, JITStubs takes care of this initialization. We do
     // it explicitly here for the C loop:
-    tagTypeNumber.i = 0xFFFF000000000000;
-    tagMask.i = 0xFFFF000000000002;
+    tagTypeNumber = 0xFFFF000000000000;
+    tagMask = 0xFFFF000000000002;
 #endif // USE(JSVALUE64)
 
     // Interpreter variables for value passing between opcodes and/or helpers:
@@ -401,14 +364,14 @@
 
 #define PUSH(cloopReg) \
     do { \
-        sp.ip--; \
-        *sp.ip = cloopReg.i; \
+        sp = sp.ip() - 1; \
+        *sp.ip() = cloopReg.i(); \
     } while (false)
 
 #define POP(cloopReg) \
     do { \
-        cloopReg.i = *sp.ip; \
-        sp.ip++; \
+        cloopReg = *sp.ip(); \
+        sp = sp.ip() + 1; \
     } while (false)
 
 #if ENABLE(OPCODE_STATS)
@@ -473,12 +436,12 @@
 
         OFFLINE_ASM_GLUE_LABEL(llint_return_to_host)
         {
-            ASSERT(startSP == sp.vp);
-            ASSERT(startCFR == cfr.callFrame);
+            ASSERT(startSP == sp.vp());
+            ASSERT(startCFR == cfr.callFrame());
 #if USE(JSVALUE32_64)
-            return JSValue(t1.i, t0.i); // returning JSValue(tag, payload);
+            return JSValue(t1.i(), t0.i()); // returning JSValue(tag, payload);
 #else
-            return JSValue::decode(t0.encodedJSValue);
+            return JSValue::decode(t0.encodedJSValue());
 #endif
         }
 
@@ -490,12 +453,12 @@
             // The part in getHostCallReturnValueWithExecState():
             JSValue result = vm->hostCallReturnValue;
 #if USE(JSVALUE32_64)
-            t1.i = result.tag();
-            t0.i = result.payload();
+            t1 = result.tag();
+            t0 = result.payload();
 #else
-            t0.encodedJSValue = JSValue::encode(result);
+            t0 = JSValue::encode(result);
 #endif
-            opcode = lr.opcode;
+            opcode = lr.opcode();
             DISPATCH_OPCODE();
         }
 
@@ -523,7 +486,6 @@
     #undef DEFINE_OPCODE
     #undef CHECK_FOR_TIMEOUT
     #undef CAST
-    #undef SIGN_BIT32
 
     return JSValue(); // to suppress a compiler warning.
 } // Interpreter::llintCLoopExecute()

Modified: branches/safari-607-branch/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (240500 => 240501)


--- branches/safari-607-branch/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2019-01-25 21:40:11 UTC (rev 240500)
+++ branches/safari-607-branch/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2019-01-25 21:43:10 UTC (rev 240501)
@@ -470,7 +470,7 @@
     .constant:
         loadp CodeBlock[cfr], tag
         loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
-        subp FirstConstantRegisterIndex, index
+        subi FirstConstantRegisterIndex, index
         loadp TagOffset[tag, index, 8], tag
     .done:
     end)
@@ -486,7 +486,7 @@
     .constant:
         loadp CodeBlock[cfr], tag
         loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
-        subp FirstConstantRegisterIndex, index
+        subi FirstConstantRegisterIndex, index
         lshifti 3, index
         addp index, tag
         loadp PayloadOffset[tag], payload

Modified: branches/safari-607-branch/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (240500 => 240501)


--- branches/safari-607-branch/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2019-01-25 21:40:11 UTC (rev 240500)
+++ branches/safari-607-branch/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2019-01-25 21:43:10 UTC (rev 240501)
@@ -1976,6 +1976,7 @@
     restoreStackPointerAfterCall()
 
     loadp CodeBlock[cfr], PB
+    loadp CodeBlock::m_metadata[PB], metadataTable
     loadp CodeBlock::m_instructionsRawPointer[PB], PB
     unpoison(_g_CodeBlockPoison, PB, t2)
     loadp VM::targetInterpreterPCForThrow[t3], PC

Modified: branches/safari-607-branch/Source/_javascript_Core/offlineasm/cloop.rb (240500 => 240501)


--- branches/safari-607-branch/Source/_javascript_Core/offlineasm/cloop.rb	2019-01-25 21:40:11 UTC (rev 240500)
+++ branches/safari-607-branch/Source/_javascript_Core/offlineasm/cloop.rb	2019-01-25 21:43:10 UTC (rev 240501)
@@ -33,21 +33,21 @@
 
 def cloopMapType(type)
     case type
-    when :int;            ".i"
-    when :uint;           ".u"
-    when :int32;          ".i32"
-    when :uint32;         ".u32"
-    when :int64;          ".i64"
-    when :uint64;         ".u64"
-    when :int8;           ".i8"
-    when :uint8;          ".u8"
-    when :int8Ptr;        ".i8p"
-    when :voidPtr;        ".vp"
-    when :nativeFunc;     ".nativeFunc"
-    when :double;         ".d"
-    when :castToDouble;   ".castToDouble"
-    when :castToInt64;    ".castToInt64"
-    when :opcode;         ".opcode"
+    when :int;            ".i()"
+    when :uint;           ".u()"
+    when :int32;          ".i32()"
+    when :uint32;         ".u32()"
+    when :int64;          ".i64()"
+    when :uint64;         ".u64()"
+    when :int8;           ".i8()"
+    when :uint8;          ".u8()"
+    when :int8Ptr;        ".i8p()"
+    when :voidPtr;        ".vp()"
+    when :nativeFunc;     ".nativeFunc()"
+    when :double;         ".d()"
+    when :bitsAsDouble;   ".bitsAsDouble()"
+    when :bitsAsInt64;    ".bitsAsInt64()"
+    when :opcode;         ".opcode()"
     else;
         raise "Unsupported type"
     end
@@ -55,6 +55,9 @@
 
 
 class SpecialRegister < NoChildren
+    def clLValue(type=:int)
+        clDump
+    end
     def clDump
         @name
     end
@@ -100,6 +103,9 @@
             raise "Bad register #{name} for C_LOOP at #{codeOriginString}"
         end
     end
+    def clLValue(type=:int)
+        clDump
+    end
     def clValue(type=:int)
         clDump + cloopMapType(type)
     end
@@ -124,6 +130,9 @@
             raise "Bad register #{name} for C_LOOP at #{codeOriginString}"
         end
     end
+    def clLValue(type=:int)
+        clDump
+    end
     def clValue(type=:int)
         clDump + cloopMapType(type)
     end
@@ -133,6 +142,9 @@
     def clDump
         "#{value}"
     end
+    def clLValue(type=:int)
+        raise "Immediate cannot be used as an LValue"
+    end
     def clValue(type=:int)
         # There is a case of a very large unsigned number (0x8000000000000000)
         # which we wish to encode.  Unfortunately, the C/C++ compiler
@@ -165,6 +177,9 @@
     def clDump
         "[#{base.clDump}, #{offset.value}]"
     end
+    def clLValue(type=:int)
+        clValue(type)
+    end
     def clValue(type=:int)
         case type
         when :int8;         int8MemRef
@@ -235,6 +250,9 @@
     def clDump
         "[#{base.clDump}, #{offset.clDump}, #{index.clDump} << #{scaleShift}]"
     end
+    def clLValue(type=:int)
+        clValue(type)
+    end
     def clValue(type=:int)
         case type
         when :int8;       int8MemRef
@@ -299,6 +317,9 @@
     def clDump
         "#{codeOriginString}"
     end
+    def clLValue(type=:int)
+        clValue(type)
+    end
     def clValue
         clDump
     end
@@ -309,7 +330,7 @@
         "*CAST<intptr_t*>(&#{cLabel})"
     end
     def cloopEmitLea(destination, type)
-        $asm.putc "#{destination.clValue(:voidPtr)} = CAST<void*>(&#{cLabel});"
+        $asm.putc "#{destination.clLValue(:voidPtr)} = CAST<void*>(&#{cLabel});"
     end
 end
 
@@ -321,9 +342,9 @@
 class Address
     def cloopEmitLea(destination, type)
         if destination == base
-            $asm.putc "#{destination.clValue(:int8Ptr)} += #{offset.clValue(type)};"
+            $asm.putc "#{destination.clLValue(:int8Ptr)} += #{offset.clValue(type)};"
         else
-            $asm.putc "#{destination.clValue(:int8Ptr)} = #{base.clValue(:int8Ptr)} + #{offset.clValue(type)};"
+            $asm.putc "#{destination.clLValue(:int8Ptr)} = #{base.clValue(:int8Ptr)} + #{offset.clValue(type)};"
         end
     end
 end
@@ -331,7 +352,7 @@
 class BaseIndex
     def cloopEmitLea(destination, type)
         raise "Malformed BaseIndex, offset should be zero at #{codeOriginString}" unless offset.value == 0
-        $asm.putc "#{destination.clValue(:int8Ptr)} = #{base.clValue(:int8Ptr)} + (#{index.clValue} << #{scaleShift});"
+        $asm.putc "#{destination.clLValue(:int8Ptr)} = #{base.clValue(:int8Ptr)} + (#{index.clValue} << #{scaleShift});"
     end
 end
 
@@ -367,35 +388,45 @@
     raise unless type == :int || type == :uint || type == :int32 || type == :uint32 || \
         type == :int64 || type == :uint64 || type == :double
     if operands.size == 3
-        $asm.putc "#{operands[2].clValue(type)} = #{operands[0].clValue(type)} #{operator} #{operands[1].clValue(type)};"
-        if operands[2].is_a? RegisterID and (type == :int32 or type == :uint32)
-            $asm.putc "#{operands[2].clDump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
-        end
+        op1 = operands[0]
+        op2 = operands[1]
+        dst = operands[2]
     else
         raise unless operands.size == 2
-        raise unless not operands[1].is_a? Immediate
-        $asm.putc "#{operands[1].clValue(type)} = #{operands[1].clValue(type)} #{operator} #{operands[0].clValue(type)};"
-        if operands[1].is_a? RegisterID and (type == :int32 or type == :uint32)
-            $asm.putc "#{operands[1].clDump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
-        end
+        op1 = operands[1]
+        op2 = operands[0]
+        dst = operands[1]
     end
+    raise unless not dst.is_a? Immediate
+    if dst.is_a? RegisterID and (type == :int32 or type == :uint32)
+        truncationHeader = "(uint32_t)("
+        truncationFooter = ")"
+    else
+        truncationHeader = ""
+        truncationFooter = ""
+    end
+    $asm.putc "#{dst.clLValue(type)} = #{truncationHeader}#{op1.clValue(type)} #{operator} #{op2.clValue(type)}#{truncationFooter};"
 end
 
 def cloopEmitShiftOperation(operands, type, operator)
     raise unless type == :int || type == :uint || type == :int32 || type == :uint32 || type == :int64 || type == :uint64
     if operands.size == 3
-        $asm.putc "#{operands[2].clValue(type)} = #{operands[1].clValue(type)} #{operator} (#{operands[0].clValue(:int)} & 0x1f);"
-        if operands[2].is_a? RegisterID and (type == :int32 or type == :uint32)
-            $asm.putc "#{operands[2].clDump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
-        end
+        op1 = operands[0]
+        op2 = operands[1]
+        dst = operands[2]
     else
-        raise unless operands.size == 2
-        raise unless not operands[1].is_a? Immediate
-        $asm.putc "#{operands[1].clValue(type)} = #{operands[1].clValue(type)} #{operator} (#{operands[0].clValue(:int)} & 0x1f);"
-        if operands[1].is_a? RegisterID and (type == :int32 or type == :uint32)
-            $asm.putc "#{operands[1].clDump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
-        end
+        op1 = operands[1]
+        op2 = operands[0]
+        dst = operands[1]
     end
+    if dst.is_a? RegisterID and (type == :int32 or type == :uint32)
+        truncationHeader = "(uint32_t)("
+        truncationFooter = ")"
+    else
+        truncationHeader = ""
+        truncationFooter = ""
+    end
+    $asm.putc "#{dst.clLValue(type)} = #{truncationHeader}#{operands[1].clValue(type)} #{operator} (#{operands[0].clValue(:int)} & 0x1f)#{truncationFooter};"
 end
 
 def cloopEmitUnaryOperation(operands, type, operator)
@@ -402,10 +433,16 @@
     raise unless type == :int || type == :uint || type == :int32 || type == :uint32 || type == :int64 || type == :uint64
     raise unless operands.size == 1
     raise unless not operands[0].is_a? Immediate
-    $asm.putc "#{operands[0].clValue(type)} = #{operator}#{operands[0].clValue(type)};"
-    if operands[0].is_a? RegisterID and (type == :int32 or type == :uint32)
-        $asm.putc "#{operands[0].clDump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
+    op = operands[0]
+    dst = operands[0]
+    if dst.is_a? RegisterID and (type == :int32 or type == :uint32)
+        truncationHeader = "(uint32_t)("
+        truncationFooter = ")"
+    else
+        truncationHeader = ""
+        truncationFooter = ""
     end
+    $asm.putc "#{dst.clLValue(type)} = #{truncationHeader}#{operator}#{op.clValue(type)}#{truncationFooter};"
 end
 
 def cloopEmitCompareDoubleWithNaNCheckAndBranch(operands, condition)
@@ -418,7 +455,7 @@
 def cloopEmitCompareAndSet(operands, type, comparator)
     # The result is a boolean.  Hence, it doesn't need to be based on the type
     # of the arguments being compared.
-    $asm.putc "#{operands[2].clValue} = (#{operands[0].clValue(type)} #{comparator} #{operands[1].clValue(type)});"
+    $asm.putc "#{operands[2].clLValue(type)} = (#{operands[0].clValue(type)} #{comparator} #{operands[1].clValue(type)});"
 end
 
 
@@ -459,7 +496,7 @@
     # int.  The passed in type is only used for the values being tested in
     # the condition test.
     conditionExpr = cloopGenerateConditionExpression(operands, type, conditionTest)
-    $asm.putc "#{operands[-1].clValue} = (#{conditionExpr});"
+    $asm.putc "#{operands[-1].clLValue} = (#{conditionExpr});"
 end
 
 def cloopEmitOpAndBranch(operands, operator, type, conditionTest)
@@ -471,12 +508,9 @@
         raise "Unimplemented type"
     end
 
-    op1 = operands[0].clValue(type)
-    op2 = operands[1].clValue(type)
-
     $asm.putc "{"
-    $asm.putc "    #{tempType} temp = #{op2} #{operator} #{op1};"
-    $asm.putc "    #{op2} = temp;"
+    $asm.putc "    #{tempType} temp = #{operands[1].clValue(type)} #{operator} #{operands[0].clValue(type)};"
+    $asm.putc "    #{operands[1].clLValue(type)} = temp;"
     $asm.putc "    if (temp #{conditionTest})"
     $asm.putc "        goto  #{operands[2].cLabel};"
     $asm.putc "}"
@@ -486,6 +520,8 @@
     case type
     when :int32
         tempType = "int32_t"
+        truncationHeader = "(uint32_t)("
+        truncationFooter = ")"
     else
         raise "Unimplemented type"
     end
@@ -501,7 +537,10 @@
         raise "Unimplemented opeartor"
     end
 
-    $asm.putc "    if (!WTF::ArithmeticOperations<#{tempType}, #{tempType}, #{tempType}>::#{operation}(#{operands[1].clValue(type)}, #{operands[0].clValue(type)}, #{operands[1].clValue(type)}))"
+    $asm.putc "    #{tempType} result;"
+    $asm.putc "    bool success = WTF::ArithmeticOperations<#{tempType}, #{tempType}, #{tempType}>::#{operation}(#{operands[1].clValue(type)}, #{operands[0].clValue(type)}, result);"
+    $asm.putc "    #{operands[1].clLValue(type)} = #{truncationHeader}result#{truncationFooter};"
+    $asm.putc "    if (!success)"
     $asm.putc "        goto #{operands[2].cLabel};"
     $asm.putc "}"
 end
@@ -509,14 +548,14 @@
 # operands: callTarget, currentFrame, currentPC
 def cloopEmitCallSlowPath(operands)
     $asm.putc "{"
-    $asm.putc "    cloopStack.setCurrentStackPointer(sp.vp);"
+    $asm.putc "    cloopStack.setCurrentStackPointer(sp.vp());"
     $asm.putc "    SlowPathReturnType result = #{operands[0].cLabel}(#{operands[1].clDump}, #{operands[2].clDump});"
-    $asm.putc "    decodeResult(result, t0.cvp, t1.cvp);"
+    $asm.putc "    decodeResult(result, t0, t1);"
     $asm.putc "}"
 end
 
 def cloopEmitCallSlowPathVoid(operands)
-    $asm.putc "cloopStack.setCurrentStackPointer(sp.vp);"
+    $asm.putc "cloopStack.setCurrentStackPointer(sp.vp());"
     $asm.putc "#{operands[0].cLabel}(#{operands[1].clDump}, #{operands[2].clDump});"
 end
 
@@ -597,15 +636,15 @@
             cloopEmitUnaryOperation(operands, :int32, "~")
 
         when "loadi"
-            $asm.putc "#{operands[1].clValue(:uint)} = #{operands[0].uint32MemRef};"
+            $asm.putc "#{operands[1].clLValue(:uint32)} = #{operands[0].uint32MemRef};"
             # There's no need to call clearHighWord() here because the above will
             # automatically take care of 0 extension.
         when "loadis"
-            $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].int32MemRef};"
+            $asm.putc "#{operands[1].clLValue(:int32)} = #{operands[0].int32MemRef};"
         when "loadq"
-            $asm.putc "#{operands[1].clValue(:int64)} = #{operands[0].int64MemRef};"
+            $asm.putc "#{operands[1].clLValue(:int64)} = #{operands[0].int64MemRef};"
         when "loadp"
-            $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].intMemRef};"
+            $asm.putc "#{operands[1].clLValue} = #{operands[0].intMemRef};"
         when "storei"
             $asm.putc "#{operands[1].int32MemRef} = #{operands[0].clValue(:int32)};"
         when "storeq"
@@ -613,19 +652,21 @@
         when "storep"
             $asm.putc "#{operands[1].intMemRef} = #{operands[0].clValue(:int)};"
         when "loadb"
-            $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].uint8MemRef};"
-        when "loadbs", "loadbsp"
-            $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].int8MemRef};"
+            $asm.putc "#{operands[1].clLValue(:int)} = #{operands[0].uint8MemRef};"
+        when "loadbs"
+            $asm.putc "#{operands[1].clLValue(:int)} = (uint32_t)(#{operands[0].int8MemRef});"
+        when "loadbsp"
+            $asm.putc "#{operands[1].clLValue(:int)} = #{operands[0].int8MemRef};"
         when "storeb"
             $asm.putc "#{operands[1].uint8MemRef} = #{operands[0].clValue(:int8)};"
         when "loadh"
-            $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].uint16MemRef};"
+            $asm.putc "#{operands[1].clLValue(:int)} = #{operands[0].uint16MemRef};"
         when "loadhs"
-            $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].int16MemRef};"
+            $asm.putc "#{operands[1].clLValue(:int)} = (uint32_t)(#{operands[0].int16MemRef});"
         when "storeh"
             $asm.putc "*#{operands[1].uint16MemRef} = #{operands[0].clValue(:int16)};"
         when "loadd"
-            $asm.putc "#{operands[1].clValue(:double)} = #{operands[0].dblMemRef};"
+            $asm.putc "#{operands[1].clLValue(:double)} = #{operands[0].dblMemRef};"
         when "stored"
             $asm.putc "#{operands[1].dblMemRef} = #{operands[0].clValue(:double)};"
 
@@ -640,8 +681,8 @@
 
         # Convert an int value to its double equivalent, and store it in a double register.
         when "ci2d"
-            $asm.putc "#{operands[1].clValue(:double)} = #{operands[0].clValue(:int32)};"
-            
+            $asm.putc "#{operands[1].clLValue(:double)} = (double)#{operands[0].clValue(:int32)}; // ci2d"
+
         when "bdeq"
             cloopEmitCompareAndBranch(operands, :double, "==")
         when "bdneq"
@@ -669,25 +710,23 @@
             cloopEmitCompareDoubleWithNaNCheckAndBranch(operands, "<=")
 
         when "td2i"
-            $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].clValue(:double)};"
-            $asm.putc "#{operands[1].clDump}.clearHighWord();"
+            $asm.putc "#{operands[1].clLValue(:int)} = (uint32_t)(intptr_t)#{operands[0].clValue(:double)}; // td2i"
 
         when "bcd2i"  # operands: srcDbl dstInt slowPath
-            $asm.putc "{"
+            $asm.putc "{ // bcd2i"
             $asm.putc "    double d = #{operands[0].clValue(:double)};"
             $asm.putc "    const int32_t asInt32 = int32_t(d);"
             $asm.putc "    if (asInt32 != d || (!asInt32 && std::signbit(d))) // true for -0.0"
             $asm.putc "        goto  #{operands[2].cLabel};"
-            $asm.putc "    #{operands[1].clValue} = asInt32;"            
-            $asm.putc "    #{operands[1].clDump}.clearHighWord();"
+            $asm.putc "    #{operands[1].clLValue} = (uint32_t)asInt32;"
             $asm.putc "}"
 
         when "move"
-            $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].clValue(:int)};"
+            $asm.putc "#{operands[1].clLValue(:int)} = #{operands[0].clValue(:int)};"
         when "sxi2q"
-            $asm.putc "#{operands[1].clValue(:int64)} = #{operands[0].clValue(:int32)};"
+            $asm.putc "#{operands[1].clLValue(:int64)} = #{operands[0].clValue(:int32)};"
         when "zxi2q"
-            $asm.putc "#{operands[1].clValue(:uint64)} = #{operands[0].clValue(:uint32)};"
+            $asm.putc "#{operands[1].clLValue(:uint64)} = #{operands[0].clValue(:uint32)};"
         when "nop"
             $asm.putc "// nop"
         when "bbeq"
@@ -831,7 +870,7 @@
         when "break"
             $asm.putc "CRASH(); // break instruction not implemented."
         when "ret"
-            $asm.putc "opcode = lr.opcode;"
+            $asm.putc "opcode = lr.opcode();"
             $asm.putc "DISPATCH_OPCODE();"
 
         when "cbeq"
@@ -955,12 +994,10 @@
         # Sign extends the lower 32 bits of t0, but put the sign extension into
         # the lower 32 bits of t1. Leave the upper 32 bits of t0 and t1 unchanged.
         when "cdqi"
-            $asm.putc "{"
-            $asm.putc "    int64_t temp = t0.i32; // sign extend the low 32bit"
-            $asm.putc "    t0.i32 = temp; // low word"
-            $asm.putc "    t0.clearHighWord();"
-            $asm.putc "    t1.i32 = uint64_t(temp) >> 32; // high word"
-            $asm.putc "    t1.clearHighWord();"
+            $asm.putc "{ // cdqi"
+            $asm.putc "    int64_t temp = t0.i32(); // sign extend the low 32bit"
+            $asm.putc "    t0 = (uint32_t)temp; // low word"
+            $asm.putc "    t1 = (uint32_t)(temp >> 32); // high word"
             $asm.putc "}"
 
         # 64-bit instruction: idivi op1 (based on X64)
@@ -976,34 +1013,32 @@
         when "idivi"
             # Divide t1,t0 (EDX,EAX) by the specified arg, and store the remainder in t1,
             # and quotient in t0:
-            $asm.putc "{"
-            $asm.putc "    int64_t dividend = (int64_t(t1.u32) << 32) | t0.u32;"
+            $asm.putc "{ // idivi"
+            $asm.putc "    int64_t dividend = (int64_t(t1.u32()) << 32) | t0.u32();"
             $asm.putc "    int64_t divisor = #{operands[0].clValue(:int)};"
-            $asm.putc "    t1.i32 = dividend % divisor; // remainder"
-            $asm.putc "    t1.clearHighWord();"
-            $asm.putc "    t0.i32 = dividend / divisor; // quotient"
-            $asm.putc "    t0.clearHighWord();"
+            $asm.putc "    t1 = (uint32_t)(dividend % divisor); // remainder"
+            $asm.putc "    t0 = (uint32_t)(dividend / divisor); // quotient"
             $asm.putc "}"
 
         # 32-bit instruction: fii2d int32LoOp int32HiOp dblOp (based on ARMv7)
         # Decode 2 32-bit ints (low and high) into a 64-bit double.
         when "fii2d"
-            $asm.putc "#{operands[2].clValue(:double)} = Ints2Double(#{operands[0].clValue(:uint32)}, #{operands[1].clValue(:uint32)});"
+            $asm.putc "#{operands[2].clLValue(:double)} = ints2Double(#{operands[0].clValue(:uint32)}, #{operands[1].clValue(:uint32)}); // fii2d"
 
         # 32-bit instruction: f2dii dblOp int32LoOp int32HiOp (based on ARMv7)
         # Encode a 64-bit double into 2 32-bit ints (low and high).
         when "fd2ii"
-            $asm.putc "Double2Ints(#{operands[0].clValue(:double)}, #{operands[1].clValue(:uint32)}, #{operands[2].clValue(:uint32)});"
+            $asm.putc "double2Ints(#{operands[0].clValue(:double)}, #{operands[1].clDump}, #{operands[2].clDump}); // fd2ii"
 
         # 64-bit instruction: fq2d int64Op dblOp (based on X64)
         # Copy a bit-encoded double in a 64-bit int register to a double register.
         when "fq2d"
-            $asm.putc "#{operands[1].clValue(:double)} = #{operands[0].clValue(:castToDouble)};"
+            $asm.putc "#{operands[1].clLValue(:double)} = #{operands[0].clValue(:bitsAsDouble)}; // fq2d"
 
         # 64-bit instruction: fd2q dblOp int64Op (based on X64 instruction set)
         # Copy a double as a bit-encoded double into a 64-bit int register.
         when "fd2q"
-            $asm.putc "#{operands[1].clValue(:int64)} = #{operands[0].clValue(:castToInt64)};"
+            $asm.putc "#{operands[1].clLValue(:int64)} = #{operands[0].clValue(:bitsAsInt64)}; // fd2q"
 
         when "leai"
             operands[0].cloopEmitLea(operands[1], :int32)
@@ -1079,7 +1114,7 @@
         # as an opcode dispatch.
         when "cloopCallJSFunction"
             uid = $asm.newUID
-            $asm.putc "lr.opcode = getOpcode(llint_cloop_did_return_from_js_#{uid});"
+            $asm.putc "lr = getOpcode(llint_cloop_did_return_from_js_#{uid});"
             $asm.putc "opcode = #{operands[0].clValue(:opcode)};"
             $asm.putc "DISPATCH_OPCODE();"
             $asm.putsLabel("llint_cloop_did_return_from_js_#{uid}", false)
@@ -1088,15 +1123,15 @@
         # fortunately we don't have to here. All native function calls always
         # have a fixed prototype of 1 args: the passed ExecState.
         when "cloopCallNative"
-            $asm.putc "cloopStack.setCurrentStackPointer(sp.vp);"
+            $asm.putc "cloopStack.setCurrentStackPointer(sp.vp());"
             $asm.putc "nativeFunc = #{operands[0].clValue(:nativeFunc)};"
-            $asm.putc "functionReturnValue = JSValue::decode(nativeFunc(t0.execState));"
+            $asm.putc "functionReturnValue = JSValue::decode(nativeFunc(t0.execState()));"
             $asm.putc "#if USE(JSVALUE32_64)"
-            $asm.putc "    t1.i = functionReturnValue.tag();"
-            $asm.putc "    t0.i = functionReturnValue.payload();"
+            $asm.putc "    t1 = functionReturnValue.tag();"
+            $asm.putc "    t0 = functionReturnValue.payload();"
             $asm.putc "#else // USE_JSVALUE64)"
-            $asm.putc "    t0.encodedJSValue = JSValue::encode(functionReturnValue);"
-            $asm.putc "#endif // USE_JSVALUE64)"            
+            $asm.putc "    t0 = JSValue::encode(functionReturnValue);"
+            $asm.putc "#endif // USE_JSVALUE64)"
 
         # We can't do generic function calls with an arbitrary set of args, but
         # fortunately we don't have to here. All slow path function calls always
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to