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

Side by Side Diff: src/objects.cc

Issue 1466243002: [proxies] Refactor JSReceiver::GetKeys() (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 5 years 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
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <sstream> 9 #include <sstream>
10 10
(...skipping 7947 matching lines...) Expand 10 before | Expand all | Expand 10 after
7958 if (length == 0) { 7958 if (length == 0) {
7959 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); 7959 return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
7960 } 7960 }
7961 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); 7961 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
7962 dictionary->CopyEnumKeysTo(*storage); 7962 dictionary->CopyEnumKeysTo(*storage);
7963 return storage; 7963 return storage;
7964 } 7964 }
7965 } 7965 }
7966 7966
7967 7967
7968 static bool GetKeysFromJSObject(Isolate* isolate, Handle<JSReceiver> receiver,
7969 Handle<JSObject> object, KeyFilter filter,
7970 Enumerability enum_policy,
7971 KeyAccumulator* accumulator) {
7972 // Check access rights if required.
7973 if (object->IsAccessCheckNeeded() &&
7974 !isolate->MayAccess(handle(isolate->context()), object)) {
7975 // TODO(jkummerow): Get whitelisted (all-can-read) keys.
7976 // It's probably best to implement a "GetKeysWithFailedAccessCheck"
7977 // helper, which will need to look at both interceptors and accessors.
7978 return false;
7979 }
7980
7981 PropertyAttributes attr_filter = static_cast<PropertyAttributes>(
7982 (enum_policy == RESPECT_ENUMERABILITY ? DONT_ENUM : NONE) |
7983 PRIVATE_SYMBOL);
7984
7985 JSObject::CollectOwnElementKeys(object, accumulator, attr_filter);
7986
7987 // Add the element keys from the interceptor.
7988 if (object->HasIndexedInterceptor()) {
7989 Handle<JSObject> result;
7990 if (JSObject::GetKeysForIndexedInterceptor(object, receiver)
7991 .ToHandle(&result)) {
7992 accumulator->AddElementKeysFromInterceptor(result);
7993 }
7994 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false);
7995 }
7996
7997 if (filter == SKIP_SYMBOLS) {
7998 if (enum_policy == IGNORE_ENUMERABILITY) UNIMPLEMENTED();
7999
8000 // We can cache the computed property keys if access checks are
8001 // not needed and no interceptors are involved.
8002 //
8003 // We do not use the cache if the object has elements and
8004 // therefore it does not make sense to cache the property names
8005 // for arguments objects. Arguments objects will always have
8006 // elements.
8007 // Wrapped strings have elements, but don't have an elements
8008 // array or dictionary. So the fast inline test for whether to
8009 // use the cache says yes, so we should not create a cache.
8010 Handle<JSFunction> arguments_function(
8011 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
8012 bool cache_enum_length =
8013 ((object->map()->GetConstructor() != *arguments_function) &&
8014 !object->IsJSValue() && !object->IsAccessCheckNeeded() &&
8015 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor());
8016 // Compute the property keys and cache them if possible.
8017 Handle<FixedArray> enum_keys =
8018 JSObject::GetEnumPropertyKeys(object, cache_enum_length);
8019 accumulator->AddKeys(enum_keys);
8020 } else {
8021 DCHECK(filter == INCLUDE_SYMBOLS);
8022 object->CollectOwnPropertyNames(accumulator, attr_filter);
8023 }
8024
8025 // Add the property keys from the interceptor.
8026 if (object->HasNamedInterceptor()) {
8027 Handle<JSObject> result;
8028 if (JSObject::GetKeysForNamedInterceptor(object, receiver)
8029 .ToHandle(&result)) {
8030 accumulator->AddKeys(result);
8031 }
8032 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false);
8033 }
8034 return true;
8035 }
8036
8037
8038 static bool GetKeysFromJSProxy(Isolate* isolate, Handle<JSReceiver> receiver,
8039 Handle<JSProxy> proxy, KeyFilter filter,
8040 Enumerability enum_policy,
8041 KeyAccumulator* accumulator) {
8042 Handle<Object> args[] = {proxy};
8043 Handle<Object> names;
8044 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
8045 isolate, names, Execution::Call(isolate, isolate->proxy_enumerate(),
8046 proxy, arraysize(args), args),
8047 false);
8048 accumulator->AddKeysFromProxy(Handle<JSObject>::cast(names));
8049 return true;
8050 }
8051
8052
8053 // Returns false if an exception was thrown, or if prototype iteration
8054 // should not continue.
8055 static bool GetKeysFromJSReceiver(Isolate* isolate, Handle<JSReceiver> receiver,
Jakob Kummerow 2015/11/25 11:33:47 We'll need this entry point so that the new GetKey
8056 Handle<JSReceiver> object, KeyFilter filter,
8057 Enumerability enum_policy,
8058 KeyAccumulator* accumulator) {
8059 if (object->IsJSProxy()) {
8060 return GetKeysFromJSProxy(isolate, receiver, Handle<JSProxy>::cast(object),
8061 filter, enum_policy, accumulator);
8062 }
8063 return GetKeysFromJSObject(isolate, receiver, Handle<JSObject>::cast(object),
8064 filter, enum_policy, accumulator);
8065 }
8066
8067
7968 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, 8068 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
7969 KeyCollectionType type, 8069 KeyCollectionType type,
7970 KeyFilter filter, 8070 KeyFilter filter,
7971 GetKeysConversion getConversion, 8071 GetKeysConversion keys_conversion,
7972 Enumerability enum_policy) { 8072 Enumerability enum_policy) {
7973 USE(ContainsOnlyValidKeys); 8073 USE(ContainsOnlyValidKeys);
7974 Isolate* isolate = object->GetIsolate(); 8074 Isolate* isolate = object->GetIsolate();
7975 KeyAccumulator accumulator(isolate, filter); 8075 KeyAccumulator accumulator(isolate, filter);
7976 Handle<JSFunction> arguments_function(
7977 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
7978 PrototypeIterator::WhereToEnd end = type == OWN_ONLY 8076 PrototypeIterator::WhereToEnd end = type == OWN_ONLY
7979 ? PrototypeIterator::END_AT_NON_HIDDEN 8077 ? PrototypeIterator::END_AT_NON_HIDDEN
7980 : PrototypeIterator::END_AT_NULL; 8078 : PrototypeIterator::END_AT_NULL;
7981 PropertyAttributes attr_filter = static_cast<PropertyAttributes>(
7982 (enum_policy == RESPECT_ENUMERABILITY ? DONT_ENUM : NONE) |
7983 PRIVATE_SYMBOL);
7984
7985 // Only collect keys if access is permitted.
7986 for (PrototypeIterator iter(isolate, object, 8079 for (PrototypeIterator iter(isolate, object,
7987 PrototypeIterator::START_AT_RECEIVER); 8080 PrototypeIterator::START_AT_RECEIVER);
7988 !iter.IsAtEnd(end); iter.Advance()) { 8081 !iter.IsAtEnd(end); iter.Advance()) {
7989 accumulator.NextPrototype(); 8082 accumulator.NextPrototype();
7990 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 8083 if (!GetKeysFromJSReceiver(isolate, object,
7991 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); 8084 PrototypeIterator::GetCurrent<JSReceiver>(iter),
7992 Handle<Object> args[] = { proxy }; 8085 filter, enum_policy, &accumulator)) {
7993 Handle<Object> names; 8086 if (isolate->has_pending_exception()) {
7994 ASSIGN_RETURN_ON_EXCEPTION( 8087 return MaybeHandle<FixedArray>();
7995 isolate, names, 8088 }
7996 Execution::Call(isolate, 8089 // If there was no exception, then "false" means "stop iterating".
7997 isolate->proxy_enumerate(),
7998 object,
7999 arraysize(args),
8000 args),
8001 FixedArray);
8002 accumulator.AddKeysFromProxy(Handle<JSObject>::cast(names));
8003 break; 8090 break;
8004 } 8091 }
8005
8006 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
8007
8008 // Check access rights if required.
8009 if (current->IsAccessCheckNeeded() &&
8010 !isolate->MayAccess(handle(isolate->context()), current)) {
8011 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
Jakob Kummerow 2015/11/25 11:33:47 I've dropped this condition as discussed, because
8012 isolate->ReportFailedAccessCheck(current);
8013 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
8014 }
8015 break;
8016 }
8017
8018 JSObject::CollectOwnElementKeys(current, &accumulator, attr_filter);
8019
8020 // Add the element keys from the interceptor.
8021 if (current->HasIndexedInterceptor()) {
8022 Handle<JSObject> result;
8023 if (JSObject::GetKeysForIndexedInterceptor(current, object)
8024 .ToHandle(&result)) {
8025 accumulator.AddElementKeysFromInterceptor(result);
8026 }
8027 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
8028 }
8029
8030 if (filter == SKIP_SYMBOLS) {
8031 if (enum_policy == IGNORE_ENUMERABILITY) UNIMPLEMENTED();
8032
8033 // We can cache the computed property keys if access checks are
8034 // not needed and no interceptors are involved.
8035 //
8036 // We do not use the cache if the object has elements and
8037 // therefore it does not make sense to cache the property names
8038 // for arguments objects. Arguments objects will always have
8039 // elements.
8040 // Wrapped strings have elements, but don't have an elements
8041 // array or dictionary. So the fast inline test for whether to
8042 // use the cache says yes, so we should not create a cache.
8043 bool cache_enum_length =
8044 ((current->map()->GetConstructor() != *arguments_function) &&
8045 !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
8046 !current->HasNamedInterceptor() &&
8047 !current->HasIndexedInterceptor());
8048 // Compute the property keys and cache them if possible.
8049 Handle<FixedArray> enum_keys =
8050 JSObject::GetEnumPropertyKeys(current, cache_enum_length);
8051 accumulator.AddKeys(enum_keys);
8052 } else {
8053 DCHECK(filter == INCLUDE_SYMBOLS);
8054 current->CollectOwnPropertyNames(&accumulator, attr_filter);
8055 }
8056
8057 // Add the property keys from the interceptor.
8058 if (current->HasNamedInterceptor()) {
8059 Handle<JSObject> result;
8060 if (JSObject::GetKeysForNamedInterceptor(current, object)
8061 .ToHandle(&result)) {
8062 accumulator.AddKeys(result);
8063 }
8064 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
8065 }
8066 } 8092 }
8067 8093
8068 Handle<FixedArray> keys = accumulator.GetKeys(getConversion); 8094 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion);
8069 DCHECK(ContainsOnlyValidKeys(keys)); 8095 DCHECK(ContainsOnlyValidKeys(keys));
8070 return keys; 8096 return keys;
8071 } 8097 }
8072 8098
8073 8099
8074 bool Map::DictionaryElementsInPrototypeChainOnly() { 8100 bool Map::DictionaryElementsInPrototypeChainOnly() {
8075 if (IsDictionaryElementsKind(elements_kind())) { 8101 if (IsDictionaryElementsKind(elements_kind())) {
8076 return false; 8102 return false;
8077 } 8103 }
8078 8104
(...skipping 10469 matching lines...) Expand 10 before | Expand all | Expand 10 after
18548 if (cell->value() != *new_value) { 18574 if (cell->value() != *new_value) {
18549 cell->set_value(*new_value); 18575 cell->set_value(*new_value);
18550 Isolate* isolate = cell->GetIsolate(); 18576 Isolate* isolate = cell->GetIsolate();
18551 cell->dependent_code()->DeoptimizeDependentCodeGroup( 18577 cell->dependent_code()->DeoptimizeDependentCodeGroup(
18552 isolate, DependentCode::kPropertyCellChangedGroup); 18578 isolate, DependentCode::kPropertyCellChangedGroup);
18553 } 18579 }
18554 } 18580 }
18555 18581
18556 } // namespace internal 18582 } // namespace internal
18557 } // namespace v8 18583 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698