| Index: src/runtime.cc
|
| ===================================================================
|
| --- src/runtime.cc (revision 5530)
|
| +++ src/runtime.cc (working copy)
|
| @@ -637,56 +637,78 @@
|
| 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]);
|
| + CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
| + CONVERT_ARG_CHECKED(String, name, 1);
|
|
|
| // This could be an element.
|
| uint32_t index;
|
| if (name->AsArrayIndex(&index)) {
|
| - if (!obj->HasLocalElement(index)) {
|
| - return Heap::undefined_value();
|
| - }
|
| + switch (obj->HasLocalElement(index)) {
|
| + case JSObject::UNDEFINED_ELEMENT:
|
| + 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;
|
| - }
|
| + case JSObject::STRING_CHARACTER_ELEMENT: {
|
| + // 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.
|
| + Handle<JSValue> js_value = Handle<JSValue>::cast(obj);
|
| + Handle<String> str(String::cast(js_value->value()));
|
| + Handle<String> substr = SubString(str, index, index+1, NOT_TENURED);
|
|
|
| - // 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.IsReadOnly()));
|
| - elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum()));
|
| - elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete()));
|
| - 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;
|
| + elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
|
| + elms->set(VALUE_INDEX, *substr);
|
| + elms->set(WRITABLE_INDEX, Heap::false_value());
|
| + elms->set(ENUMERABLE_INDEX, Heap::false_value());
|
| + elms->set(CONFIGURABLE_INDEX, Heap::false_value());
|
| + return *desc;
|
| + }
|
| +
|
| + case JSObject::INTERCEPTED_ELEMENT:
|
| + case JSObject::FAST_ELEMENT: {
|
| + elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
|
| + Handle<Object> element = GetElement(Handle<Object>(obj), index);
|
| + elms->set(VALUE_INDEX, *element);
|
| + elms->set(WRITABLE_INDEX, Heap::true_value());
|
| + elms->set(ENUMERABLE_INDEX, Heap::true_value());
|
| + elms->set(CONFIGURABLE_INDEX, Heap::true_value());
|
| + return *desc;
|
| + }
|
| +
|
| + case JSObject::DICTIONARY_ELEMENT: {
|
| + NumberDictionary* dictionary = obj->element_dictionary();
|
| + int entry = dictionary->FindEntry(index);
|
| + ASSERT(entry != NumberDictionary::kNotFound);
|
| + PropertyDetails details = dictionary->DetailsAt(entry);
|
| + switch (details.type()) {
|
| + case CALLBACKS: {
|
| + // This is an accessor property with getter and/or setter.
|
| + FixedArray* callbacks =
|
| + FixedArray::cast(dictionary->ValueAt(entry));
|
| + elms->set(IS_ACCESSOR_INDEX, Heap::true_value());
|
| + elms->set(GETTER_INDEX, callbacks->get(0));
|
| + elms->set(SETTER_INDEX, callbacks->get(1));
|
| + break;
|
| + }
|
| + case NORMAL:
|
| + // This is a data property.
|
| + elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
|
| + elms->set(VALUE_INDEX, dictionary->ValueAt(entry));
|
| + elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly()));
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + break;
|
| + }
|
| + elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum()));
|
| + elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete()));
|
| + return *desc;
|
| + }
|
| }
|
| }
|
|
|
| // Use recursive implementation to also traverse hidden prototypes
|
| - GetOwnPropertyImplementation(obj, name, &result);
|
| + GetOwnPropertyImplementation(*obj, *name, &result);
|
|
|
| if (!result.IsProperty()) {
|
| return Heap::undefined_value();
|
| @@ -697,7 +719,8 @@
|
| // Property that is internally implemented as a callback or
|
| // an API defined callback.
|
| Object* value = obj->GetPropertyWithCallback(
|
| - obj, structure, name, result.holder());
|
| + *obj, structure, *name, result.holder());
|
| + if (value->IsFailure()) return value;
|
| elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
|
| elms->set(VALUE_INDEX, value);
|
| elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly()));
|
| @@ -3329,7 +3352,8 @@
|
| for (int i = 0; i < matches ; i++) {
|
| int from = offsets.at(i * 2);
|
| int to = offsets.at(i * 2 + 1);
|
| - elements->set(i, *Factory::NewSubString(subject, from, to));
|
| + Handle<String> match = Factory::NewSubString(subject, from, to);
|
| + elements->set(i, *match);
|
| }
|
| Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
|
| result->set_length(Smi::FromInt(matches));
|
| @@ -3680,9 +3704,10 @@
|
| // Arguments array to replace function is match, captures, index and
|
| // subject, i.e., 3 + capture count in total.
|
| Handle<FixedArray> elements = Factory::NewFixedArray(3 + capture_count);
|
| - elements->set(0, *Factory::NewSubString(subject,
|
| - match_start,
|
| - match_end));
|
| + Handle<String> match = Factory::NewSubString(subject,
|
| + match_start,
|
| + match_end);
|
| + elements->set(0, *match);
|
| for (int i = 1; i <= capture_count; i++) {
|
| int start = register_vector[i * 2];
|
| if (start >= 0) {
|
| @@ -5546,12 +5571,14 @@
|
| length);
|
|
|
| for (int i = num_copied_from_cache; i < length; ++i) {
|
| - elements->set(i, *LookupSingleCharacterStringFromCode(chars[i]));
|
| + Handle<Object> str = LookupSingleCharacterStringFromCode(chars[i]);
|
| + elements->set(i, *str);
|
| }
|
| } else {
|
| elements = Factory::NewFixedArray(length);
|
| for (int i = 0; i < length; ++i) {
|
| - elements->set(i, *LookupSingleCharacterStringFromCode(s->Get(i)));
|
| + Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i));
|
| + elements->set(i, *str);
|
| }
|
| }
|
|
|
| @@ -8083,14 +8110,18 @@
|
| // The backing storage array must have non-existing elements to
|
| // preserve holes across concat operations.
|
| storage = Factory::NewFixedArrayWithHoles(result_length);
|
| - result->set_map(*Factory::GetFastElementsMap(Handle<Map>(result->map())));
|
| + Handle<Map> fast_map =
|
| + Factory::GetFastElementsMap(Handle<Map>(result->map()));
|
| + result->set_map(*fast_map);
|
| } else {
|
| // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
|
| uint32_t at_least_space_for = estimate_nof_elements +
|
| (estimate_nof_elements >> 2);
|
| storage = Handle<FixedArray>::cast(
|
| Factory::NewNumberDictionary(at_least_space_for));
|
| - result->set_map(*Factory::GetSlowElementsMap(Handle<Map>(result->map())));
|
| + Handle<Map> slow_map =
|
| + Factory::GetSlowElementsMap(Handle<Map>(result->map()));
|
| + result->set_map(*slow_map);
|
| }
|
|
|
| Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length));
|
| @@ -8407,7 +8438,8 @@
|
| uint32_t index;
|
| if (name->AsArrayIndex(&index)) {
|
| Handle<FixedArray> details = Factory::NewFixedArray(2);
|
| - details->set(0, Runtime::GetElementOrCharAt(obj, index));
|
| + Object* element_or_char = Runtime::GetElementOrCharAt(obj, index);
|
| + details->set(0, element_or_char);
|
| details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
|
| return *Factory::NewJSArrayWithElements(details);
|
| }
|
| @@ -9209,7 +9241,8 @@
|
|
|
| // Fill in scope details.
|
| details->set(kScopeDetailsTypeIndex, Smi::FromInt(it.Type()));
|
| - details->set(kScopeDetailsObjectIndex, *it.ScopeObject());
|
| + Handle<JSObject> scope_object = it.ScopeObject();
|
| + details->set(kScopeDetailsObjectIndex, *scope_object);
|
|
|
| return *Factory::NewJSArrayWithElements(details);
|
| }
|
| @@ -9254,11 +9287,11 @@
|
| Handle<FixedArray> frames_array = Factory::NewFixedArray(frames_count);
|
| for (int i = 0; i < frames_count; i++) {
|
| Handle<JSObject> frame_value = Factory::NewJSObject(Top::object_function());
|
| - frame_value->SetProperty(
|
| - *address_str,
|
| - *Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address)),
|
| - NONE);
|
| + Handle<Object> frame_address =
|
| + Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address));
|
|
|
| + frame_value->SetProperty(*address_str, *frame_address, NONE);
|
| +
|
| // Get the stack walk text for this frame.
|
| Handle<String> frame_text;
|
| int frame_text_length = StrLength(frames[i].text);
|
| @@ -9604,10 +9637,10 @@
|
| // Recursively copy the with contexts.
|
| Handle<Context> previous(context_chain->previous());
|
| Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
|
| - return Factory::NewWithContext(
|
| - CopyWithContextChain(function_context, previous),
|
| - extension,
|
| - context_chain->IsCatchContext());
|
| + Handle<Context> context = CopyWithContextChain(function_context, previous);
|
| + return Factory::NewWithContext(context,
|
| + extension,
|
| + context_chain->IsCatchContext());
|
| }
|
|
|
|
|
|
|