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 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 if (!result->IsProperty()) { | 562 if (!result->IsProperty()) { |
563 Object* proto = obj->GetPrototype(); | 563 Object* proto = obj->GetPrototype(); |
564 if (proto->IsJSObject() && | 564 if (proto->IsJSObject() && |
565 JSObject::cast(proto)->map()->is_hidden_prototype()) | 565 JSObject::cast(proto)->map()->is_hidden_prototype()) |
566 GetOwnPropertyImplementation(JSObject::cast(proto), | 566 GetOwnPropertyImplementation(JSObject::cast(proto), |
567 name, result); | 567 name, result); |
568 } | 568 } |
569 } | 569 } |
570 | 570 |
571 | 571 |
| 572 // Enumerator used as indices into the array returned from GetOwnProperty |
| 573 enum PropertyDescriptorIndices { |
| 574 IS_ACCESSOR_INDEX, |
| 575 VALUE_INDEX, |
| 576 GETTER_INDEX, |
| 577 SETTER_INDEX, |
| 578 WRITABLE_INDEX, |
| 579 ENUMERABLE_INDEX, |
| 580 CONFIGURABLE_INDEX, |
| 581 DESCRIPTOR_SIZE |
| 582 }; |
| 583 |
572 // Returns an array with the property description: | 584 // Returns an array with the property description: |
573 // if args[1] is not a property on args[0] | 585 // if args[1] is not a property on args[0] |
574 // returns undefined | 586 // returns undefined |
575 // if args[1] is a data property on args[0] | 587 // if args[1] is a data property on args[0] |
576 // [false, value, Writeable, Enumerable, Configurable] | 588 // [false, value, Writeable, Enumerable, Configurable] |
577 // if args[1] is an accessor on args[0] | 589 // if args[1] is an accessor on args[0] |
578 // [true, GetFunction, SetFunction, Enumerable, Configurable] | 590 // [true, GetFunction, SetFunction, Enumerable, Configurable] |
579 static Object* Runtime_GetOwnProperty(Arguments args) { | 591 static Object* Runtime_GetOwnProperty(Arguments args) { |
580 ASSERT(args.length() == 2); | 592 ASSERT(args.length() == 2); |
581 HandleScope scope; | 593 HandleScope scope; |
582 Handle<FixedArray> elms = Factory::NewFixedArray(5); | 594 Handle<FixedArray> elms = Factory::NewFixedArray(DESCRIPTOR_SIZE); |
583 Handle<JSArray> desc = Factory::NewJSArrayWithElements(elms); | 595 Handle<JSArray> desc = Factory::NewJSArrayWithElements(elms); |
584 LookupResult result; | 596 LookupResult result; |
585 CONVERT_CHECKED(JSObject, obj, args[0]); | 597 CONVERT_CHECKED(JSObject, obj, args[0]); |
586 CONVERT_CHECKED(String, name, args[1]); | 598 CONVERT_CHECKED(String, name, args[1]); |
587 | 599 |
| 600 // This could be an element. |
| 601 uint32_t index; |
| 602 if (name->AsArrayIndex(&index)) { |
| 603 if (!obj->HasLocalElement(index)) { |
| 604 return Heap::undefined_value(); |
| 605 } |
| 606 |
| 607 // Special handling of string objects according to ECMAScript 5 15.5.5.2. |
| 608 // Note that this might be a string object with elements other than the |
| 609 // actual string value. This is covered by the subsequent cases. |
| 610 if (obj->IsStringObjectWithCharacterAt(index)) { |
| 611 JSValue* js_value = JSValue::cast(obj); |
| 612 String* str = String::cast(js_value->value()); |
| 613 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 614 elms->set(VALUE_INDEX, str->SubString(index, index+1)); |
| 615 elms->set(WRITABLE_INDEX, Heap::false_value()); |
| 616 elms->set(ENUMERABLE_INDEX, Heap::false_value()); |
| 617 elms->set(CONFIGURABLE_INDEX, Heap::false_value()); |
| 618 return *desc; |
| 619 } |
| 620 |
| 621 // This can potentially be an element in the elements dictionary or |
| 622 // a fast element. |
| 623 if (obj->HasDictionaryElements()) { |
| 624 NumberDictionary* dictionary = obj->element_dictionary(); |
| 625 int entry = dictionary->FindEntry(index); |
| 626 PropertyDetails details = dictionary->DetailsAt(entry); |
| 627 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 628 elms->set(VALUE_INDEX, dictionary->ValueAt(entry)); |
| 629 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete())); |
| 630 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum())); |
| 631 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly())); |
| 632 return *desc; |
| 633 } else { |
| 634 // Elements that are stored as array elements always has: |
| 635 // writable: true, configurable: true, enumerable: true. |
| 636 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 637 elms->set(VALUE_INDEX, obj->GetElement(index)); |
| 638 elms->set(WRITABLE_INDEX, Heap::true_value()); |
| 639 elms->set(ENUMERABLE_INDEX, Heap::true_value()); |
| 640 elms->set(CONFIGURABLE_INDEX, Heap::true_value()); |
| 641 return *desc; |
| 642 } |
| 643 } |
| 644 |
588 // Use recursive implementation to also traverse hidden prototypes | 645 // Use recursive implementation to also traverse hidden prototypes |
589 GetOwnPropertyImplementation(obj, name, &result); | 646 GetOwnPropertyImplementation(obj, name, &result); |
590 | 647 |
591 if (!result.IsProperty()) | 648 if (!result.IsProperty()) { |
592 return Heap::undefined_value(); | 649 return Heap::undefined_value(); |
593 | 650 } |
594 if (result.type() == CALLBACKS) { | 651 if (result.type() == CALLBACKS) { |
595 Object* structure = result.GetCallbackObject(); | 652 Object* structure = result.GetCallbackObject(); |
596 if (structure->IsProxy() || structure->IsAccessorInfo()) { | 653 if (structure->IsProxy() || structure->IsAccessorInfo()) { |
597 // Property that is internally implemented as a callback or | 654 // Property that is internally implemented as a callback or |
598 // an API defined callback. | 655 // an API defined callback. |
599 Object* value = obj->GetPropertyWithCallback( | 656 Object* value = obj->GetPropertyWithCallback( |
600 obj, structure, name, result.holder()); | 657 obj, structure, name, result.holder()); |
601 elms->set(0, Heap::false_value()); | 658 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
602 elms->set(1, value); | 659 elms->set(VALUE_INDEX, value); |
603 elms->set(2, Heap::ToBoolean(!result.IsReadOnly())); | 660 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); |
604 } else if (structure->IsFixedArray()) { | 661 } else if (structure->IsFixedArray()) { |
605 // __defineGetter__/__defineSetter__ callback. | 662 // __defineGetter__/__defineSetter__ callback. |
606 elms->set(0, Heap::true_value()); | 663 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); |
607 elms->set(1, FixedArray::cast(structure)->get(0)); | 664 elms->set(GETTER_INDEX, FixedArray::cast(structure)->get(0)); |
608 elms->set(2, FixedArray::cast(structure)->get(1)); | 665 elms->set(SETTER_INDEX, FixedArray::cast(structure)->get(1)); |
609 } else { | 666 } else { |
610 return Heap::undefined_value(); | 667 return Heap::undefined_value(); |
611 } | 668 } |
612 } else { | 669 } else { |
613 elms->set(0, Heap::false_value()); | 670 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
614 elms->set(1, result.GetLazyValue()); | 671 elms->set(VALUE_INDEX, result.GetLazyValue()); |
615 elms->set(2, Heap::ToBoolean(!result.IsReadOnly())); | 672 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); |
616 } | 673 } |
617 | 674 |
618 elms->set(3, Heap::ToBoolean(!result.IsDontEnum())); | 675 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!result.IsDontEnum())); |
619 elms->set(4, Heap::ToBoolean(!result.IsDontDelete())); | 676 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!result.IsDontDelete())); |
620 return *desc; | 677 return *desc; |
621 } | 678 } |
622 | 679 |
623 | 680 |
624 static Object* Runtime_IsExtensible(Arguments args) { | 681 static Object* Runtime_IsExtensible(Arguments args) { |
625 ASSERT(args.length() == 1); | 682 ASSERT(args.length() == 1); |
626 CONVERT_CHECKED(JSObject, obj, args[0]); | 683 CONVERT_CHECKED(JSObject, obj, args[0]); |
627 return obj->map()->is_extensible() ? Heap::true_value() | 684 return obj->map()->is_extensible() ? Heap::true_value() |
628 : Heap::false_value(); | 685 : Heap::false_value(); |
629 } | 686 } |
(...skipping 9601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10231 } else { | 10288 } else { |
10232 // Handle last resort GC and make sure to allow future allocations | 10289 // Handle last resort GC and make sure to allow future allocations |
10233 // to grow the heap without causing GCs (if possible). | 10290 // to grow the heap without causing GCs (if possible). |
10234 Counters::gc_last_resort_from_js.Increment(); | 10291 Counters::gc_last_resort_from_js.Increment(); |
10235 Heap::CollectAllGarbage(false); | 10292 Heap::CollectAllGarbage(false); |
10236 } | 10293 } |
10237 } | 10294 } |
10238 | 10295 |
10239 | 10296 |
10240 } } // namespace v8::internal | 10297 } } // namespace v8::internal |
OLD | NEW |