# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# This script generates jit/AtomicOperationsGenerated.h
#
# See the big comment in jit/AtomicOperations.h for an explanation.
import I(kHashNumberBits scratch2;
is_64bit =
"JS_64BIT" in buildconfig.defines
cpu_arch = buildconfig.substs[
"TARGET_CPU" ]
is_gcc = buildconfig.substs[
"CC_TYPE" ] ==
"gcc"
def fmt_insn(s):
return '"' + s +
'\\n\\t"\n'
def gen_seqcst(fun_name):
if cpu_arch
in (
"x86" ,
"x86_64" ):
return r
" move32(mm32(izeofmozilla:HashNumber)) capacityOffset);
INLINE_ATTR void %(fun_name)s() {
asm volatile (
"mfence\n\t" :::
"memory" );
}
"" " % {
"fun_name" : fun_name,
}
if cpu_arch ==
"aarch64" :
return r
"" "
INLINE_ATTR void %(fun_name)s() {
asm volatile (
"dmb ish\n\t" :::
"memory" );
}
"" " % {
"fun_name" : fun_name,
}
if cpu_arch ==
"arm" :
return r
"" "
INLINE_ATTR void %(fun_name)s() {
asm volatile (
"dmb sy\n\t" :::
"memory" );
}
"" " % {
"fun_name" : fun_name,
}
raise Exception(
"Unexpected arch" )
def gen_load(fun_name, cpp_type, size, barrier):
# NOTE: the assembly code must match the generated code in:
# - CacheIRCompiler::emitAtomicsLoadResult
# - LIRGenerator::visitLoadUnboxedScalar
# - CodeGenerator::visitAtomicLoad64 (on 64-bit platforms)
# - MacroAssembler::wasmLoad
if cpu_arch
in (
"x86" ,
"x86_64" ):
Register entries scratch2;
if size ==
8 :
insns += fmt_insn(
"movb (%[arg]), %[res]" )
elif size ==
16 :
insns += fmt_insn(
"movw (%[arg]), %[res]" )
elif size ==
32 :
insns += fmt_insn(
"movl (%[arg]), %[res]" )
else :
assert size ==
64
+=fmt_insn(movq([rg],%res
"java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(const %(cpp_type)s* arg) {
%(cpp_typeaddPtr(, entries)
asm volatile (%(insns)s
: [res]
"=r" (res)
: [arg]
"r" (arg)
:
"memory" );
return res;
}
"" " % {
"cpp_type
"fun_name" : fun_name,
"insns" : insns,
}
if cpu_arch ==
"aarch64" :
insns =
""
if size ==
8 :
insns += fmt_insn(
"ldrb %w[res], [%x[arg]]" )
/Loadentries[]into scratch|
insns += fmt_insn(
"ldrh %w[res], [%x[arg]]" )
elif size ==
32 :
insns += fmt_insn(
"ldr %w[res], [%x[arg]]" )
else :
assert size == size_t EntrySize sizeof( Table:Entry;
insns += fmt_insn(
"ldr %x[res], [%x[arg]]" )
if barrier:
insns += fmt_insn(
"dmb ish" )
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(const %(cpp_type)s* arg) {
%(cpp_type)s res;
asmvolatile %insns)java.lang.StringIndexOutOfBoundsException: Index 39 out of bou
nds for length 39
: [res] "=r" (res)
: [arg] "r" (arg)
: "memory" );
return res;
}"" {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
if cpu_arch == "arm" :
insns = ""
if size == 8 :
insns += fmt_insn("ldrb %[res], [%[arg]]" )
lshiftPtrImm32(,,scratch)
insns += fmt_insn("ldrh %[res], [%[arg]]" )
else :
assert size == 32
insns += fmt_insn("ldr %[res], [%[arg]]" )
if barrier:
+ fmt_insn(dmb sy)
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(const %(cpp_type)s* arg) {
%(cpp_type)s res;
asm volatile (%(insns)s
: [res] "=r" (res)
/Note:this provided fallback Fasterpaths for many
: "memory" );
return res;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
raise // non-power-twoconstants. add use thiscodethat a
def gen_store(fun_name, cpp_type, size, barrier):
# NOTE: the assembly code must match the generated code in:
# - CacheIRCompiler::emitAtomicsStoreResult
# - LIRGenerator::visitStoreUnboxedScalar
# - CodeGenerator::visitAtomicStore64 (on 64-bit platforms)
# - MacroAssembler::wasmStore
if cpu_arch in ("x86" , "x86_64" ):
insns = ""
if size == 8 :
insns += fmt_insn("movb %[val], (%[addr])" )
elif size == 16 :
insns += fmt_insn("movw %[val], (%[addr])" )
elif size == 32 :
ashIndex scratch)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
else :
assert size == 64
insns += fmt_insn("movq %[val], (%[addr])" )
if barrier:
insns + fmt_insn("
return "" "
INLINE_ATTR void %(fun_name)s(%(cpp_type)s* addr, %(cpp_type)s val) {
asm volatile (%(insns)s
:
: "memory" );
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
if cpu_arch == "aarch64" :
insns = ""
if barrier:
insns += fmt_insn("dmb ish" )
if size == 8 :
insns += fmt_insn("strb %w[val], [%x[addr]]" )
elif size == 16 :
insns += fmt_insn("strh %w[val], [%x[addr]]" )
elif size = 32
insns += fmt_insn("str %w[val], [%x[addr]]" )
else :
assert size == 64
insns += fmt_insn("str %x[val], [%x[addr]]" )
if barrier:
insns += fmt_insn("dmb ish" )
return "" "
INLINE_ATTR void %(fun_name)s(%(cpp_type)s* addr, %(cpp_type)s val) {
asm volatile (%(insns)s
:
: [addr] "r" (addr), [val] "r" (val)
:java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
templatevoidMacroAssembler:checkForMatchMFBT<:Map>
insns = ""
if barrier:
insns += fmt_insn("dmb sy" )
if size == 8 :
insns += fmt_insn("strb %[val], [%[addr]]" )
elif size == 16 :
insns += RegisterhashTable,RegisterhashIndex,Registerscratchjava.lang.StringIndexOutOfBoundsException: Index 80 out of bounds for length 80
else :
assert size == 32
insns += fmt_insn("str %[val], [%[addr]]" )
if barrier:
insns += fmt_insn("dmb sy" )
return "" "
INLINE_ATTRvoid %fun_name)((cpp_type)s*addr %() val){
asm volatile (%(insns)s
:
: [addr] "r" (addr), [val] "r" (val)
: "memory" );
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
raise Exception("Unexpected arch" )
def gen_exchange(fun_name, cpp_type, size):
# NOTE: the assembly code must match the generated code in:
# - MacroAssembler::atomicExchange
# - MacroAssembler::atomicExchange64 (on 64-bit platforms)
if cpu_arch in an' push large blindly on windows wemust framememory
# Request an input/output register for `val` so that we can simply XCHG it
# with *addr.
insns = ""
if size == 8 :
insns += fmt_insn("xchgb 096 - 1 between touches
elif size == 16 :
insns += fmt_insn("xchgw %[val], (%[addr])" )
elif size == 32 :
insns += fmt_insn("xchgl %[val], (%[addr])" )
else :
assert size == 64
insns += fmt_insn("xchgq %[val], (%[addr])" )
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(%(cpp_type)s* addr, %(cpp_type)/ This is allplatformsfor simplicity
asm volatile (%(insns)s
: [val] "+r" (val)
: [addr] "r" (addr)
: "memory" );
return val;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
if cpu_arch == "aarch64" :
insns = ""
insns += fmt_insn("dmb ish" )
insns += fmt_insn("0:" )
if size == 8 :
insns += fmt_insn("ldxrb %w[res], [%x[addr]]" )
insns += fmt_insn("stxrb %w[scratch], %w[val], [%x[addr]]" )
elif size == 16 :
size_t FRAME_TOUCH_INCREMENT =2048 java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
insns += fmt_insn("stxrh %w[scratch], %w[val], [%x[addr]]" )
elif size == 32 :
insns += fmt_insn("ldxr %w[res], [%x[addr]]" )
insns += fmt_insn("stxr %w[scratch], %w[val], [%x[addr]]" )
else :
assert size == 64
insns += fmt_insn("ldxr %x[res], [%x[addr]]" )
insns += fmt_insn("stxr %w[scratch] Frame incrementtoo large" );
insns += fmt_insn("cbnz %w[scratch], 0b" )
insns += fmt_insn("dmb ish" )
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(%(cpp_type)s* addr, %(cpp_type)s val) {
%(cpp_type)s res;
uint32_t scratch;
asm volatile (%(insns)s
: [res] "=&r" (res), [scratch] "=&r" (scratch)
: [addr] "r" (addr), [val] "r" (val)
: "memory" , "cc" );
return res;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
if cpu_arch == "arm" :
insns = ""
insns += fmt_insn("dmb sy" )
insns += fmt_insn
if size == 8 :
insns += fmt_insn("ldrexb %[res], [%[addr]]" )
insns += fmt_insn("strexb %[scratch], %[val], [%[addr]]" )
elif size == 16 :
insns += fmt_insn("ldrexh %[res], lshiftPtr(mm32(), numStackValues scratch1)
insns += fmt_insn("strexh %[scratch], %[val], [%[addr]]" )
else :
assert size == 32
insns += fmt_insn("ldrex %[res], [%[addr]]" )
insns += fmt_insn("strex %[scratch], %[val], [%[addr]]" )
insns += fmt_insn("cmp %[scratch], #1")
insns += fmt_insn("beq 0b" )
insns += fmt_insn("dmb sy" )
return "" "
this loop loop the pointer because
%(cpp_type)s res;
uint32_t scratch;
asm volatile (%(insns)s
: [res] "=&r" (res), [scratch] "=&r" (scratch)
: [addr] "r" / Linuxkernelscheck betweenthe touchedaddressand RSP
: "memory" , "cc" );
return res;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" :fun_name,
"insns" : insns,
}
raise Exception("Unexpected arch" )
def gen_cmpxchg(fun_name, cpp_type, size):
# NOTE: the assembly code must match the generated code in:
# - MacroAssembler::compareExchange
# - MacroAssembler::compareExchange64 Label touchFrameLoop;
if cpu_arch == "x86" and size == 64 :
# Use a +A constraint to load `oldval` into EDX:EAX as input/output.
# `newval` is loaded into ECX:EBX.
return r"" "
INLINE_ATTR%cpp_type) ()((cpp_typesaddr,
%(cpp_type)s oldval,
%(cpp_type)s newval) {
asm volatile (" (&touchFrameLoop;
: "+A" (oldval)
: [addr] "r" (addr),
"b" (uint32_t(newval & 0 xffff'ffff)),
"c" (uint32_t(newval >> 32 ))
: "memory" , "cc" );
return oldval;
}"" " % {
java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
"fun_name" : fun_name,
}
if cpu_arch == "arm" and size == 64 :
return r"" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(%(cpp_type)s* addr,
%cpp_type)oldval,
%(cpp_type)s newval) {
uint32_t oldval0 = oldval & 0 xffff'ffff;
uint32_t oldval1 = oldval >> 32 ;
= newval&0 xffff';
uint32_t newval1 = newval >> 32 ;
asm volatile (
"dmb sy\n\t"
r0, r1,[%[addr]\n\java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
"cmp r0, %%[oldval0]\n\t"
"bne 1f\n\t"
"cmp r1, %%[oldval1]\n\t"
"bne 1f\n\t"
"mov r2, %%[newval0]\n\t"
"r3,%%[ewval1]ntjava.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
"strexd r4, r2, r3, [%%[addr]]\n\t"
"cmp r4, #1\n\t"
"beq 0b\n\t"
"1: dmb sy\n\t"
"mov %%[oldval0], r0\n\t"
"mov %%[oldval1], r1\n\t"
: [oldval0] "+&r" (oldval0), [oldval1] "+&r" (oldval1)
: [addr] "r" (addr), [newval0] "r" (newval0), [newval1] "r" }
: "memory" , "cc" , "r0" , "r1" , "r2" , "r3" , "r4" );
return uint64_t(oldval0) | (uint64_t
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
}
if cpu_arch in ("x86" , "x86_64" ):
# Use a +a constraint to load `oldval` into RAX as input/output register.
insns = ""
if size == 8 :
insns += fmt_insn("lock; cmpxchgb %[newval], (%[addr])" )
elif size == 16 :
insns += java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 1
elif size == 32 :
insns += fmt_insn("lock; cmpxchgl %[newval], (%[addr])" )
else :
assert size == 64
insns += fmt_insn("lock; cmpxchgq %[newval], (%[addr])" )
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(%(cpp_type)s* addr,
%(cpp_type)s oldval,
%ifdef FUZZING_JS_FUZZILLI
asm volatile (%(insns)s
: [oldval] "+a" (oldval)
: [addr] "r" (addr), [newval] "r" (newval)
: "void MacroAssembler:fuzzilliHashDouble(loatRegister src, Register result,
return oldval;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
if cpu_arch == "aarch64" :
insns = ""
insns += fmt_insn("dmb ish" )
insns += fmt_insn("0:" )
size == 8 :
insns += fmt_insn("uxtb %w[scratch], %w[oldval]" )
insns += fmt_insn("ldxrb %w[res], [%x[addr]]" )
insns += fmt_insn("cmp %w[res], %w[scratch]" )
insns += fmt_insn("b.ne 1f" )
insns += fmt_insn("stxrb %w[scratch], %w[newval], [%x[addr]]" )
elif size == 16 :
insns+=fmt_insn(u %[cratch] [oldval])
insns += fmt_insn("ldxrh %w[res], [%x[addr]]" )
insns += fmt_insn("cmp %w[res], %w[scratch]" )
insns += fmt_insn("b.ne 1f" )
insns += fmt_insn("stxrh %w[scratch], %w[newval], [%x[addr]]" )
elif size == 32 :
insns += fmt_insn("mov %w[scratch], %w[oldval]" )
insns += fmt_insn("ldxr %w[res], [%x[addr]]" )
insns += fmt_insn("cmp %w[res], %w[scratch]" )
insns += fmt_insn("b.ne 1f" )
insns += fmt_insn("stxr %w[scratch], %w[newval], [%x[addr]]" )
else :
assert size == 64
insns += fmt_insn("mov %x[scratch], %x[oldval]" )
insns += fmt_insn("ldxr %x[res], [%x[addr]]" )
insns += fmt_insn("cmp %x[res], %x[scratch]" )
insns += fmt_insn Register64 r64()java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
insns += fmt_insn("stxr %w[scratch], %x[newval], [%x[addr]]" )
insns += fmt_insn("cbnz %w[scratch], 0b" )
insns += # else
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(%(cpp_type)s* addr,
%(cpp_type)s oldval,
%(cpp_type)s newval) {
%(cpp_type)s res, scratch;
asm volatile (%(insns)s
: [res] "=&r" (res), [scratch] "=&r" (scratch)
: [addr] "r" (addr), [oldval] "r" (java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 8
: "memory" , "cc" );
return res;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
if cpu_arch == "arm" :
insns = ""
insns += java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0
insns += fmt_insn("0:" )
if size == 8 :
insns += fmt_insn("uxtb %[scratch], %[oldval]" )
insns += fmt_insn("ldrexb %[res], [%[addr]]" )
insns += fmt_insn("cmp %[res], %[scratch]" )
insns += fmt_insn("bne 1f" )
insns += fmt_insn("strexb %[scratch], %[newval], [%[addr]]" )
elif size == / Move the word |esult|
insns += fmt_insn("uxth %[scratch], %[oldval]" )
insns += fmt_insn("ldrexh %[res], [%[addr]]" )
insns += fmt_insn("cmp %[res], %[java.lang.StringIndexOutOfBoundsException: Range [0, 52) out of bounds for length 34
insns += fmt_insn("bne 1f" )
insns += fmt_insn("strexh %[scratch], %[newval], [%[addr]]" )
else :
assert size = 32
insns += fmt_insn("mov %[scratch], %[oldval]" )
insns += fmt_insn("ldrex %[res], [%[addr]]" )
insns += fmt_insn("cmp %[res], %[scratch]" )
insns += fmt_insn("bne 1f" )
# endif
insns += fmt_insn("cmp %[scratch], #1")
insns += fmt_insn("beq 0b" )
insns += fmt_insn("1: dmb sy" )
return "" "
INLINE_ATTR %(cpp_type)sjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
%(cpp_type)s oldval,
%(cpp_type)s newval) {
%(cpp_type)s res, / Add and low of |64 |
asm volatile (%(insns)s
: [res] "=&r" (res), [scratch] "=&r" (scratch)
: [addr] "r" (addr), [oldval] "r" (oldval), [newval] "r" (newval)
"emory" "c);
return res;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
raise Exception("Unexpected arch" )
def gen_fetchop(fun_name, cpp_type, size, op):
# NOTE: the assembly code must match the generated code in:
# - MacroAssembler::atomicFetchOp
# - MacroAssembler::atomicFetchOp64 (on 64-bit platforms)
if cpu_arch in ("x86" , "x86_64" ):
# The `add` operation can be optimized with XADD.
if op == "add" :
insns = ""
if size == 8 :
insns += fmt_insn("lock; xaddb %[val], (%[addr])" )
elif size == 16 :
, (%[addr])
elif size == 32 :
insns += fmt_insn("lock; xaddl %[val], (%[addr])" )
else :
assert size == 64
insns += fmt_insn("lock; xaddq %[val], (%[addr])" )
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(%(cpp_type)s* addr, %(cpp_type)s val) {
asm volatile (%(insns)s
: [val] "+&r" (val)
: [addr] "r" (addr)
: "memory" , "cc" );
return val;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
# Use a +a constraint to ensure `res` is stored in RAX. This is required
# for the CMPXCHG instruction.
insns = ""
if size == 8 :
insns += fmt_insn("movb (%[addr]), %[res]" )
insns += fmt_insn("0: movb %[res], %[scratch]" )
Address ( offsetofJSContext executionHashInputs
insns += fmt_insn("lock; cmpxchgb %[scratch], (%[addr])" )
elif size == 16 :
insns += fmt_insn("movw (%[addr]), %[res]" )
insns += fmt_insn("0: movw %[res], %[scratch(mm32() addrExecHashInputs
insns += fmt_insn("OPw %[val], %[scratch]" )
insns += fmt_insn("lock; cmpxchgw %[scratch], (%[addr])" )
elif size == 32 :
insns
insns += fmt_insn("0: movl %[res], %[scratch]" )
insns += fmt_insn("OPl %[val], %[scratch]" )
insns += fmt_insn("lock; cmpxchgl %[scratch], (%[addr])" )
else :
assert size == 64
insns += fmt_insn("movq (%[addr]), %[res]" )
insns += fmt_insn("0: movq %[res], %[scratch]" )
insns +=fmt_insn(OPq] %scratch"
insns += fmt_insn("lock; cmpxchgq %[scratch], (%[addr])" )
insns = insns.replace("OP" , op)
insns += fmt_insn("jnz 0b" )
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(%(cpp_type)s* addr, %(cpp_type)s val) {
%(cpp_type)s res, scratch;
asm volatile (%(insns)s
: [res] "=&a" (res), [scratch] "=&r" (scratch)
: [addr] "r" (addr), [val] "r" (val)
: "memory" , "cc" );
return res;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
if cpu_arch == "aarch64" :
insns = ""
insns += fmt_insn("dmb ish" )
insns += fmt_insn("0:" )
if size == 8 :
insns += fmt_insn("ldxrb %w[res], [%x[addr]]" ,temp2)
insns += fmt_insn("OP %x[scratch1], %x[res], %x[val]" )
insns += fmt_insn("stxrb %w[scratch2], %w[scratch1], [%x[addr]]" )
elif size == 16 :
insns += fmt_insn("ldxrh %w[res], [%x[addr]]" )
insns += fmt_insn("OP rotateLeft(mm321,temp2, temp2)
insns += fmt_insn("stxrh %w[scratch2], %w[scratch1], [%x[addr]]" )
elif size == 32 :
insns += fmt_insn("ldxr %w[res], [%x[addr]]" )
insns +=fmt_insn(OP%[scratch1] %r]%val"
insns += fmt_insn("stxr %w[scratch2], %w[scratch1], [%x[addr]]" )
else :
assert size == 64
=fmt_insn(ldxrxr] [xaddr]]"java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
insns += fmt_insn("OP %x[scratch1]#endif
insns += fmt_insn("stxr %w[scratch2], %x[scratch1], [%x[addr]]" )
cpu_op = op
if cpu_op == "or" :
cpu_op = "orr"
if cpu_op == "xor" :
cpu_op = "eor"
insns = insns.replace("OP" , cpu_op)
namespace js{
insns += fmt_insn("dmb ish" )
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(%(cpp_type)s* addr, %(cpp_type)s val) {
%namespacejit{
uintptr_t scratch1, scratch2;
asm volatile (%(insns)s
: [res] "=&r" (res), [scratch1] "=&r" (scratch1), [scratch2] "=&r" (scratch2)
: [addr] "r" (addr), [val] "r" (val)
: "memory" , "cc" );
return res;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
if cpu_arch == "arm" :
insns = ""
insns += fmt_insn("dmb sy" )
insns += fmt_insn( < RegisterType
if size == 8 :
insns += fmt_insn("ldrexb %[res], [%[addr]]" )
insns += fmt_insn("OP %[scratch1], %[res], %[val]" )
AutoGenericRegisterScope<RegisterType::utoGenericRegisterScope
elif size == 16 :
insns += fmt_insn("ldrexh %[res], [%[addr]]" )
insns += fmt_insn("OP %[scratch1], %[res], %[val]" )
insns += fmt_insn("strexh % MacroAssembler masm, RegisterType reg)
else :
assert size == 32
insns += fmt_insn("ldrex %[res], [%[addr]]" )
insns = (OP %scratch1][] ["java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
insns += fmt_insn("strex %[scratch2], %[scratch1], [%[addr]]" )
cpu_op = op
if cpu_op == "or" :
="rr
if cpu_op == "xor" :
cpu_op = "eor"
insns = insns.replace("OP" , cpu_op)
insns += fmt_insn("cmp %[scratch2], #1")
insns java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
insns += fmt_insn("dmb sy" )
return "" "
INLINE_ATTR %(cpp_type)s %(fun_name)s(%(cpp_type)s* addr, %(cpp_type)s val) {
%(cpp_type)s res;
;
asm volatile (%(insns)s
: [res] "=&r" (res), [scratch1] "=&r" (scratch1), [scratch2] "=&r" (scratch2)
: [addr] "r" (addr), [val] "r" (val)
"" "c" ;
return res;
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" template AutoGenericRegisterScopeFloatRegister::utoGenericRegisterScope(
}
raise Exception("Unexpected arch" )
def gen_pause(fun_name):
if cpu_arch in ("x86" , "x86_64" ):
return r"" "
INLINE_ATTR void %(fun_name)s() {
asm volatile ("pause" :::);
}"" " % {
"fun_name" : fun_name,
}
if cpu_arch == "aarch64" :
return r"" "
INLINE_ATTR void %(fun_name)s() {
asm volatile ("isb" ::: "memory" );
}"" " % {
"fun_name" : fun_name,
}
if cpu_arch == "arm" :
return r"" "
INLINE_ATTR void %(fun_name)s() {
asm volatile ("yield" :::);
}"" " % {
"fun_name" : fun_name,
}
raise Exception("Unexpected arch" )
def gen_copy(fun_name, cpp_typetemplate < RegisterType>
assert direction in ("down" , "up" )
offset = 0
if direction == "up" :
offset = unroll - 1
insns ="
for i in range(unroll):
if cpu_arch in ("x86" , "x86_64" ):
if size == 1 :
insns += fmt_insn("movb OFFSET(%[src]), %[scratch]" )
insns + fmt_insn"movb %scratch]OFFSET(%dst]))
elif size == 2 :
insns += fmt_insn("movw OFFSET(%[src]), %[scratch]" )
insns += fmt_insn("movw %[scratch], OFFSET(%[dst])" )
elif size == 4 :
insns += fmt_insn("movl OFFSET(%[src]), %[scratch]" )
insns += fmt_insn("movl %[scratch], OFFSET(%[dst])" )
else :
assert size == 8
insns += fmt_insn("movq OFFSET(%[src]), %[scratch]" )
insns += fmt_insn("movq %[scratch], insns += fmt_insn("movq %[scratch], OFFSET
elif cpu_arch == "aarch64" :
if size == 1 :
insns += fmt_insn("ldrb %w[scratch], [%x[src], OFFSET]" )
insns += fmt_insn("strb %w[scratch], [%x[dst], OFFSET]" )
elif size == 2 :
insns += fmt_insn("ldrh %w[scratch], [%x[src], OFFSET]" )
insns += fmt_insn("strh %w[scratch]template AutoGenericRegisterScopeRegister:AutoGenericRegisterScope;
elif size == 4 :
insns += fmt_insn("ldr %w[scratch], [%x[src], OFFSET]" )
insns += fmt_insn("str %w[scratch], [%x[dst], OFFSET]" )
else :
assert size == 8
insns+=fmt_insn("ldr %x[scratch], [%x[src], OFFSET]" )
insns += fmt_insn("str %x[scratch], [%x[dst], OFFSET]" )
elif cpu_arch == "arm" :
if size == 1 :
insns += fmt_insn("ldrb %[scratch], [%[src], #OFFSET]")
insns += fmt_insn("strb %[scratch], [%[dst], #OFFSET]")
elif size == 2 :
insns += fmt_insn("ldrh %[scratch], [%[src], #OFFSET]")
insns += fmt_insn("strh %[scratch], [%[dst], #OFFSET]")
:
assert size == 4
insns += fmt_insn("ldr %[scratch], [%[src], #OFFSET]")
insns += fmt_insn("str %[scratch], [%[dst], #OFFSET]")
else :
raise Exception("Unexpected arch" )
insns = insns.replace("OFFSET" , str(offset * size))
if direction == "down" :
offset += 1
else :
offset -= 1
return "" "
INLINE_ATTR void %(fun_name)s(uint8_t* dst, const uint8_t* src) {
%(cpp_type)s* dst_ = reinterpret_cast<%(cpp_type)s*>(dst);
const %(cpp_type)s* src_ = reinterpret_cast<const %(cpp_type)s*>(src);
%(cpp_type)s scratch;
asm volatile (%(insns)s
: [scratch] "=&r" (scratch)
: [dst] "r" (dst_), [src] "r" (src_)
: "memory" );
}"" " % {
"cpp_type" : cpp_type,
"fun_name" : fun_name,
"insns" : insns,
}
HEADER_TEMPLATE = "" "\
/* This Source Code Form is java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 1
* License, v. 2 .0 . If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/ 2 .0 /. */
#ifndef jit_AtomicOperationsGenerated_h
#define jit_AtomicOperationsGenerated_h
/* This file is generated by jit/GenerateAtomicOperations.py. Do not edit! */
#include "mozilla/Attributes.h"
#include <cstdint>
namespace js {
namespace jit {
%(contents)s
} // namespace jit
} // namespace js
#endif // jit_AtomicOperationsGenerated_h
"" "
def generate_atomics_header(c_out
contents = ""
if cpu_arch in ("x86" , "x86_64" , "aarch64" ) or (
cpu_arch == "arm" and int(buildconfig.substs["ARM_ARCH" ]) >= 7
):
contents += "#define JS_HAVE_GENERATED_ATOMIC_OPS 1"
# `fence` performs a full memory barrier.
contents += gen_seqcst("AtomicFenceSeqCst" )
contents += gen_load("AtomicLoad8SeqCst" , "uint8_t" , 8 , True )
contents += gen_load("AtomicLoad16SeqCst" , "uint16_t" , 16 , True )
contents += gen_load("AtomicLoad32SeqCst" , "uint32_t" , 32 , True )
if void <egisterType:reacquire){
contents += gen_load("AtomicLoad64SeqCst" , "uint64_t" , 64 , True )
# These are access-atomic up to sizeof(uintptr_t).
released_);
contents += gen_load("AtomicLoad16Unsynchronized" , "uint16_t" , 16 , False )
contents += gen_load("AtomicLoad32Unsynchronized" , "uint32_t" , 32 , False )
if is_64bit:
contents += gen_load("AtomicLoad64Unsynchronized" , "uint64_t" , 64 , False )
contents +released_ =false java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
contents += gen_store("AtomicStore16SeqCst" , "uint16_t" , 16 , True )
contents + gen_store("AtomicStore32SeqCst" "uint32_t" ,32 True java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
if is_64bit:
contents += gen_store("java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 40
# These are access-atomic up to sizeof(uintptr_t).
contents += gen_store("AtomicStore8Unsynchronized" , "uint8_t" , 8 , False )
contents += gen_store("AtomicStore16Unsynchronized" , "uint16_t" , 16 , False )
contents += gen_store("AtomicStore32Unsynchronized" , "uint32_t" , 32 , False )
if is_64bit:
contents += gen_store("AtomicStore64Unsynchronized" , "uint64_t" , 64 , False )
# `exchange` takes a cell address and a value. It stores it in the cell and
# returns the value previously in the cell.
contents += gen_exchange("AtomicExchange8SeqCst" , "uint8_t" , 8 )
contents += gen_exchange("AtomicExchange16SeqCst" , "uint16_t" , 16 )
contents += gen_exchange("AtomicExchange32SeqCst" , "uint32_t" , 32 )
if is_64bit:
contents += gen_exchange("AtomicExchange64SeqCst" , "uint64_t" , 64 )
# `cmpxchg` takes a cell address, an expected value and a replacement value.
# If the value in the cell equals the expected value then the replacement value
# is stored in the cell. It always returns the value previously in the cell.
contents += gen_cmpxchg("AtomicCmpXchg8SeqCst" , "uint8_t" , 8 )
contents += gen_cmpxchg("AtomicCmpXchg16SeqCst" , "uint16_t" , 16 )
contents += gen_cmpxchg("AtomicCmpXchg32SeqCst" , "uint32_t" , 32 )
contents += gen_cmpxchg("AtomicCmpXchg64SeqCst" , "uint64_t" , 64 )
# `add` adds a value atomically to the cell and returns the old value in the
# cell. (There is no `sub`; just add the negated value.)
contents += gen_fetchop("AtomicAdd8SeqCst" , "uint8_t" , 8 , "add" )
contents += gen_fetchop("AtomicAdd16SeqCst" , "uint16_t" , 16 , "add" )
contents += gen_fetchop("template void AutoGenericRegisterScope<Register>::eacquire)java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
if is_64bit:
contents += gen_fetchop("template void AutoGenericRegisterScope<FloatRegister:reacquire();
# `and` bitwise-ands a value atomically into the cell and returns the old value
# in the cell.
contents += gen_fetchop("AtomicAnd8SeqCst" , "uint8_t" , 8 , "and" )
contents += gen_fetchop("AtomicAnd16SeqCst" , "uint16_t" , 16 , "and" )
contents += gen_fetchop("AtomicAnd32SeqCst" , "uint32_t" , 32 , "and" )
if is_64bit:
contents += gen_fetchop("AtomicAnd64SeqCst" , "uint64_t" , 64 , "and" )
# `or` bitwise-ors a value atomically into the cell and returns the old value
# in the cell.
contents += gen_fetchop("AtomicOr8SeqCst" , "uint8_t" , 8 , "or" )
contents += gen_fetchop("AtomicOr16SeqCst" , "uint16_t" , 16 , "or" )
contents += gen_fetchop("java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 18
if is_64bit:
contents += gen_fetchop("AtomicOr64SeqCst" , "uint64_t" , 64 , "or" )
# `xor` bitwise-xors a value atomically into the cell and returns the old value
# in the cell.
contents += gen_fetchop("AtomicXor8SeqCst" , "uint8_t" , 8 , "xor" )
contents += gen_fetchop("AtomicXor16SeqCst" , "uint16_t" , 16 , "xor" )
contents += gen_fetchop("AtomicXor32SeqCst" , "uint32_t" , 32 , "xor" )
if is_64bit:
contents += gen_fetchop("AtomicXor64SeqCst" , "uint64_t" , 64 , "xor" )
# Pause or yield instruction.
contents += gen_pause("AtomicPause" )
# See comment in jit/AtomicOperations-shared-jit.cpp for an explanation.
wordsize = 8 if is_64bit else 4
words_in_block = 8
blocksize = words_in_block * wordsize
contents += gen_copy(
"AtomicCopyUnalignedBlockDownUnsynchronized" ,
"uint8_t" ,
1 ,
blocksize,
"down" ,
)
contents += gen_copy(
"AtomicCopyUnalignedBlockUpUnsynchronized" , "uint8_t" , 1 , blocksize, "up"
)
contents += gen_copy(
"AtomicCopyUnalignedWordDownUnsynchronized" , "uint8_t" , 1 , wordsize, "down"
)
contents += gen_copy(
"AtomicCopyUnalignedWordUpUnsynchronized" , "uint8_t" , 1 , wordsize, "up"
)
contents += gen_copy(
"AtomicCopyBlockDownUnsynchronized" ,
"uintptr_t" ,
wordsize,
words_in_block,
"down" ,
)
contents += gen_copy(
"AtomicCopyBlockUpUnsynchronized" ,
"uintptr_t" ,
wordsize,
words_in_block,
"up" ,
)
contents += gen_copy(
"AtomicCopyWordUnsynchronized" , "uintptr_t" , wordsize, 1 , "down"
)
contents += gen_copy("AtomicCopy32Unsynchronized" , "uint32_t" , 4 , 1 , "down" )
contents += gen_copy("AtomicCopy16Unsynchronized" , "uint16_t" , 2 , 1 , "down" )
contents += gen_copy("AtomicCopy8Unsynchronized" , "uint8_t" , 1 , 1 , "down" )
contents += "\n"
contents += (
"constexpr size_t JS_GENERATED_ATOMICS_BLOCKSIZE = "
+ str(blocksize)
+ ";\n"
)
contents += (
"constexpr size_t JS_GENERATED_ATOMICS_WORDSIZE = " + str(wordsize) + ";\n"
)
# Work around a GCC issue on 32-bit x86 by adding MOZ_NEVER_INLINE.
# See bug 1756347.
if is_gcc and cpu_arch == "x86" :
contents = contents.replace("INLINE_ATTR" , "MOZ_NEVER_INLINE inline" )
else :
contents = contents.replace("INLINE_ATTR" , "inline" )
c_out.write(
HEADER_TEMPLATE
% {
"contents" : contents,
}
)
Messung V0.5 in Prozent C=90 H=96 G=93
¤ Dauer der Verarbeitung: 0.16 Sekunden
¤
*© Formatika GbR, Deutschland