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

Side by Side Diff: src/runtime/runtime-forin.cc

Issue 1631583002: [for-in] Further refactorings and unification around for-in. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 11 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
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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/runtime/runtime-utils.h" 5 #include "src/runtime/runtime-utils.h"
6 6
7 #include "src/arguments.h" 7 #include "src/arguments.h"
8 #include "src/factory.h" 8 #include "src/factory.h"
9 #include "src/isolate-inl.h" 9 #include "src/isolate-inl.h"
10 #include "src/objects-inl.h" 10 #include "src/objects-inl.h"
11 11
12 namespace v8 { 12 namespace v8 {
13 namespace internal { 13 namespace internal {
14 14
15 namespace {
16
17 // Returns either a FixedArray or, if the given {receiver} has an enum cache
18 // that contains all enumerable properties of the {receiver} and its prototypes
19 // have none, the map of the {receiver}. This is used to speed up the check for
20 // deletions during a for-in.
21 MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) {
22 Isolate* const isolate = receiver->GetIsolate();
23 // Test if we have an enum cache for {receiver}.
24 if (!receiver->IsSimpleEnum()) {
25 Handle<FixedArray> keys;
26 ASSIGN_RETURN_ON_EXCEPTION(
27 isolate, keys, JSReceiver::GetKeys(receiver, JSReceiver::INCLUDE_PROTOS,
28 ENUMERABLE_STRINGS),
29 HeapObject);
30 // Test again, since cache may have been built by GetKeys() calls above.
31 if (!receiver->IsSimpleEnum()) return keys;
32 }
33 return handle(receiver->map(), isolate);
34 }
35
36
37 MaybeHandle<Object> Filter(Handle<JSReceiver> receiver, Handle<Object> key) {
38 Isolate* const isolate = receiver->GetIsolate();
39 // TODO(turbofan): Fast case for array indices.
40 Handle<Name> name;
41 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
42 Object);
43 Maybe<bool> result = JSReceiver::HasProperty(receiver, name);
44 MAYBE_RETURN_NULL(result);
45 if (result.FromJust()) return name;
46 return isolate->factory()->undefined_value();
47 }
48
49 } // namespace
50
51
52 RUNTIME_FUNCTION(Runtime_ForInEnumerate) {
53 HandleScope scope(isolate);
54 DCHECK_EQ(1, args.length());
55 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
56 Handle<HeapObject> result;
57 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Enumerate(receiver));
58 return *result;
59 }
60
61
15 RUNTIME_FUNCTION_RETURN_TRIPLE(Runtime_ForInPrepare) { 62 RUNTIME_FUNCTION_RETURN_TRIPLE(Runtime_ForInPrepare) {
16 HandleScope scope(isolate); 63 HandleScope scope(isolate);
17 DCHECK_EQ(1, args.length()); 64 DCHECK_EQ(1, args.length());
18 65 Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
19 if (!args[0]->IsJSReceiver()) { 66 Handle<Object> cache_type;
20 return MakeTriple(isolate->ThrowIllegalOperation(), nullptr, nullptr); 67 if (!Enumerate(receiver).ToHandle(&cache_type)) {
68 return MakeTriple(isolate->heap()->exception(), nullptr, nullptr);
21 } 69 }
22 Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
23
24 Object* property_names = Runtime_GetPropertyNamesFast(
25 1, Handle<Object>::cast(receiver).location(), isolate);
26 if (isolate->has_pending_exception()) {
27 return MakeTriple(property_names, nullptr, nullptr);
28 }
29
30 Handle<Object> cache_type(property_names, isolate);
31 Handle<FixedArray> cache_array; 70 Handle<FixedArray> cache_array;
32 int cache_length; 71 int cache_length;
33
34 if (cache_type->IsMap()) { 72 if (cache_type->IsMap()) {
35 Handle<Map> cache_type_map = Handle<Map>::cast(cache_type); 73 Handle<Map> cache_map = Handle<Map>::cast(cache_type);
36 int const enum_length = cache_type_map->EnumLength(); 74 Handle<DescriptorArray> descriptors(cache_map->instance_descriptors(),
37 DescriptorArray* descriptors = cache_type_map->instance_descriptors(); 75 isolate);
38 if (enum_length && descriptors->HasEnumCache()) { 76 cache_length = cache_map->EnumLength();
77 if (cache_length && descriptors->HasEnumCache()) {
39 cache_array = handle(descriptors->GetEnumCache(), isolate); 78 cache_array = handle(descriptors->GetEnumCache(), isolate);
40 cache_length = enum_length;
41 } else { 79 } else {
42 cache_array = isolate->factory()->empty_fixed_array(); 80 cache_array = isolate->factory()->empty_fixed_array();
43 cache_length = 0; 81 cache_length = 0;
44 } 82 }
45 } else { 83 } else {
46 cache_array = Handle<FixedArray>::cast(cache_type); 84 cache_array = Handle<FixedArray>::cast(cache_type);
47 cache_length = cache_array->length(); 85 cache_length = cache_array->length();
48 // Cache type of SMI one entails slow check. 86 cache_type = handle(Smi::FromInt(1), isolate);
49 cache_type = Handle<Object>(Smi::FromInt(1), isolate);
50 } 87 }
51
52 return MakeTriple(*cache_type, *cache_array, Smi::FromInt(cache_length)); 88 return MakeTriple(*cache_type, *cache_array, Smi::FromInt(cache_length));
53 } 89 }
54 90
55 91
56 RUNTIME_FUNCTION(Runtime_ForInDone) { 92 RUNTIME_FUNCTION(Runtime_ForInDone) {
57 SealHandleScope scope(isolate); 93 SealHandleScope scope(isolate);
58 DCHECK_EQ(2, args.length()); 94 DCHECK_EQ(2, args.length());
59 CONVERT_SMI_ARG_CHECKED(index, 0); 95 CONVERT_SMI_ARG_CHECKED(index, 0);
60 CONVERT_SMI_ARG_CHECKED(length, 1); 96 CONVERT_SMI_ARG_CHECKED(length, 1);
61 DCHECK_LE(0, index); 97 DCHECK_LE(0, index);
62 DCHECK_LE(index, length); 98 DCHECK_LE(index, length);
63 return isolate->heap()->ToBoolean(index == length); 99 return isolate->heap()->ToBoolean(index == length);
64 } 100 }
65 101
66 102
67 RUNTIME_FUNCTION(Runtime_ForInFilter) { 103 RUNTIME_FUNCTION(Runtime_ForInFilter) {
68 HandleScope scope(isolate); 104 HandleScope scope(isolate);
69 DCHECK_EQ(2, args.length()); 105 DCHECK_EQ(2, args.length());
70 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); 106 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
71 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); 107 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
72 // TODO(turbofan): Fast case for array indices. 108 Handle<Object> result;
73 Handle<Name> name; 109 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Filter(receiver, key));
74 if (!Object::ToName(isolate, key).ToHandle(&name)) { 110 return *result;
75 return isolate->heap()->exception();
76 }
77 Maybe<bool> result = JSReceiver::HasProperty(receiver, name);
78 if (!result.IsJust()) return isolate->heap()->exception();
79 if (result.FromJust()) return *name;
80 return isolate->heap()->undefined_value();
81 } 111 }
82 112
83 113
84 RUNTIME_FUNCTION(Runtime_ForInNext) { 114 RUNTIME_FUNCTION(Runtime_ForInNext) {
85 HandleScope scope(isolate); 115 HandleScope scope(isolate);
86 DCHECK_EQ(4, args.length()); 116 DCHECK_EQ(4, args.length());
87 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); 117 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
88 CONVERT_ARG_HANDLE_CHECKED(FixedArray, cache_array, 1); 118 CONVERT_ARG_HANDLE_CHECKED(FixedArray, cache_array, 1);
89 CONVERT_ARG_HANDLE_CHECKED(Object, cache_type, 2); 119 CONVERT_ARG_HANDLE_CHECKED(Object, cache_type, 2);
90 CONVERT_SMI_ARG_CHECKED(index, 3); 120 CONVERT_SMI_ARG_CHECKED(index, 3);
91 Handle<Object> key = handle(cache_array->get(index), isolate); 121 Handle<Object> key = handle(cache_array->get(index), isolate);
92 // Don't need filtering if expected map still matches that of the receiver, 122 // Don't need filtering if expected map still matches that of the receiver.
93 // and neither for proxies. 123 if (receiver->map() == *cache_type) {
94 if (receiver->map() == *cache_type || *cache_type == Smi::FromInt(0)) {
95 return *key; 124 return *key;
96 } 125 }
97 // TODO(turbofan): Fast case for array indices. 126 Handle<Object> result;
98 Handle<Name> name; 127 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Filter(receiver, key));
99 if (!Object::ToName(isolate, key).ToHandle(&name)) { 128 return *result;
100 return isolate->heap()->exception();
101 }
102 Maybe<bool> result = JSReceiver::HasProperty(receiver, name);
103 if (!result.IsJust()) return isolate->heap()->exception();
104 if (result.FromJust()) return *name;
105 return isolate->heap()->undefined_value();
106 } 129 }
107 130
108 131
109 RUNTIME_FUNCTION(Runtime_ForInStep) { 132 RUNTIME_FUNCTION(Runtime_ForInStep) {
110 SealHandleScope scope(isolate); 133 SealHandleScope scope(isolate);
111 DCHECK_EQ(1, args.length()); 134 DCHECK_EQ(1, args.length());
112 CONVERT_SMI_ARG_CHECKED(index, 0); 135 CONVERT_SMI_ARG_CHECKED(index, 0);
113 DCHECK_LE(0, index); 136 DCHECK_LE(0, index);
114 DCHECK_LT(index, Smi::kMaxValue); 137 DCHECK_LT(index, Smi::kMaxValue);
115 return Smi::FromInt(index + 1); 138 return Smi::FromInt(index + 1);
116 } 139 }
117 140
118 } // namespace internal 141 } // namespace internal
119 } // namespace v8 142 } // namespace v8
OLDNEW
« no previous file with comments | « src/runtime/runtime.h ('k') | src/runtime/runtime-object.cc » ('j') | src/types.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698