Changeset 239940 in webkit


Ignore:
Timestamp:
Jan 14, 2019 1:34:47 PM (5 years ago)
Author:
mark.lam@apple.com
Message:

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.

JSTests:

  • 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/JavaScriptCore:

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.

  1. 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.
  1. Fix llintOpWithReturn() to use getu (instead of get) for reading OpIsCellWithType::type because it is of type JSType, which is a uint8_t.
  1. Fix llintOpWithMetadata() to use loadis for loading OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t5] because it is of type PropertyOffset, which is a signed int.
  1. 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.
  1. Fix llintOpWithMetadata() and getClosureVar() to use loadp for loading OpGetFromScope::Metadata::operand because it is of type uintptr_t.
  1. In LowLevelInterpreter64.asm:
  1. Fix llintOpWithReturn() to use getu for reading OpIsCellWithType::type because it is of type JSType, which is a uint8_t.
  1. 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.

  1. 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.

  1. Fix llintOpWithMetadata() and getClosureVar() to use loadp for loading OpGetFromScope::Metadata::operand because it is of type uintptr_t.
  1. 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.

  1. 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.

  1. 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:
Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r239882 r239940  
     12019-01-14  Mark Lam  <mark.lam@apple.com>
     2
     3        Fix all CLoop JSC test failures (including some LLInt bugs due to recent bytecode format change).
     4        https://bugs.webkit.org/show_bug.cgi?id=193402
     5        <rdar://problem/46012309>
     6
     7        Reviewed by Keith Miller.
     8
     9        * stress/regexp-compile-oom.js:
     10        - Skip this test for !$jitTests because it is tuned for stack usage when the JIT
     11          is enabled.  As a result, it will fail on cloop builds though there is no bug.
     12
    1132019-01-11  Saam barati  <sbarati@apple.com>
    214
  • trunk/JSTests/stress/regexp-compile-oom.js

    r238508 r239940  
    1 //@ skip if $hostOS != "darwin" or $architecture == "arm" or $architecture == "x86"
     1//@ skip if $hostOS != "darwin" or $architecture == "arm" or $architecture == "x86" or not $jitTests
    22// Test that throw an OOM exception when compiling a pathological, but valid nested RegExp.
    33
  • trunk/Source/JavaScriptCore/ChangeLog

    r239933 r239940  
     12019-01-14  Mark Lam  <mark.lam@apple.com>
     2
     3        Fix all CLoop JSC test failures (including some LLInt bugs due to recent bytecode format change).
     4        https://bugs.webkit.org/show_bug.cgi?id=193402
     5        <rdar://problem/46012309>
     6
     7        Reviewed by Keith Miller.
     8
     9        The CLoop builds via build-jsc were previously completely disabled after our
     10        change to enable ASM LLInt build without the JIT.  As a result, JSC tests have
     11        regressed on CLoop builds.  The CLoop builds and tests will be re-enabled when
     12        the fix for https://bugs.webkit.org/show_bug.cgi?id=192955 lands.  This patch
     13        fixes all the regressions (and some old bugs) so that the CLoop test bots won't
     14        be red when CLoop build gets re-enabled.
     15
     16        In this patch, we do the following:
     17
     18        1. Change CLoopStack::grow() to set the new CLoop stack top at the maximum
     19           allocated capacity (after discounting the reserved zone) as opposed to setting
     20           it only at the level that the client requested.
     21
     22           This fixes a small performance bug that I happened to noticed when I was
     23           debugging a stack issue.  It does not affect correctness.
     24
     25        2. In LowLevelInterpreter32_64.asm:
     26
     27           1. Fix loadConstantOrVariableTag() to use subi for computing the constant
     28              index because the VirtualRegister offset and FirstConstantRegisterIndex
     29              values it is operating on are both signed ints.  This is just to be
     30              pedantic.  The previous use of subu will still produce a correct value.
     31
     32           2. Fix llintOpWithReturn() to use getu (instead of get) for reading
     33              OpIsCellWithType::type because it is of type JSType, which is a uint8_t.
     34
     35           3. Fix llintOpWithMetadata() to use loadis for loading
     36              OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t5] because it
     37              is of type PropertyOffset, which is a signed int.
     38
     39           4. Fix commonCallOp() to use getu for loading fields argv and argc because they
     40              are  of type unsigned for OpCall, OpConstruct, and OpTailCall, which are the
     41              clients of commonCallOp.
     42
     43           5. Fix llintOpWithMetadata() and getClosureVar() to use loadp for loading
     44              OpGetFromScope::Metadata::operand because it is of type uintptr_t.
     45
     46        3. In LowLevelInterpreter64.asm:
     47
     48           1. Fix llintOpWithReturn() to use getu for reading OpIsCellWithType::type
     49              because it is of type JSType, which is a uint8_t.
     50
     51           2. Fix llintOpWithMetadata() to use loadi for loading
     52              OpGetById::Metadata::modeMetadata.protoLoadMode.structure[t2] because it is
     53              of type StructureID, which is a uint32_t.
     54
     55              Fix llintOpWithMetadata() to use loadis for loading
     56              OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t2] because it
     57              is of type PropertyOffset, which is a signed int.
     58
     59           3. commonOp() should reload the metadataTable for op_catch because unlike
     60              for the ASM LLInt, the exception unwinding code is not able to restore
     61              "callee saved registers" for the CLoop interpreter because the CLoop uses
     62              pseudo-registers (see the CLoopRegister class).
     63
     64              This was the source of many exotic Cloop failures after the bytecode format
     65              change (which introduced the metadataTable callee saved register).  Hence,
     66              we fix it by reloading metadataTable's value on re-entry via op_catch for
     67              exception handling.  We already take care of restoring it in op_ret.
     68
     69           4. Fix llintOpWithMetadata() and getClosureVar() to use loadp for loading
     70              OpGetFromScope::Metadata::operand because it is of type uintptr_t.
     71
     72        4. In LowLevelInterpreter.asm:
     73
     74           Fix metadata() to use loadi for loading metadataTable offsets because they are
     75           of type unsigned.  This was also a source of many exotic CLoop test failures.
     76
     77        5. Change CLoopRegister into a class with a uintptr_t as its storage element.
     78           Previously, we were using a union to convert between various value types that
     79           we would store in this pseudo-register.  This method of type conversion is
     80           undefined behavior according to the C++ spec.  As a result, the C++ compiler
     81           may choose to elide some CLoop statements, thereby resulting in some exotic
     82           bugs.
     83
     84           We fix this by now always using accessor methods and assignment operators to
     85           ensure that we use bitwise_cast to do the type conversions.  Since bitwise_cast
     86           uses a memcpy, this ensures that there's no undefined behavior, and that CLoop
     87           statements won't get elided willy-nilly by the compiler.
     88
     89           Ditto for the CloopDobleRegisters.
     90
     91           Similarly, use bitwise_cast for ints2Double() and double2Ints() utility
     92           functions.
     93
     94           Also use bitwise_cast (instead of reinterpret_cast) for the CLoop CAST macro.
     95
     96        6. Fix cloop.rb to use the new CLoopRegister and CLoopDoubleRegister classes.
     97
     98           Add a clLValue accessor for offlineasm operand types to distinguish
     99           LValue use of the operands from RValue uses.
     100
     101           Replace the use of clearHighWord() with simply casting to uint32_t.  This is
     102           more efficient for the C++ compiler (and help speed up debug build runs).
     103
     104           Also fix 32-bit arithmetic operations to only set the lower 32-bit value of
     105           the pseudo registers.  This fixes some CLoop JSC test failures.
     106
     107        This patch has been manually tested with the JSC tests on the following builds:
     108        64bit X86 ASM LLLint (without JIT), 64bit and 32bit X86 CLoop, and ARMv7 Cloop.
     109
     110        * interpreter/CLoopStack.cpp:
     111        (JSC::CLoopStack::grow):
     112        * llint/LowLevelInterpreter.asm:
     113        * llint/LowLevelInterpreter.cpp:
     114        (JSC::CLoopRegister::i const):
     115        (JSC::CLoopRegister::u const):
     116        (JSC::CLoopRegister::i32 const):
     117        (JSC::CLoopRegister::u32 const):
     118        (JSC::CLoopRegister::i8 const):
     119        (JSC::CLoopRegister::u8 const):
     120        (JSC::CLoopRegister::ip const):
     121        (JSC::CLoopRegister::i8p const):
     122        (JSC::CLoopRegister::vp const):
     123        (JSC::CLoopRegister::cvp const):
     124        (JSC::CLoopRegister::callFrame const):
     125        (JSC::CLoopRegister::execState const):
     126        (JSC::CLoopRegister::instruction const):
     127        (JSC::CLoopRegister::vm const):
     128        (JSC::CLoopRegister::cell const):
     129        (JSC::CLoopRegister::protoCallFrame const):
     130        (JSC::CLoopRegister::nativeFunc const):
     131        (JSC::CLoopRegister::i64 const):
     132        (JSC::CLoopRegister::u64 const):
     133        (JSC::CLoopRegister::encodedJSValue const):
     134        (JSC::CLoopRegister::opcode const):
     135        (JSC::CLoopRegister::operator ExecState*):
     136        (JSC::CLoopRegister::operator const Instruction*):
     137        (JSC::CLoopRegister::operator JSCell*):
     138        (JSC::CLoopRegister::operator ProtoCallFrame*):
     139        (JSC::CLoopRegister::operator Register*):
     140        (JSC::CLoopRegister::operator VM*):
     141        (JSC::CLoopRegister::operator=):
     142        (JSC::CLoopRegister::bitsAsDouble const):
     143        (JSC::CLoopRegister::bitsAsInt64 const):
     144        (JSC::CLoopDoubleRegister::operator T const):
     145        (JSC::CLoopDoubleRegister::d const):
     146        (JSC::CLoopDoubleRegister::bitsAsInt64 const):
     147        (JSC::CLoopDoubleRegister::operator=):
     148        (JSC::LLInt::ints2Double):
     149        (JSC::LLInt::double2Ints):
     150        (JSC::LLInt::decodeResult):
     151        (JSC::CLoop::execute):
     152        (JSC::LLInt::Ints2Double): Deleted.
     153        (JSC::LLInt::Double2Ints): Deleted.
     154        (JSC::CLoopRegister::CLoopRegister): Deleted.
     155        (JSC::CLoopRegister::clearHighWord): Deleted.
     156        * llint/LowLevelInterpreter32_64.asm:
     157        * llint/LowLevelInterpreter64.asm:
     158        * offlineasm/cloop.rb:
     159
    11602019-01-14  Keith Miller  <keith_miller@apple.com>
    2161
  • trunk/Source/JavaScriptCore/interpreter/CLoopStack.cpp

    r238595 r239940  
    104104    addToCommittedByteCount(delta);
    105105    m_commitTop = newCommitTop;
     106    newTopOfStack = m_commitTop + m_softReservedZoneSizeInRegisters;
    106107    setCLoopStackLimit(newTopOfStack);
    107108    return true;
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r238439 r239940  
    345345
    346346macro metadata(size, opcode, dst, scratch)
    347     loadp constexpr %opcode%::opcodeID * 4[metadataTable], dst # offset = metadataTable<unsigned*>[opcodeID]
     347    loadi constexpr %opcode%::opcodeID * 4[metadataTable], dst # offset = metadataTable<unsigned*>[opcodeID]
    348348    getu(size, opcode, metadataID, scratch) # scratch = bytecode.metadataID
    349349    muli sizeof %opcode%::Metadata, scratch # scratch *= sizeof(Op::Metadata)
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.cpp

    r239199 r239940  
    124124#define OFFLINE_ASM_LOCAL_LABEL(label) label: TRACE_LABEL("OFFLINE_ASM_LOCAL_LABEL", #label); USE_LABEL(label);
    125125
    126 
    127 //============================================================================
    128 // Some utilities:
    129 //
    130 
    131126namespace JSC {
    132 namespace LLInt {
    133 
    134 #if USE(JSVALUE32_64)
    135 static double Ints2Double(uint32_t lo, uint32_t hi)
    136 {
    137     union {
    138         double dval;
    139         uint64_t ival64;
    140     } u;
    141     u.ival64 = (static_cast<uint64_t>(hi) << 32) | lo;
    142     return u.dval;
    143 }
    144 
    145 static void Double2Ints(double val, uint32_t& lo, uint32_t& hi)
    146 {
    147     union {
    148         double dval;
    149         uint64_t ival64;
    150     } u;
    151     u.dval = val;
    152     hi = static_cast<uint32_t>(u.ival64 >> 32);
    153     lo = static_cast<uint32_t>(u.ival64);
    154 }
    155 #endif // USE(JSVALUE32_64)
    156 
    157 } // namespace LLint
    158 
    159127
    160128//============================================================================
     
    163131// pseudo register, as well as hides endianness differences.
    164132
    165 struct CLoopRegister {
    166     CLoopRegister() { i = static_cast<intptr_t>(0xbadbeef0baddbeef); }
    167     union {
    168         intptr_t i;
    169         uintptr_t u;
     133class CLoopRegister {
     134public:
     135    ALWAYS_INLINE intptr_t i() const { return m_value; };
     136    ALWAYS_INLINE uintptr_t u() const { return m_value; }
     137    ALWAYS_INLINE int32_t i32() const { return m_value; }
     138    ALWAYS_INLINE uint32_t u32() const { return m_value; }
     139    ALWAYS_INLINE int8_t i8() const { return m_value; }
     140    ALWAYS_INLINE uint8_t u8() const { return m_value; }
     141
     142    ALWAYS_INLINE intptr_t* ip() const { return bitwise_cast<intptr_t*>(m_value); }
     143    ALWAYS_INLINE int8_t* i8p() const { return bitwise_cast<int8_t*>(m_value); }
     144    ALWAYS_INLINE void* vp() const { return bitwise_cast<void*>(m_value); }
     145    ALWAYS_INLINE const void* cvp() const { return bitwise_cast<const void*>(m_value); }
     146    ALWAYS_INLINE CallFrame* callFrame() const { return bitwise_cast<CallFrame*>(m_value); }
     147    ALWAYS_INLINE ExecState* execState() const { return bitwise_cast<ExecState*>(m_value); }
     148    ALWAYS_INLINE const void* instruction() const { return bitwise_cast<const void*>(m_value); }
     149    ALWAYS_INLINE VM* vm() const { return bitwise_cast<VM*>(m_value); }
     150    ALWAYS_INLINE JSCell* cell() const { return bitwise_cast<JSCell*>(m_value); }
     151    ALWAYS_INLINE ProtoCallFrame* protoCallFrame() const { return bitwise_cast<ProtoCallFrame*>(m_value); }
     152    ALWAYS_INLINE NativeFunction nativeFunc() const { return bitwise_cast<NativeFunction>(m_value); }
    170153#if USE(JSVALUE64)
    171 #if CPU(BIG_ENDIAN)
    172         struct {
    173             int32_t i32padding;
    174             int32_t i32;
    175         };
    176         struct {
    177             uint32_t u32padding;
    178             uint32_t u32;
    179         };
    180         struct {
    181             int8_t i8padding[7];
    182             int8_t i8;
    183         };
    184         struct {
    185             uint8_t u8padding[7];
    186             uint8_t u8;
    187         };
    188 #else // !CPU(BIG_ENDIAN)
    189         struct {
    190             int32_t i32;
    191             int32_t i32padding;
    192         };
    193         struct {
    194             uint32_t u32;
    195             uint32_t u32padding;
    196         };
    197         struct {
    198             int8_t i8;
    199             int8_t i8padding[7];
    200         };
    201         struct {
    202             uint8_t u8;
    203             uint8_t u8padding[7];
    204         };
    205 #endif // !CPU(BIG_ENDIAN)
    206 #else // !USE(JSVALUE64)
    207         int32_t i32;
    208         uint32_t u32;
    209 
    210 #if CPU(BIG_ENDIAN)
    211         struct {
    212             int8_t i8padding[3];
    213             int8_t i8;
    214         };
    215         struct {
    216             uint8_t u8padding[3];
    217             uint8_t u8;
    218         };
    219 
    220 #else // !CPU(BIG_ENDIAN)
    221         struct {
    222             int8_t i8;
    223             int8_t i8padding[3];
    224         };
    225         struct {
    226             uint8_t u8;
    227             uint8_t u8padding[3];
    228         };
    229 #endif // !CPU(BIG_ENDIAN)
    230 #endif // !USE(JSVALUE64)
    231 
    232         intptr_t* ip;
    233         int8_t* i8p;
    234         void* vp;
    235         const void* cvp;
    236         CallFrame* callFrame;
    237         ExecState* execState;
    238         const void* instruction;
    239         VM* vm;
    240         JSCell* cell;
    241         ProtoCallFrame* protoCallFrame;
    242         NativeFunction nativeFunc;
     154    ALWAYS_INLINE int64_t i64() const { return m_value; }
     155    ALWAYS_INLINE uint64_t u64() const { return m_value; }
     156    ALWAYS_INLINE EncodedJSValue encodedJSValue() const { return bitwise_cast<EncodedJSValue>(m_value); }
     157#endif
     158    ALWAYS_INLINE Opcode opcode() const { return bitwise_cast<Opcode>(m_value); }
     159
     160    operator ExecState*() { return bitwise_cast<ExecState*>(m_value); }
     161    operator const Instruction*() { return bitwise_cast<const Instruction*>(m_value); }
     162    operator JSCell*() { return bitwise_cast<JSCell*>(m_value); }
     163    operator ProtoCallFrame*() { return bitwise_cast<ProtoCallFrame*>(m_value); }
     164    operator Register*() { return bitwise_cast<Register*>(m_value); }
     165    operator VM*() { return bitwise_cast<VM*>(m_value); }
     166
     167    template<typename T, typename = std::enable_if_t<sizeof(T) == sizeof(uintptr_t)>>
     168    ALWAYS_INLINE void operator=(T value) { m_value = bitwise_cast<uintptr_t>(value); }
    243169#if USE(JSVALUE64)
    244         int64_t i64;
    245         uint64_t u64;
    246         EncodedJSValue encodedJSValue;
    247         double castToDouble;
    248 #endif
    249         Opcode opcode;
    250     };
    251 
    252     operator ExecState*() { return execState; }
    253     operator const Instruction*() { return reinterpret_cast<const Instruction*>(instruction); }
    254     operator VM*() { return vm; }
    255     operator ProtoCallFrame*() { return protoCallFrame; }
    256     operator Register*() { return reinterpret_cast<Register*>(vp); }
    257     operator JSCell*() { return cell; }
     170    ALWAYS_INLINE void operator=(int32_t value) { m_value = static_cast<intptr_t>(value); }
     171    ALWAYS_INLINE void operator=(uint32_t value) { m_value = static_cast<uintptr_t>(value); }
     172#endif
     173    ALWAYS_INLINE void operator=(int16_t value) { m_value = static_cast<intptr_t>(value); }
     174    ALWAYS_INLINE void operator=(uint16_t value) { m_value = static_cast<uintptr_t>(value); }
     175    ALWAYS_INLINE void operator=(int8_t value) { m_value = static_cast<intptr_t>(value); }
     176    ALWAYS_INLINE void operator=(uint8_t value) { m_value = static_cast<uintptr_t>(value); }
     177    ALWAYS_INLINE void operator=(bool value) { m_value = static_cast<uintptr_t>(value); }
    258178
    259179#if USE(JSVALUE64)
    260     inline void clearHighWord() { i32padding = 0; }
    261 #else
    262     inline void clearHighWord() { }
    263 #endif
     180    ALWAYS_INLINE double bitsAsDouble() const { return bitwise_cast<double>(m_value); }
     181    ALWAYS_INLINE int64_t bitsAsInt64() const { return bitwise_cast<int64_t>(m_value); }
     182#endif
     183
     184private:
     185    uintptr_t m_value { static_cast<uintptr_t>(0xbadbeef0baddbeef) };
    264186};
     187
     188class CLoopDoubleRegister {
     189public:
     190    template<typename T>
     191    explicit operator T() const { return bitwise_cast<T>(m_value); }
     192
     193    ALWAYS_INLINE double d() const { return m_value; }
     194    ALWAYS_INLINE int64_t bitsAsInt64() const { return bitwise_cast<int64_t>(m_value); }
     195
     196    ALWAYS_INLINE void operator=(double value) { m_value = value; }
     197
     198    template<typename T, typename = std::enable_if_t<sizeof(T) == sizeof(uintptr_t) && std::is_integral<T>::value>>
     199    ALWAYS_INLINE void operator=(T value) { m_value = bitwise_cast<double>(value); }
     200
     201private:
     202    double m_value;
     203};
     204
     205//============================================================================
     206// Some utilities:
     207//
     208
     209namespace LLInt {
     210
     211#if USE(JSVALUE32_64)
     212static double ints2Double(uint32_t lo, uint32_t hi)
     213{
     214    uint64_t value = (static_cast<uint64_t>(hi) << 32) | lo;
     215    return bitwise_cast<double>(value);
     216}
     217
     218static void double2Ints(double val, CLoopRegister& lo, CLoopRegister& hi)
     219{
     220    uint64_t value = bitwise_cast<uint64_t>(val);
     221    hi = static_cast<uint32_t>(value >> 32);
     222    lo = static_cast<uint32_t>(value);
     223}
     224#endif // USE(JSVALUE32_64)
     225
     226static void decodeResult(SlowPathReturnType result, CLoopRegister& t0, CLoopRegister& t1)
     227{
     228    const void* t0Result;
     229    const void* t1Result;
     230    JSC::decodeResult(result, t0Result, t1Result);
     231    t0 = t0Result;
     232    t1 = t1Result;
     233}
     234
     235} // namespace LLint
    265236
    266237//============================================================================
     
    270241JSValue CLoop::execute(OpcodeID entryOpcodeID, void* executableAddress, VM* vm, ProtoCallFrame* protoCallFrame, bool isInitializationPass)
    271242{
    272     #define CAST reinterpret_cast
    273     #define SIGN_BIT32(x) ((x) & 0x80000000)
     243#define CAST bitwise_cast
    274244
    275245    // One-time initialization of our address tables. We have to put this code
     
    317287    // Define the pseudo registers used by the LLINT C Loop backend:
    318288    ASSERT(sizeof(CLoopRegister) == sizeof(intptr_t));
    319 
    320     union CLoopDoubleRegister {
    321         double d;
    322 #if USE(JSVALUE64)
    323         int64_t castToInt64;
    324 #endif
    325     };
    326289
    327290    // The CLoop llint backend is initially based on the ARMv7 backend, and
     
    349312    // 3. 64 bit result values will be in t0.
    350313
    351     CLoopRegister t0, t1, t2, t3, t5, t7, sp, cfr, lr, pc;
     314    CLoopRegister t0, t1, t2, t3, t5, sp, cfr, lr, pc;
    352315#if USE(JSVALUE64)
    353316    CLoopRegister pcBase, tagTypeNumber, tagMask;
     
    375338    StackPointerScope stackPointerScope(cloopStack);
    376339
    377     lr.opcode = getOpcode(llint_return_to_host);
    378     sp.vp = cloopStack.currentStackPointer();
    379     cfr.callFrame = vm->topCallFrame;
     340    lr = getOpcode(llint_return_to_host);
     341    sp = cloopStack.currentStackPointer();
     342    cfr = vm->topCallFrame;
    380343#ifndef NDEBUG
    381     void* startSP = sp.vp;
    382     CallFrame* startCFR = cfr.callFrame;
     344    void* startSP = sp.vp();
     345    CallFrame* startCFR = cfr.callFrame();
    383346#endif
    384347
    385348    // Initialize the incoming args for doVMEntryToJavaScript:
    386     t0.vp = executableAddress;
    387     t1.vm = vm;
    388     t2.protoCallFrame = protoCallFrame;
     349    t0 = executableAddress;
     350    t1 = vm;
     351    t2 = protoCallFrame;
    389352
    390353#if USE(JSVALUE64)
    391354    // For the ASM llint, JITStubs takes care of this initialization. We do
    392355    // it explicitly here for the C loop:
    393     tagTypeNumber.i = 0xFFFF000000000000;
    394     tagMask.i = 0xFFFF000000000002;
     356    tagTypeNumber = 0xFFFF000000000000;
     357    tagMask = 0xFFFF000000000002;
    395358#endif // USE(JSVALUE64)
    396359
     
    402365#define PUSH(cloopReg) \
    403366    do { \
    404         sp.ip--; \
    405         *sp.ip = cloopReg.i; \
     367        sp = sp.ip() - 1; \
     368        *sp.ip() = cloopReg.i(); \
    406369    } while (false)
    407370
    408371#define POP(cloopReg) \
    409372    do { \
    410         cloopReg.i = *sp.ip; \
    411         sp.ip++; \
     373        cloopReg = *sp.ip(); \
     374        sp = sp.ip() + 1; \
    412375    } while (false)
    413376
     
    474437        OFFLINE_ASM_GLUE_LABEL(llint_return_to_host)
    475438        {
    476             ASSERT(startSP == sp.vp);
    477             ASSERT(startCFR == cfr.callFrame);
     439            ASSERT(startSP == sp.vp());
     440            ASSERT(startCFR == cfr.callFrame());
    478441#if USE(JSVALUE32_64)
    479             return JSValue(t1.i, t0.i); // returning JSValue(tag, payload);
    480 #else
    481             return JSValue::decode(t0.encodedJSValue);
     442            return JSValue(t1.i(), t0.i()); // returning JSValue(tag, payload);
     443#else
     444            return JSValue::decode(t0.encodedJSValue());
    482445#endif
    483446        }
     
    491454            JSValue result = vm->hostCallReturnValue;
    492455#if USE(JSVALUE32_64)
    493             t1.i = result.tag();
    494             t0.i = result.payload();
    495 #else
    496             t0.encodedJSValue = JSValue::encode(result);
    497 #endif
    498             opcode = lr.opcode;
     456            t1 = result.tag();
     457            t0 = result.payload();
     458#else
     459            t0 = JSValue::encode(result);
     460#endif
     461            opcode = lr.opcode();
    499462            DISPATCH_OPCODE();
    500463        }
     
    524487    #undef CHECK_FOR_TIMEOUT
    525488    #undef CAST
    526     #undef SIGN_BIT32
    527489
    528490    return JSValue(); // to suppress a compiler warning.
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r239867 r239940  
    471471        loadp CodeBlock[cfr], tag
    472472        loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
    473         subp FirstConstantRegisterIndex, index
     473        subi FirstConstantRegisterIndex, index
    474474        loadp TagOffset[tag, index, 8], tag
    475475    .done:
     
    487487        loadp CodeBlock[cfr], tag
    488488        loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
    489         subp FirstConstantRegisterIndex, index
     489        subi FirstConstantRegisterIndex, index
    490490        lshifti 3, index
    491491        addp index, tag
     
    12661266    loadConstantOrVariable(size, t1, t0, t3)
    12671267    bineq t0, CellTag, .notCellCase
    1268     get(type, t0)
     1268    getu(size, OpIsCellWithType, type, t0)
    12691269    cbeq JSCell::m_type[t3], t0, t1
    12701270    return(BooleanTag, t1)
     
    13521352    loadi OpGetById::Metadata::modeMetadata.protoLoadMode.structure[t5], t1
    13531353    loadConstantOrVariablePayload(size, t0, CellTag, t3, .opGetByIdSlow)
    1354     loadi OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t5], t2
     1354    loadis OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t5], t2
    13551355    bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
    13561356    loadp OpGetById::Metadata::modeMetadata.protoLoadMode.cachedSlot[t5], t3
     
    19141914        loadConstantOrVariablePayload(size, t0, CellTag, t3, .opCallSlow)
    19151915        bineq t3, t2, .opCallSlow
    1916         get(argv, t3)
     1916        getu(size, op, argv, t3)
    19171917        lshifti 3, t3
    19181918        negi t3
    19191919        addp cfr, t3  # t3 contains the new value of cfr
    19201920        storei t2, Callee + PayloadOffset[t3]
    1921         get(argc, t2)
     1921        getu(size, op, argc, t2)
    19221922        storei PC, ArgumentCount + TagOffset[cfr]
    19231923        storei t2, ArgumentCount + PayloadOffset[t3]
     
    22492249llintOpWithMetadata(op_get_from_scope, OpGetFromScope, macro (size, get, dispatch, metadata, return)
    22502250    macro getProperty()
    2251         loadis OpGetFromScope::Metadata::operand[t5], t3
     2251        loadp OpGetFromScope::Metadata::operand[t5], t3
    22522252        loadPropertyAtVariableOffset(t3, t0, t1, t2)
    22532253        valueProfile(OpGetFromScope, t5, t1, t2)
     
    22652265
    22662266    macro getClosureVar()
    2267         loadis OpGetFromScope::Metadata::operand[t5], t3
     2267        loadp OpGetFromScope::Metadata::operand[t5], t3
    22682268        loadp JSLexicalEnvironment_variables + TagOffset[t0, t3, 8], t1
    22692269        loadp JSLexicalEnvironment_variables + PayloadOffset[t0, t3, 8], t2
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r239761 r239940  
    12161216
    12171217llintOpWithReturn(op_is_cell_with_type, OpIsCellWithType, macro (size, get, dispatch, return)
    1218     get(type, t0)
     1218    getu(size, OpIsCellWithType, type, t0)
    12191219    get(operand, t1)
    12201220    loadConstantOrVariable(size, t1, t3)
     
    13031303    bbneq t1, constexpr GetByIdMode::ProtoLoad, .opGetByIdArrayLength
    13041304    loadi JSCell::m_structureID[t3], t1
    1305     loadis OpGetById::Metadata::modeMetadata.protoLoadMode.structure[t2], t3
     1305    loadi OpGetById::Metadata::modeMetadata.protoLoadMode.structure[t2], t3
    13061306    bineq t3, t1, .opGetByIdSlow
    1307     loadi OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t2], t1
     1307    loadis OpGetById::Metadata::modeMetadata.protoLoadMode.cachedOffset[t2], t1
    13081308    loadp OpGetById::Metadata::modeMetadata.protoLoadMode.cachedSlot[t2], t3
    13091309    loadPropertyAtVariableOffset(t1, t3, t0)
     
    20692069
    20702070    loadp CodeBlock[cfr], PB
     2071    loadp CodeBlock::m_metadata[PB], metadataTable
    20712072    loadp CodeBlock::m_instructionsRawPointer[PB], PB
    20722073    unpoison(_g_CodeBlockPoison, PB, t2)
     
    23122313
    23132314    macro getProperty()
    2314         loadis OpGetFromScope::Metadata::operand[t5], t1
     2315        loadp OpGetFromScope::Metadata::operand[t5], t1
    23152316        loadPropertyAtVariableOffset(t1, t0, t2)
    23162317        valueProfile(OpGetFromScope, t5, t2)
     
    23272328
    23282329    macro getClosureVar()
    2329         loadis OpGetFromScope::Metadata::operand[t5], t1
     2330        loadp OpGetFromScope::Metadata::operand[t5], t1
    23302331        loadq JSLexicalEnvironment_variables[t0, t1, 8], t0
    23312332        valueProfile(OpGetFromScope, t5, t0)
  • trunk/Source/JavaScriptCore/offlineasm/cloop.rb

    r238543 r239940  
    3434def cloopMapType(type)
    3535    case type
    36     when :int;            ".i"
    37     when :uint;           ".u"
    38     when :int32;          ".i32"
    39     when :uint32;         ".u32"
    40     when :int64;          ".i64"
    41     when :uint64;         ".u64"
    42     when :int8;           ".i8"
    43     when :uint8;          ".u8"
    44     when :int8Ptr;        ".i8p"
    45     when :voidPtr;        ".vp"
    46     when :nativeFunc;     ".nativeFunc"
    47     when :double;         ".d"
    48     when :castToDouble;   ".castToDouble"
    49     when :castToInt64;    ".castToInt64"
    50     when :opcode;         ".opcode"
     36    when :int;            ".i()"
     37    when :uint;           ".u()"
     38    when :int32;          ".i32()"
     39    when :uint32;         ".u32()"
     40    when :int64;          ".i64()"
     41    when :uint64;         ".u64()"
     42    when :int8;           ".i8()"
     43    when :uint8;          ".u8()"
     44    when :int8Ptr;        ".i8p()"
     45    when :voidPtr;        ".vp()"
     46    when :nativeFunc;     ".nativeFunc()"
     47    when :double;         ".d()"
     48    when :bitsAsDouble;   ".bitsAsDouble()"
     49    when :bitsAsInt64;    ".bitsAsInt64()"
     50    when :opcode;         ".opcode()"
    5151    else;
    5252        raise "Unsupported type"
     
    5656
    5757class SpecialRegister < NoChildren
     58    def clLValue(type=:int)
     59        clDump
     60    end
    5861    def clDump
    5962        @name
     
    101104        end
    102105    end
     106    def clLValue(type=:int)
     107        clDump
     108    end
    103109    def clValue(type=:int)
    104110        clDump + cloopMapType(type)
     
    125131        end
    126132    end
     133    def clLValue(type=:int)
     134        clDump
     135    end
    127136    def clValue(type=:int)
    128137        clDump + cloopMapType(type)
     
    133142    def clDump
    134143        "#{value}"
     144    end
     145    def clLValue(type=:int)
     146        raise "Immediate cannot be used as an LValue"
    135147    end
    136148    def clValue(type=:int)
     
    165177    def clDump
    166178        "[#{base.clDump}, #{offset.value}]"
     179    end
     180    def clLValue(type=:int)
     181        clValue(type)
    167182    end
    168183    def clValue(type=:int)
     
    236251        "[#{base.clDump}, #{offset.clDump}, #{index.clDump} << #{scaleShift}]"
    237252    end
     253    def clLValue(type=:int)
     254        clValue(type)
     255    end
    238256    def clValue(type=:int)
    239257        case type
     
    300318        "#{codeOriginString}"
    301319    end
     320    def clLValue(type=:int)
     321        clValue(type)
     322    end
    302323    def clValue
    303324        clDump
     
    310331    end
    311332    def cloopEmitLea(destination, type)
    312         $asm.putc "#{destination.clValue(:voidPtr)} = CAST<void*>(&#{cLabel});"
     333        $asm.putc "#{destination.clLValue(:voidPtr)} = CAST<void*>(&#{cLabel});"
    313334    end
    314335end
     
    322343    def cloopEmitLea(destination, type)
    323344        if destination == base
    324             $asm.putc "#{destination.clValue(:int8Ptr)} += #{offset.clValue(type)};"
     345            $asm.putc "#{destination.clLValue(:int8Ptr)} += #{offset.clValue(type)};"
    325346        else
    326             $asm.putc "#{destination.clValue(:int8Ptr)} = #{base.clValue(:int8Ptr)} + #{offset.clValue(type)};"
     347            $asm.putc "#{destination.clLValue(:int8Ptr)} = #{base.clValue(:int8Ptr)} + #{offset.clValue(type)};"
    327348        end
    328349    end
     
    332353    def cloopEmitLea(destination, type)
    333354        raise "Malformed BaseIndex, offset should be zero at #{codeOriginString}" unless offset.value == 0
    334         $asm.putc "#{destination.clValue(:int8Ptr)} = #{base.clValue(:int8Ptr)} + (#{index.clValue} << #{scaleShift});"
     355        $asm.putc "#{destination.clLValue(:int8Ptr)} = #{base.clValue(:int8Ptr)} + (#{index.clValue} << #{scaleShift});"
    335356    end
    336357end
     
    368389        type == :int64 || type == :uint64 || type == :double
    369390    if operands.size == 3
    370         $asm.putc "#{operands[2].clValue(type)} = #{operands[0].clValue(type)} #{operator} #{operands[1].clValue(type)};"
    371         if operands[2].is_a? RegisterID and (type == :int32 or type == :uint32)
    372             $asm.putc "#{operands[2].clDump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
    373         end
     391        op1 = operands[0]
     392        op2 = operands[1]
     393        dst = operands[2]
    374394    else
    375395        raise unless operands.size == 2
    376         raise unless not operands[1].is_a? Immediate
    377         $asm.putc "#{operands[1].clValue(type)} = #{operands[1].clValue(type)} #{operator} #{operands[0].clValue(type)};"
    378         if operands[1].is_a? RegisterID and (type == :int32 or type == :uint32)
    379             $asm.putc "#{operands[1].clDump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
    380         end
    381     end
     396        op1 = operands[1]
     397        op2 = operands[0]
     398        dst = operands[1]
     399    end
     400    raise unless not dst.is_a? Immediate
     401    if dst.is_a? RegisterID and (type == :int32 or type == :uint32)
     402        truncationHeader = "(uint32_t)("
     403        truncationFooter = ")"
     404    else
     405        truncationHeader = ""
     406        truncationFooter = ""
     407    end
     408    $asm.putc "#{dst.clLValue(type)} = #{truncationHeader}#{op1.clValue(type)} #{operator} #{op2.clValue(type)}#{truncationFooter};"
    382409end
    383410
     
    385412    raise unless type == :int || type == :uint || type == :int32 || type == :uint32 || type == :int64 || type == :uint64
    386413    if operands.size == 3
    387         $asm.putc "#{operands[2].clValue(type)} = #{operands[1].clValue(type)} #{operator} (#{operands[0].clValue(:int)} & 0x1f);"
    388         if operands[2].is_a? RegisterID and (type == :int32 or type == :uint32)
    389             $asm.putc "#{operands[2].clDump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
    390         end
     414        op1 = operands[0]
     415        op2 = operands[1]
     416        dst = operands[2]
    391417    else
    392         raise unless operands.size == 2
    393         raise unless not operands[1].is_a? Immediate
    394         $asm.putc "#{operands[1].clValue(type)} = #{operands[1].clValue(type)} #{operator} (#{operands[0].clValue(:int)} & 0x1f);"
    395         if operands[1].is_a? RegisterID and (type == :int32 or type == :uint32)
    396             $asm.putc "#{operands[1].clDump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
    397         end
    398     end
     418        op1 = operands[1]
     419        op2 = operands[0]
     420        dst = operands[1]
     421    end
     422    if dst.is_a? RegisterID and (type == :int32 or type == :uint32)
     423        truncationHeader = "(uint32_t)("
     424        truncationFooter = ")"
     425    else
     426        truncationHeader = ""
     427        truncationFooter = ""
     428    end
     429    $asm.putc "#{dst.clLValue(type)} = #{truncationHeader}#{operands[1].clValue(type)} #{operator} (#{operands[0].clValue(:int)} & 0x1f)#{truncationFooter};"
    399430end
    400431
     
    403434    raise unless operands.size == 1
    404435    raise unless not operands[0].is_a? Immediate
    405     $asm.putc "#{operands[0].clValue(type)} = #{operator}#{operands[0].clValue(type)};"
    406     if operands[0].is_a? RegisterID and (type == :int32 or type == :uint32)
    407         $asm.putc "#{operands[0].clDump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
    408     end
     436    op = operands[0]
     437    dst = operands[0]
     438    if dst.is_a? RegisterID and (type == :int32 or type == :uint32)
     439        truncationHeader = "(uint32_t)("
     440        truncationFooter = ")"
     441    else
     442        truncationHeader = ""
     443        truncationFooter = ""
     444    end
     445    $asm.putc "#{dst.clLValue(type)} = #{truncationHeader}#{operator}#{op.clValue(type)}#{truncationFooter};"
    409446end
    410447
     
    419456    # The result is a boolean.  Hence, it doesn't need to be based on the type
    420457    # of the arguments being compared.
    421     $asm.putc "#{operands[2].clValue} = (#{operands[0].clValue(type)} #{comparator} #{operands[1].clValue(type)});"
     458    $asm.putc "#{operands[2].clLValue(type)} = (#{operands[0].clValue(type)} #{comparator} #{operands[1].clValue(type)});"
    422459end
    423460
     
    460497    # the condition test.
    461498    conditionExpr = cloopGenerateConditionExpression(operands, type, conditionTest)
    462     $asm.putc "#{operands[-1].clValue} = (#{conditionExpr});"
     499    $asm.putc "#{operands[-1].clLValue} = (#{conditionExpr});"
    463500end
    464501
     
    472509    end
    473510
    474     op1 = operands[0].clValue(type)
    475     op2 = operands[1].clValue(type)
    476 
    477511    $asm.putc "{"
    478     $asm.putc "    #{tempType} temp = #{op2} #{operator} #{op1};"
    479     $asm.putc "    #{op2} = temp;"
     512    $asm.putc "    #{tempType} temp = #{operands[1].clValue(type)} #{operator} #{operands[0].clValue(type)};"
     513    $asm.putc "    #{operands[1].clLValue(type)} = temp;"
    480514    $asm.putc "    if (temp #{conditionTest})"
    481515    $asm.putc "        goto  #{operands[2].cLabel};"
     
    487521    when :int32
    488522        tempType = "int32_t"
     523        truncationHeader = "(uint32_t)("
     524        truncationFooter = ")"
    489525    else
    490526        raise "Unimplemented type"
     
    502538    end
    503539
    504     $asm.putc "    if (!WTF::ArithmeticOperations<#{tempType}, #{tempType}, #{tempType}>::#{operation}(#{operands[1].clValue(type)}, #{operands[0].clValue(type)}, #{operands[1].clValue(type)}))"
     540    $asm.putc "    #{tempType} result;"
     541    $asm.putc "    bool success = WTF::ArithmeticOperations<#{tempType}, #{tempType}, #{tempType}>::#{operation}(#{operands[1].clValue(type)}, #{operands[0].clValue(type)}, result);"
     542    $asm.putc "    #{operands[1].clLValue(type)} = #{truncationHeader}result#{truncationFooter};"
     543    $asm.putc "    if (!success)"
    505544    $asm.putc "        goto #{operands[2].cLabel};"
    506545    $asm.putc "}"
     
    510549def cloopEmitCallSlowPath(operands)
    511550    $asm.putc "{"
    512     $asm.putc "    cloopStack.setCurrentStackPointer(sp.vp);"
     551    $asm.putc "    cloopStack.setCurrentStackPointer(sp.vp());"
    513552    $asm.putc "    SlowPathReturnType result = #{operands[0].cLabel}(#{operands[1].clDump}, #{operands[2].clDump});"
    514     $asm.putc "    decodeResult(result, t0.cvp, t1.cvp);"
     553    $asm.putc "    decodeResult(result, t0, t1);"
    515554    $asm.putc "}"
    516555end
    517556
    518557def cloopEmitCallSlowPathVoid(operands)
    519     $asm.putc "cloopStack.setCurrentStackPointer(sp.vp);"
     558    $asm.putc "cloopStack.setCurrentStackPointer(sp.vp());"
    520559    $asm.putc "#{operands[0].cLabel}(#{operands[1].clDump}, #{operands[2].clDump});"
    521560end
     
    598637
    599638        when "loadi"
    600             $asm.putc "#{operands[1].clValue(:uint)} = #{operands[0].uint32MemRef};"
     639            $asm.putc "#{operands[1].clLValue(:uint32)} = #{operands[0].uint32MemRef};"
    601640            # There's no need to call clearHighWord() here because the above will
    602641            # automatically take care of 0 extension.
    603642        when "loadis"
    604             $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].int32MemRef};"
     643            $asm.putc "#{operands[1].clLValue(:int32)} = #{operands[0].int32MemRef};"
    605644        when "loadq"
    606             $asm.putc "#{operands[1].clValue(:int64)} = #{operands[0].int64MemRef};"
     645            $asm.putc "#{operands[1].clLValue(:int64)} = #{operands[0].int64MemRef};"
    607646        when "loadp"
    608             $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].intMemRef};"
     647            $asm.putc "#{operands[1].clLValue} = #{operands[0].intMemRef};"
    609648        when "storei"
    610649            $asm.putc "#{operands[1].int32MemRef} = #{operands[0].clValue(:int32)};"
     
    614653            $asm.putc "#{operands[1].intMemRef} = #{operands[0].clValue(:int)};"
    615654        when "loadb"
    616             $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].uint8MemRef};"
    617         when "loadbs", "loadbsp"
    618             $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].int8MemRef};"
     655            $asm.putc "#{operands[1].clLValue(:int)} = #{operands[0].uint8MemRef};"
     656        when "loadbs"
     657            $asm.putc "#{operands[1].clLValue(:int)} = (uint32_t)(#{operands[0].int8MemRef});"
     658        when "loadbsp"
     659            $asm.putc "#{operands[1].clLValue(:int)} = #{operands[0].int8MemRef};"
    619660        when "storeb"
    620661            $asm.putc "#{operands[1].uint8MemRef} = #{operands[0].clValue(:int8)};"
    621662        when "loadh"
    622             $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].uint16MemRef};"
     663            $asm.putc "#{operands[1].clLValue(:int)} = #{operands[0].uint16MemRef};"
    623664        when "loadhs"
    624             $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].int16MemRef};"
     665            $asm.putc "#{operands[1].clLValue(:int)} = (uint32_t)(#{operands[0].int16MemRef});"
    625666        when "storeh"
    626667            $asm.putc "*#{operands[1].uint16MemRef} = #{operands[0].clValue(:int16)};"
    627668        when "loadd"
    628             $asm.putc "#{operands[1].clValue(:double)} = #{operands[0].dblMemRef};"
     669            $asm.putc "#{operands[1].clLValue(:double)} = #{operands[0].dblMemRef};"
    629670        when "stored"
    630671            $asm.putc "#{operands[1].dblMemRef} = #{operands[0].clValue(:double)};"
     
    641682        # Convert an int value to its double equivalent, and store it in a double register.
    642683        when "ci2d"
    643             $asm.putc "#{operands[1].clValue(:double)} = #{operands[0].clValue(:int32)};"
    644            
     684            $asm.putc "#{operands[1].clLValue(:double)} = (double)#{operands[0].clValue(:int32)}; // ci2d"
     685
    645686        when "bdeq"
    646687            cloopEmitCompareAndBranch(operands, :double, "==")
     
    670711
    671712        when "td2i"
    672             $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].clValue(:double)};"
    673             $asm.putc "#{operands[1].clDump}.clearHighWord();"
     713            $asm.putc "#{operands[1].clLValue(:int)} = (uint32_t)(intptr_t)#{operands[0].clValue(:double)}; // td2i"
    674714
    675715        when "bcd2i"  # operands: srcDbl dstInt slowPath
    676             $asm.putc "{"
     716            $asm.putc "{ // bcd2i"
    677717            $asm.putc "    double d = #{operands[0].clValue(:double)};"
    678718            $asm.putc "    const int32_t asInt32 = int32_t(d);"
    679719            $asm.putc "    if (asInt32 != d || (!asInt32 && std::signbit(d))) // true for -0.0"
    680720            $asm.putc "        goto  #{operands[2].cLabel};"
    681             $asm.putc "    #{operands[1].clValue} = asInt32;"           
    682             $asm.putc "    #{operands[1].clDump}.clearHighWord();"
     721            $asm.putc "    #{operands[1].clLValue} = (uint32_t)asInt32;"
    683722            $asm.putc "}"
    684723
    685724        when "move"
    686             $asm.putc "#{operands[1].clValue(:int)} = #{operands[0].clValue(:int)};"
     725            $asm.putc "#{operands[1].clLValue(:int)} = #{operands[0].clValue(:int)};"
    687726        when "sxi2q"
    688             $asm.putc "#{operands[1].clValue(:int64)} = #{operands[0].clValue(:int32)};"
     727            $asm.putc "#{operands[1].clLValue(:int64)} = #{operands[0].clValue(:int32)};"
    689728        when "zxi2q"
    690             $asm.putc "#{operands[1].clValue(:uint64)} = #{operands[0].clValue(:uint32)};"
     729            $asm.putc "#{operands[1].clLValue(:uint64)} = #{operands[0].clValue(:uint32)};"
    691730        when "nop"
    692731            $asm.putc "// nop"
     
    832871            $asm.putc "CRASH(); // break instruction not implemented."
    833872        when "ret"
    834             $asm.putc "opcode = lr.opcode;"
     873            $asm.putc "opcode = lr.opcode();"
    835874            $asm.putc "DISPATCH_OPCODE();"
    836875
     
    956995        # the lower 32 bits of t1. Leave the upper 32 bits of t0 and t1 unchanged.
    957996        when "cdqi"
    958             $asm.putc "{"
    959             $asm.putc "    int64_t temp = t0.i32; // sign extend the low 32bit"
    960             $asm.putc "    t0.i32 = temp; // low word"
    961             $asm.putc "    t0.clearHighWord();"
    962             $asm.putc "    t1.i32 = uint64_t(temp) >> 32; // high word"
    963             $asm.putc "    t1.clearHighWord();"
     997            $asm.putc "{ // cdqi"
     998            $asm.putc "    int64_t temp = t0.i32(); // sign extend the low 32bit"
     999            $asm.putc "    t0 = (uint32_t)temp; // low word"
     1000            $asm.putc "    t1 = (uint32_t)(temp >> 32); // high word"
    9641001            $asm.putc "}"
    9651002
     
    9771014            # Divide t1,t0 (EDX,EAX) by the specified arg, and store the remainder in t1,
    9781015            # and quotient in t0:
    979             $asm.putc "{"
    980             $asm.putc "    int64_t dividend = (int64_t(t1.u32) << 32) | t0.u32;"
     1016            $asm.putc "{ // idivi"
     1017            $asm.putc "    int64_t dividend = (int64_t(t1.u32()) << 32) | t0.u32();"
    9811018            $asm.putc "    int64_t divisor = #{operands[0].clValue(:int)};"
    982             $asm.putc "    t1.i32 = dividend % divisor; // remainder"
    983             $asm.putc "    t1.clearHighWord();"
    984             $asm.putc "    t0.i32 = dividend / divisor; // quotient"
    985             $asm.putc "    t0.clearHighWord();"
     1019            $asm.putc "    t1 = (uint32_t)(dividend % divisor); // remainder"
     1020            $asm.putc "    t0 = (uint32_t)(dividend / divisor); // quotient"
    9861021            $asm.putc "}"
    9871022
     
    9891024        # Decode 2 32-bit ints (low and high) into a 64-bit double.
    9901025        when "fii2d"
    991             $asm.putc "#{operands[2].clValue(:double)} = Ints2Double(#{operands[0].clValue(:uint32)}, #{operands[1].clValue(:uint32)});"
     1026            $asm.putc "#{operands[2].clLValue(:double)} = ints2Double(#{operands[0].clValue(:uint32)}, #{operands[1].clValue(:uint32)}); // fii2d"
    9921027
    9931028        # 32-bit instruction: f2dii dblOp int32LoOp int32HiOp (based on ARMv7)
    9941029        # Encode a 64-bit double into 2 32-bit ints (low and high).
    9951030        when "fd2ii"
    996             $asm.putc "Double2Ints(#{operands[0].clValue(:double)}, #{operands[1].clValue(:uint32)}, #{operands[2].clValue(:uint32)});"
     1031            $asm.putc "double2Ints(#{operands[0].clValue(:double)}, #{operands[1].clDump}, #{operands[2].clDump}); // fd2ii"
    9971032
    9981033        # 64-bit instruction: fq2d int64Op dblOp (based on X64)
    9991034        # Copy a bit-encoded double in a 64-bit int register to a double register.
    10001035        when "fq2d"
    1001             $asm.putc "#{operands[1].clValue(:double)} = #{operands[0].clValue(:castToDouble)};"
     1036            $asm.putc "#{operands[1].clLValue(:double)} = #{operands[0].clValue(:bitsAsDouble)}; // fq2d"
    10021037
    10031038        # 64-bit instruction: fd2q dblOp int64Op (based on X64 instruction set)
    10041039        # Copy a double as a bit-encoded double into a 64-bit int register.
    10051040        when "fd2q"
    1006             $asm.putc "#{operands[1].clValue(:int64)} = #{operands[0].clValue(:castToInt64)};"
     1041            $asm.putc "#{operands[1].clLValue(:int64)} = #{operands[0].clValue(:bitsAsInt64)}; // fd2q"
    10071042
    10081043        when "leai"
     
    10801115        when "cloopCallJSFunction"
    10811116            uid = $asm.newUID
    1082             $asm.putc "lr.opcode = getOpcode(llint_cloop_did_return_from_js_#{uid});"
     1117            $asm.putc "lr = getOpcode(llint_cloop_did_return_from_js_#{uid});"
    10831118            $asm.putc "opcode = #{operands[0].clValue(:opcode)};"
    10841119            $asm.putc "DISPATCH_OPCODE();"
     
    10891124        # have a fixed prototype of 1 args: the passed ExecState.
    10901125        when "cloopCallNative"
    1091             $asm.putc "cloopStack.setCurrentStackPointer(sp.vp);"
     1126            $asm.putc "cloopStack.setCurrentStackPointer(sp.vp());"
    10921127            $asm.putc "nativeFunc = #{operands[0].clValue(:nativeFunc)};"
    1093             $asm.putc "functionReturnValue = JSValue::decode(nativeFunc(t0.execState));"
     1128            $asm.putc "functionReturnValue = JSValue::decode(nativeFunc(t0.execState()));"
    10941129            $asm.putc "#if USE(JSVALUE32_64)"
    1095             $asm.putc "    t1.i = functionReturnValue.tag();"
    1096             $asm.putc "    t0.i = functionReturnValue.payload();"
     1130            $asm.putc "    t1 = functionReturnValue.tag();"
     1131            $asm.putc "    t0 = functionReturnValue.payload();"
    10971132            $asm.putc "#else // USE_JSVALUE64)"
    1098             $asm.putc "    t0.encodedJSValue = JSValue::encode(functionReturnValue);"
    1099             $asm.putc "#endif // USE_JSVALUE64)"           
     1133            $asm.putc "    t0 = JSValue::encode(functionReturnValue);"
     1134            $asm.putc "#endif // USE_JSVALUE64)"
    11001135
    11011136        # We can't do generic function calls with an arbitrary set of args, but
Note: See TracChangeset for help on using the changeset viewer.