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) {
HandleScope scope(isolate);
Handle<Object> receiver = args.receiver();
@ -588,8 +576,8 @@ BUILTIN(ArrayPop) {
}
RETURN_IF_EMPTY_HANDLE(isolate, element);
RETURN_IF_EMPTY_HANDLE(isolate,
ElementsAccessorSetLengthWrapper(
isolate, accessor, array, new_length));
accessor->SetLength(
array, handle(Smi::FromInt(new_length), isolate)));
return *element;
}

View File

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

View File

@ -112,8 +112,6 @@ class ElementsAccessor {
MUST_USE_RESULT virtual Handle<Object> SetLength(
Handle<JSArray> holder,
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
// 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() {
if (IsSmi()) return this;
if (IsHeapNumber()) {

View File

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