Version 2.2.13.
Implement Object.getOwnPropertyDescriptor for element indices and strings (issue 599).
Fix bug for windows 64 bit C calls from generated code.
Add new scons flag unalignedaccesses for arm builds.
Performance improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@4756 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/runtime.cc b/src/runtime.cc
index b421ac7..d53b13d 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -291,7 +291,7 @@
Handle<String> name(String::cast(*key));
ASSERT(!name->AsArrayIndex(&element_index));
result = SetProperty(boilerplate, name, value, NONE);
- } else if (Array::IndexFromObject(*key, &element_index)) {
+ } else if (key->ToArrayIndex(&element_index)) {
// Array index (uint32).
result = SetElement(boilerplate, element_index, value);
} else {
@@ -569,6 +569,18 @@
}
+// Enumerator used as indices into the array returned from GetOwnProperty
+enum PropertyDescriptorIndices {
+ IS_ACCESSOR_INDEX,
+ VALUE_INDEX,
+ GETTER_INDEX,
+ SETTER_INDEX,
+ WRITABLE_INDEX,
+ ENUMERABLE_INDEX,
+ CONFIGURABLE_INDEX,
+ DESCRIPTOR_SIZE
+};
+
// Returns an array with the property description:
// if args[1] is not a property on args[0]
// returns undefined
@@ -579,18 +591,63 @@
static Object* Runtime_GetOwnProperty(Arguments args) {
ASSERT(args.length() == 2);
HandleScope scope;
- Handle<FixedArray> elms = Factory::NewFixedArray(5);
+ Handle<FixedArray> elms = Factory::NewFixedArray(DESCRIPTOR_SIZE);
Handle<JSArray> desc = Factory::NewJSArrayWithElements(elms);
LookupResult result;
CONVERT_CHECKED(JSObject, obj, args[0]);
CONVERT_CHECKED(String, name, args[1]);
+ // This could be an element.
+ uint32_t index;
+ if (name->AsArrayIndex(&index)) {
+ if (!obj->HasLocalElement(index)) {
+ return Heap::undefined_value();
+ }
+
+ // Special handling of string objects according to ECMAScript 5 15.5.5.2.
+ // Note that this might be a string object with elements other than the
+ // actual string value. This is covered by the subsequent cases.
+ if (obj->IsStringObjectWithCharacterAt(index)) {
+ JSValue* js_value = JSValue::cast(obj);
+ String* str = String::cast(js_value->value());
+ elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
+ elms->set(VALUE_INDEX, str->SubString(index, index+1));
+ elms->set(WRITABLE_INDEX, Heap::false_value());
+ elms->set(ENUMERABLE_INDEX, Heap::false_value());
+ elms->set(CONFIGURABLE_INDEX, Heap::false_value());
+ return *desc;
+ }
+
+ // This can potentially be an element in the elements dictionary or
+ // a fast element.
+ if (obj->HasDictionaryElements()) {
+ NumberDictionary* dictionary = obj->element_dictionary();
+ int entry = dictionary->FindEntry(index);
+ PropertyDetails details = dictionary->DetailsAt(entry);
+ elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
+ elms->set(VALUE_INDEX, dictionary->ValueAt(entry));
+ elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete()));
+ elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum()));
+ elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly()));
+ return *desc;
+ } else {
+ // Elements that are stored as array elements always has:
+ // writable: true, configurable: true, enumerable: true.
+ elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
+ elms->set(VALUE_INDEX, obj->GetElement(index));
+ elms->set(WRITABLE_INDEX, Heap::true_value());
+ elms->set(ENUMERABLE_INDEX, Heap::true_value());
+ elms->set(CONFIGURABLE_INDEX, Heap::true_value());
+ return *desc;
+ }
+ }
+
// Use recursive implementation to also traverse hidden prototypes
GetOwnPropertyImplementation(obj, name, &result);
- if (!result.IsProperty())
+ if (!result.IsProperty()) {
return Heap::undefined_value();
-
+ }
if (result.type() == CALLBACKS) {
Object* structure = result.GetCallbackObject();
if (structure->IsProxy() || structure->IsAccessorInfo()) {
@@ -598,25 +655,25 @@
// an API defined callback.
Object* value = obj->GetPropertyWithCallback(
obj, structure, name, result.holder());
- elms->set(0, Heap::false_value());
- elms->set(1, value);
- elms->set(2, Heap::ToBoolean(!result.IsReadOnly()));
+ elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
+ elms->set(VALUE_INDEX, value);
+ elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly()));
} else if (structure->IsFixedArray()) {
// __defineGetter__/__defineSetter__ callback.
- elms->set(0, Heap::true_value());
- elms->set(1, FixedArray::cast(structure)->get(0));
- elms->set(2, FixedArray::cast(structure)->get(1));
+ elms->set(IS_ACCESSOR_INDEX, Heap::true_value());
+ elms->set(GETTER_INDEX, FixedArray::cast(structure)->get(0));
+ elms->set(SETTER_INDEX, FixedArray::cast(structure)->get(1));
} else {
return Heap::undefined_value();
}
} else {
- elms->set(0, Heap::false_value());
- elms->set(1, result.GetLazyValue());
- elms->set(2, Heap::ToBoolean(!result.IsReadOnly()));
+ elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
+ elms->set(VALUE_INDEX, result.GetLazyValue());
+ elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly()));
}
- elms->set(3, Heap::ToBoolean(!result.IsDontEnum()));
- elms->set(4, Heap::ToBoolean(!result.IsDontDelete()));
+ elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!result.IsDontEnum()));
+ elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!result.IsDontDelete()));
return *desc;
}
@@ -1583,7 +1640,7 @@
static Object* CharCodeAt(String* subject, Object* index) {
uint32_t i = 0;
- if (!Array::IndexFromObject(index, &i)) return Heap::nan_value();
+ if (!index->ToArrayIndex(&i)) return Heap::nan_value();
// Flatten the string. If someone wants to get a char at an index
// in a cons string, it is likely that more indices will be
// accessed.
@@ -1599,7 +1656,7 @@
static Object* CharFromCode(Object* char_code) {
uint32_t code;
- if (Array::IndexFromObject(char_code, &code)) {
+ if (char_code->ToArrayIndex(&code)) {
if (code <= 0xffff) {
return Heap::LookupSingleCharacterStringFromCode(code);
}
@@ -2780,7 +2837,7 @@
Object* index = args[2];
uint32_t start_index;
- if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
+ if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
int position = Runtime::StringMatch(sub, pat, start_index);
@@ -2830,7 +2887,7 @@
Object* index = args[2];
uint32_t start_index;
- if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
+ if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
uint32_t pat_length = pat->length();
uint32_t sub_length = sub->length();
@@ -3657,7 +3714,7 @@
// Check if the given key is an array index.
uint32_t index;
- if (Array::IndexFromObject(*key, &index)) {
+ if (key->ToArrayIndex(&index)) {
return GetElementOrCharAt(object, index);
}
@@ -3843,7 +3900,7 @@
// Check if the given key is an array index.
uint32_t index;
- if (Array::IndexFromObject(*key, &index)) {
+ if (key->ToArrayIndex(&index)) {
// In Firefox/SpiderMonkey, Safari and Opera you can access the characters
// of a string using [] notation. We need to support this too in
// JavaScript.
@@ -3895,7 +3952,7 @@
// Check if the given key is an array index.
uint32_t index;
- if (Array::IndexFromObject(*key, &index)) {
+ if (key->ToArrayIndex(&index)) {
// In Firefox/SpiderMonkey, Safari and Opera you can access the characters
// of a string using [] notation. We need to support this too in
// JavaScript.
@@ -3942,7 +3999,7 @@
// Check if the given key is an array index.
uint32_t index;
- if (Array::IndexFromObject(*key, &index)) {
+ if (key->ToArrayIndex(&index)) {
// In Firefox/SpiderMonkey, Safari and Opera you can access the
// characters of a string using [] notation. In the case of a
// String object we just need to redirect the deletion to the
@@ -4355,7 +4412,7 @@
// Try to convert the key to an index. If successful and within
// index return the the argument from the frame.
uint32_t index;
- if (Array::IndexFromObject(args[0], &index) && index < n) {
+ if (args[0]->ToArrayIndex(&index) && index < n) {
return frame->GetParameter(index);
}
@@ -5287,6 +5344,25 @@
}
+static Object* Runtime_NumberToIntegerMapMinusZero(Arguments args) {
+ NoHandleAllocation ha;
+ ASSERT(args.length() == 1);
+
+ CONVERT_DOUBLE_CHECKED(number, args[0]);
+
+ // We do not include 0 so that we don't have to treat +0 / -0 cases.
+ if (number > 0 && number <= Smi::kMaxValue) {
+ return Smi::FromInt(static_cast<int>(number));
+ }
+
+ double double_value = DoubleToInteger(number);
+ // Map both -0 and +0 to +0.
+ if (double_value == 0) double_value = 0;
+
+ return Heap::NumberFromDouble(double_value);
+}
+
+
static Object* Runtime_NumberToJSUint32(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -6457,8 +6533,8 @@
if (obj->IsFailure()) return obj;
AssertNoAllocation no_gc;
- reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map());
- FixedArray* array = FixedArray::cast(obj);
+ FixedArray* array = reinterpret_cast<FixedArray*>(obj);
+ array->set_map(Heap::fixed_array_map());
array->set_length(length);
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
@@ -7747,8 +7823,8 @@
Handle<Object> key2 = args.at<Object>(2);
uint32_t index1, index2;
- if (!Array::IndexFromObject(*key1, &index1)
- || !Array::IndexFromObject(*key2, &index2)) {
+ if (!key1->ToArrayIndex(&index1)
+ || !key2->ToArrayIndex(&index2)) {
return Top::ThrowIllegalOperation();
}
@@ -7779,17 +7855,19 @@
for (int i = 0; i < keys_length; i++) {
Object* key = keys->get(i);
uint32_t index;
- if (!Array::IndexFromObject(key, &index) || index >= length) {
+ if (!key->ToArrayIndex(&index) || index >= length) {
// Zap invalid keys.
keys->set_undefined(i);
}
}
return *Factory::NewJSArrayWithElements(keys);
} else {
+ ASSERT(array->HasFastElements());
Handle<FixedArray> single_interval = Factory::NewFixedArray(2);
// -1 means start of array.
single_interval->set(0, Smi::FromInt(-1));
- uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
+ uint32_t actual_length =
+ static_cast<uint32_t>(FixedArray::cast(array->elements())->length());
uint32_t min_length = actual_length < length ? actual_length : length;
Handle<Object> length_object =
Factory::NewNumber(static_cast<double>(min_length));