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:
parent
bdea3e9a8f
commit
158269c132
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
130
src/elements.cc
130
src/elements.cc
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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()) {
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user