mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1164391 - record an address within the instruction. r=luke (b55506f22)
- Bug 1172638 - guard a test case. r=bbouvier (7e372b400)
- Bug 1155176 - correct return types for atomics. r=luke (16ddf75f0)
- Bug 1172517 - track sharedness in global. r=luke (2b8a664e7)
- pointer style (9f9af957c)
- Bug 1142668: Fix int32x4 to float32x4 conversion in asm.js; r=luke (79867d66f)
- Bug 1155211 - SIMD: Rename lane mutators - with -> replaceLane. r=bbouvier (ea7f5e3f1)
- Bug 1181318 - Eliminate duplicate mRefCnt members in nsRunnable subclasses. r=ehsan (abb9c7d3d)
- Bug 1176406 - IonMonkey: Poor type refinement of element access results during inlininig (873686ca4)
- Bug 1157624: Odin: split parsing/validation from codegen; r=luke (bf20abaf8)
- Bug 1164042 - Log weak map entries in DumpHeapComplete. r=terrence (f9be8e243)
- Bug 1167795 - Share the root and child tracing code in DumpHeapComplete; r=mccr8 (0a946f546)
- Bug 1168103 - "Execution cannot reach the expression "?unknown?" inside this statement in jsfriendapi.cpp". r=evilpies (906b8e714)
- Bug 1168103 - Convert tabs to spaces. r=me (5cf8a2b07)
- Bug 1169692 - Use virtual dispatch in WeakMapTracer instead of function pointers; r=sfink, r=mccr8 (0ce57cae9)
- Bug 1135993 - Remove js::IsInNonStrictPropertySet. r=jorendorff (bf2bee8c7)
- Bug 1164815 - Use an enum to define GlobalObject slot constants r=luke (21e53a9bb)
- Bug 1124291 - added ToInt8 and ToInt16. r=Waldo (350f2ece9)
- Bug 1124291 - SIMD (interpreter): Implemented int8x16 and int16x8 on a CLOSED TREE. r=bbouvier (8055710fb)
- Bug 1165654 - Cleanup how libjpeg-turbo assembly build variables are set. r=mshal (e32f6db51)
- Bug 1155211: Part 3.0 - Implement SIMD[type].extractLane; p=flomerz;bbouvier; r=h4writer (ca61952ba)
- Bug 1127932 - IonMonkey: Inline SIMD.float32x4.add/sub/mul calls; r=bbouvier (0472a833c)
- Bug 1112158 - Optimize MSimdUnbox with GVN. r=bbouvier (b89048669)
- Bug 1136189 - SIMD: inline SIMD constructors with missing arguments. r=bbouvier (e5cdc380f)
- revert some PM changes for escaped expressions (b20b2a292)
- Bug 1147817 - Part 1: Add RegExpInitialize. r=till (b00f0a12b)
- revert some changes, update closer to gecko code (74b20a236)
- Bug 1147817 - Part 2: Use IsRegExp in RegExp constructor. r=till (ffb568ffb)
- Bug 1124456 - Check channel's contentPolicyType to see if it is XMLHttpRequest. r=vporof (b4e4d4aaf)
- Bug 1150697 - Add IP address to the Network Monitor domain tooltip. r=bgrins (ec37b3505)
- Bug 1150697 - Fix confusing messages in Network Monitor tests. r=bgrins (40987b29c)
- Bug 764958 - Show cached network requests in the net monitor. r=jsantell (1507a9c7e)
- add as of Get rid of JSOP_{GET,CALL}UPVAR and simplify code greatly (592202) (29e91f1bc)
- Bug 1155900 - Make destructuring right-hand-side expressions that correspond to left-hand-side object patterns pass the RequireObjectCoercible gauntlet before any properties are destructured out of them. r=shu (3a93c0aa6)
- Bug 1131043 - Part 2: Implement Map[@@species] and Set[@@species] getter. r=evilpie (07bd91ec1)
- Bug 1063946 SIMD: Group tests in logical units - typed objects; r=bbouvier (43f4b18ee)
- Bug 1063946 SIMD: Group tests in logical units - unary operations; r=bbouvier (b30903604)
- Bug 1063946 SIMD: Group tests in logical units - binary operations; r=bbouvier (469f31c8c)
- Bug 1124291 - SIMD (interpreter): Added test cases for int8x16 and inBug 1124291 - SIMD (interpreter): Added test cases for int8x16 and in (e2d35c44b)
- Bug 1156365 - IonMonkey MIPS: Fix build failure on MIPS; rename Registers::code() to Registers::Encoding(). r=rankov (7fc1252e9)
- pointer style (385d63410)
- Bug 1181151 - Fix Registers::GetName typedef issue with clang. r=rankov (fc11c5a13)
- Bug 1163168 - Prettify IonAssemblerBuffer.h. r=dougc (33f0e1430)
- Bug 1165793 - Add executableCopy() back for MIPS. r=sstangl (5b44df890)
- Bug 1139299 - Fix align stack in Simulator-mips::call. r=rankov, r=nbp (d4e45e869)
- Bug 1140821 - IonMonkey: MIPS: Fix profiler enter frame calculating. r=nbp (69c16c5d6)
- Bug 1144005 - IonMonkey: MIPS: Fix encode break instruction. r=rankov (02bb1a736)
- Bug 1147424 - IonMonkey MIPS: Fix build failures on MIPS caused by recent updates (MacroAssemblerMIPS::ma_b). r=rankov (757605049)
- Bug 1147908 - IonMonkey: MIPS: Fix UDiv and UMod for double and merge them. r=rankov (6de529261)
- adapted Bug 1136799 - SIMD (interpreter): Fix order of operations of ReciprocalSqrt. r=bbouvier, a=me (2290b4e19)
- Bug 1150836 - SIMD (interpreter): change order of operations of ReciprocalSqrtApproximation. r=bbouvier (35a3354b5)
- Bug 1153602 - SIMD (interpreter): Added more test cases for ReciprocalSqrtApproximation. r=Waldo (aaedd70d6)
- Bug 1148494: SimdUnbox shouldn't be removed; r=sunfish (c120c51a7)
- pointer style (5f3ce20ca)
- Bug 1061909: Add breakdown argument to Debugger.Memory.prototype.takeCensus, covering all existing count types. r=fitzgen (3503e969b)
- Bug 1061909: Add documentation for Debugger.Memory.prototype.takeCensus's 'breakdown' parameter. r=fitzgen (1cd40cc94)
- Bug 1061909: Define a testing function to introduce easily traceable objects. r=fitzgen (f6e09a60b)
- Bug 1061909: Arrange for trees of census counts to be traced by the GC. r=fitzgen (13c7fb169)
- Bug 1061909: Implement 'allocationStack' breakdown for Debugger.Memory.prototype.takeCensus. r=fitzgen (c7cb27fe6)
- Bug 1061909 followup: Add missing 'override' keyword to count() methods in DebuggerMemory.cpp. rs=ehsan (059b6b9eb)
- Bug 1060567: Debugger.Memory.prototype.takeCensus: provide byte counts on request. r=fitzgen (b6a0f1bef)
- Bug 1169639 - Make intrinsicsHolder-accesses fallible, now that it's possible to access it without having previously gone through intrinsics-object creation code to ensure its existence. r=shu (3fe01f933)
- Bug 1159469 - Add public jsapi ES6 Set convenience functions; r=jorendorff (ca74a2a09)
- Bug 1159469 - Add ForEach C++ public function for ES6 Maps/Sets; r=jorendorff (19f28135a)
- fix parenthesis and redundant new lines (63618bc8a)
- Bug 1151333: Reserve enough stack space for SIMD shuffles; r=sunfish (100f2fbc8)
- Bug 1159469 - Add public jsapi ES6 Map delete method; r=jorendorff (b1db40c51)
- Bug 1159469 - Make sure public jsapi Map/Set calls deal with compartments/proxies; r=bz r=jorendorff (69bf75c49)
- Bug 1159469 - Add get function to JSJitCallArguments; r=jorendorff (583cec75a)
- Bug 1173722: Part 1 - Capitalize all the SIMD types names; r=nbp (70c68229f)
This commit is contained in:
+15
-42
@@ -3845,11 +3845,6 @@ VPX_X86_ASM=
|
||||
VPX_ARM_ASM=
|
||||
LIBJPEG_TURBO_AS=
|
||||
LIBJPEG_TURBO_ASFLAGS=
|
||||
LIBJPEG_TURBO_X86_ASM=
|
||||
LIBJPEG_TURBO_X64_ASM=
|
||||
LIBJPEG_TURBO_ARM_ASM=
|
||||
LIBJPEG_TURBO_ARM64_ASM=
|
||||
LIBJPEG_TURBO_MIPS_ASM=
|
||||
MOZ_PERMISSIONS=1
|
||||
MOZ_PLACES=1
|
||||
MOZ_SOCIAL=1
|
||||
@@ -5856,55 +5851,47 @@ dnl files.
|
||||
if test -n "$MOZ_LIBJPEG_TURBO"; then
|
||||
|
||||
dnl Do we support libjpeg-turbo on this platform?
|
||||
case "$OS_ARCH:$OS_TEST" in
|
||||
Darwin:i?86)
|
||||
case "$OS_ARCH:$CPU_ARCH" in
|
||||
Darwin:x86)
|
||||
LIBJPEG_TURBO_ASFLAGS="-f macho32 -rnasm -pnasm -DPIC -DMACHO"
|
||||
LIBJPEG_TURBO_X86_ASM=1
|
||||
;;
|
||||
Darwin:x86_64)
|
||||
LIBJPEG_TURBO_ASFLAGS="-f macho64 -rnasm -pnasm -D__x86_64__ -DPIC -DMACHO"
|
||||
LIBJPEG_TURBO_X64_ASM=1
|
||||
;;
|
||||
WINNT:x86|WINNT:i?86)
|
||||
WINNT:x86)
|
||||
LIBJPEG_TURBO_ASFLAGS="-f win32 -rnasm -pnasm -DPIC -DWIN32"
|
||||
LIBJPEG_TURBO_X86_ASM=1
|
||||
;;
|
||||
WINNT:x86_64)
|
||||
LIBJPEG_TURBO_ASFLAGS="-f win64 -rnasm -pnasm -D__x86_64__ -DPIC -DWIN64 -DMSVC"
|
||||
LIBJPEG_TURBO_X64_ASM=1
|
||||
;;
|
||||
*:arm*)
|
||||
*:arm)
|
||||
LIBJPEG_TURBO_ASFLAGS="-march=armv7-a -mfpu=neon"
|
||||
LIBJPEG_TURBO_ARM_ASM=1
|
||||
;;
|
||||
*:aarch64*)
|
||||
*:aarch64)
|
||||
LIBJPEG_TURBO_ASFLAGS="-march=armv8-a"
|
||||
LIBJPEG_TURBO_ARM64_ASM=1
|
||||
;;
|
||||
*:mips*)
|
||||
*:mips)
|
||||
LIBJPEG_TURBO_ASFLAGS="-mdspr2"
|
||||
LIBJPEG_TURBO_MIPS_ASM=1
|
||||
;;
|
||||
*:x86|*:i?86)
|
||||
*:x86)
|
||||
if $CC -E -dM -</dev/null | grep -q __ELF__; then
|
||||
LIBJPEG_TURBO_ASFLAGS="-f elf32 -rnasm -pnasm -DPIC -DELF"
|
||||
LIBJPEG_TURBO_X86_ASM=1
|
||||
fi
|
||||
;;
|
||||
*:x86_64)
|
||||
if $CC -E -dM -</dev/null | grep -q __ELF__; then
|
||||
LIBJPEG_TURBO_ASFLAGS="-f elf64 -rnasm -pnasm -D__x86_64__ -DPIC -DELF"
|
||||
LIBJPEG_TURBO_X64_ASM=1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
|
||||
if test -n "$LIBJPEG_TURBO_ASFLAGS"; then
|
||||
case "$CPU_ARCH" in
|
||||
dnl If we're on an x86 or x64 system which supports libjpeg-turbo's asm routines
|
||||
dnl and --disable-libjpeg-turbo wasn't passed, check for Yasm, and error out if
|
||||
dnl it doesn't exist or we have too old of a version.
|
||||
if test -n "$LIBJPEG_TURBO_X86_ASM" -o -n "$LIBJPEG_TURBO_X64_ASM" ; then
|
||||
x86_64|x86)
|
||||
LIBJPEG_TURBO_AS=$YASM
|
||||
|
||||
if test -z "$LIBJPEG_TURBO_AS" ; then
|
||||
@@ -5922,21 +5909,12 @@ if test -n "$LIBJPEG_TURBO_X86_ASM" -o -n "$LIBJPEG_TURBO_X64_ASM" ; then
|
||||
AC_MSG_ERROR([Yasm 1.1 or greater is required to build with libjpeg-turbo's optimized JPEG decoding routines, but you appear to have version $_YASM_MAJOR_VERSION.$_YASM_MINOR_VERSION. Upgrade to the newest version or configure with --disable-libjpeg-turbo to use the pure C JPEG decoder. See https://developer.mozilla.org/en/YASM for more details.])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl If we're on an ARM system which supports libjpeg-turbo's asm routines and
|
||||
dnl --disable-libjpeg-turbo wasn't passed, use the C compiler as the assembler.
|
||||
if test -n "$LIBJPEG_TURBO_ARM_ASM" ; then
|
||||
echo "Using $AS as the assembler for ARM code."
|
||||
;;
|
||||
dnl On other platforms, use the C compiler as the assembler.
|
||||
*)
|
||||
LIBJPEG_TURBO_AS=$AS
|
||||
fi
|
||||
|
||||
if test -n "$LIBJPEG_TURBO_X86_ASM"; then
|
||||
AC_DEFINE(LIBJPEG_TURBO_X86_ASM)
|
||||
elif test -n "$LIBJPEG_TURBO_X64_ASM"; then
|
||||
AC_DEFINE(LIBJPEG_TURBO_X64_ASM)
|
||||
elif test -n "$LIBJPEG_TURBO_ARM_ASM"; then
|
||||
AC_DEFINE(LIBJPEG_TURBO_ARM_ASM)
|
||||
;;
|
||||
esac
|
||||
elif test -n "$MOZ_LIBJPEG_TURBO"; then
|
||||
dnl Warn if we're not building the optimized routines, even though the user
|
||||
dnl didn't specify --disable-libjpeg-turbo.
|
||||
@@ -8543,11 +8521,6 @@ AC_SUBST(MOZ_INSTRUMENT_EVENT_LOOP)
|
||||
AC_SUBST(MOZ_CODE_COVERAGE)
|
||||
AC_SUBST(LIBJPEG_TURBO_AS)
|
||||
AC_SUBST_LIST(LIBJPEG_TURBO_ASFLAGS)
|
||||
AC_SUBST(LIBJPEG_TURBO_X86_ASM)
|
||||
AC_SUBST(LIBJPEG_TURBO_X64_ASM)
|
||||
AC_SUBST(LIBJPEG_TURBO_ARM_ASM)
|
||||
AC_SUBST(LIBJPEG_TURBO_ARM64_ASM)
|
||||
AC_SUBST(LIBJPEG_TURBO_MIPS_ASM)
|
||||
|
||||
AC_SUBST(MOZ_PACKAGE_JSSHELL)
|
||||
AC_SUBST(MOZ_FOLD_LIBS)
|
||||
|
||||
+7
-11
@@ -10393,15 +10393,13 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
|
||||
# indexed setter. That's how the object would normally behave if
|
||||
# you tried to set the property on it. That means we don't need to
|
||||
# do anything special for Xrays here.
|
||||
set += fill(
|
||||
set += dedent(
|
||||
"""
|
||||
if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
|
||||
return js::IsInNonStrictPropertySet(cx)
|
||||
? opresult.succeed()
|
||||
: ThrowErrorMessage(cx, MSG_NO_INDEXED_SETTER, "${name}");
|
||||
*defined = true;
|
||||
return opresult.failNoIndexedSetter();
|
||||
}
|
||||
""",
|
||||
name=self.descriptor.name)
|
||||
""")
|
||||
|
||||
namedSetter = self.descriptor.operations['NamedSetter']
|
||||
if namedSetter:
|
||||
@@ -10434,13 +10432,11 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
|
||||
$*{presenceChecker}
|
||||
|
||||
if (found) {
|
||||
return js::IsInNonStrictPropertySet(cx)
|
||||
? opresult.succeed()
|
||||
: ThrowErrorMessage(cx, MSG_NO_NAMED_SETTER, "${name}");
|
||||
*defined = true;
|
||||
return opresult.failNoNamedSetter();
|
||||
}
|
||||
""",
|
||||
presenceChecker=CGProxyNamedPresenceChecker(self.descriptor, foundVar="found").define(),
|
||||
name=self.descriptor.name)
|
||||
presenceChecker=CGProxyNamedPresenceChecker(self.descriptor, foundVar="found").define())
|
||||
set += ("return mozilla::dom::DOMProxyHandler::defineProperty(%s);\n" %
|
||||
", ".join(a.name for a in self.args))
|
||||
return set
|
||||
|
||||
@@ -34,8 +34,6 @@ MSG_DEF(MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 1, JSEXN_TYPEERR, "\"this\" objec
|
||||
MSG_DEF(MSG_NOT_IN_UNION, 2, JSEXN_TYPEERR, "{0} could not be converted to any of: {1}.")
|
||||
MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, JSEXN_TYPEERR, "Illegal constructor.")
|
||||
MSG_DEF(MSG_CONSTRUCTOR_WITHOUT_NEW, 1, JSEXN_TYPEERR, "Constructor {0} requires 'new'")
|
||||
MSG_DEF(MSG_NO_INDEXED_SETTER, 1, JSEXN_TYPEERR, "{0} doesn't have an indexed property setter.")
|
||||
MSG_DEF(MSG_NO_NAMED_SETTER, 1, JSEXN_TYPEERR, "{0} doesn't have a named property setter.")
|
||||
MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, JSEXN_TYPEERR, "Non-finite value is out of range for {0}.")
|
||||
MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "Value is out of range for {0}.")
|
||||
MSG_DEF(MSG_NOT_SEQUENCE, 1, JSEXN_TYPEERR, "{0} can't be converted to a sequence.")
|
||||
|
||||
@@ -35,8 +35,6 @@ private:
|
||||
class DelayedResolveOrReject : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DelayedResolveOrReject)
|
||||
|
||||
DelayedResolveOrReject(MediaTaskQueue* aTaskQueue,
|
||||
TestPromise::Private* aPromise,
|
||||
TestPromise::ResolveOrRejectValue aValue,
|
||||
|
||||
@@ -25,8 +25,6 @@ public:
|
||||
: mManager(aManager), mDebugger(aDebugger), mHasListeners(aHasListeners)
|
||||
{ }
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
private:
|
||||
~RegisterDebuggerRunnable()
|
||||
{ }
|
||||
@@ -40,8 +38,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(RegisterDebuggerRunnable, nsIRunnable);
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class WorkerDebuggerEnumerator final : public nsISimpleEnumerator
|
||||
|
||||
+3
-1
@@ -142,6 +142,8 @@ class ObjectOpResult
|
||||
JS_PUBLIC_API(bool) failCantDeleteWindowElement();
|
||||
JS_PUBLIC_API(bool) failCantDeleteWindowNamedProperty();
|
||||
JS_PUBLIC_API(bool) failCantPreventExtensions();
|
||||
JS_PUBLIC_API(bool) failNoNamedSetter();
|
||||
JS_PUBLIC_API(bool) failNoIndexedSetter();
|
||||
|
||||
uint32_t failureCode() const {
|
||||
MOZ_ASSERT(!ok());
|
||||
@@ -668,7 +670,7 @@ struct JSClass {
|
||||
// the beginning of every global object's slots for use by the
|
||||
// application.
|
||||
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
|
||||
#define JSCLASS_GLOBAL_SLOT_COUNT (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 33)
|
||||
#define JSCLASS_GLOBAL_SLOT_COUNT (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 35)
|
||||
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
||||
#define JSCLASS_GLOBAL_FLAGS \
|
||||
|
||||
@@ -32,6 +32,14 @@ ToBooleanSlow(JS::HandleValue v);
|
||||
extern JS_PUBLIC_API(bool)
|
||||
ToNumberSlow(JSContext* cx, JS::Value v, double* dp);
|
||||
|
||||
/* DO NOT CALL THIS. Use JS::ToInt8. */
|
||||
extern JS_PUBLIC_API(bool)
|
||||
ToInt8Slow(JSContext *cx, JS::HandleValue v, int8_t *out);
|
||||
|
||||
/* DO NOT CALL THIS. Use JS::ToInt16. */
|
||||
extern JS_PUBLIC_API(bool)
|
||||
ToInt16Slow(JSContext *cx, JS::HandleValue v, int16_t *out);
|
||||
|
||||
/* DO NOT CALL THIS. Use JS::ToInt32. */
|
||||
extern JS_PUBLIC_API(bool)
|
||||
ToInt32Slow(JSContext* cx, JS::HandleValue v, int32_t* out);
|
||||
@@ -168,6 +176,19 @@ ToUint32(JSContext* cx, HandleValue v, uint32_t* out)
|
||||
return js::ToUint32Slow(cx, v, out);
|
||||
}
|
||||
|
||||
/* ES6 draft 20141224, 7.1.7. */
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
ToInt16(JSContext *cx, JS::HandleValue v, int16_t *out)
|
||||
{
|
||||
detail::AssertArgumentsAreSane(cx, v);
|
||||
|
||||
if (v.isInt32()) {
|
||||
*out = int16_t(v.toInt32());
|
||||
return true;
|
||||
}
|
||||
return js::ToInt16Slow(cx, v, out);
|
||||
}
|
||||
|
||||
/* ES6 draft 20141224, 7.1.8. */
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
ToUint16(JSContext* cx, HandleValue v, uint16_t* out)
|
||||
@@ -181,6 +202,19 @@ ToUint16(JSContext* cx, HandleValue v, uint16_t* out)
|
||||
return js::ToUint16Slow(cx, v, out);
|
||||
}
|
||||
|
||||
/* ES6 draft 20141224, 7.1.9 */
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
ToInt8(JSContext *cx, JS::HandleValue v, int8_t *out)
|
||||
{
|
||||
detail::AssertArgumentsAreSane(cx, v);
|
||||
|
||||
if (v.isInt32()) {
|
||||
*out = int8_t(v.toInt32());
|
||||
return true;
|
||||
}
|
||||
return js::ToInt8Slow(cx, v, out);
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-standard, with behavior similar to that of ToInt32, except in its
|
||||
* producing an int64_t.
|
||||
@@ -482,6 +516,20 @@ ToUint32(double d)
|
||||
return detail::ToUintWidth<uint32_t>(d);
|
||||
}
|
||||
|
||||
/* WEBIDL 4.2.4 */
|
||||
inline int8_t
|
||||
ToInt8(double d)
|
||||
{
|
||||
return detail::ToIntWidth<int8_t>(d);
|
||||
}
|
||||
|
||||
/* WEBIDL 4.2.6 */
|
||||
inline int16_t
|
||||
ToInt16(double d)
|
||||
{
|
||||
return detail::ToIntWidth<int16_t>(d);
|
||||
}
|
||||
|
||||
/* WEBIDL 4.2.10 */
|
||||
inline int64_t
|
||||
ToInt64(double d)
|
||||
|
||||
@@ -133,11 +133,6 @@ class JS_PUBLIC_API(CallbackTracer) : public JSTracer
|
||||
contextName_(nullptr), contextIndex_(InvalidIndex), contextFunctor_(nullptr)
|
||||
{}
|
||||
|
||||
// Update the trace callback.
|
||||
void setTraceCallback(JSTraceCallback traceCallback) {
|
||||
callback = traceCallback;
|
||||
}
|
||||
|
||||
// Test if the given callback is the same as our callback.
|
||||
bool hasCallback(JSTraceCallback maybeCallback) const {
|
||||
return maybeCallback == callback;
|
||||
|
||||
@@ -480,6 +480,13 @@ OnOutOfBounds()
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
|
||||
}
|
||||
|
||||
static void
|
||||
OnImpreciseConversion()
|
||||
{
|
||||
JSContext* cx = JSRuntime::innermostAsmJSActivation()->cx();
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SIMD_FAILED_CONVERSION);
|
||||
}
|
||||
|
||||
static bool
|
||||
AsmJSHandleExecutionInterrupt()
|
||||
{
|
||||
@@ -676,6 +683,8 @@ AddressOf(AsmJSImmKind kind, ExclusiveContext* cx)
|
||||
return RedirectCall(FuncCast(OnDetached), Args_General0);
|
||||
case AsmJSImm_OnOutOfBounds:
|
||||
return RedirectCall(FuncCast(OnOutOfBounds), Args_General0);
|
||||
case AsmJSImm_OnImpreciseConversion:
|
||||
return RedirectCall(FuncCast(OnImpreciseConversion), Args_General0);
|
||||
case AsmJSImm_HandleExecutionInterrupt:
|
||||
return RedirectCall(FuncCast(AsmJSHandleExecutionInterrupt), Args_General0);
|
||||
case AsmJSImm_InvokeFromAsmJS_Ignore:
|
||||
|
||||
+3834
-1119
File diff suppressed because it is too large
Load Diff
+336
-38
@@ -1351,7 +1351,6 @@ MapObject::extract(CallReceiver call)
|
||||
uint32_t
|
||||
MapObject::size(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
MOZ_ASSERT(MapObject::is(obj));
|
||||
ValueMap& map = extract(obj);
|
||||
static_assert(sizeof(map.count()) <= sizeof(uint32_t),
|
||||
"map count must be precisely representable as a JS number");
|
||||
@@ -1377,8 +1376,6 @@ bool
|
||||
MapObject::get(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, MutableHandleValue rval)
|
||||
{
|
||||
MOZ_ASSERT(MapObject::is(obj));
|
||||
|
||||
ValueMap& map = extract(obj);
|
||||
AutoHashableValueRooter k(cx);
|
||||
|
||||
@@ -1410,8 +1407,6 @@ MapObject::get(JSContext* cx, unsigned argc, Value* vp)
|
||||
bool
|
||||
MapObject::has(JSContext* cx, HandleObject obj, HandleValue key, bool* rval)
|
||||
{
|
||||
MOZ_ASSERT(MapObject::is(obj));
|
||||
|
||||
ValueMap& map = extract(obj);
|
||||
AutoHashableValueRooter k(cx);
|
||||
|
||||
@@ -1466,7 +1461,23 @@ MapObject::set(JSContext* cx, unsigned argc, Value* vp)
|
||||
}
|
||||
|
||||
bool
|
||||
MapObject::delete_impl(JSContext* cx, const CallArgs& args)
|
||||
MapObject::delete_(JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
|
||||
{
|
||||
ValueMap &map = extract(obj);
|
||||
AutoHashableValueRooter k(cx);
|
||||
|
||||
if (!k.setValue(cx, key))
|
||||
return false;
|
||||
|
||||
if (!map.remove(k, rval)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MapObject::delete_impl(JSContext *cx, const CallArgs& args)
|
||||
{
|
||||
// MapObject::mark does not mark deleted entries. Incremental GC therefore
|
||||
// requires that no RelocatableValue objects pointing to heap values be
|
||||
@@ -1501,7 +1512,6 @@ bool
|
||||
MapObject::iterator(JSContext* cx, IteratorKind kind,
|
||||
HandleObject obj, MutableHandleValue iter)
|
||||
{
|
||||
MOZ_ASSERT(MapObject::is(obj));
|
||||
ValueMap& map = extract(obj);
|
||||
Rooted<JSObject*> iterobj(cx, MapIteratorObject::create(cx, obj, &map, kind));
|
||||
return iterobj && (iter.setObject(*iterobj), true);
|
||||
@@ -1571,7 +1581,6 @@ MapObject::clear(JSContext* cx, unsigned argc, Value* vp)
|
||||
bool
|
||||
MapObject::clear(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
MOZ_ASSERT(MapObject::is(obj));
|
||||
ValueMap& map = extract(obj);
|
||||
if (!map.clear()) {
|
||||
ReportOutOfMemory(cx);
|
||||
@@ -1955,7 +1964,20 @@ SetObject::is(HandleValue v)
|
||||
return v.isObject() && v.toObject().hasClass(&class_) && v.toObject().as<SetObject>().getPrivate();
|
||||
}
|
||||
|
||||
ValueSet&
|
||||
bool
|
||||
SetObject::is(HandleObject o)
|
||||
{
|
||||
return o->hasClass(&class_) && o->as<SetObject>().getPrivate();
|
||||
}
|
||||
|
||||
ValueSet &
|
||||
SetObject::extract(HandleObject o)
|
||||
{
|
||||
MOZ_ASSERT(o->hasClass(&SetObject::class_));
|
||||
return *o->as<SetObject>().getData();
|
||||
}
|
||||
|
||||
ValueSet &
|
||||
SetObject::extract(CallReceiver call)
|
||||
{
|
||||
MOZ_ASSERT(call.thisv().isObject());
|
||||
@@ -1963,6 +1985,16 @@ SetObject::extract(CallReceiver call)
|
||||
return *static_cast<SetObject&>(call.thisv().toObject()).getData();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SetObject::size(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
MOZ_ASSERT(SetObject::is(obj));
|
||||
ValueSet &set = extract(obj);
|
||||
static_assert(sizeof(set.count()) <= sizeof(uint32_t),
|
||||
"set count must be precisely representable as a JS number");
|
||||
return set.count();
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::size_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
@@ -1994,7 +2026,22 @@ SetObject::has_impl(JSContext* cx, const CallArgs& args)
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::has(JSContext* cx, unsigned argc, Value* vp)
|
||||
SetObject::has(JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
|
||||
{
|
||||
MOZ_ASSERT(SetObject::is(obj));
|
||||
|
||||
ValueSet &set = extract(obj);
|
||||
AutoHashableValueRooter k(cx);
|
||||
|
||||
if (!k.setValue(cx, key))
|
||||
return false;
|
||||
|
||||
*rval = set.has(k);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::has(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<SetObject::is, SetObject::has_impl>(cx, args);
|
||||
@@ -2024,7 +2071,25 @@ SetObject::add(JSContext* cx, unsigned argc, Value* vp)
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::delete_impl(JSContext* cx, const CallArgs& args)
|
||||
SetObject::delete_(JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
|
||||
{
|
||||
MOZ_ASSERT(SetObject::is(obj));
|
||||
|
||||
ValueSet &set = extract(obj);
|
||||
AutoHashableValueRooter k(cx);
|
||||
|
||||
if (!k.setValue(cx, key))
|
||||
return false;
|
||||
|
||||
if (!set.remove(k, rval)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::delete_impl(JSContext *cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(is(args.thisv()));
|
||||
|
||||
@@ -2047,7 +2112,17 @@ SetObject::delete_(JSContext* cx, unsigned argc, Value* vp)
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind)
|
||||
SetObject::iterator(JSContext *cx, IteratorKind kind,
|
||||
HandleObject obj, MutableHandleValue iter)
|
||||
{
|
||||
MOZ_ASSERT(SetObject::is(obj));
|
||||
ValueSet &set = extract(obj);
|
||||
Rooted<JSObject*> iterobj(cx, SetIteratorObject::create(cx, obj, &set, kind));
|
||||
return iterobj && (iter.setObject(*iterobj), true);
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::iterator_impl(JSContext *cx, const CallArgs& args, IteratorKind kind)
|
||||
{
|
||||
Rooted<SetObject*> setobj(cx, &args.thisv().toObject().as<SetObject>());
|
||||
ValueSet& set = *setobj->getData();
|
||||
@@ -2085,7 +2160,19 @@ SetObject::entries(JSContext* cx, unsigned argc, Value* vp)
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::clear_impl(JSContext* cx, const CallArgs& args)
|
||||
SetObject::clear(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
MOZ_ASSERT(SetObject::is(obj));
|
||||
ValueSet &set = extract(obj);
|
||||
if (!set.clear()) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SetObject::clear_impl(JSContext *cx, const CallArgs& args)
|
||||
{
|
||||
Rooted<SetObject*> setobj(cx, &args.thisv().toObject().as<SetObject>());
|
||||
if (!setobj->getData()->clear()) {
|
||||
@@ -2121,6 +2208,98 @@ js::InitSelfHostingCollectionIteratorFunctions(JSContext* cx, HandleObject obj)
|
||||
return JS_DefineFunctions(cx, obj, selfhosting_collection_iterator_methods);
|
||||
}
|
||||
|
||||
/*** JS static utility functions *********************************************/
|
||||
|
||||
static
|
||||
bool
|
||||
forEach(const char* funcName, JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue thisArg)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
RootedId forEachId(cx, NameToId(cx->names().forEach));
|
||||
RootedFunction forEachFunc(cx, JS::GetSelfHostedFunction(cx, funcName, forEachId, 2));
|
||||
if (!forEachFunc)
|
||||
return false;
|
||||
InvokeArgs args(cx);
|
||||
if (!args.init(2))
|
||||
return false;
|
||||
args.setCallee(JS::ObjectValue(*forEachFunc));
|
||||
args.setThis(JS::ObjectValue(*obj));
|
||||
args[0].set(callbackFn);
|
||||
args[1].set(thisArg);
|
||||
return Invoke(cx, args);
|
||||
}
|
||||
|
||||
// Handles Clear/Size for public jsapi map/set access
|
||||
template<typename RetT>
|
||||
RetT
|
||||
CallObjFunc(RetT(*ObjFunc)(JSContext*, HandleObject), JSContext* cx, HandleObject obj)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
|
||||
// Always unwrap, in case this is an xray or cross-compartment wrapper.
|
||||
RootedObject unwrappedObj(cx);
|
||||
unwrappedObj = UncheckedUnwrap(obj);
|
||||
|
||||
// Enter the compartment of the backing object before calling functions on
|
||||
// it.
|
||||
JSAutoCompartment ac(cx, unwrappedObj);
|
||||
return ObjFunc(cx, unwrappedObj);
|
||||
}
|
||||
|
||||
// Handles Has/Delete for public jsapi map/set access
|
||||
bool
|
||||
CallObjFunc(bool(*ObjFunc)(JSContext *cx, HandleObject obj, HandleValue key, bool *rval),
|
||||
JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, key);
|
||||
|
||||
// Always unwrap, in case this is an xray or cross-compartment wrapper.
|
||||
RootedObject unwrappedObj(cx);
|
||||
unwrappedObj = UncheckedUnwrap(obj);
|
||||
JSAutoCompartment ac(cx, unwrappedObj);
|
||||
|
||||
// If we're working with a wrapped map/set, rewrap the key into the
|
||||
// compartment of the unwrapped map/set.
|
||||
RootedValue wrappedKey(cx, key);
|
||||
if (obj != unwrappedObj) {
|
||||
if (!JS_WrapValue(cx, &wrappedKey))
|
||||
return false;
|
||||
}
|
||||
return ObjFunc(cx, unwrappedObj, wrappedKey, rval);
|
||||
}
|
||||
|
||||
// Handles iterator generation for public jsapi map/set access
|
||||
template<typename Iter>
|
||||
bool
|
||||
CallObjFunc(bool(*ObjFunc)(JSContext* cx, Iter kind,
|
||||
HandleObject obj, MutableHandleValue iter),
|
||||
JSContext *cx, Iter iterType, HandleObject obj, MutableHandleValue rval)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
|
||||
// Always unwrap, in case this is an xray or cross-compartment wrapper.
|
||||
RootedObject unwrappedObj(cx);
|
||||
unwrappedObj = UncheckedUnwrap(obj);
|
||||
{
|
||||
// Retrieve the iterator while in the unwrapped map/set's compartment,
|
||||
// otherwise we'll crash on a compartment assert.
|
||||
JSAutoCompartment ac(cx, unwrappedObj);
|
||||
if (!ObjFunc(cx, iterType, unwrappedObj, rval))
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the caller is in a different compartment than the map/set, rewrap the
|
||||
// iterator object into the caller's compartment.
|
||||
if (obj != unwrappedObj) {
|
||||
if (!JS_WrapValue(cx, rval))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*** JS public APIs **********************************************************/
|
||||
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
@@ -2132,63 +2311,182 @@ JS::NewMapObject(JSContext* cx)
|
||||
JS_PUBLIC_API(uint32_t)
|
||||
JS::MapSize(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
return MapObject::size(cx, obj);
|
||||
return CallObjFunc<uint32_t>(&MapObject::size, cx, obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::MapGet(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, MutableHandleValue rval)
|
||||
JS::MapGet(JSContext* cx, HandleObject obj, HandleValue key, MutableHandleValue rval)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, key, rval);
|
||||
return MapObject::get(cx, obj, key, rval);
|
||||
assertSameCompartment(cx, obj, key, rval);
|
||||
|
||||
// Unwrap the object, and enter its compartment. If object isn't wrapped,
|
||||
// this is essentially a noop.
|
||||
RootedObject unwrappedObj(cx);
|
||||
unwrappedObj = UncheckedUnwrap(obj);
|
||||
{
|
||||
JSAutoCompartment ac(cx, unwrappedObj);
|
||||
RootedValue wrappedKey(cx, key);
|
||||
|
||||
// If we passed in a wrapper, wrap our key into its compartment now.
|
||||
if (obj != unwrappedObj) {
|
||||
if (!JS_WrapValue(cx, &wrappedKey))
|
||||
return false;
|
||||
}
|
||||
if (!MapObject::get(cx, unwrappedObj, wrappedKey, rval))
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we passed in a wrapper, wrap our return value on the way out.
|
||||
if (obj != unwrappedObj) {
|
||||
if (!JS_WrapValue(cx, rval))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::MapSet(JSContext *cx, HandleObject obj, HandleValue key, HandleValue val)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, key, val);
|
||||
|
||||
// Unwrap the object, and enter its compartment. If object isn't wrapped,
|
||||
// this is essentially a noop.
|
||||
RootedObject unwrappedObj(cx);
|
||||
unwrappedObj = UncheckedUnwrap(obj);
|
||||
{
|
||||
JSAutoCompartment ac(cx, unwrappedObj);
|
||||
|
||||
// If we passed in a wrapper, wrap both key and value before adding to
|
||||
// the map
|
||||
RootedValue wrappedKey(cx, key);
|
||||
RootedValue wrappedValue(cx, val);
|
||||
if (obj != unwrappedObj) {
|
||||
if (!JS_WrapValue(cx, &wrappedKey) ||
|
||||
!JS_WrapValue(cx, &wrappedValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return MapObject::set(cx, unwrappedObj, wrappedKey, wrappedValue);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::MapHas(JSContext* cx, HandleObject obj, HandleValue key, bool* rval)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, key);
|
||||
return MapObject::has(cx, obj, key, rval);
|
||||
return CallObjFunc(MapObject::has, cx, obj, key, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::MapSet(JSContext* cx, HandleObject obj,
|
||||
HandleValue key, HandleValue val)
|
||||
JS::MapDelete(JSContext *cx, HandleObject obj, HandleValue key, bool* rval)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, key, val);
|
||||
return MapObject::set(cx, obj, key, val);
|
||||
return CallObjFunc(MapObject::delete_, cx, obj, key, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::MapClear(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
return MapObject::clear(cx, obj);
|
||||
return CallObjFunc(&MapObject::clear, cx, obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::MapKeys(JSContext* cx, HandleObject obj, MutableHandleValue rval)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, rval);
|
||||
return MapObject::iterator(cx, MapObject::Keys, obj, rval);
|
||||
return CallObjFunc(&MapObject::iterator, cx, MapObject::Keys, obj, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::MapValues(JSContext* cx, HandleObject obj, MutableHandleValue rval)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, rval);
|
||||
return MapObject::iterator(cx, MapObject::Values, obj, rval);
|
||||
return CallObjFunc(&MapObject::iterator, cx, MapObject::Values, obj, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::MapEntries(JSContext* cx, HandleObject obj, MutableHandleValue rval)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, rval);
|
||||
return MapObject::iterator(cx, MapObject::Entries, obj, rval);
|
||||
return CallObjFunc(&MapObject::iterator, cx, MapObject::Entries, obj, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::MapForEach(JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue thisVal)
|
||||
{
|
||||
return forEach("MapForEach", cx, obj, callbackFn, thisVal);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS::NewSetObject(JSContext *cx)
|
||||
{
|
||||
return SetObject::create(cx);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uint32_t)
|
||||
JS::SetSize(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
return CallObjFunc<uint32_t>(&SetObject::size, cx, obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::SetAdd(JSContext *cx, HandleObject obj, HandleValue key)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, key);
|
||||
|
||||
// Unwrap the object, and enter its compartment. If object isn't wrapped,
|
||||
// this is essentially a noop.
|
||||
RootedObject unwrappedObj(cx);
|
||||
unwrappedObj = UncheckedUnwrap(obj);
|
||||
{
|
||||
JSAutoCompartment ac(cx, unwrappedObj);
|
||||
|
||||
// If we passed in a wrapper, wrap key before adding to the set
|
||||
RootedValue wrappedKey(cx, key);
|
||||
if (obj != unwrappedObj) {
|
||||
if (!JS_WrapValue(cx, &wrappedKey))
|
||||
return false;
|
||||
}
|
||||
return SetObject::add(cx, unwrappedObj, wrappedKey);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::SetHas(JSContext* cx, HandleObject obj, HandleValue key, bool* rval)
|
||||
{
|
||||
return CallObjFunc(SetObject::has, cx, obj, key, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::SetDelete(JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
|
||||
{
|
||||
return CallObjFunc(SetObject::delete_, cx, obj, key, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::SetClear(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
return CallObjFunc(&SetObject::clear, cx, obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::SetKeys(JSContext* cx, HandleObject obj, MutableHandleValue rval)
|
||||
{
|
||||
return SetValues(cx, obj, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::SetValues(JSContext* cx, HandleObject obj, MutableHandleValue rval)
|
||||
{
|
||||
return CallObjFunc(&SetObject::iterator, cx, SetObject::Values, obj, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::SetEntries(JSContext* cx, HandleObject obj, MutableHandleValue rval)
|
||||
{
|
||||
return CallObjFunc(&SetObject::iterator, cx, SetObject::Entries, obj, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::SetForEach(JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue thisVal)
|
||||
{
|
||||
return forEach("SetForEach", cx, obj, callbackFn, thisVal);
|
||||
}
|
||||
|
||||
+28
-11
@@ -98,12 +98,19 @@ class MapObject : public NativeObject {
|
||||
static bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MapObject* create(JSContext* cx);
|
||||
|
||||
static uint32_t size(JSContext* cx, HandleObject obj);
|
||||
static bool get(JSContext* cx, HandleObject obj, HandleValue key, MutableHandleValue rval);
|
||||
static bool has(JSContext* cx, HandleObject obj, HandleValue key, bool* rval);
|
||||
static bool set(JSContext* cx, HandleObject obj, HandleValue key, HandleValue val);
|
||||
static bool clear(JSContext* cx, HandleObject obj);
|
||||
static bool iterator(JSContext* cx, IteratorKind kind, HandleObject obj, MutableHandleValue iter);
|
||||
// Publicly exposed Map calls for JSAPI access (webidl maplike/setlike
|
||||
// interfaces, etc.)
|
||||
static uint32_t size(JSContext *cx, HandleObject obj);
|
||||
static bool get(JSContext *cx, HandleObject obj, HandleValue key, MutableHandleValue rval);
|
||||
static bool has(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
|
||||
static bool delete_(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
|
||||
|
||||
// Set call for public JSAPI exposure. Does not actually return map object
|
||||
// as stated in spec, expects caller to return a value. for instance, with
|
||||
// webidl maplike/setlike, should return interface object.
|
||||
static bool set(JSContext *cx, HandleObject obj, HandleValue key, HandleValue val);
|
||||
static bool clear(JSContext *cx, HandleObject obj);
|
||||
static bool iterator(JSContext *cx, IteratorKind kind, HandleObject obj, MutableHandleValue iter);
|
||||
|
||||
private:
|
||||
static const JSPropertySpec properties[];
|
||||
@@ -145,23 +152,33 @@ class SetObject : public NativeObject {
|
||||
static JSObject* initClass(JSContext* cx, JSObject* obj);
|
||||
static const Class class_;
|
||||
|
||||
static bool keys(JSContext* cx, HandleObject obj, JS::AutoValueVector* keys);
|
||||
static bool values(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool add(JSContext* cx, HandleObject obj, HandleValue key);
|
||||
static bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||
static SetObject* create(JSContext* cx);
|
||||
static bool keys(JSContext *cx, HandleObject obj, JS::AutoValueVector *keys);
|
||||
static bool values(JSContext *cx, unsigned argc, Value *vp);
|
||||
static bool add(JSContext *cx, HandleObject obj, HandleValue key);
|
||||
static bool has(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
// Publicly exposed Set calls for JSAPI access (webidl maplike/setlike
|
||||
// interfaces, etc.)
|
||||
static SetObject* create(JSContext *cx);
|
||||
static uint32_t size(JSContext *cx, HandleObject obj);
|
||||
static bool has(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
|
||||
static bool clear(JSContext *cx, HandleObject obj);
|
||||
static bool iterator(JSContext *cx, IteratorKind kind, HandleObject obj, MutableHandleValue iter);
|
||||
static bool delete_(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
|
||||
|
||||
private:
|
||||
static const JSPropertySpec properties[];
|
||||
static const JSFunctionSpec methods[];
|
||||
static const JSPropertySpec staticProperties[];
|
||||
ValueSet* getData() { return static_cast<ValueSet*>(getPrivate()); }
|
||||
static ValueSet & extract(HandleObject o);
|
||||
static ValueSet & extract(CallReceiver call);
|
||||
static void mark(JSTracer* trc, JSObject* obj);
|
||||
static void finalize(FreeOp* fop, JSObject* obj);
|
||||
static bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static bool is(HandleValue v);
|
||||
static bool is(HandleObject o);
|
||||
|
||||
static bool iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind);
|
||||
|
||||
|
||||
+10
-22
@@ -1121,39 +1121,25 @@ CreateObjectPrototype(JSContext* cx, JSProtoKey key)
|
||||
static bool
|
||||
FinishObjectClassInit(JSContext* cx, JS::HandleObject ctor, JS::HandleObject proto)
|
||||
{
|
||||
Rooted<GlobalObject*> self(cx, cx->global());
|
||||
Rooted<GlobalObject*> global(cx, cx->global());
|
||||
|
||||
/* ES5 15.1.2.1. */
|
||||
RootedId evalId(cx, NameToId(cx->names().eval));
|
||||
JSObject* evalobj = DefineFunction(cx, self, evalId, IndirectEval, 1,
|
||||
JSObject* evalobj = DefineFunction(cx, global, evalId, IndirectEval, 1,
|
||||
JSFUN_STUB_GSOPS | JSPROP_RESOLVING);
|
||||
if (!evalobj)
|
||||
return false;
|
||||
self->setOriginalEval(evalobj);
|
||||
global->setOriginalEval(evalobj);
|
||||
|
||||
RootedObject intrinsicsHolder(cx);
|
||||
bool isSelfHostingGlobal = cx->runtime()->isSelfHostingGlobal(self);
|
||||
if (isSelfHostingGlobal) {
|
||||
intrinsicsHolder = self;
|
||||
} else {
|
||||
intrinsicsHolder = NewObjectWithGivenProto<PlainObject>(cx, proto, TenuredObject);
|
||||
if (!intrinsicsHolder)
|
||||
return false;
|
||||
}
|
||||
self->setIntrinsicsHolder(intrinsicsHolder);
|
||||
/* Define a property 'global' with the current global as its value. */
|
||||
RootedValue global(cx, ObjectValue(*self));
|
||||
if (!DefineProperty(cx, intrinsicsHolder, cx->names().global, global,
|
||||
nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
|
||||
{
|
||||
Rooted<NativeObject*> holder(cx, GlobalObject::getIntrinsicsHolder(cx, global));
|
||||
if (!holder)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Define self-hosted functions after setting the intrinsics holder
|
||||
* (which is needed to define self-hosted functions)
|
||||
*/
|
||||
if (!isSelfHostingGlobal) {
|
||||
if (!cx->runtime()->isSelfHostingGlobal(global)) {
|
||||
if (!JS_DefineFunctions(cx, ctor, object_static_methods, OnlyDefineLateProperties))
|
||||
return false;
|
||||
if (!JS_DefineFunctions(cx, proto, object_methods, OnlyDefineLateProperties))
|
||||
@@ -1169,8 +1155,10 @@ FinishObjectClassInit(JSContext* cx, JS::HandleObject ctor, JS::HandleObject pro
|
||||
* only set the [[Prototype]] if it hasn't already been set.
|
||||
*/
|
||||
Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
|
||||
if (self->shouldSplicePrototype(cx) && !self->splicePrototype(cx, self->getClass(), tagged))
|
||||
return false;
|
||||
if (global->shouldSplicePrototype(cx)) {
|
||||
if (!global->splicePrototype(cx, global->getClass(), tagged))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+200
-118
@@ -139,117 +139,39 @@ js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, RegExpObject& reobj,
|
||||
return CreateRegExpMatchResult(cx, input, matches, rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile a new |RegExpShared| for the |RegExpObject|.
|
||||
*/
|
||||
static bool
|
||||
CompileRegExpObject(JSContext* cx, RegExpObjectBuilder& builder,
|
||||
const CallArgs& args, RegExpStaticsUse staticsUse,
|
||||
RegExpCreationMode creationMode)
|
||||
/* ES6 draft rc4 21.2.3.2.2. */
|
||||
bool
|
||||
RegExpInitialize(JSContext* cx, RegExpObjectBuilder& builder,
|
||||
HandleValue patternValue, HandleValue flagsValue,
|
||||
RegExpStaticsUse staticsUse, MutableHandleObject result)
|
||||
{
|
||||
if (args.length() == 0) {
|
||||
MOZ_ASSERT(staticsUse == UseRegExpStatics);
|
||||
RegExpStatics* res = cx->global()->getRegExpStatics(cx);
|
||||
if (!res)
|
||||
return false;
|
||||
Rooted<JSAtom*> empty(cx, cx->names().emptyRegExp);
|
||||
RegExpObject* reobj = builder.build(empty, res->getFlags());
|
||||
if (!reobj)
|
||||
return false;
|
||||
args.rval().setObject(*reobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedValue sourceValue(cx, args[0]);
|
||||
|
||||
if (IsObjectWithClass(sourceValue, ESClass_RegExp, cx)) {
|
||||
/*
|
||||
* For RegExp.prototype.compile, if the first argument is a RegExp object,
|
||||
* the second argument must be undefined. Otherwise, throw a TypeError.
|
||||
*/
|
||||
if (args.hasDefined(1) && creationMode == CreateForCompile) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NEWREGEXP_FLAGGED);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Beware, sourceObj may be a (transparent) proxy to a RegExp, so only
|
||||
* use generic (proxyable) operations on sourceObj that do not assume
|
||||
* sourceObj.is<RegExpObject>().
|
||||
*/
|
||||
RootedObject sourceObj(cx, &sourceValue.toObject());
|
||||
|
||||
RegExpFlag flags;
|
||||
{
|
||||
/*
|
||||
* Only extract the 'flags' out of sourceObj; do not reuse the
|
||||
* RegExpShared since it may be from a different compartment.
|
||||
*/
|
||||
RegExpGuard g(cx);
|
||||
if (!RegExpToShared(cx, sourceObj, &g))
|
||||
return false;
|
||||
/*
|
||||
* If args[1] is not undefined, then parse the 'flags' from args[1].
|
||||
* Otherwise, extract the 'flags' from sourceObj.
|
||||
*/
|
||||
if (args.hasDefined(1)) {
|
||||
flags = RegExpFlag(0);
|
||||
RootedString flagStr(cx, ToString<CanGC>(cx, args[1]));
|
||||
if (!flagStr)
|
||||
return false;
|
||||
if (!ParseRegExpFlags(cx, flagStr, &flags))
|
||||
return false;
|
||||
} else {
|
||||
flags = g->getFlags();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 'toSource' is a permanent read-only property, so this is equivalent
|
||||
* to executing RegExpObject::getSource on the unwrapped object.
|
||||
*/
|
||||
RootedValue v(cx);
|
||||
if (!GetProperty(cx, sourceObj, sourceObj, cx->names().source, &v))
|
||||
return false;
|
||||
|
||||
// For proxies like CPOWs, we can't assume the result of a property get
|
||||
// for 'source' is atomized.
|
||||
Rooted<JSAtom*> sourceAtom(cx, AtomizeString(cx, v.toString()));
|
||||
RegExpObject* reobj = builder.build(sourceAtom, flags);
|
||||
if (!reobj)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*reobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedAtom source(cx);
|
||||
if (sourceValue.isUndefined()) {
|
||||
source = cx->runtime()->emptyString;
|
||||
RootedAtom pattern(cx);
|
||||
if (patternValue.isUndefined()) {
|
||||
/* Step 1. */
|
||||
pattern = cx->runtime()->emptyString;
|
||||
} else {
|
||||
/* Coerce to string and compile. */
|
||||
source = ToAtom<CanGC>(cx, sourceValue);
|
||||
if (!source)
|
||||
/* Steps 2-3. */
|
||||
pattern = ToAtom<CanGC>(cx, patternValue);
|
||||
if (!pattern)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Step 4. */
|
||||
RegExpFlag flags = RegExpFlag(0);
|
||||
if (args.hasDefined(1)) {
|
||||
RootedString flagStr(cx, ToString<CanGC>(cx, args[1]));
|
||||
if (!flagsValue.isUndefined()) {
|
||||
/* Steps 5-6. */
|
||||
RootedString flagStr(cx, ToString<CanGC>(cx, flagsValue));
|
||||
if (!flagStr)
|
||||
return false;
|
||||
/* Step 7. */
|
||||
if (!ParseRegExpFlags(cx, flagStr, &flags))
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedAtom escapedSourceStr(cx, EscapeRegExpPattern(cx, source));
|
||||
if (!escapedSourceStr)
|
||||
return false;
|
||||
|
||||
/* Steps 9-10. */
|
||||
CompileOptions options(cx);
|
||||
frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
|
||||
|
||||
if (!irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), escapedSourceStr))
|
||||
if (!irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern))
|
||||
return false;
|
||||
|
||||
if (staticsUse == UseRegExpStatics) {
|
||||
@@ -258,10 +180,146 @@ CompileRegExpObject(JSContext* cx, RegExpObjectBuilder& builder,
|
||||
return false;
|
||||
flags = RegExpFlag(flags | res->getFlags());
|
||||
}
|
||||
RegExpObject* reobj = builder.build(escapedSourceStr, flags);
|
||||
|
||||
/* Steps 11-15. */
|
||||
RootedObject reobj(cx, builder.build(pattern, flags));
|
||||
if (!reobj)
|
||||
return false;
|
||||
|
||||
/* Step 16. */
|
||||
result.set(reobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* ES6 draft rc4 21.2.3.1 steps 5-10.
|
||||
* ES6 draft rc4 B.2.5.1 steps 3-5.
|
||||
* Compile a new |RegExpShared| for the |RegExpObject|.
|
||||
*/
|
||||
static bool
|
||||
CompileRegExpObject(JSContext* cx, RegExpObjectBuilder& builder, CallArgs args,
|
||||
RegExpCreationMode creationMode, bool patternIsRegExp=false)
|
||||
{
|
||||
if (args.length() == 0) {
|
||||
/*
|
||||
* 21.2.3.1 step 10.
|
||||
* B.2.5.1 step 5.
|
||||
*/
|
||||
RegExpStatics* res = cx->global()->getRegExpStatics(cx);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
RootedAtom empty(cx, cx->runtime()->emptyString);
|
||||
RegExpObject* reobj = builder.build(empty, res->getFlags());
|
||||
if (!reobj)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*reobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedValue patternValue(cx, args.get(0));
|
||||
|
||||
/*
|
||||
* 21.2.3.1 step 5
|
||||
* B.2.5.1 step 3.
|
||||
*/
|
||||
if (IsObjectWithClass(patternValue, ESClass_RegExp, cx)) {
|
||||
/*
|
||||
* B.2.5.1 step 3.a.
|
||||
*/
|
||||
if (args.hasDefined(1) && creationMode == CreateForCompile) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NEWREGEXP_FLAGGED);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Beware, patternObj may be a (transparent) proxy to a RegExp, so only
|
||||
* use generic (proxyable) operations on patternObj that do not assume
|
||||
* patternObj.is<RegExpObject>().
|
||||
*/
|
||||
RootedObject patternObj(cx, &patternValue.toObject());
|
||||
|
||||
RootedAtom sourceAtom(cx);
|
||||
RegExpFlag flags;
|
||||
{
|
||||
/*
|
||||
* 21.2.3.1 step 5.a.
|
||||
* B.2.5.1 step 3.a.
|
||||
* Extract the 'source' from patternObj; do not reuse the
|
||||
* RegExpShared since it may be from a different compartment.
|
||||
*/
|
||||
RegExpGuard g(cx);
|
||||
if (!RegExpToShared(cx, patternObj, &g))
|
||||
return false;
|
||||
sourceAtom = g->getSource();
|
||||
|
||||
if (args.hasDefined(1)) {
|
||||
/* 21.2.3.1 step 5.c. */
|
||||
flags = RegExpFlag(0);
|
||||
RootedString flagStr(cx, ToString<CanGC>(cx, args[1]));
|
||||
if (!flagStr)
|
||||
return false;
|
||||
if (!ParseRegExpFlags(cx, flagStr, &flags))
|
||||
return false;
|
||||
} else {
|
||||
/*
|
||||
* 21.2.3.1 step 5.b.
|
||||
* B.2.5.1 step 3.c.
|
||||
*/
|
||||
flags = g->getFlags();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 21.2.3.1 steps 8-10.
|
||||
* B.2.5.1 step 5.
|
||||
*/
|
||||
RegExpObject* reobj = builder.build(sourceAtom, flags);
|
||||
if (!reobj)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*reobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedValue P(cx);
|
||||
RootedValue F(cx);
|
||||
/* 21.2.3.1 step 6. */
|
||||
if (patternIsRegExp) {
|
||||
MOZ_ASSERT(creationMode == CreateForConstruct);
|
||||
RootedObject patternObj(cx, &patternValue.toObject());
|
||||
|
||||
/* 21.2.3.1 steps 6.a-b. */
|
||||
if (!GetProperty(cx, patternObj, patternObj, cx->names().source, &P))
|
||||
return false;
|
||||
|
||||
/* 21.2.3.1 step 6.c. */
|
||||
if (!args.hasDefined(1)) {
|
||||
/* 21.2.3.1 steps 6.c.i-ii. */
|
||||
if (!GetProperty(cx, patternObj, patternObj, cx->names().flags, &F))
|
||||
return false;
|
||||
} else {
|
||||
/* 21.2.3.1 steps 6.d. */
|
||||
F = args[1];
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* 21.2.3.1 steps 7.a-b.
|
||||
* B.2.5.1 steps 4.a-b.
|
||||
*/
|
||||
P = patternValue;
|
||||
F = args.get(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* 21.2.3.1 steps 8-10.
|
||||
* B.2.5.1 step 5.
|
||||
*/
|
||||
RootedObject reobj(cx);
|
||||
if (!RegExpInitialize(cx, builder, P, F, UseRegExpStatics, &reobj))
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*reobj);
|
||||
return true;
|
||||
}
|
||||
@@ -300,43 +358,59 @@ IsRegExpObject(HandleValue v)
|
||||
return v.isObject() && v.toObject().is<RegExpObject>();
|
||||
}
|
||||
|
||||
/* ES6 draft rc4 B.2.5.1. */
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
regexp_compile_impl(JSContext *cx, const CallArgs &args)
|
||||
regexp_compile_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsRegExpObject(args.thisv()));
|
||||
|
||||
/* Steps 3-5. */
|
||||
RegExpObjectBuilder builder(cx, &args.thisv().toObject().as<RegExpObject>());
|
||||
return CompileRegExpObject(cx, builder, args, UseRegExpStatics, CreateForCompile);
|
||||
return CompileRegExpObject(cx, builder, args, CreateForCompile);
|
||||
}
|
||||
|
||||
static bool
|
||||
regexp_compile(JSContext *cx, unsigned argc, Value *vp)
|
||||
regexp_compile(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
/* Steps 1-2. */
|
||||
return CallNonGenericMethod<IsRegExpObject, regexp_compile_impl>(cx, args);
|
||||
}
|
||||
|
||||
/* ES6 draft rc4 21.2.3.1. */
|
||||
bool
|
||||
js::regexp_construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
js::regexp_construct(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
/* Steps 1-2. */
|
||||
bool patternIsRegExp;
|
||||
if (!IsRegExp(cx, args.get(0), &patternIsRegExp))
|
||||
return false;
|
||||
|
||||
/* Step 4. */
|
||||
if (!args.isConstructing()) {
|
||||
/*
|
||||
* If first arg is regexp and no flags are given, just return the arg.
|
||||
* Otherwise, delegate to the standard constructor.
|
||||
* See ECMAv5 15.10.3.1.
|
||||
*/
|
||||
if (args.hasDefined(0) &&
|
||||
IsObjectWithClass(args[0], ESClass_RegExp, cx) &&
|
||||
!args.hasDefined(1))
|
||||
{
|
||||
args.rval().set(args[0]);
|
||||
return true;
|
||||
/* Step 4.b. */
|
||||
if (patternIsRegExp && !args.hasDefined(1)) {
|
||||
RootedObject patternObj(cx, &args[0].toObject());
|
||||
|
||||
/* Steps 4.b.i-ii. */
|
||||
RootedValue patternConstructor(cx);
|
||||
if (!GetProperty(cx, patternObj, patternObj, cx->names().constructor, &patternConstructor))
|
||||
return false;
|
||||
|
||||
/* Step 4.b.iii. */
|
||||
if (patternConstructor.isObject() && patternConstructor.toObject() == args.callee()) {
|
||||
args.rval().set(args[0]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Steps 5-10. */
|
||||
RegExpObjectBuilder builder(cx);
|
||||
return CompileRegExpObject(cx, builder, args, UseRegExpStatics, CreateForConstruct);
|
||||
return CompileRegExpObject(cx, builder, args, CreateForConstruct, patternIsRegExp);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -349,8 +423,16 @@ js::regexp_construct_no_statics(JSContext* cx, unsigned argc, Value* vp)
|
||||
MOZ_ASSERT_IF(args.length() == 2, args[1].isString());
|
||||
MOZ_ASSERT(!args.isConstructing());
|
||||
|
||||
/* Steps 1-6 are not required since pattern is always string. */
|
||||
|
||||
/* Steps 7-10. */
|
||||
RegExpObjectBuilder builder(cx);
|
||||
return CompileRegExpObject(cx, builder, args, DontUseRegExpStatics, CreateForConstruct);
|
||||
RootedObject reobj(cx);
|
||||
if (!RegExpInitialize(cx, builder, args[0], args.get(1), DontUseRegExpStatics, &reobj))
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*reobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ES6 draft rev32 21.2.5.4. */
|
||||
@@ -571,8 +653,8 @@ const JSPropertySpec js::regexp_static_props[] = {
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
JSObject *
|
||||
js::CreateRegExpPrototype(JSContext *cx, JSProtoKey key)
|
||||
JSObject*
|
||||
js::CreateRegExpPrototype(JSContext* cx, JSProtoKey key)
|
||||
{
|
||||
MOZ_ASSERT(key == JSProto_RegExp);
|
||||
|
||||
@@ -581,7 +663,7 @@ js::CreateRegExpPrototype(JSContext *cx, JSProtoKey key)
|
||||
return nullptr;
|
||||
proto->NativeObject::setPrivate(nullptr);
|
||||
|
||||
HandlePropertyName empty = cx->names().emptyRegExp;
|
||||
HandlePropertyName empty = cx->names().empty;
|
||||
RegExpObjectBuilder builder(cx, proto);
|
||||
if (!builder.build(empty, RegExpFlag(0)))
|
||||
return nullptr;
|
||||
|
||||
+246
-72
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "builtin/SIMD.h"
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/IntegerTypeTraits.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
@@ -30,11 +31,13 @@ using mozilla::ArrayLength;
|
||||
using mozilla::IsFinite;
|
||||
using mozilla::IsNaN;
|
||||
using mozilla::FloorLog2;
|
||||
using mozilla::NumberIsInt32;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// SIMD
|
||||
|
||||
static const char* laneNames[] = {"lane 0", "lane 1", "lane 2", "lane3"};
|
||||
static const char* laneNames[] = {"lane 0", "lane 1", "lane 2", "lane 3", "lane 4", "lane 5", "lane 6", "lane 7",
|
||||
"lane 8", "lane 9", "lane 10", "lane 11", "lane 12", "lane 13", "lane 14", "lane 15"};
|
||||
|
||||
static bool
|
||||
CheckVectorObject(HandleValue v, SimdTypeDescr::Type expectedType)
|
||||
@@ -60,6 +63,8 @@ js::IsVectorObject(HandleValue v)
|
||||
return CheckVectorObject(v, V::type);
|
||||
}
|
||||
|
||||
template bool js::IsVectorObject<Int8x16>(HandleValue v);
|
||||
template bool js::IsVectorObject<Int16x8>(HandleValue v);
|
||||
template bool js::IsVectorObject<Int32x4>(HandleValue v);
|
||||
template bool js::IsVectorObject<Float32x4>(HandleValue v);
|
||||
template bool js::IsVectorObject<Float64x2>(HandleValue v);
|
||||
@@ -145,7 +150,27 @@ static bool type##Lane##lane(JSContext* cx, unsigned argc, Value* vp) { \
|
||||
|
||||
FOUR_LANES_ACCESSOR(Int32x4);
|
||||
FOUR_LANES_ACCESSOR(Float32x4);
|
||||
|
||||
#define EIGHT_LANES_ACCESSOR(type) \
|
||||
FOUR_LANES_ACCESSOR(type) \
|
||||
LANE_ACCESSOR(type, 4) \
|
||||
LANE_ACCESSOR(type, 5) \
|
||||
LANE_ACCESSOR(type, 6) \
|
||||
LANE_ACCESSOR(type, 7)
|
||||
|
||||
EIGHT_LANES_ACCESSOR(Int16x8);
|
||||
|
||||
EIGHT_LANES_ACCESSOR(Int8x16);
|
||||
LANE_ACCESSOR(Int8x16, 8);
|
||||
LANE_ACCESSOR(Int8x16, 9);
|
||||
LANE_ACCESSOR(Int8x16, 10);
|
||||
LANE_ACCESSOR(Int8x16, 11);
|
||||
LANE_ACCESSOR(Int8x16, 12);
|
||||
LANE_ACCESSOR(Int8x16, 13);
|
||||
LANE_ACCESSOR(Int8x16, 14);
|
||||
LANE_ACCESSOR(Int8x16, 15);
|
||||
#undef FOUR_LANES_ACCESSOR
|
||||
#undef EIGHT_LANES_ACCESSOR
|
||||
|
||||
LANE_ACCESSOR(Float64x2, 0);
|
||||
LANE_ACCESSOR(Float64x2, 1);
|
||||
@@ -194,6 +219,8 @@ static bool type##SignMask(JSContext* cx, unsigned argc, Value* vp) { \
|
||||
}
|
||||
SIGN_MASK(Float32x4);
|
||||
SIGN_MASK(Float64x2);
|
||||
SIGN_MASK(Int8x16);
|
||||
SIGN_MASK(Int16x8);
|
||||
SIGN_MASK(Int32x4);
|
||||
#undef SIGN_MASK
|
||||
|
||||
@@ -215,6 +242,22 @@ const Class SimdTypeDescr::class_ = {
|
||||
namespace {
|
||||
|
||||
// These classes just exist to group together various properties and so on.
|
||||
class Int8x16Defn {
|
||||
public:
|
||||
static const SimdTypeDescr::Type type = SimdTypeDescr::Int8x16;
|
||||
static const JSFunctionSpec TypeDescriptorMethods[];
|
||||
static const JSPropertySpec TypedObjectProperties[];
|
||||
static const JSFunctionSpec TypedObjectMethods[];
|
||||
static const JSFunctionSpec Methods[];
|
||||
};
|
||||
class Int16x8Defn {
|
||||
public:
|
||||
static const SimdTypeDescr::Type type = SimdTypeDescr::Int16x8;
|
||||
static const JSFunctionSpec TypeDescriptorMethods[];
|
||||
static const JSPropertySpec TypedObjectProperties[];
|
||||
static const JSFunctionSpec TypedObjectMethods[];
|
||||
static const JSFunctionSpec Methods[];
|
||||
};
|
||||
class Int32x4Defn {
|
||||
public:
|
||||
static const SimdTypeDescr::Type type = SimdTypeDescr::Int32x4;
|
||||
@@ -298,6 +341,80 @@ const JSFunctionSpec Float64x2Defn::Methods[] = {
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
const JSFunctionSpec Int8x16Defn::TypeDescriptorMethods[] = {
|
||||
JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
|
||||
JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
|
||||
JS_SELF_HOSTED_FN("equivalent", "TypeDescrEquivalent", 1, 0),
|
||||
JS_FS_END,
|
||||
};
|
||||
|
||||
const JSPropertySpec Int8x16Defn::TypedObjectProperties[] = {
|
||||
JS_PSG("s0", Int8x16Lane0, JSPROP_PERMANENT),
|
||||
JS_PSG("s1", Int8x16Lane1, JSPROP_PERMANENT),
|
||||
JS_PSG("s2", Int8x16Lane2, JSPROP_PERMANENT),
|
||||
JS_PSG("s3", Int8x16Lane3, JSPROP_PERMANENT),
|
||||
JS_PSG("s4", Int8x16Lane4, JSPROP_PERMANENT),
|
||||
JS_PSG("s5", Int8x16Lane5, JSPROP_PERMANENT),
|
||||
JS_PSG("s6", Int8x16Lane6, JSPROP_PERMANENT),
|
||||
JS_PSG("s7", Int8x16Lane7, JSPROP_PERMANENT),
|
||||
JS_PSG("s8", Int8x16Lane8, JSPROP_PERMANENT),
|
||||
JS_PSG("s9", Int8x16Lane9, JSPROP_PERMANENT),
|
||||
JS_PSG("s10", Int8x16Lane10, JSPROP_PERMANENT),
|
||||
JS_PSG("s11", Int8x16Lane11, JSPROP_PERMANENT),
|
||||
JS_PSG("s12", Int8x16Lane12, JSPROP_PERMANENT),
|
||||
JS_PSG("s13", Int8x16Lane13, JSPROP_PERMANENT),
|
||||
JS_PSG("s14", Int8x16Lane14, JSPROP_PERMANENT),
|
||||
JS_PSG("s15", Int8x16Lane15, JSPROP_PERMANENT),
|
||||
JS_PSG("signMask", Int8x16SignMask, JSPROP_PERMANENT),
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
const JSFunctionSpec Int8x16Defn::TypedObjectMethods[] = {
|
||||
JS_SELF_HOSTED_FN("toSource", "SimdToSource", 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
const JSFunctionSpec Int8x16Defn::Methods[] = {
|
||||
#define SIMD_INT8X16_FUNCTION_ITEM(Name, Func, Operands) \
|
||||
JS_FN(#Name, js::simd_int8x16_##Name, Operands, 0),
|
||||
INT8X16_FUNCTION_LIST(SIMD_INT8X16_FUNCTION_ITEM)
|
||||
#undef SIMD_INT8X16_FUNCTION_ITEM
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
const JSFunctionSpec Int16x8Defn::TypeDescriptorMethods[] = {
|
||||
JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
|
||||
JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
|
||||
JS_SELF_HOSTED_FN("equivalent", "TypeDescrEquivalent", 1, 0),
|
||||
JS_FS_END,
|
||||
};
|
||||
|
||||
const JSPropertySpec Int16x8Defn::TypedObjectProperties[] = {
|
||||
JS_PSG("s0", Int16x8Lane0, JSPROP_PERMANENT),
|
||||
JS_PSG("s1", Int16x8Lane1, JSPROP_PERMANENT),
|
||||
JS_PSG("s2", Int16x8Lane2, JSPROP_PERMANENT),
|
||||
JS_PSG("s3", Int16x8Lane3, JSPROP_PERMANENT),
|
||||
JS_PSG("s4", Int16x8Lane4, JSPROP_PERMANENT),
|
||||
JS_PSG("s5", Int16x8Lane5, JSPROP_PERMANENT),
|
||||
JS_PSG("s6", Int16x8Lane6, JSPROP_PERMANENT),
|
||||
JS_PSG("s7", Int16x8Lane7, JSPROP_PERMANENT),
|
||||
JS_PSG("signMask", Int16x8SignMask, JSPROP_PERMANENT),
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
const JSFunctionSpec Int16x8Defn::TypedObjectMethods[] = {
|
||||
JS_SELF_HOSTED_FN("toSource", "SimdToSource", 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
const JSFunctionSpec Int16x8Defn::Methods[] = {
|
||||
#define SIMD_INT16X8_FUNCTION_ITEM(Name, Func, Operands) \
|
||||
JS_FN(#Name, js::simd_int16x8_##Name, Operands, 0),
|
||||
INT16X8_FUNCTION_LIST(SIMD_INT16X8_FUNCTION_ITEM)
|
||||
#undef SIMD_INT16X8_FUNCTION_ITEM
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
const JSFunctionSpec Int32x4Defn::TypeDescriptorMethods[] = {
|
||||
JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
|
||||
JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
|
||||
@@ -418,6 +535,8 @@ SimdTypeDescr::call(JSContext* cx, unsigned argc, Value* vp)
|
||||
return false;
|
||||
|
||||
switch (descr->type()) {
|
||||
case SimdTypeDescr::Int8x16: return FillLanes< ::Int8x16>(cx, result, args);
|
||||
case SimdTypeDescr::Int16x8: return FillLanes< ::Int16x8>(cx, result, args);
|
||||
case SimdTypeDescr::Int32x4: return FillLanes< ::Int32x4>(cx, result, args);
|
||||
case SimdTypeDescr::Float32x4: return FillLanes< ::Float32x4>(cx, result, args);
|
||||
case SimdTypeDescr::Float64x2: return FillLanes< ::Float64x2>(cx, result, args);
|
||||
@@ -455,6 +574,18 @@ SIMDObject::initClass(JSContext* cx, Handle<GlobalObject*> global)
|
||||
if (!SIMD)
|
||||
return nullptr;
|
||||
|
||||
RootedObject i8x16(cx);
|
||||
i8x16 = CreateAndBindSimdClass<Int8x16Defn>(cx, global, SIMD, cx->names().int8x16);
|
||||
if (!i8x16)
|
||||
return nullptr;
|
||||
global->setInt8x16TypeDescr(*i8x16);
|
||||
|
||||
RootedObject i16x8(cx);
|
||||
i16x8 = CreateAndBindSimdClass<Int16x8Defn>(cx, global, SIMD, cx->names().int16x8);
|
||||
if (!i16x8)
|
||||
return nullptr;
|
||||
global->setInt16x8TypeDescr(*i16x8);
|
||||
|
||||
RootedObject f32x4(cx);
|
||||
f32x4 = CreateAndBindSimdClass<Float32x4Defn>(cx, global, SIMD, cx->names().float32x4);
|
||||
if (!f32x4)
|
||||
@@ -512,6 +643,8 @@ js::CreateSimd(JSContext* cx, const typename V::Elem* data)
|
||||
|
||||
template JSObject* js::CreateSimd<Float32x4>(JSContext* cx, const Float32x4::Elem* data);
|
||||
template JSObject* js::CreateSimd<Float64x2>(JSContext* cx, const Float64x2::Elem* data);
|
||||
template JSObject* js::CreateSimd<Int8x16>(JSContext* cx, const Int8x16::Elem* data);
|
||||
template JSObject* js::CreateSimd<Int16x8>(JSContext* cx, const Int16x8::Elem* data);
|
||||
template JSObject* js::CreateSimd<Int32x4>(JSContext* cx, const Int32x4::Elem* data);
|
||||
|
||||
namespace js {
|
||||
@@ -538,7 +671,7 @@ struct RecApprox {
|
||||
};
|
||||
template<typename T>
|
||||
struct RecSqrtApprox {
|
||||
static T apply(T x) { return 1 / sqrt(x); }
|
||||
static inline T apply(T x) { return 1 / sqrt(x); }
|
||||
};
|
||||
template<typename T>
|
||||
struct Sqrt {
|
||||
@@ -580,27 +713,27 @@ struct MaxNum {
|
||||
};
|
||||
template<typename T>
|
||||
struct LessThan {
|
||||
static int32_t apply(T l, T r) { return l < r ? 0xFFFFFFFF : 0x0; }
|
||||
static bool apply(T l, T r) { return l < r; }
|
||||
};
|
||||
template<typename T>
|
||||
struct LessThanOrEqual {
|
||||
static int32_t apply(T l, T r) { return l <= r ? 0xFFFFFFFF : 0x0; }
|
||||
static bool apply(T l, T r) { return l <= r; }
|
||||
};
|
||||
template<typename T>
|
||||
struct GreaterThan {
|
||||
static int32_t apply(T l, T r) { return l > r ? 0xFFFFFFFF : 0x0; }
|
||||
static bool apply(T l, T r) { return l > r; }
|
||||
};
|
||||
template<typename T>
|
||||
struct GreaterThanOrEqual {
|
||||
static int32_t apply(T l, T r) { return l >= r ? 0xFFFFFFFF : 0x0; }
|
||||
static bool apply(T l, T r) { return l >= r; }
|
||||
};
|
||||
template<typename T>
|
||||
struct Equal {
|
||||
static int32_t apply(T l, T r) { return l == r ? 0xFFFFFFFF : 0x0; }
|
||||
static bool apply(T l, T r) { return l == r; }
|
||||
};
|
||||
template<typename T>
|
||||
struct NotEqual {
|
||||
static int32_t apply(T l, T r) { return l != r ? 0xFFFFFFFF : 0x0; }
|
||||
static bool apply(T l, T r) { return l != r; }
|
||||
};
|
||||
template<typename T>
|
||||
struct Xor {
|
||||
@@ -614,38 +747,26 @@ template<typename T>
|
||||
struct Or {
|
||||
static T apply(T l, T r) { return l | r; }
|
||||
};
|
||||
template<typename T>
|
||||
struct WithX {
|
||||
static T apply(int32_t lane, T scalar, T x) { return lane == 0 ? scalar : x; }
|
||||
};
|
||||
template<typename T>
|
||||
struct WithY {
|
||||
static T apply(int32_t lane, T scalar, T x) { return lane == 1 ? scalar : x; }
|
||||
};
|
||||
template<typename T>
|
||||
struct WithZ {
|
||||
static T apply(int32_t lane, T scalar, T x) { return lane == 2 ? scalar : x; }
|
||||
};
|
||||
template<typename T>
|
||||
struct WithW {
|
||||
static T apply(int32_t lane, T scalar, T x) { return lane == 3 ? scalar : x; }
|
||||
};
|
||||
// For the following three operators, if the value v we're trying to shift is
|
||||
// such that v << bits can't fit in the int32 range, then we have undefined
|
||||
// behavior, according to C++11 [expr.shift]p2.
|
||||
template<typename T>
|
||||
struct ShiftLeft {
|
||||
static int32_t apply(int32_t v, int32_t bits) {
|
||||
return uint32_t(bits) >= 32 ? 0 : v << bits;
|
||||
static T apply(T v, int32_t bits) {
|
||||
return uint32_t(bits) >= sizeof(T) * 8 ? 0 : v << bits;
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct ShiftRightArithmetic {
|
||||
static int32_t apply(int32_t v, int32_t bits) {
|
||||
return v >> (uint32_t(bits) >= 32 ? 31 : bits);
|
||||
static T apply(T v, int32_t bits) {
|
||||
uint32_t maxBits = sizeof(T) * 8;
|
||||
return v >> (uint32_t(bits) >= maxBits ? maxBits - 1 : bits);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct ShiftRightLogical {
|
||||
static int32_t apply(int32_t v, int32_t bits) {
|
||||
return uint32_t(bits) >= 32 ? 0 : uint32_t(v) >> bits;
|
||||
static T apply(T v, int32_t bits) {
|
||||
return uint32_t(bits) >= sizeof(T) * 8 ? 0 : uint32_t(v) >> bits;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -718,26 +839,54 @@ BinaryFunc(JSContext* cx, unsigned argc, Value* vp)
|
||||
return CoercedBinaryFunc<In, Out, Op, Out>(cx, argc, vp);
|
||||
}
|
||||
|
||||
template<typename V, template<typename T> class OpWith>
|
||||
template<typename V>
|
||||
static bool
|
||||
FuncWith(JSContext* cx, unsigned argc, Value* vp)
|
||||
ExtractLane(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
typedef typename V::Elem Elem;
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
// Only the first argument is mandatory
|
||||
if (args.length() < 1 || !IsVectorObject<V>(args[0]))
|
||||
if (args.length() < 2 || !IsVectorObject<V>(args[0]) || !args[1].isNumber())
|
||||
return ErrorBadArgs(cx);
|
||||
|
||||
int32_t lane;
|
||||
if (!NumberIsInt32(args[1].toNumber(), &lane))
|
||||
return ErrorBadArgs(cx);
|
||||
if (lane < 0 || uint32_t(lane) >= V::lanes)
|
||||
return ErrorBadArgs(cx);
|
||||
|
||||
Elem* vec = TypedObjectMemory<Elem*>(args[0]);
|
||||
V::setReturn(args, vec[lane]);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
static bool
|
||||
ReplaceLane(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
typedef typename V::Elem Elem;
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
// Only the first and second arguments are mandatory
|
||||
if (args.length() < 2 || !IsVectorObject<V>(args[0]))
|
||||
return ErrorBadArgs(cx);
|
||||
|
||||
Elem* vec = TypedObjectMemory<Elem*>(args[0]);
|
||||
Elem result[V::lanes];
|
||||
|
||||
if (!args[1].isInt32())
|
||||
return ErrorBadArgs(cx);
|
||||
int32_t lanearg = args[1].toInt32();
|
||||
if (lanearg < 0 || uint32_t(lanearg) >= V::lanes)
|
||||
return ErrorBadArgs(cx);
|
||||
uint32_t lane = uint32_t(lanearg);
|
||||
|
||||
Elem value;
|
||||
if (!V::toType(cx, args.get(1), &value))
|
||||
if (!V::toType(cx, args.get(2), &value))
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < V::lanes; i++)
|
||||
result[i] = OpWith<Elem>::apply(i, value, vec[i]);
|
||||
result[i] = i == lane ? value : vec[i];
|
||||
return StoreResult<V>(cx, args, result);
|
||||
}
|
||||
|
||||
@@ -802,47 +951,50 @@ Shuffle(JSContext* cx, unsigned argc, Value* vp)
|
||||
return StoreResult<V>(cx, args, result);
|
||||
}
|
||||
|
||||
template<typename Op>
|
||||
template<typename V, template<typename T> class Op>
|
||||
static bool
|
||||
Int32x4BinaryScalar(JSContext* cx, unsigned argc, Value* vp)
|
||||
BinaryScalar(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
typedef typename V::Elem Elem;
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() != 2)
|
||||
return ErrorBadArgs(cx);
|
||||
|
||||
int32_t result[4];
|
||||
if (!IsVectorObject<Int32x4>(args[0]))
|
||||
Elem result[V::lanes];
|
||||
if (!IsVectorObject<V>(args[0]))
|
||||
return ErrorBadArgs(cx);
|
||||
|
||||
int32_t* val = TypedObjectMemory<int32_t*>(args[0]);
|
||||
Elem* val = TypedObjectMemory<Elem*>(args[0]);
|
||||
int32_t bits;
|
||||
if (!ToInt32(cx, args[1], &bits))
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
result[i] = Op::apply(val[i], bits);
|
||||
return StoreResult<Int32x4>(cx, args, result);
|
||||
for (unsigned i = 0; i < V::lanes; i++)
|
||||
result[i] = Op<Elem>::apply(val[i], bits);
|
||||
return StoreResult<V>(cx, args, result);
|
||||
}
|
||||
|
||||
template<typename In, template<typename C> class Op>
|
||||
template<typename In, template<typename C> class Op, typename Out>
|
||||
static bool
|
||||
CompareFunc(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
typedef typename In::Elem InElem;
|
||||
typedef typename Out::Elem OutElem;
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() != 2 || !IsVectorObject<In>(args[0]) || !IsVectorObject<In>(args[1]))
|
||||
return ErrorBadArgs(cx);
|
||||
|
||||
int32_t result[Int32x4::lanes];
|
||||
OutElem result[Out::lanes];
|
||||
InElem* left = TypedObjectMemory<InElem*>(args[0]);
|
||||
InElem* right = TypedObjectMemory<InElem*>(args[1]);
|
||||
for (unsigned i = 0; i < Int32x4::lanes; i++) {
|
||||
unsigned j = (i * In::lanes) / Int32x4::lanes;
|
||||
result[i] = Op<InElem>::apply(left[j], right[j]);
|
||||
for (unsigned i = 0; i < Out::lanes; i++) {
|
||||
unsigned j = (i * In::lanes) / Out::lanes;
|
||||
result[i] = Op<InElem>::apply(left[j], right[j]) ? -1 : 0;
|
||||
}
|
||||
|
||||
return StoreResult<Int32x4>(cx, args, result);
|
||||
return StoreResult<Out>(cx, args, result);
|
||||
}
|
||||
|
||||
// This struct defines whether we should throw during a conversion attempt,
|
||||
@@ -967,15 +1119,18 @@ FuncSplat(JSContext* cx, unsigned argc, Value* vp)
|
||||
return StoreResult<Vret>(cx, args, result);
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
static bool
|
||||
Int32x4Bool(JSContext* cx, unsigned argc, Value* vp)
|
||||
Bool(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
typedef typename V::Elem Elem;
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
int32_t result[Int32x4::lanes];
|
||||
for (unsigned i = 0; i < Int32x4::lanes; i++)
|
||||
Elem result[V::lanes];
|
||||
for (unsigned i = 0; i < V::lanes; i++)
|
||||
result[i] = ToBoolean(args.get(i)) ? -1 : 0;
|
||||
return StoreResult<Int32x4>(cx, args, result);
|
||||
return StoreResult<V>(cx, args, result);
|
||||
}
|
||||
|
||||
template<typename In>
|
||||
@@ -1003,53 +1158,55 @@ Clamp(JSContext* cx, unsigned argc, Value* vp)
|
||||
return StoreResult<In>(cx, args, result);
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
template<typename V, typename MaskType>
|
||||
static bool
|
||||
BitSelect(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
typedef typename V::Elem Elem;
|
||||
typedef typename MaskType::Elem MaskTypeElem;
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() != 3 || !IsVectorObject<Int32x4>(args[0]) ||
|
||||
if (args.length() != 3 || !IsVectorObject<MaskType>(args[0]) ||
|
||||
!IsVectorObject<V>(args[1]) || !IsVectorObject<V>(args[2]))
|
||||
{
|
||||
return ErrorBadArgs(cx);
|
||||
}
|
||||
|
||||
int32_t* val = TypedObjectMemory<int32_t*>(args[0]);
|
||||
int32_t* tv = TypedObjectMemory<int32_t*>(args[1]);
|
||||
int32_t* fv = TypedObjectMemory<int32_t*>(args[2]);
|
||||
MaskTypeElem* val = TypedObjectMemory<MaskTypeElem*>(args[0]);
|
||||
MaskTypeElem* tv = TypedObjectMemory<MaskTypeElem*>(args[1]);
|
||||
MaskTypeElem* fv = TypedObjectMemory<MaskTypeElem*>(args[2]);
|
||||
|
||||
int32_t tr[Int32x4::lanes];
|
||||
for (unsigned i = 0; i < Int32x4::lanes; i++)
|
||||
tr[i] = And<int32_t>::apply(val[i], tv[i]);
|
||||
MaskTypeElem tr[MaskType::lanes];
|
||||
for (unsigned i = 0; i < MaskType::lanes; i++)
|
||||
tr[i] = And<MaskTypeElem>::apply(val[i], tv[i]);
|
||||
|
||||
int32_t fr[Int32x4::lanes];
|
||||
for (unsigned i = 0; i < Int32x4::lanes; i++)
|
||||
fr[i] = And<int32_t>::apply(Not<int32_t>::apply(val[i]), fv[i]);
|
||||
MaskTypeElem fr[MaskType::lanes];
|
||||
for (unsigned i = 0; i < MaskType::lanes; i++)
|
||||
fr[i] = And<MaskTypeElem>::apply(Not<MaskTypeElem>::apply(val[i]), fv[i]);
|
||||
|
||||
int32_t orInt[Int32x4::lanes];
|
||||
for (unsigned i = 0; i < Int32x4::lanes; i++)
|
||||
orInt[i] = Or<int32_t>::apply(tr[i], fr[i]);
|
||||
MaskTypeElem orInt[MaskType::lanes];
|
||||
for (unsigned i = 0; i < MaskType::lanes; i++)
|
||||
orInt[i] = Or<MaskTypeElem>::apply(tr[i], fr[i]);
|
||||
|
||||
Elem* result = reinterpret_cast<Elem*>(orInt);
|
||||
return StoreResult<V>(cx, args, result);
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
template<typename V, typename MaskType>
|
||||
static bool
|
||||
Select(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
typedef typename V::Elem Elem;
|
||||
typedef typename MaskType::Elem MaskTypeElem;
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() != 3 || !IsVectorObject<Int32x4>(args[0]) ||
|
||||
if (args.length() != 3 || !IsVectorObject<MaskType>(args[0]) ||
|
||||
!IsVectorObject<V>(args[1]) || !IsVectorObject<V>(args[2]))
|
||||
{
|
||||
return ErrorBadArgs(cx);
|
||||
}
|
||||
|
||||
int32_t* mask = TypedObjectMemory<int32_t*>(args[0]);
|
||||
MaskTypeElem* mask = TypedObjectMemory<MaskTypeElem*>(args[0]);
|
||||
Elem* tv = TypedObjectMemory<Elem*>(args[1]);
|
||||
Elem* fv = TypedObjectMemory<Elem*>(args[2]);
|
||||
|
||||
@@ -1163,6 +1320,24 @@ js::simd_float64x2_##Name(JSContext* cx, unsigned argc, Value* vp) \
|
||||
FLOAT64X2_FUNCTION_LIST(DEFINE_SIMD_FLOAT64X2_FUNCTION)
|
||||
#undef DEFINE_SIMD_FLOAT64X2_FUNCTION
|
||||
|
||||
#define DEFINE_SIMD_INT8X16_FUNCTION(Name, Func, Operands) \
|
||||
bool \
|
||||
js::simd_int8x16_##Name(JSContext* cx, unsigned argc, Value* vp) \
|
||||
{ \
|
||||
return Func(cx, argc, vp); \
|
||||
}
|
||||
INT8X16_FUNCTION_LIST(DEFINE_SIMD_INT8X16_FUNCTION)
|
||||
#undef DEFINE_SIMD_INT8X16_FUNCTION
|
||||
|
||||
#define DEFINE_SIMD_INT16X8_FUNCTION(Name, Func, Operands) \
|
||||
bool \
|
||||
js::simd_int16x8_##Name(JSContext* cx, unsigned argc, Value* vp) \
|
||||
{ \
|
||||
return Func(cx, argc, vp); \
|
||||
}
|
||||
INT16X8_FUNCTION_LIST(DEFINE_SIMD_INT16X8_FUNCTION)
|
||||
#undef DEFINE_SIMD_INT16X8_FUNCTION
|
||||
|
||||
#define DEFINE_SIMD_INT32X4_FUNCTION(Name, Func, Operands) \
|
||||
bool \
|
||||
js::simd_int32x4_##Name(JSContext* cx, unsigned argc, Value* vp) \
|
||||
@@ -1171,4 +1346,3 @@ js::simd_int32x4_##Name(JSContext* cx, unsigned argc, Value* vp) \
|
||||
}
|
||||
INT32X4_FUNCTION_LIST(DEFINE_SIMD_INT32X4_FUNCTION)
|
||||
#undef DEFINE_SIMD_INT32X4_FUNCTION
|
||||
|
||||
|
||||
+207
-61
@@ -25,6 +25,8 @@
|
||||
V(check, (UnaryFunc<Float32x4, Identity, Float32x4>), 1) \
|
||||
V(fromFloat64x2, (FuncConvert<Float64x2, Float32x4> ), 1) \
|
||||
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Float32x4>), 1) \
|
||||
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Float32x4>), 1) \
|
||||
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Float32x4>), 1) \
|
||||
V(fromInt32x4, (FuncConvert<Int32x4, Float32x4> ), 1) \
|
||||
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Float32x4>), 1) \
|
||||
V(neg, (UnaryFunc<Float32x4, Neg, Float32x4>), 1) \
|
||||
@@ -38,11 +40,12 @@
|
||||
V(add, (BinaryFunc<Float32x4, Add, Float32x4>), 2) \
|
||||
V(and, (CoercedBinaryFunc<Float32x4, Int32x4, And, Float32x4>), 2) \
|
||||
V(div, (BinaryFunc<Float32x4, Div, Float32x4>), 2) \
|
||||
V(equal, (CompareFunc<Float32x4, Equal>), 2) \
|
||||
V(greaterThan, (CompareFunc<Float32x4, GreaterThan>), 2) \
|
||||
V(greaterThanOrEqual, (CompareFunc<Float32x4, GreaterThanOrEqual>), 2) \
|
||||
V(lessThan, (CompareFunc<Float32x4, LessThan>), 2) \
|
||||
V(lessThanOrEqual, (CompareFunc<Float32x4, LessThanOrEqual>), 2) \
|
||||
V(equal, (CompareFunc<Float32x4, Equal, Int32x4>), 2) \
|
||||
V(extractLane, (ExtractLane<Float32x4>), 2) \
|
||||
V(greaterThan, (CompareFunc<Float32x4, GreaterThan, Int32x4>), 2) \
|
||||
V(greaterThanOrEqual, (CompareFunc<Float32x4, GreaterThanOrEqual, Int32x4>), 2) \
|
||||
V(lessThan, (CompareFunc<Float32x4, LessThan, Int32x4>), 2) \
|
||||
V(lessThanOrEqual, (CompareFunc<Float32x4, LessThanOrEqual, Int32x4>), 2) \
|
||||
V(load, (Load<Float32x4, 4>), 2) \
|
||||
V(load3, (Load<Float32x4, 3>), 2) \
|
||||
V(load2, (Load<Float32x4, 2>), 2) \
|
||||
@@ -52,27 +55,24 @@
|
||||
V(min, (BinaryFunc<Float32x4, Minimum, Float32x4>), 2) \
|
||||
V(minNum, (BinaryFunc<Float32x4, MinNum, Float32x4>), 2) \
|
||||
V(mul, (BinaryFunc<Float32x4, Mul, Float32x4>), 2) \
|
||||
V(notEqual, (CompareFunc<Float32x4, NotEqual>), 2) \
|
||||
V(notEqual, (CompareFunc<Float32x4, NotEqual, Int32x4>), 2) \
|
||||
V(or, (CoercedBinaryFunc<Float32x4, Int32x4, Or, Float32x4>), 2) \
|
||||
V(store, (Store<Float32x4, 4>), 3) \
|
||||
V(store3, (Store<Float32x4, 3>), 3) \
|
||||
V(store2, (Store<Float32x4, 2>), 3) \
|
||||
V(store1, (Store<Float32x4, 1>), 3) \
|
||||
V(sub, (BinaryFunc<Float32x4, Sub, Float32x4>), 2) \
|
||||
V(withX, (FuncWith<Float32x4, WithX>), 2) \
|
||||
V(withY, (FuncWith<Float32x4, WithY>), 2) \
|
||||
V(withZ, (FuncWith<Float32x4, WithZ>), 2) \
|
||||
V(withW, (FuncWith<Float32x4, WithW>), 2) \
|
||||
V(xor, (CoercedBinaryFunc<Float32x4, Int32x4, Xor, Float32x4>), 2)
|
||||
|
||||
#define FLOAT32X4_TERNARY_FUNCTION_LIST(V) \
|
||||
V(bitselect, BitSelect<Float32x4>, 3) \
|
||||
V(bitselect, (BitSelect<Float32x4, Int32x4>), 3) \
|
||||
V(clamp, Clamp<Float32x4>, 3) \
|
||||
V(select, Select<Float32x4>, 3)
|
||||
V(replaceLane, (ReplaceLane<Float32x4>), 3) \
|
||||
V(select, (Select<Float32x4, Int32x4>), 3) \
|
||||
V(store, (Store<Float32x4, 4>), 3) \
|
||||
V(store3, (Store<Float32x4, 3>), 3) \
|
||||
V(store2, (Store<Float32x4, 2>), 3) \
|
||||
V(store1, (Store<Float32x4, 1>), 3)
|
||||
|
||||
#define FLOAT32X4_SHUFFLE_FUNCTION_LIST(V) \
|
||||
V(swizzle, Swizzle<Float32x4>, 2) \
|
||||
V(shuffle, Shuffle<Float32x4>, 3)
|
||||
V(swizzle, Swizzle<Float32x4>, 5) \
|
||||
V(shuffle, Shuffle<Float32x4>, 6)
|
||||
|
||||
#define FLOAT32X4_FUNCTION_LIST(V) \
|
||||
FLOAT32X4_UNARY_FUNCTION_LIST(V) \
|
||||
@@ -85,6 +85,8 @@
|
||||
V(check, (UnaryFunc<Float64x2, Identity, Float64x2>), 1) \
|
||||
V(fromFloat32x4, (FuncConvert<Float32x4, Float64x2> ), 1) \
|
||||
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Float64x2>), 1) \
|
||||
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Float64x2>), 1) \
|
||||
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Float64x2>), 1) \
|
||||
V(fromInt32x4, (FuncConvert<Int32x4, Float64x2> ), 1) \
|
||||
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Float64x2>), 1) \
|
||||
V(neg, (UnaryFunc<Float64x2, Neg, Float64x2>), 1) \
|
||||
@@ -96,11 +98,12 @@
|
||||
#define FLOAT64X2_BINARY_FUNCTION_LIST(V) \
|
||||
V(add, (BinaryFunc<Float64x2, Add, Float64x2>), 2) \
|
||||
V(div, (BinaryFunc<Float64x2, Div, Float64x2>), 2) \
|
||||
V(equal, (CompareFunc<Float64x2, Equal>), 2) \
|
||||
V(greaterThan, (CompareFunc<Float64x2, GreaterThan>), 2) \
|
||||
V(greaterThanOrEqual, (CompareFunc<Float64x2, GreaterThanOrEqual>), 2) \
|
||||
V(lessThan, (CompareFunc<Float64x2, LessThan>), 2) \
|
||||
V(lessThanOrEqual, (CompareFunc<Float64x2, LessThanOrEqual>), 2) \
|
||||
V(equal, (CompareFunc<Float64x2, Equal, Int32x4>), 2) \
|
||||
V(extractLane, (ExtractLane<Float64x2>), 2) \
|
||||
V(greaterThan, (CompareFunc<Float64x2, GreaterThan, Int32x4>), 2) \
|
||||
V(greaterThanOrEqual, (CompareFunc<Float64x2, GreaterThanOrEqual, Int32x4>), 2) \
|
||||
V(lessThan, (CompareFunc<Float64x2, LessThan, Int32x4>), 2) \
|
||||
V(lessThanOrEqual, (CompareFunc<Float64x2, LessThanOrEqual, Int32x4>), 2) \
|
||||
V(load, (Load<Float64x2, 2>), 2) \
|
||||
V(load1, (Load<Float64x2, 1>), 2) \
|
||||
V(max, (BinaryFunc<Float64x2, Maximum, Float64x2>), 2) \
|
||||
@@ -108,21 +111,20 @@
|
||||
V(min, (BinaryFunc<Float64x2, Minimum, Float64x2>), 2) \
|
||||
V(minNum, (BinaryFunc<Float64x2, MinNum, Float64x2>), 2) \
|
||||
V(mul, (BinaryFunc<Float64x2, Mul, Float64x2>), 2) \
|
||||
V(notEqual, (CompareFunc<Float64x2, NotEqual>), 2) \
|
||||
V(store, (Store<Float64x2, 2>), 3) \
|
||||
V(store1, (Store<Float64x2, 1>), 3) \
|
||||
V(sub, (BinaryFunc<Float64x2, Sub, Float64x2>), 2) \
|
||||
V(withX, (FuncWith<Float64x2, WithX>), 2) \
|
||||
V(withY, (FuncWith<Float64x2, WithY>), 2)
|
||||
V(notEqual, (CompareFunc<Float64x2, NotEqual, Int32x4>), 2) \
|
||||
V(sub, (BinaryFunc<Float64x2, Sub, Float64x2>), 2)
|
||||
|
||||
#define FLOAT64X2_TERNARY_FUNCTION_LIST(V) \
|
||||
V(bitselect, BitSelect<Float64x2>, 3) \
|
||||
V(bitselect, (BitSelect<Float64x2, Int32x4>), 3) \
|
||||
V(clamp, Clamp<Float64x2>, 3) \
|
||||
V(select, Select<Float64x2>, 3)
|
||||
V(replaceLane, (ReplaceLane<Float64x2>), 3) \
|
||||
V(select, (Select<Float64x2, Int32x4>), 3) \
|
||||
V(store, (Store<Float64x2, 2>), 3) \
|
||||
V(store1, (Store<Float64x2, 1>), 3)
|
||||
|
||||
#define FLOAT64X2_SHUFFLE_FUNCTION_LIST(V) \
|
||||
V(swizzle, Swizzle<Float64x2>, 2) \
|
||||
V(shuffle, Shuffle<Float64x2>, 3)
|
||||
V(swizzle, Swizzle<Float64x2>, 3) \
|
||||
V(shuffle, Shuffle<Float64x2>, 4)
|
||||
|
||||
#define FLOAT64X2_FUNCTION_LIST(V) \
|
||||
FLOAT64X2_UNARY_FUNCTION_LIST(V) \
|
||||
@@ -130,12 +132,112 @@
|
||||
FLOAT64X2_TERNARY_FUNCTION_LIST(V) \
|
||||
FLOAT64X2_SHUFFLE_FUNCTION_LIST(V)
|
||||
|
||||
#define INT8X16_UNARY_FUNCTION_LIST(V) \
|
||||
V(check, (UnaryFunc<Int8x16, Identity, Int8x16>), 1) \
|
||||
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Int8x16>), 1) \
|
||||
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Int8x16>), 1) \
|
||||
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Int8x16>), 1) \
|
||||
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Int8x16>), 1) \
|
||||
V(neg, (UnaryFunc<Int8x16, Neg, Int8x16>), 1) \
|
||||
V(not, (UnaryFunc<Int8x16, Not, Int8x16>), 1) \
|
||||
V(splat, (FuncSplat<Int8x16>), 1)
|
||||
|
||||
#define INT8X16_BINARY_FUNCTION_LIST(V) \
|
||||
V(add, (BinaryFunc<Int8x16, Add, Int8x16>), 2) \
|
||||
V(and, (BinaryFunc<Int8x16, And, Int8x16>), 2) \
|
||||
V(equal, (CompareFunc<Int8x16, Equal, Int8x16>), 2) \
|
||||
V(extractLane, (ExtractLane<Int8x16>), 2) \
|
||||
V(greaterThan, (CompareFunc<Int8x16, GreaterThan, Int8x16>), 2) \
|
||||
V(greaterThanOrEqual, (CompareFunc<Int8x16, GreaterThanOrEqual, Int8x16>), 2) \
|
||||
V(lessThan, (CompareFunc<Int8x16, LessThan, Int8x16>), 2) \
|
||||
V(lessThanOrEqual, (CompareFunc<Int8x16, LessThanOrEqual, Int8x16>), 2) \
|
||||
V(load, (Load<Int8x16, 16>), 2) \
|
||||
V(mul, (BinaryFunc<Int8x16, Mul, Int8x16>), 2) \
|
||||
V(notEqual, (CompareFunc<Int8x16, NotEqual, Int8x16>), 2) \
|
||||
V(or, (BinaryFunc<Int8x16, Or, Int8x16>), 2) \
|
||||
V(sub, (BinaryFunc<Int8x16, Sub, Int8x16>), 2) \
|
||||
V(shiftLeftByScalar, (BinaryScalar<Int8x16, ShiftLeft>), 2) \
|
||||
V(shiftRightArithmeticByScalar, (BinaryScalar<Int8x16, ShiftRightArithmetic>), 2) \
|
||||
V(shiftRightLogicalByScalar, (BinaryScalar<Int8x16, ShiftRightLogical>), 2) \
|
||||
V(xor, (BinaryFunc<Int8x16, Xor, Int8x16>), 2)
|
||||
|
||||
#define INT8X16_TERNARY_FUNCTION_LIST(V) \
|
||||
V(bitselect, (BitSelect<Int8x16, Int8x16>), 3) \
|
||||
V(replaceLane, (ReplaceLane<Int8x16>), 3) \
|
||||
V(select, (Select<Int8x16, Int8x16>), 3) \
|
||||
V(store, (Store<Int8x16, 16>), 3)
|
||||
|
||||
#define INT8X16_BOOL_FUNCTION_LIST(V) \
|
||||
V(bool, Bool<Int8x16>, 16)
|
||||
|
||||
#define INT8X16_SHUFFLE_FUNCTION_LIST(V) \
|
||||
V(swizzle, Swizzle<Int8x16>, 17) \
|
||||
V(shuffle, Shuffle<Int8x16>, 18)
|
||||
|
||||
#define INT8X16_FUNCTION_LIST(V) \
|
||||
INT8X16_UNARY_FUNCTION_LIST(V) \
|
||||
INT8X16_BINARY_FUNCTION_LIST(V) \
|
||||
INT8X16_TERNARY_FUNCTION_LIST(V) \
|
||||
INT8X16_BOOL_FUNCTION_LIST(V) \
|
||||
INT8X16_SHUFFLE_FUNCTION_LIST(V)
|
||||
|
||||
#define INT16X8_UNARY_FUNCTION_LIST(V) \
|
||||
V(check, (UnaryFunc<Int16x8, Identity, Int16x8>), 1) \
|
||||
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Int16x8>), 1) \
|
||||
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Int16x8>), 1) \
|
||||
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Int16x8>), 1) \
|
||||
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Int16x8>), 1) \
|
||||
V(neg, (UnaryFunc<Int16x8, Neg, Int16x8>), 1) \
|
||||
V(not, (UnaryFunc<Int16x8, Not, Int16x8>), 1) \
|
||||
V(splat, (FuncSplat<Int16x8>), 1)
|
||||
|
||||
#define INT16X8_BINARY_FUNCTION_LIST(V) \
|
||||
V(add, (BinaryFunc<Int16x8, Add, Int16x8>), 2) \
|
||||
V(and, (BinaryFunc<Int16x8, And, Int16x8>), 2) \
|
||||
V(equal, (CompareFunc<Int16x8, Equal, Int16x8>), 2) \
|
||||
V(extractLane, (ExtractLane<Int16x8>), 2) \
|
||||
V(greaterThan, (CompareFunc<Int16x8, GreaterThan, Int16x8>), 2) \
|
||||
V(greaterThanOrEqual, (CompareFunc<Int16x8, GreaterThanOrEqual, Int16x8>), 2) \
|
||||
V(lessThan, (CompareFunc<Int16x8, LessThan, Int16x8>), 2) \
|
||||
V(lessThanOrEqual, (CompareFunc<Int16x8, LessThanOrEqual, Int16x8>), 2) \
|
||||
V(load, (Load<Int16x8, 8>), 2) \
|
||||
V(mul, (BinaryFunc<Int16x8, Mul, Int16x8>), 2) \
|
||||
V(notEqual, (CompareFunc<Int16x8, NotEqual, Int16x8>), 2) \
|
||||
V(or, (BinaryFunc<Int16x8, Or, Int16x8>), 2) \
|
||||
V(sub, (BinaryFunc<Int16x8, Sub, Int16x8>), 2) \
|
||||
V(shiftLeftByScalar, (BinaryScalar<Int16x8, ShiftLeft>), 2) \
|
||||
V(shiftRightArithmeticByScalar, (BinaryScalar<Int16x8, ShiftRightArithmetic>), 2) \
|
||||
V(shiftRightLogicalByScalar, (BinaryScalar<Int16x8, ShiftRightLogical>), 2) \
|
||||
V(xor, (BinaryFunc<Int16x8, Xor, Int16x8>), 2)
|
||||
|
||||
#define INT16X8_TERNARY_FUNCTION_LIST(V) \
|
||||
V(bitselect, (BitSelect<Int16x8, Int16x8>), 3) \
|
||||
V(replaceLane, (ReplaceLane<Int16x8>), 3) \
|
||||
V(select, (Select<Int16x8, Int16x8>), 3) \
|
||||
V(store, (Store<Int16x8, 8>), 3)
|
||||
|
||||
#define INT16X8_BOOL_FUNCTION_LIST(V) \
|
||||
V(bool, Bool<Int16x8>, 8)
|
||||
|
||||
#define INT16X8_SHUFFLE_FUNCTION_LIST(V) \
|
||||
V(swizzle, Swizzle<Int16x8>, 9) \
|
||||
V(shuffle, Shuffle<Int16x8>, 10)
|
||||
|
||||
#define INT16X8_FUNCTION_LIST(V) \
|
||||
INT16X8_UNARY_FUNCTION_LIST(V) \
|
||||
INT16X8_BINARY_FUNCTION_LIST(V) \
|
||||
INT16X8_TERNARY_FUNCTION_LIST(V) \
|
||||
INT16X8_BOOL_FUNCTION_LIST(V) \
|
||||
INT16X8_SHUFFLE_FUNCTION_LIST(V)
|
||||
|
||||
#define INT32X4_UNARY_FUNCTION_LIST(V) \
|
||||
V(check, (UnaryFunc<Int32x4, Identity, Int32x4>), 1) \
|
||||
V(fromFloat32x4, (FuncConvert<Float32x4, Int32x4>), 1) \
|
||||
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Int32x4>), 1) \
|
||||
V(fromFloat64x2, (FuncConvert<Float64x2, Int32x4>), 1) \
|
||||
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Int32x4>), 1) \
|
||||
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Int32x4>), 1) \
|
||||
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Int32x4>), 1) \
|
||||
V(neg, (UnaryFunc<Int32x4, Neg, Int32x4>), 1) \
|
||||
V(not, (UnaryFunc<Int32x4, Not, Int32x4>), 1) \
|
||||
V(splat, (FuncSplat<Int32x4>), 0)
|
||||
@@ -143,42 +245,40 @@
|
||||
#define INT32X4_BINARY_FUNCTION_LIST(V) \
|
||||
V(add, (BinaryFunc<Int32x4, Add, Int32x4>), 2) \
|
||||
V(and, (BinaryFunc<Int32x4, And, Int32x4>), 2) \
|
||||
V(equal, (CompareFunc<Int32x4, Equal>), 2) \
|
||||
V(greaterThan, (CompareFunc<Int32x4, GreaterThan>), 2) \
|
||||
V(greaterThanOrEqual, (CompareFunc<Int32x4, GreaterThanOrEqual>), 2) \
|
||||
V(lessThan, (CompareFunc<Int32x4, LessThan>), 2) \
|
||||
V(lessThanOrEqual, (CompareFunc<Int32x4, LessThanOrEqual>), 2) \
|
||||
V(equal, (CompareFunc<Int32x4, Equal, Int32x4>), 2) \
|
||||
V(extractLane, (ExtractLane<Int32x4>), 2) \
|
||||
V(greaterThan, (CompareFunc<Int32x4, GreaterThan, Int32x4>), 2) \
|
||||
V(greaterThanOrEqual, (CompareFunc<Int32x4, GreaterThanOrEqual, Int32x4>), 2) \
|
||||
V(lessThan, (CompareFunc<Int32x4, LessThan, Int32x4>), 2) \
|
||||
V(lessThanOrEqual, (CompareFunc<Int32x4, LessThanOrEqual, Int32x4>), 2) \
|
||||
V(load, (Load<Int32x4, 4>), 2) \
|
||||
V(load3, (Load<Int32x4, 3>), 2) \
|
||||
V(load2, (Load<Int32x4, 2>), 2) \
|
||||
V(load1, (Load<Int32x4, 1>), 2) \
|
||||
V(mul, (BinaryFunc<Int32x4, Mul, Int32x4>), 2) \
|
||||
V(notEqual, (CompareFunc<Int32x4, NotEqual>), 2) \
|
||||
V(notEqual, (CompareFunc<Int32x4, NotEqual, Int32x4>), 2) \
|
||||
V(or, (BinaryFunc<Int32x4, Or, Int32x4>), 2) \
|
||||
V(sub, (BinaryFunc<Int32x4, Sub, Int32x4>), 2) \
|
||||
V(shiftLeftByScalar, (Int32x4BinaryScalar<ShiftLeft>), 2) \
|
||||
V(shiftRightArithmeticByScalar, (Int32x4BinaryScalar<ShiftRightArithmetic>), 2) \
|
||||
V(shiftRightLogicalByScalar, (Int32x4BinaryScalar<ShiftRightLogical>), 2) \
|
||||
V(store, (Store<Int32x4, 4>), 3) \
|
||||
V(store3, (Store<Int32x4, 3>), 3) \
|
||||
V(store2, (Store<Int32x4, 2>), 3) \
|
||||
V(store1, (Store<Int32x4, 1>), 3) \
|
||||
V(withX, (FuncWith<Int32x4, WithX>), 2) \
|
||||
V(withY, (FuncWith<Int32x4, WithY>), 2) \
|
||||
V(withZ, (FuncWith<Int32x4, WithZ>), 2) \
|
||||
V(withW, (FuncWith<Int32x4, WithW>), 2) \
|
||||
V(shiftLeftByScalar, (BinaryScalar<Int32x4, ShiftLeft>), 2) \
|
||||
V(shiftRightArithmeticByScalar, (BinaryScalar<Int32x4, ShiftRightArithmetic>), 2) \
|
||||
V(shiftRightLogicalByScalar, (BinaryScalar<Int32x4, ShiftRightLogical>), 2) \
|
||||
V(xor, (BinaryFunc<Int32x4, Xor, Int32x4>), 2)
|
||||
|
||||
#define INT32X4_TERNARY_FUNCTION_LIST(V) \
|
||||
V(bitselect, BitSelect<Int32x4>, 3) \
|
||||
V(select, Select<Int32x4>, 3)
|
||||
V(bitselect, (BitSelect<Int32x4, Int32x4>), 3) \
|
||||
V(replaceLane, (ReplaceLane<Int32x4>), 3) \
|
||||
V(select, (Select<Int32x4, Int32x4>), 3) \
|
||||
V(store, (Store<Int32x4, 4>), 3) \
|
||||
V(store3, (Store<Int32x4, 3>), 3) \
|
||||
V(store2, (Store<Int32x4, 2>), 3) \
|
||||
V(store1, (Store<Int32x4, 1>), 3)
|
||||
|
||||
#define INT32X4_QUARTERNARY_FUNCTION_LIST(V) \
|
||||
V(bool, Int32x4Bool, 4)
|
||||
V(bool, Bool<Int32x4>, 4)
|
||||
|
||||
#define INT32X4_SHUFFLE_FUNCTION_LIST(V) \
|
||||
V(swizzle, Swizzle<Int32x4>, 2) \
|
||||
V(shuffle, Shuffle<Int32x4>, 3)
|
||||
V(swizzle, Swizzle<Int32x4>, 5) \
|
||||
V(shuffle, Shuffle<Int32x4>, 6)
|
||||
|
||||
#define INT32X4_FUNCTION_LIST(V) \
|
||||
INT32X4_UNARY_FUNCTION_LIST(V) \
|
||||
@@ -226,16 +326,12 @@
|
||||
_(notEqual) \
|
||||
_(greaterThan) \
|
||||
_(greaterThanOrEqual)
|
||||
#define WITH_COMMONX4_SIMD_OP(_) \
|
||||
_(withX) \
|
||||
_(withY) \
|
||||
_(withZ) \
|
||||
_(withW)
|
||||
// TODO: remove when all SIMD calls are inlined (bug 1112155)
|
||||
#define ION_COMMONX4_SIMD_OP(_) \
|
||||
ARITH_COMMONX4_SIMD_OP(_) \
|
||||
BITWISE_COMMONX4_SIMD_OP(_) \
|
||||
WITH_COMMONX4_SIMD_OP(_) \
|
||||
_(extractLane) \
|
||||
_(replaceLane) \
|
||||
_(bitselect) \
|
||||
_(select) \
|
||||
_(splat) \
|
||||
@@ -316,6 +412,44 @@ struct Float64x2 {
|
||||
}
|
||||
};
|
||||
|
||||
struct Int8x16 {
|
||||
typedef int8_t Elem;
|
||||
static const unsigned lanes = 16;
|
||||
static const SimdTypeDescr::Type type = SimdTypeDescr::Int8x16;
|
||||
|
||||
static TypeDescr& GetTypeDescr(GlobalObject& global) {
|
||||
return global.int8x16TypeDescr().as<TypeDescr>();
|
||||
}
|
||||
static Elem toType(Elem a) {
|
||||
return JS::ToInt8(a);
|
||||
}
|
||||
static bool toType(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
return ToInt8(cx, v, out);
|
||||
}
|
||||
static void setReturn(CallArgs& args, Elem value) {
|
||||
args.rval().setInt32(value);
|
||||
}
|
||||
};
|
||||
|
||||
struct Int16x8 {
|
||||
typedef int16_t Elem;
|
||||
static const unsigned lanes = 8;
|
||||
static const SimdTypeDescr::Type type = SimdTypeDescr::Int16x8;
|
||||
|
||||
static TypeDescr& GetTypeDescr(GlobalObject& global) {
|
||||
return global.int16x8TypeDescr().as<TypeDescr>();
|
||||
}
|
||||
static Elem toType(Elem a) {
|
||||
return JS::ToInt16(a);
|
||||
}
|
||||
static bool toType(JSContext* cx, JS::HandleValue v, Elem* out) {
|
||||
return ToInt16(cx, v, out);
|
||||
}
|
||||
static void setReturn(CallArgs& args, Elem value) {
|
||||
args.rval().setInt32(value);
|
||||
}
|
||||
};
|
||||
|
||||
struct Int32x4 {
|
||||
typedef int32_t Elem;
|
||||
static const unsigned lanes = 4;
|
||||
@@ -356,6 +490,18 @@ simd_float64x2_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
FLOAT64X2_FUNCTION_LIST(DECLARE_SIMD_FLOAT64X2_FUNCTION)
|
||||
#undef DECLARE_SIMD_FLOAT64X2_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_INT8X16_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
simd_int8x16_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
INT8X16_FUNCTION_LIST(DECLARE_SIMD_INT8X16_FUNCTION)
|
||||
#undef DECLARE_SIMD_INT8X16_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_INT16X8_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
simd_int16x8_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
INT16X8_FUNCTION_LIST(DECLARE_SIMD_INT16X8_FUNCTION)
|
||||
#undef DECLARE_SIMD_INT16X8_FUNCTION
|
||||
|
||||
#define DECLARE_SIMD_INT32x4_FUNCTION(Name, Func, Operands) \
|
||||
extern bool \
|
||||
simd_int32x4_##Name(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
+20
-20
@@ -7,7 +7,7 @@
|
||||
/* ES6 Draft Oct 14, 2014 21.1.3.19 */
|
||||
function String_substring(start, end) {
|
||||
// Steps 1-3.
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var str = ToString(this);
|
||||
|
||||
// Step 4.
|
||||
@@ -51,7 +51,7 @@ function String_static_substring(string, start, end) {
|
||||
/* ES6 Draft Oct 14, 2014 B.2.3.1 */
|
||||
function String_substr(start, length) {
|
||||
// Steps 1-2.
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var str = ToString(this);
|
||||
|
||||
// Steps 3-4.
|
||||
@@ -90,7 +90,7 @@ function String_static_substr(string, start, length) {
|
||||
/* ES6 Draft Oct 14, 2014 21.1.3.16 */
|
||||
function String_slice(start, end) {
|
||||
// Steps 1-3.
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var str = ToString(this);
|
||||
|
||||
// Step 4.
|
||||
@@ -127,7 +127,7 @@ function String_static_slice(string, start, end) {
|
||||
/* ES6 Draft September 5, 2013 21.1.3.3 */
|
||||
function String_codePointAt(pos) {
|
||||
// Steps 1-3.
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var S = ToString(this);
|
||||
|
||||
// Steps 4-5.
|
||||
@@ -159,7 +159,7 @@ var collatorCache = new Record();
|
||||
/* ES6 20121122 draft 15.5.4.21. */
|
||||
function String_repeat(count) {
|
||||
// Steps 1-3.
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var S = ToString(this);
|
||||
|
||||
// Steps 4-5.
|
||||
@@ -194,7 +194,7 @@ function String_repeat(count) {
|
||||
|
||||
// ES6 draft specification, section 21.1.3.27, version 2013-09-27.
|
||||
function String_iterator() {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var S = ToString(this);
|
||||
var iterator = NewStringIterator();
|
||||
UnsafeSetReservedSlot(iterator, STRING_ITERATOR_SLOT_ITERATED_STRING, S);
|
||||
@@ -244,7 +244,7 @@ function StringIteratorNext() {
|
||||
*/
|
||||
function String_localeCompare(that) {
|
||||
// Steps 1-3.
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var S = ToString(this);
|
||||
var That = ToString(that);
|
||||
|
||||
@@ -377,55 +377,55 @@ function String_static_localeCompare(str1, str2) {
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.3
|
||||
function String_big() {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
return "<big>" + ToString(this) + "</big>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.4
|
||||
function String_blink() {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
return "<blink>" + ToString(this) + "</blink>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.5
|
||||
function String_bold() {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
return "<b>" + ToString(this) + "</b>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.6
|
||||
function String_fixed() {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
return "<tt>" + ToString(this) + "</tt>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.9
|
||||
function String_italics() {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
return "<i>" + ToString(this) + "</i>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.11
|
||||
function String_small() {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
return "<small>" + ToString(this) + "</small>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.12
|
||||
function String_strike() {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
return "<strike>" + ToString(this) + "</strike>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.13
|
||||
function String_sub() {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
return "<sub>" + ToString(this) + "</sub>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.14
|
||||
function String_sup() {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
return "<sup>" + ToString(this) + "</sup>";
|
||||
}
|
||||
|
||||
@@ -449,28 +449,28 @@ function EscapeAttributeValue(v) {
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.2
|
||||
function String_anchor(name) {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var S = ToString(this);
|
||||
return '<a name="' + EscapeAttributeValue(name) + '">' + S + "</a>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.7
|
||||
function String_fontcolor(color) {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var S = ToString(this);
|
||||
return '<font color="' + EscapeAttributeValue(color) + '">' + S + "</font>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.8
|
||||
function String_fontsize(size) {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var S = ToString(this);
|
||||
return '<font size="' + EscapeAttributeValue(size) + '">' + S + "</font>";
|
||||
}
|
||||
|
||||
// ES6 draft 2014-04-27 B.2.3.10
|
||||
function String_link(url) {
|
||||
CheckObjectCoercible(this);
|
||||
RequireObjectCoercible(this);
|
||||
var S = ToString(this);
|
||||
return '<a href="' + EscapeAttributeValue(url) + '">' + S + "</a>";
|
||||
}
|
||||
|
||||
@@ -2551,6 +2551,20 @@ GetConstructorName(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
AllocationMarker(JSContext* cx, unsigned argc, jsval* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
static const JSClass cls = { "AllocationMarker" };
|
||||
|
||||
RootedObject obj(cx, JS_NewObject(cx, &cls));
|
||||
if (!obj)
|
||||
return false;
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const JSFunctionSpecWithHelp TestingFunctions[] = {
|
||||
JS_FN_HELP("gc", ::GC, 0, 0,
|
||||
"gc([obj] | 'compartment' [, 'shrinking'])",
|
||||
@@ -2948,6 +2962,13 @@ gc::ZealModeHelpText),
|
||||
" If the given object was created with `new Ctor`, return the constructor's display name. "
|
||||
" Otherwise, return null."),
|
||||
|
||||
JS_FN_HELP("allocationMarker", AllocationMarker, 0, 0,
|
||||
"allocationMarker()",
|
||||
" Return a freshly allocated object whose [[Class]] name is\n"
|
||||
" \"AllocationMarker\". Such objects are allocated only by calls\n"
|
||||
" to this function, never implicitly by the system, making them\n"
|
||||
" suitable for use in allocation tooling tests.\n"),
|
||||
|
||||
JS_FS_HELP_END
|
||||
};
|
||||
|
||||
|
||||
@@ -2620,6 +2620,26 @@ js::GetFloat64x2TypeDescr(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::GetInt8x16TypeDescr(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
Rooted<GlobalObject*> global(cx, cx->global());
|
||||
MOZ_ASSERT(global);
|
||||
args.rval().setObject(global->int8x16TypeDescr());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::GetInt16x8TypeDescr(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
Rooted<GlobalObject*> global(cx, cx->global());
|
||||
MOZ_ASSERT(global);
|
||||
args.rval().setObject(global->int16x8TypeDescr());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::GetInt32x4TypeDescr(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
||||
@@ -328,12 +328,14 @@ class ComplexTypeDescr : public TypeDescr
|
||||
};
|
||||
|
||||
/*
|
||||
* Type descriptors `float32x4`, `int32x4` and `float64x2`
|
||||
* Type descriptors `int8x16`, `int16x8`, `int32x4`, `float32x4` and `float64x2`
|
||||
*/
|
||||
class SimdTypeDescr : public ComplexTypeDescr
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
Int8x16 = JS_SIMDTYPEREPR_INT8,
|
||||
Int16x8 = JS_SIMDTYPEREPR_INT16,
|
||||
Int32x4 = JS_SIMDTYPEREPR_INT32,
|
||||
Float32x4 = JS_SIMDTYPEREPR_FLOAT32,
|
||||
Float64x2 = JS_SIMDTYPEREPR_FLOAT64,
|
||||
@@ -356,6 +358,8 @@ class SimdTypeDescr : public ComplexTypeDescr
|
||||
};
|
||||
|
||||
#define JS_FOR_EACH_SIMD_TYPE_REPR(macro_) \
|
||||
macro_(SimdTypeDescr::Int8x16, int8_t, int8, 16) \
|
||||
macro_(SimdTypeDescr::Int16x8, int16_t, int16, 8) \
|
||||
macro_(SimdTypeDescr::Int32x4, int32_t, int32, 4) \
|
||||
macro_(SimdTypeDescr::Float32x4, float, float32, 4) \
|
||||
macro_(SimdTypeDescr::Float64x2, double, float64, 2)
|
||||
@@ -863,6 +867,22 @@ bool GetFloat32x4TypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
*/
|
||||
bool GetFloat64x2TypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: GetInt8x16TypeDescr()
|
||||
*
|
||||
* Returns the int8x16 type object. SIMD pseudo-module must have
|
||||
* been initialized for this to be safe.
|
||||
*/
|
||||
bool GetInt8x16TypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: GetInt16x8TypeDescr()
|
||||
*
|
||||
* Returns the int16x8 type object. SIMD pseudo-module must have
|
||||
* been initialized for this to be safe.
|
||||
*/
|
||||
bool GetInt16x8TypeDescr(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/*
|
||||
* Usage: GetInt32x4TypeDescr()
|
||||
*
|
||||
|
||||
+128
-14
@@ -157,6 +157,37 @@ function TypedObjectGetSimd(descr, typedObj, offset) {
|
||||
var y = Load_float64(typedObj, offset + 8);
|
||||
return GetFloat64x2TypeDescr()(x, y);
|
||||
|
||||
case JS_SIMDTYPEREPR_INT8:
|
||||
var s0 = Load_int8(typedObj, offset + 0);
|
||||
var s1 = Load_int8(typedObj, offset + 1);
|
||||
var s2 = Load_int8(typedObj, offset + 2);
|
||||
var s3 = Load_int8(typedObj, offset + 3);
|
||||
var s4 = Load_int8(typedObj, offset + 4);
|
||||
var s5 = Load_int8(typedObj, offset + 5);
|
||||
var s6 = Load_int8(typedObj, offset + 6);
|
||||
var s7 = Load_int8(typedObj, offset + 7);
|
||||
var s8 = Load_int8(typedObj, offset + 8);
|
||||
var s9 = Load_int8(typedObj, offset + 9);
|
||||
var s10 = Load_int8(typedObj, offset + 10);
|
||||
var s11 = Load_int8(typedObj, offset + 11);
|
||||
var s12 = Load_int8(typedObj, offset + 12);
|
||||
var s13 = Load_int8(typedObj, offset + 13);
|
||||
var s14 = Load_int8(typedObj, offset + 14);
|
||||
var s15 = Load_int8(typedObj, offset + 15);
|
||||
return GetInt8x16TypeDescr()(s0, s1, s2, s3, s4, s5, s6, s7,
|
||||
s8, s9, s10, s11, s12, s13, s14, s15);
|
||||
|
||||
case JS_SIMDTYPEREPR_INT16:
|
||||
var s0 = Load_int16(typedObj, offset + 0);
|
||||
var s1 = Load_int16(typedObj, offset + 2);
|
||||
var s2 = Load_int16(typedObj, offset + 4);
|
||||
var s3 = Load_int16(typedObj, offset + 6);
|
||||
var s4 = Load_int16(typedObj, offset + 8);
|
||||
var s5 = Load_int16(typedObj, offset + 10);
|
||||
var s6 = Load_int16(typedObj, offset + 12);
|
||||
var s7 = Load_int16(typedObj, offset + 14);
|
||||
return GetInt16x8TypeDescr()(s0, s1, s2, s3, s4, s5, s6, s7);
|
||||
|
||||
case JS_SIMDTYPEREPR_INT32:
|
||||
var x = Load_int32(typedObj, offset + 0);
|
||||
var y = Load_int32(typedObj, offset + 4);
|
||||
@@ -252,11 +283,11 @@ function TypedObjectSetScalar(descr, typedObj, offset, fromValue) {
|
||||
switch (type) {
|
||||
case JS_SCALARTYPEREPR_INT8:
|
||||
return Store_int8(typedObj, offset,
|
||||
TO_INT32(fromValue) & 0xFF);
|
||||
TO_INT32(fromValue) & 0xFF);
|
||||
|
||||
case JS_SCALARTYPEREPR_UINT8:
|
||||
return Store_uint8(typedObj, offset,
|
||||
TO_UINT32(fromValue) & 0xFF);
|
||||
TO_UINT32(fromValue) & 0xFF);
|
||||
|
||||
case JS_SCALARTYPEREPR_UINT8_CLAMPED:
|
||||
var v = ClampToUint8(+fromValue);
|
||||
@@ -264,19 +295,19 @@ function TypedObjectSetScalar(descr, typedObj, offset, fromValue) {
|
||||
|
||||
case JS_SCALARTYPEREPR_INT16:
|
||||
return Store_int16(typedObj, offset,
|
||||
TO_INT32(fromValue) & 0xFFFF);
|
||||
TO_INT32(fromValue) & 0xFFFF);
|
||||
|
||||
case JS_SCALARTYPEREPR_UINT16:
|
||||
return Store_uint16(typedObj, offset,
|
||||
TO_UINT32(fromValue) & 0xFFFF);
|
||||
TO_UINT32(fromValue) & 0xFFFF);
|
||||
|
||||
case JS_SCALARTYPEREPR_INT32:
|
||||
return Store_int32(typedObj, offset,
|
||||
TO_INT32(fromValue));
|
||||
TO_INT32(fromValue));
|
||||
|
||||
case JS_SCALARTYPEREPR_UINT32:
|
||||
return Store_uint32(typedObj, offset,
|
||||
TO_UINT32(fromValue));
|
||||
TO_UINT32(fromValue));
|
||||
|
||||
case JS_SCALARTYPEREPR_FLOAT32:
|
||||
return Store_float32(typedObj, offset, +fromValue);
|
||||
@@ -331,6 +362,34 @@ function TypedObjectSetSimd(descr, typedObj, offset, fromValue) {
|
||||
Store_float64(typedObj, offset + 0, Load_float64(fromValue, 0));
|
||||
Store_float64(typedObj, offset + 8, Load_float64(fromValue, 8));
|
||||
break;
|
||||
case JS_SIMDTYPEREPR_INT8:
|
||||
Store_int8(typedObj, offset + 0, Load_int8(fromValue, 0));
|
||||
Store_int8(typedObj, offset + 1, Load_int8(fromValue, 1));
|
||||
Store_int8(typedObj, offset + 2, Load_int8(fromValue, 2));
|
||||
Store_int8(typedObj, offset + 3, Load_int8(fromValue, 3));
|
||||
Store_int8(typedObj, offset + 4, Load_int8(fromValue, 4));
|
||||
Store_int8(typedObj, offset + 5, Load_int8(fromValue, 5));
|
||||
Store_int8(typedObj, offset + 6, Load_int8(fromValue, 6));
|
||||
Store_int8(typedObj, offset + 7, Load_int8(fromValue, 7));
|
||||
Store_int8(typedObj, offset + 8, Load_int8(fromValue, 8));
|
||||
Store_int8(typedObj, offset + 9, Load_int8(fromValue, 9));
|
||||
Store_int8(typedObj, offset + 10, Load_int8(fromValue, 10));
|
||||
Store_int8(typedObj, offset + 11, Load_int8(fromValue, 11));
|
||||
Store_int8(typedObj, offset + 12, Load_int8(fromValue, 12));
|
||||
Store_int8(typedObj, offset + 13, Load_int8(fromValue, 13));
|
||||
Store_int8(typedObj, offset + 14, Load_int8(fromValue, 14));
|
||||
Store_int8(typedObj, offset + 15, Load_int8(fromValue, 15));
|
||||
break;
|
||||
case JS_SIMDTYPEREPR_INT16:
|
||||
Store_int16(typedObj, offset + 0, Load_int16(fromValue, 0));
|
||||
Store_int16(typedObj, offset + 2, Load_int16(fromValue, 2));
|
||||
Store_int16(typedObj, offset + 4, Load_int16(fromValue, 4));
|
||||
Store_int16(typedObj, offset + 6, Load_int16(fromValue, 6));
|
||||
Store_int16(typedObj, offset + 8, Load_int16(fromValue, 8));
|
||||
Store_int16(typedObj, offset + 10, Load_int16(fromValue, 10));
|
||||
Store_int16(typedObj, offset + 12, Load_int16(fromValue, 12));
|
||||
Store_int16(typedObj, offset + 14, Load_int16(fromValue, 14));
|
||||
break;
|
||||
case JS_SIMDTYPEREPR_INT32:
|
||||
Store_int32(typedObj, offset + 0, Load_int32(fromValue, 0));
|
||||
Store_int32(typedObj, offset + 4, Load_int32(fromValue, 4));
|
||||
@@ -462,6 +521,10 @@ function TypedObjectArrayRedimension(newArrayType) {
|
||||
|
||||
function SimdProtoString(type) {
|
||||
switch (type) {
|
||||
case JS_SIMDTYPEREPR_INT8:
|
||||
return "int8x16";
|
||||
case JS_SIMDTYPEREPR_INT16:
|
||||
return "int16x8";
|
||||
case JS_SIMDTYPEREPR_INT32:
|
||||
return "int32x4";
|
||||
case JS_SIMDTYPEREPR_FLOAT32:
|
||||
@@ -476,6 +539,10 @@ function SimdProtoString(type) {
|
||||
|
||||
function SimdTypeToLength(type) {
|
||||
switch (type) {
|
||||
case JS_SIMDTYPEREPR_INT8:
|
||||
return 16;
|
||||
case JS_SIMDTYPEREPR_INT16:
|
||||
return 8;
|
||||
case JS_SIMDTYPEREPR_INT32:
|
||||
case JS_SIMDTYPEREPR_FLOAT32:
|
||||
return 4;
|
||||
@@ -495,14 +562,61 @@ function SimdToSource() {
|
||||
|
||||
if (DESCR_KIND(descr) != JS_TYPEREPR_SIMD_KIND)
|
||||
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD", "toSource", typeof this);
|
||||
|
||||
var type = DESCR_TYPE(descr);
|
||||
var protoString = SimdProtoString(type);
|
||||
var length = SimdTypeToLength(type);
|
||||
if (length == 4)
|
||||
return protoString+"("+this.x+", "+this.y+", "+this.z+", "+this.w+")";
|
||||
else if (length == 2)
|
||||
return protoString+"("+this.x+", "+this.y+")";
|
||||
var typerepr = DESCR_TYPE(descr);
|
||||
var protoString = SimdProtoString(typerepr);
|
||||
switch (typerepr) {
|
||||
case JS_SIMDTYPEREPR_INT8: {
|
||||
var s1 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 0);
|
||||
var s2 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 1);
|
||||
var s3 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 2);
|
||||
var s4 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 3);
|
||||
var s5 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 4);
|
||||
var s6 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 5);
|
||||
var s7 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 6);
|
||||
var s8 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 7);
|
||||
var s9 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 0);
|
||||
var s10 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 1);
|
||||
var s11 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 2);
|
||||
var s12 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 3);
|
||||
var s13 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 4);
|
||||
var s14 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 5);
|
||||
var s15 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 6);
|
||||
var s16 = callFunction(std_SIMD_Int8x16_extractLane, null, this, 7);
|
||||
return `${protoString}(${s1}, ${s2}, ${s3}, ${s4}, ${s5}, ${s6}, ${s7}, ${s8}, ${s9}, ${s10}, ${s11}, ${s12}, ${s13}, ${s14}, ${s15}, ${s16})`;
|
||||
}
|
||||
case JS_SIMDTYPEREPR_INT16: {
|
||||
var s1 = callFunction(std_SIMD_Int16x8_extractLane, null, this, 0);
|
||||
var s2 = callFunction(std_SIMD_Int16x8_extractLane, null, this, 1);
|
||||
var s3 = callFunction(std_SIMD_Int16x8_extractLane, null, this, 2);
|
||||
var s4 = callFunction(std_SIMD_Int16x8_extractLane, null, this, 3);
|
||||
var s5 = callFunction(std_SIMD_Int16x8_extractLane, null, this, 4);
|
||||
var s6 = callFunction(std_SIMD_Int16x8_extractLane, null, this, 5);
|
||||
var s7 = callFunction(std_SIMD_Int16x8_extractLane, null, this, 6);
|
||||
var s8 = callFunction(std_SIMD_Int16x8_extractLane, null, this, 7);
|
||||
return `${protoString}(${s1}, ${s2}, ${s3}, ${s4}, ${s5}, ${s6}, ${s7}, ${s8})`;
|
||||
}
|
||||
case JS_SIMDTYPEREPR_INT32: {
|
||||
var x = callFunction(std_SIMD_Int32x4_extractLane, null, this, 0);
|
||||
var y = callFunction(std_SIMD_Int32x4_extractLane, null, this, 1);
|
||||
var z = callFunction(std_SIMD_Int32x4_extractLane, null, this, 2);
|
||||
var w = callFunction(std_SIMD_Int32x4_extractLane, null, this, 3);
|
||||
return `${protoString}(${x}, ${y}, ${z}, ${w})`;
|
||||
}
|
||||
case JS_SIMDTYPEREPR_FLOAT32: {
|
||||
var x = callFunction(std_SIMD_Float32x4_extractLane, null, this, 0);
|
||||
var y = callFunction(std_SIMD_Float32x4_extractLane, null, this, 1);
|
||||
var z = callFunction(std_SIMD_Float32x4_extractLane, null, this, 2);
|
||||
var w = callFunction(std_SIMD_Float32x4_extractLane, null, this, 3);
|
||||
return `${protoString}(${x}, ${y}, ${z}, ${w})`;
|
||||
}
|
||||
case JS_SIMDTYPEREPR_FLOAT64: {
|
||||
var x = callFunction(std_SIMD_Float64x2_extractLane, null, this, 0);
|
||||
var y = callFunction(std_SIMD_Float64x2_extractLane, null, this, 1);
|
||||
return `${protoString}(${x}, ${y})`;
|
||||
}
|
||||
}
|
||||
assert(false, "unexpected SIMD kind");
|
||||
return '?';
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -105,8 +105,10 @@
|
||||
// prefer SimdTypeRepresentation::TYPE_INT32 etc, since that allows
|
||||
// you to write a switch which will receive a warning if you omit a
|
||||
// case.
|
||||
#define JS_SIMDTYPEREPR_INT32 0
|
||||
#define JS_SIMDTYPEREPR_FLOAT32 1
|
||||
#define JS_SIMDTYPEREPR_FLOAT64 2
|
||||
#define JS_SIMDTYPEREPR_INT8 0
|
||||
#define JS_SIMDTYPEREPR_INT16 1
|
||||
#define JS_SIMDTYPEREPR_INT32 2
|
||||
#define JS_SIMDTYPEREPR_FLOAT32 3
|
||||
#define JS_SIMDTYPEREPR_FLOAT64 4
|
||||
|
||||
#endif
|
||||
|
||||
@@ -88,8 +88,8 @@ function ToNumber(v) {
|
||||
}
|
||||
|
||||
|
||||
/* Spec: ECMAScript Language Specification, 5.1 edition, 9.10 */
|
||||
function CheckObjectCoercible(v) {
|
||||
// ES6 7.2.1 (previously, ES5 9.10 under the name "CheckObjectCoercible").
|
||||
function RequireObjectCoercible(v) {
|
||||
if (v === undefined || v === null)
|
||||
ThrowTypeError(JSMSG_CANT_CONVERT_TO, ToString(v), "object");
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ function indirectCallCannotGC(fullCaller, fullVariable)
|
||||
if (name == "op" && /GetWeakmapKeyDelegate/.test(caller))
|
||||
return true;
|
||||
|
||||
var CheckCallArgs = "AsmJSValidate.cpp:uint8 CheckCallArgs(FunctionCompiler*, js::frontend::ParseNode*, (uint8)(FunctionCompiler*,js::frontend::ParseNode*,Type)*, FunctionCompiler::Call*)";
|
||||
var CheckCallArgs = "AsmJSValidate.cpp:uint8 CheckCallArgs(FunctionBuilder*, js::frontend::ParseNode*, (uint8)(FunctionBuilder*,js::frontend::ParseNode*,Type)*, Signature*)";
|
||||
if (name == "checkArg" && caller == CheckCallArgs)
|
||||
return true;
|
||||
|
||||
|
||||
@@ -241,42 +241,193 @@ Function Properties of the `Debugger.Memory.prototype` Object
|
||||
When `trackingAllocationSites` is `false`, `drainAllocationsLog()` throws an
|
||||
`Error`.
|
||||
|
||||
<code id='take-census'>takeCensus()</code>
|
||||
<code id='take-census'>takeCensus(<i>options</i>)</code>
|
||||
: Carry out a census of the debuggee compartments' contents. A *census* is a
|
||||
complete traversal of the graph of all reachable memory items belonging to a
|
||||
particular `Debugger`'s debuggees. The census produces a count of those
|
||||
items, broken down by various criteria.
|
||||
|
||||
The `takeCensus` method returns an object of the form:
|
||||
The <i>options</i> argument is an object whose properties specify how the
|
||||
census should be carried out.
|
||||
|
||||
If <i>options</i> has a `breakdown` property, that determines how the census
|
||||
categorizes the items it finds, and what data it collects about them. For
|
||||
example, if `dbg` is a `Debugger` instance, the following performs a simple
|
||||
count of debuggee items:
|
||||
|
||||
dbg.memory.takeCensus({ breakdown: { by: 'count' } })
|
||||
|
||||
That might produce a result like:
|
||||
|
||||
{ "count": 1616, "bytes": 93240 }
|
||||
|
||||
Here is a breakdown that groups JavaScript objects by their class name, and
|
||||
non-string, non-script items by their C++ type name:
|
||||
|
||||
{
|
||||
by: "coarseType",
|
||||
objects: { by: "objectClass" },
|
||||
other: { by: "internalType" }
|
||||
}
|
||||
|
||||
which produces a result like this:
|
||||
|
||||
{
|
||||
"objects": {
|
||||
"Function": { "count": 404, "bytes": 37328 },
|
||||
"Object": { "count": 11, "bytes": 1264 },
|
||||
"Debugger": { "count": 1, "bytes": 416 },
|
||||
"ScriptSource": { "count": 1, "bytes": 64 },
|
||||
// ... omitted for brevity...
|
||||
},
|
||||
"scripts": { "count": 1, "bytes": 0 },
|
||||
"strings": { "count": 701, "bytes": 49080 },
|
||||
"other": {
|
||||
"js::Shape": { "count": 450, "bytes": 0 },
|
||||
"js::BaseShape": { "count": 21, "bytes": 0 },
|
||||
"js::ObjectGroup": { "count": 17, "bytes": 0 }
|
||||
}
|
||||
}
|
||||
|
||||
In general, a `breakdown` value has one of the following forms:
|
||||
|
||||
<code>{ by: "count", count:<i>count<i>, bytes:<i>bytes</i> }</code>
|
||||
: The trivial categorization: none whatsoever. Simply tally up the items
|
||||
visited. If <i>count</i> is true, count the number of items visited; if
|
||||
<i>bytes</i> is true, total the number of bytes the items use directly.
|
||||
Both <i>count</i> and <i>bytes</i> are optional; if omitted, they
|
||||
default to `true`. In the result of the census, this breakdown produces
|
||||
a value of the form:
|
||||
|
||||
{ "count":<i>n</b>, "bytes":<i>b</i> }
|
||||
|
||||
where the `count` and `bytes` properties are present as directed by the
|
||||
<i>count</i> and <i>bytes</i> properties on the breakdown.
|
||||
|
||||
Note that the census can produce byte sizes only for the most common
|
||||
types. When the census cannot find the byte size for a given type, it
|
||||
returns zero.
|
||||
|
||||
<code>{ by: "allocationStack", then:<i>breakdown</i>, noStack:<i>noStackBreakdown</i> }</code>
|
||||
: Group items by the full JavaScript stack trace at which they were
|
||||
allocated.
|
||||
|
||||
Further categorize all the items allocated at each distinct stack using
|
||||
<i>breakdown</i>.
|
||||
|
||||
In the result of the census, this breakdown produces a JavaScript `Map`
|
||||
value whose keys are `SavedFrame` values, and whose values are whatever
|
||||
sort of result <i>breakdown</i> produces. Objects allocated on an empty
|
||||
JavaScript stack appear under the key `null`.
|
||||
|
||||
SpiderMonkey only tracks allocation sites for items if requested via the
|
||||
[`trackingAllocationSites`][tracking-allocs] flag; even then, it does
|
||||
not record allocation sites for every kind of item that appears in the
|
||||
heap. Items that lack allocation site information are counted using
|
||||
<i>noStackBreakdown</i>. These appear in the result `Map` under the key
|
||||
string `"noStack"`.
|
||||
|
||||
<code>{ by: "objectClass", then:<i>breakdown</i>, other:<i>otherBreakdown</i> }</code>
|
||||
: Group JavaScript objects by their ECMAScript `[[Class]]` internal property values.
|
||||
|
||||
Further categorize JavaScript objects in each class using
|
||||
<i>breakdown</i>. Further categorize items that are not JavaScript
|
||||
objects using <i>otherBreakdown</i>.
|
||||
|
||||
In the result of the census, this breakdown produces a JavaScript object
|
||||
with no prototype whose own property names are strings naming classes,
|
||||
and whose values are whatever sort of result <i>breakdown</i> produces.
|
||||
The results for non-object items appear as the value of the property
|
||||
named `"other"`.
|
||||
|
||||
<code>{ by: "coarseType", objects:<i>objects</i>, scripts:<i>scripts</i>, strings:<i>strings</i>, other:<i>other</i> }</code>
|
||||
: Group items by their coarse type.
|
||||
|
||||
Use the breakdown value <i>objects</i> for items that are JavaScript
|
||||
objects.
|
||||
|
||||
Use the breakdown value <i>scripts</i> for items that are
|
||||
representations of JavaScript code. This includes bytecode, compiled
|
||||
machine code, and saved source code.
|
||||
|
||||
Use the breakdown value <i>strings</i> for JavaScript strings.
|
||||
|
||||
Use the breakdown value <i>other</i> for items that don't fit into any of
|
||||
the above categories.
|
||||
|
||||
In the result of the census, this breakdown produces a JavaScript object
|
||||
of the form:
|
||||
|
||||
<pre class='language-js'><code>
|
||||
{
|
||||
"objects": <i>result</i>,
|
||||
"scripts": <i>result</i>,
|
||||
"strings": <i>result</i>,
|
||||
"other": <i>result</i>
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
where each <i>result</i> is a value of whatever sort the corresponding
|
||||
breakdown value produces. All breakdown values are optional, and default
|
||||
to `{ type: "count" }`.
|
||||
|
||||
<code>{ by: "internalType", then:<i>breakdown</i> }</code>
|
||||
: Group items by the names given their types internally by SpiderMonkey.
|
||||
These names are not meaningful to web developers, but this type of
|
||||
breakdown does serve as a catch-all that can be useful to Firefox tool
|
||||
developers.
|
||||
|
||||
For example, a census of a pristine debuggee global broken down by
|
||||
internal type name typically looks like this:
|
||||
|
||||
{
|
||||
"JSString": { "count": 701, "bytes": 49080 },
|
||||
"js::Shape": { "count": 450, "bytes": 0 },
|
||||
"JSObject": { "count": 426, "bytes": 44160 },
|
||||
"js::BaseShape": { "count": 21, "bytes": 0 },
|
||||
"js::ObjectGroup": { "count": 17, "bytes": 0 },
|
||||
"JSScript": { "count": 1, "bytes": 0 }
|
||||
}
|
||||
|
||||
In the result of the census, this breakdown produces a JavaScript object
|
||||
with no prototype whose own property names are strings naming types,
|
||||
and whose values are whatever sort of result <i>breakdown</i> produces.
|
||||
|
||||
<code>[ <i>breakdown</i>, ... ]</code>
|
||||
: Group each item using all the given breakdown values. In the result of
|
||||
the census, this breakdown produces an array of values of the sort
|
||||
produced by each listed breakdown.
|
||||
|
||||
To simplify breakdown values, all `then` and `other` properties are optional.
|
||||
If omitted, they are treated as if they were `{ type: "count" }`.
|
||||
|
||||
If the `options` argument has no `breakdown` property, `takeCensus` defaults
|
||||
to the following:
|
||||
|
||||
<pre class='language-js'><code>
|
||||
{
|
||||
"objects": { <i>class</i>: <i>tally</i>, ... },
|
||||
"scripts": <i>tally</i>,
|
||||
"strings": <i>tally</i>,
|
||||
"other": { <i>type name</i>: <i>tally</i>, ... }
|
||||
by: "coarseType",
|
||||
objects: { by: "objectClass" },
|
||||
other: { by: "internalType" }
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
Each <i>tally</i> has the form:
|
||||
which produces results of the form:
|
||||
|
||||
<pre class='language-js'><code>
|
||||
{ "count": <i>count</i> }
|
||||
{
|
||||
objects: { <i>class</i>: <i>count</i>, ... },
|
||||
scripts: <i>count</i>,
|
||||
strings: <i>count</i>,
|
||||
other: { <i>type name</i>: <i>count</i>, ... }
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
where <i>count</i> is the number of items in the category.
|
||||
where each <i>count</i> has the form:
|
||||
|
||||
The `"objects"` property's value contains the tallies of JavaScript objects,
|
||||
broken down by their ECMAScript `[[Class]]` internal property values. Each
|
||||
<i>class</i> is a string.
|
||||
|
||||
The `"scripts"` property's value tallies the in-memory representation of
|
||||
JavaScript code.
|
||||
|
||||
The `"strings"` property's value tallies the debuggee's strings.
|
||||
|
||||
The `"other"` property's value contains the tallies of other items used
|
||||
internally by SpiderMonkey, broken down by their C++ type name.
|
||||
<pre class='language-js'><code>
|
||||
{ "count": <i>count</i>, bytes:<i>bytes</i> }
|
||||
</code></pre>
|
||||
|
||||
Because performing a census requires traversing the entire graph of objects
|
||||
in debuggee compartments, it is an expensive operation. On developer
|
||||
@@ -336,7 +487,7 @@ simpler ones when it pleases. Such conversions usually increase memory
|
||||
consumption.
|
||||
|
||||
SpiderMonkey shares some strings amongst all web pages and browser JS. These
|
||||
shared strings, called *atoms*, are not included in censuses' string tallies.
|
||||
shared strings, called *atoms*, are not included in censuses' string counts.
|
||||
|
||||
|
||||
### Scripts
|
||||
|
||||
@@ -3721,11 +3721,14 @@ BytecodeEmitter::emitDestructuringOpsObjectHelper(ParseNode* pattern, VarEmitOpt
|
||||
MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(pattern->isArity(PN_LIST));
|
||||
|
||||
MOZ_ASSERT(this->stackDepth != 0); // ... OBJ
|
||||
MOZ_ASSERT(this->stackDepth > 0); // ... RHS
|
||||
|
||||
if (!emitRequireObjectCoercible()) // ... RHS
|
||||
return false;
|
||||
|
||||
for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
|
||||
// Duplicate the value being destructured to use as a reference base.
|
||||
if (!emit1(JSOP_DUP)) // ... OBJ OBJ
|
||||
if (!emit1(JSOP_DUP)) // ... RHS RHS
|
||||
return false;
|
||||
|
||||
// Now push the property name currently being matched, which is the
|
||||
@@ -3735,7 +3738,7 @@ BytecodeEmitter::emitDestructuringOpsObjectHelper(ParseNode* pattern, VarEmitOpt
|
||||
|
||||
ParseNode* subpattern;
|
||||
if (member->isKind(PNK_MUTATEPROTO)) {
|
||||
if (!emitAtomOp(cx->names().proto, JSOP_GETPROP)) // ... OBJ PROP
|
||||
if (!emitAtomOp(cx->names().proto, JSOP_GETPROP)) // ... RHS PROP
|
||||
return false;
|
||||
needsGetElem = false;
|
||||
subpattern = member->pn_kid;
|
||||
@@ -3744,7 +3747,7 @@ BytecodeEmitter::emitDestructuringOpsObjectHelper(ParseNode* pattern, VarEmitOpt
|
||||
|
||||
ParseNode* key = member->pn_left;
|
||||
if (key->isKind(PNK_NUMBER)) {
|
||||
if (!emitNumberOp(key->pn_dval)) // ... OBJ OBJ KEY
|
||||
if (!emitNumberOp(key->pn_dval)) // ... RHS RHS KEY
|
||||
return false;
|
||||
} else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
|
||||
PropertyName* name = key->pn_atom->asPropertyName();
|
||||
@@ -3754,16 +3757,16 @@ BytecodeEmitter::emitDestructuringOpsObjectHelper(ParseNode* pattern, VarEmitOpt
|
||||
// as indexes for simplification of downstream analysis.
|
||||
jsid id = NameToId(name);
|
||||
if (id != IdToTypeId(id)) {
|
||||
if (!emitTree(key)) // ... OBJ OBJ KEY
|
||||
if (!emitTree(key)) // ... RHS RHS KEY
|
||||
return false;
|
||||
} else {
|
||||
if (!emitAtomOp(name, JSOP_GETPROP)) // ...OBJ PROP
|
||||
if (!emitAtomOp(name, JSOP_GETPROP)) // ...RHS PROP
|
||||
return false;
|
||||
needsGetElem = false;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(key->isKind(PNK_COMPUTED_NAME));
|
||||
if (!emitTree(key->pn_kid)) // ... OBJ OBJ KEY
|
||||
if (!emitTree(key->pn_kid)) // ... RHS RHS KEY
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3771,7 +3774,7 @@ BytecodeEmitter::emitDestructuringOpsObjectHelper(ParseNode* pattern, VarEmitOpt
|
||||
}
|
||||
|
||||
// Get the property value if not done already.
|
||||
if (needsGetElem && !emitElemOpBase(JSOP_GETELEM)) // ... OBJ PROP
|
||||
if (needsGetElem && !emitElemOpBase(JSOP_GETELEM)) // ... RHS PROP
|
||||
return false;
|
||||
|
||||
if (subpattern->isKind(PNK_ASSIGN)) {
|
||||
@@ -3789,7 +3792,7 @@ BytecodeEmitter::emitDestructuringOpsObjectHelper(ParseNode* pattern, VarEmitOpt
|
||||
// target in the subpattern's LHS as it went, then popped PROP. We've
|
||||
// correctly returned to the loop-entry stack, and we continue to the
|
||||
// next member.
|
||||
if (emitOption == InitializeVars) // ... OBJ
|
||||
if (emitOption == InitializeVars) // ... RHS
|
||||
continue;
|
||||
|
||||
MOZ_ASSERT(emitOption == PushInitialValues);
|
||||
@@ -4921,6 +4924,42 @@ BytecodeEmitter::emitWith(ParseNode* pn)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitRequireObjectCoercible()
|
||||
{
|
||||
// For simplicity, handle this in self-hosted code, at cost of 13 bytes of
|
||||
// bytecode versus 1 byte for a dedicated opcode. As more places need this
|
||||
// behavior, we may want to reconsider this tradeoff.
|
||||
|
||||
#ifdef DEBUG
|
||||
auto depth = this->stackDepth;
|
||||
#endif
|
||||
MOZ_ASSERT(depth > 0); // VAL
|
||||
if (!emit1(JSOP_DUP)) // VAL VAL
|
||||
return false;
|
||||
|
||||
// Note that "intrinsic" is a misnomer: we're calling a *self-hosted*
|
||||
// function that's not an intrinsic! But it nonetheless works as desired.
|
||||
if (!emitAtomOp(cx->names().RequireObjectCoercible,
|
||||
JSOP_GETINTRINSIC)) // VAL VAL REQUIREOBJECTCOERCIBLE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!emit1(JSOP_UNDEFINED)) // VAL VAL REQUIREOBJECTCOERCIBLE UNDEFINED
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, jsbytecode(2))) // VAL REQUIREOBJECTCOERCIBLE UNDEFINED VAL
|
||||
return false;
|
||||
if (!emitCall(JSOP_CALL, 1)) // VAL IGNORED
|
||||
return false;
|
||||
checkTypeSet(JSOP_CALL);
|
||||
|
||||
if (!emit1(JSOP_POP)) // VAL
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(depth == this->stackDepth);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitIterator()
|
||||
{
|
||||
|
||||
@@ -522,6 +522,10 @@ struct BytecodeEmitter
|
||||
// the stack.
|
||||
bool emitInitializeDestructuringDecls(JSOp prologueOp, ParseNode* pattern);
|
||||
|
||||
// Throw a TypeError if the value atop the stack isn't convertible to an
|
||||
// object, with no overall effect on the stack.
|
||||
bool emitRequireObjectCoercible();
|
||||
|
||||
// emitIterator expects the iterable to already be on the stack.
|
||||
// It will replace that stack value with the corresponding iterator
|
||||
bool emitIterator();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
if (typeof SIMD === "undefined")
|
||||
quit();
|
||||
|
||||
var float32x4 = SIMD.float32x4;
|
||||
var f = float32x4(11, 22, 33, 44);
|
||||
var Float32x4 = SIMD.Float32x4;
|
||||
var f = Float32x4(11, 22, 33, 44);
|
||||
assertEq(f.toSource(), "float32x4(11, 22, 33, 44)");
|
||||
|
||||
var int32x4 = SIMD.int32x4;
|
||||
var f = int32x4(11, 22, 33, 44);
|
||||
var Int32x4 = SIMD.Int32x4;
|
||||
var f = Int32x4(11, 22, 33, 44);
|
||||
assertEq(f.toSource(), "int32x4(11, 22, 33, 44)");
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
load(libdir + 'simd.js');
|
||||
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
var i1 = SIMD.Int32x4(1, 2, 3, 4);
|
||||
var i2 = SIMD.Int32x4(4, 3, 2, 1);
|
||||
|
||||
var f1 = SIMD.Float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.Float32x4(4, 3, 2, 1);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.Float32x4.add(f1, f2), binaryX4((x, y) => x + y, f1, f2));
|
||||
assertEqX4(SIMD.Float32x4.sub(f1, f2), binaryX4((x, y) => x - y, f1, f2));
|
||||
assertEqX4(SIMD.Float32x4.mul(f1, f2), binaryX4((x, y) => x * y, f1, f2));
|
||||
|
||||
assertEqX4(SIMD.Int32x4.add(i1, i2), binaryX4((x, y) => x + y, i1, i2));
|
||||
assertEqX4(SIMD.Int32x4.sub(i1, i2), binaryX4((x, y) => x - y, i1, i2));
|
||||
assertEqX4(SIMD.Int32x4.mul(i1, i2), binaryX4((x, y) => x * y, i1, i2));
|
||||
}
|
||||
}
|
||||
|
||||
f();
|
||||
@@ -6,9 +6,9 @@ const T = -1, F = 0;
|
||||
|
||||
function f() {
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.int32x4.bool(i + 1, true, 'hey', null), [T, T, T, F]);
|
||||
assertEqX4(SIMD.int32x4.bool(undefined, '', {}, objectEmulatingUndefined()), [F, F, T, F]);
|
||||
assertEqX4(SIMD.int32x4.bool(null, NaN, false, Infinity), [F, F, F, T]);
|
||||
assertEqX4(SIMD.Int32x4.bool(i + 1, true, 'hey', null), [T, T, T, F]);
|
||||
assertEqX4(SIMD.Int32x4.bool(undefined, '', {}, objectEmulatingUndefined()), [F, F, T, F]);
|
||||
assertEqX4(SIMD.Int32x4.bool(null, NaN, false, Infinity), [F, F, F, T]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
if (typeof TypedObject === "undefined" || typeof SIMD === 'undefined')
|
||||
quit();
|
||||
|
||||
var Int32x4 = SIMD.Int32x4;
|
||||
var a = Int32x4((4294967295), 200, 300, 400);
|
||||
addCase( new Array(Math.pow(2,12)) );
|
||||
for ( var arg = "", i = 0; i < Math.pow(2,12); i++ ) {}
|
||||
addCase( a );
|
||||
function addCase(object) {
|
||||
object.length
|
||||
}
|
||||
@@ -7,20 +7,20 @@ setJitCompilerOption("ion.warmup.trigger", 30);
|
||||
function test_1(i) {
|
||||
if (i >= 40)
|
||||
return;
|
||||
var a = SIMD.float32x4(1.1, 2.2, 3.3, 4.6);
|
||||
SIMD.int32x4.fromFloat32x4(a);
|
||||
var a = SIMD.Float32x4(1.1, 2.2, 3.3, 4.6);
|
||||
SIMD.Int32x4.fromFloat32x4(a);
|
||||
test_1(i + 1);
|
||||
}
|
||||
test_1(0);
|
||||
|
||||
|
||||
var float32x4 = SIMD.float32x4;
|
||||
var Float32x4 = SIMD.Float32x4;
|
||||
function test_2() {
|
||||
var Array = float32x4.array(3);
|
||||
var Array = Float32x4.array(3);
|
||||
var array = new Array([
|
||||
float32x4(1, 2, 3, 4),
|
||||
float32x4(5, 6, 7, 8),
|
||||
float32x4(9, 10, 11, 12)
|
||||
Float32x4(1, 2, 3, 4),
|
||||
Float32x4(5, 6, 7, 8),
|
||||
Float32x4(9, 10, 11, 12)
|
||||
]);
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
if (!this.hasOwnProperty("SIMD"))
|
||||
quit();
|
||||
|
||||
var float64x2 = SIMD.float64x2;
|
||||
var Float64x2 = SIMD.Float64x2;
|
||||
function test() {
|
||||
var a = float64x2(1, 2);
|
||||
var a = Float64x2(1, 2);
|
||||
}
|
||||
test();
|
||||
test();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
if (!this.hasOwnProperty("SIMD"))
|
||||
quit();
|
||||
|
||||
var int32x4 = SIMD.int32x4;
|
||||
var Int32x4 = SIMD.Int32x4;
|
||||
function test() {
|
||||
var a = int32x4();
|
||||
var b = int32x4(10, 20, 30, 40);
|
||||
var c = SIMD.int32x4.and(a, b);
|
||||
var a = Int32x4();
|
||||
var b = Int32x4(10, 20, 30, 40);
|
||||
var c = SIMD.Int32x4.and(a, b);
|
||||
assertEq(c.x, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
if (!this.hasOwnProperty("TypedObject") || !this.hasOwnProperty("SIMD"))
|
||||
quit();
|
||||
|
||||
var Float32x4 = SIMD.Float32x4;
|
||||
Float32x4.array(1);
|
||||
@@ -3,17 +3,15 @@ load(libdir + 'simd.js');
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
var f1 = SIMD.float32x4(1, 2, 3, 4);
|
||||
|
||||
var i1 = SIMD.int32x4(1, 2, -3, 4);
|
||||
|
||||
var f1 = SIMD.Float32x4(1, 2, 3, 4);
|
||||
var i1 = SIMD.Int32x4(1, 2, -3, 4);
|
||||
var i = 0;
|
||||
try {
|
||||
for (; i < 150; i++) {
|
||||
if (i > 148)
|
||||
i1 = f1;
|
||||
assertEqVec(SIMD.int32x4.check(i1), i1);
|
||||
assertEqVec(SIMD.float32x4.check(f1), f1);
|
||||
assertEqVec(SIMD.Int32x4.check(i1), i1);
|
||||
assertEqVec(SIMD.Float32x4.check(f1), f1);
|
||||
}
|
||||
} catch (ex) {
|
||||
assertEq(i, 149);
|
||||
|
||||
@@ -7,26 +7,26 @@ function bool(x) {
|
||||
}
|
||||
|
||||
function f() {
|
||||
var f1 = SIMD.float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.float32x4(NaN, Infinity, 3.14, -0);
|
||||
var f1 = SIMD.Float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.Float32x4(NaN, Infinity, 3.14, -0);
|
||||
|
||||
var i1 = SIMD.int32x4(1, 2, -3, 4);
|
||||
var i2 = SIMD.int32x4(1, -2, 3, 0);
|
||||
var i1 = SIMD.Int32x4(1, 2, -3, 4);
|
||||
var i2 = SIMD.Int32x4(1, -2, 3, 0);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.int32x4.lessThan(i1, i2), [0, 0, 1, 0].map(bool));
|
||||
assertEqX4(SIMD.int32x4.lessThanOrEqual(i1, i2), [1, 0, 1, 0].map(bool));
|
||||
assertEqX4(SIMD.int32x4.equal(i1, i2), [1, 0, 0, 0].map(bool));
|
||||
assertEqX4(SIMD.int32x4.notEqual(i1, i2), [0, 1, 1, 1].map(bool));
|
||||
assertEqX4(SIMD.int32x4.greaterThan(i1, i2), [0, 1, 0, 1].map(bool));
|
||||
assertEqX4(SIMD.int32x4.greaterThanOrEqual(i1, i2), [1, 1, 0, 1].map(bool));
|
||||
assertEqX4(SIMD.Int32x4.lessThan(i1, i2), [0, 0, 1, 0].map(bool));
|
||||
assertEqX4(SIMD.Int32x4.lessThanOrEqual(i1, i2), [1, 0, 1, 0].map(bool));
|
||||
assertEqX4(SIMD.Int32x4.equal(i1, i2), [1, 0, 0, 0].map(bool));
|
||||
assertEqX4(SIMD.Int32x4.notEqual(i1, i2), [0, 1, 1, 1].map(bool));
|
||||
assertEqX4(SIMD.Int32x4.greaterThan(i1, i2), [0, 1, 0, 1].map(bool));
|
||||
assertEqX4(SIMD.Int32x4.greaterThanOrEqual(i1, i2), [1, 1, 0, 1].map(bool));
|
||||
|
||||
assertEqX4(SIMD.float32x4.lessThan(f1, f2), [0, 1, 1, 0].map(bool));
|
||||
assertEqX4(SIMD.float32x4.lessThanOrEqual(f1, f2), [0, 1, 1, 0].map(bool));
|
||||
assertEqX4(SIMD.float32x4.equal(f1, f2), [0, 0, 0, 0].map(bool));
|
||||
assertEqX4(SIMD.float32x4.notEqual(f1, f2), [1, 1, 1, 1].map(bool));
|
||||
assertEqX4(SIMD.float32x4.greaterThan(f1, f2), [0, 0, 0, 1].map(bool));
|
||||
assertEqX4(SIMD.float32x4.greaterThanOrEqual(f1, f2), [0, 0, 0, 1].map(bool));
|
||||
assertEqX4(SIMD.Float32x4.lessThan(f1, f2), [0, 1, 1, 0].map(bool));
|
||||
assertEqX4(SIMD.Float32x4.lessThanOrEqual(f1, f2), [0, 1, 1, 0].map(bool));
|
||||
assertEqX4(SIMD.Float32x4.equal(f1, f2), [0, 0, 0, 0].map(bool));
|
||||
assertEqX4(SIMD.Float32x4.notEqual(f1, f2), [1, 1, 1, 1].map(bool));
|
||||
assertEqX4(SIMD.Float32x4.greaterThan(f1, f2), [0, 0, 0, 1].map(bool));
|
||||
assertEqX4(SIMD.Float32x4.greaterThanOrEqual(f1, f2), [0, 0, 0, 1].map(bool));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
load(libdir + 'simd.js');
|
||||
|
||||
if (typeof SIMD === "undefined")
|
||||
quit();
|
||||
|
||||
setJitCompilerOption("baseline.warmup.trigger", 10);
|
||||
setJitCompilerOption("ion.warmup.trigger", 90);
|
||||
var max = 100; // Make have the warm-up counter high enough to
|
||||
// consider inlining functions.
|
||||
|
||||
var f4 = SIMD.Int32x4; // :TODO: Support Float32x4 arith.
|
||||
var f4add = f4.add;
|
||||
var f4sub = f4.sub;
|
||||
var f4mul = f4.mul;
|
||||
|
||||
function c4mul(z1, z2) {
|
||||
var { re: re1, im: im1 } = z1;
|
||||
var { re: re2, im: im2 } = z2;
|
||||
var rere = f4mul(re1, re2);
|
||||
var reim = f4mul(re1, im2);
|
||||
var imre = f4mul(im1, re2);
|
||||
var imim = f4mul(im1, im2);
|
||||
return { re: f4sub(rere, imim), im: f4add(reim, imre) };
|
||||
}
|
||||
|
||||
function c4inv(z) {
|
||||
var { re: re, im: im } = z;
|
||||
var minus = f4(-1, -1, -1, -1);
|
||||
return { re: re, im: f4mul(im, minus) };
|
||||
}
|
||||
|
||||
function c4inv_inplace(z) {
|
||||
var res = c4inv(z);
|
||||
z.re = res.re;
|
||||
z.im = res.im;
|
||||
}
|
||||
|
||||
function c4norm(z) {
|
||||
var { re: re, im: im } = c4mul(z, c4inv(z));
|
||||
return re;
|
||||
}
|
||||
|
||||
function c4scale(z, s) {
|
||||
var { re: re, im: im } = z;
|
||||
var f4s = f4(s, s, s, s);
|
||||
return { re: f4mul(re, f4s), im: f4mul(im, f4s) };
|
||||
}
|
||||
|
||||
var rotate90 = { re: f4(0, 0, 0, 0), im: f4(1, 1, 1, 1) };
|
||||
var cardinals = { re: f4(1, 0, -1, 0), im: f4(0, 1, 0, -1) };
|
||||
|
||||
function test(dots) {
|
||||
for (var j = 0; j < 4; j++) {
|
||||
dots = c4mul(rotate90, dots);
|
||||
if (j % 2 == 0) // Magic !
|
||||
c4inv_inplace(dots);
|
||||
dots = c4scale(dots, 2);
|
||||
}
|
||||
return dots;
|
||||
}
|
||||
|
||||
assertEqX4(c4norm(cardinals), simdToArray(f4.splat(1)));
|
||||
var cardinals16 = c4scale(cardinals, 16);
|
||||
|
||||
for (var i = 0; i < max; i++) {
|
||||
var res = test(cardinals);
|
||||
assertEqX4(c4norm(res), simdToArray(f4.splat(16 * 16)));
|
||||
assertEqX4(res.re, simdToArray(cardinals16.re));
|
||||
assertEqX4(res.im, simdToArray(cardinals16.im));
|
||||
}
|
||||
@@ -20,27 +20,26 @@ var cast = (function() {
|
||||
|
||||
function f() {
|
||||
// No bailout here.
|
||||
var f4 = SIMD.float32x4(1, 2, 3, 4);
|
||||
var i4 = SIMD.int32x4(1, 2, 3, 4);
|
||||
var f4 = SIMD.Float32x4(1, 2, 3, 4);
|
||||
var i4 = SIMD.Int32x4(1, 2, 3, 4);
|
||||
var BitOrZero = (x) => x | 0;
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.float32x4.fromInt32x4(i4), unaryX4(BitOrZero, f4, Math.fround));
|
||||
assertEqX4(SIMD.float32x4.fromInt32x4Bits(i4), unaryX4(cast.fromInt32Bits, f4, Math.fround));
|
||||
assertEqX4(SIMD.int32x4.fromFloat32x4(f4), unaryX4(Math.fround, i4, BitOrZero));
|
||||
assertEqX4(SIMD.int32x4.fromFloat32x4Bits(f4), unaryX4(cast.fromFloat32Bits, i4, BitOrZero));
|
||||
assertEqX4(SIMD.Float32x4.fromInt32x4(i4), unaryX4(BitOrZero, f4, Math.fround));
|
||||
assertEqX4(SIMD.Float32x4.fromInt32x4Bits(i4), unaryX4(cast.fromInt32Bits, f4, Math.fround));
|
||||
assertEqX4(SIMD.Int32x4.fromFloat32x4(f4), unaryX4(Math.fround, i4, BitOrZero));
|
||||
assertEqX4(SIMD.Int32x4.fromFloat32x4Bits(f4), unaryX4(cast.fromFloat32Bits, i4, BitOrZero));
|
||||
}
|
||||
}
|
||||
|
||||
function uglyDuckling(val) {
|
||||
// We bail out when i == 149 because the conversion will return
|
||||
// 0x80000000 and the input actually wasn't in bounds.
|
||||
print('entering uglyDuckling');
|
||||
val = Math.fround(val);
|
||||
for (var i = 0; i < 150; i++) {
|
||||
var caught = false;
|
||||
try {
|
||||
var v = SIMD.float32x4(i < 149 ? 0 : val, 0, 0, 0)
|
||||
SIMD.int32x4.fromFloat32x4(v);
|
||||
var v = SIMD.Float32x4(i < 149 ? 0 : val, 0, 0, 0)
|
||||
SIMD.Int32x4.fromFloat32x4(v);
|
||||
} catch(e) {
|
||||
assertEq(e instanceof RangeError, true);
|
||||
assertEq(i, 149);
|
||||
@@ -51,12 +50,11 @@ function uglyDuckling(val) {
|
||||
}
|
||||
|
||||
function dontBail() {
|
||||
print('entering dontbail');
|
||||
// On x86, the conversion will return 0x80000000, which will imply that we
|
||||
// check the input values. However, we shouldn't bail out in this case.
|
||||
for (var i = 0; i < 150; i++) {
|
||||
var v = SIMD.float32x4(i < 149 ? 0 : -Math.pow(2, 31), 0, 0, 0)
|
||||
SIMD.int32x4.fromFloat32x4(v);
|
||||
var v = SIMD.Float32x4(i < 149 ? 0 : -Math.pow(2, 31), 0, 0, 0)
|
||||
SIMD.Int32x4.fromFloat32x4(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,14 +19,14 @@ function minNum(x, y) {
|
||||
}
|
||||
|
||||
function f() {
|
||||
var f1 = SIMD.float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.float32x4(4, 3, 2, 1);
|
||||
var f1 = SIMD.Float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.Float32x4(4, 3, 2, 1);
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.float32x4.div(f1, f2), binaryX4((x, y) => x / y, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.min(f1, f2), binaryX4(Math.min, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.max(f1, f2), binaryX4(Math.max, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.minNum(f1, f2), binaryX4(minNum, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.maxNum(f1, f2), binaryX4(maxNum, f1, f2));
|
||||
assertEqX4(SIMD.Float32x4.div(f1, f2), binaryX4((x, y) => x / y, f1, f2));
|
||||
assertEqX4(SIMD.Float32x4.min(f1, f2), binaryX4(Math.min, f1, f2));
|
||||
assertEqX4(SIMD.Float32x4.max(f1, f2), binaryX4(Math.max, f1, f2));
|
||||
assertEqX4(SIMD.Float32x4.minNum(f1, f2), binaryX4(minNum, f1, f2));
|
||||
assertEqX4(SIMD.Float32x4.maxNum(f1, f2), binaryX4(maxNum, f1, f2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +28,12 @@ var helpers = (function() {
|
||||
})();
|
||||
|
||||
function f() {
|
||||
var f1 = SIMD.float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.float32x4(4, 3, 2, 1);
|
||||
var f1 = SIMD.Float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.Float32x4(4, 3, 2, 1);
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.float32x4.and(f1, f2), binaryX4(helpers.and, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.or(f1, f2), binaryX4(helpers.or, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.xor(f1, f2), binaryX4(helpers.xor, f1, f2));
|
||||
assertEqX4(SIMD.Float32x4.and(f1, f2), binaryX4(helpers.and, f1, f2));
|
||||
assertEqX4(SIMD.Float32x4.or(f1, f2), binaryX4(helpers.or, f1, f2));
|
||||
assertEqX4(SIMD.Float32x4.xor(f1, f2), binaryX4(helpers.xor, f1, f2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ load(libdir + 'simd.js');
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
var i4 = SIMD.int32x4(1, -2, 3, -4);
|
||||
var i4 = SIMD.Int32x4(1, -2, 3, -4);
|
||||
|
||||
var v = Math.fround(13.37);
|
||||
var f4 = SIMD.float32x4(13.37, NaN, Infinity, -0);
|
||||
var f4 = SIMD.Float32x4(13.37, NaN, Infinity, -0);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEq(i4.x, 1);
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
load(libdir + 'simd.js');
|
||||
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function test(i) {
|
||||
assertEqX4(SIMD.Int32x4(), [0, 0, 0, 0]);
|
||||
assertEqX4(SIMD.Int32x4(i), [i, 0, 0, 0]);
|
||||
assertEqX4(SIMD.Int32x4(i, 1), [i, 1, 0, 0]);
|
||||
assertEqX4(SIMD.Int32x4(i, 1, 2), [i, 1, 2, 0]);
|
||||
assertEqX4(SIMD.Int32x4(i, 1, 2, 3), [i, 1, 2, 3]);
|
||||
assertEqX4(SIMD.Int32x4(i, 1, 2, 3, 4), [i, 1, 2, 3]);
|
||||
|
||||
assertEqX4(SIMD.Float32x4(), [NaN, NaN, NaN, NaN]);
|
||||
assertEqX4(SIMD.Float32x4(i), [i, NaN, NaN, NaN]);
|
||||
assertEqX4(SIMD.Float32x4(i, 1), [i, 1, NaN, NaN]);
|
||||
assertEqX4(SIMD.Float32x4(i, 1, 2), [i, 1, 2, NaN]);
|
||||
assertEqX4(SIMD.Float32x4(i, 1, 2, 3), [i, 1, 2, 3 ]);
|
||||
assertEqX4(SIMD.Float32x4(i, 1, 2, 3, 4), [i, 1, 2, 3 ]);
|
||||
}
|
||||
|
||||
for(var i=0; i<300; i++) {
|
||||
test(i);
|
||||
}
|
||||
@@ -16,76 +16,75 @@ function f() {
|
||||
var u8 = new Uint8Array(f32.buffer);
|
||||
|
||||
function testLoad() {
|
||||
assertEqX4(SIMD.float32x4.load(f64, 0), [1,2,3,4]);
|
||||
assertEqX4(SIMD.float32x4.load(f32, 1), [2,3,4,5]);
|
||||
assertEqX4(SIMD.float32x4.load(i32, 2), [3,4,5,6]);
|
||||
assertEqX4(SIMD.float32x4.load(i16, 3 << 1), [4,5,6,7]);
|
||||
assertEqX4(SIMD.float32x4.load(u16, 4 << 1), [5,6,7,8]);
|
||||
assertEqX4(SIMD.float32x4.load(i8 , 5 << 2), [6,7,8,9]);
|
||||
assertEqX4(SIMD.float32x4.load(u8 , 6 << 2), [7,8,9,10]);
|
||||
|
||||
assertEqX4(SIMD.float32x4.load(f64, (16 >> 1) - (4 >> 1)), [13,14,15,16]);
|
||||
assertEqX4(SIMD.float32x4.load(f32, 16 - 4), [13,14,15,16]);
|
||||
assertEqX4(SIMD.float32x4.load(i32, 16 - 4), [13,14,15,16]);
|
||||
assertEqX4(SIMD.float32x4.load(i16, (16 << 1) - (4 << 1)), [13,14,15,16]);
|
||||
assertEqX4(SIMD.float32x4.load(u16, (16 << 1) - (4 << 1)), [13,14,15,16]);
|
||||
assertEqX4(SIMD.float32x4.load(i8, (16 << 2) - (4 << 2)), [13,14,15,16]);
|
||||
assertEqX4(SIMD.float32x4.load(u8, (16 << 2) - (4 << 2)), [13,14,15,16]);
|
||||
|
||||
assertEqX4(SIMD.Float32x4.load(f64, 0), [1,2,3,4]);
|
||||
assertEqX4(SIMD.Float32x4.load(f32, 1), [2,3,4,5]);
|
||||
assertEqX4(SIMD.Float32x4.load(i32, 2), [3,4,5,6]);
|
||||
assertEqX4(SIMD.Float32x4.load(i16, 3 << 1), [4,5,6,7]);
|
||||
assertEqX4(SIMD.Float32x4.load(u16, 4 << 1), [5,6,7,8]);
|
||||
assertEqX4(SIMD.Float32x4.load(i8 , 5 << 2), [6,7,8,9]);
|
||||
assertEqX4(SIMD.Float32x4.load(u8 , 6 << 2), [7,8,9,10]);
|
||||
|
||||
assertEqX4(SIMD.Float32x4.load(f64, (16 >> 1) - (4 >> 1)), [13,14,15,16]);
|
||||
assertEqX4(SIMD.Float32x4.load(f32, 16 - 4), [13,14,15,16]);
|
||||
assertEqX4(SIMD.Float32x4.load(i32, 16 - 4), [13,14,15,16]);
|
||||
assertEqX4(SIMD.Float32x4.load(i16, (16 << 1) - (4 << 1)), [13,14,15,16]);
|
||||
assertEqX4(SIMD.Float32x4.load(u16, (16 << 1) - (4 << 1)), [13,14,15,16]);
|
||||
assertEqX4(SIMD.Float32x4.load(i8, (16 << 2) - (4 << 2)), [13,14,15,16]);
|
||||
assertEqX4(SIMD.Float32x4.load(u8, (16 << 2) - (4 << 2)), [13,14,15,16]);
|
||||
}
|
||||
|
||||
function testLoad1() {
|
||||
assertEqX4(SIMD.float32x4.load1(f64, 0), [1,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(f32, 1), [2,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(i32, 2), [3,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(i16, 3 << 1), [4,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(u16, 4 << 1), [5,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(i8 , 5 << 2), [6,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(u8 , 6 << 2), [7,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(f64, 0), [1,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(f32, 1), [2,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(i32, 2), [3,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(i16, 3 << 1), [4,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(u16, 4 << 1), [5,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(i8 , 5 << 2), [6,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(u8 , 6 << 2), [7,0,0,0]);
|
||||
|
||||
assertEqX4(SIMD.float32x4.load1(f64, (16 >> 1) - (4 >> 1)), [13,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(f32, 16 - 4), [13,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(i32, 16 - 4), [13,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(i16, (16 << 1) - (4 << 1)), [13,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(u16, (16 << 1) - (4 << 1)), [13,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(i8, (16 << 2) - (4 << 2)), [13,0,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load1(u8, (16 << 2) - (4 << 2)), [13,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(f64, (16 >> 1) - (4 >> 1)), [13,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(f32, 16 - 4), [13,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(i32, 16 - 4), [13,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(i16, (16 << 1) - (4 << 1)), [13,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(u16, (16 << 1) - (4 << 1)), [13,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(i8, (16 << 2) - (4 << 2)), [13,0,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load1(u8, (16 << 2) - (4 << 2)), [13,0,0,0]);
|
||||
}
|
||||
|
||||
function testLoad2() {
|
||||
assertEqX4(SIMD.float32x4.load2(f64, 0), [1,2,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(f32, 1), [2,3,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(i32, 2), [3,4,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(i16, 3 << 1), [4,5,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(u16, 4 << 1), [5,6,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(i8 , 5 << 2), [6,7,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(u8 , 6 << 2), [7,8,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(f64, 0), [1,2,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(f32, 1), [2,3,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(i32, 2), [3,4,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(i16, 3 << 1), [4,5,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(u16, 4 << 1), [5,6,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(i8 , 5 << 2), [6,7,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(u8 , 6 << 2), [7,8,0,0]);
|
||||
|
||||
assertEqX4(SIMD.float32x4.load2(f64, (16 >> 1) - (4 >> 1)), [13,14,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(f32, 16 - 4), [13,14,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(i32, 16 - 4), [13,14,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(i16, (16 << 1) - (4 << 1)), [13,14,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(u16, (16 << 1) - (4 << 1)), [13,14,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(i8, (16 << 2) - (4 << 2)), [13,14,0,0]);
|
||||
assertEqX4(SIMD.float32x4.load2(u8, (16 << 2) - (4 << 2)), [13,14,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(f64, (16 >> 1) - (4 >> 1)), [13,14,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(f32, 16 - 4), [13,14,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(i32, 16 - 4), [13,14,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(i16, (16 << 1) - (4 << 1)), [13,14,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(u16, (16 << 1) - (4 << 1)), [13,14,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(i8, (16 << 2) - (4 << 2)), [13,14,0,0]);
|
||||
assertEqX4(SIMD.Float32x4.load2(u8, (16 << 2) - (4 << 2)), [13,14,0,0]);
|
||||
}
|
||||
|
||||
function testLoad3() {
|
||||
assertEqX4(SIMD.float32x4.load3(f64, 0), [1,2,3,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(f32, 1), [2,3,4,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(i32, 2), [3,4,5,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(i16, 3 << 1), [4,5,6,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(u16, 4 << 1), [5,6,7,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(i8 , 5 << 2), [6,7,8,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(u8 , 6 << 2), [7,8,9,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(f64, 0), [1,2,3,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(f32, 1), [2,3,4,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(i32, 2), [3,4,5,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(i16, 3 << 1), [4,5,6,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(u16, 4 << 1), [5,6,7,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(i8 , 5 << 2), [6,7,8,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(u8 , 6 << 2), [7,8,9,0]);
|
||||
|
||||
assertEqX4(SIMD.float32x4.load3(f64, (16 >> 1) - (4 >> 1)), [13,14,15,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(f32, 16 - 4), [13,14,15,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(i32, 16 - 4), [13,14,15,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(i16, (16 << 1) - (4 << 1)), [13,14,15,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(u16, (16 << 1) - (4 << 1)), [13,14,15,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(i8, (16 << 2) - (4 << 2)), [13,14,15,0]);
|
||||
assertEqX4(SIMD.float32x4.load3(u8, (16 << 2) - (4 << 2)), [13,14,15,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(f64, (16 >> 1) - (4 >> 1)), [13,14,15,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(f32, 16 - 4), [13,14,15,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(i32, 16 - 4), [13,14,15,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(i16, (16 << 1) - (4 << 1)), [13,14,15,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(u16, (16 << 1) - (4 << 1)), [13,14,15,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(i8, (16 << 2) - (4 << 2)), [13,14,15,0]);
|
||||
assertEqX4(SIMD.Float32x4.load3(u8, (16 << 2) - (4 << 2)), [13,14,15,0]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
@@ -106,10 +105,9 @@ function testBailout(uglyDuckling) {
|
||||
var i8 = new Int8Array(f32.buffer);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
|
||||
var caught = false;
|
||||
try {
|
||||
SIMD.float32x4.load(i8, (i < 149) ? 0 : uglyDuckling);
|
||||
SIMD.Float32x4.load(i8, (i < 149) ? 0 : uglyDuckling);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
assertEq(e instanceof RangeError, true);
|
||||
|
||||
@@ -6,8 +6,8 @@ if (typeof SIMD === "undefined")
|
||||
setJitCompilerOption("baseline.warmup.trigger", 10);
|
||||
setJitCompilerOption("ion.warmup.trigger", 30);
|
||||
|
||||
var i4 = SIMD.int32x4;
|
||||
var i4sub = SIMD.int32x4.sub;
|
||||
var i4 = SIMD.Int32x4;
|
||||
var i4sub = SIMD.Int32x4.sub;
|
||||
|
||||
function simdbox(i) {
|
||||
return i4(i, i, i, i);
|
||||
|
||||
@@ -25,7 +25,7 @@ var uceFault = function (i) {
|
||||
// Check that we can correctly recover a boxed value.
|
||||
var uceFault_simdBox_i4 = eval(uneval(uceFault).replace('uceFault', 'uceFault_simdBox_i4'));
|
||||
function simdBox_i4(i) {
|
||||
var a = SIMD.int32x4(i, i, i, i);
|
||||
var a = SIMD.Int32x4(i, i, i, i);
|
||||
if (uceFault_simdBox_i4(i) || uceFault_simdBox_i4(i))
|
||||
assertEqX4(a, [i, i, i, i]);
|
||||
assertRecoveredOnBailout(a, true);
|
||||
@@ -34,7 +34,7 @@ function simdBox_i4(i) {
|
||||
|
||||
var uceFault_simdBox_f4 = eval(uneval(uceFault).replace('uceFault', 'uceFault_simdBox_f4'));
|
||||
function simdBox_f4(i) {
|
||||
var a = SIMD.float32x4(i, i + 0.1, i + 0.2, i + 0.3);
|
||||
var a = SIMD.Float32x4(i, i + 0.1, i + 0.2, i + 0.3);
|
||||
if (uceFault_simdBox_f4(i) || uceFault_simdBox_f4(i))
|
||||
assertEqX4(a, [i, i + 0.1, i + 0.2, i + 0.3].map(Math.fround));
|
||||
assertRecoveredOnBailout(a, true);
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
load(libdir + 'simd.js');
|
||||
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
var f4 = SIMD.Float32x4(1, 2, 3, 4);
|
||||
var i4 = SIMD.Int32x4(1, 2, 3, 4);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.Int32x4.replaceLane(i4, 0, 42), [42, 2, 3, 4]);
|
||||
assertEqX4(SIMD.Int32x4.replaceLane(i4, 1, 42), [1, 42, 3, 4]);
|
||||
assertEqX4(SIMD.Int32x4.replaceLane(i4, 2, 42), [1, 2, 42, 4]);
|
||||
assertEqX4(SIMD.Int32x4.replaceLane(i4, 3, 42), [1, 2, 3, 42]);
|
||||
|
||||
assertEqX4(SIMD.Float32x4.replaceLane(f4, 0, 42), [42, 2, 3, 4]);
|
||||
assertEqX4(SIMD.Float32x4.replaceLane(f4, 1, 42), [1, 42, 3, 4]);
|
||||
assertEqX4(SIMD.Float32x4.replaceLane(f4, 2, 42), [1, 2, 42, 4]);
|
||||
assertEqX4(SIMD.Float32x4.replaceLane(f4, 3, 42), [1, 2, 3, 42]);
|
||||
}
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
function e() {
|
||||
var f4 = SIMD.Float32x4(1, 2, 3, 4);
|
||||
var i4 = SIMD.Int32x4(1, 2, 3, 4);
|
||||
|
||||
for (let i = 0; i < 150; i++) {
|
||||
let caught = false;
|
||||
try {
|
||||
let x = SIMD.Int32x4.replaceLane(i < 149 ? i4 : f4, 0, 42);
|
||||
} catch(e) {
|
||||
assertEq(e instanceof TypeError, true);
|
||||
assertEq(i, 149);
|
||||
caught = true;
|
||||
}
|
||||
assertEq(i < 149 || caught, true);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 150; i++) {
|
||||
let caught = false;
|
||||
try {
|
||||
let x = SIMD.Int32x4.replaceLane(i4, i < 149 ? 0 : 4, 42);
|
||||
} catch(e) {
|
||||
assertEq(e instanceof TypeError, true);
|
||||
assertEq(i, 149);
|
||||
caught = true;
|
||||
}
|
||||
assertEq(i < 149 || caught, true);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 150; i++) {
|
||||
let caught = false;
|
||||
try {
|
||||
let x = SIMD.Int32x4.replaceLane(i4, i < 149 ? 0 : 1.1, 42);
|
||||
} catch(e) {
|
||||
assertEq(e instanceof TypeError, true);
|
||||
assertEq(i, 149);
|
||||
caught = true;
|
||||
}
|
||||
assertEq(i < 149 || caught, true);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 150; i++) {
|
||||
let caught = false;
|
||||
try {
|
||||
let x = SIMD.Float32x4.replaceLane(i < 149 ? f4 : i4, 0, 42);
|
||||
} catch(e) {
|
||||
assertEq(e instanceof TypeError, true);
|
||||
assertEq(i, 149);
|
||||
caught = true;
|
||||
}
|
||||
assertEq(i < 149 || caught, true);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 150; i++) {
|
||||
let caught = false;
|
||||
try {
|
||||
let x = SIMD.Float32x4.replaceLane(f4, i < 149 ? 0 : 4, 42);
|
||||
} catch(e) {
|
||||
assertEq(e instanceof TypeError, true);
|
||||
assertEq(i, 149);
|
||||
caught = true;
|
||||
}
|
||||
assertEq(i < 149 || caught, true);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 150; i++) {
|
||||
let caught = false;
|
||||
try {
|
||||
let x = SIMD.Float32x4.replaceLane(f4, i < 149 ? 0 : 1.1, 42);
|
||||
} catch(e) {
|
||||
assertEq(e instanceof TypeError, true);
|
||||
assertEq(i, 149);
|
||||
caught = true;
|
||||
}
|
||||
assertEq(i < 149 || caught, true);
|
||||
}
|
||||
}
|
||||
|
||||
e();
|
||||
@@ -2,45 +2,45 @@ load(libdir + 'simd.js');
|
||||
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function int32x4FromTypeBits(type, vec) {
|
||||
if (type == SIMD.int32x4)
|
||||
function Int32x4FromTypeBits(type, vec) {
|
||||
if (type == SIMD.Int32x4)
|
||||
return vec;
|
||||
if (type == SIMD.float32x4)
|
||||
return SIMD.int32x4.fromFloat32x4Bits(vec);
|
||||
if (type == SIMD.Float32x4)
|
||||
return SIMD.Int32x4.fromFloat32x4Bits(vec);
|
||||
throw 'unimplemented';
|
||||
}
|
||||
|
||||
function bitselect(type, mask, ifTrue, ifFalse) {
|
||||
var int32x4 = SIMD.int32x4;
|
||||
var tv = int32x4FromTypeBits(type, ifTrue);
|
||||
var fv = int32x4FromTypeBits(type, ifFalse);
|
||||
var tr = int32x4.and(mask, tv);
|
||||
var fr = int32x4.and(int32x4.not(mask), fv);
|
||||
var orApplied = int32x4.or(tr, fr);
|
||||
var converted = type == int32x4 ? orApplied : type.fromInt32x4Bits(orApplied);
|
||||
var Int32x4 = SIMD.Int32x4;
|
||||
var tv = Int32x4FromTypeBits(type, ifTrue);
|
||||
var fv = Int32x4FromTypeBits(type, ifFalse);
|
||||
var tr = Int32x4.and(mask, tv);
|
||||
var fr = Int32x4.and(Int32x4.not(mask), fv);
|
||||
var orApplied = Int32x4.or(tr, fr);
|
||||
var converted = type == Int32x4 ? orApplied : type.fromInt32x4Bits(orApplied);
|
||||
return simdToArray(converted);
|
||||
}
|
||||
|
||||
function f() {
|
||||
var f1 = SIMD.float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.float32x4(NaN, Infinity, 3.14, -0);
|
||||
var f1 = SIMD.Float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.Float32x4(NaN, Infinity, 3.14, -0);
|
||||
|
||||
var i1 = SIMD.int32x4(2, 3, 5, 8);
|
||||
var i2 = SIMD.int32x4(13, 37, 24, 42);
|
||||
var i1 = SIMD.Int32x4(2, 3, 5, 8);
|
||||
var i2 = SIMD.Int32x4(13, 37, 24, 42);
|
||||
|
||||
var TTFT = SIMD.int32x4(-1, -1, 0, -1);
|
||||
var TFTF = SIMD.int32x4(-1, 0, -1, 0);
|
||||
var TTFT = SIMD.Int32x4(-1, -1, 0, -1);
|
||||
var TFTF = SIMD.Int32x4(-1, 0, -1, 0);
|
||||
|
||||
var mask = SIMD.int32x4(0xdeadbeef, 0xbaadf00d, 0x00ff1ce, 0xdeadc0de);
|
||||
var mask = SIMD.Int32x4(0xdeadbeef, 0xbaadf00d, 0x00ff1ce, 0xdeadc0de);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.float32x4.select(TTFT, f1, f2), [f1.x, f1.y, f2.z, f1.w]);
|
||||
assertEqX4(SIMD.float32x4.select(TFTF, f1, f2), [f1.x, f2.y, f1.z, f2.w]);
|
||||
assertEqX4(SIMD.int32x4.select(TFTF, i1, i2), [i1.x, i2.y, i1.z, i2.w]);
|
||||
assertEqX4(SIMD.int32x4.select(TTFT, i1, i2), [i1.x, i1.y, i2.z, i1.w]);
|
||||
assertEqX4(SIMD.Float32x4.select(TTFT, f1, f2), [f1.x, f1.y, f2.z, f1.w]);
|
||||
assertEqX4(SIMD.Float32x4.select(TFTF, f1, f2), [f1.x, f2.y, f1.z, f2.w]);
|
||||
assertEqX4(SIMD.Int32x4.select(TFTF, i1, i2), [i1.x, i2.y, i1.z, i2.w]);
|
||||
assertEqX4(SIMD.Int32x4.select(TTFT, i1, i2), [i1.x, i1.y, i2.z, i1.w]);
|
||||
|
||||
assertEqX4(SIMD.float32x4.bitselect(mask, f1, f2), bitselect(SIMD.float32x4, mask, f1, f2));
|
||||
assertEqX4(SIMD.int32x4.bitselect(mask, i1, i2), bitselect(SIMD.int32x4, mask, i1, i2));
|
||||
assertEqX4(SIMD.Float32x4.bitselect(mask, f1, f2), bitselect(SIMD.Float32x4, mask, f1, f2));
|
||||
assertEqX4(SIMD.Int32x4.bitselect(mask, i1, i2), bitselect(SIMD.Int32x4, mask, i1, i2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ function binaryUrsh(count, v) { if (count>>>0 >= 32) return 0; return (v >>> cou
|
||||
function ursh(count) { return curry(binaryUrsh, count); }
|
||||
|
||||
function f() {
|
||||
var v = SIMD.int32x4(1, 2, -3, 4);
|
||||
var v = SIMD.Int32x4(1, 2, -3, 4);
|
||||
var a = [1, 2, -3, 4];
|
||||
var zeros = [0,0,0,0];
|
||||
|
||||
@@ -23,32 +23,32 @@ function f() {
|
||||
var r;
|
||||
for (var i = 0; i < 150; i++) {
|
||||
// Constant shift counts
|
||||
assertEqX4(SIMD.int32x4.shiftLeftByScalar(v, -1), a.map(lsh(-1)));
|
||||
assertEqX4(SIMD.int32x4.shiftLeftByScalar(v, 0), a.map(lsh(0)));
|
||||
assertEqX4(SIMD.int32x4.shiftLeftByScalar(v, 1), a.map(lsh(1)));
|
||||
assertEqX4(SIMD.int32x4.shiftLeftByScalar(v, 2), a.map(lsh(2)));
|
||||
assertEqX4(SIMD.int32x4.shiftLeftByScalar(v, 31), a.map(lsh(31)));
|
||||
assertEqX4(SIMD.int32x4.shiftLeftByScalar(v, 32), a.map(lsh(32)));
|
||||
assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, -1), a.map(lsh(-1)));
|
||||
assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 0), a.map(lsh(0)));
|
||||
assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 1), a.map(lsh(1)));
|
||||
assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 2), a.map(lsh(2)));
|
||||
assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 31), a.map(lsh(31)));
|
||||
assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 32), a.map(lsh(32)));
|
||||
|
||||
assertEqX4(SIMD.int32x4.shiftRightArithmeticByScalar(v, -1), a.map(rsh(31)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightArithmeticByScalar(v, 0), a.map(rsh(0)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightArithmeticByScalar(v, 1), a.map(rsh(1)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightArithmeticByScalar(v, 2), a.map(rsh(2)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightArithmeticByScalar(v, 31), a.map(rsh(31)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightArithmeticByScalar(v, 32), a.map(rsh(31)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightArithmeticByScalar(v, -1), a.map(rsh(31)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightArithmeticByScalar(v, 0), a.map(rsh(0)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightArithmeticByScalar(v, 1), a.map(rsh(1)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightArithmeticByScalar(v, 2), a.map(rsh(2)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightArithmeticByScalar(v, 31), a.map(rsh(31)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightArithmeticByScalar(v, 32), a.map(rsh(31)));
|
||||
|
||||
assertEqX4(SIMD.int32x4.shiftRightLogicalByScalar(v, -1), a.map(ursh(-1)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightLogicalByScalar(v, 0), a.map(ursh(0)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightLogicalByScalar(v, 1), a.map(ursh(1)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightLogicalByScalar(v, 2), a.map(ursh(2)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightLogicalByScalar(v, 31), a.map(ursh(31)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightLogicalByScalar(v, 32), a.map(ursh(32)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightLogicalByScalar(v, -1), a.map(ursh(-1)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightLogicalByScalar(v, 0), a.map(ursh(0)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightLogicalByScalar(v, 1), a.map(ursh(1)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightLogicalByScalar(v, 2), a.map(ursh(2)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightLogicalByScalar(v, 31), a.map(ursh(31)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightLogicalByScalar(v, 32), a.map(ursh(32)));
|
||||
|
||||
// Non constant shift counts
|
||||
var c = shifts[i % shifts.length];
|
||||
assertEqX4(SIMD.int32x4.shiftLeftByScalar(v, c), a.map(lsh(c)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightArithmeticByScalar(v, c), a.map(rsh(c)));
|
||||
assertEqX4(SIMD.int32x4.shiftRightLogicalByScalar(v, c), a.map(ursh(c)));
|
||||
assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, c), a.map(lsh(c)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightArithmeticByScalar(v, c), a.map(rsh(c)));
|
||||
assertEqX4(SIMD.Int32x4.shiftRightLogicalByScalar(v, c), a.map(ursh(c)));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ load(libdir + 'simd.js');
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
var i1 = SIMD.int32x4(1, 2, 3, 4);
|
||||
var i2 = SIMD.int32x4(5, 6, 7, 8);
|
||||
var i1 = SIMD.Int32x4(1, 2, 3, 4);
|
||||
var i2 = SIMD.Int32x4(5, 6, 7, 8);
|
||||
|
||||
var leet = Math.fround(13.37);
|
||||
var f1 = SIMD.float32x4(-.5, -0, Infinity, leet);
|
||||
var f2 = SIMD.float32x4(42, .5, 23, -10);
|
||||
var f1 = SIMD.Float32x4(-.5, -0, Infinity, leet);
|
||||
var f2 = SIMD.Float32x4(42, .5, 23, -10);
|
||||
|
||||
// computes all rotations of a given array
|
||||
function *gen(arr) {
|
||||
@@ -35,31 +35,31 @@ function f() {
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
// Variable lanes
|
||||
var r = SIMD.float32x4.shuffle(f1, f2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8);
|
||||
var r = SIMD.Float32x4.shuffle(f1, f2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8);
|
||||
assertEqX4(r, compF[i % 8]);
|
||||
|
||||
// Constant lanes
|
||||
assertEqX4(SIMD.float32x4.shuffle(f1, f2, 3, 2, 4, 5), [leet, Infinity, 42, .5]);
|
||||
assertEqX4(SIMD.Float32x4.shuffle(f1, f2, 3, 2, 4, 5), [leet, Infinity, 42, .5]);
|
||||
|
||||
// Variable lanes
|
||||
var r = SIMD.int32x4.shuffle(i1, i2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8);
|
||||
var r = SIMD.Int32x4.shuffle(i1, i2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8);
|
||||
assertEqX4(r, compI[i % 8]);
|
||||
|
||||
// Constant lanes
|
||||
assertEqX4(SIMD.int32x4.shuffle(i1, i2, 3, 2, 4, 5), [4, 3, 5, 6]);
|
||||
assertEqX4(SIMD.Int32x4.shuffle(i1, i2, 3, 2, 4, 5), [4, 3, 5, 6]);
|
||||
}
|
||||
}
|
||||
|
||||
function testBailouts(uglyDuckling) {
|
||||
var i1 = SIMD.int32x4(1, 2, 3, 4);
|
||||
var i2 = SIMD.int32x4(5, 6, 7, 8);
|
||||
var i1 = SIMD.Int32x4(1, 2, 3, 4);
|
||||
var i2 = SIMD.Int32x4(5, 6, 7, 8);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
// Test bailouts
|
||||
var value = i == 149 ? uglyDuckling : 3;
|
||||
var caught = false;
|
||||
try {
|
||||
assertEqX4(SIMD.int32x4.shuffle(i1, i2, value, 2, 4, 5), [4, 3, 5, 6]);
|
||||
assertEqX4(SIMD.Int32x4.shuffle(i1, i2, value, 2, 4, 5), [4, 3, 5, 6]);
|
||||
} catch(e) {
|
||||
print(e);
|
||||
caught = true;
|
||||
|
||||
@@ -4,8 +4,8 @@ setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.int32x4.splat(42), [42, 42, 42, 42]);
|
||||
assertEqX4(SIMD.float32x4.splat(42), [42, 42, 42, 42]);
|
||||
assertEqX4(SIMD.Int32x4.splat(42), [42, 42, 42, 42]);
|
||||
assertEqX4(SIMD.Float32x4.splat(42), [42, 42, 42, 42]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ function f() {
|
||||
var i8 = new Int8Array(f32.buffer);
|
||||
var u8 = new Uint8Array(f32.buffer);
|
||||
|
||||
var f4 = SIMD.float32x4(42, 43, 44, 45);
|
||||
var f4 = SIMD.Float32x4(42, 43, 44, 45);
|
||||
|
||||
function check(n) {
|
||||
assertEq(f32[0], 42);
|
||||
@@ -30,78 +30,78 @@ function f() {
|
||||
}
|
||||
|
||||
function testStore() {
|
||||
SIMD.float32x4.store(f64, 0, f4);
|
||||
SIMD.Float32x4.store(f64, 0, f4);
|
||||
check(4);
|
||||
SIMD.float32x4.store(f32, 0, f4);
|
||||
SIMD.Float32x4.store(f32, 0, f4);
|
||||
check(4);
|
||||
SIMD.float32x4.store(i32, 0, f4);
|
||||
SIMD.Float32x4.store(i32, 0, f4);
|
||||
check(4);
|
||||
SIMD.float32x4.store(u32, 0, f4);
|
||||
SIMD.Float32x4.store(u32, 0, f4);
|
||||
check(4);
|
||||
SIMD.float32x4.store(i16, 0, f4);
|
||||
SIMD.Float32x4.store(i16, 0, f4);
|
||||
check(4);
|
||||
SIMD.float32x4.store(u16, 0, f4);
|
||||
SIMD.Float32x4.store(u16, 0, f4);
|
||||
check(4);
|
||||
SIMD.float32x4.store(i8, 0, f4);
|
||||
SIMD.Float32x4.store(i8, 0, f4);
|
||||
check(4);
|
||||
SIMD.float32x4.store(u8, 0, f4);
|
||||
SIMD.Float32x4.store(u8, 0, f4);
|
||||
check(4);
|
||||
}
|
||||
|
||||
function testStore1() {
|
||||
SIMD.float32x4.store1(f64, 0, f4);
|
||||
SIMD.Float32x4.store1(f64, 0, f4);
|
||||
check(1);
|
||||
SIMD.float32x4.store1(f32, 0, f4);
|
||||
SIMD.Float32x4.store1(f32, 0, f4);
|
||||
check(1);
|
||||
SIMD.float32x4.store1(i32, 0, f4);
|
||||
SIMD.Float32x4.store1(i32, 0, f4);
|
||||
check(1);
|
||||
SIMD.float32x4.store1(u32, 0, f4);
|
||||
SIMD.Float32x4.store1(u32, 0, f4);
|
||||
check(1);
|
||||
SIMD.float32x4.store1(i16, 0, f4);
|
||||
SIMD.Float32x4.store1(i16, 0, f4);
|
||||
check(1);
|
||||
SIMD.float32x4.store1(u16, 0, f4);
|
||||
SIMD.Float32x4.store1(u16, 0, f4);
|
||||
check(1);
|
||||
SIMD.float32x4.store1(i8, 0, f4);
|
||||
SIMD.Float32x4.store1(i8, 0, f4);
|
||||
check(1);
|
||||
SIMD.float32x4.store1(u8, 0, f4);
|
||||
SIMD.Float32x4.store1(u8, 0, f4);
|
||||
check(1);
|
||||
}
|
||||
|
||||
function testStore2() {
|
||||
SIMD.float32x4.store2(f64, 0, f4);
|
||||
SIMD.Float32x4.store2(f64, 0, f4);
|
||||
check(2);
|
||||
SIMD.float32x4.store2(f32, 0, f4);
|
||||
SIMD.Float32x4.store2(f32, 0, f4);
|
||||
check(2);
|
||||
SIMD.float32x4.store2(i32, 0, f4);
|
||||
SIMD.Float32x4.store2(i32, 0, f4);
|
||||
check(2);
|
||||
SIMD.float32x4.store2(u32, 0, f4);
|
||||
SIMD.Float32x4.store2(u32, 0, f4);
|
||||
check(2);
|
||||
SIMD.float32x4.store2(i16, 0, f4);
|
||||
SIMD.Float32x4.store2(i16, 0, f4);
|
||||
check(2);
|
||||
SIMD.float32x4.store2(u16, 0, f4);
|
||||
SIMD.Float32x4.store2(u16, 0, f4);
|
||||
check(2);
|
||||
SIMD.float32x4.store2(i8, 0, f4);
|
||||
SIMD.Float32x4.store2(i8, 0, f4);
|
||||
check(2);
|
||||
SIMD.float32x4.store2(u8, 0, f4);
|
||||
SIMD.Float32x4.store2(u8, 0, f4);
|
||||
check(2);
|
||||
}
|
||||
|
||||
function testStore3() {
|
||||
SIMD.float32x4.store3(f64, 0, f4);
|
||||
SIMD.Float32x4.store3(f64, 0, f4);
|
||||
check(3);
|
||||
SIMD.float32x4.store3(f32, 0, f4);
|
||||
SIMD.Float32x4.store3(f32, 0, f4);
|
||||
check(3);
|
||||
SIMD.float32x4.store3(i32, 0, f4);
|
||||
SIMD.Float32x4.store3(i32, 0, f4);
|
||||
check(3);
|
||||
SIMD.float32x4.store3(u32, 0, f4);
|
||||
SIMD.Float32x4.store3(u32, 0, f4);
|
||||
check(3);
|
||||
SIMD.float32x4.store3(i16, 0, f4);
|
||||
SIMD.Float32x4.store3(i16, 0, f4);
|
||||
check(3);
|
||||
SIMD.float32x4.store3(u16, 0, f4);
|
||||
SIMD.Float32x4.store3(u16, 0, f4);
|
||||
check(3);
|
||||
SIMD.float32x4.store3(i8, 0, f4);
|
||||
SIMD.Float32x4.store3(i8, 0, f4);
|
||||
check(3);
|
||||
SIMD.float32x4.store3(u8, 0, f4);
|
||||
SIMD.Float32x4.store3(u8, 0, f4);
|
||||
check(3);
|
||||
}
|
||||
|
||||
@@ -122,12 +122,12 @@ function testBailout(uglyDuckling) {
|
||||
|
||||
var i8 = new Int8Array(f32.buffer);
|
||||
|
||||
var f4 = SIMD.float32x4(42, 43, 44, 45);
|
||||
var f4 = SIMD.Float32x4(42, 43, 44, 45);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
var caught = false;
|
||||
try {
|
||||
SIMD.float32x4.store(i8, (i < 149) ? 0 : (16 << 2) - (4 << 2) + 1, f4);
|
||||
SIMD.Float32x4.store(i8, (i < 149) ? 0 : (16 << 2) - (4 << 2) + 1, f4);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
assertEq(e instanceof RangeError, true);
|
||||
|
||||
@@ -6,10 +6,10 @@ load(libdir + 'simd.js');
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
var i4 = SIMD.int32x4(1, 2, 3, 4);
|
||||
var i4 = SIMD.Int32x4(1, 2, 3, 4);
|
||||
|
||||
var leet = Math.fround(13.37);
|
||||
var f4 = SIMD.float32x4(-.5, -0, Infinity, leet);
|
||||
var f4 = SIMD.Float32x4(-.5, -0, Infinity, leet);
|
||||
|
||||
var compI = [
|
||||
[1,2,3,4],
|
||||
@@ -27,29 +27,29 @@ function f() {
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
// Variable lanes
|
||||
var r = SIMD.float32x4.swizzle(f4, i % 4, (i + 1) % 4, (i + 2) % 4, (i + 3) % 4);
|
||||
var r = SIMD.Float32x4.swizzle(f4, i % 4, (i + 1) % 4, (i + 2) % 4, (i + 3) % 4);
|
||||
assertEqX4(r, compF[i % 4]);
|
||||
|
||||
// Constant lanes
|
||||
assertEqX4(SIMD.float32x4.swizzle(f4, 3, 2, 1, 0), [leet, Infinity, -0, -.5]);
|
||||
assertEqX4(SIMD.Float32x4.swizzle(f4, 3, 2, 1, 0), [leet, Infinity, -0, -.5]);
|
||||
|
||||
// Variable lanes
|
||||
var r = SIMD.int32x4.swizzle(i4, i % 4, (i + 1) % 4, (i + 2) % 4, (i + 3) % 4);
|
||||
var r = SIMD.Int32x4.swizzle(i4, i % 4, (i + 1) % 4, (i + 2) % 4, (i + 3) % 4);
|
||||
assertEqX4(r, compI[i % 4]);
|
||||
|
||||
// Constant lanes
|
||||
assertEqX4(SIMD.int32x4.swizzle(i4, 3, 2, 1, 0), [4, 3, 2, 1]);
|
||||
assertEqX4(SIMD.Int32x4.swizzle(i4, 3, 2, 1, 0), [4, 3, 2, 1]);
|
||||
}
|
||||
}
|
||||
|
||||
function testBailouts(uglyDuckling) {
|
||||
var i4 = SIMD.int32x4(1, 2, 3, 4);
|
||||
var i4 = SIMD.Int32x4(1, 2, 3, 4);
|
||||
for (var i = 0; i < 150; i++) {
|
||||
// Test bailouts
|
||||
var value = i == 149 ? uglyDuckling : 0;
|
||||
var caught = false;
|
||||
try {
|
||||
assertEqX4(SIMD.int32x4.swizzle(i4, value, 3, 2, 0), [1, 4, 3, 1]);
|
||||
assertEqX4(SIMD.Int32x4.swizzle(i4, value, 3, 2, 0), [1, 4, 3, 1]);
|
||||
} catch(e) {
|
||||
print(e);
|
||||
caught = true;
|
||||
@@ -60,6 +60,14 @@ function testBailouts(uglyDuckling) {
|
||||
}
|
||||
}
|
||||
|
||||
function testInt32x4SwizzleBailout() {
|
||||
// Test out-of-bounds non-constant indices. This is expected to throw.
|
||||
var i4 = SIMD.Int32x4(1, 2, 3, 4);
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.Int32x4.swizzle(i4, i, 3, 2, 0), [i + 1, 4, 3, 1]);
|
||||
}
|
||||
}
|
||||
|
||||
f();
|
||||
testBailouts(-1);
|
||||
testBailouts(4);
|
||||
@@ -69,3 +77,10 @@ testBailouts(null);
|
||||
testBailouts({});
|
||||
testBailouts('one');
|
||||
testBailouts(true);
|
||||
|
||||
try {
|
||||
testInt32x4SwizzleBailout();
|
||||
throw 'not caught';
|
||||
} catch(e) {
|
||||
assertEq(e instanceof TypeError, true);
|
||||
}
|
||||
|
||||
@@ -13,20 +13,20 @@ var notf = (function() {
|
||||
})();
|
||||
|
||||
function f() {
|
||||
var f4 = SIMD.float32x4(1, 2, 3, 4);
|
||||
var i4 = SIMD.int32x4(1, 2, 3, 4);
|
||||
var f4 = SIMD.Float32x4(1, 2, 3, 4);
|
||||
var i4 = SIMD.Int32x4(1, 2, 3, 4);
|
||||
var BitOrZero = (x) => x | 0;
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.float32x4.not(f4), unaryX4(notf, f4, Math.fround));
|
||||
assertEqX4(SIMD.float32x4.neg(f4), unaryX4((x) => -x, f4, Math.fround));
|
||||
assertEqX4(SIMD.float32x4.abs(f4), unaryX4(Math.abs, f4, Math.fround));
|
||||
assertEqX4(SIMD.float32x4.sqrt(f4), unaryX4(Math.sqrt, f4, Math.fround));
|
||||
assertEqX4(SIMD.Float32x4.not(f4), unaryX4(notf, f4, Math.fround));
|
||||
assertEqX4(SIMD.Float32x4.neg(f4), unaryX4((x) => -x, f4, Math.fround));
|
||||
assertEqX4(SIMD.Float32x4.abs(f4), unaryX4(Math.abs, f4, Math.fround));
|
||||
assertEqX4(SIMD.Float32x4.sqrt(f4), unaryX4(Math.sqrt, f4, Math.fround));
|
||||
|
||||
assertEqX4(SIMD.float32x4.reciprocalApproximation(f4), unaryX4((x) => 1 / x, f4, Math.fround), assertNear);
|
||||
assertEqX4(SIMD.float32x4.reciprocalSqrtApproximation(f4), unaryX4((x) => 1 / Math.sqrt(x), f4, Math.fround), assertNear);
|
||||
assertEqX4(SIMD.Float32x4.reciprocalApproximation(f4), unaryX4((x) => 1 / x, f4, Math.fround), assertNear);
|
||||
assertEqX4(SIMD.Float32x4.reciprocalSqrtApproximation(f4), unaryX4((x) => 1 / Math.sqrt(x), f4, Math.fround), assertNear);
|
||||
|
||||
assertEqX4(SIMD.int32x4.not(i4), unaryX4((x) => ~x, i4, BitOrZero));
|
||||
assertEqX4(SIMD.int32x4.neg(i4), unaryX4((x) => -x, i4, BitOrZero));
|
||||
assertEqX4(SIMD.Int32x4.not(i4), unaryX4((x) => ~x, i4, BitOrZero));
|
||||
assertEqX4(SIMD.Int32x4.neg(i4), unaryX4((x) => -x, i4, BitOrZero));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ setJitCompilerOption("baseline.warmup.trigger", 10);
|
||||
setJitCompilerOption("ion.warmup.trigger", 30);
|
||||
var max = 40, pivot = 35;
|
||||
|
||||
var i32x4 = SIMD.int32x4;
|
||||
var f32x4 = SIMD.float32x4;
|
||||
var i32x4Add = SIMD.int32x4.add;
|
||||
var i32x4 = SIMD.Int32x4;
|
||||
var f32x4 = SIMD.Float32x4;
|
||||
var i32x4Add = SIMD.Int32x4.add;
|
||||
|
||||
var FakeSIMDType = function (o) { this.x = o.x; this.y = o.y; this.z = o.z; this.w = o.w; };
|
||||
if (this.hasOwnProperty("TypedObject")) {
|
||||
@@ -15,7 +15,6 @@ if (this.hasOwnProperty("TypedObject")) {
|
||||
FakeSIMDType = new TO.StructType({ x: TO.int32, y: TO.int32, z: TO.int32, w: TO.int32 });
|
||||
}
|
||||
|
||||
|
||||
function simdunbox_bail_undef(i, lhs, rhs) {
|
||||
return i32x4Add(lhs, rhs);
|
||||
}
|
||||
@@ -106,3 +105,40 @@ for (i = 0; i < max; i++) {
|
||||
assertEqX4(arr_typeobj[i], ref);
|
||||
assertEqX4(arr_badsimd[i], ref);
|
||||
}
|
||||
|
||||
// Check that unbox operations aren't removed
|
||||
(function() {
|
||||
|
||||
function add(i, v, w) {
|
||||
if (i % 2 == 0) {
|
||||
SIMD.Int32x4.add(v, w);
|
||||
} else {
|
||||
SIMD.Float32x4.add(v, w);
|
||||
}
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var caught = false;
|
||||
var f4 = SIMD.Float32x4(1,2,3,4);
|
||||
var i4 = SIMD.Int32x4(1,2,3,4);
|
||||
try {
|
||||
for (; i < 200; i++) {
|
||||
if (i % 2 == 0) {
|
||||
add(i, i4, i4);
|
||||
} else if (i == 199) {
|
||||
add(i, i4, f4);
|
||||
} else {
|
||||
add(i, f4, f4);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
print(e);
|
||||
assertEq(e instanceof TypeError, true);
|
||||
assertEq(i, 199);
|
||||
caught = true;
|
||||
}
|
||||
|
||||
assertEq(i < 199 || caught, true);
|
||||
|
||||
})();
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
load(libdir + 'simd.js');
|
||||
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
var f4 = SIMD.float32x4(1, 2, 3, 4);
|
||||
var i4 = SIMD.int32x4(1, 2, 3, 4);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.int32x4.withX(i4, 42), [42, 2, 3, 4]);
|
||||
assertEqX4(SIMD.int32x4.withY(i4, 42), [1, 42, 3, 4]);
|
||||
assertEqX4(SIMD.int32x4.withZ(i4, 42), [1, 2, 42, 4]);
|
||||
assertEqX4(SIMD.int32x4.withW(i4, 42), [1, 2, 3, 42]);
|
||||
|
||||
assertEqX4(SIMD.float32x4.withX(f4, 42), [42, 2, 3, 4]);
|
||||
assertEqX4(SIMD.float32x4.withY(f4, 42), [1, 42, 3, 4]);
|
||||
assertEqX4(SIMD.float32x4.withZ(f4, 42), [1, 2, 42, 4]);
|
||||
assertEqX4(SIMD.float32x4.withW(f4, 42), [1, 2, 3, 42]);
|
||||
}
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
|
||||
if (typeof TypedObject === "undefined")
|
||||
quit();
|
||||
|
||||
var int32x4 = SIMD.int32x4;
|
||||
var a = int32x4((4294967295), 200, 300, 400);
|
||||
addCase( new Array(Math.pow(2,12)) );
|
||||
for ( var arg = "", i = 0; i < Math.pow(2,12); i++ ) {}
|
||||
addCase( a );
|
||||
function addCase(object) {
|
||||
object.length
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
if (!this.hasOwnProperty("TypedObject"))
|
||||
quit();
|
||||
|
||||
var float32x4 = SIMD.float32x4;
|
||||
float32x4.array(1);
|
||||
@@ -21,10 +21,10 @@ if (!isSimdAvailable() || typeof SIMD === 'undefined') {
|
||||
var v = asmLink(asmCompile('global', `
|
||||
"use asm";
|
||||
var frd = global.Math.fround;
|
||||
var float32x4 = global.SIMD.float32x4;
|
||||
var splat = float32x4.splat;
|
||||
var Float32x4 = global.SIMD.Float32x4;
|
||||
var splat = Float32x4.splat;
|
||||
function e() {
|
||||
var v = float32x4(0,0,0,0);
|
||||
var v = Float32x4(0,0,0,0);
|
||||
var x = frd(0.);
|
||||
v = splat(.1e+71);
|
||||
x = v.x;
|
||||
@@ -40,8 +40,8 @@ assertEq(v, NaN);
|
||||
setJitCompilerOption("ion.gvn.enable", 0);
|
||||
var v = asmLink(asmCompile('global', `
|
||||
"use asm";
|
||||
var float32x4 = global.SIMD.float32x4;
|
||||
var splat = float32x4.splat;
|
||||
var Float32x4 = global.SIMD.Float32x4;
|
||||
var splat = Float32x4.splat;
|
||||
function e() {
|
||||
return +splat(.1e+71).x;
|
||||
}
|
||||
|
||||
@@ -10,11 +10,6 @@
|
||||
if (!isAsmJSCompilationAvailable())
|
||||
quit(0);
|
||||
|
||||
/*
|
||||
|
||||
// Commented out until we can fix bug #1172517, which makes this fail
|
||||
// for other reasons.
|
||||
|
||||
function module_a(stdlib, foreign, heap) {
|
||||
"use asm";
|
||||
|
||||
@@ -35,8 +30,6 @@ function module_a(stdlib, foreign, heap) {
|
||||
if (this.SharedArrayBuffer)
|
||||
assertEq(isAsmJSModule(module_a), true);
|
||||
|
||||
*/
|
||||
|
||||
function module_b(stdlib, foreign, heap) {
|
||||
"use asm";
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ var code = `
|
||||
const getAccelDataSteps = imp.accelDataSteps | 0;
|
||||
var getActualBirds = imp.getActualBirds;
|
||||
|
||||
var i4 = global.SIMD.int32x4;
|
||||
var f4 = global.SIMD.float32x4;
|
||||
var i4 = global.SIMD.Int32x4;
|
||||
var f4 = global.SIMD.Float32x4;
|
||||
var i4add = i4.add;
|
||||
var i4and = i4.and;
|
||||
var f4select = f4.select;
|
||||
|
||||
@@ -28,9 +28,9 @@ var moduleCode = `
|
||||
"use asm"
|
||||
var b8 = new global.Uint8Array(buffer);
|
||||
var toF = global.Math.fround;
|
||||
var i4 = global.SIMD.int32x4;
|
||||
var i4 = global.SIMD.Int32x4;
|
||||
var ci4 = i4.check;
|
||||
var f4 = global.SIMD.float32x4;
|
||||
var f4 = global.SIMD.Float32x4;
|
||||
var i4add = i4.add;
|
||||
var i4and = i4.and;
|
||||
var f4add = f4.add;
|
||||
|
||||
@@ -30,6 +30,9 @@ function m(stdlib, ffi, heap)
|
||||
return {add_sharedEv:add_sharedEv};
|
||||
}
|
||||
|
||||
if (isAsmJSCompilationAvailable())
|
||||
assertEq(isAsmJSModule(m), true);
|
||||
|
||||
var x;
|
||||
|
||||
var sab = new SharedArrayBuffer(65536);
|
||||
|
||||
@@ -24,7 +24,7 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
// Load element 0
|
||||
function do_load() {
|
||||
var v = 0;
|
||||
v = atomic_load(i32a, 0);
|
||||
v = atomic_load(i32a, 0)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -32,14 +32,14 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
function do_load_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_load(i32a, i>>2);
|
||||
v = atomic_load(i32a, i>>2)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// Store 37 in element 0
|
||||
function do_store() {
|
||||
var v = 0;
|
||||
v = atomic_store(i32a, 0, 37);
|
||||
v = atomic_store(i32a, 0, 37)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -47,14 +47,14 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
function do_store_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_store(i32a, i>>2, 37);
|
||||
v = atomic_store(i32a, i>>2, 37)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// Add 37 to element 10
|
||||
function do_add() {
|
||||
var v = 0;
|
||||
v = atomic_add(i32a, 10, 37);
|
||||
v = atomic_add(i32a, 10, 37)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -62,14 +62,14 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
function do_add_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_add(i32a, i>>2, 37);
|
||||
v = atomic_add(i32a, i>>2, 37)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// Subtract 148 from element 20
|
||||
function do_sub() {
|
||||
var v = 0;
|
||||
v = atomic_sub(i32a, 20, 148);
|
||||
v = atomic_sub(i32a, 20, 148)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -77,14 +77,14 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
function do_sub_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_sub(i32a, i>>2, 148);
|
||||
v = atomic_sub(i32a, i>>2, 148)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// AND 0x33333333 into element 30
|
||||
function do_and() {
|
||||
var v = 0;
|
||||
v = atomic_and(i32a, 30, 0x33333333);
|
||||
v = atomic_and(i32a, 30, 0x33333333)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -92,14 +92,14 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
function do_and_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_and(i32a, i>>2, 0x33333333);
|
||||
v = atomic_and(i32a, i>>2, 0x33333333)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// OR 0x33333333 into element 40
|
||||
function do_or() {
|
||||
var v = 0;
|
||||
v = atomic_or(i32a, 40, 0x33333333);
|
||||
v = atomic_or(i32a, 40, 0x33333333)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -107,14 +107,14 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
function do_or_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_or(i32a, i>>2, 0x33333333);
|
||||
v = atomic_or(i32a, i>>2, 0x33333333)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// XOR 0x33333333 into element 50
|
||||
function do_xor() {
|
||||
var v = 0;
|
||||
v = atomic_xor(i32a, 50, 0x33333333);
|
||||
v = atomic_xor(i32a, 50, 0x33333333)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -122,21 +122,21 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
function do_xor_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_xor(i32a, i>>2, 0x33333333);
|
||||
v = atomic_xor(i32a, i>>2, 0x33333333)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// CAS element 100: 0 -> -1
|
||||
function do_cas1() {
|
||||
var v = 0;
|
||||
v = atomic_cmpxchg(i32a, 100, 0, -1);
|
||||
v = atomic_cmpxchg(i32a, 100, 0, -1)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// CAS element 100: -1 -> 0x5A5A5A5A
|
||||
function do_cas2() {
|
||||
var v = 0;
|
||||
v = atomic_cmpxchg(i32a, 100, -1, 0x5A5A5A5A);
|
||||
v = atomic_cmpxchg(i32a, 100, -1, 0x5A5A5A5A)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
function do_cas1_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_cmpxchg(i32a, i>>2, 0, -1);
|
||||
v = atomic_cmpxchg(i32a, i>>2, 0, -1)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
function do_cas2_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_cmpxchg(i32a, i>>2, -1, 0x5A5A5A5A);
|
||||
v = atomic_cmpxchg(i32a, i>>2, -1, 0x5A5A5A5A)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -177,6 +177,9 @@ function loadModule_int32(stdlib, foreign, heap) {
|
||||
cas2_i: do_cas2_i };
|
||||
}
|
||||
|
||||
if (isAsmJSCompilationAvailable())
|
||||
assertEq(isAsmJSModule(loadModule_int32), true);
|
||||
|
||||
function loadModule_int8(stdlib, foreign, heap) {
|
||||
"use asm";
|
||||
|
||||
@@ -194,7 +197,7 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
// Load element 0
|
||||
function do_load() {
|
||||
var v = 0;
|
||||
v = atomic_load(i8a, 0);
|
||||
v = atomic_load(i8a, 0)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -202,14 +205,14 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
function do_load_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_load(i8a, i);
|
||||
v = atomic_load(i8a, i)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// Store 37 in element 0
|
||||
function do_store() {
|
||||
var v = 0;
|
||||
v = atomic_store(i8a, 0, 37);
|
||||
v = atomic_store(i8a, 0, 37)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -217,14 +220,14 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
function do_store_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_store(i8a, i, 37);
|
||||
v = atomic_store(i8a, i, 37)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// Add 37 to element 10
|
||||
function do_add() {
|
||||
var v = 0;
|
||||
v = atomic_add(i8a, 10, 37);
|
||||
v = atomic_add(i8a, 10, 37)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -232,14 +235,14 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
function do_add_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_add(i8a, i, 37);
|
||||
v = atomic_add(i8a, i, 37)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// Subtract 108 from element 20
|
||||
function do_sub() {
|
||||
var v = 0;
|
||||
v = atomic_sub(i8a, 20, 108);
|
||||
v = atomic_sub(i8a, 20, 108)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -247,14 +250,14 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
function do_sub_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_sub(i8a, i, 108);
|
||||
v = atomic_sub(i8a, i, 108)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// AND 0x33 into element 30
|
||||
function do_and() {
|
||||
var v = 0;
|
||||
v = atomic_and(i8a, 30, 0x33);
|
||||
v = atomic_and(i8a, 30, 0x33)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -262,14 +265,14 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
function do_and_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_and(i8a, i, 0x33);
|
||||
v = atomic_and(i8a, i, 0x33)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// OR 0x33 into element 40
|
||||
function do_or() {
|
||||
var v = 0;
|
||||
v = atomic_or(i8a, 40, 0x33);
|
||||
v = atomic_or(i8a, 40, 0x33)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -277,14 +280,14 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
function do_or_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_or(i8a, i, 0x33);
|
||||
v = atomic_or(i8a, i, 0x33)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// XOR 0x33 into element 50
|
||||
function do_xor() {
|
||||
var v = 0;
|
||||
v = atomic_xor(i8a, 50, 0x33);
|
||||
v = atomic_xor(i8a, 50, 0x33)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -292,21 +295,21 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
function do_xor_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_xor(i8a, i, 0x33);
|
||||
v = atomic_xor(i8a, i, 0x33)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// CAS element 100: 0 -> -1
|
||||
function do_cas1() {
|
||||
var v = 0;
|
||||
v = atomic_cmpxchg(i8a, 100, 0, -1);
|
||||
v = atomic_cmpxchg(i8a, 100, 0, -1)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
// CAS element 100: -1 -> 0x5A
|
||||
function do_cas2() {
|
||||
var v = 0;
|
||||
v = atomic_cmpxchg(i8a, 100, -1, 0x5A);
|
||||
v = atomic_cmpxchg(i8a, 100, -1, 0x5A)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -314,7 +317,7 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
function do_cas1_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_cmpxchg(i8a, i, 0, -1);
|
||||
v = atomic_cmpxchg(i8a, i, 0, -1)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -322,7 +325,7 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
function do_cas2_i(i) {
|
||||
i = i|0;
|
||||
var v = 0;
|
||||
v = atomic_cmpxchg(i8a, i, -1, 0x5A);
|
||||
v = atomic_cmpxchg(i8a, i, -1, 0x5A)|0;
|
||||
return v|0;
|
||||
}
|
||||
|
||||
@@ -346,6 +349,9 @@ function loadModule_int8(stdlib, foreign, heap) {
|
||||
cas2_i: do_cas2_i };
|
||||
}
|
||||
|
||||
if (isAsmJSCompilationAvailable())
|
||||
assertEq(isAsmJSModule(loadModule_int8), true);
|
||||
|
||||
// TODO: halfword arrays
|
||||
// TODO: signed vs unsigned; negative results
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ if (typeof SIMD === 'undefined' || !isSimdAvailable()) {
|
||||
(function(global) {
|
||||
"use asm";
|
||||
var frd = global.Math.fround;
|
||||
var fx4 = global.SIMD.float32x4;
|
||||
var fx4 = global.SIMD.Float32x4;
|
||||
var fsp = fx4.splat;
|
||||
function s(){}
|
||||
function d(x){x=fx4(x);}
|
||||
@@ -21,7 +21,7 @@ if (typeof SIMD === 'undefined' || !isSimdAvailable()) {
|
||||
|
||||
(function(m) {
|
||||
"use asm"
|
||||
var g = m.SIMD.int32x4
|
||||
var g = m.SIMD.Int32x4
|
||||
var h = g.select
|
||||
function f() {
|
||||
var x = g(0, 0, 0, 0)
|
||||
@@ -34,7 +34,7 @@ if (typeof SIMD === 'undefined' || !isSimdAvailable()) {
|
||||
t = (function(global) {
|
||||
"use asm"
|
||||
var toF = global.Math.fround
|
||||
var f4 = global.SIMD.float32x4
|
||||
var f4 = global.SIMD.Float32x4
|
||||
function p(x, y, width, value, max_iterations) {
|
||||
x = x | 0
|
||||
y = y | 0
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable())
|
||||
quit(0);
|
||||
|
||||
// The way this is constructed, either the first module does not
|
||||
// verify as asm.js (if the >>>0 is left off, which was legal prior to
|
||||
// bug 1155176), or the results of the two modules have to be equal.
|
||||
|
||||
function m(stdlib, ffi, heap) {
|
||||
"use asm";
|
||||
|
||||
var view = new stdlib.SharedUint32Array(heap);
|
||||
var cas = stdlib.Atomics.compareExchange;
|
||||
var hi = ffi.hi;
|
||||
|
||||
function run() {
|
||||
hi(+(cas(view, 37, 0, 0)>>>0));
|
||||
}
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
assertEq(isAsmJSModule(m), true);
|
||||
|
||||
function nonm(stdlib, ffi, heap) {
|
||||
|
||||
var view = new stdlib.SharedUint32Array(heap);
|
||||
var cas = stdlib.Atomics.compareExchange;
|
||||
var hi = ffi.hi;
|
||||
|
||||
function run() {
|
||||
hi(+cas(view, 37, 0, 0));
|
||||
}
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
var sab = new SharedArrayBuffer(65536);
|
||||
var ua = new SharedUint32Array(sab);
|
||||
var results = [];
|
||||
var mrun = m(this, {hi: function (x) { results.push(x) }}, sab);
|
||||
var nonmrun = nonm(this, {hi: function (x) { results.push(x) }}, sab);
|
||||
|
||||
ua[37] = 0x80000001;
|
||||
|
||||
mrun();
|
||||
nonmrun();
|
||||
|
||||
assertEq(results[0], ua[37]);
|
||||
assertEq(results[0], results[1]);
|
||||
@@ -0,0 +1,23 @@
|
||||
if (!this.SharedArrayBuffer)
|
||||
quit(0);
|
||||
|
||||
function m(stdlib, ffi, heap) {
|
||||
"use asm";
|
||||
var HEAP32 = new stdlib.SharedInt32Array(heap);
|
||||
var add = stdlib.Atomics.add;
|
||||
var load = stdlib.Atomics.load;
|
||||
function add_sharedEv(i1) {
|
||||
i1 = i1 | 0;
|
||||
load(HEAP32, i1 >> 2);
|
||||
add(HEAP32, i1 >> 2, 1);
|
||||
load(HEAP32, i1 >> 2);
|
||||
}
|
||||
return {add_sharedEv:add_sharedEv};
|
||||
}
|
||||
|
||||
if (isAsmJSCompilationAvailable())
|
||||
assertEq(isAsmJSModule(m), true);
|
||||
|
||||
var sab = new SharedArrayBuffer(65536);
|
||||
var {add_sharedEv} = m(this, {}, sab);
|
||||
add_sharedEv(sab.byteLength);
|
||||
@@ -168,7 +168,7 @@ assertAsmTypeFail('glob', 'ffis', 'b', SETUP + 'function f() { var i = 0; i32[((
|
||||
assertAsmTypeFail('glob', 'ffis', 'b', SETUP + 'function f() { var i = 0; i32[((i32[i>>2]|0) + (g()|0)) >> 2] = 0 } function g() { return 0 } return f');
|
||||
assertAsmTypeFail('glob', 'ffis', 'b', SETUP + 'function f() { var i = 0; i32[i >> 2] = (i32[i>>2]|0) + (g()|0) } function g() { return 0 } return f');
|
||||
if (isSimdAvailable() && typeof SIMD !== 'undefined')
|
||||
asmCompile('glob', 'ffis', 'b', USE_ASM + IMPORT2 + 'var i4 = glob.SIMD.int32x4; var add = i4.add;' + CHANGE_FUN + 'function f(i) { i=i|0; i32[i4(i,1,2,i).x >> 2]; i32[add(i4(0,0,0,0),i4(1,1,1,1)).x >> 2]; } return f');
|
||||
asmCompile('glob', 'ffis', 'b', USE_ASM + IMPORT2 + 'var i4 = glob.SIMD.Int32x4; var add = i4.add;' + CHANGE_FUN + 'function f(i) { i=i|0; i32[i4(i,1,2,i).x >> 2]; i32[add(i4(0,0,0,0),i4(1,1,1,1)).x >> 2]; } return f');
|
||||
|
||||
// Tests for constant heap accesses when change-heap is used
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ function assertEqX4(real, expected, assertFunc) {
|
||||
try {
|
||||
|
||||
// Load / Store
|
||||
var IMPORTS = USE_ASM + 'var H=new glob.Uint8Array(heap); var i4=glob.SIMD.int32x4; var ci4=i4.check; var load=i4.load; var store=i4.store;';
|
||||
var IMPORTS = USE_ASM + 'var H=new glob.Uint8Array(heap); var i4=glob.SIMD.Int32x4; var ci4=i4.check; var load=i4.load; var store=i4.store;';
|
||||
|
||||
// Bad number of args
|
||||
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load();} return f");
|
||||
@@ -45,7 +45,7 @@ assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0.;load(H
|
||||
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "var H2=new glob.Int32Array(heap); function f(){var i=0;load(H2, i)} return f");
|
||||
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "var H2=42; function f(){var i=0;load(H2, i)} return f");
|
||||
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0;load(H2, i)} return f");
|
||||
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "var f4=glob.SIMD.float32x4; function f(){var i=0;var vec=f4(1,2,3,4); store(H, i, vec)} return f");
|
||||
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "var f4=glob.SIMD.Float32x4; function f(){var i=0;var vec=f4(1,2,3,4); store(H, i, vec)} return f");
|
||||
|
||||
// Bad coercions of returned values
|
||||
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0;return load(H, i)|0;} return f");
|
||||
@@ -77,12 +77,12 @@ var loadStoreCode = `
|
||||
|
||||
var H = new glob.Uint8Array(heap);
|
||||
|
||||
var i4 = glob.SIMD.int32x4;
|
||||
var i4 = glob.SIMD.Int32x4;
|
||||
var i4load = i4.load;
|
||||
var i4store = i4.store;
|
||||
var ci4 = i4.check;
|
||||
|
||||
var f4 = glob.SIMD.float32x4;
|
||||
var f4 = glob.SIMD.Float32x4;
|
||||
var f4load = f4.load;
|
||||
var f4store = f4.store;
|
||||
var cf4 = f4.check;
|
||||
@@ -159,7 +159,7 @@ assertThrowsInstanceOf(() => f32l(SIZE - 3), RangeError);
|
||||
|
||||
var code = `
|
||||
"use asm";
|
||||
var f4 = glob.SIMD.float32x4;
|
||||
var f4 = glob.SIMD.Float32x4;
|
||||
var f4l = f4.load;
|
||||
var u8 = new glob.Uint8Array(heap);
|
||||
|
||||
@@ -183,8 +183,8 @@ assertThrowsInstanceOf(() => asmLink(asmCompile('glob', 'ffi', 'heap', code), th
|
||||
// Float32x4.store
|
||||
function f32s(n, v) { return m.f32s((n|0) << 2 | 0, v); };
|
||||
|
||||
var vec = SIMD.float32x4(5,6,7,8);
|
||||
var vec2 = SIMD.float32x4(0,1,2,3);
|
||||
var vec = SIMD.Float32x4(5,6,7,8);
|
||||
var vec2 = SIMD.Float32x4(0,1,2,3);
|
||||
|
||||
reset();
|
||||
f32s(0, vec);
|
||||
@@ -242,8 +242,8 @@ assertThrowsInstanceOf(() => i32(SIZE - 3), RangeError);
|
||||
// Int32x4.store
|
||||
function i32s(n, v) { return m.i32s((n|0) << 2 | 0, v); };
|
||||
|
||||
var vec = SIMD.int32x4(5,6,7,8);
|
||||
var vec2 = SIMD.int32x4(0,1,2,3);
|
||||
var vec = SIMD.Int32x4(5,6,7,8);
|
||||
var vec2 = SIMD.Int32x4(0,1,2,3);
|
||||
|
||||
reset();
|
||||
i32s(0, vec);
|
||||
@@ -488,26 +488,26 @@ function TestPartialStores(m, typedArray, typeName, x, y, z, w) {
|
||||
}
|
||||
|
||||
var f32 = new Float32Array(SIZE);
|
||||
var mfloat32x4 = asmLink(asmCompile('glob', 'ffi', 'heap', MakeCodeFor('float32x4')), this, null, f32.buffer);
|
||||
var mFloat32x4 = asmLink(asmCompile('glob', 'ffi', 'heap', MakeCodeFor('Float32x4')), this, null, f32.buffer);
|
||||
|
||||
TestPartialLoads(mfloat32x4, f32,
|
||||
TestPartialLoads(mFloat32x4, f32,
|
||||
(i) => i + 1,
|
||||
(i) => Math.fround(13.37),
|
||||
(i) => Math.fround(1/i),
|
||||
(i) => Math.fround(Math.sqrt(0x2000 - i)));
|
||||
|
||||
TestPartialStores(mfloat32x4, f32, 'float32x4', 42, -0, NaN, 0.1337);
|
||||
TestPartialStores(mFloat32x4, f32, 'Float32x4', 42, -0, NaN, 0.1337);
|
||||
|
||||
var i32 = new Int32Array(f32.buffer);
|
||||
var mint32x4 = asmLink(asmCompile('glob', 'ffi', 'heap', MakeCodeFor('int32x4')), this, null, i32.buffer);
|
||||
var mInt32x4 = asmLink(asmCompile('glob', 'ffi', 'heap', MakeCodeFor('Int32x4')), this, null, i32.buffer);
|
||||
|
||||
TestPartialLoads(mint32x4, i32,
|
||||
TestPartialLoads(mInt32x4, i32,
|
||||
(i) => i + 1 | 0,
|
||||
(i) => -i | 0,
|
||||
(i) => i * 2 | 0,
|
||||
(i) => 42);
|
||||
|
||||
TestPartialStores(mint32x4, i32, 'int32x4', 42, -3, 13, 37);
|
||||
TestPartialStores(mInt32x4, i32, 'Int32x4', 42, -3, 13, 37);
|
||||
|
||||
})();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
load(libdir + "asm.js");
|
||||
load(libdir + "asserts.js");
|
||||
var heap = new ArrayBuffer(0x10000);
|
||||
|
||||
// Set to true to see more JS debugging spew
|
||||
@@ -9,12 +10,12 @@ if (!isSimdAvailable() || typeof SIMD === 'undefined') {
|
||||
quit(0);
|
||||
}
|
||||
|
||||
const I32 = 'var i4 = glob.SIMD.int32x4;'
|
||||
const I32 = 'var i4 = glob.SIMD.Int32x4;'
|
||||
const CI32 = 'var ci4 = i4.check;'
|
||||
const I32A = 'var i4a = i4.add;'
|
||||
const I32S = 'var i4s = i4.sub;'
|
||||
const I32M = 'var i4m = i4.mul;'
|
||||
const F32 = 'var f4 = glob.SIMD.float32x4;'
|
||||
const F32 = 'var f4 = glob.SIMD.Float32x4;'
|
||||
const CF32 = 'var cf4 = f4.check;'
|
||||
const F32A = 'var f4a = f4.add;'
|
||||
const F32S = 'var f4s = f4.sub;'
|
||||
@@ -56,10 +57,10 @@ try {
|
||||
// 1. Constructors
|
||||
|
||||
// 1.1 Compilation
|
||||
assertAsmTypeFail('glob', USE_ASM + "var i4 = int32x4 ; return {}") ;
|
||||
assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.int32x4 ; return {}") ;
|
||||
assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.globglob.int32x4 ; return {}") ;
|
||||
assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.Math.int32x4 ; return {}") ;
|
||||
assertAsmTypeFail('glob', USE_ASM + "var i4 = Int32x4 ; return {}") ;
|
||||
assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.Int32x4 ; return {}") ;
|
||||
assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.globglob.Int32x4 ; return {}") ;
|
||||
assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.Math.Int32x4 ; return {}") ;
|
||||
assertAsmTypeFail('glob', USE_ASM + "var herd = glob.SIMD.ponyX4 ; return {}") ;
|
||||
|
||||
// 1.2 Linking
|
||||
@@ -67,22 +68,22 @@ assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: 42});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: Math.fround});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {int32x4: 42}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {int32x4: Math.fround}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {int32x4: new Array}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {int32x4: SIMD.float32x4}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: 42}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: Math.fround}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: new Array}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: SIMD.Float32x4}});
|
||||
|
||||
[Type, int32] = [TypedObject.StructType, TypedObject.int32];
|
||||
var MyStruct = new Type({'x': int32, 'y': int32, 'z': int32, 'w': int32});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {int32x4: MyStruct}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {int32x4: new MyStruct}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: MyStruct}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: new MyStruct}});
|
||||
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {} return f"), {SIMD:{int32x4: SIMD.int32x4}})(), undefined);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {} return f"), {SIMD:{Int32x4: SIMD.Int32x4}})(), undefined);
|
||||
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {float32x4: 42}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {float32x4: Math.fround}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {float32x4: new Array}});
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {} return f"), {SIMD:{float32x4: SIMD.float32x4}})(), undefined);
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {Float32x4: 42}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {Float32x4: Math.fround}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {Float32x4: new Array}});
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {} return f"), {SIMD:{Float32x4: SIMD.Float32x4}})(), undefined);
|
||||
|
||||
// 1.3 Correctness
|
||||
// 1.3.1 Local variables declarations
|
||||
@@ -158,7 +159,7 @@ function CheckSignMask(innerBody, coerceBefore, coerceAfter, expected) {
|
||||
var lanes = ['x', 'y', 'z', 'w'];
|
||||
for (var i = 0; i < lanes.length; i++) {
|
||||
var lane = lanes[i];
|
||||
var laneCheckCode = `"use asm"; var i4=glob.SIMD.int32x4; var f4=glob.SIMD.float32x4; function f() {${innerBody}; return ${coerceBefore}x.${lane}${coerceAfter} } return f;`;
|
||||
var laneCheckCode = `"use asm"; var i4=glob.SIMD.Int32x4; var f4=glob.SIMD.Float32x4; function f() {${innerBody}; return ${coerceBefore}x.${lane}${coerceAfter} } return f;`;
|
||||
assertEq(asmLink(asmCompile('glob', laneCheckCode), this)(), expected[i]);
|
||||
}
|
||||
}
|
||||
@@ -243,13 +244,13 @@ assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "function f() {var x=f4(1,2,3,4)
|
||||
|
||||
CheckF4('', 'var x=f4(1,2,3,4); var y=f4(4,3,2,1); x=3?y:x', [4, 3, 2, 1]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=x|0; var v=f4(1,2,3,4); var w=f4(5,6,7,8); return cf4(x?w:v);} return f"), this)(1), [5,6,7,8]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(v) {v=cf4(v); var w=f4(5,6,7,8); return cf4(4?w:v);} return f"), this)(SIMD.float32x4(1,2,3,4)), [5,6,7,8]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(v, x) {v=cf4(v); x=x|0; var w=f4(5,6,7,8); return cf4(x?w:v);} return f"), this)(SIMD.float32x4(1,2,3,4), 0), [1,2,3,4]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(v) {v=cf4(v); var w=f4(5,6,7,8); return cf4(4?w:v);} return f"), this)(SIMD.Float32x4(1,2,3,4)), [5,6,7,8]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(v, x) {v=cf4(v); x=x|0; var w=f4(5,6,7,8); return cf4(x?w:v);} return f"), this)(SIMD.Float32x4(1,2,3,4), 0), [1,2,3,4]);
|
||||
|
||||
CheckI4('', 'var x=i4(1,2,3,4); var y=i4(4,3,2,1); x=(x.x|0)?y:x', [4, 3, 2, 1]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=x|0; var v=i4(1,2,3,4); var w=i4(5,6,7,8); return ci4(x?w:v);} return f"), this)(1), [5,6,7,8]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(v) {v=ci4(v); var w=i4(5,6,7,8); return ci4(4?w:v);} return f"), this)(SIMD.int32x4(1,2,3,4)), [5,6,7,8]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(v, x) {v=ci4(v); x=x|0; var w=i4(5,6,7,8); return ci4(x?w:v);} return f"), this)(SIMD.int32x4(1,2,3,4), 0), [1,2,3,4]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(v) {v=ci4(v); var w=i4(5,6,7,8); return ci4(4?w:v);} return f"), this)(SIMD.Int32x4(1,2,3,4)), [5,6,7,8]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(v, x) {v=ci4(v); x=x|0; var w=i4(5,6,7,8); return ci4(x?w:v);} return f"), this)(SIMD.Int32x4(1,2,3,4), 0), [1,2,3,4]);
|
||||
|
||||
// 1.3.4 Return values
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {var x=1; return ci4(x)} return f");
|
||||
@@ -270,7 +271,7 @@ assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + "function f() {ci4(f32
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + CF32 + "function f(x) {x=cf4(x); ci4(x);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return 1 + ci4(x) | 0;} return f");
|
||||
|
||||
var i32x4 = SIMD.int32x4(1, 3, 3, 7);
|
||||
var i32x4 = SIMD.Int32x4(1, 3, 3, 7);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x)} return f"), this)(i32x4), undefined);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return ci4(x);} return f"), this)(i32x4), [1,3,3,7]);
|
||||
|
||||
@@ -282,7 +283,7 @@ assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + FROUND + "function f() {cf4(f32
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + F32 + CF32 + "function f(x) {x=cf4(x); cf4(x);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return 1 + cf4(x) | 0;} return f");
|
||||
|
||||
var f32x4 = SIMD.float32x4(13.37, 42.42, -0, NaN);
|
||||
var f32x4 = SIMD.Float32x4(13.37, 42.42, -0, NaN);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x)} return f"), this)(f32x4), undefined);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return cf4(x);} return f"), this)(f32x4), [13.37, 42.42, -0, NaN].map(Math.fround));
|
||||
|
||||
@@ -317,14 +318,14 @@ assertCaught(f);
|
||||
assertCaught(f, 1);
|
||||
assertCaught(f, {});
|
||||
assertCaught(f, "I sincerely am a SIMD typed object.");
|
||||
assertCaught(f, SIMD.int32x4(1,2,3,4));
|
||||
assertCaught(f, SIMD.Int32x4(1,2,3,4));
|
||||
|
||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return ci4(x);} return f"), this);
|
||||
assertCaught(f);
|
||||
assertCaught(f, 1);
|
||||
assertCaught(f, {});
|
||||
assertCaught(f, "I sincerely am a SIMD typed object.");
|
||||
assertCaught(f, SIMD.float32x4(4,3,2,1));
|
||||
assertCaught(f, SIMD.Float32x4(4,3,2,1));
|
||||
|
||||
// 1.3.6 Globals
|
||||
// 1.3.6.1 Local globals
|
||||
@@ -377,40 +378,40 @@ CheckF4('var x=f4(0,0,0,0); var y=42; var z=3.9; var w=13.37', 'x=f4(1,2,3,4); y
|
||||
|
||||
// 1.3.6.2 Imported globals
|
||||
// Read
|
||||
var int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {return ci4(g)} return f"), this, {g: SIMD.int32x4(1,2,3,4)})();
|
||||
assertEq(int32x4.x, 1);
|
||||
assertEq(int32x4.y, 2);
|
||||
assertEq(int32x4.z, 3);
|
||||
assertEq(int32x4.w, 4);
|
||||
var Int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {return ci4(g)} return f"), this, {g: SIMD.Int32x4(1,2,3,4)})();
|
||||
assertEq(Int32x4.x, 1);
|
||||
assertEq(Int32x4.y, 2);
|
||||
assertEq(Int32x4.z, 3);
|
||||
assertEq(Int32x4.w, 4);
|
||||
|
||||
for (var v of [1, {}, "totally legit SIMD variable", SIMD.float32x4(1,2,3,4)])
|
||||
for (var v of [1, {}, "totally legit SIMD variable", SIMD.Float32x4(1,2,3,4)])
|
||||
assertCaught(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {return ci4(g)} return f"), this, {g: v});
|
||||
|
||||
var float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {return cf4(g)} return f"), this, {g: SIMD.float32x4(1,2,3,4)})();
|
||||
assertEq(float32x4.x, 1);
|
||||
assertEq(float32x4.y, 2);
|
||||
assertEq(float32x4.z, 3);
|
||||
assertEq(float32x4.w, 4);
|
||||
var Float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {return cf4(g)} return f"), this, {g: SIMD.Float32x4(1,2,3,4)})();
|
||||
assertEq(Float32x4.x, 1);
|
||||
assertEq(Float32x4.y, 2);
|
||||
assertEq(Float32x4.z, 3);
|
||||
assertEq(Float32x4.w, 4);
|
||||
|
||||
for (var v of [1, {}, "totally legit SIMD variable", SIMD.int32x4(1,2,3,4)])
|
||||
for (var v of [1, {}, "totally legit SIMD variable", SIMD.Int32x4(1,2,3,4)])
|
||||
assertCaught(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {return cf4(g)} return f"), this, {g: v});
|
||||
|
||||
// Write
|
||||
var int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {g=i4(4,5,6,7); return ci4(g)} return f"), this, {g: SIMD.int32x4(1,2,3,4)})();
|
||||
assertEq(int32x4.x, 4);
|
||||
assertEq(int32x4.y, 5);
|
||||
assertEq(int32x4.z, 6);
|
||||
assertEq(int32x4.w, 7);
|
||||
var Int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {g=i4(4,5,6,7); return ci4(g)} return f"), this, {g: SIMD.Int32x4(1,2,3,4)})();
|
||||
assertEq(Int32x4.x, 4);
|
||||
assertEq(Int32x4.y, 5);
|
||||
assertEq(Int32x4.z, 6);
|
||||
assertEq(Int32x4.w, 7);
|
||||
|
||||
var float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {g=f4(4.,5.,6.,7.); return cf4(g)} return f"), this, {g: SIMD.float32x4(1,2,3,4)})();
|
||||
assertEq(float32x4.x, 4);
|
||||
assertEq(float32x4.y, 5);
|
||||
assertEq(float32x4.z, 6);
|
||||
assertEq(float32x4.w, 7);
|
||||
var Float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {g=f4(4.,5.,6.,7.); return cf4(g)} return f"), this, {g: SIMD.Float32x4(1,2,3,4)})();
|
||||
assertEq(Float32x4.x, 4);
|
||||
assertEq(Float32x4.y, 5);
|
||||
assertEq(Float32x4.z, 6);
|
||||
assertEq(Float32x4.w, 7);
|
||||
|
||||
// 2. SIMD operations
|
||||
// 2.1 Compilation
|
||||
assertAsmTypeFail('glob', USE_ASM + "var add = int32x4.add; return {}");
|
||||
assertAsmTypeFail('glob', USE_ASM + "var add = Int32x4.add; return {}");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32A + I32 + "return {}");
|
||||
assertAsmTypeFail('glob', USE_ASM + "var g = 3; var add = g.add; return {}");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "var func = i4.doTheHarlemShake; return {}");
|
||||
@@ -421,14 +422,14 @@ assertAsmTypeFail('glob', USE_ASM + "var f32 = glob.Math.fround; var i4a = f32.a
|
||||
assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + I32 + I32A + "function f() {} return f"), {});
|
||||
assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + I32 + I32A + "function f() {} return f"), {SIMD: Math.fround});
|
||||
|
||||
var oldInt32x4Add = SIMD.int32x4.add;
|
||||
var oldInt32x4Add = SIMD.Int32x4.add;
|
||||
var code = asmCompile('glob', USE_ASM + I32 + I32A + "return {}");
|
||||
for (var v of [42, Math.fround, SIMD.float32x4.add, function(){}, SIMD.int32x4.mul]) {
|
||||
SIMD.int32x4.add = v;
|
||||
assertAsmLinkFail(code, {SIMD: {int32x4: SIMD.int32x4}});
|
||||
for (var v of [42, Math.fround, SIMD.Float32x4.add, function(){}, SIMD.Int32x4.mul]) {
|
||||
SIMD.Int32x4.add = v;
|
||||
assertAsmLinkFail(code, {SIMD: {Int32x4: SIMD.Int32x4}});
|
||||
}
|
||||
SIMD.int32x4.add = oldInt32x4Add; // finally replace the add function with the original one
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + I32A + "function f() {} return f"), {SIMD: {int32x4: SIMD.int32x4}})(), undefined);
|
||||
SIMD.Int32x4.add = oldInt32x4Add; // finally replace the add function with the original one
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + I32A + "function f() {} return f"), {SIMD: {Int32x4: SIMD.Int32x4}})(), undefined);
|
||||
|
||||
// 2.3. Binary arithmetic operations
|
||||
// 2.3.1 Additions
|
||||
@@ -495,23 +496,23 @@ CheckF4(F32M, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [4,6,15,8]);
|
||||
CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [Math.fround(13.37) * 4,6,15,8]);
|
||||
CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=cf4(f4m(x,y))', [Math.fround(13.37) * 4,6,15,8]);
|
||||
|
||||
var f32x4 = SIMD.float32x4(0, NaN, -0, NaN);
|
||||
var another = SIMD.float32x4(NaN, -1, -0, NaN);
|
||||
var f32x4 = SIMD.Float32x4(0, NaN, -0, NaN);
|
||||
var another = SIMD.Float32x4(NaN, -1, -0, NaN);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32M + CF32 + "function f(x, y) {x=cf4(x); y=cf4(y); x=f4m(x,y); return cf4(x);} return f"), this)(f32x4, another), [NaN, NaN, 0, NaN]);
|
||||
|
||||
CheckF4(F32D, 'var x=f4(1,2,3,4); x=f4d(x,x)', [1,1,1,1]);
|
||||
CheckF4(F32D, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4d(x,y)', [1/4,2/3,3/5,2]);
|
||||
CheckF4(F32D, 'var x=f4(13.37,1,1,4); var y=f4(4,0,-0.,2); x=f4d(x,y)', [Math.fround(13.37) / 4,+Infinity,-Infinity,2]);
|
||||
|
||||
var f32x4 = SIMD.float32x4(0, 0, -0, NaN);
|
||||
var another = SIMD.float32x4(0, -0, 0, 0);
|
||||
var f32x4 = SIMD.Float32x4(0, 0, -0, NaN);
|
||||
var another = SIMD.Float32x4(0, -0, 0, 0);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32D + CF32 + "function f(x,y) {x=cf4(x); y=cf4(y); x=f4d(x,y); return cf4(x);} return f"), this)(f32x4, another), [NaN, NaN, NaN, NaN]);
|
||||
|
||||
// Unary arithmetic operators
|
||||
function CheckUnaryF4(op, checkFunc, assertFunc) {
|
||||
var _ = asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + 'var op=f4.' + op + '; function f(x){x=cf4(x); return cf4(op(x)); } return f'), this);
|
||||
return function(input) {
|
||||
var simd = SIMD.float32x4(input[0], input[1], input[2], input[3]);
|
||||
var simd = SIMD.Float32x4(input[0], input[1], input[2], input[3]);
|
||||
|
||||
var exp = input.map(Math.fround).map(checkFunc).map(Math.fround);
|
||||
var obs = _(simd);
|
||||
@@ -522,7 +523,7 @@ function CheckUnaryF4(op, checkFunc, assertFunc) {
|
||||
function CheckUnaryI4(op, checkFunc) {
|
||||
var _ = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + 'var op=i4.' + op + '; function f(x){x=ci4(x); return ci4(op(x)); } return f'), this);
|
||||
return function(input) {
|
||||
var simd = SIMD.int32x4(input[0], input[1], input[2], input[3]);
|
||||
var simd = SIMD.Int32x4(input[0], input[1], input[2], input[3]);
|
||||
assertEqX4(_(simd), input.map(checkFunc).map(function(x) { return x | 0}));
|
||||
}
|
||||
}
|
||||
@@ -608,37 +609,34 @@ CheckF4(F32MAXNUM, 'var x=f4(0,0,-0,-0); var y=f4(0,-0,0,-0); x=max(x,y)', [0,0,
|
||||
CheckF4(F32MAXNUM + FROUND + 'var NaN = glob.NaN;', 'var x=f4(0,0,0,0); var y=f4(0,0,0,0); var n=f32(0); n=f32(NaN); x=f4(n,0.,n,0.); y=f4(n,n,0.,0.); x=max(x,y)', [NaN, 0, 0, 0]);
|
||||
|
||||
// With
|
||||
const WXF = 'var w = f4.withX;';
|
||||
const WYF = 'var w = f4.withY;';
|
||||
const WZF = 'var w = f4.withZ;';
|
||||
const WWF = 'var w = f4.withW;';
|
||||
const RLF = 'var r = f4.replaceLane;';
|
||||
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + "function f() {var x = f4(1,2,3,4); x = w(x, 1);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + "function f() {var x = f4(1,2,3,4); x = w(x, x);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); x = w(1, f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); x = w(1., f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); x = w(f32(1), f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); var y = i4(1,2,3,4); x = w(y, f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + "function f() {var x = f4(1,2,3,4); x = r(x, 0, 1);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + "function f() {var x = f4(1,2,3,4); x = r(x, 0, x);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(x, 4, f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(x, f32(0), f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(1, 0, f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(1, 0., f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(f32(1), 0, f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); var l = 0; x = r(x, l, f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); var y = i4(1,2,3,4); x = r(y, 0, f32(1));} return f");
|
||||
|
||||
CheckF4(WXF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [Math.fround(13.37), 2, 3, 4]);
|
||||
CheckF4(WYF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [1, Math.fround(13.37), 3, 4]);
|
||||
CheckF4(WZF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [1, 2, Math.fround(13.37), 4]);
|
||||
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [1, 2, 3, Math.fround(13.37)]);
|
||||
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37) + f32(6.63));', [1, 2, 3, Math.fround(Math.fround(13.37) + Math.fround(6.63))]);
|
||||
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 0, f32(13.37));', [Math.fround(13.37), 2, 3, 4]);
|
||||
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 1, f32(13.37));', [1, Math.fround(13.37), 3, 4]);
|
||||
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 2, f32(13.37));', [1, 2, Math.fround(13.37), 4]);
|
||||
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, f32(13.37));', [1, 2, 3, Math.fround(13.37)]);
|
||||
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, f32(13.37) + f32(6.63));', [1, 2, 3, Math.fround(Math.fround(13.37) + Math.fround(6.63))]);
|
||||
|
||||
CheckF4(WXF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [Math.fround(13.37), 2, 3, 4]);
|
||||
CheckF4(WYF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [1, Math.fround(13.37), 3, 4]);
|
||||
CheckF4(WZF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [1, 2, Math.fround(13.37), 4]);
|
||||
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [1, 2, 3, Math.fround(13.37)]);
|
||||
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 0, 13.37);', [Math.fround(13.37), 2, 3, 4]);
|
||||
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 1, 13.37);', [1, Math.fround(13.37), 3, 4]);
|
||||
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 2, 13.37);', [1, 2, Math.fround(13.37), 4]);
|
||||
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, 13.37);', [1, 2, 3, Math.fround(13.37)]);
|
||||
|
||||
const WXI = 'var w = i4.withX;';
|
||||
const WYI = 'var w = i4.withY;';
|
||||
const WZI = 'var w = i4.withZ;';
|
||||
const WWI = 'var w = i4.withW;';
|
||||
CheckI4(WXI, 'var x = i4(1,2,3,4); x = w(x, 42);', [42, 2, 3, 4]);
|
||||
CheckI4(WYI, 'var x = i4(1,2,3,4); x = w(x, 42);', [1, 42, 3, 4]);
|
||||
CheckI4(WZI, 'var x = i4(1,2,3,4); x = w(x, 42);', [1, 2, 42, 4]);
|
||||
CheckI4(WWI, 'var x = i4(1,2,3,4); x = w(x, 42);', [1, 2, 3, 42]);
|
||||
const RLI = 'var r = i4.replaceLane;';
|
||||
CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 0, 42);', [42, 2, 3, 4]);
|
||||
CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 1, 42);', [1, 42, 3, 4]);
|
||||
CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 2, 42);', [1, 2, 42, 4]);
|
||||
CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 3, 42);', [1, 2, 3, 42]);
|
||||
|
||||
// Comparisons
|
||||
// True yields all bits set to 1 (i.e as an int32, 0xFFFFFFFF === -1), false
|
||||
@@ -726,17 +724,22 @@ assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=i4(
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=f4(1,2,3,4); x=cvt(x);} return f");
|
||||
|
||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + CI32 + CVTIF + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); y=cvt(x); return cf4(y);} return f'), this);
|
||||
assertEqX4(f(SIMD.int32x4(1,2,3,4)), [1, 2, 3, 4]);
|
||||
assertEqX4(f(SIMD.int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, Math.fround(INT32_MIN), Math.fround(INT32_MAX), -1]);
|
||||
assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4]);
|
||||
assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, Math.fround(INT32_MIN), Math.fround(INT32_MAX), -1]);
|
||||
|
||||
// TODO amend tests once int32x4.fromFloat32x4 is fully specified, when float
|
||||
// values can't be converted into an int32 without overflowing. In these
|
||||
// tests, we assume x86/x64, so a conversion which failed will return the
|
||||
// undefined int32 value. See also bug 1068028.
|
||||
const UNDEFINED_INT32 = 0x80000000 | 0;
|
||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + CVTFI + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); y=cvt(x); return ci4(y);} return f'), this);
|
||||
assertEqX4(f(SIMD.float32x4(1,2,3,4)), [1, 2, 3, 4]);
|
||||
assertEqX4(f(SIMD.float32x4(NaN,Infinity,-Infinity,-0)), [UNDEFINED_INT32, UNDEFINED_INT32, UNDEFINED_INT32, 0]);
|
||||
assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4]);
|
||||
// Test that INT32_MIN (exactly representable as an float32) and the first
|
||||
// integer representable as an float32 can be converted.
|
||||
assertEqX4(f(SIMD.Float32x4(INT32_MIN, INT32_MAX - 64, -0, 0)), [INT32_MIN, INT32_MAX - 64, 0, 0].map(Math.fround));
|
||||
// Test boundaries: first integer less than INT32_MIN and representable as a float32
|
||||
assertThrowsInstanceOf(() => f(SIMD.Float32x4(INT32_MIN - 129, 0, 0, 0)), RangeError);
|
||||
// INT_MAX + 1
|
||||
assertThrowsInstanceOf(() => f(SIMD.Float32x4(Math.pow(2, 31), 0, 0, 0)), RangeError);
|
||||
// Special values
|
||||
assertThrowsInstanceOf(() => f(SIMD.Float32x4(NaN, 0, 0, 0)), RangeError);
|
||||
assertThrowsInstanceOf(() => f(SIMD.Float32x4(Infinity, 0, 0, 0)), RangeError);
|
||||
assertThrowsInstanceOf(() => f(SIMD.Float32x4(-Infinity, 0, 0, 0)), RangeError);
|
||||
|
||||
// Cast operators
|
||||
const CVTIFB = 'var cvt=f4.fromInt32x4Bits;';
|
||||
@@ -768,20 +771,20 @@ assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIFB + "function f() {var x=i4
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIFB + "function f() {var x=f4(1,2,3,4); x=cvt(x);} return f");
|
||||
|
||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CVTIFB + CF32 + CI32 + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); y=cvt(x); return cf4(y);} return f'), this);
|
||||
assertEqX4(f(SIMD.int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits));
|
||||
assertEqX4(f(SIMD.int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits));
|
||||
assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits));
|
||||
assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits));
|
||||
|
||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32A + CVTIFB + CF32 + CI32 + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); var z=f4(1,1,1,1); y=cvt(x); y=f4a(y, z); return cf4(y)} return f'), this);
|
||||
assertEqX4(f(SIMD.int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits).map((x) => x+1));
|
||||
assertEqX4(f(SIMD.int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits).map((x) => x+1));
|
||||
assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits).map((x) => x+1));
|
||||
assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits).map((x) => x+1));
|
||||
|
||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + CVTFIB + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); y=cvt(x); return ci4(y);} return f'), this);
|
||||
assertEqX4(f(SIMD.float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits));
|
||||
assertEqX4(f(SIMD.float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits));
|
||||
assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits));
|
||||
assertEqX4(f(SIMD.Float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits));
|
||||
|
||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + I32A + CVTFIB + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); var z=i4(1,1,1,1); y=cvt(x); y=i4a(y,z); return ci4(y);} return f'), this);
|
||||
assertEqX4(f(SIMD.float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits).map((x) => x+1));
|
||||
assertEqX4(f(SIMD.float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits).map((x) => x+1));
|
||||
assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits).map((x) => x+1));
|
||||
assertEqX4(f(SIMD.Float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits).map((x) => x+1));
|
||||
|
||||
// Bitwise ops
|
||||
const ANDI32 = 'var andd=i4.and;';
|
||||
@@ -905,37 +908,37 @@ assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32BSEL + "fu
|
||||
|
||||
// Specific bitselect tests
|
||||
var masks = [
|
||||
SIMD.int32x4(1337, 0x1337, 0x42, 42),
|
||||
SIMD.int32x4(0x00FF1CE, 0xBAADF00D, 0xDEADBEEF, 0xCAFED00D),
|
||||
SIMD.int32x4(0xD15EA5E, 0xDEADC0DE, 0xFACEB00C, 0x4B1D4B1D)
|
||||
SIMD.Int32x4(1337, 0x1337, 0x42, 42),
|
||||
SIMD.Int32x4(0x00FF1CE, 0xBAADF00D, 0xDEADBEEF, 0xCAFED00D),
|
||||
SIMD.Int32x4(0xD15EA5E, 0xDEADC0DE, 0xFACEB00C, 0x4B1D4B1D)
|
||||
];
|
||||
|
||||
var simdToArray = (vec) => [vec.x, vec.y, vec.z, vec.w];
|
||||
|
||||
var inputs = [
|
||||
[SIMD.int32x4(0,4,9,16), SIMD.int32x4(1,2,3,4)],
|
||||
[SIMD.int32x4(-1, 2, INT32_MAX, INT32_MIN), SIMD.int32x4(INT32_MAX, -4, INT32_MIN, 42)]
|
||||
[SIMD.Int32x4(0,4,9,16), SIMD.Int32x4(1,2,3,4)],
|
||||
[SIMD.Int32x4(-1, 2, INT32_MAX, INT32_MIN), SIMD.Int32x4(INT32_MAX, -4, INT32_MIN, 42)]
|
||||
];
|
||||
|
||||
var i32bsel = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32BSEL + "function f(mask, ifTrue, ifFalse) {mask=ci4(mask); ifTrue=ci4(ifTrue); ifFalse=ci4(ifFalse); return ci4(i4sel(mask,ifTrue,ifFalse)); } return f"), this)
|
||||
|
||||
for (var mask of masks) {
|
||||
for (var [x, y] of inputs) {
|
||||
assertEqX4(i32bsel(mask, x, y), simdToArray(SIMD.int32x4.bitselect(mask, x, y)));
|
||||
assertEqX4(i32bsel(mask, x, y), simdToArray(SIMD.Int32x4.bitselect(mask, x, y)));
|
||||
}
|
||||
}
|
||||
|
||||
inputs = [
|
||||
[SIMD.float32x4(0.125,4.25,9.75,16.125), SIMD.float32x4(1.5,2.75,3.25,4.5)],
|
||||
[SIMD.float32x4(-1.5,-0,NaN,-Infinity), SIMD.float32x4(1,-2,13.37,3.13)],
|
||||
[SIMD.float32x4(1.5,2.75,NaN,Infinity), SIMD.float32x4(-NaN,-Infinity,9.75,16.125)]
|
||||
[SIMD.Float32x4(0.125,4.25,9.75,16.125), SIMD.Float32x4(1.5,2.75,3.25,4.5)],
|
||||
[SIMD.Float32x4(-1.5,-0,NaN,-Infinity), SIMD.Float32x4(1,-2,13.37,3.13)],
|
||||
[SIMD.Float32x4(1.5,2.75,NaN,Infinity), SIMD.Float32x4(-NaN,-Infinity,9.75,16.125)]
|
||||
];
|
||||
|
||||
var f32bsel = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CI32 + CF32 + F32BSEL + "function f(mask, ifTrue, ifFalse) {mask=ci4(mask); ifTrue=cf4(ifTrue); ifFalse=cf4(ifFalse); return cf4(f4sel(mask,ifTrue,ifFalse)); } return f"), this)
|
||||
|
||||
for (var mask of masks)
|
||||
for (var [x, y] of inputs)
|
||||
assertEqX4(f32bsel(mask, x, y), simdToArray(SIMD.float32x4.bitselect(mask, x, y)));
|
||||
assertEqX4(f32bsel(mask, x, y), simdToArray(SIMD.Float32x4.bitselect(mask, x, y)));
|
||||
|
||||
// Splat
|
||||
const I32SPLAT = 'var splat=i4.splat;'
|
||||
@@ -1114,7 +1117,7 @@ var code = USE_ASM + I32 + CI32 + I32A + `
|
||||
return f;
|
||||
`;
|
||||
|
||||
var v4 = SIMD.int32x4(1,2,3,4);
|
||||
var v4 = SIMD.Int32x4(1,2,3,4);
|
||||
function check(x, y, z, w) {
|
||||
assertEq(x, 35);
|
||||
assertEq(y, 35);
|
||||
@@ -1165,7 +1168,7 @@ for (var i = 1; i < 10; ++i) {
|
||||
// Stress-test for register spilling code and stack depth checks
|
||||
var code = `
|
||||
"use asm";
|
||||
var i4 = glob.SIMD.int32x4;
|
||||
var i4 = glob.SIMD.Int32x4;
|
||||
var i4a = i4.add;
|
||||
var assertEq = ffi.assertEq;
|
||||
function g() {
|
||||
@@ -1185,7 +1188,7 @@ asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)();
|
||||
(function() {
|
||||
var code = `
|
||||
"use asm";
|
||||
var i4 = glob.SIMD.int32x4;
|
||||
var i4 = glob.SIMD.Int32x4;
|
||||
var i4a = i4.add;
|
||||
var assertEq = ffi.assertEq;
|
||||
var one = ffi.one;
|
||||
@@ -1227,7 +1230,7 @@ asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)();
|
||||
(function() {
|
||||
var code = `
|
||||
"use asm";
|
||||
var i4 = glob.SIMD.int32x4;
|
||||
var i4 = glob.SIMD.Int32x4;
|
||||
var ci4 = i4.check;
|
||||
function h(
|
||||
// In registers:
|
||||
@@ -1285,7 +1288,7 @@ asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)();
|
||||
var iters = 2000000;
|
||||
var code = `
|
||||
"use asm";
|
||||
var i4 = glob.SIMD.int32x4;
|
||||
var i4 = glob.SIMD.Int32x4;
|
||||
var i4a = i4.add;
|
||||
var ci4 = i4.check;
|
||||
function _() {
|
||||
@@ -1313,4 +1316,3 @@ asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)();
|
||||
print('Error:', e)
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
@@ -209,10 +209,10 @@ function testSimdX4(ctor, shift, scale, disp, simdName, simdCtor) {
|
||||
}
|
||||
|
||||
function testFloat32x4(ctor, shift, scale, disp) {
|
||||
testSimdX4(ctor, shift, scale, disp, 'float32x4', SIMD.float32x4);
|
||||
testSimdX4(ctor, shift, scale, disp, 'Float32x4', SIMD.Float32x4);
|
||||
}
|
||||
function testInt32x4(ctor, shift, scale, disp) {
|
||||
testSimdX4(ctor, shift, scale, disp, 'int32x4', SIMD.int32x4);
|
||||
testSimdX4(ctor, shift, scale, disp, 'Int32x4', SIMD.Int32x4);
|
||||
}
|
||||
|
||||
function test(tester, ctor, shift) {
|
||||
|
||||
@@ -139,7 +139,7 @@ assertEq(a.y, 2);
|
||||
|
||||
// defaults are evaluated even if there is no binding
|
||||
var evaled = false;
|
||||
({a: {} = (evaled = true, null)}) = {};
|
||||
({a: {} = (evaled = true, {})}) = {};
|
||||
assertEq(evaled, true);
|
||||
evaled = false;
|
||||
assertThrowsInstanceOf(() => { [[] = (evaled = true, 2)] = [] }, TypeError);
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
load(libdir + 'asserts.js');
|
||||
load(libdir + 'iteration.js');
|
||||
|
||||
function f(v)
|
||||
{
|
||||
if (v + "")
|
||||
({} = v);
|
||||
}
|
||||
|
||||
f(true);
|
||||
f({});
|
||||
assertThrowsInstanceOf(() => f(null), TypeError);
|
||||
assertThrowsInstanceOf(() => f(undefined), TypeError);
|
||||
|
||||
function g(v)
|
||||
{
|
||||
if (v + "")
|
||||
({} = v);
|
||||
}
|
||||
|
||||
g(true);
|
||||
g({});
|
||||
assertThrowsInstanceOf(() => g(undefined), TypeError);
|
||||
assertThrowsInstanceOf(() => g(null), TypeError);
|
||||
|
||||
function h(v)
|
||||
{
|
||||
if (v + "")
|
||||
([] = v);
|
||||
}
|
||||
|
||||
h([true]);
|
||||
h("foo");
|
||||
assertThrowsInstanceOf(() => h(undefined), TypeError);
|
||||
assertThrowsInstanceOf(() => h(null), TypeError);
|
||||
|
||||
Object.defineProperty(Boolean.prototype, "v",
|
||||
{ get() { "use strict"; return typeof this; },
|
||||
enumerable: true,
|
||||
configurable: true });
|
||||
|
||||
Object.defineProperty(Number.prototype, "v",
|
||||
{ get() { "use strict"; return typeof this; },
|
||||
enumerable: true,
|
||||
configurable: true });
|
||||
|
||||
Object.defineProperty(String.prototype, "v",
|
||||
{ get() { "use strict"; return typeof this; },
|
||||
enumerable: true,
|
||||
configurable: true });
|
||||
|
||||
Object.defineProperty(Symbol.prototype, "v",
|
||||
{ get() { "use strict"; return typeof this; },
|
||||
enumerable: true,
|
||||
configurable: true });
|
||||
|
||||
function primitiveThisSupported()
|
||||
{
|
||||
return 3.14.custom === "number";
|
||||
}
|
||||
|
||||
function primitiveThisTests()
|
||||
{
|
||||
function f(v)
|
||||
{
|
||||
var type = typeof v;
|
||||
|
||||
({ v } = v);
|
||||
|
||||
assertEq(v, type);
|
||||
}
|
||||
|
||||
f(true);
|
||||
f(3.14);
|
||||
f(72);
|
||||
f("ohai");
|
||||
f(Symbol.iterator);
|
||||
|
||||
assertThrowsInstanceOf(() => f(undefined), TypeError);
|
||||
assertThrowsInstanceOf(() => f(null), TypeError);
|
||||
|
||||
function g(v)
|
||||
{
|
||||
var type = typeof v;
|
||||
|
||||
({ v } = v);
|
||||
|
||||
assertEq(v, type);
|
||||
}
|
||||
|
||||
g(true);
|
||||
g(3.14);
|
||||
g(72);
|
||||
g("ohai");
|
||||
g(Symbol.iterator);
|
||||
|
||||
assertThrowsInstanceOf(() => g(null), TypeError);
|
||||
assertThrowsInstanceOf(() => g(undefined), TypeError);
|
||||
}
|
||||
if (primitiveThisSupported())
|
||||
primitiveThisTests();
|
||||
|
||||
// Ensure the internal implementation of destructuring object pattern
|
||||
// assignment -- using a self-hosted intrinsic function -- works even when lazy
|
||||
// standard class initialization hasn't occurred. Unfortunately we can't use
|
||||
// |newGlobal()| because that method eagerly initializes standard classes.
|
||||
evalcx("({} = 1);", evalcx("lazy"));
|
||||
@@ -101,12 +101,27 @@ check("o[- (o)]");
|
||||
// A few one off tests
|
||||
check_one("6", (function () { 6() }), " is not a function");
|
||||
check_one("0", (function () { Array.prototype.reverse.call('123'); }), " is read-only");
|
||||
check_one(`(intermediate value)[Symbol.iterator](...).next(...).value`,
|
||||
function () { var [{ x }] = [null, {}]; }, " is null");
|
||||
check_one(`(intermediate value)[Symbol.iterator](...).next(...).value`,
|
||||
check_one("(intermediate value)[Symbol.iterator](...).next(...).value",
|
||||
function () { ieval("{ let x; var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined");
|
||||
check_one("void 1", function() { (void 1)(); }, " is not a function");
|
||||
check_one("void o[1]", function() { var o = []; (void o[1])() }, " is not a function");
|
||||
|
||||
// Manual testing for this case: the only way to trigger an error is *not* on
|
||||
// an attempted property access during destructuring, and the error message
|
||||
// invoking ToObject(null) is different: "can't convert {0} to object".
|
||||
try
|
||||
{
|
||||
(function() {
|
||||
var [{x}] = [null, {}];
|
||||
})();
|
||||
throw new Error("didn't throw");
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
assertEq(e instanceof TypeError, true,
|
||||
"expected TypeError, got " + e);
|
||||
assertEq(e.message, "can't convert null to object");
|
||||
}
|
||||
|
||||
// Check fallback behavior
|
||||
assertThrowsInstanceOf(function () { for (let x of undefined) {} }, TypeError);
|
||||
|
||||
@@ -76,7 +76,6 @@ test("new RegExp('1')", r => assertEq("a1".search(r), 1));
|
||||
test("new RegExp('1')", r => assertEq("a1".match(r)[0], '1'));
|
||||
test("new RegExp('1')", r => assertEq("a1".replace(r, 'A'), 'aA'));
|
||||
test("new RegExp('1')", r => assertEq(String("a1b".split(r)), "a,b"));
|
||||
test("new RegExp('1')", r => assertEq(r, RegExp(r)));
|
||||
test("new RegExp('1')", r => assertEq(String(new RegExp(r)), String(r)));
|
||||
test("new RegExp('1')", r => assertEq(String(/x/.compile(r)), String(r)));
|
||||
test("new WeakMap()", w => WeakMap.prototype.has.call(w, {}));
|
||||
|
||||
@@ -5,22 +5,22 @@ var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
|
||||
g.eval(`
|
||||
function withTypedArrayOnStack(f) {
|
||||
function withAllocationMarkerOnStack(f) {
|
||||
(function () {
|
||||
var onStack = new Int8Array();
|
||||
var onStack = allocationMarker();
|
||||
f();
|
||||
}())
|
||||
}
|
||||
`);
|
||||
|
||||
assertEq("Int8Array" in dbg.memory.takeCensus().objects, false,
|
||||
"There shouldn't exist any typed arrays in the census.");
|
||||
assertEq("AllocationMarker" in dbg.memory.takeCensus().objects, false,
|
||||
"There shouldn't exist any allocation markers in the census.");
|
||||
|
||||
var typedArrayCount;
|
||||
g.withTypedArrayOnStack(() => {
|
||||
typedArrayCount = dbg.memory.takeCensus().objects.Int8Array.count;
|
||||
var allocationMarkerCount;
|
||||
g.withAllocationMarkerOnStack(() => {
|
||||
allocationMarkerCount = dbg.memory.takeCensus().objects.AllocationMarker.count;
|
||||
});
|
||||
|
||||
assertEq(typedArrayCount, 1,
|
||||
"Should have one typed array in the census, because there " +
|
||||
assertEq(allocationMarkerCount, 1,
|
||||
"Should have one allocation marker in the census, because there " +
|
||||
"was one on the stack.");
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
|
||||
assertEq("Int8Array" in dbg.memory.takeCensus().objects, false,
|
||||
"There shouldn't exist any typed arrays in the census.");
|
||||
assertEq("AllocationMarker" in dbg.memory.takeCensus().objects, false,
|
||||
"There shouldn't exist any allocation markers in the census.");
|
||||
|
||||
this.ccw = g.eval("new Int8Array()");
|
||||
this.ccw = g.allocationMarker();
|
||||
|
||||
assertEq(dbg.memory.takeCensus().objects.Int8Array.count, 1,
|
||||
"Should have one typed array in the census, because there " +
|
||||
"is one cross-compartment wrapper.");
|
||||
assertEq(dbg.memory.takeCensus().objects.AllocationMarker.count, 1,
|
||||
"Should have one allocation marker in the census, because there " +
|
||||
"is one cross-compartment wrapper referring to it.");
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
// Check Debugger.Memory.prototype.takeCensus handling of 'breakdown' argument.
|
||||
|
||||
load(libdir + 'match.js');
|
||||
var Pattern = Match.Pattern;
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
|
||||
Pattern({ count: Pattern.NATURAL,
|
||||
bytes: Pattern.NATURAL })
|
||||
.assert(dbg.memory.takeCensus({ breakdown: { by: 'count' } }));
|
||||
|
||||
let census = dbg.memory.takeCensus({ breakdown: { by: 'count', count: false, bytes: false } });
|
||||
assertEq('count' in census, false);
|
||||
assertEq('bytes' in census, false);
|
||||
|
||||
let census = dbg.memory.takeCensus({ breakdown: { by: 'count', count: true, bytes: false } });
|
||||
assertEq('count' in census, true);
|
||||
assertEq('bytes' in census, false);
|
||||
|
||||
let census = dbg.memory.takeCensus({ breakdown: { by: 'count', count: false, bytes: true } });
|
||||
assertEq('count' in census, false);
|
||||
assertEq('bytes' in census, true);
|
||||
|
||||
let census = dbg.memory.takeCensus({ breakdown: { by: 'count', count: true, bytes: true } });
|
||||
assertEq('count' in census, true);
|
||||
assertEq('bytes' in census, true);
|
||||
|
||||
|
||||
// Pattern doesn't mind objects with extra properties, so we'll restrict this
|
||||
// list to the object classes we're pretty sure are going to stick around for
|
||||
// the forseeable future.
|
||||
Pattern({
|
||||
Function: { count: Pattern.NATURAL },
|
||||
Object: { count: Pattern.NATURAL },
|
||||
Debugger: { count: Pattern.NATURAL },
|
||||
global: { count: Pattern.NATURAL },
|
||||
|
||||
// The below are all Debugger prototype objects.
|
||||
Source: { count: Pattern.NATURAL },
|
||||
Environment: { count: Pattern.NATURAL },
|
||||
Script: { count: Pattern.NATURAL },
|
||||
Memory: { count: Pattern.NATURAL },
|
||||
Frame: { count: Pattern.NATURAL }
|
||||
})
|
||||
.assert(dbg.memory.takeCensus({ breakdown: { by: 'objectClass' } }));
|
||||
|
||||
Pattern({
|
||||
objects: { count: Pattern.NATURAL },
|
||||
scripts: { count: Pattern.NATURAL },
|
||||
strings: { count: Pattern.NATURAL },
|
||||
other: { count: Pattern.NATURAL }
|
||||
})
|
||||
.assert(dbg.memory.takeCensus({ breakdown: { by: 'coarseType' } }));
|
||||
|
||||
// As for { by: 'objectClass' }, restrict our pattern to the types
|
||||
// we predict will stick around for a long time.
|
||||
Pattern({
|
||||
JSString: { count: Pattern.NATURAL },
|
||||
'js::Shape': { count: Pattern.NATURAL },
|
||||
JSObject: { count: Pattern.NATURAL },
|
||||
JSScript: { count: Pattern.NATURAL }
|
||||
})
|
||||
.assert(dbg.memory.takeCensus({ breakdown: { by: 'internalType' } }));
|
||||
|
||||
|
||||
// Nested breakdowns.
|
||||
|
||||
let coarse_type_pattern = {
|
||||
objects: { count: Pattern.NATURAL },
|
||||
scripts: { count: Pattern.NATURAL },
|
||||
strings: { count: Pattern.NATURAL },
|
||||
other: { count: Pattern.NATURAL }
|
||||
};
|
||||
|
||||
Pattern({
|
||||
JSString: coarse_type_pattern,
|
||||
'js::Shape': coarse_type_pattern,
|
||||
JSObject: coarse_type_pattern,
|
||||
JSScript: coarse_type_pattern,
|
||||
})
|
||||
.assert(dbg.memory.takeCensus({
|
||||
breakdown: { by: 'internalType',
|
||||
then: { by: 'coarseType' }
|
||||
}
|
||||
}));
|
||||
|
||||
Pattern({
|
||||
Function: { count: Pattern.NATURAL },
|
||||
Object: { count: Pattern.NATURAL },
|
||||
Debugger: { count: Pattern.NATURAL },
|
||||
global: { count: Pattern.NATURAL },
|
||||
other: coarse_type_pattern
|
||||
})
|
||||
.assert(dbg.memory.takeCensus({
|
||||
breakdown: {
|
||||
by: 'objectClass',
|
||||
then: { by: 'count' },
|
||||
other: { by: 'coarseType' }
|
||||
}
|
||||
}));
|
||||
|
||||
Pattern({
|
||||
objects: { count: Pattern.NATURAL, label: "object" },
|
||||
scripts: { count: Pattern.NATURAL, label: "scripts" },
|
||||
strings: { count: Pattern.NATURAL, label: "strings" },
|
||||
other: { count: Pattern.NATURAL, label: "other" }
|
||||
})
|
||||
.assert(dbg.memory.takeCensus({
|
||||
breakdown: {
|
||||
by: 'coarseType',
|
||||
objects: { by: 'count', label: 'object' },
|
||||
scripts: { by: 'count', label: 'scripts' },
|
||||
strings: { by: 'count', label: 'strings' },
|
||||
other: { by: 'count', label: 'other' }
|
||||
}
|
||||
}));
|
||||
@@ -0,0 +1,75 @@
|
||||
// Debugger.Memory.prototype.takeCensus breakdown: check error handling on
|
||||
// property gets.
|
||||
|
||||
load(libdir + 'asserts.js');
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
|
||||
assertThrowsValue(() => {
|
||||
dbg.memory.takeCensus({
|
||||
breakdown: { get by() { throw "ಠ_ಠ" } }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
|
||||
|
||||
assertThrowsValue(() => {
|
||||
dbg.memory.takeCensus({
|
||||
breakdown: { by: 'count', get count() { throw "ಠ_ಠ" } }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
assertThrowsValue(() => {
|
||||
dbg.memory.takeCensus({
|
||||
breakdown: { by: 'count', get bytes() { throw "ಠ_ಠ" } }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
|
||||
|
||||
assertThrowsValue(() => {
|
||||
dbg.memory.takeCensus({
|
||||
breakdown: { by: 'objectClass', get then() { throw "ಠ_ಠ" } }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
assertThrowsValue(() => {
|
||||
dbg.memory.takeCensus({
|
||||
breakdown: { by: 'objectClass', get other() { throw "ಠ_ಠ" } }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
|
||||
|
||||
assertThrowsValue(() => {
|
||||
dbg.memory.takeCensus({
|
||||
breakdown: { by: 'coarseType', get objects() { throw "ಠ_ಠ" } }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
assertThrowsValue(() => {
|
||||
dbg.memory.takeCensus({
|
||||
breakdown: { by: 'coarseType', get scripts() { throw "ಠ_ಠ" } }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
assertThrowsValue(() => {
|
||||
dbg.memory.takeCensus({
|
||||
breakdown: { by: 'coarseType', get strings() { throw "ಠ_ಠ" } }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
assertThrowsValue(() => {
|
||||
dbg.memory.takeCensus({
|
||||
breakdown: { by: 'coarseType', get other() { throw "ಠ_ಠ" } }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
|
||||
|
||||
assertThrowsValue(() => {
|
||||
dbg.memory.takeCensus({
|
||||
breakdown: { by: 'internalType', get then() { throw "ಠ_ಠ" } }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
@@ -0,0 +1,73 @@
|
||||
// Debugger.Memory.prototype.takeCensus: test by: 'count' breakdown
|
||||
|
||||
let g = newGlobal();
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
g.eval(`
|
||||
var stuff = [];
|
||||
function add(n, c) {
|
||||
for (let i = 0; i < n; i++)
|
||||
stuff.push(c());
|
||||
}
|
||||
|
||||
let count = 0;
|
||||
|
||||
function obj() { return { count: count++ }; }
|
||||
obj.factor = 1;
|
||||
|
||||
// This creates a closure (a function JSObject) that has captured
|
||||
// a Call object. So each call creates two items.
|
||||
function fun() { let v = count; return () => { return v; } }
|
||||
fun.factor = 2;
|
||||
|
||||
function str() { return 'perambulator' + count++; }
|
||||
str.factor = 1;
|
||||
|
||||
// Eval a fresh text each time, allocating:
|
||||
// - a fresh ScriptSourceObject
|
||||
// - a new JSScripts, not an eval cache hits
|
||||
// - a fresh prototype object
|
||||
// - a fresh Call object, since the eval makes 'ev' heavyweight
|
||||
// - the new function itself
|
||||
function ev() {
|
||||
return eval(\`(function () { return \${ count++ } })\`);
|
||||
}
|
||||
ev.factor = 5;
|
||||
|
||||
// A new object (1) with a new shape (2) with a new atom (3)
|
||||
function shape() { return { [ 'theobroma' + count++ ]: count }; }
|
||||
shape.factor = 3;
|
||||
`);
|
||||
|
||||
let baseline = 0;
|
||||
function countIncreasedByAtLeast(n) {
|
||||
let oldBaseline = baseline;
|
||||
|
||||
// Since a census counts only reachable objects, one might assume that calling
|
||||
// GC here would have no effect on the census results. But GC also throws away
|
||||
// JIT code and any objects it might be holding (template objects, say);
|
||||
// takeCensus reaches those. Shake everything loose that we can, to make the
|
||||
// census approximate reachability a bit more closely, and make our results a
|
||||
// bit more predictable.
|
||||
gc(g, 'shrinking');
|
||||
|
||||
baseline = dbg.memory.takeCensus({ breakdown: { by: 'count' } }).count;
|
||||
return baseline >= oldBaseline + n;
|
||||
}
|
||||
|
||||
countIncreasedByAtLeast(0);
|
||||
|
||||
g.add(100, g.obj);
|
||||
assertEq(countIncreasedByAtLeast(g.obj.factor * 100), true);
|
||||
|
||||
g.add(100, g.fun);
|
||||
assertEq(countIncreasedByAtLeast(g.fun.factor * 100), true);
|
||||
|
||||
g.add(100, g.str);
|
||||
assertEq(countIncreasedByAtLeast(g.str.factor * 100), true);
|
||||
|
||||
g.add(100, g.ev);
|
||||
assertEq(countIncreasedByAtLeast(g.ev.factor * 100), true);
|
||||
|
||||
g.add(100, g.shape);
|
||||
assertEq(countIncreasedByAtLeast(g.shape.factor * 100), true);
|
||||
@@ -0,0 +1,74 @@
|
||||
// Debugger.Memory.prototype.takeCensus: by: allocationStack breakdown
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
|
||||
g.evaluate(`
|
||||
var log = [];
|
||||
function f() { log.push(allocationMarker()); }
|
||||
function g() { f(); }
|
||||
function h() { f(); }
|
||||
`,
|
||||
{ fileName: "Rockford", lineNumber: 1000 });
|
||||
|
||||
// Create one allocationMarker with tracking turned off,
|
||||
// so it will have no associated stack.
|
||||
g.f();
|
||||
|
||||
dbg.memory.allocationSamplingProbability = 1;
|
||||
dbg.memory.trackingAllocationSites = true;
|
||||
|
||||
for ([f, n] of [[g.f, 20], [g.g, 10], [g.h, 5]])
|
||||
for (let i = 0; i < n; i++)
|
||||
f(); // all allocations of allocationMarker occur with this line as the
|
||||
// oldest stack frame.
|
||||
|
||||
let census = dbg.memory.takeCensus({ breakdown: { by: 'objectClass',
|
||||
then: { by: 'allocationStack',
|
||||
then: { by: 'count',
|
||||
label: 'haz stack'
|
||||
},
|
||||
noStack: { by: 'count',
|
||||
label: 'no haz stack'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let map = census.AllocationMarker;
|
||||
assertEq(map instanceof Map, true);
|
||||
|
||||
// Gather the stacks we are expecting to appear as keys, and
|
||||
// check that there are no unexpected keys.
|
||||
let stacks = { };
|
||||
|
||||
map.forEach((v, k) => {
|
||||
if (k === 'noStack') {
|
||||
// No need to save this key.
|
||||
} else if (k.functionDisplayName === 'f' &&
|
||||
k.parent.functionDisplayName === null) {
|
||||
stacks.f = k;
|
||||
} else if (k.functionDisplayName === 'f' &&
|
||||
k.parent.functionDisplayName === 'g' &&
|
||||
k.parent.parent.functionDisplayName === null) {
|
||||
stacks.fg = k;
|
||||
} else if (k.functionDisplayName === 'f' &&
|
||||
k.parent.functionDisplayName === 'h' &&
|
||||
k.parent.parent.functionDisplayName === null) {
|
||||
stacks.fh = k;
|
||||
} else {
|
||||
assertEq(true, false);
|
||||
}
|
||||
});
|
||||
|
||||
assertEq(map.get('noStack').label, 'no haz stack');
|
||||
assertEq(map.get('noStack').count, 1);
|
||||
|
||||
assertEq(map.get(stacks.f).label, 'haz stack');
|
||||
assertEq(map.get(stacks.f).count, 20);
|
||||
|
||||
assertEq(map.get(stacks.fg).label, 'haz stack');
|
||||
assertEq(map.get(stacks.fg).count, 10);
|
||||
|
||||
assertEq(map.get(stacks.fh).label, 'haz stack');
|
||||
assertEq(map.get(stacks.fh).count, 5);
|
||||
@@ -0,0 +1,57 @@
|
||||
// Check byte counts produced by takeCensus.
|
||||
|
||||
let g = newGlobal();
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
let sizeOfAM = byteSize(allocationMarker());
|
||||
|
||||
// Allocate a single allocation marker, and check that we can find it.
|
||||
g.eval('let hold = allocationMarker();');
|
||||
let census = dbg.memory.takeCensus({ breakdown: { by: 'objectClass' } });
|
||||
assertEq(census.AllocationMarker.count, 1);
|
||||
assertEq(census.AllocationMarker.bytes, sizeOfAM);
|
||||
|
||||
g.evaluate(`
|
||||
var objs = [];
|
||||
function fnerd() {
|
||||
objs.push(allocationMarker());
|
||||
for (let i = 0; i < 10; i++)
|
||||
objs.push(allocationMarker());
|
||||
}
|
||||
`,
|
||||
{ fileName: 'J. Edgar Hoover', lineNumber: 2000 });
|
||||
|
||||
dbg.memory.allocationSamplingProbability = 1;
|
||||
dbg.memory.trackingAllocationSites = true;
|
||||
|
||||
g.hold = null;
|
||||
g.fnerd();
|
||||
|
||||
let census = dbg.memory.takeCensus({
|
||||
breakdown: { by: 'objectClass',
|
||||
then: { by: 'allocationStack' }
|
||||
}
|
||||
});
|
||||
|
||||
let seen = 0;
|
||||
census.AllocationMarker.forEach((v, k) => {
|
||||
assertEq(k.functionDisplayName, 'fnerd');
|
||||
assertEq(k.source, 'J. Edgar Hoover');
|
||||
switch (k.line) {
|
||||
case 2003:
|
||||
assertEq(v.count, 1);
|
||||
assertEq(v.bytes, sizeOfAM);
|
||||
seen++;
|
||||
break;
|
||||
|
||||
case 2005:
|
||||
assertEq(v.count, 10);
|
||||
assertEq(v.bytes, 10 * sizeOfAM);
|
||||
seen++;
|
||||
break;
|
||||
|
||||
default: assertEq(true, false);
|
||||
}
|
||||
});
|
||||
|
||||
assertEq(seen, 2);
|
||||
@@ -7672,9 +7672,10 @@ IonBuilder::jsop_intrinsic(PropertyName* name)
|
||||
return pushTypeBarrier(ins, types, BarrierKind::TypeSet);
|
||||
}
|
||||
|
||||
// Bake in the intrinsic. Make sure that TI agrees with us on the type.
|
||||
Value vp;
|
||||
JS_ALWAYS_TRUE(script()->global().maybeGetIntrinsicValue(name, &vp));
|
||||
// Bake in the intrinsic, guaranteed to exist because a non-empty typeset
|
||||
// means the intrinsic was successfully gotten in the VM call above.
|
||||
// Assert that TI agrees with us on the type.
|
||||
Value vp = script()->global().existingIntrinsicValue(name);
|
||||
MOZ_ASSERT(types->hasType(TypeSet::GetValueType(vp)));
|
||||
|
||||
pushConstant(vp);
|
||||
@@ -8482,6 +8483,43 @@ IonBuilder::getElemTryCache(bool* emitted, MDefinition* obj, MDefinition* index)
|
||||
return true;
|
||||
}
|
||||
|
||||
TemporaryTypeSet*
|
||||
IonBuilder::computeHeapType(const TemporaryTypeSet* objTypes, const jsid id)
|
||||
{
|
||||
if (objTypes->unknownObject() || objTypes->getObjectCount() == 0)
|
||||
return nullptr;
|
||||
|
||||
TemporaryTypeSet empty;
|
||||
TemporaryTypeSet* acc = ∅
|
||||
LifoAlloc* lifoAlloc = alloc().lifoAlloc();
|
||||
|
||||
Vector<HeapTypeSetKey, 4, SystemAllocPolicy> properties;
|
||||
if (!properties.reserve(objTypes->getObjectCount()))
|
||||
return nullptr;
|
||||
|
||||
for (unsigned i = 0; i < objTypes->getObjectCount(); i++) {
|
||||
TypeSet::ObjectKey* key = objTypes->getObject(i);
|
||||
|
||||
if (key->unknownProperties())
|
||||
return nullptr;
|
||||
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSet* currentSet = property.maybeTypes();
|
||||
|
||||
if (!currentSet || currentSet->unknown())
|
||||
return nullptr;
|
||||
|
||||
properties.infallibleAppend(property);
|
||||
acc = TypeSet::unionSets(acc, currentSet, lifoAlloc);
|
||||
}
|
||||
|
||||
// Freeze all the properties associated with the refined type set.
|
||||
for (HeapTypeSetKey* i = properties.begin(); i != properties.end(); i++)
|
||||
i->freeze(constraints());
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType unboxedType)
|
||||
{
|
||||
@@ -8527,12 +8565,21 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
|
||||
// If we can load the element as a definite double, make sure to check that
|
||||
// the array has been converted to homogenous doubles first.
|
||||
TemporaryTypeSet* objTypes = obj->resultTypeSet();
|
||||
bool inBounds = !readOutOfBounds && !needsHoleCheck;
|
||||
|
||||
if (inBounds) {
|
||||
TemporaryTypeSet* heapTypes = computeHeapType(objTypes, JSID_VOID);
|
||||
if (heapTypes && heapTypes->isSubset(types)) {
|
||||
knownType = heapTypes->getKnownMIRType();
|
||||
types = heapTypes;
|
||||
}
|
||||
}
|
||||
|
||||
bool loadDouble =
|
||||
unboxedType == JSVAL_TYPE_MAGIC &&
|
||||
barrier == BarrierKind::NoBarrier &&
|
||||
loopDepth_ &&
|
||||
!readOutOfBounds &&
|
||||
!needsHoleCheck &&
|
||||
inBounds &&
|
||||
knownType == MIRType_Double &&
|
||||
objTypes &&
|
||||
objTypes->convertDoubleElements(constraints()) == TemporaryTypeSet::AlwaysConvertToDoubles;
|
||||
@@ -8568,8 +8615,10 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
|
||||
MOZ_ASSERT(knownType == MIRType_Value);
|
||||
}
|
||||
|
||||
if (knownType != MIRType_Value)
|
||||
if (knownType != MIRType_Value) {
|
||||
load->setResultType(knownType);
|
||||
load->setResultTypeSet(types);
|
||||
}
|
||||
|
||||
current->push(load);
|
||||
return pushTypeBarrier(load, types, barrier);
|
||||
@@ -10324,6 +10373,8 @@ IonBuilder::SimdTypeDescrToMIRType(SimdTypeDescr::Type type)
|
||||
switch (type) {
|
||||
case SimdTypeDescr::Int32x4: return MIRType_Int32x4;
|
||||
case SimdTypeDescr::Float32x4: return MIRType_Float32x4;
|
||||
case SimdTypeDescr::Int8x16:
|
||||
case SimdTypeDescr::Int16x8:
|
||||
case SimdTypeDescr::Float64x2: return MIRType_Undefined;
|
||||
}
|
||||
MOZ_CRASH("unimplemented MIR type for a SimdTypeDescr::Type");
|
||||
|
||||
+12
-2
@@ -587,6 +587,7 @@ class IonBuilder
|
||||
TypedObjectPrediction objTypeReprs,
|
||||
TypedObjectPrediction elemTypeReprs,
|
||||
int32_t elemSize);
|
||||
TemporaryTypeSet* computeHeapType(const TemporaryTypeSet* objTypes, const jsid id);
|
||||
|
||||
enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck };
|
||||
|
||||
@@ -818,8 +819,10 @@ class IonBuilder
|
||||
MSimdBinaryComp::Operation op, SimdTypeDescr::Type compType);
|
||||
InliningStatus inlineUnarySimd(CallInfo& callInfo, JSNative native,
|
||||
MSimdUnaryArith::Operation op, SimdTypeDescr::Type type);
|
||||
InliningStatus inlineSimdWith(CallInfo& callInfo, JSNative native, SimdLane lane,
|
||||
SimdTypeDescr::Type type);
|
||||
InliningStatus inlineSimdExtractLane(CallInfo& callInfo, JSNative native,
|
||||
SimdTypeDescr::Type type);
|
||||
InliningStatus inlineSimdReplaceLane(CallInfo& callInfo, JSNative native,
|
||||
SimdTypeDescr::Type type);
|
||||
InliningStatus inlineSimdSplat(CallInfo& callInfo, JSNative native, SimdTypeDescr::Type type);
|
||||
InliningStatus inlineSimdShuffle(CallInfo& callInfo, JSNative native, SimdTypeDescr::Type type,
|
||||
unsigned numVectors, unsigned numLanes);
|
||||
@@ -1325,6 +1328,13 @@ class CallInfo
|
||||
return args_[i];
|
||||
}
|
||||
|
||||
MDefinition* getArgWithDefault(uint32_t i, MDefinition* defaultValue) const {
|
||||
if (i < argc())
|
||||
return args_[i];
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
void setArg(uint32_t i, MDefinition* def) {
|
||||
MOZ_ASSERT(i < argc());
|
||||
args_[i] = def;
|
||||
|
||||
@@ -25,8 +25,9 @@
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
|
||||
using JS::TrackedStrategy;
|
||||
using JS::DoubleNaNValue;
|
||||
using JS::TrackedOutcome;
|
||||
using JS::TrackedStrategy;
|
||||
using JS::TrackedTypeSite;
|
||||
|
||||
namespace js {
|
||||
@@ -316,17 +317,15 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
||||
COMP_COMMONX4_TO_INT32X4_SIMD_OP(INLINE_SIMD_COMPARISON_)
|
||||
#undef INLINE_SIMD_COMPARISON_
|
||||
|
||||
#define INLINE_SIMD_SETTER_(LANE) \
|
||||
if (native == js::simd_int32x4_with##LANE) \
|
||||
return inlineSimdWith(callInfo, native, SimdLane::Lane##LANE, SimdTypeDescr::Int32x4); \
|
||||
if (native == js::simd_float32x4_with##LANE) \
|
||||
return inlineSimdWith(callInfo, native, SimdLane::Lane##LANE, SimdTypeDescr::Float32x4);
|
||||
if (native == js::simd_int32x4_extractLane)
|
||||
return inlineSimdExtractLane(callInfo, native, SimdTypeDescr::Int32x4);
|
||||
if (native == js::simd_float32x4_extractLane)
|
||||
return inlineSimdExtractLane(callInfo, native, SimdTypeDescr::Float32x4);
|
||||
|
||||
INLINE_SIMD_SETTER_(X)
|
||||
INLINE_SIMD_SETTER_(Y)
|
||||
INLINE_SIMD_SETTER_(Z)
|
||||
INLINE_SIMD_SETTER_(W)
|
||||
#undef INLINE_SIMD_SETTER_
|
||||
if (native == js::simd_int32x4_replaceLane)
|
||||
return inlineSimdReplaceLane(callInfo, native, SimdTypeDescr::Int32x4);
|
||||
if (native == js::simd_float32x4_replaceLane)
|
||||
return inlineSimdReplaceLane(callInfo, native, SimdTypeDescr::Float32x4);
|
||||
|
||||
if (native == js::simd_int32x4_not)
|
||||
return inlineUnarySimd(callInfo, native, MSimdUnaryArith::not_, SimdTypeDescr::Int32x4);
|
||||
@@ -3135,21 +3134,13 @@ IonBuilder::inlineConstructTypedObject(CallInfo& callInfo, TypeDescr* descr)
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineConstructSimdObject(CallInfo& callInfo, SimdTypeDescr* descr)
|
||||
{
|
||||
if (callInfo.argc() == 1)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Generic constructor of SIMD valuesX4.
|
||||
MIRType simdType = SimdTypeDescrToMIRType(descr->type());
|
||||
|
||||
// TODO Happens for Float64x2 (Bug 1124205)
|
||||
// TODO Happens for Float64x2 (Bug 1124205) and Int8x16/Int16x8 (Bug 1136226)
|
||||
if (simdType == MIRType_Undefined)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// We do not inline SIMD constructors if the number of arguments does not
|
||||
// match the number of lanes.
|
||||
if (SimdTypeToLength(simdType) != callInfo.argc())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Take the templateObject out of Baseline ICs, such that we can box
|
||||
// SIMD value type in the same kind of objects.
|
||||
MOZ_ASSERT(size_t(descr->size(descr->type())) < InlineTypedObject::MaximumSize);
|
||||
@@ -3162,9 +3153,24 @@ IonBuilder::inlineConstructSimdObject(CallInfo& callInfo, SimdTypeDescr* descr)
|
||||
InlineTypedObject* inlineTypedObject = &templateObject->as<InlineTypedObject>();
|
||||
MOZ_ASSERT(&inlineTypedObject->typeDescr() == descr);
|
||||
|
||||
MSimdValueX4* values = MSimdValueX4::New(alloc(), simdType,
|
||||
callInfo.getArg(0), callInfo.getArg(1),
|
||||
callInfo.getArg(2), callInfo.getArg(3));
|
||||
// When there are missing arguments, provide a default value
|
||||
// containing the coercion of 'undefined' to the right type.
|
||||
MConstant* defVal = nullptr;
|
||||
if (callInfo.argc() < SimdTypeToLength(simdType)) {
|
||||
MIRType scalarType = SimdTypeToScalarType(simdType);
|
||||
if (scalarType == MIRType_Int32) {
|
||||
defVal = constant(Int32Value(0));
|
||||
} else {
|
||||
MOZ_ASSERT(IsFloatingPointType(scalarType));
|
||||
defVal = constant(DoubleNaNValue());
|
||||
defVal->setResultType(scalarType);
|
||||
}
|
||||
}
|
||||
|
||||
MSimdValueX4* values =
|
||||
MSimdValueX4::New(alloc(), simdType,
|
||||
callInfo.getArgWithDefault(0, defVal), callInfo.getArgWithDefault(1, defVal),
|
||||
callInfo.getArgWithDefault(2, defVal), callInfo.getArgWithDefault(3, defVal));
|
||||
current->add(values);
|
||||
|
||||
MSimdBox* obj = MSimdBox::New(alloc(), constraints(), values, inlineTypedObject,
|
||||
@@ -3271,17 +3277,49 @@ IonBuilder::inlineSimdSplat(CallInfo& callInfo, JSNative native, SimdTypeDescr::
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdWith(CallInfo& callInfo, JSNative native, SimdLane lane,
|
||||
SimdTypeDescr::Type type)
|
||||
IonBuilder::inlineSimdExtractLane(CallInfo& callInfo, JSNative native, SimdTypeDescr::Type type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!checkInlineSimd(callInfo, native, type, 2, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* arg = callInfo.getArg(1);
|
||||
if (!arg->isConstantValue() || arg->type() != MIRType_Int32)
|
||||
return InliningStatus_NotInlined;
|
||||
int32_t lane = callInfo.getArg(1)->constantValue().toInt32();
|
||||
if (lane < 0 || lane >= 4)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineBinarySimd
|
||||
MIRType vecType = SimdTypeDescrToMIRType(type);
|
||||
MIRType scalarType = SimdTypeToScalarType(vecType);
|
||||
MSimdExtractElement* ins = MSimdExtractElement::New(alloc(), callInfo.getArg(0),
|
||||
vecType, scalarType, SimdLane(lane));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, SimdTypeDescr::Type type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!checkInlineSimd(callInfo, native, type, 3, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* arg = callInfo.getArg(1);
|
||||
if (!arg->isConstantValue() || arg->type() != MIRType_Int32)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
int32_t lane = arg->constantValue().toInt32();
|
||||
if (lane < 0 || lane >= 4)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineBinarySimd
|
||||
MIRType mirType = SimdTypeDescrToMIRType(type);
|
||||
MSimdInsertElement* ins = MSimdInsertElement::New(alloc(), callInfo.getArg(0),
|
||||
callInfo.getArg(1), mirType, lane);
|
||||
callInfo.getArg(2), mirType, SimdLane(lane));
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
@@ -3329,9 +3367,6 @@ IonBuilder::inlineSimdCheck(CallInfo& callInfo, JSNative native, SimdTypeDescr::
|
||||
|
||||
MIRType mirType = SimdTypeDescrToMIRType(type);
|
||||
MSimdUnbox* unbox = MSimdUnbox::New(alloc(), callInfo.getArg(0), mirType);
|
||||
// Make sure not to remove this unbox!
|
||||
unbox->setGuard();
|
||||
|
||||
current->add(unbox);
|
||||
current->push(callInfo.getArg(0));
|
||||
|
||||
@@ -3367,6 +3402,8 @@ SimdTypeToScalarType(SimdTypeDescr::Type type)
|
||||
switch (type) {
|
||||
case SimdTypeDescr::Float32x4: return Scalar::Float32x4;
|
||||
case SimdTypeDescr::Int32x4: return Scalar::Int32x4;
|
||||
case SimdTypeDescr::Int8x16:
|
||||
case SimdTypeDescr::Int16x8:
|
||||
case SimdTypeDescr::Float64x2: break;
|
||||
}
|
||||
MOZ_CRASH("unexpected simd type");
|
||||
|
||||
@@ -930,6 +930,24 @@ MSimdSplatX4::foldsTo(TempAllocator& alloc)
|
||||
return MSimdConstant::New(alloc, cst, type());
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
MSimdUnbox::foldsTo(TempAllocator &alloc)
|
||||
{
|
||||
MDefinition* in = input();
|
||||
|
||||
if (in->isSimdBox()) {
|
||||
// If the operand is a MSimdBox, then we just reuse the operand of the
|
||||
// MSimdBox as long as the type corresponds to what we are supposed to
|
||||
// unbox.
|
||||
in = in->toSimdBox()->input();
|
||||
if (in->type() != type())
|
||||
return this;
|
||||
return in;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
MSimdSwizzle::foldsTo(TempAllocator& alloc)
|
||||
{
|
||||
|
||||
@@ -3253,6 +3253,7 @@ class MSimdUnbox
|
||||
: MUnaryInstruction(op)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
setGuard();
|
||||
setMovable();
|
||||
setResultType(type);
|
||||
}
|
||||
@@ -3266,6 +3267,11 @@ class MSimdUnbox
|
||||
return new(alloc) MSimdUnbox(op, type);
|
||||
}
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::None();
|
||||
}
|
||||
|
||||
@@ -1342,6 +1342,12 @@ RSimdBox::recover(JSContext* cx, SnapshotIterator &iter) const
|
||||
case SimdTypeDescr::Float64x2:
|
||||
MOZ_CRASH("NYI, RSimdBox of Float64x2");
|
||||
break;
|
||||
case SimdTypeDescr::Int8x16:
|
||||
MOZ_CRASH("NYI, RSimdBox of Int8x16");
|
||||
break;
|
||||
case SimdTypeDescr::Int16x8:
|
||||
MOZ_CRASH("NYI, RSimdBox of Int16x8");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!resultObject)
|
||||
|
||||
@@ -112,7 +112,7 @@ class Registers
|
||||
ra = r31,
|
||||
invalid_reg
|
||||
};
|
||||
typedef RegisterID Code;
|
||||
typedef uint8_t Code;
|
||||
typedef RegisterID Encoding;
|
||||
|
||||
// Content spilled during bailouts.
|
||||
@@ -120,22 +120,22 @@ class Registers
|
||||
uintptr_t r;
|
||||
};
|
||||
|
||||
static const char *GetName(Code code) {
|
||||
static const char* GetName(Code code) {
|
||||
MOZ_ASSERT(code < Total);
|
||||
static const char * const Names[] = { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
|
||||
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
||||
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
||||
"t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"};
|
||||
return Names[code];
|
||||
}
|
||||
static const char *GetName(uint32_t i) {
|
||||
MOZ_ASSERT(i < Total);
|
||||
static const char* GetName(Encoding i) {
|
||||
return GetName(Code(i));
|
||||
}
|
||||
|
||||
static Code FromName(const char* name);
|
||||
|
||||
static const Code StackPointer = sp;
|
||||
static const Code Invalid = invalid_reg;
|
||||
static const Encoding StackPointer = sp;
|
||||
static const Encoding Invalid = invalid_reg;
|
||||
|
||||
static const uint32_t Total = 32;
|
||||
static const uint32_t Allocatable = 14;
|
||||
@@ -277,7 +277,7 @@ class FloatRegisters
|
||||
double d;
|
||||
};
|
||||
|
||||
static const char *GetName(Code code) {
|
||||
static const char* GetName(Code code) {
|
||||
static const char * const Names[] = { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
|
||||
"f8", "f9", "f10", "f11", "f12", "f13",
|
||||
"f14", "f15", "f16", "f17", "f18", "f19",
|
||||
@@ -285,7 +285,7 @@ class FloatRegisters
|
||||
"f26", "f27", "f28", "f29", "f30", "f31"};
|
||||
return Names[code];
|
||||
}
|
||||
static const char *GetName(uint32_t i) {
|
||||
static const char* GetName(uint32_t i) {
|
||||
MOZ_ASSERT(i < Total);
|
||||
return GetName(Code(i % 32));
|
||||
}
|
||||
|
||||
@@ -1420,7 +1420,7 @@ void
|
||||
Assembler::as_break(uint32_t code)
|
||||
{
|
||||
MOZ_ASSERT(code <= MAX_BREAK_CODE);
|
||||
writeInst(op_special | code << RTShift | ff_break);
|
||||
writeInst(op_special | code << FunctionBits | ff_break);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
||||
@@ -641,6 +641,20 @@ PatchBackedge(CodeLocationJump& jump_, CodeLocationLabel label, JitRuntime::Back
|
||||
class Assembler;
|
||||
typedef js::jit::AssemblerBuffer<1024, Instruction> MIPSBuffer;
|
||||
|
||||
class MIPSBufferWithExecutableCopy : public MIPSBuffer
|
||||
{
|
||||
public:
|
||||
void executableCopy(uint8_t* buffer) {
|
||||
if (this->oom())
|
||||
return;
|
||||
|
||||
for (Slice* cur = head; cur != nullptr; cur = cur->getNext()) {
|
||||
memcpy(buffer, &cur->instructions, cur->length());
|
||||
buffer += cur->length();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Assembler : public AssemblerShared
|
||||
{
|
||||
public:
|
||||
@@ -751,7 +765,7 @@ class Assembler : public AssemblerShared
|
||||
CompactBufferWriter dataRelocations_;
|
||||
CompactBufferWriter preBarriers_;
|
||||
|
||||
MIPSBuffer m_buffer;
|
||||
MIPSBufferWithExecutableCopy m_buffer;
|
||||
|
||||
public:
|
||||
Assembler()
|
||||
|
||||
@@ -2028,44 +2028,15 @@ CodeGeneratorMIPS::visitAsmJSPassStackArg(LAsmJSPassStackArg* ins)
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorMIPS::visitUDiv(LUDiv* ins)
|
||||
{
|
||||
Register lhs = ToRegister(ins->lhs());
|
||||
Register rhs = ToRegister(ins->rhs());
|
||||
Register output = ToRegister(ins->output());
|
||||
|
||||
Label done;
|
||||
if (ins->mir()->canBeDivideByZero()) {
|
||||
if (ins->mir()->isTruncated()) {
|
||||
Label notzero;
|
||||
masm.ma_b(rhs, rhs, ¬zero, Assembler::NonZero, ShortJump);
|
||||
masm.move32(Imm32(0), output);
|
||||
masm.ma_b(&done, ShortJump);
|
||||
masm.bind(¬zero);
|
||||
} else {
|
||||
MOZ_ASSERT(ins->mir()->fallible());
|
||||
bailoutCmp32(Assembler::Equal, rhs, Imm32(0), ins->snapshot());
|
||||
}
|
||||
}
|
||||
|
||||
masm.as_divu(lhs, rhs);
|
||||
masm.as_mflo(output);
|
||||
|
||||
if (!ins->mir()->isTruncated())
|
||||
bailoutCmp32(Assembler::LessThan, output, Imm32(0), ins->snapshot());
|
||||
|
||||
masm.bind(&done);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorMIPS::visitUMod(LUMod* ins)
|
||||
CodeGeneratorMIPS::visitUDivOrMod(LUDivOrMod* ins)
|
||||
{
|
||||
Register lhs = ToRegister(ins->lhs());
|
||||
Register rhs = ToRegister(ins->rhs());
|
||||
Register output = ToRegister(ins->output());
|
||||
Label done;
|
||||
|
||||
if (ins->mir()->canBeDivideByZero()) {
|
||||
// Prevent divide by zero.
|
||||
if (ins->canBeDivideByZero()) {
|
||||
if (ins->mir()->isTruncated()) {
|
||||
// Infinity|0 == 0
|
||||
Label notzero;
|
||||
@@ -2074,7 +2045,6 @@ CodeGeneratorMIPS::visitUMod(LUMod* ins)
|
||||
masm.ma_b(&done, ShortJump);
|
||||
masm.bind(¬zero);
|
||||
} else {
|
||||
MOZ_ASSERT(ins->mir()->fallible());
|
||||
bailoutCmp32(Assembler::Equal, rhs, Imm32(0), ins->snapshot());
|
||||
}
|
||||
}
|
||||
@@ -2082,6 +2052,14 @@ CodeGeneratorMIPS::visitUMod(LUMod* ins)
|
||||
masm.as_divu(lhs, rhs);
|
||||
masm.as_mfhi(output);
|
||||
|
||||
// If the remainder is > 0, bailout since this must be a double.
|
||||
if (ins->mir()->isDiv()) {
|
||||
if (!ins->mir()->toDiv()->canTruncateRemainder())
|
||||
bailoutCmp32(Assembler::NonZero, output, output, ins->snapshot());
|
||||
// Get quotient
|
||||
masm.as_mflo(output);
|
||||
}
|
||||
|
||||
if (!ins->mir()->isTruncated())
|
||||
bailoutCmp32(Assembler::LessThan, output, Imm32(0), ins->snapshot());
|
||||
|
||||
|
||||
@@ -249,8 +249,7 @@ class CodeGeneratorMIPS : public CodeGeneratorShared
|
||||
|
||||
protected:
|
||||
void visitEffectiveAddress(LEffectiveAddress* ins);
|
||||
void visitUDiv(LUDiv* ins);
|
||||
void visitUMod(LUMod* ins);
|
||||
void visitUDivOrMod(LUDivOrMod* ins);
|
||||
|
||||
public:
|
||||
// Unimplemented SIMD instructions
|
||||
|
||||
@@ -355,23 +355,20 @@ class LMulI : public LBinaryMath<0>
|
||||
}
|
||||
};
|
||||
|
||||
class LUDiv : public LBinaryMath<0>
|
||||
class LUDivOrMod : public LBinaryMath<0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(UDiv);
|
||||
LIR_HEADER(UDivOrMod);
|
||||
|
||||
MDiv* mir() {
|
||||
return mir_->toDiv();
|
||||
MBinaryArithInstruction* mir() const {
|
||||
MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
|
||||
return static_cast<MBinaryArithInstruction* >(mir_);
|
||||
}
|
||||
};
|
||||
|
||||
class LUMod : public LBinaryMath<0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(UMod);
|
||||
|
||||
MMod* mir() {
|
||||
return mir_->toMod();
|
||||
bool canBeDivideByZero() const {
|
||||
if (mir_->isMod())
|
||||
return mir_->toMod()->canBeDivideByZero();
|
||||
return mir_->toDiv()->canBeDivideByZero();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
_(PowHalfD) \
|
||||
_(AsmJSUInt32ToDouble) \
|
||||
_(AsmJSUInt32ToFloat32) \
|
||||
_(UDiv) \
|
||||
_(UMod) \
|
||||
_(UDivOrMod) \
|
||||
_(AsmJSLoadFuncPtr)
|
||||
|
||||
#endif // jit_mips_LOpcodes_mips_h__
|
||||
|
||||
@@ -419,7 +419,7 @@ LIRGeneratorMIPS::lowerUDiv(MDiv* div)
|
||||
MDefinition* lhs = div->getOperand(0);
|
||||
MDefinition* rhs = div->getOperand(1);
|
||||
|
||||
LUDiv* lir = new(alloc()) LUDiv;
|
||||
LUDivOrMod* lir = new(alloc()) LUDivOrMod;
|
||||
lir->setOperand(0, useRegister(lhs));
|
||||
lir->setOperand(1, useRegister(rhs));
|
||||
if (div->fallible())
|
||||
@@ -434,7 +434,7 @@ LIRGeneratorMIPS::lowerUMod(MMod* mod)
|
||||
MDefinition* lhs = mod->getOperand(0);
|
||||
MDefinition* rhs = mod->getOperand(1);
|
||||
|
||||
LUMod* lir = new(alloc()) LUMod;
|
||||
LUDivOrMod* lir = new(alloc()) LUDivOrMod;
|
||||
lir->setOperand(0, useRegister(lhs));
|
||||
lir->setOperand(1, useRegister(rhs));
|
||||
if (mod->fallible())
|
||||
|
||||
@@ -234,6 +234,15 @@ class MacroAssemblerMIPS : public Assembler
|
||||
ma_li(ScratchRegister, imm);
|
||||
ma_b(lhs, ScratchRegister, l, c, jumpKind);
|
||||
}
|
||||
void ma_b(Register lhs, ImmWord imm, Label* l, Condition c, JumpKind jumpKind = LongJump)
|
||||
{
|
||||
ma_b(lhs, Imm32(uint32_t(imm.value)), l, c, jumpKind);
|
||||
}
|
||||
void ma_b(Address addr, ImmWord imm, Label* l, Condition c, JumpKind jumpKind = LongJump)
|
||||
{
|
||||
ma_b(addr, Imm32(uint32_t(imm.value)), l, c, jumpKind);
|
||||
}
|
||||
|
||||
void ma_b(Register lhs, Address addr, Label* l, Condition c, JumpKind jumpKind = LongJump);
|
||||
void ma_b(Address addr, Imm32 imm, Label* l, Condition c, JumpKind jumpKind = LongJump);
|
||||
void ma_b(Address addr, ImmGCPtr imm, Label* l, Condition c, JumpKind jumpKind = LongJump);
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
static const Instr kCallRedirInstr = op_special | MAX_BREAK_CODE << RTShift | ff_break;
|
||||
static const Instr kCallRedirInstr = op_special | MAX_BREAK_CODE << FunctionBits | ff_break;
|
||||
|
||||
// Utils functions.
|
||||
static bool
|
||||
@@ -3423,7 +3423,7 @@ Simulator::call(uint8_t* entry, int argument_count, ...)
|
||||
else
|
||||
entry_stack = entry_stack - kCArgsSlotsSize;
|
||||
|
||||
entry_stack &= ~ABIStackAlignment;
|
||||
entry_stack &= ~(ABIStackAlignment - 1);
|
||||
|
||||
intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
|
||||
|
||||
|
||||
@@ -276,7 +276,7 @@ JitRuntime::generateEnterJIT(JSContext* cx, EnterJitType type)
|
||||
AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
|
||||
masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0),
|
||||
&skipProfilingInstrumentation);
|
||||
masm.ma_addu(realFramePtr, StackPointer, Imm32(sizeof(void*)));
|
||||
masm.ma_addu(realFramePtr, framePtr, Imm32(sizeof(void*)));
|
||||
masm.profilerEnterFrame(realFramePtr, scratch);
|
||||
masm.bind(&skipProfilingInstrumentation);
|
||||
}
|
||||
|
||||
@@ -846,6 +846,7 @@ enum AsmJSImmKind
|
||||
AsmJSImm_ReportOverRecursed,
|
||||
AsmJSImm_OnDetached,
|
||||
AsmJSImm_OnOutOfBounds,
|
||||
AsmJSImm_OnImpreciseConversion,
|
||||
AsmJSImm_HandleExecutionInterrupt,
|
||||
AsmJSImm_InvokeFromAsmJS_Ignore,
|
||||
AsmJSImm_InvokeFromAsmJS_ToInt32,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user