Activate smi-only optimizations for large array literals.
BUG=none TEST=none Review URL: http://codereview.chromium.org/8177005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9553 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
e340163301
commit
3b07abbdbe
@ -1524,12 +1524,10 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
__ RecordWriteField(
|
||||
r1, offset, result_register(), r2, kLRHasBeenSaved, kDontSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||
if (FLAG_smi_only_arrays) {
|
||||
__ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
|
||||
__ CheckFastSmiOnlyElements(r3, r2, &no_map_change);
|
||||
__ push(r6); // Copy of array literal.
|
||||
__ CallRuntime(Runtime::kNonSmiElementStored, 1);
|
||||
}
|
||||
__ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
|
||||
__ CheckFastSmiOnlyElements(r3, r2, &no_map_change);
|
||||
__ push(r6); // Copy of array literal.
|
||||
__ CallRuntime(Runtime::kNonSmiElementStored, 1);
|
||||
__ bind(&no_map_change);
|
||||
|
||||
PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
|
||||
|
@ -1380,10 +1380,8 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
||||
__ Ret();
|
||||
|
||||
__ bind(&non_smi_value);
|
||||
if (FLAG_smi_only_arrays) {
|
||||
// Escape to slow case when writing non-smi into smi-only array.
|
||||
__ CheckFastObjectElements(receiver_map, scratch_value, &slow);
|
||||
}
|
||||
// Escape to slow case when writing non-smi into smi-only array.
|
||||
__ CheckFastObjectElements(receiver_map, scratch_value, &slow);
|
||||
// Fast elements array, store the value to the elements backing store.
|
||||
__ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
||||
__ add(address, address, Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize));
|
||||
|
@ -1618,10 +1618,8 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
||||
|
||||
__ bind(&with_write_barrier);
|
||||
|
||||
if (FLAG_smi_only_arrays) {
|
||||
__ ldr(r6, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
__ CheckFastSmiOnlyElements(r6, r6, &call_builtin);
|
||||
}
|
||||
__ ldr(r6, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
__ CheckFastSmiOnlyElements(r6, r6, &call_builtin);
|
||||
|
||||
// Save new length.
|
||||
__ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
||||
@ -1652,15 +1650,13 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
||||
}
|
||||
|
||||
__ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize));
|
||||
if (FLAG_smi_only_arrays) {
|
||||
// Growing elements that are SMI-only requires special handling in case
|
||||
// the new element is non-Smi. For now, delegate to the builtin.
|
||||
Label no_fast_elements_check;
|
||||
__ JumpIfSmi(r2, &no_fast_elements_check);
|
||||
__ ldr(r7, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(r7, r7, &call_builtin);
|
||||
__ bind(&no_fast_elements_check);
|
||||
}
|
||||
// Growing elements that are SMI-only requires special handling in case
|
||||
// the new element is non-Smi. For now, delegate to the builtin.
|
||||
Label no_fast_elements_check;
|
||||
__ JumpIfSmi(r2, &no_fast_elements_check);
|
||||
__ ldr(r7, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(r7, r7, &call_builtin);
|
||||
__ bind(&no_fast_elements_check);
|
||||
|
||||
Isolate* isolate = masm()->isolate();
|
||||
ExternalReference new_space_allocation_top =
|
||||
|
@ -242,11 +242,9 @@ BUILTIN(ArrayCodeGeneric) {
|
||||
}
|
||||
|
||||
// Set length and elements on the array.
|
||||
if (FLAG_smi_only_arrays) {
|
||||
MaybeObject* maybe_object =
|
||||
array->EnsureCanContainElements(FixedArray::cast(obj));
|
||||
if (maybe_object->IsFailure()) return maybe_object;
|
||||
}
|
||||
MaybeObject* maybe_object =
|
||||
array->EnsureCanContainElements(FixedArray::cast(obj));
|
||||
if (maybe_object->IsFailure()) return maybe_object;
|
||||
|
||||
AssertNoAllocation no_gc;
|
||||
FixedArray* elms = FixedArray::cast(obj);
|
||||
@ -402,15 +400,36 @@ static bool ArrayPrototypeHasNoElements(Heap* heap,
|
||||
|
||||
MUST_USE_RESULT
|
||||
static inline MaybeObject* EnsureJSArrayWithWritableFastElements(
|
||||
Heap* heap, Object* receiver) {
|
||||
Heap* heap, Object* receiver, Arguments* args, int first_added_arg) {
|
||||
if (!receiver->IsJSArray()) return NULL;
|
||||
JSArray* array = JSArray::cast(receiver);
|
||||
HeapObject* elms = array->elements();
|
||||
if (elms->map() == heap->fixed_array_map()) return elms;
|
||||
if (elms->map() == heap->fixed_cow_array_map()) {
|
||||
return array->EnsureWritableFastElements();
|
||||
Map* map = elms->map();
|
||||
if (map == heap->fixed_array_map()) {
|
||||
if (args == NULL || !array->HasFastSmiOnlyElements()) {
|
||||
return elms;
|
||||
}
|
||||
} else if (map == heap->fixed_cow_array_map()) {
|
||||
MaybeObject* maybe_writable_result = array->EnsureWritableFastElements();
|
||||
if (args == NULL || !array->HasFastSmiOnlyElements() ||
|
||||
maybe_writable_result->IsFailure()) {
|
||||
return maybe_writable_result;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
// Need to ensure that the arguments passed in args can be contained in
|
||||
// the array.
|
||||
int args_length = args->length();
|
||||
if (first_added_arg >= args_length) return array->elements();
|
||||
|
||||
MaybeObject* maybe_array = array->EnsureCanContainElements(
|
||||
args,
|
||||
first_added_arg,
|
||||
args_length - first_added_arg);
|
||||
if (maybe_array->IsFailure()) return maybe_array;
|
||||
return array->elements();
|
||||
}
|
||||
|
||||
|
||||
@ -455,7 +474,7 @@ BUILTIN(ArrayPush) {
|
||||
Object* receiver = *args.receiver();
|
||||
Object* elms_obj;
|
||||
{ MaybeObject* maybe_elms_obj =
|
||||
EnsureJSArrayWithWritableFastElements(heap, receiver);
|
||||
EnsureJSArrayWithWritableFastElements(heap, receiver, &args, 1);
|
||||
if (maybe_elms_obj == NULL) {
|
||||
return CallJsBuiltin(isolate, "ArrayPush", args);
|
||||
}
|
||||
@ -493,9 +512,6 @@ BUILTIN(ArrayPush) {
|
||||
elms = new_elms;
|
||||
}
|
||||
|
||||
MaybeObject* maybe = array->EnsureCanContainElements(&args, 1, to_add);
|
||||
if (maybe->IsFailure()) return maybe;
|
||||
|
||||
// Add the provided values.
|
||||
AssertNoAllocation no_gc;
|
||||
WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
|
||||
@ -518,7 +534,7 @@ BUILTIN(ArrayPop) {
|
||||
Object* receiver = *args.receiver();
|
||||
Object* elms_obj;
|
||||
{ MaybeObject* maybe_elms_obj =
|
||||
EnsureJSArrayWithWritableFastElements(heap, receiver);
|
||||
EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0);
|
||||
if (maybe_elms_obj == NULL) return CallJsBuiltin(isolate, "ArrayPop", args);
|
||||
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
|
||||
}
|
||||
@ -551,7 +567,7 @@ BUILTIN(ArrayShift) {
|
||||
Object* receiver = *args.receiver();
|
||||
Object* elms_obj;
|
||||
{ MaybeObject* maybe_elms_obj =
|
||||
EnsureJSArrayWithWritableFastElements(heap, receiver);
|
||||
EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0);
|
||||
if (maybe_elms_obj == NULL)
|
||||
return CallJsBuiltin(isolate, "ArrayShift", args);
|
||||
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
|
||||
@ -593,7 +609,7 @@ BUILTIN(ArrayUnshift) {
|
||||
Object* receiver = *args.receiver();
|
||||
Object* elms_obj;
|
||||
{ MaybeObject* maybe_elms_obj =
|
||||
EnsureJSArrayWithWritableFastElements(heap, receiver);
|
||||
EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0);
|
||||
if (maybe_elms_obj == NULL)
|
||||
return CallJsBuiltin(isolate, "ArrayUnshift", args);
|
||||
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
|
||||
@ -612,11 +628,9 @@ BUILTIN(ArrayUnshift) {
|
||||
// we should never hit this case.
|
||||
ASSERT(to_add <= (Smi::kMaxValue - len));
|
||||
|
||||
if (FLAG_smi_only_arrays) {
|
||||
MaybeObject* maybe_object =
|
||||
array->EnsureCanContainElements(&args, 1, to_add);
|
||||
if (maybe_object->IsFailure()) return maybe_object;
|
||||
}
|
||||
MaybeObject* maybe_object =
|
||||
array->EnsureCanContainElements(&args, 1, to_add);
|
||||
if (maybe_object->IsFailure()) return maybe_object;
|
||||
|
||||
if (new_length > elms->length()) {
|
||||
// New backing storage is needed.
|
||||
@ -745,11 +759,9 @@ BUILTIN(ArraySlice) {
|
||||
}
|
||||
FixedArray* result_elms = FixedArray::cast(result);
|
||||
|
||||
if (FLAG_smi_only_arrays) {
|
||||
MaybeObject* maybe_object =
|
||||
result_array->EnsureCanContainElements(result_elms);
|
||||
if (maybe_object->IsFailure()) return maybe_object;
|
||||
}
|
||||
MaybeObject* maybe_object =
|
||||
result_array->EnsureCanContainElements(result_elms);
|
||||
if (maybe_object->IsFailure()) return maybe_object;
|
||||
|
||||
AssertNoAllocation no_gc;
|
||||
CopyElements(heap, &no_gc, result_elms, 0, elms, k, result_len);
|
||||
@ -768,7 +780,7 @@ BUILTIN(ArraySplice) {
|
||||
Object* receiver = *args.receiver();
|
||||
Object* elms_obj;
|
||||
{ MaybeObject* maybe_elms_obj =
|
||||
EnsureJSArrayWithWritableFastElements(heap, receiver);
|
||||
EnsureJSArrayWithWritableFastElements(heap, receiver, &args, 3);
|
||||
if (maybe_elms_obj == NULL)
|
||||
return CallJsBuiltin(isolate, "ArraySplice", args);
|
||||
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
|
||||
@ -855,12 +867,6 @@ BUILTIN(ArraySplice) {
|
||||
}
|
||||
|
||||
int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
|
||||
|
||||
if (FLAG_smi_only_arrays) {
|
||||
MaybeObject* maybe = array->EnsureCanContainElements(&args, 3, item_count);
|
||||
if (maybe->IsFailure()) return maybe;
|
||||
}
|
||||
|
||||
int new_length = len - actual_delete_count + item_count;
|
||||
|
||||
bool elms_changed = false;
|
||||
@ -997,15 +1003,13 @@ BUILTIN(ArrayConcat) {
|
||||
}
|
||||
FixedArray* result_elms = FixedArray::cast(result);
|
||||
|
||||
if (FLAG_smi_only_arrays) {
|
||||
// Ensure element type transitions happen before copying elements in.
|
||||
if (result_array->HasFastSmiOnlyElements()) {
|
||||
for (int i = 0; i < n_arguments; i++) {
|
||||
JSArray* array = JSArray::cast(args[i]);
|
||||
int len = Smi::cast(array->length())->value();
|
||||
if (len > 0) {
|
||||
FixedArray* elms = FixedArray::cast(array->elements());
|
||||
MaybeObject* maybe_object =
|
||||
result_array->EnsureCanContainElements(elms);
|
||||
if (maybe_object->IsFailure()) return maybe_object;
|
||||
if (!array->HasFastSmiOnlyElements()) {
|
||||
result_array->EnsureCanContainNonSmiElements();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3346,46 +3346,42 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
HValue* key = AddInstruction(
|
||||
new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)),
|
||||
Representation::Integer32()));
|
||||
if (FLAG_smi_only_arrays) {
|
||||
HInstruction* elements_kind =
|
||||
AddInstruction(new(zone()) HElementsKind(literal));
|
||||
HBasicBlock* store_fast = graph()->CreateBasicBlock();
|
||||
// Two empty blocks to satisfy edge split form.
|
||||
HBasicBlock* store_fast_edgesplit1 = graph()->CreateBasicBlock();
|
||||
HBasicBlock* store_fast_edgesplit2 = graph()->CreateBasicBlock();
|
||||
HBasicBlock* store_generic = graph()->CreateBasicBlock();
|
||||
HBasicBlock* check_smi_only_elements = graph()->CreateBasicBlock();
|
||||
HBasicBlock* join = graph()->CreateBasicBlock();
|
||||
HInstruction* elements_kind =
|
||||
AddInstruction(new(zone()) HElementsKind(literal));
|
||||
HBasicBlock* store_fast = graph()->CreateBasicBlock();
|
||||
// Two empty blocks to satisfy edge split form.
|
||||
HBasicBlock* store_fast_edgesplit1 = graph()->CreateBasicBlock();
|
||||
HBasicBlock* store_fast_edgesplit2 = graph()->CreateBasicBlock();
|
||||
HBasicBlock* store_generic = graph()->CreateBasicBlock();
|
||||
HBasicBlock* check_smi_only_elements = graph()->CreateBasicBlock();
|
||||
HBasicBlock* join = graph()->CreateBasicBlock();
|
||||
|
||||
HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(value);
|
||||
smicheck->SetSuccessorAt(0, store_fast_edgesplit1);
|
||||
smicheck->SetSuccessorAt(1, check_smi_only_elements);
|
||||
current_block()->Finish(smicheck);
|
||||
store_fast_edgesplit1->Finish(new(zone()) HGoto(store_fast));
|
||||
HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(value);
|
||||
smicheck->SetSuccessorAt(0, store_fast_edgesplit1);
|
||||
smicheck->SetSuccessorAt(1, check_smi_only_elements);
|
||||
current_block()->Finish(smicheck);
|
||||
store_fast_edgesplit1->Finish(new(zone()) HGoto(store_fast));
|
||||
|
||||
set_current_block(check_smi_only_elements);
|
||||
HCompareConstantEqAndBranch* smi_elements_check =
|
||||
new(zone()) HCompareConstantEqAndBranch(elements_kind,
|
||||
FAST_SMI_ONLY_ELEMENTS,
|
||||
Token::EQ_STRICT);
|
||||
smi_elements_check->SetSuccessorAt(0, store_generic);
|
||||
smi_elements_check->SetSuccessorAt(1, store_fast_edgesplit2);
|
||||
current_block()->Finish(smi_elements_check);
|
||||
store_fast_edgesplit2->Finish(new(zone()) HGoto(store_fast));
|
||||
set_current_block(check_smi_only_elements);
|
||||
HCompareConstantEqAndBranch* smi_elements_check =
|
||||
new(zone()) HCompareConstantEqAndBranch(elements_kind,
|
||||
FAST_SMI_ONLY_ELEMENTS,
|
||||
Token::EQ_STRICT);
|
||||
smi_elements_check->SetSuccessorAt(0, store_generic);
|
||||
smi_elements_check->SetSuccessorAt(1, store_fast_edgesplit2);
|
||||
current_block()->Finish(smi_elements_check);
|
||||
store_fast_edgesplit2->Finish(new(zone()) HGoto(store_fast));
|
||||
|
||||
set_current_block(store_fast);
|
||||
AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
|
||||
store_fast->Goto(join);
|
||||
set_current_block(store_fast);
|
||||
AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
|
||||
store_fast->Goto(join);
|
||||
|
||||
set_current_block(store_generic);
|
||||
AddInstruction(BuildStoreKeyedGeneric(literal, key, value));
|
||||
store_generic->Goto(join);
|
||||
set_current_block(store_generic);
|
||||
AddInstruction(BuildStoreKeyedGeneric(literal, key, value));
|
||||
store_generic->Goto(join);
|
||||
|
||||
join->SetJoinId(expr->id());
|
||||
set_current_block(join);
|
||||
} else {
|
||||
AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
|
||||
}
|
||||
join->SetJoinId(expr->id());
|
||||
set_current_block(join);
|
||||
|
||||
AddSimulate(expr->GetIdForElement(i));
|
||||
}
|
||||
|
@ -1505,12 +1505,10 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
kDontSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET,
|
||||
OMIT_SMI_CHECK);
|
||||
if (FLAG_smi_only_arrays) {
|
||||
__ mov(edi, FieldOperand(ebx, JSObject::kMapOffset));
|
||||
__ CheckFastSmiOnlyElements(edi, &no_map_change, Label::kNear);
|
||||
__ push(Operand(esp, 0));
|
||||
__ CallRuntime(Runtime::kNonSmiElementStored, 1);
|
||||
}
|
||||
__ mov(edi, FieldOperand(ebx, JSObject::kMapOffset));
|
||||
__ CheckFastSmiOnlyElements(edi, &no_map_change, Label::kNear);
|
||||
__ push(Operand(esp, 0));
|
||||
__ CallRuntime(Runtime::kNonSmiElementStored, 1);
|
||||
__ bind(&no_map_change);
|
||||
|
||||
PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
|
||||
|
@ -833,11 +833,9 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&non_smi_value);
|
||||
if (FLAG_smi_only_arrays) {
|
||||
// Escape to slow case when writing non-smi into smi-only array.
|
||||
__ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(edi, &slow, Label::kNear);
|
||||
}
|
||||
// Escape to slow case when writing non-smi into smi-only array.
|
||||
__ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(edi, &slow, Label::kNear);
|
||||
|
||||
// Fast elements array, store the value to the elements backing store.
|
||||
__ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
|
||||
|
@ -1486,10 +1486,8 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
||||
|
||||
__ bind(&with_write_barrier);
|
||||
|
||||
if (FLAG_smi_only_arrays) {
|
||||
__ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(edi, &call_builtin);
|
||||
}
|
||||
__ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(edi, &call_builtin);
|
||||
|
||||
// Save new length.
|
||||
__ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
|
||||
@ -1511,15 +1509,13 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
||||
}
|
||||
|
||||
__ mov(edi, Operand(esp, argc * kPointerSize));
|
||||
if (FLAG_smi_only_arrays) {
|
||||
// Growing elements that are SMI-only requires special handling in case
|
||||
// the new element is non-Smi. For now, delegate to the builtin.
|
||||
Label no_fast_elements_check;
|
||||
__ JumpIfSmi(edi, &no_fast_elements_check);
|
||||
__ mov(esi, FieldOperand(edx, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(esi, &call_builtin, Label::kFar);
|
||||
__ bind(&no_fast_elements_check);
|
||||
}
|
||||
// Growing elements that are SMI-only requires special handling in case
|
||||
// the new element is non-Smi. For now, delegate to the builtin.
|
||||
Label no_fast_elements_check;
|
||||
__ JumpIfSmi(edi, &no_fast_elements_check);
|
||||
__ mov(esi, FieldOperand(edx, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(esi, &call_builtin, Label::kFar);
|
||||
__ bind(&no_fast_elements_check);
|
||||
|
||||
// We could be lucky and the elements array could be at the top of
|
||||
// new-space. In this case we can just grow it in place by moving the
|
||||
|
@ -1306,8 +1306,7 @@ FixedArrayBase* JSObject::elements() {
|
||||
|
||||
void JSObject::ValidateSmiOnlyElements() {
|
||||
#if DEBUG
|
||||
if (FLAG_smi_only_arrays &&
|
||||
map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
|
||||
if (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
|
||||
Heap* heap = GetHeap();
|
||||
// Don't use elements, since integrity checks will fail if there
|
||||
// are filler pointers in the array.
|
||||
@ -1332,8 +1331,7 @@ MaybeObject* JSObject::EnsureCanContainNonSmiElements() {
|
||||
#if DEBUG
|
||||
ValidateSmiOnlyElements();
|
||||
#endif
|
||||
if (FLAG_smi_only_arrays &&
|
||||
(map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS)) {
|
||||
if ((map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS)) {
|
||||
Object* obj;
|
||||
MaybeObject* maybe_obj = GetElementsTransitionMap(FAST_ELEMENTS);
|
||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||
@ -1345,8 +1343,7 @@ MaybeObject* JSObject::EnsureCanContainNonSmiElements() {
|
||||
|
||||
MaybeObject* JSObject::EnsureCanContainElements(Object** objects,
|
||||
uint32_t count) {
|
||||
if (FLAG_smi_only_arrays &&
|
||||
map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
|
||||
if (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
Object* current = *objects++;
|
||||
if (!current->IsSmi() && current != GetHeap()->the_hole_value()) {
|
||||
@ -1359,13 +1356,9 @@ MaybeObject* JSObject::EnsureCanContainElements(Object** objects,
|
||||
|
||||
|
||||
MaybeObject* JSObject::EnsureCanContainElements(FixedArray* elements) {
|
||||
if (FLAG_smi_only_arrays) {
|
||||
Object** objects = reinterpret_cast<Object**>(
|
||||
FIELD_ADDR(elements, elements->OffsetOfElementAt(0)));
|
||||
return EnsureCanContainElements(objects, elements->length());
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
Object** objects = reinterpret_cast<Object**>(
|
||||
FIELD_ADDR(elements, elements->OffsetOfElementAt(0)));
|
||||
return EnsureCanContainElements(objects, elements->length());
|
||||
}
|
||||
|
||||
|
||||
|
@ -7765,7 +7765,6 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(
|
||||
if (elements()->map() != heap->non_strict_arguments_elements_map()) {
|
||||
Object* object;
|
||||
bool has_fast_smi_only_elements =
|
||||
FLAG_smi_only_arrays &&
|
||||
(set_capacity_mode == kAllowSmiOnlyElements) &&
|
||||
(elements()->map()->has_fast_smi_only_elements() ||
|
||||
elements() == heap->empty_fixed_array());
|
||||
|
@ -422,6 +422,9 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
|
||||
}
|
||||
|
||||
|
||||
static const int kSmiOnlyLiteralMinimumLength = 1024;
|
||||
|
||||
|
||||
static Handle<Object> CreateArrayLiteralBoilerplate(
|
||||
Isolate* isolate,
|
||||
Handle<FixedArray> literals,
|
||||
@ -431,6 +434,13 @@ static Handle<Object> CreateArrayLiteralBoilerplate(
|
||||
JSFunction::GlobalContextFromLiterals(*literals)->array_function());
|
||||
Handle<Object> object = isolate->factory()->NewJSObject(constructor);
|
||||
|
||||
if (elements->length() > kSmiOnlyLiteralMinimumLength) {
|
||||
Handle<Map> smi_array_map = isolate->factory()->GetElementsTransitionMap(
|
||||
Handle<JSObject>::cast(object),
|
||||
FAST_SMI_ONLY_ELEMENTS);
|
||||
HeapObject::cast(*object)->set_map(*smi_array_map);
|
||||
}
|
||||
|
||||
const bool is_cow =
|
||||
(elements->map() == isolate->heap()->fixed_cow_array_map());
|
||||
Handle<FixedArray> copied_elements =
|
||||
@ -440,21 +450,18 @@ static Handle<Object> CreateArrayLiteralBoilerplate(
|
||||
bool has_non_smi = false;
|
||||
if (is_cow) {
|
||||
// Copy-on-write arrays must be shallow (and simple).
|
||||
if (FLAG_smi_only_arrays) {
|
||||
for (int i = 0; i < content->length(); i++) {
|
||||
Object* current = content->get(i);
|
||||
ASSERT(!current->IsFixedArray());
|
||||
if (!current->IsSmi() && !current->IsTheHole()) {
|
||||
has_non_smi = true;
|
||||
}
|
||||
for (int i = 0; i < content->length(); i++) {
|
||||
Object* current = content->get(i);
|
||||
ASSERT(!current->IsFixedArray());
|
||||
if (!current->IsSmi() && !current->IsTheHole()) {
|
||||
has_non_smi = true;
|
||||
}
|
||||
} else {
|
||||
#if DEBUG
|
||||
for (int i = 0; i < content->length(); i++) {
|
||||
ASSERT(!content->get(i)->IsFixedArray());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if DEBUG
|
||||
for (int i = 0; i < content->length(); i++) {
|
||||
ASSERT(!content->get(i)->IsFixedArray());
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
for (int i = 0; i < content->length(); i++) {
|
||||
Object* current = content->get(i);
|
||||
@ -479,10 +486,8 @@ static Handle<Object> CreateArrayLiteralBoilerplate(
|
||||
Handle<JSArray> js_object(Handle<JSArray>::cast(object));
|
||||
isolate->factory()->SetContent(js_object, content);
|
||||
|
||||
if (FLAG_smi_only_arrays) {
|
||||
if (has_non_smi && js_object->HasFastSmiOnlyElements()) {
|
||||
isolate->factory()->EnsureCanContainNonSmiElements(js_object);
|
||||
}
|
||||
if (has_non_smi && js_object->HasFastSmiOnlyElements()) {
|
||||
isolate->factory()->EnsureCanContainNonSmiElements(js_object);
|
||||
}
|
||||
|
||||
return object;
|
||||
@ -1661,7 +1666,7 @@ RUNTIME_FUNCTION(MaybeObject*,
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_NonSmiElementStored) {
|
||||
ASSERT(args.length() == 1);
|
||||
CONVERT_ARG_CHECKED(JSObject, object, 0);
|
||||
if (FLAG_smi_only_arrays && object->HasFastSmiOnlyElements()) {
|
||||
if (object->HasFastSmiOnlyElements()) {
|
||||
MaybeObject* maybe_map = object->GetElementsTransitionMap(FAST_ELEMENTS);
|
||||
Map* map;
|
||||
if (!maybe_map->To<Map>(&map)) return maybe_map;
|
||||
|
@ -1473,12 +1473,10 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
kDontSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET,
|
||||
OMIT_SMI_CHECK);
|
||||
if (FLAG_smi_only_arrays) {
|
||||
__ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset));
|
||||
__ CheckFastSmiOnlyElements(rdi, &no_map_change, Label::kNear);
|
||||
__ push(r8);
|
||||
__ CallRuntime(Runtime::kNonSmiElementStored, 1);
|
||||
}
|
||||
__ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset));
|
||||
__ CheckFastSmiOnlyElements(rdi, &no_map_change, Label::kNear);
|
||||
__ push(r8);
|
||||
__ CallRuntime(Runtime::kNonSmiElementStored, 1);
|
||||
__ bind(&no_map_change);
|
||||
|
||||
PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
|
||||
|
@ -709,11 +709,9 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&non_smi_value);
|
||||
if (FLAG_smi_only_arrays) {
|
||||
// Writing a non-smi, check whether array allows non-smi elements.
|
||||
// r9: receiver's map
|
||||
__ CheckFastObjectElements(r9, &slow, Label::kNear);
|
||||
}
|
||||
// Writing a non-smi, check whether array allows non-smi elements.
|
||||
// r9: receiver's map
|
||||
__ CheckFastObjectElements(r9, &slow, Label::kNear);
|
||||
__ lea(rcx,
|
||||
FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize));
|
||||
__ movq(Operand(rcx, 0), rax);
|
||||
|
@ -1460,10 +1460,8 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
||||
|
||||
__ bind(&with_write_barrier);
|
||||
|
||||
if (FLAG_smi_only_arrays) {
|
||||
__ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(rdi, &call_builtin);
|
||||
}
|
||||
__ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(rdi, &call_builtin);
|
||||
|
||||
// Save new length.
|
||||
__ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
|
||||
@ -1486,15 +1484,13 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
||||
}
|
||||
|
||||
__ movq(rdi, Operand(rsp, argc * kPointerSize));
|
||||
if (FLAG_smi_only_arrays) {
|
||||
// Growing elements that are SMI-only requires special handling in case
|
||||
// the new element is non-Smi. For now, delegate to the builtin.
|
||||
Label no_fast_elements_check;
|
||||
__ JumpIfSmi(rdi, &no_fast_elements_check);
|
||||
__ movq(rsi, FieldOperand(rdx, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(rsi, &call_builtin, Label::kFar);
|
||||
__ bind(&no_fast_elements_check);
|
||||
}
|
||||
// Growing elements that are SMI-only requires special handling in case
|
||||
// the new element is non-Smi. For now, delegate to the builtin.
|
||||
Label no_fast_elements_check;
|
||||
__ JumpIfSmi(rdi, &no_fast_elements_check);
|
||||
__ movq(rsi, FieldOperand(rdx, HeapObject::kMapOffset));
|
||||
__ CheckFastObjectElements(rsi, &call_builtin, Label::kFar);
|
||||
__ bind(&no_fast_elements_check);
|
||||
|
||||
ExternalReference new_space_allocation_top =
|
||||
ExternalReference::new_space_allocation_top_address(isolate());
|
||||
|
Loading…
Reference in New Issue
Block a user