Index: src/builtins/builtins-sharedarraybuffer-gen.cc |
diff --git a/src/builtins/builtins-sharedarraybuffer-gen.cc b/src/builtins/builtins-sharedarraybuffer-gen.cc |
index 056dfc6e1a5c27c0f6c289b3af17ca57b2141c79..a9331a15484c417838c7113f994a07186ba9e7b2 100644 |
--- a/src/builtins/builtins-sharedarraybuffer-gen.cc |
+++ b/src/builtins/builtins-sharedarraybuffer-gen.cc |
@@ -27,8 +27,11 @@ class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler { |
Node** out_backing_store); |
Node* ConvertTaggedAtomicIndexToWord32(Node* tagged, Node* context, |
Node** number_index); |
- void ValidateAtomicIndex(Node* index_word, Node* array_length_word, |
- Node* context); |
+ void ValidateAtomicIndex(Node* array, Node* index_word, Node* context); |
+#if DEBUG |
+ void DebugSanityCheckAtomicIndex(Node* array, Node* index_word, |
+ Node* context); |
+#endif |
void AtomicBinopBuiltinCommon(Node* array, Node* index, Node* value, |
Node* context, AssemblerFunction function, |
Runtime::FunctionId runtime_function); |
@@ -88,56 +91,35 @@ void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray( |
Node* SharedArrayBufferBuiltinsAssembler::ConvertTaggedAtomicIndexToWord32( |
Node* tagged, Node* context, Node** number_index) { |
VARIABLE(var_result, MachineRepresentation::kWord32); |
- |
- // TODO(jkummerow): Skip ToNumber call when |tagged| is a number already. |
- // Maybe this can be unified with other tagged-to-index conversions? |
- // Why does this return an int32, and not an intptr? |
- // Why is there the additional |number_index| output parameter? |
- Callable to_number = CodeFactory::ToNumber(isolate()); |
- *number_index = CallStub(to_number, context, tagged); |
- Label done(this, &var_result); |
- |
- Label if_numberissmi(this), if_numberisnotsmi(this); |
- Branch(TaggedIsSmi(*number_index), &if_numberissmi, &if_numberisnotsmi); |
- |
- BIND(&if_numberissmi); |
+ Label done(this), range_error(this); |
+ |
+ // Returns word32 since index cannot be longer than a TypedArray length, |
+ // which has a uint32 maximum. |
+ // The |number_index| output parameter is used only for architectures that |
+ // don't currently have a TF implementation and forward to runtime functions |
+ // instead; they expect the value has already been coerced to an integer. |
+ *number_index = ToSmiIndex(tagged, context, &range_error); |
+ var_result.Bind(SmiToWord32(*number_index)); |
+ Goto(&done); |
+ |
+ BIND(&range_error); |
{ |
- var_result.Bind(SmiToWord32(*number_index)); |
- Goto(&done); |
- } |
- |
- BIND(&if_numberisnotsmi); |
- { |
- Node* number_index_value = LoadHeapNumberValue(*number_index); |
- Node* access_index = TruncateFloat64ToWord32(number_index_value); |
- Node* test_index = ChangeInt32ToFloat64(access_index); |
- |
- Label if_indexesareequal(this), if_indexesarenotequal(this); |
- Branch(Float64Equal(number_index_value, test_index), &if_indexesareequal, |
- &if_indexesarenotequal); |
- |
- BIND(&if_indexesareequal); |
- { |
- var_result.Bind(access_index); |
- Goto(&done); |
- } |
- |
- BIND(&if_indexesarenotequal); |
- { |
- CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context); |
- Unreachable(); |
- } |
+ CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context); |
+ Unreachable(); |
} |
BIND(&done); |
return var_result.value(); |
} |
-void SharedArrayBufferBuiltinsAssembler::ValidateAtomicIndex( |
- Node* index_word, Node* array_length_word, Node* context) { |
+void SharedArrayBufferBuiltinsAssembler::ValidateAtomicIndex(Node* array, |
+ Node* index_word, |
+ Node* context) { |
// Check if the index is in bounds. If not, throw RangeError. |
Label check_passed(this); |
- GotoIf(Uint32LessThan(index_word, array_length_word), &check_passed); |
+ Node* array_length_word32 = TruncateTaggedToWord32( |
+ context, LoadObjectField(array, JSTypedArray::kLengthOffset)); |
+ GotoIf(Uint32LessThan(index_word, array_length_word32), &check_passed); |
CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context); |
Unreachable(); |
@@ -145,22 +127,35 @@ void SharedArrayBufferBuiltinsAssembler::ValidateAtomicIndex( |
BIND(&check_passed); |
} |
+#if DEBUG |
+void SharedArrayBufferBuiltinsAssembler::DebugSanityCheckAtomicIndex( |
+ Node* array, Node* index_word, Node* context) { |
+ // In Debug mode, we re-validate the index as a sanity check because |
+ // ToInteger above calls out to JavaScript. A SharedArrayBuffer can't be |
+ // neutered and the TypedArray length can't change either, so skipping this |
+ // check in Release mode is safe. |
+ CSA_ASSERT( |
+ this, |
+ Uint32LessThan( |
+ index_word, |
+ TruncateTaggedToWord32( |
+ context, LoadObjectField(array, JSTypedArray::kLengthOffset)))); |
+} |
+#endif |
+ |
TF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) { |
Node* array = Parameter(Descriptor::kArray); |
Node* index = Parameter(Descriptor::kIndex); |
Node* context = Parameter(Descriptor::kContext); |
- Node* index_integer; |
- Node* index_word32 = |
- ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); |
- |
Node* instance_type; |
Node* backing_store; |
ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
- Node* array_length_word32 = TruncateTaggedToWord32( |
- context, LoadObjectField(array, JSTypedArray::kLengthOffset)); |
- ValidateAtomicIndex(index_word32, array_length_word32, context); |
+ Node* index_integer; |
+ Node* index_word32 = |
+ ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); |
+ ValidateAtomicIndex(array, index_word32, context); |
Node* index_word = ChangeUint32ToWord(index_word32); |
Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), |
@@ -210,25 +205,22 @@ TF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) { |
Node* value = Parameter(Descriptor::kValue); |
Node* context = Parameter(Descriptor::kContext); |
- // The value_integer needs to be computed before the validations as the |
- // ToInteger function can be potentially modified in JS to invalidate the |
- // conditions. This is just a no-cost safety measure as SABs can't be neutered |
- // or shrunk. |
- Node* value_integer = ToInteger(context, value); |
- Node* value_word32 = TruncateTaggedToWord32(context, value_integer); |
+ Node* instance_type; |
+ Node* backing_store; |
+ ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
Node* index_integer; |
Node* index_word32 = |
ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); |
+ ValidateAtomicIndex(array, index_word32, context); |
+ Node* index_word = ChangeUint32ToWord(index_word32); |
- Node* instance_type; |
- Node* backing_store; |
- ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
+ Node* value_integer = ToInteger(context, value); |
+ Node* value_word32 = TruncateTaggedToWord32(context, value_integer); |
- Node* array_length_word32 = TruncateTaggedToWord32( |
- context, LoadObjectField(array, JSTypedArray::kLengthOffset)); |
- ValidateAtomicIndex(index_word32, array_length_word32, context); |
- Node* index_word = ChangeUint32ToWord(index_word32); |
+#if DEBUG |
+ DebugSanityCheckAtomicIndex(array, index_word32, context); |
+#endif |
Label u8(this), u16(this), u32(this), other(this); |
int32_t case_values[] = { |
@@ -267,23 +259,20 @@ TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) { |
Node* value = Parameter(Descriptor::kValue); |
Node* context = Parameter(Descriptor::kContext); |
- // The value_integer needs to be computed before the validations as the |
- // ToInteger function can be potentially modified in JS to invalidate the |
- // conditions. This is just a no-cost safety measure as SABs can't be neutered |
- // or shrunk. |
- Node* value_integer = ToInteger(context, value); |
+ Node* instance_type; |
+ Node* backing_store; |
+ ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
Node* index_integer; |
Node* index_word32 = |
ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); |
+ ValidateAtomicIndex(array, index_word32, context); |
- Node* instance_type; |
- Node* backing_store; |
- ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
+ Node* value_integer = ToInteger(context, value); |
- Node* array_length_word32 = TruncateTaggedToWord32( |
- context, LoadObjectField(array, JSTypedArray::kLengthOffset)); |
- ValidateAtomicIndex(index_word32, array_length_word32, context); |
+#if DEBUG |
+ DebugSanityCheckAtomicIndex(array, index_word32, context); |
+#endif |
#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 |
Return(CallRuntime(Runtime::kAtomicsExchange, context, array, index_integer, |
@@ -344,24 +333,21 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) { |
Node* new_value = Parameter(Descriptor::kNewValue); |
Node* context = Parameter(Descriptor::kContext); |
- // The value_integers needs to be computed before the validations as the |
- // ToInteger function can be potentially modified in JS to invalidate the |
- // conditions. This is just a no-cost safety measure as SABs can't be neutered |
- // or shrunk. |
- Node* old_value_integer = ToInteger(context, old_value); |
- Node* new_value_integer = ToInteger(context, new_value); |
+ Node* instance_type; |
+ Node* backing_store; |
+ ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
Node* index_integer; |
Node* index_word32 = |
ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); |
+ ValidateAtomicIndex(array, index_word32, context); |
- Node* instance_type; |
- Node* backing_store; |
- ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
+ Node* old_value_integer = ToInteger(context, old_value); |
+ Node* new_value_integer = ToInteger(context, new_value); |
- Node* array_length_word32 = TruncateTaggedToWord32( |
- context, LoadObjectField(array, JSTypedArray::kLengthOffset)); |
- ValidateAtomicIndex(index_word32, array_length_word32, context); |
+#if DEBUG |
+ DebugSanityCheckAtomicIndex(array, index_word32, context); |
+#endif |
#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 || \ |
V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X |
@@ -443,23 +429,24 @@ BINOP_BUILTIN(Xor) |
void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon( |
Node* array, Node* index, Node* value, Node* context, |
AssemblerFunction function, Runtime::FunctionId runtime_function) { |
- // The value_integer needs to be computed before the validations as the |
- // ToInteger function can be potentially modified in JS to invalidate the |
- // conditions. This is just a no-cost safety measure as SABs can't be neutered |
- // or shrunk. |
- Node* value_integer = ToInteger(context, value); |
+ Node* instance_type; |
+ Node* backing_store; |
+ ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
Node* index_integer; |
Node* index_word32 = |
ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); |
+ ValidateAtomicIndex(array, index_word32, context); |
- Node* instance_type; |
- Node* backing_store; |
- ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
+ Node* value_integer = ToInteger(context, value); |
- Node* array_length_word32 = TruncateTaggedToWord32( |
- context, LoadObjectField(array, JSTypedArray::kLengthOffset)); |
- ValidateAtomicIndex(index_word32, array_length_word32, context); |
+#if DEBUG |
+ // In Debug mode, we re-validate the index as a sanity check because |
+ // ToInteger above calls out to JavaScript. A SharedArrayBuffer can't be |
+ // neutered and the TypedArray length can't change either, so skipping this |
+ // check in Release mode is safe. |
+ ValidateAtomicIndex(array, index_word32, context); |
+#endif |
#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 || \ |
V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X |