Index: src/runtime/runtime-forin.cc |
diff --git a/src/runtime/runtime-forin.cc b/src/runtime/runtime-forin.cc |
index c44945c94ce64141006ee7293b30b4ceb068606a..6374cb97e5a8a92ad37b0b671059363274ac3c1e 100644 |
--- a/src/runtime/runtime-forin.cc |
+++ b/src/runtime/runtime-forin.cc |
@@ -5,8 +5,10 @@ |
#include "src/runtime/runtime-utils.h" |
#include "src/arguments.h" |
+#include "src/elements.h" |
#include "src/factory.h" |
#include "src/isolate-inl.h" |
+#include "src/keys.h" |
#include "src/objects-inl.h" |
namespace v8 { |
@@ -20,15 +22,15 @@ namespace { |
// deletions during a for-in. |
MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) { |
Isolate* const isolate = receiver->GetIsolate(); |
+ FastKeyAccumulator accumulator(isolate, receiver, INCLUDE_PROTOS, |
+ ENUMERABLE_STRINGS); |
// Test if we have an enum cache for {receiver}. |
- if (!receiver->IsSimpleEnum()) { |
+ if (!accumulator.is_receiver_simple_enum()) { |
Handle<FixedArray> keys; |
- ASSIGN_RETURN_ON_EXCEPTION( |
- isolate, keys, |
- JSReceiver::GetKeys(receiver, INCLUDE_PROTOS, ENUMERABLE_STRINGS), |
- HeapObject); |
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, keys, accumulator.GetKeys(KEEP_NUMBERS), |
+ HeapObject); |
// Test again, since cache may have been built by GetKeys() calls above. |
- if (!receiver->IsSimpleEnum()) return keys; |
+ if (!accumulator.is_receiver_simple_enum()) return keys; |
} |
return handle(receiver->map(), isolate); |
} |
@@ -36,10 +38,19 @@ MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) { |
MaybeHandle<Object> Filter(Handle<JSReceiver> receiver, Handle<Object> key) { |
Isolate* const isolate = receiver->GetIsolate(); |
- // TODO(turbofan): Fast case for array indices. |
Handle<Name> name; |
ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key), |
Object); |
+ // Directly check for elements if the key is a smi and avoid a conversion |
+ // roundtrip (Number -> Name -> Number). |
+ if (key->IsNumber() && receiver->map()->OnlyHasSimpleProperties()) { |
+ Handle<JSObject> object = Handle<JSObject>::cast(receiver); |
+ ElementsAccessor* accessor = object->GetElementsAccessor(); |
+ DCHECK_LT(key->Number(), kMaxUInt32); |
+ if (accessor->HasElement(object, key->Number(), ONLY_ENUMERABLE)) { |
+ return name; |
+ } |
+ } |
Maybe<bool> result = JSReceiver::HasProperty(receiver, name); |
MAYBE_RETURN_NULL(result); |
if (result.FromJust()) return name; |