| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 // if args[1] is a data property on args[0] | 631 // if args[1] is a data property on args[0] |
| 632 // [false, value, Writeable, Enumerable, Configurable] | 632 // [false, value, Writeable, Enumerable, Configurable] |
| 633 // if args[1] is an accessor on args[0] | 633 // if args[1] is an accessor on args[0] |
| 634 // [true, GetFunction, SetFunction, Enumerable, Configurable] | 634 // [true, GetFunction, SetFunction, Enumerable, Configurable] |
| 635 static Object* Runtime_GetOwnProperty(Arguments args) { | 635 static Object* Runtime_GetOwnProperty(Arguments args) { |
| 636 ASSERT(args.length() == 2); | 636 ASSERT(args.length() == 2); |
| 637 HandleScope scope; | 637 HandleScope scope; |
| 638 Handle<FixedArray> elms = Factory::NewFixedArray(DESCRIPTOR_SIZE); | 638 Handle<FixedArray> elms = Factory::NewFixedArray(DESCRIPTOR_SIZE); |
| 639 Handle<JSArray> desc = Factory::NewJSArrayWithElements(elms); | 639 Handle<JSArray> desc = Factory::NewJSArrayWithElements(elms); |
| 640 LookupResult result; | 640 LookupResult result; |
| 641 CONVERT_CHECKED(JSObject, obj, args[0]); | 641 CONVERT_ARG_CHECKED(JSObject, obj, 0); |
| 642 CONVERT_CHECKED(String, name, args[1]); | 642 CONVERT_ARG_CHECKED(String, name, 1); |
| 643 | 643 |
| 644 // This could be an element. | 644 // This could be an element. |
| 645 uint32_t index; | 645 uint32_t index; |
| 646 if (name->AsArrayIndex(&index)) { | 646 if (name->AsArrayIndex(&index)) { |
| 647 switch (obj->HasLocalElement(index)) { | 647 switch (obj->HasLocalElement(index)) { |
| 648 case JSObject::UNDEFINED_ELEMENT: | 648 case JSObject::UNDEFINED_ELEMENT: |
| 649 return Heap::undefined_value(); | 649 return Heap::undefined_value(); |
| 650 | 650 |
| 651 case JSObject::STRING_CHARACTER_ELEMENT: { | 651 case JSObject::STRING_CHARACTER_ELEMENT: { |
| 652 // Special handling of string objects according to ECMAScript 5 | 652 // Special handling of string objects according to ECMAScript 5 |
| 653 // 15.5.5.2. Note that this might be a string object with elements | 653 // 15.5.5.2. Note that this might be a string object with elements |
| 654 // other than the actual string value. This is covered by the | 654 // other than the actual string value. This is covered by the |
| 655 // subsequent cases. | 655 // subsequent cases. |
| 656 JSValue* js_value = JSValue::cast(obj); | 656 Handle<JSValue> js_value = Handle<JSValue>::cast(obj); |
| 657 String* str = String::cast(js_value->value()); | 657 Handle<String> str(String::cast(js_value->value())); |
| 658 Handle<String> substr = SubString(str, index, index+1, NOT_TENURED); |
| 659 |
| 658 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 660 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 659 elms->set(VALUE_INDEX, str->SubString(index, index+1)); | 661 elms->set(VALUE_INDEX, *substr); |
| 660 elms->set(WRITABLE_INDEX, Heap::false_value()); | 662 elms->set(WRITABLE_INDEX, Heap::false_value()); |
| 661 elms->set(ENUMERABLE_INDEX, Heap::false_value()); | 663 elms->set(ENUMERABLE_INDEX, Heap::false_value()); |
| 662 elms->set(CONFIGURABLE_INDEX, Heap::false_value()); | 664 elms->set(CONFIGURABLE_INDEX, Heap::false_value()); |
| 663 return *desc; | 665 return *desc; |
| 664 } | 666 } |
| 665 | 667 |
| 666 case JSObject::INTERCEPTED_ELEMENT: | 668 case JSObject::INTERCEPTED_ELEMENT: |
| 667 case JSObject::FAST_ELEMENT: | 669 case JSObject::FAST_ELEMENT: { |
| 668 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 670 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 669 elms->set(VALUE_INDEX, obj->GetElement(index)); | 671 Handle<Object> element = GetElement(Handle<Object>(obj), index); |
| 672 elms->set(VALUE_INDEX, *element); |
| 670 elms->set(WRITABLE_INDEX, Heap::true_value()); | 673 elms->set(WRITABLE_INDEX, Heap::true_value()); |
| 671 elms->set(ENUMERABLE_INDEX, Heap::true_value()); | 674 elms->set(ENUMERABLE_INDEX, Heap::true_value()); |
| 672 elms->set(CONFIGURABLE_INDEX, Heap::true_value()); | 675 elms->set(CONFIGURABLE_INDEX, Heap::true_value()); |
| 673 return *desc; | 676 return *desc; |
| 677 } |
| 674 | 678 |
| 675 case JSObject::DICTIONARY_ELEMENT: { | 679 case JSObject::DICTIONARY_ELEMENT: { |
| 676 NumberDictionary* dictionary = obj->element_dictionary(); | 680 NumberDictionary* dictionary = obj->element_dictionary(); |
| 677 int entry = dictionary->FindEntry(index); | 681 int entry = dictionary->FindEntry(index); |
| 678 ASSERT(entry != NumberDictionary::kNotFound); | 682 ASSERT(entry != NumberDictionary::kNotFound); |
| 679 PropertyDetails details = dictionary->DetailsAt(entry); | 683 PropertyDetails details = dictionary->DetailsAt(entry); |
| 680 switch (details.type()) { | 684 switch (details.type()) { |
| 681 case CALLBACKS: { | 685 case CALLBACKS: { |
| 682 // This is an accessor property with getter and/or setter. | 686 // This is an accessor property with getter and/or setter. |
| 683 FixedArray* callbacks = | 687 FixedArray* callbacks = |
| (...skipping 14 matching lines...) Expand all Loading... |
| 698 break; | 702 break; |
| 699 } | 703 } |
| 700 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum())); | 704 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum())); |
| 701 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete())); | 705 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete())); |
| 702 return *desc; | 706 return *desc; |
| 703 } | 707 } |
| 704 } | 708 } |
| 705 } | 709 } |
| 706 | 710 |
| 707 // Use recursive implementation to also traverse hidden prototypes | 711 // Use recursive implementation to also traverse hidden prototypes |
| 708 GetOwnPropertyImplementation(obj, name, &result); | 712 GetOwnPropertyImplementation(*obj, *name, &result); |
| 709 | 713 |
| 710 if (!result.IsProperty()) { | 714 if (!result.IsProperty()) { |
| 711 return Heap::undefined_value(); | 715 return Heap::undefined_value(); |
| 712 } | 716 } |
| 713 if (result.type() == CALLBACKS) { | 717 if (result.type() == CALLBACKS) { |
| 714 Object* structure = result.GetCallbackObject(); | 718 Object* structure = result.GetCallbackObject(); |
| 715 if (structure->IsProxy() || structure->IsAccessorInfo()) { | 719 if (structure->IsProxy() || structure->IsAccessorInfo()) { |
| 716 // Property that is internally implemented as a callback or | 720 // Property that is internally implemented as a callback or |
| 717 // an API defined callback. | 721 // an API defined callback. |
| 718 Object* value = obj->GetPropertyWithCallback( | 722 Object* value = obj->GetPropertyWithCallback( |
| 719 obj, structure, name, result.holder()); | 723 *obj, structure, *name, result.holder()); |
| 724 if (value->IsFailure()) return value; |
| 720 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 725 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 721 elms->set(VALUE_INDEX, value); | 726 elms->set(VALUE_INDEX, value); |
| 722 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); | 727 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); |
| 723 } else if (structure->IsFixedArray()) { | 728 } else if (structure->IsFixedArray()) { |
| 724 // __defineGetter__/__defineSetter__ callback. | 729 // __defineGetter__/__defineSetter__ callback. |
| 725 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); | 730 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); |
| 726 elms->set(GETTER_INDEX, FixedArray::cast(structure)->get(0)); | 731 elms->set(GETTER_INDEX, FixedArray::cast(structure)->get(0)); |
| 727 elms->set(SETTER_INDEX, FixedArray::cast(structure)->get(1)); | 732 elms->set(SETTER_INDEX, FixedArray::cast(structure)->get(1)); |
| 728 } else { | 733 } else { |
| 729 return Heap::undefined_value(); | 734 return Heap::undefined_value(); |
| (...skipping 6800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7530 // If estimated number of elements is more than half of length, a | 7535 // If estimated number of elements is more than half of length, a |
| 7531 // fixed array (fast case) is more time and space-efficient than a | 7536 // fixed array (fast case) is more time and space-efficient than a |
| 7532 // dictionary. | 7537 // dictionary. |
| 7533 bool fast_case = (estimate_nof_elements * 2) >= result_length; | 7538 bool fast_case = (estimate_nof_elements * 2) >= result_length; |
| 7534 | 7539 |
| 7535 Handle<FixedArray> storage; | 7540 Handle<FixedArray> storage; |
| 7536 if (fast_case) { | 7541 if (fast_case) { |
| 7537 // The backing storage array must have non-existing elements to | 7542 // The backing storage array must have non-existing elements to |
| 7538 // preserve holes across concat operations. | 7543 // preserve holes across concat operations. |
| 7539 storage = Factory::NewFixedArrayWithHoles(result_length); | 7544 storage = Factory::NewFixedArrayWithHoles(result_length); |
| 7540 result->set_map(*Factory::GetFastElementsMap(Handle<Map>(result->map()))); | 7545 Handle<Map> fast_map = |
| 7546 Factory::GetFastElementsMap(Handle<Map>(result->map())); |
| 7547 result->set_map(*fast_map); |
| 7541 } else { | 7548 } else { |
| 7542 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate | 7549 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate |
| 7543 uint32_t at_least_space_for = estimate_nof_elements + | 7550 uint32_t at_least_space_for = estimate_nof_elements + |
| 7544 (estimate_nof_elements >> 2); | 7551 (estimate_nof_elements >> 2); |
| 7545 storage = Handle<FixedArray>::cast( | 7552 storage = Handle<FixedArray>::cast( |
| 7546 Factory::NewNumberDictionary(at_least_space_for)); | 7553 Factory::NewNumberDictionary(at_least_space_for)); |
| 7547 result->set_map(*Factory::GetSlowElementsMap(Handle<Map>(result->map()))); | 7554 Handle<Map> slow_map = |
| 7555 Factory::GetSlowElementsMap(Handle<Map>(result->map())); |
| 7556 result->set_map(*slow_map); |
| 7548 } | 7557 } |
| 7549 | 7558 |
| 7550 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length)); | 7559 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length)); |
| 7551 | 7560 |
| 7552 ArrayConcatVisitor visitor(storage, result_length, fast_case); | 7561 ArrayConcatVisitor visitor(storage, result_length, fast_case); |
| 7553 | 7562 |
| 7554 IterateArguments(arguments, &visitor); | 7563 IterateArguments(arguments, &visitor); |
| 7555 | 7564 |
| 7556 result->set_length(*len); | 7565 result->set_length(*len); |
| 7557 // Please note the storage might have changed in the visitor. | 7566 // Please note the storage might have changed in the visitor. |
| (...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9072 static Handle<Context> CopyWithContextChain(Handle<Context> context_chain, | 9081 static Handle<Context> CopyWithContextChain(Handle<Context> context_chain, |
| 9073 Handle<Context> function_context) { | 9082 Handle<Context> function_context) { |
| 9074 // At the bottom of the chain. Return the function context to link to. | 9083 // At the bottom of the chain. Return the function context to link to. |
| 9075 if (context_chain->is_function_context()) { | 9084 if (context_chain->is_function_context()) { |
| 9076 return function_context; | 9085 return function_context; |
| 9077 } | 9086 } |
| 9078 | 9087 |
| 9079 // Recursively copy the with contexts. | 9088 // Recursively copy the with contexts. |
| 9080 Handle<Context> previous(context_chain->previous()); | 9089 Handle<Context> previous(context_chain->previous()); |
| 9081 Handle<JSObject> extension(JSObject::cast(context_chain->extension())); | 9090 Handle<JSObject> extension(JSObject::cast(context_chain->extension())); |
| 9082 return Factory::NewWithContext( | 9091 Handle<Context> context = CopyWithContextChain(function_context, previous); |
| 9083 CopyWithContextChain(function_context, previous), | 9092 return Factory::NewWithContext(context, |
| 9084 extension, | 9093 extension, |
| 9085 context_chain->IsCatchContext()); | 9094 context_chain->IsCatchContext()); |
| 9086 } | 9095 } |
| 9087 | 9096 |
| 9088 | 9097 |
| 9089 // Helper function to find or create the arguments object for | 9098 // Helper function to find or create the arguments object for |
| 9090 // Runtime_DebugEvaluate. | 9099 // Runtime_DebugEvaluate. |
| 9091 static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame, | 9100 static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame, |
| 9092 Handle<JSFunction> function, | 9101 Handle<JSFunction> function, |
| 9093 Handle<SerializedScopeInfo> scope_info, | 9102 Handle<SerializedScopeInfo> scope_info, |
| 9094 const ScopeInfo<>* sinfo, | 9103 const ScopeInfo<>* sinfo, |
| 9095 Handle<Context> function_context) { | 9104 Handle<Context> function_context) { |
| (...skipping 1108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10204 } else { | 10213 } else { |
| 10205 // Handle last resort GC and make sure to allow future allocations | 10214 // Handle last resort GC and make sure to allow future allocations |
| 10206 // to grow the heap without causing GCs (if possible). | 10215 // to grow the heap without causing GCs (if possible). |
| 10207 Counters::gc_last_resort_from_js.Increment(); | 10216 Counters::gc_last_resort_from_js.Increment(); |
| 10208 Heap::CollectAllGarbage(false); | 10217 Heap::CollectAllGarbage(false); |
| 10209 } | 10218 } |
| 10210 } | 10219 } |
| 10211 | 10220 |
| 10212 | 10221 |
| 10213 } } // namespace v8::internal | 10222 } } // namespace v8::internal |
| OLD | NEW |