Commit 6da51b4b authored by fedor's avatar fedor Committed by Commit bot

TypedArray accessor detection: consider entire prototype chain

When looking up a special accessor for known TypedArray fields
("length", "byteLength", "byteOffset"), consider the entire prototype
chain, not only the direct prototype.
This allows subclasses of TypedArrays to benefit from fast specialized
accesses.

Review URL: https://codereview.chromium.org/1313493005

Cr-Commit-Position: refs/heads/master@{#30678}
parent ebd16fd8
...@@ -99,22 +99,37 @@ bool Accessors::IsJSArrayBufferViewFieldAccessor(Handle<Map> map, ...@@ -99,22 +99,37 @@ bool Accessors::IsJSArrayBufferViewFieldAccessor(Handle<Map> map,
Isolate* isolate = name->GetIsolate(); Isolate* isolate = name->GetIsolate();
switch (map->instance_type()) { switch (map->instance_type()) {
case JS_TYPED_ARRAY_TYPE: case JS_TYPED_ARRAY_TYPE: {
// %TypedArray%.prototype is non-configurable, and so are the following if (!CheckForName(name, isolate->factory()->length_string(),
// named properties on %TypedArray%.prototype, so we can directly inline JSTypedArray::kLengthOffset, object_offset) &&
// the field-load for typed array maps that still use their !CheckForName(name, isolate->factory()->byte_length_string(),
// %TypedArray%.prototype. JSTypedArray::kByteLengthOffset, object_offset) &&
if (JSFunction::cast(map->GetConstructor())->prototype() != !CheckForName(name, isolate->factory()->byte_offset_string(),
map->prototype()) { JSTypedArray::kByteOffsetOffset, object_offset)) {
return false; return false;
} }
return CheckForName(name, isolate->factory()->length_string(),
JSTypedArray::kLengthOffset, object_offset) ||
CheckForName(name, isolate->factory()->byte_length_string(),
JSTypedArray::kByteLengthOffset, object_offset) ||
CheckForName(name, isolate->factory()->byte_offset_string(),
JSTypedArray::kByteOffsetOffset, object_offset);
if (map->is_dictionary_map()) return false;
// Check if the property is overridden on the instance.
DescriptorArray* descriptors = map->instance_descriptors();
int descriptor = descriptors->SearchWithCache(*name, *map);
if (descriptor != DescriptorArray::kNotFound) return false;
Handle<Object> proto = Handle<Object>(map->prototype(), isolate);
if (!proto->IsJSReceiver()) return false;
// Check if the property is defined in the prototype chain.
LookupIterator it(proto, name);
if (!it.IsFound()) return false;
Object* original_proto =
JSFunction::cast(map->GetConstructor())->prototype();
// Property is not configurable. It is enough to verify that
// the holder is the same.
return *it.GetHolder<Object>() == original_proto;
}
case JS_DATA_VIEW_TYPE: case JS_DATA_VIEW_TYPE:
return CheckForName(name, isolate->factory()->byte_length_string(), return CheckForName(name, isolate->factory()->byte_length_string(),
JSDataView::kByteLengthOffset, object_offset) || JSDataView::kByteLengthOffset, object_offset) ||
......
...@@ -71,6 +71,43 @@ assertEquals(undefined, get(a)); ...@@ -71,6 +71,43 @@ assertEquals(undefined, get(a));
assertEquals(undefined, get(a)); assertEquals(undefined, get(a));
})(); })();
(function() {
"use strict";
class MyTypedArray extends Int32Array {
constructor(length) {
super(length);
}
}
a = new MyTypedArray(1024);
get = function(a) {
return a.length;
}
assertEquals(1024, get(a));
assertEquals(1024, get(a));
assertEquals(1024, get(a));
%OptimizeFunctionOnNextCall(get);
assertEquals(1024, get(a));
})();
(function() {
"use strict";
var a = new Uint8Array(4);
Object.defineProperty(a, "length", {get: function() { return "blah"; }});
get = function(a) {
return a.length;
}
assertEquals("blah", get(a));
assertEquals("blah", get(a));
assertEquals("blah", get(a));
%OptimizeFunctionOnNextCall(get);
assertEquals("blah", get(a));
})();
// Ensure we cannot delete length, byteOffset, byteLength. // Ensure we cannot delete length, byteOffset, byteLength.
assertTrue(Int32Array.prototype.hasOwnProperty("length")); assertTrue(Int32Array.prototype.hasOwnProperty("length"));
assertTrue(Int32Array.prototype.hasOwnProperty("byteOffset")); assertTrue(Int32Array.prototype.hasOwnProperty("byteOffset"));
......
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