}
-// 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)) {
}
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);
}
// -------------------------------------------------------------------
// Exports
-utils.Export(function(to) {
- to.ArrayIteratorCreateResultObject = CreateIteratorResultObject;
-});
-
$arrayValues = ArrayValues;
%InstallToContext(["array_values_iterator", ArrayValues]);
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
}
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;
}
}
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;
}
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) \
}
+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) {
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);
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));
}
}
+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);
}
+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);
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;
__ 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);
}
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)
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);
}
}
+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()));
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));
__ 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);
}
}
+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);
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);
}
}
+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);
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);
}
}
+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);
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);
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:
}
+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) {
}
+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)));
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);
F(JSCollectionGetTable) \
F(StringGetRawHashField) \
F(TheHole) \
+ /* ES6 Iterators */ \
+ F(CreateIterResultObject) \
/* Arrays */ \
F(HasFastPackedElements) \
/* Strings */ \
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;
}
+void JSIteratorResult::JSIteratorResultVerify() {
+ CHECK(IsJSIteratorResult());
+ JSObjectVerify();
+ VerifyPointer(done());
+ VerifyPointer(value());
+}
+
+
void JSWeakMap::JSWeakMapVerify() {
CHECK(IsJSWeakMap());
JSObjectVerify();
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)
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:
CAST_ACCESSOR(JSRegExp)
CAST_ACCESSOR(JSSet)
CAST_ACCESSOR(JSSetIterator)
+CAST_ACCESSOR(JSIteratorResult)
CAST_ACCESSOR(JSTypedArray)
CAST_ACCESSOR(JSValue)
CAST_ACCESSOR(JSWeakMap)
}
+ACCESSORS(JSIteratorResult, done, Object, kDoneOffset)
+ACCESSORS(JSIteratorResult, value, Object, kValueOffset)
+
+
String::SubStringRange::SubStringRange(String* string, int first, int length)
: string_(string),
first_(first),
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;
}
+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";
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) \
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,
V(JSMap) \
V(JSSetIterator) \
V(JSMapIterator) \
+ V(JSIteratorResult) \
V(JSWeakCollection) \
V(JSWeakMap) \
V(JSWeakSet) \
// 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);
};
};
+// 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:
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
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) \
// -------------------------------------------------------------------
// Imports
-var ArrayIteratorCreateResultObject;
var GlobalString = global.String;
var iteratorSymbol = utils.ImportNow("iterator_symbol");
var stringIteratorIteratedStringSymbol =
utils.ImportNow("string_iterator_next_index_symbol");
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
-utils.Import(function(from) {
- ArrayIteratorCreateResultObject = from.ArrayIteratorCreateResultObject;
-});
-
// -------------------------------------------------------------------
function StringIterator() {}
}
-// 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)) {
}
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);
}
// 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