Reviewers: Jakob,
Message:
ptal
Description:
Add fast path for setting array.length
BUG=
Please review this at https://codereview.chromium.org/1195823002/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+47, -46 lines):
M src/accessors.h
M src/accessors.cc
M src/objects.h
Index: src/accessors.cc
diff --git a/src/accessors.cc b/src/accessors.cc
index
58db0024ea1b2f824e15fa634e07befa10aa5bc7..5743c7552f1ae7539dec267a87b3bdd6b5c705f5
100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -173,21 +173,6 @@ Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo(
//
-// The helper function will 'flatten' Number objects.
-Handle<Object> Accessors::FlattenNumber(Isolate* isolate,
- Handle<Object> value) {
- if (value->IsNumber() || !value->IsJSValue()) return value;
- Handle<JSValue> wrapper = Handle<JSValue>::cast(value);
- DCHECK(wrapper->GetIsolate()->native_context()->number_function()->
- has_initial_map());
- if (wrapper->map() == isolate->number_function()->initial_map()) {
- return handle(wrapper->value(), isolate);
- }
-
- return value;
-}
-
-
void Accessors::ArrayLengthGetter(
v8::Local<v8::Name> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
@@ -200,44 +185,64 @@ void Accessors::ArrayLengthGetter(
}
+// Tries to non-observably convert |value| to a valid array length.
+// Returns false if it fails.
+static bool FastAsArrayLength(Isolate* isolate, Handle<Object> value,
+ uint32_t* length) {
+ if (value->ToArrayLength(length)) return true;
+ // We don't support AsArrayLength, so use AsArrayIndex for now. This just
+ // misses out on kMaxUInt32.
+ if (value->IsString()) return String::cast(*value)->AsArrayIndex(length);
+ if (!value->IsJSValue()) return false;
+ Handle<JSValue> wrapper = Handle<JSValue>::cast(value);
+ DCHECK(wrapper->GetIsolate()
+ ->native_context()
+ ->number_function()
+ ->has_initial_map());
+ // Only support fast unwrapping for the initial map. Otherwise valueOf
might
+ // have been overwritten, in which case unwrapping is invalid.
+ if (wrapper->map() != isolate->number_function()->initial_map()) return
false;
+ return wrapper->value()->ToArrayIndex(length);
+}
+
+
void Accessors::ArrayLengthSetter(
v8::Local<v8::Name> name,
v8::Local<v8::Value> val,
const v8::PropertyCallbackInfo<void>& info) {
- // TODO(verwaest): Speed up.
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
HandleScope scope(isolate);
+
Handle<JSObject> object = Utils::OpenHandle(*info.This());
- Handle<Object> value = Utils::OpenHandle(*val);
+ Handle<JSArray> array = Handle<JSArray>::cast(object);
+ Handle<Object> length_obj = Utils::OpenHandle(*val);
+
+ uint32_t length = 0;
+ if (!FastAsArrayLength(isolate, length_obj, &length)) {
+ Handle<Object> uint32_v;
+ if (!Execution::ToUint32(isolate, length_obj).ToHandle(&uint32_v)) {
+ isolate->OptionalRescheduleException(false);
+ return;
+ }
- value = FlattenNumber(isolate, value);
+ Handle<Object> number_v;
+ if (!Execution::ToNumber(isolate, length_obj).ToHandle(&number_v)) {
+ isolate->OptionalRescheduleException(false);
+ return;
+ }
- Handle<JSArray> array_handle = Handle<JSArray>::cast(object);
- MaybeHandle<Object> maybe;
- Handle<Object> uint32_v;
- maybe = Execution::ToUint32(isolate, value);
- if (!maybe.ToHandle(&uint32_v)) {
- isolate->OptionalRescheduleException(false);
- return;
- }
- Handle<Object> number_v;
- maybe = Execution::ToNumber(isolate, value);
- if (!maybe.ToHandle(&number_v)) {
- isolate->OptionalRescheduleException(false);
- return;
- }
+ if (uint32_v->Number() != number_v->Number()) {
+ Handle<Object> exception = isolate->factory()->NewRangeError(
+ MessageTemplate::kInvalidArrayLength);
+ return isolate->ScheduleThrow(*exception);
+ }
- if (uint32_v->Number() == number_v->Number()) {
- uint32_t new_length = 0;
- CHECK(uint32_v->ToArrayLength(&new_length));
- maybe = JSArray::ObservableSetLength(array_handle, new_length);
- if (maybe.is_null()) isolate->OptionalRescheduleException(false);
- return;
+ CHECK(uint32_v->ToArrayLength(&length));
}
- Handle<Object> exception =
-
isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength);
- isolate->ScheduleThrow(*exception);
+ if (JSArray::ObservableSetLength(array, length).is_null()) {
+ isolate->OptionalRescheduleException(false);
+ }
}
Index: src/accessors.h
diff --git a/src/accessors.h b/src/accessors.h
index
d37b6b770cafa5db88b3ed2bf3ef0005e90590be..227af745b70a49328fbf9005eb5ed123c873b330
100644
--- a/src/accessors.h
+++ b/src/accessors.h
@@ -98,11 +98,6 @@ class Accessors : public AllStatic {
static Handle<ExecutableAccessorInfo> CloneAccessor(
Isolate* isolate,
Handle<ExecutableAccessorInfo> accessor);
-
-
- private:
- // Helper functions.
- static Handle<Object> FlattenNumber(Isolate* isolate, Handle<Object>
value);
};
} } // namespace v8::internal
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index
0cfee84e9ee14192b5ec994640a2e5af6dc1b2d3..6ec7ccc8ead2c81f2190649801f9b192fd9d7f44
100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -8577,6 +8577,7 @@ class Name: public HeapObject {
// Conversion.
inline bool AsArrayIndex(uint32_t* index);
+ inline bool AsArrayLength(uint32_t* index);
// If the name is private, it can only name own properties.
inline bool IsPrivate();
--
--
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.