Commit 885f0bc4 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[csa] Support typed arrays in Has(Own)Property

BUG=chromium:703226

Change-Id: Ic71ae018c0090b2142f1d732bcf9c94c65e81f83
Reviewed-on: https://chromium-review.googlesource.com/458917Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44110}
parent 565829f5
...@@ -80,7 +80,7 @@ TF_BUILTIN(ObjectHasOwnProperty, ObjectBuiltinsAssembler) { ...@@ -80,7 +80,7 @@ TF_BUILTIN(ObjectHasOwnProperty, ObjectBuiltinsAssembler) {
// Handle negative keys in the runtime. // Handle negative keys in the runtime.
GotoIf(IntPtrLessThan(var_index.value(), IntPtrConstant(0)), &call_runtime); GotoIf(IntPtrLessThan(var_index.value(), IntPtrConstant(0)), &call_runtime);
TryLookupElement(object, map, instance_type, var_index.value(), TryLookupElement(object, map, instance_type, var_index.value(),
&return_true, &return_false, &call_runtime); &return_true, &return_false, &return_false, &call_runtime);
} }
Bind(&return_true); Bind(&return_true);
Return(BooleanConstant(true)); Return(BooleanConstant(true));
......
...@@ -5147,7 +5147,7 @@ void CodeStubAssembler::TryGetOwnProperty( ...@@ -5147,7 +5147,7 @@ void CodeStubAssembler::TryGetOwnProperty(
void CodeStubAssembler::TryLookupElement(Node* object, Node* map, void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
Node* instance_type, Node* instance_type,
Node* intptr_index, Label* if_found, Node* intptr_index, Label* if_found,
Label* if_not_found, Label* if_absent, Label* if_not_found,
Label* if_bailout) { Label* if_bailout) {
// Handle special objects in runtime. // Handle special objects in runtime.
GotoIf(Int32LessThanOrEqual(instance_type, GotoIf(Int32LessThanOrEqual(instance_type,
...@@ -5158,7 +5158,8 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, ...@@ -5158,7 +5158,8 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
// TODO(verwaest): Support other elements kinds as well. // TODO(verwaest): Support other elements kinds as well.
Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this), Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this),
if_isfaststringwrapper(this), if_isslowstringwrapper(this), if_oob(this); if_isfaststringwrapper(this), if_isslowstringwrapper(this), if_oob(this),
if_typedarray(this);
// clang-format off // clang-format off
int32_t values[] = { int32_t values[] = {
// Handled by {if_isobjectorsmi}. // Handled by {if_isobjectorsmi}.
...@@ -5174,6 +5175,16 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, ...@@ -5174,6 +5175,16 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
SLOW_STRING_WRAPPER_ELEMENTS, SLOW_STRING_WRAPPER_ELEMENTS,
// Handled by {if_not_found}. // Handled by {if_not_found}.
NO_ELEMENTS, NO_ELEMENTS,
// Handled by {if_typed_array}.
UINT8_ELEMENTS,
INT8_ELEMENTS,
UINT16_ELEMENTS,
INT16_ELEMENTS,
UINT32_ELEMENTS,
INT32_ELEMENTS,
FLOAT32_ELEMENTS,
FLOAT64_ELEMENTS,
UINT8_CLAMPED_ELEMENTS,
}; };
Label* labels[] = { Label* labels[] = {
&if_isobjectorsmi, &if_isobjectorsmi, &if_isobjectorsmi, &if_isobjectorsmi, &if_isobjectorsmi, &if_isobjectorsmi,
...@@ -5183,6 +5194,15 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, ...@@ -5183,6 +5194,15 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
&if_isfaststringwrapper, &if_isfaststringwrapper,
&if_isslowstringwrapper, &if_isslowstringwrapper,
if_not_found, if_not_found,
&if_typedarray,
&if_typedarray,
&if_typedarray,
&if_typedarray,
&if_typedarray,
&if_typedarray,
&if_typedarray,
&if_typedarray,
&if_typedarray,
}; };
// clang-format on // clang-format on
STATIC_ASSERT(arraysize(values) == arraysize(labels)); STATIC_ASSERT(arraysize(values) == arraysize(labels));
...@@ -5239,6 +5259,15 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, ...@@ -5239,6 +5259,15 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found); GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found);
Goto(&if_isdictionary); Goto(&if_isdictionary);
} }
Bind(&if_typedarray);
{
Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
GotoIf(IsDetachedBuffer(buffer), if_absent);
Node* length = TryToIntptr(
LoadObjectField(object, JSTypedArray::kLengthOffset), if_bailout);
Branch(UintPtrLessThan(intptr_index, length), if_found, if_absent);
}
Bind(&if_oob); Bind(&if_oob);
{ {
// Positive OOB indices mean "not found", negative indices must be // Positive OOB indices mean "not found", negative indices must be
...@@ -7519,11 +7548,12 @@ Node* CodeStubAssembler::HasProperty( ...@@ -7519,11 +7548,12 @@ Node* CodeStubAssembler::HasProperty(
}; };
CodeStubAssembler::LookupInHolder lookup_element_in_holder = CodeStubAssembler::LookupInHolder lookup_element_in_holder =
[this, &return_true](Node* receiver, Node* holder, Node* holder_map, [this, &return_true, &return_false](
Node* holder_instance_type, Node* index, Node* receiver, Node* holder, Node* holder_map,
Label* next_holder, Label* if_bailout) { Node* holder_instance_type, Node* index, Label* next_holder,
Label* if_bailout) {
TryLookupElement(holder, holder_map, holder_instance_type, index, TryLookupElement(holder, holder_map, holder_instance_type, index,
&return_true, next_holder, if_bailout); &return_true, &return_false, next_holder, if_bailout);
}; };
TryPrototypeChainLookup(object, key, lookup_property_in_holder, TryPrototypeChainLookup(object, key, lookup_property_in_holder,
......
...@@ -1068,8 +1068,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -1068,8 +1068,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Variable* var_meta_storage, Variable* var_name_index, Variable* var_meta_storage, Variable* var_name_index,
Label* if_not_found, Label* if_bailout); Label* if_not_found, Label* if_bailout);
// This method jumps to if_found if the element is known to exist. To
// if_absent if it's known to not exist. To if_not_found if the prototype
// chain needs to be checked. And if_bailout if the lookup is unsupported.
void TryLookupElement(Node* object, Node* map, Node* instance_type, void TryLookupElement(Node* object, Node* map, Node* instance_type,
Node* intptr_index, Label* if_found, Node* intptr_index, Label* if_found, Label* if_absent,
Label* if_not_found, Label* if_bailout); Label* if_not_found, Label* if_bailout);
// This is a type of a lookup in holder generator function. In case of a // This is a type of a lookup in holder generator function. In case of a
......
...@@ -1027,25 +1027,29 @@ TEST(TryLookupElement) { ...@@ -1027,25 +1027,29 @@ TEST(TryLookupElement) {
CodeAssemblerTester data(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state()); CodeStubAssembler m(data.state());
enum Result { kFound, kNotFound, kBailout }; enum Result { kFound, kAbsent, kNotFound, kBailout };
{ {
Node* object = m.Parameter(0); Node* object = m.Parameter(0);
Node* index = m.SmiUntag(m.Parameter(1)); Node* index = m.SmiUntag(m.Parameter(1));
Node* expected_result = m.Parameter(2); Node* expected_result = m.Parameter(2);
Label passed(&m), failed(&m); Label passed(&m), failed(&m);
Label if_found(&m), if_not_found(&m), if_bailout(&m); Label if_found(&m), if_not_found(&m), if_bailout(&m), if_absent(&m);
Node* map = m.LoadMap(object); Node* map = m.LoadMap(object);
Node* instance_type = m.LoadMapInstanceType(map); Node* instance_type = m.LoadMapInstanceType(map);
m.TryLookupElement(object, map, instance_type, index, &if_found, m.TryLookupElement(object, map, instance_type, index, &if_found, &if_absent,
&if_not_found, &if_bailout); &if_not_found, &if_bailout);
m.Bind(&if_found); m.Bind(&if_found);
m.Branch(m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))), m.Branch(m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
&passed, &failed); &passed, &failed);
m.Bind(&if_absent);
m.Branch(m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kAbsent))),
&passed, &failed);
m.Bind(&if_not_found); m.Bind(&if_not_found);
m.Branch( m.Branch(
m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))), m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
...@@ -1074,6 +1078,7 @@ TEST(TryLookupElement) { ...@@ -1074,6 +1078,7 @@ TEST(TryLookupElement) {
Handle<Object> smi42(Smi::FromInt(42), isolate); Handle<Object> smi42(Smi::FromInt(42), isolate);
Handle<Object> expect_found(Smi::FromInt(kFound), isolate); Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
Handle<Object> expect_absent(Smi::FromInt(kAbsent), isolate);
Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate); Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate); Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate);
...@@ -1085,6 +1090,17 @@ TEST(TryLookupElement) { ...@@ -1085,6 +1090,17 @@ TEST(TryLookupElement) {
CHECK(!JSReceiver::HasElement(object, index).FromJust()); \ CHECK(!JSReceiver::HasElement(object, index).FromJust()); \
ft.CheckTrue(object, smi##index, expect_not_found); ft.CheckTrue(object, smi##index, expect_not_found);
#define CHECK_ABSENT(object, index) \
{ \
bool success; \
Handle<Smi> smi(Smi::FromInt(index), isolate); \
LookupIterator it = \
LookupIterator::PropertyOrElement(isolate, object, smi, &success); \
CHECK(success); \
CHECK(!JSReceiver::HasProperty(&it).FromJust()); \
ft.CheckTrue(object, smi, expect_absent); \
}
{ {
Handle<JSArray> object = factory->NewJSArray(0, FAST_SMI_ELEMENTS); Handle<JSArray> object = factory->NewJSArray(0, FAST_SMI_ELEMENTS);
AddElement(object, 0, smi0); AddElement(object, 0, smi0);
...@@ -1137,6 +1153,30 @@ TEST(TryLookupElement) { ...@@ -1137,6 +1153,30 @@ TEST(TryLookupElement) {
CHECK_NOT_FOUND(object, 42); CHECK_NOT_FOUND(object, 42);
} }
{
Handle<JSTypedArray> object = factory->NewJSTypedArray(INT32_ELEMENTS, 2);
Local<v8::ArrayBuffer> buffer = Utils::ToLocal(object->GetBuffer());
CHECK_EQ(INT32_ELEMENTS, object->map()->elements_kind());
CHECK_FOUND(object, 0);
CHECK_FOUND(object, 1);
CHECK_ABSENT(object, -10);
CHECK_ABSENT(object, 13);
CHECK_ABSENT(object, 42);
v8::ArrayBuffer::Contents contents = buffer->Externalize();
buffer->Neuter();
isolate->array_buffer_allocator()->Free(contents.Data(),
contents.ByteLength());
CHECK_ABSENT(object, 0);
CHECK_ABSENT(object, 1);
CHECK_ABSENT(object, -10);
CHECK_ABSENT(object, 13);
CHECK_ABSENT(object, 42);
}
{ {
Handle<JSFunction> constructor = isolate->string_function(); Handle<JSFunction> constructor = isolate->string_function();
Handle<JSObject> object = factory->NewJSObject(constructor); Handle<JSObject> object = factory->NewJSObject(constructor);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment