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

Unified Diff: src/accessors.cc

Issue 1195823002: Add fast path for setting length (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 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
« no previous file with comments | « src/accessors.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
Toon Verwaest 2015/06/19 20:48:57 I think this is actually wrong... Number.prototyp
Jakob Kummerow 2015/06/20 11:26:38 Good point, in addition to checking the wrapper's
+}
+
+
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);
+ }
}
« no previous file with comments | « src/accessors.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698