Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 702d8a222dcdd8ee31d06fec4206eaf3d6445c33..dd4f8ed40e4579b52524c51ff15cb80e15cff487 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -28,6 +28,7 @@ |
| #include "src/mark-compact.h" |
| #include "src/objects-inl.h" |
| #include "src/objects-visiting-inl.h" |
| +#include "src/prototype.h" |
| #include "src/safepoint-table.h" |
| #include "src/string-search.h" |
| #include "src/string-stream.h" |
| @@ -801,30 +802,29 @@ MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate, |
| Handle<Object> object, |
| Handle<Object> receiver, |
| uint32_t index) { |
| - Handle<Object> holder; |
| + if (object->IsUndefined()) { |
|
Toon Verwaest
2014/07/11 09:41:28
I think this condition should never occur. Reading
|
| + return isolate->factory()->undefined_value(); |
| + } |
| // Iterate up the prototype chain until an element is found or the null |
| // prototype is encountered. |
| - for (holder = object; |
| - !holder->IsNull(); |
| - holder = Handle<Object>(holder->GetPrototype(isolate), isolate)) { |
| - if (!holder->IsJSObject()) { |
| - if (holder->IsJSProxy()) { |
| - return JSProxy::GetElementWithHandler( |
| - Handle<JSProxy>::cast(holder), receiver, index); |
| - } else if (holder->IsUndefined()) { |
| - // Undefined has no indexed properties. |
| - return isolate->factory()->undefined_value(); |
| - } else { |
| - holder = Handle<Object>(holder->GetPrototype(isolate), isolate); |
| - ASSERT(holder->IsJSObject()); |
| - } |
| - } |
| + for (PrototypeIterator iter(isolate, object, |
| + object->IsJSProxy() || object->IsJSObject() |
| + ? PrototypeIterator::START_AT_RECEIVER |
| + : PrototypeIterator::START_AT_PROTOTYPE); |
| + !iter.IsAtEnd(); iter.Advance()) { |
| + if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
| + return JSProxy::GetElementWithHandler( |
| + Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver, |
| + index); |
| + } |
| + ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSObject()); |
|
Toon Verwaest
2014/07/11 09:41:28
This condition should be ensured by the iterator I
|
| // Inline the case for JSObjects. Doing so significantly improves the |
| // performance of fetching elements where checking the prototype chain is |
| // necessary. |
| - Handle<JSObject> js_object = Handle<JSObject>::cast(holder); |
| + Handle<JSObject> js_object = |
| + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| // Check access rights if needed. |
| if (js_object->IsAccessCheckNeeded()) { |
| @@ -853,11 +853,11 @@ MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate, |
| } |
| -Object* Object::GetPrototype(Isolate* isolate) { |
| +Map* Object::GetRootMap(Isolate* isolate) { |
| DisallowHeapAllocation no_alloc; |
| if (IsSmi()) { |
| Context* context = isolate->context()->native_context(); |
| - return context->number_function()->instance_prototype(); |
| + return context->number_function()->initial_map(); |
| } |
| HeapObject* heap_object = HeapObject::cast(this); |
| @@ -865,30 +865,23 @@ Object* Object::GetPrototype(Isolate* isolate) { |
| // The object is either a number, a string, a boolean, |
| // a real JS object, or a Harmony proxy. |
| if (heap_object->IsJSReceiver()) { |
| - return heap_object->map()->prototype(); |
| + return heap_object->map(); |
| } |
| Context* context = isolate->context()->native_context(); |
| if (heap_object->IsHeapNumber()) { |
| - return context->number_function()->instance_prototype(); |
| + return context->number_function()->initial_map(); |
| } |
| if (heap_object->IsString()) { |
| - return context->string_function()->instance_prototype(); |
| + return context->string_function()->initial_map(); |
| } |
| if (heap_object->IsSymbol()) { |
| - return context->symbol_function()->instance_prototype(); |
| + return context->symbol_function()->initial_map(); |
| } |
| if (heap_object->IsBoolean()) { |
| - return context->boolean_function()->instance_prototype(); |
| - } else { |
| - return isolate->heap()->null_value(); |
| + return context->boolean_function()->initial_map(); |
| } |
| -} |
| - |
| - |
| -Handle<Object> Object::GetPrototype(Isolate* isolate, |
| - Handle<Object> object) { |
| - return handle(object->GetPrototype(isolate), isolate); |
| + return isolate->heap()->null_value()->map(); |
| } |
| @@ -3028,20 +3021,16 @@ MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( |
| bool* found, |
| StrictMode strict_mode) { |
| Isolate *isolate = object->GetIsolate(); |
| - for (Handle<Object> proto = handle(object->GetPrototype(), isolate); |
| - !proto->IsNull(); |
| - proto = handle(proto->GetPrototype(isolate), isolate)) { |
| - if (proto->IsJSProxy()) { |
| + for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd(); |
| + iter.Advance()) { |
| + if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
| return JSProxy::SetPropertyViaPrototypesWithHandler( |
| - Handle<JSProxy>::cast(proto), |
| - object, |
| + Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), object, |
| isolate->factory()->Uint32ToString(index), // name |
| - value, |
| - NONE, |
| - strict_mode, |
| - found); |
| + value, NONE, strict_mode, found); |
| } |
| - Handle<JSObject> js_proto = Handle<JSObject>::cast(proto); |
| + Handle<JSObject> js_proto = |
| + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| if (!js_proto->HasDictionaryElements()) { |
| continue; |
| } |
| @@ -3519,14 +3508,11 @@ void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name, |
| LookupResult* result) { |
| DisallowHeapAllocation no_gc; |
| Isolate* isolate = GetIsolate(); |
| - Heap* heap = isolate->heap(); |
| - for (Object* pt = GetPrototype(); |
| - pt != heap->null_value(); |
| - pt = pt->GetPrototype(isolate)) { |
| - if (pt->IsJSProxy()) { |
| - return result->HandlerResult(JSProxy::cast(pt)); |
| + for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd(); iter.Advance()) { |
| + if (iter.GetCurrent()->IsJSProxy()) { |
| + return result->HandlerResult(JSProxy::cast(iter.GetCurrent())); |
| } |
| - JSObject::cast(pt)->LookupOwnRealNamedProperty(name, result); |
| + JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result); |
| ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); |
| if (result->IsFound()) return; |
| } |
| @@ -6369,11 +6355,12 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
| JSFunction::cast(isolate->sloppy_arguments_map()->constructor())); |
| // Only collect keys if access is permitted. |
| - for (Handle<Object> p = object; |
| - *p != isolate->heap()->null_value(); |
| - p = Handle<Object>(p->GetPrototype(isolate), isolate)) { |
| - if (p->IsJSProxy()) { |
| - Handle<JSProxy> proxy(JSProxy::cast(*p), isolate); |
| + for (PrototypeIterator iter(isolate, object, |
| + PrototypeIterator::START_AT_RECEIVER); |
| + !iter.IsAtEnd(); iter.Advance()) { |
| + if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
| + Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)), |
| + isolate); |
| Handle<Object> args[] = { proxy }; |
| Handle<Object> names; |
| ASSIGN_RETURN_ON_EXCEPTION( |
| @@ -6392,7 +6379,8 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
| break; |
| } |
| - Handle<JSObject> current(JSObject::cast(*p), isolate); |
| + Handle<JSObject> current( |
| + JSObject::cast(*PrototypeIterator::GetCurrent(iter)), isolate); |
|
Toon Verwaest
2014/07/11 09:41:28
Handle<JSObject> current = Handle<JSObject>::cast(
|
| // Check access rights if required. |
| if (current->IsAccessCheckNeeded() && |
| @@ -6610,22 +6598,18 @@ void JSObject::DefinePropertyAccessor(Handle<JSObject> object, |
| bool Map::DictionaryElementsInPrototypeChainOnly() { |
| - Heap* heap = GetHeap(); |
| - |
| if (IsDictionaryElementsKind(elements_kind())) { |
| return false; |
| } |
| - for (Object* prototype = this->prototype(); |
| - prototype != heap->null_value(); |
| - prototype = prototype->GetPrototype(GetIsolate())) { |
| - if (prototype->IsJSProxy()) { |
| + for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) { |
| + if (iter.GetCurrent()->IsJSProxy()) { |
| // Be conservative, don't walk into proxies. |
| return true; |
| } |
| if (IsDictionaryElementsKind( |
| - JSObject::cast(prototype)->map()->elements_kind())) { |
| + JSObject::cast(iter.GetCurrent())->map()->elements_kind())) { |
| return true; |
| } |
| } |
| @@ -10126,9 +10110,14 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { |
| Handle<Object> prototype; |
| if (function->has_instance_prototype()) { |
| prototype = handle(function->instance_prototype(), isolate); |
| - for (Handle<Object> p = prototype; !p->IsNull() && !p->IsJSProxy(); |
| - p = Object::GetPrototype(isolate, p)) { |
| - JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(p)); |
| + for (PrototypeIterator iter(isolate, prototype, |
| + PrototypeIterator::START_AT_RECEIVER); |
| + !iter.IsAtEnd(); iter.Advance()) { |
| + if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
| + break; |
| + } |
| + JSObject::OptimizeAsPrototype( |
| + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); |
| } |
| } else { |
| prototype = isolate->factory()->NewFunctionPrototype(function); |
| @@ -12198,10 +12187,10 @@ MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
| // prototype cycles are prevented. |
| // It is sufficient to validate that the receiver is not in the new prototype |
| // chain. |
| - for (Object* pt = *value; |
| - pt != heap->null_value(); |
| - pt = pt->GetPrototype(isolate)) { |
| - if (JSReceiver::cast(pt) == *object) { |
| + for (PrototypeIterator iter(isolate, *value, |
| + PrototypeIterator::START_AT_RECEIVER); |
| + !iter.IsAtEnd(); iter.Advance()) { |
| + if (JSReceiver::cast(iter.GetCurrent()) == *object) { |
| // Cycle detected. |
| Handle<Object> error = isolate->factory()->NewError( |
| "cyclic_proto", HandleVector<Object>(NULL, 0)); |
| @@ -12216,11 +12205,11 @@ MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
| if (skip_hidden_prototypes) { |
| // Find the first object in the chain whose prototype object is not |
| // hidden and set the new prototype on that object. |
| - Object* current_proto = real_receiver->GetPrototype(); |
| - while (current_proto->IsJSObject() && |
| - JSObject::cast(current_proto)->map()->is_hidden_prototype()) { |
| - real_receiver = handle(JSObject::cast(current_proto), isolate); |
| - current_proto = current_proto->GetPrototype(isolate); |
| + PrototypeIterator iter(isolate, real_receiver); |
| + while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { |
| + real_receiver = |
| + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| + iter.Advance(); |
| } |
| } |