// Try to allocate the object without transitioning into C code. If any of
// the preconditions is not met, the code bails out to the runtime call.
if (FLAG_inline_new) {
- Label undo_allocation;
ExternalReference debug_step_in_fp =
ExternalReference::debug_step_in_fp_address(isolate);
__ mov(r2, Operand(debug_step_in_fp));
// Allocate object with a slack.
__ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
- __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
+ __ Ubfx(r0, r0, Map::kInObjectPropertiesByte * kBitsPerByte,
kBitsPerByte);
+ __ ldr(r2, FieldMemOperand(r2, Map::kInstanceAttributesOffset));
+ __ Ubfx(r2, r2, Map::kUnusedPropertyFieldsByte * kBitsPerByte,
+ kBitsPerByte);
+ __ sub(r0, r0, Operand(r2));
__ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
// r0: offset of first field after pre-allocated fields
if (FLAG_debug_code) {
}
// Add the object tag to make the JSObject real, so that we can continue
- // and jump into the continuation code at any time from now on. Any
- // failures need to undo the allocation, so that the heap is in a
- // consistent state and verifiable.
+ // and jump into the continuation code at any time from now on.
__ add(r4, r4, Operand(kHeapObjectTag));
- // Check if a non-empty properties array is needed. Continue with
- // allocated object if not; allocate and initialize a FixedArray if yes.
- // r1: constructor function
- // r4: JSObject
- // r5: start of next object (not tagged)
- __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
- // The field instance sizes contains both pre-allocated property fields
- // and in-object properties.
- __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
- __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
- kBitsPerByte);
- __ add(r3, r3, Operand(r6));
- __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte,
- kBitsPerByte);
- __ sub(r3, r3, Operand(r6), SetCC);
-
- // Done if no extra properties are to be allocated.
- __ b(eq, &allocated);
- __ Assert(pl, kPropertyAllocationCountFailed);
-
- // Scale the number of elements by pointer size and add the header for
- // FixedArrays to the start of the next object calculation from above.
- // r1: constructor
- // r3: number of elements in properties array
- // r4: JSObject
- // r5: start of next object
- __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
- __ Allocate(
- r0,
- r5,
- r6,
- r2,
- &undo_allocation,
- static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
-
- // Initialize the FixedArray.
- // r1: constructor
- // r3: number of elements in properties array
- // r4: JSObject
- // r5: FixedArray (not tagged)
- __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
- __ mov(r2, r5);
- DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
- __ str(r6, MemOperand(r2, kPointerSize, PostIndex));
- DCHECK_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
- __ SmiTag(r0, r3);
- __ str(r0, MemOperand(r2, kPointerSize, PostIndex));
-
- // Initialize the fields to undefined.
- // r1: constructor function
- // r2: First element of FixedArray (not tagged)
- // r3: number of elements in properties array
- // r4: JSObject
- // r5: FixedArray (not tagged)
- __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
- DCHECK_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
- __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
- __ InitializeFieldsWithFiller(r2, r6, r0);
-
- // Store the initialized FixedArray into the properties field of
- // the JSObject
- // r1: constructor function
- // r4: JSObject
- // r5: FixedArray (not tagged)
- __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag.
- __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset));
-
// Continue with JSObject being successfully allocated
- // r1: constructor function
// r4: JSObject
__ jmp(&allocated);
-
- // Undo the setting of the new top so that the heap is verifiable. For
- // example, the map's unused properties potentially do not match the
- // allocated objects unused properties.
- // r4: JSObject (previous new top)
- __ bind(&undo_allocation);
- __ UndoAllocationInNewSpace(r4, r5);
}
// Allocate the new receiver object using the runtime call.
}
-void MacroAssembler::UndoAllocationInNewSpace(Register object,
- Register scratch) {
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
-
- // Make sure the object has no tag before resetting top.
- and_(object, object, Operand(~kHeapObjectTagMask));
-#ifdef DEBUG
- // Check that the object un-allocated is below the current top.
- mov(scratch, Operand(new_space_allocation_top));
- ldr(scratch, MemOperand(scratch));
- cmp(object, scratch);
- Check(lt, kUndoAllocationOfNonAllocatedMemory);
-#endif
- // Write the address of the object to un-allocate as the current top.
- mov(scratch, Operand(new_space_allocation_top));
- str(object, MemOperand(scratch));
-}
-
-
void MacroAssembler::AllocateTwoByteString(Register result,
Register length,
Register scratch1,
Label* gc_required,
AllocationFlags flags);
- // Undo allocation in new space. The object passed and objects allocated after
- // it will no longer be allocated. The caller must make sure that no pointers
- // are left to the object(s) no longer allocated as they would be invalid when
- // allocation is undone.
- void UndoAllocationInNewSpace(Register object, Register scratch);
-
-
void AllocateTwoByteString(Register result,
Register length,
Register scratch1,
// Try to allocate the object without transitioning into C code. If any of
// the preconditions is not met, the code bails out to the runtime call.
if (FLAG_inline_new) {
- Label undo_allocation;
ExternalReference debug_step_in_fp =
ExternalReference::debug_step_in_fp_address(isolate);
__ Mov(x2, Operand(debug_step_in_fp));
// Obtain number of pre-allocated property fields and in-object
// properties.
- Register prealloc_fields = x10;
+ Register unused_props = x10;
Register inobject_props = x11;
- Register inst_sizes = x11;
- __ Ldr(inst_sizes, FieldMemOperand(init_map, Map::kInstanceSizesOffset));
- __ Ubfx(prealloc_fields, inst_sizes,
- Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
- kBitsPerByte);
- __ Ubfx(inobject_props, inst_sizes,
+ Register inst_sizes_or_attrs = x11;
+ Register prealloc_fields = x10;
+ __ Ldr(inst_sizes_or_attrs,
+ FieldMemOperand(init_map, Map::kInstanceAttributesOffset));
+ __ Ubfx(unused_props, inst_sizes_or_attrs,
+ Map::kUnusedPropertyFieldsByte * kBitsPerByte, kBitsPerByte);
+ __ Ldr(inst_sizes_or_attrs,
+ FieldMemOperand(init_map, Map::kInstanceSizesOffset));
+ __ Ubfx(inobject_props, inst_sizes_or_attrs,
Map::kInObjectPropertiesByte * kBitsPerByte, kBitsPerByte);
+ __ Sub(prealloc_fields, inobject_props, unused_props);
// Calculate number of property fields in the object.
Register prop_fields = x6;
}
// Add the object tag to make the JSObject real, so that we can continue
- // and jump into the continuation code at any time from now on. Any
- // failures need to undo the allocation, so that the heap is in a
- // consistent state and verifiable.
+ // and jump into the continuation code at any time from now on.
__ Add(new_obj, new_obj, kHeapObjectTag);
- // Check if a non-empty properties array is needed. Continue with
- // allocated object if not; allocate and initialize a FixedArray if yes.
- Register element_count = x3;
- __ Ldrb(element_count,
- FieldMemOperand(init_map, Map::kUnusedPropertyFieldsOffset));
- // The field instance sizes contains both pre-allocated property fields
- // and in-object properties.
- __ Add(element_count, element_count, prealloc_fields);
- __ Subs(element_count, element_count, inobject_props);
-
- // Done if no extra properties are to be allocated.
- __ B(eq, &allocated);
- __ Assert(pl, kPropertyAllocationCountFailed);
-
- // Scale the number of elements by pointer size and add the header for
- // FixedArrays to the start of the next object calculation from above.
- Register new_array = x5;
- Register array_size = x6;
- __ Add(array_size, element_count, FixedArray::kHeaderSize / kPointerSize);
- __ Allocate(array_size, new_array, x11, x12, &undo_allocation,
- static_cast<AllocationFlags>(RESULT_CONTAINS_TOP |
- SIZE_IN_WORDS));
-
- Register array_map = x10;
- __ LoadRoot(array_map, Heap::kFixedArrayMapRootIndex);
- __ Str(array_map, MemOperand(new_array, FixedArray::kMapOffset));
- __ SmiTag(x0, element_count);
- __ Str(x0, MemOperand(new_array, FixedArray::kLengthOffset));
-
- // Initialize the fields to undefined.
- Register elements = x10;
- __ Add(elements, new_array, FixedArray::kHeaderSize);
- __ FillFields(elements, element_count, filler);
-
- // Store the initialized FixedArray into the properties field of the
- // JSObject.
- __ Add(new_array, new_array, kHeapObjectTag);
- __ Str(new_array, FieldMemOperand(new_obj, JSObject::kPropertiesOffset));
-
// Continue with JSObject being successfully allocated.
__ B(&allocated);
-
- // Undo the setting of the new top so that the heap is verifiable. For
- // example, the map's unused properties potentially do not match the
- // allocated objects unused properties.
- __ Bind(&undo_allocation);
- __ UndoAllocationInNewSpace(new_obj, x14);
}
// Allocate the new receiver object using the runtime call.
}
-void MacroAssembler::UndoAllocationInNewSpace(Register object,
- Register scratch) {
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
-
- // Make sure the object has no tag before resetting top.
- Bic(object, object, kHeapObjectTagMask);
-#ifdef DEBUG
- // Check that the object un-allocated is below the current top.
- Mov(scratch, new_space_allocation_top);
- Ldr(scratch, MemOperand(scratch));
- Cmp(object, scratch);
- Check(lt, kUndoAllocationOfNonAllocatedMemory);
-#endif
- // Write the address of the object to un-allocate as the current top.
- Mov(scratch, new_space_allocation_top);
- Str(object, MemOperand(scratch));
-}
-
-
void MacroAssembler::AllocateTwoByteString(Register result,
Register length,
Register scratch1,
Label* gc_required,
AllocationFlags flags);
- // Undo allocation in new space. The object passed and objects allocated after
- // it will no longer be allocated. The caller must make sure that no pointers
- // are left to the object(s) no longer allocated as they would be invalid when
- // allocation is undone.
- void UndoAllocationInNewSpace(Register object, Register scratch);
-
void AllocateTwoByteString(Register result,
Register length,
Register scratch1,
V(kParseScopeError, "Parse/scope error") \
V(kPossibleDirectCallToEval, "Possible direct call to eval") \
V(kPreconditionsWereNotMet, "Preconditions were not met") \
- V(kPropertyAllocationCountFailed, "Property allocation count failed") \
V(kReceivedInvalidReturnAddress, "Received invalid return address") \
V(kReferenceToAVariableWhichRequiresDynamicLookup, \
"Reference to a variable which requires dynamic lookup") \
V(kUnalignedAllocationInNewSpace, "Unaligned allocation in new space") \
V(kUnalignedCellInWriteBarrier, "Unaligned cell in write barrier") \
V(kUndefinedValueNotLoaded, "Undefined value not loaded") \
- V(kUndoAllocationOfNonAllocatedMemory, \
- "Undo allocation of non allocated memory") \
V(kUnexpectedAllocationTop, "Unexpected allocation top") \
V(kUnexpectedColorFound, "Unexpected color bit pattern found") \
V(kUnexpectedElementsKindInArrayConstructor, \
static const int num_fields = JSRegExp::kInObjectFieldCount;
initial_map->set_inobject_properties(num_fields);
- initial_map->set_pre_allocated_property_fields(num_fields);
initial_map->set_unused_property_fields(0);
initial_map->set_instance_size(initial_map->instance_size() +
num_fields * kPointerSize);
iterator_result_map->AppendDescriptor(&done_descr);
iterator_result_map->set_unused_property_fields(0);
- iterator_result_map->set_pre_allocated_property_fields(
- JSGeneratorObject::kResultPropertyCount);
DCHECK_EQ(JSGeneratorObject::kResultSize,
iterator_result_map->instance_size());
native_context()->set_iterator_result_map(*iterator_result_map);
// @@iterator method is added later.
map->set_function_with_prototype(true);
- map->set_pre_allocated_property_fields(2);
map->set_inobject_properties(2);
native_context()->set_sloppy_arguments_map(*map);
Handle<Map> map = isolate->sloppy_arguments_map();
map = Map::Copy(map, "FastAliasedArguments");
map->set_elements_kind(FAST_SLOPPY_ARGUMENTS_ELEMENTS);
- DCHECK_EQ(2, map->pre_allocated_property_fields());
+ DCHECK_EQ(2, map->inobject_properties());
native_context()->set_fast_aliased_arguments_map(*map);
map = Map::Copy(map, "SlowAliasedArguments");
map->set_elements_kind(SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
- DCHECK_EQ(2, map->pre_allocated_property_fields());
+ DCHECK_EQ(2, map->inobject_properties());
native_context()->set_slow_aliased_arguments_map(*map);
}
DCHECK_EQ(native_context()->object_function()->prototype(),
*isolate->initial_object_prototype());
Map::SetPrototype(map, isolate->initial_object_prototype());
- map->set_pre_allocated_property_fields(1);
map->set_inobject_properties(1);
// Copy constructor from the sloppy arguments boilerplate.
}
initial_map->set_inobject_properties(2);
- initial_map->set_pre_allocated_property_fields(2);
initial_map->set_unused_property_fields(0);
native_context()->set_regexp_result_map(*initial_map);
}
case JS_OBJECT_TYPE: {
Handle<JSObject> object =
- isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED, false);
+ isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED);
slot->value_ = object;
Handle<Object> properties = MaterializeAt(frame_index, value_index);
Handle<Object> elements = MaterializeAt(frame_index, value_index);
Handle<JSObject> Factory::NewJSObjectFromMap(
Handle<Map> map,
PretenureFlag pretenure,
- bool alloc_props,
Handle<AllocationSite> allocation_site) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateJSObjectFromMap(
*map,
pretenure,
- alloc_props,
allocation_site.is_null() ? NULL : *allocation_site),
JSObject);
}
DCHECK(size_difference >= 0);
// Allocate the backing storage for the properties.
- int prop_size = map->InitialPropertiesLength();
- Handle<FixedArray> properties = NewFixedArray(prop_size, TENURED);
+ Handle<FixedArray> properties = empty_fixed_array();
Heap* heap = isolate()->heap();
MaybeHandle<SharedFunctionInfo> shared;
Handle<Map> map = NewMap(JS_GLOBAL_PROXY_TYPE, JSGlobalProxy::kSize);
// Maintain invariant expected from any JSGlobalProxy.
map->set_is_access_check_needed(true);
- CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->AllocateJSObjectFromMap(
- *map, NOT_TENURED, false),
- JSGlobalProxy);
+ CALL_HEAP_FUNCTION(
+ isolate(), isolate()->heap()->AllocateJSObjectFromMap(*map, NOT_TENURED),
+ JSGlobalProxy);
}
DCHECK(map->instance_type() == object->map()->instance_type());
// Allocate the backing storage for the properties.
- int prop_size = map->InitialPropertiesLength();
- Handle<FixedArray> properties = NewFixedArray(prop_size, TENURED);
+ Handle<FixedArray> properties = empty_fixed_array();
// In order to keep heap in consistent state there must be no allocations
// before object re-initialization is finished.
Handle<JSObject> NewJSObjectFromMap(
Handle<Map> map,
PretenureFlag pretenure = NOT_TENURED,
- bool allocate_properties = true,
Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
// JS modules are pretenured.
reinterpret_cast<Map*>(result)
->set_layout_descriptor(LayoutDescriptor::FastPointerLayout());
}
+ reinterpret_cast<Map*>(result)->clear_unused();
reinterpret_cast<Map*>(result)->set_inobject_properties(0);
- reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0);
reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
reinterpret_cast<Map*>(result)->set_bit_field(0);
reinterpret_cast<Map*>(result)->set_bit_field2(0);
map->set_prototype(null_value(), SKIP_WRITE_BARRIER);
map->set_constructor_or_backpointer(null_value(), SKIP_WRITE_BARRIER);
map->set_instance_size(instance_size);
+ map->clear_unused();
map->set_inobject_properties(0);
- map->set_pre_allocated_property_fields(0);
map->set_code_cache(empty_fixed_array(), SKIP_WRITE_BARRIER);
map->set_dependent_code(DependentCode::cast(empty_fixed_array()),
SKIP_WRITE_BARRIER);
AllocationResult Heap::AllocateJSObjectFromMap(
- Map* map, PretenureFlag pretenure, bool allocate_properties,
- AllocationSite* allocation_site) {
+ Map* map, PretenureFlag pretenure, AllocationSite* allocation_site) {
// JSFunctions should be allocated using AllocateFunction to be
// properly initialized.
DCHECK(map->instance_type() != JS_FUNCTION_TYPE);
DCHECK(map->instance_type() != JS_BUILTINS_OBJECT_TYPE);
// Allocate the backing storage for the properties.
- FixedArray* properties;
- if (allocate_properties) {
- int prop_size = map->InitialPropertiesLength();
- DCHECK(prop_size >= 0);
- {
- AllocationResult allocation = AllocateFixedArray(prop_size, pretenure);
- if (!allocation.To(&properties)) return allocation;
- }
- } else {
- properties = empty_fixed_array();
- }
+ FixedArray* properties = empty_fixed_array();
// Allocate the JSObject.
int size = map->instance_size();
// Allocate the object based on the constructors initial map.
AllocationResult allocation = AllocateJSObjectFromMap(
- constructor->initial_map(), pretenure, true, allocation_site);
+ constructor->initial_map(), pretenure, allocation_site);
#ifdef DEBUG
// Make sure result is NOT a global object if valid.
HeapObject* obj;
// points to the site.
MUST_USE_RESULT AllocationResult
AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure = NOT_TENURED,
- bool alloc_props = true,
AllocationSite* allocation_site = NULL);
// Allocates a HeapNumber from value.
// Checks whether allocation using the given constructor can be inlined.
static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
return constructor->has_initial_map() &&
- constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
- constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
- constructor->initial_map()->InitialPropertiesLength() == 0;
+ constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
+ constructor->initial_map()->instance_size() <
+ HAllocate::kMaxInlineSize;
}
DCHECK(constructor->has_initial_map());
Handle<Map> initial_map(constructor->initial_map());
int instance_size = initial_map->instance_size();
- DCHECK(initial_map->InitialPropertiesLength() == 0);
// Allocate an instance of the implicit receiver object.
HValue* size_in_bytes = Add<HConstant>(instance_size);
// the preconditions is not met, the code bails out to the runtime call.
Label rt_call;
if (FLAG_inline_new) {
- Label undo_allocation;
ExternalReference debug_step_in_fp =
ExternalReference::debug_step_in_fp_address(masm->isolate());
__ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
__ j(less, &no_inobject_slack_tracking);
// Allocate object with a slack.
- __ movzx_b(esi,
- FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
+ __ movzx_b(esi, FieldOperand(eax, Map::kInObjectPropertiesOffset));
+ __ movzx_b(eax, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
+ __ sub(esi, eax);
__ lea(esi,
Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
// esi: offset of first field after pre-allocated fields
}
// Add the object tag to make the JSObject real, so that we can continue
- // and jump into the continuation code at any time from now on. Any
- // failures need to undo the allocation, so that the heap is in a
- // consistent state and verifiable.
- // eax: initial map
- // ebx: JSObject
- // edi: start of next object
+ // and jump into the continuation code at any time from now on.
+ // ebx: JSObject (untagged)
__ or_(ebx, Immediate(kHeapObjectTag));
- // Check if a non-empty properties array is needed.
- // Allocate and initialize a FixedArray if it is.
- // eax: initial map
- // ebx: JSObject
- // edi: start of next object
- // Calculate the total number of properties described by the map.
- __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
- __ movzx_b(ecx,
- FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
- __ add(edx, ecx);
- // Calculate unused properties past the end of the in-object properties.
- __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
- __ sub(edx, ecx);
- // Done if no extra properties are to be allocated.
- __ j(zero, &allocated);
- __ Assert(positive, kPropertyAllocationCountFailed);
-
- // Scale the number of elements by pointer size and add the header for
- // FixedArrays to the start of the next object calculation from above.
- // ebx: JSObject
- // edi: start of next object (will be start of FixedArray)
- // edx: number of elements in properties array
- __ Allocate(FixedArray::kHeaderSize,
- times_pointer_size,
- edx,
- REGISTER_VALUE_IS_INT32,
- edi,
- ecx,
- no_reg,
- &undo_allocation,
- RESULT_CONTAINS_TOP);
-
- // Initialize the FixedArray.
- // ebx: JSObject
- // edi: FixedArray
- // edx: number of elements
- // ecx: start of next object
- __ mov(eax, factory->fixed_array_map());
- __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map
- __ SmiTag(edx);
- __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length
-
- // Initialize the fields to undefined.
- // ebx: JSObject
- // edi: FixedArray
- // ecx: start of next object
- __ mov(edx, factory->undefined_value());
- __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
- __ InitializeFieldsWithFiller(eax, ecx, edx);
-
- // Store the initialized FixedArray into the properties field of
- // the JSObject
- // ebx: JSObject
- // edi: FixedArray
- __ or_(edi, Immediate(kHeapObjectTag)); // add the heap tag
- __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
-
-
// Continue with JSObject being successfully allocated
- // ebx: JSObject
+ // ebx: JSObject (tagged)
__ jmp(&allocated);
-
- // Undo the setting of the new top so that the heap is verifiable. For
- // example, the map's unused properties potentially do not match the
- // allocated objects unused properties.
- // ebx: JSObject (previous new top)
- __ bind(&undo_allocation);
- __ UndoAllocationInNewSpace(ebx);
}
// Allocate the new receiver object using the runtime call.
}
-void MacroAssembler::UndoAllocationInNewSpace(Register object) {
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
-
- // Make sure the object has no tag before resetting top.
- and_(object, Immediate(~kHeapObjectTagMask));
-#ifdef DEBUG
- cmp(object, Operand::StaticVariable(new_space_allocation_top));
- Check(below, kUndoAllocationOfNonAllocatedMemory);
-#endif
- mov(Operand::StaticVariable(new_space_allocation_top), object);
-}
-
-
void MacroAssembler::AllocateHeapNumber(Register result,
Register scratch1,
Register scratch2,
Label* gc_required,
AllocationFlags flags);
- // Undo allocation in new space. The object passed and objects allocated after
- // it will no longer be allocated. Make sure that no pointers are left to the
- // object(s) no longer allocated as they would be invalid when allocation is
- // un-done.
- void UndoAllocationInNewSpace(Register object);
-
// Allocate a heap number in new space with undefined value. The
// register scratch2 can be passed as no_reg; the others must be
// valid registers. Returns tagged pointer in result register, or
// Try to allocate the object without transitioning into C code. If any of
// the preconditions is not met, the code bails out to the runtime call.
if (FLAG_inline_new) {
- Label undo_allocation;
ExternalReference debug_step_in_fp =
ExternalReference::debug_step_in_fp_address(isolate);
__ li(a2, Operand(debug_step_in_fp));
Operand(Map::kSlackTrackingCounterEnd));
// Allocate object with a slack.
- __ lbu(a0, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset));
+ __ lbu(a0, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
+ __ lbu(a2, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
+ __ subu(a0, a0, a2);
__ sll(at, a0, kPointerSizeLog2);
__ addu(a0, t5, at);
// a0: offset of first field after pre-allocated fields
}
// Add the object tag to make the JSObject real, so that we can continue
- // and jump into the continuation code at any time from now on. Any
- // failures need to undo the allocation, so that the heap is in a
- // consistent state and verifiable.
+ // and jump into the continuation code at any time from now on.
__ Addu(t4, t4, Operand(kHeapObjectTag));
- // Check if a non-empty properties array is needed. Continue with
- // allocated object if not; allocate and initialize a FixedArray if yes.
- // a1: constructor function
- // t4: JSObject
- // t5: start of next object (not tagged)
- __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
- // The field instance sizes contains both pre-allocated property fields
- // and in-object properties.
- __ lbu(t6, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset));
- __ Addu(a3, a3, Operand(t6));
- __ lbu(t6, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
- __ subu(a3, a3, t6);
-
- // Done if no extra properties are to be allocated.
- __ Branch(&allocated, eq, a3, Operand(zero_reg));
- __ Assert(greater_equal, kPropertyAllocationCountFailed,
- a3, Operand(zero_reg));
-
- // Scale the number of elements by pointer size and add the header for
- // FixedArrays to the start of the next object calculation from above.
- // a1: constructor
- // a3: number of elements in properties array
- // t4: JSObject
- // t5: start of next object
- __ Addu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize));
- __ Allocate(
- a0,
- t5,
- t6,
- a2,
- &undo_allocation,
- static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
-
- // Initialize the FixedArray.
- // a1: constructor
- // a3: number of elements in properties array (untagged)
- // t4: JSObject
- // t5: start of FixedArray (untagged)
- __ LoadRoot(t6, Heap::kFixedArrayMapRootIndex);
- __ mov(a2, t5);
- __ sw(t6, MemOperand(a2, JSObject::kMapOffset));
- __ sll(a0, a3, kSmiTagSize);
- __ sw(a0, MemOperand(a2, FixedArray::kLengthOffset));
- __ Addu(a2, a2, Operand(2 * kPointerSize));
-
- DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
- DCHECK_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
-
- // Initialize the fields to undefined.
- // a1: constructor
- // a2: First element of FixedArray (not tagged)
- // a3: number of elements in properties array
- // t4: JSObject
- // t5: FixedArray (not tagged)
- __ sll(t3, a3, kPointerSizeLog2);
- __ addu(t6, a2, t3); // End of object.
- DCHECK_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
- if (!is_api_function || create_memento) {
- __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
- } else if (FLAG_debug_code) {
- __ LoadRoot(t2, Heap::kUndefinedValueRootIndex);
- __ Assert(eq, kUndefinedValueNotLoaded, t7, Operand(t2));
- }
- __ InitializeFieldsWithFiller(a2, t6, t7);
-
- // Store the initialized FixedArray into the properties field of
- // the JSObject.
- // a1: constructor function
- // t4: JSObject
- // t5: FixedArray (not tagged)
- __ Addu(t5, t5, Operand(kHeapObjectTag)); // Add the heap tag.
- __ sw(t5, FieldMemOperand(t4, JSObject::kPropertiesOffset));
-
// Continue with JSObject being successfully allocated.
- // a1: constructor function
- // a4: JSObject
+ // t4: JSObject
__ jmp(&allocated);
-
- // Undo the setting of the new top so that the heap is verifiable. For
- // example, the map's unused properties potentially do not match the
- // allocated objects unused properties.
- // t4: JSObject (previous new top)
- __ bind(&undo_allocation);
- __ UndoAllocationInNewSpace(t4, t5);
}
// Allocate the new receiver object using the runtime call.
}
-void MacroAssembler::UndoAllocationInNewSpace(Register object,
- Register scratch) {
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
-
- // Make sure the object has no tag before resetting top.
- And(object, object, Operand(~kHeapObjectTagMask));
-#ifdef DEBUG
- // Check that the object un-allocated is below the current top.
- li(scratch, Operand(new_space_allocation_top));
- lw(scratch, MemOperand(scratch));
- Check(less, kUndoAllocationOfNonAllocatedMemory,
- object, Operand(scratch));
-#endif
- // Write the address of the object to un-allocate as the current top.
- li(scratch, Operand(new_space_allocation_top));
- sw(object, MemOperand(scratch));
-}
-
-
void MacroAssembler::AllocateTwoByteString(Register result,
Register length,
Register scratch1,
Label* gc_required,
AllocationFlags flags);
- // Undo allocation in new space. The object passed and objects allocated after
- // it will no longer be allocated. The caller must make sure that no pointers
- // are left to the object(s) no longer allocated as they would be invalid when
- // allocation is undone.
- void UndoAllocationInNewSpace(Register object, Register scratch);
-
-
void AllocateTwoByteString(Register result,
Register length,
Register scratch1,
// Try to allocate the object without transitioning into C code. If any of
// the preconditions is not met, the code bails out to the runtime call.
if (FLAG_inline_new) {
- Label undo_allocation;
ExternalReference debug_step_in_fp =
ExternalReference::debug_step_in_fp_address(isolate);
__ li(a2, Operand(debug_step_in_fp));
// Allocate object with a slack.
__ lwu(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
- __ Ext(a0, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
- kBitsPerByte);
+ __ Ext(a0, a0, Map::kInObjectPropertiesByte * kBitsPerByte,
+ kBitsPerByte);
+ __ lwu(a2, FieldMemOperand(a2, Map::kInstanceAttributesOffset));
+ __ Ext(a2, a2, Map::kUnusedPropertyFieldsByte * kBitsPerByte,
+ kBitsPerByte);
+ __ dsubu(a0, a0, a2);
__ dsll(at, a0, kPointerSizeLog2);
__ daddu(a0, t1, at);
// a0: offset of first field after pre-allocated fields
}
// Add the object tag to make the JSObject real, so that we can continue
- // and jump into the continuation code at any time from now on. Any
- // failures need to undo the allocation, so that the heap is in a
- // consistent state and verifiable.
+ // and jump into the continuation code at any time from now on.
__ Daddu(t0, t0, Operand(kHeapObjectTag));
- // Check if a non-empty properties array is needed. Continue with
- // allocated object if not; allocate and initialize a FixedArray if yes.
- // a1: constructor function
- // t0: JSObject
- // t1: start of next object (not tagged)
- __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
- // The field instance sizes contains both pre-allocated property fields
- // and in-object properties.
- __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
- __ Ext(t2, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
- kBitsPerByte);
- __ Daddu(a3, a3, Operand(t2));
- __ Ext(t2, a0, Map::kInObjectPropertiesByte * kBitsPerByte,
- kBitsPerByte);
- __ dsubu(a3, a3, t2);
-
- // Done if no extra properties are to be allocated.
- __ Branch(&allocated, eq, a3, Operand(zero_reg));
- __ Assert(greater_equal, kPropertyAllocationCountFailed,
- a3, Operand(zero_reg));
-
- // Scale the number of elements by pointer size and add the header for
- // FixedArrays to the start of the next object calculation from above.
- // a1: constructor
- // a3: number of elements in properties array
- // t0: JSObject
- // t1: start of next object
- __ Daddu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize));
- __ Allocate(
- a0,
- t1,
- t2,
- a2,
- &undo_allocation,
- static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
-
- // Initialize the FixedArray.
- // a1: constructor
- // a3: number of elements in properties array (untagged)
- // t0: JSObject
- // t1: start of FixedArray (untagged)
- __ LoadRoot(t2, Heap::kFixedArrayMapRootIndex);
- __ mov(a2, t1);
- __ sd(t2, MemOperand(a2, JSObject::kMapOffset));
- // Tag number of elements.
- __ dsll32(a0, a3, 0);
- __ sd(a0, MemOperand(a2, FixedArray::kLengthOffset));
- __ Daddu(a2, a2, Operand(2 * kPointerSize));
-
- DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
- DCHECK_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
-
- // Initialize the fields to undefined.
- // a1: constructor
- // a2: First element of FixedArray (not tagged)
- // a3: number of elements in properties array
- // t0: JSObject
- // t1: FixedArray (not tagged)
- __ dsll(a7, a3, kPointerSizeLog2);
- __ daddu(t2, a2, a7); // End of object.
- DCHECK_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
- if (!is_api_function || create_memento) {
- __ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
- } else if (FLAG_debug_code) {
- __ LoadRoot(a6, Heap::kUndefinedValueRootIndex);
- __ Assert(eq, kUndefinedValueNotLoaded, t3, Operand(a6));
- }
- __ InitializeFieldsWithFiller(a2, t2, t3);
-
- // Store the initialized FixedArray into the properties field of
- // the JSObject.
- // a1: constructor function
- // t0: JSObject
- // t1: FixedArray (not tagged)
- __ Daddu(t1, t1, Operand(kHeapObjectTag)); // Add the heap tag.
- __ sd(t1, FieldMemOperand(t0, JSObject::kPropertiesOffset));
-
// Continue with JSObject being successfully allocated.
- // a1: constructor function
// a4: JSObject
__ jmp(&allocated);
-
- // Undo the setting of the new top so that the heap is verifiable. For
- // example, the map's unused properties potentially do not match the
- // allocated objects unused properties.
- // t0: JSObject (previous new top)
- __ bind(&undo_allocation);
- __ UndoAllocationInNewSpace(t0, t1);
}
// Allocate the new receiver object using the runtime call.
}
-void MacroAssembler::UndoAllocationInNewSpace(Register object,
- Register scratch) {
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
-
- // Make sure the object has no tag before resetting top.
- And(object, object, Operand(~kHeapObjectTagMask));
-#ifdef DEBUG
- // Check that the object un-allocated is below the current top.
- li(scratch, Operand(new_space_allocation_top));
- ld(scratch, MemOperand(scratch));
- Check(less, kUndoAllocationOfNonAllocatedMemory,
- object, Operand(scratch));
-#endif
- // Write the address of the object to un-allocate as the current top.
- li(scratch, Operand(new_space_allocation_top));
- sd(object, MemOperand(scratch));
-}
-
-
void MacroAssembler::AllocateTwoByteString(Register result,
Register length,
Register scratch1,
Label* gc_required,
AllocationFlags flags);
- // Undo allocation in new space. The object passed and objects allocated after
- // it will no longer be allocated. The caller must make sure that no pointers
- // are left to the object(s) no longer allocated as they would be invalid when
- // allocation is undone.
- void UndoAllocationInNewSpace(Register object, Register scratch);
-
-
void AllocateTwoByteString(Register result,
Register length,
Register scratch1,
MapVerify();
CHECK(is_dictionary_map());
CHECK(instance_descriptors()->IsEmpty());
- CHECK_EQ(0, pre_allocated_property_fields());
CHECK_EQ(0, unused_property_fields());
CHECK_EQ(StaticVisitorBase::GetVisitorId(this), visitor_id());
}
int size = map->instance_size();
int offset = kHeaderSize;
if (filler_value != pre_allocated_value) {
- int pre_allocated = map->pre_allocated_property_fields();
+ int pre_allocated =
+ map->inobject_properties() - map->unused_property_fields();
DCHECK(pre_allocated * kPointerSize + kHeaderSize <= size);
for (int i = 0; i < pre_allocated; i++) {
WRITE_FIELD(this, offset, pre_allocated_value);
}
-int Map::pre_allocated_property_fields() {
- return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
-}
-
-
int Map::GetInObjectPropertyOffset(int index) {
// Adjust for the number of properties stored in the object.
index -= inobject_properties();
}
-void Map::set_pre_allocated_property_fields(int value) {
- DCHECK(0 <= value && value < 256);
- WRITE_BYTE_FIELD(this,
- kPreAllocatedPropertyFieldsOffset,
- static_cast<byte>(value));
-}
+void Map::clear_unused() { WRITE_BYTE_FIELD(this, kUnusedOffset, 0); }
InstanceType Map::instance_type() {
os << " - type: " << TypeToString(instance_type()) << "\n";
os << " - instance size: " << instance_size() << "\n";
os << " - inobject properties: " << inobject_properties() << "\n";
- os << " - elements kind: " << ElementsKindToString(elements_kind());
- os << "\n - pre-allocated property fields: "
- << pre_allocated_property_fields() << "\n";
+ os << " - elements kind: " << ElementsKindToString(elements_kind()) << "\n";
os << " - unused property fields: " << unused_property_fields() << "\n";
if (is_deprecated()) os << " - deprecated_map\n";
if (is_stable()) os << " - stable_map\n";
result->set_inobject_properties(map->inobject_properties());
result->set_unused_property_fields(map->unused_property_fields());
- result->set_pre_allocated_property_fields(
- map->pre_allocated_property_fields());
result->ClearCodeCache(map->GetHeap());
map->NotifyLeafMapLayoutChange();
return result;
inline int instance_size();
inline void set_instance_size(int value);
+ // Only to clear an unused byte, remove once byte is used.
+ inline void clear_unused();
+
// Count of properties allocated in the object.
inline int inobject_properties();
inline void set_inobject_properties(int value);
- // Count of property fields pre-allocated in the object when first allocated.
- inline int pre_allocated_property_fields();
- inline void set_pre_allocated_property_fields(int value);
-
// Instance type.
inline InstanceType instance_type();
inline void set_instance_type(InstanceType value);
int NumberOfDescribedProperties(DescriptorFlag which = OWN_DESCRIPTORS,
PropertyAttributes filter = NONE);
- // Returns the number of slots allocated for the initial properties
- // backing storage for instances of this map.
- int InitialPropertiesLength() {
- return pre_allocated_property_fields() + unused_property_fields() -
- inobject_properties();
- }
-
DECLARE_CAST(Map)
// Code cache operations.
static const int kInObjectPropertiesByte = 1;
static const int kInObjectPropertiesOffset =
kInstanceSizesOffset + kInObjectPropertiesByte;
- static const int kPreAllocatedPropertyFieldsByte = 2;
- static const int kPreAllocatedPropertyFieldsOffset =
- kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
+ // Note there is one byte available for use here.
+ static const int kUnusedByte = 2;
+ static const int kUnusedOffset = kInstanceSizesOffset + kUnusedByte;
static const int kVisitorIdByte = 3;
static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
static const int kInstanceTypeAndBitFieldOffset =
kInstanceAttributesOffset + 0;
static const int kBitField2Offset = kInstanceAttributesOffset + 2;
+ static const int kUnusedPropertyFieldsByte = 3;
static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 3;
STATIC_ASSERT(kInstanceTypeAndBitFieldOffset ==
// Try to allocate the object without transitioning into C code. If any of
// the preconditions is not met, the code bails out to the runtime call.
if (FLAG_inline_new) {
- Label undo_allocation;
ExternalReference debug_step_in_fp =
ExternalReference::debug_step_in_fp_address(isolate);
__ mov(r5, Operand(debug_step_in_fp));
__ blt(&no_inobject_slack_tracking);
// Allocate object with a slack.
- __ lbz(r3, FieldMemOperand(r5, Map::kPreAllocatedPropertyFieldsOffset));
+ __ lbz(r3, FieldMemOperand(r5, Map::kInObjectPropertiesOffset));
+ __ lbz(r5, FieldMemOperand(r5, Map::kUnusedPropertyFieldsOffset));
+ __ sub(r3, r3, r5);
if (FLAG_debug_code) {
__ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2));
__ add(r0, r8, r0);
}
// Add the object tag to make the JSObject real, so that we can continue
- // and jump into the continuation code at any time from now on. Any
- // failures need to undo the allocation, so that the heap is in a
- // consistent state and verifiable.
+ // and jump into the continuation code at any time from now on.
__ addi(r7, r7, Operand(kHeapObjectTag));
- // Check if a non-empty properties array is needed. Continue with
- // allocated object if not; allocate and initialize a FixedArray if yes.
- // r4: constructor function
- // r7: JSObject
- // r8: start of next object (not tagged)
- __ lbz(r6, FieldMemOperand(r5, Map::kUnusedPropertyFieldsOffset));
- // The field instance sizes contains both pre-allocated property fields
- // and in-object properties.
- __ lbz(r0, FieldMemOperand(r5, Map::kPreAllocatedPropertyFieldsOffset));
- __ add(r6, r6, r0);
- __ lbz(r0, FieldMemOperand(r5, Map::kInObjectPropertiesOffset));
- __ sub(r6, r6, r0, LeaveOE, SetRC);
-
- // Done if no extra properties are to be allocated.
- __ beq(&allocated, cr0);
- __ Assert(ge, kPropertyAllocationCountFailed, cr0);
-
- // Scale the number of elements by pointer size and add the header for
- // FixedArrays to the start of the next object calculation from above.
- // r4: constructor
- // r6: number of elements in properties array
- // r7: JSObject
- // r8: start of next object
- __ addi(r3, r6, Operand(FixedArray::kHeaderSize / kPointerSize));
- __ Allocate(
- r3, r8, r9, r5, &undo_allocation,
- static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
-
- // Initialize the FixedArray.
- // r4: constructor
- // r6: number of elements in properties array
- // r7: JSObject
- // r8: FixedArray (not tagged)
- __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
- __ mr(r5, r8);
- DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
- __ StoreP(r9, MemOperand(r5));
- DCHECK_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
- __ SmiTag(r3, r6);
- __ StoreP(r3, MemOperand(r5, kPointerSize));
- __ addi(r5, r5, Operand(2 * kPointerSize));
-
- // Initialize the fields to undefined.
- // r4: constructor function
- // r5: First element of FixedArray (not tagged)
- // r6: number of elements in properties array
- // r7: JSObject
- // r8: FixedArray (not tagged)
- DCHECK_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
- {
- Label done;
- __ cmpi(r6, Operand::Zero());
- __ beq(&done);
- if (!is_api_function || create_memento) {
- __ LoadRoot(r10, Heap::kUndefinedValueRootIndex);
- } else if (FLAG_debug_code) {
- __ LoadRoot(r11, Heap::kUndefinedValueRootIndex);
- __ cmp(r10, r11);
- __ Assert(eq, kUndefinedValueNotLoaded);
- }
- __ InitializeNFieldsWithFiller(r5, r6, r10);
- __ bind(&done);
- }
-
- // Store the initialized FixedArray into the properties field of
- // the JSObject
- // r4: constructor function
- // r7: JSObject
- // r8: FixedArray (not tagged)
- __ addi(r8, r8, Operand(kHeapObjectTag)); // Add the heap tag.
- __ StoreP(r8, FieldMemOperand(r7, JSObject::kPropertiesOffset), r0);
-
// Continue with JSObject being successfully allocated
- // r4: constructor function
// r7: JSObject
__ b(&allocated);
-
- // Undo the setting of the new top so that the heap is verifiable. For
- // example, the map's unused properties potentially do not match the
- // allocated objects unused properties.
- // r7: JSObject (previous new top)
- __ bind(&undo_allocation);
- __ UndoAllocationInNewSpace(r7, r8);
}
// Allocate the new receiver object using the runtime call.
}
-void MacroAssembler::UndoAllocationInNewSpace(Register object,
- Register scratch) {
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
-
- // Make sure the object has no tag before resetting top.
- ClearRightImm(object, object, Operand(kHeapObjectTagSize));
-#ifdef DEBUG
- // Check that the object un-allocated is below the current top.
- mov(scratch, Operand(new_space_allocation_top));
- LoadP(scratch, MemOperand(scratch));
- cmp(object, scratch);
- Check(lt, kUndoAllocationOfNonAllocatedMemory);
-#endif
- // Write the address of the object to un-allocate as the current top.
- mov(scratch, Operand(new_space_allocation_top));
- StoreP(object, MemOperand(scratch));
-}
-
-
void MacroAssembler::AllocateTwoByteString(Register result, Register length,
Register scratch1, Register scratch2,
Register scratch3,
void Allocate(Register object_size, Register result, Register scratch1,
Register scratch2, Label* gc_required, AllocationFlags flags);
- // Undo allocation in new space. The object passed and objects allocated after
- // it will no longer be allocated. The caller must make sure that no pointers
- // are left to the object(s) no longer allocated as they would be invalid when
- // allocation is undone.
- void UndoAllocationInNewSpace(Register object, Register scratch);
-
-
void AllocateTwoByteString(Register result, Register length,
Register scratch1, Register scratch2,
Register scratch3, Label* gc_required);
allocation_site = site;
}
- array = Handle<JSArray>::cast(factory->NewJSObjectFromMap(
- initial_map, NOT_TENURED, true, allocation_site));
+ array = Handle<JSArray>::cast(
+ factory->NewJSObjectFromMap(initial_map, NOT_TENURED, allocation_site));
} else {
array = Handle<JSArray>::cast(factory->NewJSObject(constructor));
Handle<FixedArray> elements = isolate->factory()->NewFixedArray(size);
Handle<Map> regexp_map(isolate->native_context()->regexp_result_map());
Handle<JSObject> object =
- isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED, false);
+ isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED);
Handle<JSArray> array = Handle<JSArray>::cast(object);
array->set_elements(*elements);
array->set_length(Smi::FromInt(size));
// Try to allocate the object without transitioning into C code. If any of
// the preconditions is not met, the code bails out to the runtime call.
if (FLAG_inline_new) {
- Label undo_allocation;
-
ExternalReference debug_step_in_fp =
ExternalReference::debug_step_in_fp_address(masm->isolate());
__ Move(kScratchRegister, debug_step_in_fp);
__ j(less, &no_inobject_slack_tracking);
// Allocate object with a slack.
- __ movzxbp(rsi,
- FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset));
+ __ movzxbp(rsi, FieldOperand(rax, Map::kInObjectPropertiesOffset));
+ __ movzxbp(rax, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset));
+ __ subp(rsi, rax);
__ leap(rsi,
Operand(rbx, rsi, times_pointer_size, JSObject::kHeaderSize));
// rsi: offset of first field after pre-allocated fields
}
// Add the object tag to make the JSObject real, so that we can continue
- // and jump into the continuation code at any time from now on. Any
- // failures need to undo the allocation, so that the heap is in a
- // consistent state and verifiable.
- // rax: initial map
- // rbx: JSObject
- // rdi: start of next object
+ // and jump into the continuation code at any time from now on.
+ // rbx: JSObject (untagged)
__ orp(rbx, Immediate(kHeapObjectTag));
- // Check if a non-empty properties array is needed.
- // Allocate and initialize a FixedArray if it is.
- // rax: initial map
- // rbx: JSObject
- // rdi: start of next object
- // Calculate total properties described map.
- __ movzxbp(rdx, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset));
- __ movzxbp(rcx,
- FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset));
- __ addp(rdx, rcx);
- // Calculate unused properties past the end of the in-object properties.
- __ movzxbp(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset));
- __ subp(rdx, rcx);
- // Done if no extra properties are to be allocated.
- __ j(zero, &allocated);
- __ Assert(positive, kPropertyAllocationCountFailed);
-
- // Scale the number of elements by pointer size and add the header for
- // FixedArrays to the start of the next object calculation from above.
- // rbx: JSObject
- // rdi: start of next object (will be start of FixedArray)
- // rdx: number of elements in properties array
- __ Allocate(FixedArray::kHeaderSize,
- times_pointer_size,
- rdx,
- rdi,
- rax,
- no_reg,
- &undo_allocation,
- RESULT_CONTAINS_TOP);
-
- // Initialize the FixedArray.
- // rbx: JSObject
- // rdi: FixedArray
- // rdx: number of elements
- // rax: start of next object
- __ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex);
- __ movp(Operand(rdi, HeapObject::kMapOffset), rcx); // setup the map
- __ Integer32ToSmi(rdx, rdx);
- __ movp(Operand(rdi, FixedArray::kLengthOffset), rdx); // and length
-
- // Initialize the fields to undefined.
- // rbx: JSObject
- // rdi: FixedArray
- // rax: start of next object
- // rdx: number of elements
- __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
- __ leap(rcx, Operand(rdi, FixedArray::kHeaderSize));
- __ InitializeFieldsWithFiller(rcx, rax, rdx);
-
- // Store the initialized FixedArray into the properties field of
- // the JSObject
- // rbx: JSObject
- // rdi: FixedArray
- __ orp(rdi, Immediate(kHeapObjectTag)); // add the heap tag
- __ movp(FieldOperand(rbx, JSObject::kPropertiesOffset), rdi);
-
-
// Continue with JSObject being successfully allocated
- // rbx: JSObject
+ // rbx: JSObject (tagged)
__ jmp(&allocated);
-
- // Undo the setting of the new top so that the heap is verifiable. For
- // example, the map's unused properties potentially do not match the
- // allocated objects unused properties.
- // rbx: JSObject (previous new top)
- __ bind(&undo_allocation);
- __ UndoAllocationInNewSpace(rbx);
}
// Allocate the new receiver object using the runtime call.
}
-void MacroAssembler::UndoAllocationInNewSpace(Register object) {
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
-
- // Make sure the object has no tag before resetting top.
- andp(object, Immediate(~kHeapObjectTagMask));
- Operand top_operand = ExternalOperand(new_space_allocation_top);
-#ifdef DEBUG
- cmpp(object, top_operand);
- Check(below, kUndoAllocationOfNonAllocatedMemory);
-#endif
- movp(top_operand, object);
-}
-
-
void MacroAssembler::AllocateHeapNumber(Register result,
Register scratch,
Label* gc_required,
Label* gc_required,
AllocationFlags flags);
- // Undo allocation in new space. The object passed and objects allocated after
- // it will no longer be allocated. Make sure that no pointers are left to the
- // object(s) no longer allocated as they would be invalid when allocation is
- // un-done.
- void UndoAllocationInNewSpace(Register object);
-
// Allocate a heap number in new space with undefined value. Returns
// tagged pointer in result register, or jumps to gc_required if new
// space is full.
// the preconditions is not met, the code bails out to the runtime call.
Label rt_call;
if (FLAG_inline_new) {
- Label undo_allocation;
ExternalReference debug_step_in_fp =
ExternalReference::debug_step_in_fp_address(masm->isolate());
__ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
__ j(less, &no_inobject_slack_tracking);
// Allocate object with a slack.
- __ movzx_b(esi,
- FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
+ __ movzx_b(esi, FieldOperand(eax, Map::kInObjectPropertiesOffset));
+ __ movzx_b(eax, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
+ __ sub(esi, eax);
__ lea(esi,
Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
// esi: offset of first field after pre-allocated fields
}
// Add the object tag to make the JSObject real, so that we can continue
- // and jump into the continuation code at any time from now on. Any
- // failures need to undo the allocation, so that the heap is in a
- // consistent state and verifiable.
- // eax: initial map
- // ebx: JSObject
- // edi: start of next object
+ // and jump into the continuation code at any time from now on.
+ // ebx: JSObject (untagged)
__ or_(ebx, Immediate(kHeapObjectTag));
- // Check if a non-empty properties array is needed.
- // Allocate and initialize a FixedArray if it is.
- // eax: initial map
- // ebx: JSObject
- // edi: start of next object
- // Calculate the total number of properties described by the map.
- __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
- __ movzx_b(ecx,
- FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
- __ add(edx, ecx);
- // Calculate unused properties past the end of the in-object properties.
- __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
- __ sub(edx, ecx);
- // Done if no extra properties are to be allocated.
- __ j(zero, &allocated);
- __ Assert(positive, kPropertyAllocationCountFailed);
-
- // Scale the number of elements by pointer size and add the header for
- // FixedArrays to the start of the next object calculation from above.
- // ebx: JSObject
- // edi: start of next object (will be start of FixedArray)
- // edx: number of elements in properties array
- __ Allocate(FixedArray::kHeaderSize,
- times_pointer_size,
- edx,
- REGISTER_VALUE_IS_INT32,
- edi,
- ecx,
- no_reg,
- &undo_allocation,
- RESULT_CONTAINS_TOP);
-
- // Initialize the FixedArray.
- // ebx: JSObject
- // edi: FixedArray
- // edx: number of elements
- // ecx: start of next object
- __ mov(eax, factory->fixed_array_map());
- __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map
- __ SmiTag(edx);
- __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length
-
- // Initialize the fields to undefined.
- // ebx: JSObject
- // edi: FixedArray
- // ecx: start of next object
- __ mov(edx, factory->undefined_value());
- __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
- __ InitializeFieldsWithFiller(eax, ecx, edx);
-
- // Store the initialized FixedArray into the properties field of
- // the JSObject
- // ebx: JSObject
- // edi: FixedArray
- __ or_(edi, Immediate(kHeapObjectTag)); // add the heap tag
- __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
-
-
// Continue with JSObject being successfully allocated
- // ebx: JSObject
+ // ebx: JSObject (tagged)
__ jmp(&allocated);
-
- // Undo the setting of the new top so that the heap is verifiable. For
- // example, the map's unused properties potentially do not match the
- // allocated objects unused properties.
- // ebx: JSObject (previous new top)
- __ bind(&undo_allocation);
- __ UndoAllocationInNewSpace(ebx);
}
// Allocate the new receiver object using the runtime call.
}
-void MacroAssembler::UndoAllocationInNewSpace(Register object) {
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
-
- // Make sure the object has no tag before resetting top.
- and_(object, Immediate(~kHeapObjectTagMask));
-#ifdef DEBUG
- cmp(object, Operand::StaticVariable(new_space_allocation_top));
- Check(below, kUndoAllocationOfNonAllocatedMemory);
-#endif
- mov(Operand::StaticVariable(new_space_allocation_top), object);
-}
-
-
void MacroAssembler::AllocateHeapNumber(Register result,
Register scratch1,
Register scratch2,
Label* gc_required,
AllocationFlags flags);
- // Undo allocation in new space. The object passed and objects allocated after
- // it will no longer be allocated. Make sure that no pointers are left to the
- // object(s) no longer allocated as they would be invalid when allocation is
- // un-done.
- void UndoAllocationInNewSpace(Register object);
-
// Allocate a heap number in new space with undefined value. The
// register scratch2 can be passed as no_reg; the others must be
// valid registers. Returns tagged pointer in result register, or
CHECK_EQ(Page::kObjectStartOffset, page->Offset(temp2->address()));
}
- Handle<JSObject> o = factory->NewJSObjectFromMap(map1, TENURED, false);
+ Handle<JSObject> o = factory->NewJSObjectFromMap(map1, TENURED);
o->set_properties(*factory->empty_fixed_array());
// Ensure that the object allocated where we need it.
INSERT_TRANSITION).ToHandleChecked();
// Create object in new space.
- Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED, false);
+ Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED);
Handle<HeapNumber> heap_number = factory->NewHeapNumber(42.5);
obj->WriteToField(0, *heap_number);
}
// Create object in new space.
- Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED, false);
+ Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED);
Handle<HeapNumber> heap_number = factory->NewHeapNumber(42.5);
obj->WriteToField(0, *heap_number);
INSERT_TRANSITION).ToHandleChecked();
// Create object in new space.
- Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED, false);
+ Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED);
Handle<HeapNumber> heap_number = factory->NewHeapNumber(42.5);
obj->WriteToField(0, *heap_number);
my_map = Map::CopyWithField(my_map, name, HeapType::Any(isolate), NONE,
Representation::Double(),
INSERT_TRANSITION).ToHandleChecked();
- my_map->set_pre_allocated_property_fields(1);
- int n_properties = my_map->InitialPropertiesLength();
- CHECK_GE(n_properties, 0);
int object_size = my_map->instance_size();
Handle<HeapObject> obj_value;
{
AlwaysAllocateScope always_allocate(isolate);
- obj = factory->NewJSObjectFromMap(map, TENURED, false);
+ obj = factory->NewJSObjectFromMap(map, TENURED);
CHECK(old_space->Contains(*obj));
obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS);
Page* ec_page;
{
AlwaysAllocateScope always_allocate(isolate);
- obj = factory->NewJSObjectFromMap(map, TENURED, false);
+ obj = factory->NewJSObjectFromMap(map, TENURED);
CHECK(old_space->Contains(*obj));
// Make sure |obj_value| is placed on an old-space evacuation candidate.