| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 702d8a222dcdd8ee31d06fec4206eaf3d6445c33..1571d79c48ff0b7ade03214983088bfbe047f31c 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,30 @@ MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
|
| Handle<Object> object,
|
| Handle<Object> receiver,
|
| uint32_t index) {
|
| - Handle<Object> holder;
|
| + if (object->IsUndefined()) {
|
| + // TODO(verwaest): Why is this check here?
|
| + UNREACHABLE();
|
| + 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);
|
| }
|
|
|
| // 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 +854,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 +866,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 +3022,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 +3509,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 +6356,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 +6380,8 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
|
| break;
|
| }
|
|
|
| - Handle<JSObject> current(JSObject::cast(*p), isolate);
|
| + Handle<JSObject> current =
|
| + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
|
|
| // Check access rights if required.
|
| if (current->IsAccessCheckNeeded() &&
|
| @@ -6610,22 +6599,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 +10111,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 +12188,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 +12206,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();
|
| }
|
| }
|
|
|
|
|