[es6] Introduce a dedicated JSIteratorResult type.
authorbmeurer <bmeurer@chromium.org>
Thu, 3 Sep 2015 12:16:15 +0000 (05:16 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 3 Sep 2015 12:16:25 +0000 (12:16 +0000)
Use a single JSIteratorResult type for all implementation provided
iterator results (i.e. the String, Array and collection iterators,
and also for generators).  This removes one source of unnecessary
polymorphism in for-of loops.  It is accomplished by a new intrinsic
%_CreateIterResultObject() that should be used to create iterator
result objects from JavaScript builtins (there's a matching factory
method for C++ code).

Also restructure the %StringIteratorPrototype%.next() and
%ArrayIteratorPrototype%.next() functions to be a bit more friendly
to optimizing compilers.

R=ishell@chromium.org

Review URL: https://codereview.chromium.org/1302173007

Cr-Commit-Position: refs/heads/master@{#30557}

24 files changed:
src/array-iterator.js
src/bootstrapper.cc
src/collection-iterator.js
src/contexts.h
src/factory.cc
src/factory.h
src/full-codegen/arm/full-codegen-arm.cc
src/full-codegen/arm64/full-codegen-arm64.cc
src/full-codegen/full-codegen.h
src/full-codegen/ia32/full-codegen-ia32.cc
src/full-codegen/mips/full-codegen-mips.cc
src/full-codegen/mips64/full-codegen-mips64.cc
src/full-codegen/x64/full-codegen-x64.cc
src/heap/objects-visiting.cc
src/hydrogen.cc
src/hydrogen.h
src/objects-debug.cc
src/objects-inl.h
src/objects-printer.cc
src/objects.h
src/runtime/runtime-object.cc
src/runtime/runtime.h
src/string-iterator.js
src/x64/macro-assembler-x64.h

index 762714e..bf17a0a 100644 (file)
@@ -62,21 +62,17 @@ function CreateArrayIterator(array, kind) {
 }
 
 
-// 15.19.4.3.4 CreateItrResultObject
-function CreateIteratorResultObject(value, done) {
-  return {value: value, done: done};
-}
-
-
 // 22.1.5.2.2 %ArrayIteratorPrototype%[@@iterator]
 function ArrayIteratorIterator() {
     return this;
 }
 
 
-// 15.4.5.2.2 ArrayIterator.prototype.next( )
+// ES6 section 22.1.5.2.1 %ArrayIteratorPrototype%.next( )
 function ArrayIteratorNext() {
   var iterator = this;
+  var value = UNDEFINED;
+  var done = true;
 
   if (!IS_SPEC_OBJECT(iterator) ||
       !HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) {
@@ -85,32 +81,30 @@ function ArrayIteratorNext() {
   }
 
   var array = GET_PRIVATE(iterator, arrayIteratorObjectSymbol);
-  if (IS_UNDEFINED(array)) {
-    return CreateIteratorResultObject(UNDEFINED, true);
-  }
-
-  var index = GET_PRIVATE(iterator, arrayIteratorNextIndexSymbol);
-  var itemKind = GET_PRIVATE(iterator, arrayIterationKindSymbol);
-  var length = TO_UINT32(array.length);
-
-  // "sparse" is never used.
-
-  if (index >= length) {
-    SET_PRIVATE(iterator, arrayIteratorObjectSymbol, UNDEFINED);
-    return CreateIteratorResultObject(UNDEFINED, true);
+  if (!IS_UNDEFINED(array)) {
+    var index = GET_PRIVATE(iterator, arrayIteratorNextIndexSymbol);
+    var itemKind = GET_PRIVATE(iterator, arrayIterationKindSymbol);
+    var length = TO_UINT32(array.length);
+
+    // "sparse" is never used.
+
+    if (index >= length) {
+      SET_PRIVATE(iterator, arrayIteratorObjectSymbol, UNDEFINED);
+    } else {
+      SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, index + 1);
+
+      if (itemKind == ITERATOR_KIND_VALUES) {
+        value = array[index];
+      } else if (itemKind == ITERATOR_KIND_ENTRIES) {
+        value = [index, array[index]];
+      } else {
+        value = index;
+      }
+      done = false;
+    }
   }
 
-  SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, index + 1);
-
-  if (itemKind == ITERATOR_KIND_VALUES) {
-    return CreateIteratorResultObject(array[index], false);
-  }
-
-  if (itemKind == ITERATOR_KIND_ENTRIES) {
-    return CreateIteratorResultObject([index, array[index]], false);
-  }
-
-  return CreateIteratorResultObject(index, false);
+  return %_CreateIterResultObject(value, done);
 }
 
 
@@ -167,10 +161,6 @@ TYPED_ARRAYS(EXTEND_TYPED_ARRAY)
 // -------------------------------------------------------------------
 // Exports
 
-utils.Export(function(to) {
-  to.ArrayIteratorCreateResultObject = CreateIteratorResultObject;
-});
-
 $arrayValues = ArrayValues;
 
 %InstallToContext(["array_values_iterator", ArrayValues]);
index a8858b7..e8cf0d6 100644 (file)
@@ -1312,32 +1312,26 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
     native_context()->set_js_set_fun(*js_set_fun);
   }
 
-  {  // Set up the iterator result object
-    STATIC_ASSERT(JSGeneratorObject::kResultPropertyCount == 2);
-    Handle<JSFunction> object_function(native_context()->object_function());
-    Handle<Map> iterator_result_map =
-        Map::Create(isolate, JSGeneratorObject::kResultPropertyCount);
-    DCHECK_EQ(JSGeneratorObject::kResultSize,
-              iterator_result_map->instance_size());
-    DCHECK_EQ(JSGeneratorObject::kResultPropertyCount,
-              iterator_result_map->GetInObjectProperties());
-    Map::EnsureDescriptorSlack(iterator_result_map,
-                               JSGeneratorObject::kResultPropertyCount);
-
-    DataDescriptor value_descr(factory->value_string(),
-                               JSGeneratorObject::kResultValuePropertyIndex,
-                               NONE, Representation::Tagged());
-    iterator_result_map->AppendDescriptor(&value_descr);
-
-    DataDescriptor done_descr(factory->done_string(),
-                              JSGeneratorObject::kResultDonePropertyIndex, NONE,
-                              Representation::Tagged());
-    iterator_result_map->AppendDescriptor(&done_descr);
-
-    iterator_result_map->set_unused_property_fields(0);
-    DCHECK_EQ(JSGeneratorObject::kResultSize,
-              iterator_result_map->instance_size());
-    native_context()->set_iterator_result_map(*iterator_result_map);
+  {  // -- I t e r a t o r R e s u l t
+    Handle<Map> map =
+        factory->NewMap(JS_ITERATOR_RESULT_TYPE, JSIteratorResult::kSize);
+    Map::SetPrototype(map, isolate->initial_object_prototype());
+    Map::EnsureDescriptorSlack(map, 2);
+
+    {  // value
+      DataDescriptor d(factory->value_string(), JSIteratorResult::kValueIndex,
+                       NONE, Representation::Tagged());
+      map->AppendDescriptor(&d);
+    }
+
+    {  // done
+      DataDescriptor d(factory->done_string(), JSIteratorResult::kDoneIndex,
+                       NONE, Representation::Tagged());
+      map->AppendDescriptor(&d);
+    }
+
+    map->SetInObjectProperties(2);
+    native_context()->set_iterator_result_map(*map);
   }
 
   // -- W e a k M a p
index 9cfe31e..c799d6f 100644 (file)
@@ -32,21 +32,21 @@ function SetIteratorNextJS() {
   }
 
   var value_array = [UNDEFINED, UNDEFINED];
-  var entry = {value: value_array, done: false};
+  var result = %_CreateIterResultObject(value_array, false);
   switch (%SetIteratorNext(this, value_array)) {
     case 0:
-      entry.value = UNDEFINED;
-      entry.done = true;
+      result.value = UNDEFINED;
+      result.done = true;
       break;
     case ITERATOR_KIND_VALUES:
-      entry.value = value_array[0];
+      result.value = value_array[0];
       break;
     case ITERATOR_KIND_ENTRIES:
       value_array[1] = value_array[0];
       break;
   }
 
-  return entry;
+  return result;
 }
 
 
@@ -104,22 +104,22 @@ function MapIteratorNextJS() {
   }
 
   var value_array = [UNDEFINED, UNDEFINED];
-  var entry = {value: value_array, done: false};
+  var result = %_CreateIterResultObject(value_array, false);
   switch (%MapIteratorNext(this, value_array)) {
     case 0:
-      entry.value = UNDEFINED;
-      entry.done = true;
+      result.value = UNDEFINED;
+      result.done = true;
       break;
     case ITERATOR_KIND_KEYS:
-      entry.value = value_array[0];
+      result.value = value_array[0];
       break;
     case ITERATOR_KIND_VALUES:
-      entry.value = value_array[1];
+      result.value = value_array[1];
       break;
     // ITERATOR_KIND_ENTRIES does not need any processing.
   }
 
-  return entry;
+  return result;
 }
 
 
index 8d85667..dc35d97 100644 (file)
@@ -247,6 +247,7 @@ enum BindingFlags {
   V(JS_SET_MAP_INDEX, Map, js_set_map)                                         \
   V(MAP_CACHE_INDEX, Object, map_cache)                                        \
   V(MAP_ITERATOR_MAP_INDEX, Map, map_iterator_map)                             \
+  V(STRING_ITERATOR_MAP_INDEX, Map, string_iterator_map)                       \
   V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners)                      \
   V(NATIVES_UTILS_OBJECT_INDEX, Object, natives_utils_object)                  \
   V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache)                  \
index 9045289..9104d60 100644 (file)
@@ -1680,6 +1680,16 @@ Handle<JSSetIterator> Factory::NewJSSetIterator() {
 }
 
 
+Handle<JSIteratorResult> Factory::NewJSIteratorResult(Handle<Object> value,
+                                                      Handle<Object> done) {
+  Handle<JSIteratorResult> result = Handle<JSIteratorResult>::cast(
+      NewJSObjectFromMap(isolate()->iterator_result_map()));
+  result->set_value(*value);
+  result->set_done(*done);
+  return result;
+}
+
+
 namespace {
 
 ElementsKind GetExternalArrayElementsKind(ExternalArrayType type) {
index 2596ae3..d182726 100644 (file)
@@ -475,6 +475,11 @@ class Factory final {
   Handle<JSMapIterator> NewJSMapIterator();
   Handle<JSSetIterator> NewJSSetIterator();
 
+  // Creates a new JSIteratorResult object with the arguments {value} and
+  // {done}.  Implemented according to ES6 section 7.4.7 CreateIterResultObject.
+  Handle<JSIteratorResult> NewJSIteratorResult(Handle<Object> value,
+                                               Handle<Object> done);
+
   // Allocates a Harmony proxy.
   Handle<JSProxy> NewJSProxy(Handle<Object> handler, Handle<Object> prototype);
 
index bd36108..7d81817 100644 (file)
@@ -2275,41 +2275,28 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
 
 
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
-  Label gc_required;
-  Label allocated;
+  Label allocate, done_allocate;
 
-  const int instance_size = 5 * kPointerSize;
-  DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(),
-            instance_size);
+  __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &allocate, TAG_OBJECT);
+  __ b(&done_allocate);
 
-  __ Allocate(instance_size, r0, r2, r3, &gc_required, TAG_OBJECT);
-  __ jmp(&allocated);
-
-  __ bind(&gc_required);
-  __ Push(Smi::FromInt(instance_size));
+  __ bind(&allocate);
+  __ Push(Smi::FromInt(JSIteratorResult::kSize));
   __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
-  __ ldr(context_register(),
-         MemOperand(fp, StandardFrameConstants::kContextOffset));
 
-  __ bind(&allocated);
+  __ bind(&done_allocate);
   __ ldr(r1, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
   __ ldr(r1, FieldMemOperand(r1, GlobalObject::kNativeContextOffset));
   __ ldr(r1, ContextOperand(r1, Context::ITERATOR_RESULT_MAP_INDEX));
   __ pop(r2);
-  __ mov(r3, Operand(isolate()->factory()->ToBoolean(done)));
-  __ mov(r4, Operand(isolate()->factory()->empty_fixed_array()));
+  __ LoadRoot(r3,
+              done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
+  __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex);
   __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
   __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
   __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
-  __ str(r2,
-         FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset));
-  __ str(r3,
-         FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset));
-
-  // Only the value field needs a write barrier, as the other values are in the
-  // root set.
-  __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset,
-                      r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
+  __ str(r2, FieldMemOperand(r0, JSIteratorResult::kValueOffset));
+  __ str(r3, FieldMemOperand(r0, JSIteratorResult::kDoneOffset));
 }
 
 
@@ -4473,6 +4460,37 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(2, args->length());
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+
+  Label runtime, done;
+
+  __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &runtime, TAG_OBJECT);
+  __ ldr(r1, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+  __ ldr(r1, FieldMemOperand(r1, GlobalObject::kNativeContextOffset));
+  __ ldr(r1, ContextOperand(r1, Context::ITERATOR_RESULT_MAP_INDEX));
+  __ pop(r3);
+  __ pop(r2);
+  __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex);
+  __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
+  __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
+  __ str(r2, FieldMemOperand(r0, JSIteratorResult::kValueOffset));
+  __ str(r3, FieldMemOperand(r0, JSIteratorResult::kDoneOffset));
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
+  __ b(&done);
+
+  __ bind(&runtime);
+  __ CallRuntime(Runtime::kCreateIterResultObject, 2);
+
+  __ bind(&done);
+  context()->Plug(r0);
+}
+
+
 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
   // Push undefined as the receiver.
   __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
index 65ceb7c..8b32fc9 100644 (file)
@@ -4172,6 +4172,49 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(2, args->length());
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+
+  Label runtime, done;
+
+  Register result = x0;
+  __ Allocate(JSIteratorResult::kSize, result, x10, x11, &runtime, TAG_OBJECT);
+  Register map_reg = x1;
+  Register result_value = x2;
+  Register boolean_done = x3;
+  Register empty_fixed_array = x4;
+  Register untagged_result = x5;
+  __ Ldr(map_reg, GlobalObjectMemOperand());
+  __ Ldr(map_reg, FieldMemOperand(map_reg, GlobalObject::kNativeContextOffset));
+  __ Ldr(map_reg,
+         ContextMemOperand(map_reg, Context::ITERATOR_RESULT_MAP_INDEX));
+  __ Pop(boolean_done);
+  __ Pop(result_value);
+  __ LoadRoot(empty_fixed_array, Heap::kEmptyFixedArrayRootIndex);
+  STATIC_ASSERT(JSObject::kPropertiesOffset + kPointerSize ==
+                JSObject::kElementsOffset);
+  STATIC_ASSERT(JSIteratorResult::kValueOffset + kPointerSize ==
+                JSIteratorResult::kDoneOffset);
+  __ ObjectUntag(untagged_result, result);
+  __ Str(map_reg, MemOperand(untagged_result, HeapObject::kMapOffset));
+  __ Stp(empty_fixed_array, empty_fixed_array,
+         MemOperand(untagged_result, JSObject::kPropertiesOffset));
+  __ Stp(result_value, boolean_done,
+         MemOperand(untagged_result, JSIteratorResult::kValueOffset));
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
+  __ B(&done);
+
+  __ Bind(&runtime);
+  __ CallRuntime(Runtime::kCreateIterResultObject, 2);
+
+  __ Bind(&done);
+  context()->Plug(x0);
+}
+
+
 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
   // Push undefined as the receiver.
   __ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
@@ -5081,26 +5124,19 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
 
 
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
-  Label gc_required;
-  Label allocated;
-
-  const int instance_size = 5 * kPointerSize;
-  DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(),
-            instance_size);
+  Label allocate, done_allocate;
 
   // Allocate and populate an object with this form: { value: VAL, done: DONE }
 
   Register result = x0;
-  __ Allocate(instance_size, result, x10, x11, &gc_required, TAG_OBJECT);
-  __ B(&allocated);
+  __ Allocate(JSIteratorResult::kSize, result, x10, x11, &allocate, TAG_OBJECT);
+  __ B(&done_allocate);
 
-  __ Bind(&gc_required);
-  __ Push(Smi::FromInt(instance_size));
+  __ Bind(&allocate);
+  __ Push(Smi::FromInt(JSIteratorResult::kSize));
   __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
-  __ Ldr(context_register(),
-         MemOperand(fp, StandardFrameConstants::kContextOffset));
 
-  __ Bind(&allocated);
+  __ Bind(&done_allocate);
   Register map_reg = x1;
   Register result_value = x2;
   Register boolean_done = x3;
@@ -5111,24 +5147,20 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   __ Ldr(map_reg,
          ContextMemOperand(map_reg, Context::ITERATOR_RESULT_MAP_INDEX));
   __ Pop(result_value);
-  __ Mov(boolean_done, Operand(isolate()->factory()->ToBoolean(done)));
-  __ Mov(empty_fixed_array, Operand(isolate()->factory()->empty_fixed_array()));
+  __ LoadRoot(boolean_done,
+              done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
+  __ LoadRoot(empty_fixed_array, Heap::kEmptyFixedArrayRootIndex);
   STATIC_ASSERT(JSObject::kPropertiesOffset + kPointerSize ==
                 JSObject::kElementsOffset);
-  STATIC_ASSERT(JSGeneratorObject::kResultValuePropertyOffset + kPointerSize ==
-                JSGeneratorObject::kResultDonePropertyOffset);
+  STATIC_ASSERT(JSIteratorResult::kValueOffset + kPointerSize ==
+                JSIteratorResult::kDoneOffset);
   __ ObjectUntag(untagged_result, result);
   __ Str(map_reg, MemOperand(untagged_result, HeapObject::kMapOffset));
   __ Stp(empty_fixed_array, empty_fixed_array,
          MemOperand(untagged_result, JSObject::kPropertiesOffset));
   __ Stp(result_value, boolean_done,
-         MemOperand(untagged_result,
-                    JSGeneratorObject::kResultValuePropertyOffset));
-
-  // Only the value field needs a write barrier, as the other values are in the
-  // root set.
-  __ RecordWriteField(result, JSGeneratorObject::kResultValuePropertyOffset,
-                      x10, x11, kLRHasBeenSaved, kDontSaveFPRegs);
+         MemOperand(untagged_result, JSIteratorResult::kValueOffset));
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
 }
 
 
index 435b56d..a4af52d 100644 (file)
@@ -530,7 +530,8 @@ class FullCodeGenerator: public AstVisitor {
   F(ToString)                             \
   F(ToName)                               \
   F(ToObject)                             \
-  F(DebugIsActive)
+  F(DebugIsActive)                        \
+  F(CreateIterResultObject)
 
 #define GENERATOR_DECLARATION(Name) void Emit##Name(CallRuntime* call);
   FOR_EACH_FULL_CODE_INTRINSIC(GENERATOR_DECLARATION)
index fab491b..df7ae9c 100644 (file)
@@ -2193,40 +2193,28 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
 
 
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
-  Label gc_required;
-  Label allocated;
+  Label allocate, done_allocate;
 
-  const int instance_size = 5 * kPointerSize;
-  DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(),
-            instance_size);
+  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT);
+  __ jmp(&done_allocate, Label::kNear);
 
-  __ Allocate(instance_size, eax, ecx, edx, &gc_required, TAG_OBJECT);
-  __ jmp(&allocated);
-
-  __ bind(&gc_required);
-  __ Push(Smi::FromInt(instance_size));
+  __ bind(&allocate);
+  __ Push(Smi::FromInt(JSIteratorResult::kSize));
   __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
-  __ mov(context_register(),
-         Operand(ebp, StandardFrameConstants::kContextOffset));
 
-  __ bind(&allocated);
-  __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  __ bind(&done_allocate);
+  __ mov(ebx, GlobalObjectOperand());
   __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
   __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
-  __ pop(ecx);
-  __ mov(edx, isolate()->factory()->ToBoolean(done));
   __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
   __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
          isolate()->factory()->empty_fixed_array());
   __ mov(FieldOperand(eax, JSObject::kElementsOffset),
          isolate()->factory()->empty_fixed_array());
-  __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx);
-  __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx);
-
-  // Only the value field needs a write barrier, as the other values are in the
-  // root set.
-  __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset,
-                      ecx, edx, kDontSaveFPRegs);
+  __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset));
+  __ mov(FieldOperand(eax, JSIteratorResult::kDoneOffset),
+         isolate()->factory()->ToBoolean(done));
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
 }
 
 
@@ -4412,6 +4400,36 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(2, args->length());
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+
+  Label runtime, done;
+
+  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime, TAG_OBJECT);
+  __ mov(ebx, GlobalObjectOperand());
+  __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
+  __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
+  __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
+  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
+         isolate()->factory()->empty_fixed_array());
+  __ mov(FieldOperand(eax, JSObject::kElementsOffset),
+         isolate()->factory()->empty_fixed_array());
+  __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset));
+  __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset));
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
+  __ jmp(&done, Label::kNear);
+
+  __ bind(&runtime);
+  __ CallRuntime(Runtime::kCreateIterResultObject, 2);
+
+  __ bind(&done);
+  context()->Plug(eax);
+}
+
+
 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
   // Push undefined as receiver.
   __ push(Immediate(isolate()->factory()->undefined_value()));
index a2e7cba..e985f44 100644 (file)
@@ -2266,23 +2266,16 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
 
 
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
-  Label gc_required;
-  Label allocated;
+  Label allocate, done_allocate;
 
-  const int instance_size = 5 * kPointerSize;
-  DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(),
-            instance_size);
+  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &allocate, TAG_OBJECT);
+  __ jmp(&done_allocate);
 
-  __ Allocate(instance_size, v0, a2, a3, &gc_required, TAG_OBJECT);
-  __ jmp(&allocated);
-
-  __ bind(&gc_required);
-  __ Push(Smi::FromInt(instance_size));
+  __ bind(&allocate);
+  __ Push(Smi::FromInt(JSIteratorResult::kSize));
   __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
-  __ lw(context_register(),
-        MemOperand(fp, StandardFrameConstants::kContextOffset));
 
-  __ bind(&allocated);
+  __ bind(&done_allocate);
   __ lw(a1, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
   __ lw(a1, FieldMemOperand(a1, GlobalObject::kNativeContextOffset));
   __ lw(a1, ContextOperand(a1, Context::ITERATOR_RESULT_MAP_INDEX));
@@ -2292,15 +2285,9 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   __ sw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
   __ sw(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset));
   __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
-  __ sw(a2,
-        FieldMemOperand(v0, JSGeneratorObject::kResultValuePropertyOffset));
-  __ sw(a3,
-        FieldMemOperand(v0, JSGeneratorObject::kResultDonePropertyOffset));
-
-  // Only the value field needs a write barrier, as the other values are in the
-  // root set.
-  __ RecordWriteField(v0, JSGeneratorObject::kResultValuePropertyOffset,
-                      a2, a3, kRAHasBeenSaved, kDontSaveFPRegs);
+  __ sw(a2, FieldMemOperand(v0, JSIteratorResult::kValueOffset));
+  __ sw(a3, FieldMemOperand(v0, JSIteratorResult::kDoneOffset));
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
 }
 
 
@@ -4499,6 +4486,37 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(2, args->length());
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+
+  Label runtime, done;
+
+  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &runtime, TAG_OBJECT);
+  __ lw(a1, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+  __ lw(a1, FieldMemOperand(a1, GlobalObject::kNativeContextOffset));
+  __ lw(a1, ContextOperand(a1, Context::ITERATOR_RESULT_MAP_INDEX));
+  __ pop(a3);
+  __ pop(a2);
+  __ li(t0, Operand(isolate()->factory()->empty_fixed_array()));
+  __ sw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
+  __ sw(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+  __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
+  __ sw(a2, FieldMemOperand(v0, JSIteratorResult::kValueOffset));
+  __ sw(a3, FieldMemOperand(v0, JSIteratorResult::kDoneOffset));
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
+  __ jmp(&done);
+
+  __ bind(&runtime);
+  __ CallRuntime(Runtime::kCreateIterResultObject, 2);
+
+  __ bind(&done);
+  context()->Plug(v0);
+}
+
+
 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
   // Push undefined as the receiver.
   __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
index bcd90de..bd1fea2 100644 (file)
@@ -2264,41 +2264,28 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
 
 
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
-  Label gc_required;
-  Label allocated;
+  Label allocate, done_allocate;
 
-  const int instance_size = 5 * kPointerSize;
-  DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(),
-            instance_size);
+  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &allocate, TAG_OBJECT);
+  __ jmp(&done_allocate);
 
-  __ Allocate(instance_size, v0, a2, a3, &gc_required, TAG_OBJECT);
-  __ jmp(&allocated);
-
-  __ bind(&gc_required);
-  __ Push(Smi::FromInt(instance_size));
+  __ bind(&allocate);
+  __ Push(Smi::FromInt(JSIteratorResult::kSize));
   __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
-  __ ld(context_register(),
-        MemOperand(fp, StandardFrameConstants::kContextOffset));
 
-  __ bind(&allocated);
+  __ bind(&done_allocate);
   __ ld(a1, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
   __ ld(a1, FieldMemOperand(a1, GlobalObject::kNativeContextOffset));
   __ ld(a1, ContextOperand(a1, Context::ITERATOR_RESULT_MAP_INDEX));
   __ pop(a2);
   __ li(a3, Operand(isolate()->factory()->ToBoolean(done)));
-  __ li(a4, Operand(isolate()->factory()->empty_fixed_array()));
+  __ li(t0, Operand(isolate()->factory()->empty_fixed_array()));
   __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
-  __ sd(a4, FieldMemOperand(v0, JSObject::kPropertiesOffset));
-  __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset));
-  __ sd(a2,
-        FieldMemOperand(v0, JSGeneratorObject::kResultValuePropertyOffset));
-  __ sd(a3,
-        FieldMemOperand(v0, JSGeneratorObject::kResultDonePropertyOffset));
-
-  // Only the value field needs a write barrier, as the other values are in the
-  // root set.
-  __ RecordWriteField(v0, JSGeneratorObject::kResultValuePropertyOffset,
-                      a2, a3, kRAHasBeenSaved, kDontSaveFPRegs);
+  __ sd(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+  __ sd(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
+  __ sd(a2, FieldMemOperand(v0, JSIteratorResult::kValueOffset));
+  __ sd(a3, FieldMemOperand(v0, JSIteratorResult::kDoneOffset));
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
 }
 
 
@@ -4503,6 +4490,37 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(2, args->length());
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+
+  Label runtime, done;
+
+  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &runtime, TAG_OBJECT);
+  __ ld(a1, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+  __ ld(a1, FieldMemOperand(a1, GlobalObject::kNativeContextOffset));
+  __ ld(a1, ContextOperand(a1, Context::ITERATOR_RESULT_MAP_INDEX));
+  __ pop(a3);
+  __ pop(a2);
+  __ li(t0, Operand(isolate()->factory()->empty_fixed_array()));
+  __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
+  __ sd(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+  __ sd(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
+  __ sd(a2, FieldMemOperand(v0, JSIteratorResult::kValueOffset));
+  __ sd(a3, FieldMemOperand(v0, JSIteratorResult::kDoneOffset));
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
+  __ jmp(&done);
+
+  __ bind(&runtime);
+  __ CallRuntime(Runtime::kCreateIterResultObject, 2);
+
+  __ bind(&done);
+  context()->Plug(v0);
+}
+
+
 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
   // Push undefined as the receiver.
   __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
index a91ccdd..2010590 100644 (file)
@@ -2217,42 +2217,27 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
 
 
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
-  Label gc_required;
-  Label allocated;
+  Label allocate, done_allocate;
 
-  const int instance_size = 5 * kPointerSize;
-  DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(),
-            instance_size);
+  __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &allocate, TAG_OBJECT);
+  __ jmp(&done_allocate, Label::kNear);
 
-  __ Allocate(instance_size, rax, rcx, rdx, &gc_required, TAG_OBJECT);
-  __ jmp(&allocated);
-
-  __ bind(&gc_required);
-  __ Push(Smi::FromInt(instance_size));
+  __ bind(&allocate);
+  __ Push(Smi::FromInt(JSIteratorResult::kSize));
   __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
-  __ movp(context_register(),
-          Operand(rbp, StandardFrameConstants::kContextOffset));
 
-  __ bind(&allocated);
-  __ movp(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  __ bind(&done_allocate);
+  __ movp(rbx, GlobalObjectOperand());
   __ movp(rbx, FieldOperand(rbx, GlobalObject::kNativeContextOffset));
   __ movp(rbx, ContextOperand(rbx, Context::ITERATOR_RESULT_MAP_INDEX));
-  __ Pop(rcx);
-  __ Move(rdx, isolate()->factory()->ToBoolean(done));
   __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
-  __ Move(FieldOperand(rax, JSObject::kPropertiesOffset),
-          isolate()->factory()->empty_fixed_array());
-  __ Move(FieldOperand(rax, JSObject::kElementsOffset),
-          isolate()->factory()->empty_fixed_array());
-  __ movp(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset),
-          rcx);
-  __ movp(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset),
-          rdx);
-
-  // Only the value field needs a write barrier, as the other values are in the
-  // root set.
-  __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset,
-                      rcx, rdx, kDontSaveFPRegs);
+  __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
+  __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
+  __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx);
+  __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset));
+  __ LoadRoot(FieldOperand(rax, JSIteratorResult::kDoneOffset),
+              done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
 }
 
 
@@ -4423,6 +4408,35 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(2, args->length());
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+
+  Label runtime, done;
+
+  __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &runtime, TAG_OBJECT);
+  __ movp(rbx, GlobalObjectOperand());
+  __ movp(rbx, FieldOperand(rbx, GlobalObject::kNativeContextOffset));
+  __ movp(rbx, ContextOperand(rbx, Context::ITERATOR_RESULT_MAP_INDEX));
+  __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
+  __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
+  __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
+  __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx);
+  __ Pop(FieldOperand(rax, JSIteratorResult::kDoneOffset));
+  __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset));
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
+  __ jmp(&done, Label::kNear);
+
+  __ bind(&runtime);
+  __ CallRuntime(Runtime::kCreateIterResultObject, 2);
+
+  __ bind(&done);
+  context()->Plug(rax);
+}
+
+
 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
   // Push the builtins object as receiver.
   __ PushRoot(Heap::kUndefinedValueRootIndex);
index 28a68ee..6660d42 100644 (file)
@@ -137,6 +137,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
     case JS_MESSAGE_OBJECT_TYPE:
     case JS_SET_ITERATOR_TYPE:
     case JS_MAP_ITERATOR_TYPE:
+    case JS_ITERATOR_RESULT_TYPE:
       return GetVisitorIdForSize(kVisitJSObject, kVisitJSObjectGeneric,
                                  instance_size, has_unboxed_fields);
 
@@ -226,6 +227,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
     case JS_MAP_TYPE:
     case JS_SET_ITERATOR_TYPE:
     case JS_MAP_ITERATOR_TYPE:
+    case JS_ITERATOR_RESULT_TYPE:
     case JS_WEAK_MAP_TYPE:
     case JS_WEAK_SET_TYPE:
     case JS_REGEXP_TYPE:
index 46a1e6f..ef6579e 100644 (file)
@@ -1816,6 +1816,37 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
 }
 
 
+HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value,
+                                                   HValue* done) {
+  NoObservableSideEffectsScope scope(this);
+
+  // Allocate the JSIteratorResult object.
+  HValue* result =
+      Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(),
+                     NOT_TENURED, JS_ITERATOR_RESULT_TYPE);
+
+  // Initialize the JSIteratorResult object.
+  HValue* native_context = BuildGetNativeContext();
+  HValue* map = Add<HLoadNamedField>(
+      native_context, nullptr,
+      HObjectAccess::ForContextSlot(Context::ITERATOR_RESULT_MAP_INDEX));
+  Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
+  HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
+  Add<HStoreNamedField>(result, HObjectAccess::ForPropertiesPointer(),
+                        empty_fixed_array);
+  Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(),
+                        empty_fixed_array);
+  Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
+                                    JSIteratorResult::kValueOffset),
+                        value);
+  Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
+                                    JSIteratorResult::kDoneOffset),
+                        done);
+  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
+  return result;
+}
+
+
 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
                                                   HValue* index,
                                                   HValue* input) {
@@ -12597,6 +12628,17 @@ void HOptimizedGraphBuilder::GenerateTheHole(CallRuntime* call) {
 }
 
 
+void HOptimizedGraphBuilder::GenerateCreateIterResultObject(CallRuntime* call) {
+  DCHECK_EQ(2, call->arguments()->length());
+  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
+  HValue* done = Pop();
+  HValue* value = Pop();
+  HValue* result = BuildCreateIterResultObject(value, done);
+  return ast_context()->ReturnValue(result);
+}
+
+
 void HOptimizedGraphBuilder::GenerateJSCollectionGetTable(CallRuntime* call) {
   DCHECK(call->arguments()->length() == 1);
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
index 0a6b2e2..45c15ba 100644 (file)
@@ -1358,6 +1358,9 @@ class HGraphBuilder {
                                               HValue* hash,
                                               LanguageMode language_mode);
 
+  // ES6 section 7.4.7 CreateIterResultObject ( value, done )
+  HValue* BuildCreateIterResultObject(HValue* value, HValue* done);
+
   HValue* BuildRegExpConstructResult(HValue* length,
                                      HValue* index,
                                      HValue* input);
@@ -2267,6 +2270,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
   F(JSCollectionGetTable)              \
   F(StringGetRawHashField)             \
   F(TheHole)                           \
+  /* ES6 Iterators */                  \
+  F(CreateIterResultObject)            \
   /* Arrays */                         \
   F(HasFastPackedElements)             \
   /* Strings */                        \
index 889a760..12b4ec7 100644 (file)
@@ -144,6 +144,9 @@ void HeapObject::HeapObjectVerify() {
     case JS_MAP_ITERATOR_TYPE:
       JSMapIterator::cast(this)->JSMapIteratorVerify();
       break;
+    case JS_ITERATOR_RESULT_TYPE:
+      JSIteratorResult::cast(this)->JSIteratorResultVerify();
+      break;
     case JS_WEAK_MAP_TYPE:
       JSWeakMap::cast(this)->JSWeakMapVerify();
       break;
@@ -741,6 +744,14 @@ void JSMapIterator::JSMapIteratorVerify() {
 }
 
 
+void JSIteratorResult::JSIteratorResultVerify() {
+  CHECK(IsJSIteratorResult());
+  JSObjectVerify();
+  VerifyPointer(done());
+  VerifyPointer(value());
+}
+
+
 void JSWeakMap::JSWeakMapVerify() {
   CHECK(IsJSWeakMap());
   JSObjectVerify();
index 794e017..bbcca26 100644 (file)
@@ -704,6 +704,7 @@ TYPE_CHECKER(JSSet, JS_SET_TYPE)
 TYPE_CHECKER(JSMap, JS_MAP_TYPE)
 TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
 TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
+TYPE_CHECKER(JSIteratorResult, JS_ITERATOR_RESULT_TYPE)
 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
 TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
@@ -2150,6 +2151,8 @@ int JSObject::GetHeaderSize() {
       return JSSetIterator::kSize;
     case JS_MAP_ITERATOR_TYPE:
       return JSMapIterator::kSize;
+    case JS_ITERATOR_RESULT_TYPE:
+      return JSIteratorResult::kSize;
     case JS_WEAK_MAP_TYPE:
       return JSWeakMap::kSize;
     case JS_WEAK_SET_TYPE:
@@ -3325,6 +3328,7 @@ CAST_ACCESSOR(JSReceiver)
 CAST_ACCESSOR(JSRegExp)
 CAST_ACCESSOR(JSSet)
 CAST_ACCESSOR(JSSetIterator)
+CAST_ACCESSOR(JSIteratorResult)
 CAST_ACCESSOR(JSTypedArray)
 CAST_ACCESSOR(JSValue)
 CAST_ACCESSOR(JSWeakMap)
@@ -7799,6 +7803,10 @@ Object* JSMapIterator::CurrentValue() {
 }
 
 
+ACCESSORS(JSIteratorResult, done, Object, kDoneOffset)
+ACCESSORS(JSIteratorResult, value, Object, kValueOffset)
+
+
 String::SubStringRange::SubStringRange(String* string, int first, int length)
     : string_(string),
       first_(first),
index 6cab6fd..aa74624 100644 (file)
@@ -144,6 +144,9 @@ void HeapObject::HeapObjectPrint(std::ostream& os) {  // NOLINT
     case JS_MAP_ITERATOR_TYPE:
       JSMapIterator::cast(this)->JSMapIteratorPrint(os);
       break;
+    case JS_ITERATOR_RESULT_TYPE:
+      JSIteratorResult::cast(this)->JSIteratorResultPrint(os);
+      break;
     case JS_WEAK_MAP_TYPE:
       JSWeakMap::cast(this)->JSWeakMapPrint(os);
       break;
@@ -756,6 +759,15 @@ void JSMapIterator::JSMapIteratorPrint(std::ostream& os) {  // NOLINT
 }
 
 
+void JSIteratorResult::JSIteratorResultPrint(std::ostream& os) {  // NOLINT
+  HeapObject::PrintHeader(os, "JSIteratorResult");
+  os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
+  os << " - done = " << Brief(done()) << "\n";
+  os << " - value = " << Brief(value()) << "\n";
+  os << "\n";
+}
+
+
 void JSWeakMap::JSWeakMapPrint(std::ostream& os) {  // NOLINT
   HeapObject::PrintHeader(os, "JSWeakMap");
   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
index 0c9a6d2..4ece658 100644 (file)
@@ -431,6 +431,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
   V(JS_MAP_TYPE)                                                \
   V(JS_SET_ITERATOR_TYPE)                                       \
   V(JS_MAP_ITERATOR_TYPE)                                       \
+  V(JS_ITERATOR_RESULT_TYPE)                                    \
   V(JS_WEAK_MAP_TYPE)                                           \
   V(JS_WEAK_SET_TYPE)                                           \
   V(JS_REGEXP_TYPE)                                             \
@@ -729,6 +730,7 @@ enum InstanceType {
   JS_MAP_TYPE,
   JS_SET_ITERATOR_TYPE,
   JS_MAP_ITERATOR_TYPE,
+  JS_ITERATOR_RESULT_TYPE,
   JS_WEAK_MAP_TYPE,
   JS_WEAK_SET_TYPE,
   JS_REGEXP_TYPE,
@@ -957,6 +959,7 @@ template <class C> inline bool Is(Object* obj);
   V(JSMap)                         \
   V(JSSetIterator)                 \
   V(JSMapIterator)                 \
+  V(JSIteratorResult)              \
   V(JSWeakCollection)              \
   V(JSWeakMap)                     \
   V(JSWeakSet)                     \
@@ -6860,17 +6863,6 @@ class JSGeneratorObject: public JSObject {
   // Resume mode, for use by runtime functions.
   enum ResumeMode { NEXT, THROW };
 
-  // Yielding from a generator returns an object with the following inobject
-  // properties.  See Context::iterator_result_map() for the map.
-  static const int kResultValuePropertyIndex = 0;
-  static const int kResultDonePropertyIndex = 1;
-  static const int kResultPropertyCount = 2;
-
-  static const int kResultValuePropertyOffset = JSObject::kHeaderSize;
-  static const int kResultDonePropertyOffset =
-      kResultValuePropertyOffset + kPointerSize;
-  static const int kResultSize = kResultDonePropertyOffset + kPointerSize;
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSGeneratorObject);
 };
@@ -9489,6 +9481,40 @@ class JSMapIterator: public OrderedHashTableIterator<JSMapIterator,
 };
 
 
+// ES6 section 25.1.1.3 The IteratorResult Interface
+class JSIteratorResult final : public JSObject {
+ public:
+  // [done]: This is the result status of an iterator next method call.  If the
+  // end of the iterator was reached done is true.  If the end was not reached
+  // done is false and a [value] is available.
+  DECL_ACCESSORS(done, Object)
+
+  // [value]: If [done] is false, this is the current iteration element value.
+  // If [done] is true, this is the return value of the iterator, if it supplied
+  // one.  If the iterator does not have a return value, value is undefined.
+  // In that case, the value property may be absent from the conforming object
+  // if it does not inherit an explicit value property.
+  DECL_ACCESSORS(value, Object)
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(JSIteratorResult)
+  DECLARE_VERIFIER(JSIteratorResult)
+
+  DECLARE_CAST(JSIteratorResult)
+
+  static const int kValueOffset = JSObject::kHeaderSize;
+  static const int kDoneOffset = kValueOffset + kPointerSize;
+  static const int kSize = kDoneOffset + kPointerSize;
+
+  // Indices of in-object properties.
+  static const int kValueIndex = 0;
+  static const int kDoneIndex = 1;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSIteratorResult);
+};
+
+
 // Base class for both JSWeakMap and JSWeakSet
 class JSWeakCollection: public JSObject {
  public:
index e53aef6..5945488 100644 (file)
@@ -1558,5 +1558,15 @@ RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) {
       object->HasInPrototypeChain(isolate, prototype));
 }
 
+
+// ES6 section 7.4.7 CreateIterResultObject ( value, done )
+RUNTIME_FUNCTION(Runtime_CreateIterResultObject) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(2, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, done, 1);
+  return *isolate->factory()->NewJSIteratorResult(value, done);
+}
+
 }  // namespace internal
 }  // namespace v8
index d0738a0..30ea5fc 100644 (file)
@@ -498,7 +498,8 @@ namespace internal {
   F(ToName, 1, 1)                                    \
   F(StrictEquals, 2, 1)                              \
   F(InstanceOf, 2, 1)                                \
-  F(HasInPrototypeChain, 2, 1)
+  F(HasInPrototypeChain, 2, 1)                       \
+  F(CreateIterResultObject, 2, 1)
 
 
 #define FOR_EACH_INTRINSIC_OBSERVE(F)            \
index 42ddb23..d637757 100644 (file)
@@ -11,7 +11,6 @@
 // -------------------------------------------------------------------
 // Imports
 
-var ArrayIteratorCreateResultObject;
 var GlobalString = global.String;
 var iteratorSymbol = utils.ImportNow("iterator_symbol");
 var stringIteratorIteratedStringSymbol =
@@ -20,10 +19,6 @@ var stringIteratorNextIndexSymbol =
     utils.ImportNow("string_iterator_next_index_symbol");
 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
 
-utils.Import(function(from) {
-  ArrayIteratorCreateResultObject = from.ArrayIteratorCreateResultObject;
-});
-
 // -------------------------------------------------------------------
 
 function StringIterator() {}
@@ -39,9 +34,11 @@ function CreateStringIterator(string) {
 }
 
 
-// 21.1.5.2.1 %StringIteratorPrototype%.next( )
+// ES6 section 21.1.5.2.1 %StringIteratorPrototype%.next ( )
 function StringIteratorNext() {
   var iterator = this;
+  var value = UNDEFINED;
+  var done = true;
 
   if (!IS_SPEC_OBJECT(iterator) ||
       !HAS_DEFINED_PRIVATE(iterator, stringIteratorNextIndexSymbol)) {
@@ -50,34 +47,29 @@ function StringIteratorNext() {
   }
 
   var s = GET_PRIVATE(iterator, stringIteratorIteratedStringSymbol);
-  if (IS_UNDEFINED(s)) {
-    return ArrayIteratorCreateResultObject(UNDEFINED, true);
-  }
-
-  var position = GET_PRIVATE(iterator, stringIteratorNextIndexSymbol);
-  var length = TO_UINT32(s.length);
-
-  if (position >= length) {
-    SET_PRIVATE(iterator, stringIteratorIteratedStringSymbol,
-                UNDEFINED);
-    return ArrayIteratorCreateResultObject(UNDEFINED, true);
-  }
+  if (!IS_UNDEFINED(s)) {
+    var position = GET_PRIVATE(iterator, stringIteratorNextIndexSymbol);
+    var length = TO_UINT32(s.length);
+    if (position >= length) {
+      SET_PRIVATE(iterator, stringIteratorIteratedStringSymbol, UNDEFINED);
+    } else {
+      var first = %_StringCharCodeAt(s, position);
+      value = %_StringCharFromCode(first);
+      done = false;
+      position++;
 
-  var first = %_StringCharCodeAt(s, position);
-  var resultString = %_StringCharFromCode(first);
-  position++;
+      if (first >= 0xD800 && first <= 0xDBFF && position < length) {
+        var second = %_StringCharCodeAt(s, position);
+        if (second >= 0xDC00 && second <= 0xDFFF) {
+          value += %_StringCharFromCode(second);
+          position++;
+        }
+      }
 
-  if (first >= 0xD800 && first <= 0xDBFF && position < length) {
-    var second = %_StringCharCodeAt(s, position);
-    if (second >= 0xDC00 && second <= 0xDFFF) {
-      resultString += %_StringCharFromCode(second);
-      position++;
+      SET_PRIVATE(iterator, stringIteratorNextIndexSymbol, position);
     }
   }
-
-  SET_PRIVATE(iterator, stringIteratorNextIndexSymbol, position);
-
-  return ArrayIteratorCreateResultObject(resultString, false);
+  return %_CreateIterResultObject(value, done);
 }
 
 
index 769b91b..63feb82 100644 (file)
@@ -133,6 +133,10 @@ class MacroAssembler: public Assembler {
 
   // Operations on roots in the root-array.
   void LoadRoot(Register destination, Heap::RootListIndex index);
+  void LoadRoot(const Operand& destination, Heap::RootListIndex index) {
+    LoadRoot(kScratchRegister, index);
+    movp(destination, kScratchRegister);
+  }
   void StoreRoot(Register source, Heap::RootListIndex index);
   // Load a root value where the index (or part of it) is variable.
   // The variable_offset register is added to the fixed_offset value