Commit 3c1f62ad authored by jkummerow's avatar jkummerow Committed by Commit bot

Unify ToArrayLength conversions

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

Cr-Commit-Position: refs/heads/master@{#31310}
parent d820268c
...@@ -198,18 +198,6 @@ void Accessors::ArrayLengthGetter( ...@@ -198,18 +198,6 @@ 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);
return false;
}
void Accessors::ArrayLengthSetter( void Accessors::ArrayLengthSetter(
v8::Local<v8::Name> name, v8::Local<v8::Name> name,
v8::Local<v8::Value> val, v8::Local<v8::Value> val,
...@@ -222,26 +210,9 @@ void Accessors::ArrayLengthSetter( ...@@ -222,26 +210,9 @@ void Accessors::ArrayLengthSetter(
Handle<Object> length_obj = Utils::OpenHandle(*val); Handle<Object> length_obj = Utils::OpenHandle(*val);
uint32_t length = 0; uint32_t length = 0;
if (!FastAsArrayLength(isolate, length_obj, &length)) { if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) {
Handle<Object> uint32_v; isolate->OptionalRescheduleException(false);
if (!Object::ToUint32(isolate, length_obj).ToHandle(&uint32_v)) { return;
isolate->OptionalRescheduleException(false);
return;
}
Handle<Object> number_v;
if (!Object::ToNumber(length_obj).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);
}
CHECK(uint32_v->ToArrayLength(&length));
} }
if (JSArray::ObservableSetLength(array, length).is_null()) { if (JSArray::ObservableSetLength(array, length).is_null()) {
...@@ -260,7 +231,6 @@ Handle<AccessorInfo> Accessors::ArrayLengthInfo( ...@@ -260,7 +231,6 @@ Handle<AccessorInfo> Accessors::ArrayLengthInfo(
} }
// //
// Accessors::StringLength // Accessors::StringLength
// //
......
...@@ -70,7 +70,7 @@ inline unsigned int FastD2UI(double x) { ...@@ -70,7 +70,7 @@ inline unsigned int FastD2UI(double x) {
inline float DoubleToFloat32(double x) { inline float DoubleToFloat32(double x) {
// TODO(yanggou): This static_cast is implementation-defined behaviour in C++, // TODO(yangguo): This static_cast is implementation-defined behaviour in C++,
// so we may need to do the conversion manually instead to match the spec. // so we may need to do the conversion manually instead to match the spec.
volatile float f = static_cast<float>(x); volatile float f = static_cast<float>(x);
return f; return f;
......
...@@ -2365,27 +2365,11 @@ void Struct::InitializeBody(int object_size) { ...@@ -2365,27 +2365,11 @@ void Struct::InitializeBody(int object_size) {
} }
bool Object::ToArrayLength(uint32_t* index) { bool Object::ToArrayLength(uint32_t* index) { return Object::ToUint32(index); }
if (IsSmi()) {
int value = Smi::cast(this)->value();
if (value < 0) return false;
*index = value;
return true;
}
if (IsHeapNumber()) {
double value = HeapNumber::cast(this)->value();
uint32_t uint_value = static_cast<uint32_t>(value);
if (value == static_cast<double>(uint_value)) {
*index = uint_value;
return true;
}
}
return false;
}
bool Object::ToArrayIndex(uint32_t* index) { bool Object::ToArrayIndex(uint32_t* index) {
return ToArrayLength(index) && *index != kMaxUInt32; return Object::ToUint32(index) && *index != kMaxUInt32;
} }
......
...@@ -715,15 +715,16 @@ bool Object::ToInt32(int32_t* value) { ...@@ -715,15 +715,16 @@ bool Object::ToInt32(int32_t* value) {
bool Object::ToUint32(uint32_t* value) { bool Object::ToUint32(uint32_t* value) {
if (IsSmi()) { if (IsSmi()) {
int num = Smi::cast(this)->value(); int num = Smi::cast(this)->value();
if (num >= 0) { if (num < 0) return false;
*value = static_cast<uint32_t>(num); *value = static_cast<uint32_t>(num);
return true; return true;
}
} }
if (IsHeapNumber()) { if (IsHeapNumber()) {
double num = HeapNumber::cast(this)->value(); double num = HeapNumber::cast(this)->value();
if (num >= 0 && FastUI2D(FastD2UI(num)) == num) { if (num < 0) return false;
*value = FastD2UI(num); uint32_t uint_value = FastD2UI(num);
if (FastUI2D(uint_value) == num) {
*value = uint_value;
return true; return true;
} }
} }
...@@ -6393,26 +6394,28 @@ bool JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o, ...@@ -6393,26 +6394,28 @@ bool JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o,
} }
// TODO(jkummerow): Consider unification with ArrayLengthSetter in accessors.cc. // Part of ES6 9.4.2.4 ArraySetLength.
bool AnythingToArrayLength(Isolate* isolate, Handle<Object> length_obj, // static
uint32_t* output) { bool JSArray::AnythingToArrayLength(Isolate* isolate,
Handle<Object> length_object,
uint32_t* output) {
// Fast path: check numbers and strings that can be converted directly // Fast path: check numbers and strings that can be converted directly
// and unobservably. // and unobservably.
if (length_obj->ToUint32(output)) return true; if (length_object->ToArrayLength(output)) return true;
if (length_obj->IsString() && if (length_object->IsString() &&
Handle<String>::cast(length_obj)->AsArrayIndex(output)) { Handle<String>::cast(length_object)->AsArrayIndex(output)) {
return true; return true;
} }
// Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength". // Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength".
// 3. Let newLen be ToUint32(Desc.[[Value]]). // 3. Let newLen be ToUint32(Desc.[[Value]]).
Handle<Object> uint32_v; Handle<Object> uint32_v;
if (!Object::ToUint32(isolate, length_obj).ToHandle(&uint32_v)) { if (!Object::ToUint32(isolate, length_object).ToHandle(&uint32_v)) {
// 4. ReturnIfAbrupt(newLen). // 4. ReturnIfAbrupt(newLen).
return false; return false;
} }
// 5. Let numberLen be ToNumber(Desc.[[Value]]). // 5. Let numberLen be ToNumber(Desc.[[Value]]).
Handle<Object> number_v; Handle<Object> number_v;
if (!Object::ToNumber(length_obj).ToHandle(&number_v)) { if (!Object::ToNumber(length_object).ToHandle(&number_v)) {
// 6. ReturnIfAbrupt(newLen). // 6. ReturnIfAbrupt(newLen).
return false; return false;
} }
...@@ -6423,7 +6426,8 @@ bool AnythingToArrayLength(Isolate* isolate, Handle<Object> length_obj, ...@@ -6423,7 +6426,8 @@ bool AnythingToArrayLength(Isolate* isolate, Handle<Object> length_obj,
isolate->Throw(*exception); isolate->Throw(*exception);
return false; return false;
} }
return uint32_v->ToArrayLength(output); CHECK(uint32_v->ToArrayLength(output));
return true;
} }
......
...@@ -10076,6 +10076,9 @@ class JSArray: public JSObject { ...@@ -10076,6 +10076,9 @@ class JSArray: public JSObject {
Handle<Object> name, PropertyDescriptor* desc, Handle<Object> name, PropertyDescriptor* desc,
ShouldThrow should_throw); ShouldThrow should_throw);
static bool AnythingToArrayLength(Isolate* isolate,
Handle<Object> length_object,
uint32_t* output);
static bool ArraySetLength(Isolate* isolate, Handle<JSArray> a, static bool ArraySetLength(Isolate* isolate, Handle<JSArray> a,
PropertyDescriptor* desc, PropertyDescriptor* desc,
ShouldThrow should_throw); ShouldThrow should_throw);
......
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