Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: src/objects.cc

Issue 376233002: Introduce a PrototypeIterator class and use it for prototype access (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: updates Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/allocation-site-scopes.h" 8 #include "src/allocation-site-scopes.h"
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/arguments.h" 10 #include "src/arguments.h"
(...skipping 10 matching lines...) Expand all
21 #include "src/field-index.h" 21 #include "src/field-index.h"
22 #include "src/full-codegen.h" 22 #include "src/full-codegen.h"
23 #include "src/hydrogen.h" 23 #include "src/hydrogen.h"
24 #include "src/isolate-inl.h" 24 #include "src/isolate-inl.h"
25 #include "src/log.h" 25 #include "src/log.h"
26 #include "src/lookup.h" 26 #include "src/lookup.h"
27 #include "src/macro-assembler.h" 27 #include "src/macro-assembler.h"
28 #include "src/mark-compact.h" 28 #include "src/mark-compact.h"
29 #include "src/objects-inl.h" 29 #include "src/objects-inl.h"
30 #include "src/objects-visiting-inl.h" 30 #include "src/objects-visiting-inl.h"
31 #include "src/prototype.h"
31 #include "src/safepoint-table.h" 32 #include "src/safepoint-table.h"
32 #include "src/string-search.h" 33 #include "src/string-search.h"
33 #include "src/string-stream.h" 34 #include "src/string-stream.h"
34 #include "src/utils.h" 35 #include "src/utils.h"
35 36
36 #ifdef ENABLE_DISASSEMBLER 37 #ifdef ENABLE_DISASSEMBLER
37 #include "src/disasm.h" 38 #include "src/disasm.h"
38 #include "src/disassembler.h" 39 #include "src/disassembler.h"
39 #endif 40 #endif
40 41
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 return map() != fun->initial_map() 795 return map() != fun->initial_map()
795 || !HasFastObjectElements() 796 || !HasFastObjectElements()
796 || !HasFastProperties(); 797 || !HasFastProperties();
797 } 798 }
798 799
799 800
800 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate, 801 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
801 Handle<Object> object, 802 Handle<Object> object,
802 Handle<Object> receiver, 803 Handle<Object> receiver,
803 uint32_t index) { 804 uint32_t index) {
804 Handle<Object> holder; 805 if (object->IsUndefined()) {
Toon Verwaest 2014/07/11 09:41:28 I think this condition should never occur. Reading
806 return isolate->factory()->undefined_value();
807 }
805 808
806 // Iterate up the prototype chain until an element is found or the null 809 // Iterate up the prototype chain until an element is found or the null
807 // prototype is encountered. 810 // prototype is encountered.
808 for (holder = object; 811 for (PrototypeIterator iter(isolate, object,
809 !holder->IsNull(); 812 object->IsJSProxy() || object->IsJSObject()
810 holder = Handle<Object>(holder->GetPrototype(isolate), isolate)) { 813 ? PrototypeIterator::START_AT_RECEIVER
811 if (!holder->IsJSObject()) { 814 : PrototypeIterator::START_AT_PROTOTYPE);
812 if (holder->IsJSProxy()) { 815 !iter.IsAtEnd(); iter.Advance()) {
813 return JSProxy::GetElementWithHandler( 816 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
814 Handle<JSProxy>::cast(holder), receiver, index); 817 return JSProxy::GetElementWithHandler(
815 } else if (holder->IsUndefined()) { 818 Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
816 // Undefined has no indexed properties. 819 index);
817 return isolate->factory()->undefined_value();
818 } else {
819 holder = Handle<Object>(holder->GetPrototype(isolate), isolate);
820 ASSERT(holder->IsJSObject());
821 }
822 } 820 }
821 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSObject());
Toon Verwaest 2014/07/11 09:41:28 This condition should be ensured by the iterator I
823 822
824 // Inline the case for JSObjects. Doing so significantly improves the 823 // Inline the case for JSObjects. Doing so significantly improves the
825 // performance of fetching elements where checking the prototype chain is 824 // performance of fetching elements where checking the prototype chain is
826 // necessary. 825 // necessary.
827 Handle<JSObject> js_object = Handle<JSObject>::cast(holder); 826 Handle<JSObject> js_object =
827 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
828 828
829 // Check access rights if needed. 829 // Check access rights if needed.
830 if (js_object->IsAccessCheckNeeded()) { 830 if (js_object->IsAccessCheckNeeded()) {
831 if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) { 831 if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
832 isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET); 832 isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
833 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 833 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
834 return isolate->factory()->undefined_value(); 834 return isolate->factory()->undefined_value();
835 } 835 }
836 } 836 }
837 837
838 if (js_object->HasIndexedInterceptor()) { 838 if (js_object->HasIndexedInterceptor()) {
839 return JSObject::GetElementWithInterceptor(js_object, receiver, index); 839 return JSObject::GetElementWithInterceptor(js_object, receiver, index);
840 } 840 }
841 841
842 if (js_object->elements() != isolate->heap()->empty_fixed_array()) { 842 if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
843 Handle<Object> result; 843 Handle<Object> result;
844 ASSIGN_RETURN_ON_EXCEPTION( 844 ASSIGN_RETURN_ON_EXCEPTION(
845 isolate, result, 845 isolate, result,
846 js_object->GetElementsAccessor()->Get(receiver, js_object, index), 846 js_object->GetElementsAccessor()->Get(receiver, js_object, index),
847 Object); 847 Object);
848 if (!result->IsTheHole()) return result; 848 if (!result->IsTheHole()) return result;
849 } 849 }
850 } 850 }
851 851
852 return isolate->factory()->undefined_value(); 852 return isolate->factory()->undefined_value();
853 } 853 }
854 854
855 855
856 Object* Object::GetPrototype(Isolate* isolate) { 856 Map* Object::GetRootMap(Isolate* isolate) {
857 DisallowHeapAllocation no_alloc; 857 DisallowHeapAllocation no_alloc;
858 if (IsSmi()) { 858 if (IsSmi()) {
859 Context* context = isolate->context()->native_context(); 859 Context* context = isolate->context()->native_context();
860 return context->number_function()->instance_prototype(); 860 return context->number_function()->initial_map();
861 } 861 }
862 862
863 HeapObject* heap_object = HeapObject::cast(this); 863 HeapObject* heap_object = HeapObject::cast(this);
864 864
865 // The object is either a number, a string, a boolean, 865 // The object is either a number, a string, a boolean,
866 // a real JS object, or a Harmony proxy. 866 // a real JS object, or a Harmony proxy.
867 if (heap_object->IsJSReceiver()) { 867 if (heap_object->IsJSReceiver()) {
868 return heap_object->map()->prototype(); 868 return heap_object->map();
869 } 869 }
870 Context* context = isolate->context()->native_context(); 870 Context* context = isolate->context()->native_context();
871 871
872 if (heap_object->IsHeapNumber()) { 872 if (heap_object->IsHeapNumber()) {
873 return context->number_function()->instance_prototype(); 873 return context->number_function()->initial_map();
874 } 874 }
875 if (heap_object->IsString()) { 875 if (heap_object->IsString()) {
876 return context->string_function()->instance_prototype(); 876 return context->string_function()->initial_map();
877 } 877 }
878 if (heap_object->IsSymbol()) { 878 if (heap_object->IsSymbol()) {
879 return context->symbol_function()->instance_prototype(); 879 return context->symbol_function()->initial_map();
880 } 880 }
881 if (heap_object->IsBoolean()) { 881 if (heap_object->IsBoolean()) {
882 return context->boolean_function()->instance_prototype(); 882 return context->boolean_function()->initial_map();
883 } else {
884 return isolate->heap()->null_value();
885 } 883 }
884 return isolate->heap()->null_value()->map();
886 } 885 }
887 886
888 887
889 Handle<Object> Object::GetPrototype(Isolate* isolate,
890 Handle<Object> object) {
891 return handle(object->GetPrototype(isolate), isolate);
892 }
893
894
895 Object* Object::GetHash() { 888 Object* Object::GetHash() {
896 // The object is either a number, a name, an odd-ball, 889 // The object is either a number, a name, an odd-ball,
897 // a real JS object, or a Harmony proxy. 890 // a real JS object, or a Harmony proxy.
898 if (IsNumber()) { 891 if (IsNumber()) {
899 uint32_t hash = ComputeLongHash(double_to_uint64(Number())); 892 uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
900 return Smi::FromInt(hash & Smi::kMaxValue); 893 return Smi::FromInt(hash & Smi::kMaxValue);
901 } 894 }
902 if (IsName()) { 895 if (IsName()) {
903 uint32_t hash = Name::cast(this)->Hash(); 896 uint32_t hash = Name::cast(this)->Hash();
904 return Smi::FromInt(hash); 897 return Smi::FromInt(hash);
(...skipping 2116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3021 } 3014 }
3022 3015
3023 3016
3024 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( 3017 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
3025 Handle<JSObject> object, 3018 Handle<JSObject> object,
3026 uint32_t index, 3019 uint32_t index,
3027 Handle<Object> value, 3020 Handle<Object> value,
3028 bool* found, 3021 bool* found,
3029 StrictMode strict_mode) { 3022 StrictMode strict_mode) {
3030 Isolate *isolate = object->GetIsolate(); 3023 Isolate *isolate = object->GetIsolate();
3031 for (Handle<Object> proto = handle(object->GetPrototype(), isolate); 3024 for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
3032 !proto->IsNull(); 3025 iter.Advance()) {
3033 proto = handle(proto->GetPrototype(isolate), isolate)) { 3026 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
3034 if (proto->IsJSProxy()) {
3035 return JSProxy::SetPropertyViaPrototypesWithHandler( 3027 return JSProxy::SetPropertyViaPrototypesWithHandler(
3036 Handle<JSProxy>::cast(proto), 3028 Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), object,
3037 object,
3038 isolate->factory()->Uint32ToString(index), // name 3029 isolate->factory()->Uint32ToString(index), // name
3039 value, 3030 value, NONE, strict_mode, found);
3040 NONE,
3041 strict_mode,
3042 found);
3043 } 3031 }
3044 Handle<JSObject> js_proto = Handle<JSObject>::cast(proto); 3032 Handle<JSObject> js_proto =
3033 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
3045 if (!js_proto->HasDictionaryElements()) { 3034 if (!js_proto->HasDictionaryElements()) {
3046 continue; 3035 continue;
3047 } 3036 }
3048 Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary()); 3037 Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary());
3049 int entry = dictionary->FindEntry(index); 3038 int entry = dictionary->FindEntry(index);
3050 if (entry != SeededNumberDictionary::kNotFound) { 3039 if (entry != SeededNumberDictionary::kNotFound) {
3051 PropertyDetails details = dictionary->DetailsAt(entry); 3040 PropertyDetails details = dictionary->DetailsAt(entry);
3052 if (details.type() == CALLBACKS) { 3041 if (details.type() == CALLBACKS) {
3053 *found = true; 3042 *found = true;
3054 Handle<Object> structure(dictionary->ValueAt(entry), isolate); 3043 Handle<Object> structure(dictionary->ValueAt(entry), isolate);
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
3512 if (result->IsFound()) return; 3501 if (result->IsFound()) return;
3513 3502
3514 LookupRealNamedPropertyInPrototypes(name, result); 3503 LookupRealNamedPropertyInPrototypes(name, result);
3515 } 3504 }
3516 3505
3517 3506
3518 void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name, 3507 void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name,
3519 LookupResult* result) { 3508 LookupResult* result) {
3520 DisallowHeapAllocation no_gc; 3509 DisallowHeapAllocation no_gc;
3521 Isolate* isolate = GetIsolate(); 3510 Isolate* isolate = GetIsolate();
3522 Heap* heap = isolate->heap(); 3511 for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd(); iter.Advance()) {
3523 for (Object* pt = GetPrototype(); 3512 if (iter.GetCurrent()->IsJSProxy()) {
3524 pt != heap->null_value(); 3513 return result->HandlerResult(JSProxy::cast(iter.GetCurrent()));
3525 pt = pt->GetPrototype(isolate)) {
3526 if (pt->IsJSProxy()) {
3527 return result->HandlerResult(JSProxy::cast(pt));
3528 } 3514 }
3529 JSObject::cast(pt)->LookupOwnRealNamedProperty(name, result); 3515 JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result);
3530 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); 3516 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
3531 if (result->IsFound()) return; 3517 if (result->IsFound()) return;
3532 } 3518 }
3533 result->NotFound(); 3519 result->NotFound();
3534 } 3520 }
3535 3521
3536 3522
3537 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, 3523 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
3538 LookupResult* result, 3524 LookupResult* result,
3539 Handle<Name> key, 3525 Handle<Name> key,
(...skipping 2822 matching lines...) Expand 10 before | Expand all | Expand 10 after
6362 6348
6363 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, 6349 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6364 KeyCollectionType type) { 6350 KeyCollectionType type) {
6365 USE(ContainsOnlyValidKeys); 6351 USE(ContainsOnlyValidKeys);
6366 Isolate* isolate = object->GetIsolate(); 6352 Isolate* isolate = object->GetIsolate();
6367 Handle<FixedArray> content = isolate->factory()->empty_fixed_array(); 6353 Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
6368 Handle<JSFunction> arguments_function( 6354 Handle<JSFunction> arguments_function(
6369 JSFunction::cast(isolate->sloppy_arguments_map()->constructor())); 6355 JSFunction::cast(isolate->sloppy_arguments_map()->constructor()));
6370 6356
6371 // Only collect keys if access is permitted. 6357 // Only collect keys if access is permitted.
6372 for (Handle<Object> p = object; 6358 for (PrototypeIterator iter(isolate, object,
6373 *p != isolate->heap()->null_value(); 6359 PrototypeIterator::START_AT_RECEIVER);
6374 p = Handle<Object>(p->GetPrototype(isolate), isolate)) { 6360 !iter.IsAtEnd(); iter.Advance()) {
6375 if (p->IsJSProxy()) { 6361 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6376 Handle<JSProxy> proxy(JSProxy::cast(*p), isolate); 6362 Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
6363 isolate);
6377 Handle<Object> args[] = { proxy }; 6364 Handle<Object> args[] = { proxy };
6378 Handle<Object> names; 6365 Handle<Object> names;
6379 ASSIGN_RETURN_ON_EXCEPTION( 6366 ASSIGN_RETURN_ON_EXCEPTION(
6380 isolate, names, 6367 isolate, names,
6381 Execution::Call(isolate, 6368 Execution::Call(isolate,
6382 isolate->proxy_enumerate(), 6369 isolate->proxy_enumerate(),
6383 object, 6370 object,
6384 ARRAY_SIZE(args), 6371 ARRAY_SIZE(args),
6385 args), 6372 args),
6386 FixedArray); 6373 FixedArray);
6387 ASSIGN_RETURN_ON_EXCEPTION( 6374 ASSIGN_RETURN_ON_EXCEPTION(
6388 isolate, content, 6375 isolate, content,
6389 FixedArray::AddKeysFromArrayLike( 6376 FixedArray::AddKeysFromArrayLike(
6390 content, Handle<JSObject>::cast(names)), 6377 content, Handle<JSObject>::cast(names)),
6391 FixedArray); 6378 FixedArray);
6392 break; 6379 break;
6393 } 6380 }
6394 6381
6395 Handle<JSObject> current(JSObject::cast(*p), isolate); 6382 Handle<JSObject> current(
6383 JSObject::cast(*PrototypeIterator::GetCurrent(iter)), isolate);
Toon Verwaest 2014/07/11 09:41:28 Handle<JSObject> current = Handle<JSObject>::cast(
6396 6384
6397 // Check access rights if required. 6385 // Check access rights if required.
6398 if (current->IsAccessCheckNeeded() && 6386 if (current->IsAccessCheckNeeded() &&
6399 !isolate->MayNamedAccess( 6387 !isolate->MayNamedAccess(
6400 current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) { 6388 current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
6401 isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS); 6389 isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS);
6402 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); 6390 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6403 break; 6391 break;
6404 } 6392 }
6405 6393
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
6603 } 6591 }
6604 6592
6605 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); 6593 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name);
6606 accessors->SetComponents(*getter, *setter); 6594 accessors->SetComponents(*getter, *setter);
6607 6595
6608 SetPropertyCallback(object, name, accessors, attributes); 6596 SetPropertyCallback(object, name, accessors, attributes);
6609 } 6597 }
6610 6598
6611 6599
6612 bool Map::DictionaryElementsInPrototypeChainOnly() { 6600 bool Map::DictionaryElementsInPrototypeChainOnly() {
6613 Heap* heap = GetHeap();
6614
6615 if (IsDictionaryElementsKind(elements_kind())) { 6601 if (IsDictionaryElementsKind(elements_kind())) {
6616 return false; 6602 return false;
6617 } 6603 }
6618 6604
6619 for (Object* prototype = this->prototype(); 6605 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
6620 prototype != heap->null_value(); 6606 if (iter.GetCurrent()->IsJSProxy()) {
6621 prototype = prototype->GetPrototype(GetIsolate())) {
6622 if (prototype->IsJSProxy()) {
6623 // Be conservative, don't walk into proxies. 6607 // Be conservative, don't walk into proxies.
6624 return true; 6608 return true;
6625 } 6609 }
6626 6610
6627 if (IsDictionaryElementsKind( 6611 if (IsDictionaryElementsKind(
6628 JSObject::cast(prototype)->map()->elements_kind())) { 6612 JSObject::cast(iter.GetCurrent())->map()->elements_kind())) {
6629 return true; 6613 return true;
6630 } 6614 }
6631 } 6615 }
6632 6616
6633 return false; 6617 return false;
6634 } 6618 }
6635 6619
6636 6620
6637 void JSObject::SetElementCallback(Handle<JSObject> object, 6621 void JSObject::SetElementCallback(Handle<JSObject> object,
6638 uint32_t index, 6622 uint32_t index,
(...skipping 3480 matching lines...) Expand 10 before | Expand all | Expand 10 after
10119 instance_type = JS_OBJECT_TYPE; 10103 instance_type = JS_OBJECT_TYPE;
10120 instance_size = function->shared()->CalculateInstanceSize(); 10104 instance_size = function->shared()->CalculateInstanceSize();
10121 in_object_properties = function->shared()->CalculateInObjectProperties(); 10105 in_object_properties = function->shared()->CalculateInObjectProperties();
10122 } 10106 }
10123 Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size); 10107 Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
10124 10108
10125 // Fetch or allocate prototype. 10109 // Fetch or allocate prototype.
10126 Handle<Object> prototype; 10110 Handle<Object> prototype;
10127 if (function->has_instance_prototype()) { 10111 if (function->has_instance_prototype()) {
10128 prototype = handle(function->instance_prototype(), isolate); 10112 prototype = handle(function->instance_prototype(), isolate);
10129 for (Handle<Object> p = prototype; !p->IsNull() && !p->IsJSProxy(); 10113 for (PrototypeIterator iter(isolate, prototype,
10130 p = Object::GetPrototype(isolate, p)) { 10114 PrototypeIterator::START_AT_RECEIVER);
10131 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(p)); 10115 !iter.IsAtEnd(); iter.Advance()) {
10116 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
10117 break;
10118 }
10119 JSObject::OptimizeAsPrototype(
10120 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
10132 } 10121 }
10133 } else { 10122 } else {
10134 prototype = isolate->factory()->NewFunctionPrototype(function); 10123 prototype = isolate->factory()->NewFunctionPrototype(function);
10135 } 10124 }
10136 map->set_inobject_properties(in_object_properties); 10125 map->set_inobject_properties(in_object_properties);
10137 map->set_unused_property_fields(in_object_properties); 10126 map->set_unused_property_fields(in_object_properties);
10138 map->set_prototype(*prototype); 10127 map->set_prototype(*prototype);
10139 ASSERT(map->has_fast_object_elements()); 10128 ASSERT(map->has_fast_object_elements());
10140 10129
10141 // Finally link initial map and constructor function. 10130 // Finally link initial map and constructor function.
(...skipping 2049 matching lines...) Expand 10 before | Expand all | Expand 10 after
12191 Handle<Object> args[] = { object }; 12180 Handle<Object> args[] = { object };
12192 Handle<Object> error = isolate->factory()->NewTypeError( 12181 Handle<Object> error = isolate->factory()->NewTypeError(
12193 "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args))); 12182 "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args)));
12194 return isolate->Throw<Object>(error); 12183 return isolate->Throw<Object>(error);
12195 } 12184 }
12196 12185
12197 // Before we can set the prototype we need to be sure 12186 // Before we can set the prototype we need to be sure
12198 // prototype cycles are prevented. 12187 // prototype cycles are prevented.
12199 // It is sufficient to validate that the receiver is not in the new prototype 12188 // It is sufficient to validate that the receiver is not in the new prototype
12200 // chain. 12189 // chain.
12201 for (Object* pt = *value; 12190 for (PrototypeIterator iter(isolate, *value,
12202 pt != heap->null_value(); 12191 PrototypeIterator::START_AT_RECEIVER);
12203 pt = pt->GetPrototype(isolate)) { 12192 !iter.IsAtEnd(); iter.Advance()) {
12204 if (JSReceiver::cast(pt) == *object) { 12193 if (JSReceiver::cast(iter.GetCurrent()) == *object) {
12205 // Cycle detected. 12194 // Cycle detected.
12206 Handle<Object> error = isolate->factory()->NewError( 12195 Handle<Object> error = isolate->factory()->NewError(
12207 "cyclic_proto", HandleVector<Object>(NULL, 0)); 12196 "cyclic_proto", HandleVector<Object>(NULL, 0));
12208 return isolate->Throw<Object>(error); 12197 return isolate->Throw<Object>(error);
12209 } 12198 }
12210 } 12199 }
12211 12200
12212 bool dictionary_elements_in_chain = 12201 bool dictionary_elements_in_chain =
12213 object->map()->DictionaryElementsInPrototypeChainOnly(); 12202 object->map()->DictionaryElementsInPrototypeChainOnly();
12214 Handle<JSObject> real_receiver = object; 12203 Handle<JSObject> real_receiver = object;
12215 12204
12216 if (skip_hidden_prototypes) { 12205 if (skip_hidden_prototypes) {
12217 // Find the first object in the chain whose prototype object is not 12206 // Find the first object in the chain whose prototype object is not
12218 // hidden and set the new prototype on that object. 12207 // hidden and set the new prototype on that object.
12219 Object* current_proto = real_receiver->GetPrototype(); 12208 PrototypeIterator iter(isolate, real_receiver);
12220 while (current_proto->IsJSObject() && 12209 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
12221 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { 12210 real_receiver =
12222 real_receiver = handle(JSObject::cast(current_proto), isolate); 12211 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
12223 current_proto = current_proto->GetPrototype(isolate); 12212 iter.Advance();
12224 } 12213 }
12225 } 12214 }
12226 12215
12227 // Set the new prototype of the object. 12216 // Set the new prototype of the object.
12228 Handle<Map> map(real_receiver->map()); 12217 Handle<Map> map(real_receiver->map());
12229 12218
12230 // Nothing to do if prototype is already set. 12219 // Nothing to do if prototype is already set.
12231 if (map->prototype() == *value) return value; 12220 if (map->prototype() == *value) return value;
12232 12221
12233 if (value->IsJSObject()) { 12222 if (value->IsJSObject()) {
(...skipping 4761 matching lines...) Expand 10 before | Expand all | Expand 10 after
16995 #define ERROR_MESSAGES_TEXTS(C, T) T, 16984 #define ERROR_MESSAGES_TEXTS(C, T) T,
16996 static const char* error_messages_[] = { 16985 static const char* error_messages_[] = {
16997 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16986 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16998 }; 16987 };
16999 #undef ERROR_MESSAGES_TEXTS 16988 #undef ERROR_MESSAGES_TEXTS
17000 return error_messages_[reason]; 16989 return error_messages_[reason];
17001 } 16990 }
17002 16991
17003 16992
17004 } } // namespace v8::internal 16993 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698