Reviewers: Michael Achenbach,
Message:
Hello!
This one seems to be very important for node.js, as we inherit our Buffer
from
the Uint8Array.
Note that while we are doing some prototype twiddling:
https://github.com/nodejs/node/blob/f8152df5e815c98be702fe58753258b58f02c4ad/lib/buffer.js#L51
Buffer does not actually override neither of the accessors to the Uint8Array
properties. So it should still be optimizied into a field load.
Applying this fix improves performance in x10 times.
Thanks a lot!
Fedor.
Description:
[accessors] second-chance typed array field lookup
Give a second-chance when looking up accessor for the typed array field
(`length`, `byteLength`, `byteOffset`). Instead of just bailing out,
allow users to do a first-order inheritance from it.
BUG=
Please review this at https://codereview.chromium.org/1313493005/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+61, -9 lines):
M src/accessors.cc
M test/mjsunit/regress/regress-typedarray-length.js
Index: src/accessors.cc
diff --git a/src/accessors.cc b/src/accessors.cc
index
6544e7197c1283f50f9e686643650589f1ff7aab..3d67d8751d8863688aa8a18842945915de1bd3cd
100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -99,22 +99,52 @@ bool
Accessors::IsJSArrayBufferViewFieldAccessor(Handle<Map> map,
Isolate* isolate = name->GetIsolate();
switch (map->instance_type()) {
- case JS_TYPED_ARRAY_TYPE:
+ case JS_TYPED_ARRAY_TYPE: {
+ int offset;
+
+ if (Name::Equals(name, isolate->factory()->length_string())) {
+ offset = JSTypedArray::kLengthOffset;
+ } else if (Name::Equals(name,
isolate->factory()->byte_length_string())) {
+ offset = JSTypedArray::kByteLengthOffset;
+ } else if (Name::Equals(name,
isolate->factory()->byte_offset_string())) {
+ offset = JSTypedArray::kByteOffsetOffset;
+ } else {
+ return false;
+ }
+
+ Object* proto = map->prototype();
+ Object* original_proto =
+ JSFunction::cast(map->GetConstructor())->prototype();
+
// %TypedArray%.prototype is non-configurable, and so are the
following
// named properties on %TypedArray%.prototype, so we can directly
inline
// the field-load for typed array maps that still use their
// %TypedArray%.prototype.
- if (JSFunction::cast(map->GetConstructor())->prototype() !=
- map->prototype()) {
+ if (original_proto == proto) {
+ *object_offset = offset;
+ return true;
+ }
+
+ if (!proto->IsJSObject()) return false;
+
+ JSObject* js_proto = JSObject::cast(proto);
+
+ // Check if the typed array is a second order child of the original
+ // constructor
+ if (js_proto->map()->prototype() != original_proto) return false;
+
+ // If the middle-prototype does not override the fast property -
+ // return it's offset
+ Maybe<PropertyAttributes> maybe_attr =
+ JSReceiver::GetOwnPropertyAttributes(Handle<JSObject>(js_proto),
+ name);
+ if (maybe_attr.IsJust() && maybe_attr.FromJust() != ABSENT) {
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);
+ *object_offset = offset;
+ return true;
+ }
case JS_DATA_VIEW_TYPE:
return CheckForName(name, isolate->factory()->byte_length_string(),
JSDataView::kByteLengthOffset, object_offset) ||
Index: test/mjsunit/regress/regress-typedarray-length.js
diff --git a/test/mjsunit/regress/regress-typedarray-length.js
b/test/mjsunit/regress/regress-typedarray-length.js
index
cae55731f921ced9e26218d1b47631867aa71c30..4c76bde3c2739b92ecae67a7d81b73d975cef349
100644
--- a/test/mjsunit/regress/regress-typedarray-length.js
+++ b/test/mjsunit/regress/regress-typedarray-length.js
@@ -71,6 +71,28 @@ 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));
+})();
+
// Ensure we cannot delete length, byteOffset, byteLength.
assertTrue(Int32Array.prototype.hasOwnProperty("length"));
assertTrue(Int32Array.prototype.hasOwnProperty("byteOffset"));
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.