Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Unified Diff: src/builtins.cc

Issue 1617503003: [Atomics] code stubs for atomic operations (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: remove unnecessary CSA additions Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/builtins.cc
diff --git a/src/builtins.cc b/src/builtins.cc
index fa3921a3544b9119d9fa81e3c06854e44b6b4370..238c498ec32f35c8e6764dcfaf1e040692823828 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -9,6 +9,7 @@
#include "src/arguments.h"
#include "src/base/once.h"
#include "src/bootstrapper.h"
+#include "src/compiler/code-stub-assembler.h"
#include "src/dateparser-inl.h"
#include "src/elements.h"
#include "src/frames-inl.h"
@@ -4358,6 +4359,220 @@ void Builtins::Generate_StackCheck(MacroAssembler* masm) {
}
+namespace {
+
+void ValidateSharedTypedArray(compiler::CodeStubAssembler* a,
+ compiler::Node* tagged) {
+ using namespace compiler;
+ CodeStubAssembler::Label is_smi(a), not_smi(a), is_typed_array(a),
+ not_typed_array(a), is_shared(a), not_shared(a), is_float(a),
+ not_float(a), invalid(a);
+ Node* context = a->Context();
+
+ // Check if it is a heap object.
+ a->Branch(a->WordIsSmi(tagged), &is_smi, &not_smi);
+ a->Bind(&is_smi);
+ a->Goto(&invalid);
binji 2016/02/12 01:46:56 This Bind/Goto dance I end up having to do a lot o
+
+ // Check if the array's instance type is JSTypedArray.
+ a->Bind(&not_smi);
+ a->Branch(a->WordEqual(a->InstanceType(tagged),
+ a->Int32Constant(JS_TYPED_ARRAY_TYPE)),
+ &is_typed_array, &not_typed_array);
+ a->Bind(&not_typed_array);
+ a->Goto(&invalid);
+
+ // Check if the array's JSArrayBuffer is shared.
+ a->Bind(&is_typed_array);
+ Node* is_buffer_shared =
+ a->BitFieldValue<JSArrayBuffer::IsShared>(a->LoadObjectField(
+ a->LoadObjectField(tagged, JSTypedArray::kBufferOffset),
+ JSArrayBuffer::kBitFieldOffset));
+ a->Branch(is_buffer_shared, &is_shared, &not_shared);
+ a->Bind(&not_shared);
+ a->Goto(&invalid);
+
+ // Check if the array's element type is float32 or float64.
+ // TODO(binji): should fail on clamped as well.
+ a->Bind(&is_shared);
+ Node* elements_instance_type =
+ a->InstanceType(a->LoadObjectField(tagged, JSObject::kElementsOffset));
+ a->Branch(a->WordOr(a->WordEqual(elements_instance_type,
+ a->Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)),
+ a->WordEqual(elements_instance_type,
+ a->Int32Constant(FIXED_FLOAT64_ARRAY_TYPE))),
+ &is_float, &not_float);
+ a->Bind(&is_float);
+ a->Goto(&invalid);
+
+ a->Bind(&invalid);
+ a->TailCallRuntime(Runtime::kThrowNotIntegerSharedTypedArrayError, context,
+ tagged);
+
+ a->Bind(&not_float);
+}
+
+
+compiler::Node* TaggedNumberAsWord32(compiler::CodeStubAssembler* a,
+ compiler::Node* tagged) {
+ using namespace compiler;
+ CodeStubAssembler::Label is_smi(a), is_not_smi(a), is_word(a);
+ CodeStubAssembler::Variable result(a, MachineRepresentation::kWord32);
+
+ a->Branch(a->WordIsSmi(tagged), &is_smi, &is_not_smi);
+
+ a->Bind(&is_smi);
+ result.Bind(a->SmiUntag(tagged));
+ a->Goto(&is_word);
+
+ a->Bind(&is_not_smi);
+ result.Bind(a->ChangeFloat64ToUint32(a->LoadHeapNumber(tagged)));
+ a->Goto(&is_word);
+
+ a->Bind(&is_word);
+ return result.value();
+}
+
+
+compiler::Node* ConvertTaggedAtomicIndexToWord32(compiler::CodeStubAssembler* a,
+ compiler::Node* tagged) {
+ using namespace compiler;
+ CodeStubAssembler::Label is_smi(a), is_not_smi(a), is_string(a),
+ is_not_string(a), strings_equal(a), strings_not_equal(a),
+ string_number_is_smi(a), string_number_is_not_smi(a), is_number(a),
+ convert_number(a), is_unknown(a), is_integer(a), is_not_integer(a),
+ is_word(a), invalid(a);
+ CodeStubAssembler::Variable number(a, MachineRepresentation::kTagged);
+ CodeStubAssembler::Variable word(a, MachineRepresentation::kWord32);
+ Node* context = a->Context();
+
+ // Check if the index's type is a Smi.
+ a->Branch(a->WordIsSmi(tagged), &is_smi, &is_not_smi);
+
+ // Check if the index's type is a String.
+ a->Bind(&is_not_smi);
+ Node* instance_type = a->InstanceType(tagged);
+ a->Branch(a->WordEqual(
+ a->WordAnd(instance_type, a->Int32Constant(kIsNotStringMask)),
+ a->Int32Constant(0)),
+ &is_string, &is_not_string);
+
+ // Check that converting the string to a number and back is equal to itself.
+ a->Bind(&is_string);
+ Node* string_as_number =
+ a->CallRuntime(Runtime::kStringToNumber, context, tagged);
+ a->Branch(
+ a->WordEqual(a->CallRuntime(Runtime::kStringEquals, context,
+ a->CallRuntime(Runtime::kNumberToString,
+ context, string_as_number),
+ tagged),
+ a->Int32Constant(EQUAL)),
+ &strings_equal, &strings_not_equal);
+
+ a->Bind(&strings_not_equal);
+ a->Goto(&invalid);
+
+ // Check if the string converted to a number is a Smi.
+ a->Bind(&strings_equal);
+ a->Branch(a->WordIsSmi(string_as_number), &string_number_is_smi,
+ &string_number_is_not_smi);
+
+ // If the string-number is a Smi, untag it.
+ a->Bind(&string_number_is_smi);
+ word.Bind(a->SmiUntag(string_as_number));
+ a->Goto(&is_word);
+
+ // If the string-number is a HeapNumber, convert it to a word32.
+ a->Bind(&string_number_is_not_smi);
+ number.Bind(string_as_number);
+ a->Goto(&convert_number);
+
+ // Check if the index's type is a HeapNumber.
+ a->Bind(&is_not_string);
+ a->Branch(a->WordEqual(instance_type, a->Int32Constant(HEAP_NUMBER_TYPE)),
+ &is_number, &is_unknown);
+
+ // Index is an invalid type, throw.
+ a->Bind(&is_unknown);
+ a->Goto(&invalid);
+
+ a->Bind(&is_number);
+ number.Bind(tagged);
+ a->Goto(&convert_number);
+
+ // Convert index from a HeapNumber to a word32.
+ a->Bind(&convert_number);
+ Node* number_value = a->LoadHeapNumber(number.value());
+ word.Bind(a->ChangeFloat64ToUint32(number_value));
+
+ // Check that the index is an integer.
+ a->Branch(
+ a->Float64Equal(a->ChangeUint32ToFloat64(word.value()), number_value),
+ &is_integer, &is_not_integer);
+
+ a->Bind(&is_not_integer);
+ a->Goto(&invalid);
+
+ a->Bind(&is_integer);
+ a->Goto(&is_word);
+
+ // Index is a Smi, untag.
+ a->Bind(&is_smi);
+ word.Bind(a->SmiUntag(tagged));
+ a->Goto(&is_word);
+
+ a->Bind(&invalid);
+ a->TailCallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context);
+
+ a->Bind(&is_word);
+ return word.value();
+}
+
+
+void ValidateAtomicIndex(compiler::CodeStubAssembler* a,
+ compiler::Node* index_word,
+ compiler::Node* array_length_word) {
+ using namespace compiler;
+ // Check if the index is in bounds. If not, throw RangeError.
+ CodeStubAssembler::Label in_bounds(a), not_in_bounds(a);
+ a->Branch(
+ a->WordOr(a->Int32LessThan(index_word, a->Int32Constant(0)),
+ a->Int32GreaterThanOrEqual(index_word, array_length_word)),
+ &not_in_bounds, &in_bounds);
+ a->Bind(&not_in_bounds);
+ a->TailCallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError,
+ a->Context());
+ a->Bind(&in_bounds);
+}
+
+} // anonymous namespace
+
+
+void Builtins::Generate_AtomicsLoadCheck(MacroAssembler* masm) {
+ using namespace compiler;
+ Isolate* isolate = masm->isolate();
+ Zone zone;
+ CodeStubAssembler a(isolate, &zone, 2, Code::ComputeFlags(Code::STUB),
+ "AtomicsLoadCheck");
+
+ Node* array = a.Parameter(0);
+ Node* index = a.Parameter(1);
+ ValidateSharedTypedArray(&a, array);
+ Node* index_word = ConvertTaggedAtomicIndexToWord32(&a, index);
+ Node* array_length_word = TaggedNumberAsWord32(
+ &a, a.LoadObjectField(array, JSTypedArray::kLengthOffset));
+ ValidateAtomicIndex(&a, index_word, array_length_word);
+
+ AtomicsLoadStub stub(isolate);
+ // TODO(binji): can't just re-tag index, because it might be out of range.
+ // Can we just pass the untagged index value to the code stub?
+ Node* stub_args[] = {array, a.SmiTag(index_word), a.Context()};
+ a.TailCallStub(stub, stub_args);
+
+ masm->Jump(a.GenerateCode(), RelocInfo::CODE_TARGET);
binji 2016/02/12 01:46:56 Is this right? I've seen some errors when I run ce
+}
+
+
#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \
Handle<Code> Builtins::name() { \
Code** code_address = \
« no previous file with comments | « src/builtins.h ('k') | src/code-factory.h » ('j') | src/compiler/code-stub-assembler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698