ElementsAccessor::SetLength() handlified.

R=yangguo@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20090 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ishell@chromium.org 2014-03-19 16:29:19 +00:00
parent bdea3e9a8f
commit 158269c132
5 changed files with 92 additions and 73 deletions

View File

@ -548,18 +548,6 @@ static Handle<Object> ElementsAccessorGetWrapper(
} }
// TODO(ishell): Temporary wrapper until handlified.
static Handle<Object> ElementsAccessorSetLengthWrapper(
Isolate* isolate,
ElementsAccessor* accessor,
Handle<JSArray> array,
int new_length) {
CALL_HEAP_FUNCTION(isolate,
accessor->SetLength(*array, Smi::FromInt(new_length)),
Object);
}
BUILTIN(ArrayPop) { BUILTIN(ArrayPop) {
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<Object> receiver = args.receiver(); Handle<Object> receiver = args.receiver();
@ -588,8 +576,8 @@ BUILTIN(ArrayPop) {
} }
RETURN_IF_EMPTY_HANDLE(isolate, element); RETURN_IF_EMPTY_HANDLE(isolate, element);
RETURN_IF_EMPTY_HANDLE(isolate, RETURN_IF_EMPTY_HANDLE(isolate,
ElementsAccessorSetLengthWrapper( accessor->SetLength(
isolate, accessor, array, new_length)); array, handle(Smi::FromInt(new_length), isolate)));
return *element; return *element;
} }

View File

@ -160,11 +160,11 @@ static bool HasKey(FixedArray* array, Object* key) {
} }
static Failure* ThrowArrayLengthRangeError(Heap* heap) { static Handle<Object> ThrowArrayLengthRangeError(Isolate* isolate) {
HandleScope scope(heap->isolate()); isolate->Throw(
return heap->isolate()->Throw( *isolate->factory()->NewRangeError("invalid_array_length",
*heap->isolate()->factory()->NewRangeError("invalid_array_length", HandleVector<Object>(NULL, 0)));
HandleVector<Object>(NULL, 0))); return Handle<Object>();
} }
@ -737,25 +737,18 @@ class ElementsAccessorBase : public ElementsAccessor {
return NULL; return NULL;
} }
// TODO(ishell): Temporary wrapper until handlified.
MUST_USE_RESULT virtual Handle<Object> SetLength( MUST_USE_RESULT virtual Handle<Object> SetLength(
Handle<JSArray> array, Handle<JSArray> array,
Handle<Object> length) { Handle<Object> length) {
CALL_HEAP_FUNCTION(array->GetIsolate(), Isolate* isolate = array->GetIsolate();
SetLength(*array, *length),
Object);
}
MUST_USE_RESULT virtual MaybeObject* SetLength(JSArray* array,
Object* length) {
return ElementsAccessorSubclass::SetLengthImpl( return ElementsAccessorSubclass::SetLengthImpl(
array, length, array->elements()); array, length, handle(array->elements(), isolate));
} }
MUST_USE_RESULT static MaybeObject* SetLengthImpl( MUST_USE_RESULT static Handle<Object> SetLengthImpl(
JSObject* obj, Handle<JSObject> obj,
Object* length, Handle<Object> length,
FixedArrayBase* backing_store); Handle<FixedArrayBase> backing_store);
MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength( MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength(
JSArray* array, JSArray* array,
@ -994,6 +987,18 @@ class FastElementsAccessor
return array->GetHeap()->undefined_value(); return array->GetHeap()->undefined_value();
} }
// TODO(ishell): Temporary wrapper until handlified.
static Handle<Object> SetLengthWithoutNormalize(
Handle<FixedArrayBase> backing_store,
Handle<JSArray> array,
Handle<Object> length_object,
uint32_t length) {
CALL_HEAP_FUNCTION(array->GetIsolate(),
SetLengthWithoutNormalize(
*backing_store, *array, *length_object, length),
Object);
}
static MaybeObject* DeleteCommon(JSObject* obj, static MaybeObject* DeleteCommon(JSObject* obj,
uint32_t key, uint32_t key,
JSReceiver::DeleteMode mode) { JSReceiver::DeleteMode mode) {
@ -1382,10 +1387,10 @@ class TypedElementsAccessor
? FIELD : NONEXISTENT; ? FIELD : NONEXISTENT;
} }
MUST_USE_RESULT static MaybeObject* SetLengthImpl( MUST_USE_RESULT static Handle<Object> SetLengthImpl(
JSObject* obj, Handle<JSObject> obj,
Object* length, Handle<Object> length,
FixedArrayBase* backing_store) { Handle<FixedArrayBase> backing_store) {
// External arrays do not support changing their length. // External arrays do not support changing their length.
UNREACHABLE(); UNREACHABLE();
return obj; return obj;
@ -1493,6 +1498,18 @@ class DictionaryElementsAccessor
return length_object; return length_object;
} }
// TODO(ishell): Temporary wrapper until handlified.
MUST_USE_RESULT static Handle<Object> SetLengthWithoutNormalize(
Handle<FixedArrayBase> store,
Handle<JSArray> array,
Handle<Object> length_object,
uint32_t length) {
CALL_HEAP_FUNCTION(array->GetIsolate(),
SetLengthWithoutNormalize(
*store, *array, *length_object, length),
Object);
}
MUST_USE_RESULT static MaybeObject* DeleteCommon( MUST_USE_RESULT static MaybeObject* DeleteCommon(
JSObject* obj, JSObject* obj,
uint32_t key, uint32_t key,
@ -1736,10 +1753,10 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
} }
} }
MUST_USE_RESULT static MaybeObject* SetLengthImpl( MUST_USE_RESULT static Handle<Object> SetLengthImpl(
JSObject* obj, Handle<JSObject> obj,
Object* length, Handle<Object> length,
FixedArrayBase* parameter_map) { Handle<FixedArrayBase> parameter_map) {
// TODO(mstarzinger): This was never implemented but will be used once we // TODO(mstarzinger): This was never implemented but will be used once we
// correctly implement [[DefineOwnProperty]] on arrays. // correctly implement [[DefineOwnProperty]] on arrays.
UNIMPLEMENTED(); UNIMPLEMENTED();
@ -1851,23 +1868,24 @@ void ElementsAccessor::TearDown() {
template <typename ElementsAccessorSubclass, typename ElementsKindTraits> template <typename ElementsAccessorSubclass, typename ElementsKindTraits>
MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, MUST_USE_RESULT Handle<Object> ElementsAccessorBase<ElementsAccessorSubclass,
ElementsKindTraits>:: ElementsKindTraits>::
SetLengthImpl(JSObject* obj, SetLengthImpl(Handle<JSObject> obj,
Object* length, Handle<Object> length,
FixedArrayBase* backing_store) { Handle<FixedArrayBase> backing_store) {
JSArray* array = JSArray::cast(obj); Isolate* isolate = obj->GetIsolate();
Handle<JSArray> array = Handle<JSArray>::cast(obj);
// Fast case: The new length fits into a Smi. // Fast case: The new length fits into a Smi.
MaybeObject* maybe_smi_length = length->ToSmi(); Handle<Object> smi_length = Object::ToSmi(isolate, length);
Object* smi_length = Smi::FromInt(0);
if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { if (!smi_length.is_null() && smi_length->IsSmi()) {
const int value = Smi::cast(smi_length)->value(); const int value = Handle<Smi>::cast(smi_length)->value();
if (value >= 0) { if (value >= 0) {
Object* new_length; Handle<Object> new_length = ElementsAccessorSubclass::
MaybeObject* result = ElementsAccessorSubclass::
SetLengthWithoutNormalize(backing_store, array, smi_length, value); SetLengthWithoutNormalize(backing_store, array, smi_length, value);
if (!result->ToObject(&new_length)) return result; RETURN_IF_EMPTY_HANDLE_VALUE(isolate, new_length, new_length);
// even though the proposed length was a smi, new_length could // even though the proposed length was a smi, new_length could
// still be a heap number because SetLengthWithoutNormalize doesn't // still be a heap number because SetLengthWithoutNormalize doesn't
// allow the array length property to drop below the index of // allow the array length property to drop below the index of
@ -1875,14 +1893,14 @@ MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass,
ASSERT(new_length->IsSmi() || new_length->IsHeapNumber() || ASSERT(new_length->IsSmi() || new_length->IsHeapNumber() ||
new_length->IsUndefined()); new_length->IsUndefined());
if (new_length->IsSmi()) { if (new_length->IsSmi()) {
array->set_length(Smi::cast(new_length)); array->set_length(*Handle<Smi>::cast(new_length));
return array; return array;
} else if (new_length->IsHeapNumber()) { } else if (new_length->IsHeapNumber()) {
array->set_length(new_length); array->set_length(*new_length);
return array; return array;
} }
} else { } else {
return ThrowArrayLengthRangeError(array->GetHeap()); return ThrowArrayLengthRangeError(isolate);
} }
} }
@ -1891,30 +1909,28 @@ MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass,
if (length->IsNumber()) { if (length->IsNumber()) {
uint32_t value; uint32_t value;
if (length->ToArrayIndex(&value)) { if (length->ToArrayIndex(&value)) {
SeededNumberDictionary* dictionary; Handle<SeededNumberDictionary> dictionary =
MaybeObject* maybe_object = array->NormalizeElements(); JSObject::NormalizeElements(array);
if (!maybe_object->To(&dictionary)) return maybe_object; RETURN_IF_EMPTY_HANDLE_VALUE(isolate, dictionary, dictionary);
Object* new_length;
MaybeObject* result = DictionaryElementsAccessor:: Handle<Object> new_length = DictionaryElementsAccessor::
SetLengthWithoutNormalize(dictionary, array, length, value); SetLengthWithoutNormalize(dictionary, array, length, value);
if (!result->ToObject(&new_length)) return result; RETURN_IF_EMPTY_HANDLE_VALUE(isolate, new_length, new_length);
ASSERT(new_length->IsNumber()); ASSERT(new_length->IsNumber());
array->set_length(new_length); array->set_length(*new_length);
return array; return array;
} else { } else {
return ThrowArrayLengthRangeError(array->GetHeap()); return ThrowArrayLengthRangeError(isolate);
} }
} }
Factory* factory = isolate->factory();
// Fall-back case: The new length is not a number so make the array // Fall-back case: The new length is not a number so make the array
// size one and set only element to length. // size one and set only element to length.
FixedArray* new_backing_store; Handle<FixedArray> new_backing_store = factory->NewFixedArray(1);
MaybeObject* maybe_obj = array->GetHeap()->AllocateFixedArray(1); new_backing_store->set(0, *length);
if (!maybe_obj->To(&new_backing_store)) return maybe_obj; factory->SetContent(array, new_backing_store);
new_backing_store->set(0, length);
{ MaybeObject* result = array->SetContent(new_backing_store);
if (result->IsFailure()) return result;
}
return array; return array;
} }

View File

@ -112,8 +112,6 @@ class ElementsAccessor {
MUST_USE_RESULT virtual Handle<Object> SetLength( MUST_USE_RESULT virtual Handle<Object> SetLength(
Handle<JSArray> holder, Handle<JSArray> holder,
Handle<Object> new_length) = 0; Handle<Object> new_length) = 0;
MUST_USE_RESULT virtual MaybeObject* SetLength(JSArray* holder,
Object* new_length) = 0;
// Modifies both the length and capacity of a JSArray, resizing the underlying // Modifies both the length and capacity of a JSArray, resizing the underlying
// backing store as necessary. This method does NOT honor the semantics of // backing store as necessary. This method does NOT honor the semantics of

View File

@ -1031,6 +1031,21 @@ bool Object::IsNaN() {
} }
// static
Handle<Object> Object::ToSmi(Isolate* isolate, Handle<Object> object) {
if (object->IsSmi()) return object;
if (object->IsHeapNumber()) {
double value = Handle<HeapNumber>::cast(object)->value();
int int_value = FastD2I(value);
if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
return handle(Smi::FromInt(int_value), isolate);
}
}
return Handle<Object>();
}
// TODO(ishell): Use handlified version instead.
MaybeObject* Object::ToSmi() { MaybeObject* Object::ToSmi() {
if (IsSmi()) return this; if (IsSmi()) return this;
if (IsHeapNumber()) { if (IsHeapNumber()) {

View File

@ -1536,6 +1536,8 @@ class Object : public MaybeObject {
// Converts this to a Smi if possible. // Converts this to a Smi if possible.
// Failure is returned otherwise. // Failure is returned otherwise.
static MUST_USE_RESULT inline Handle<Object> ToSmi(Isolate* isolate,
Handle<Object> object);
MUST_USE_RESULT inline MaybeObject* ToSmi(); MUST_USE_RESULT inline MaybeObject* ToSmi();
void Lookup(Name* name, LookupResult* result); void Lookup(Name* name, LookupResult* result);