Update V8 to version 4.1.0.21
This is a cherry-pick of all commits up to and including the
4.1.0.21 cherry-pick in Chromium.
Original commit message:
Version 4.1.0.21 (cherry-pick)
Merged 206e9136bde0f2b5ae8cb77afbb1e7833e5bd412
Unlink pages from the space page list after evacuation.
BUG=430201
LOG=N
R=jkummerow@chromium.org
Review URL: https://codereview.chromium.org/953813002
Cr-Commit-Position: refs/branch-heads/4.1@{#22}
Cr-Branched-From: 2e08d2a7aa9d65d269d8c57aba82eb38a8cb0a18-refs/heads/candidates@{#25353}
---
FPIIM-449
Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
diff --git a/src/ic/x64/handler-compiler-x64.cc b/src/ic/x64/handler-compiler-x64.cc
index c4d6ecf..46fa8cc 100644
--- a/src/ic/x64/handler-compiler-x64.cc
+++ b/src/ic/x64/handler-compiler-x64.cc
@@ -15,6 +15,28 @@
#define __ ACCESS_MASM(masm)
+void PropertyHandlerCompiler::PushVectorAndSlot(Register vector,
+ Register slot) {
+ MacroAssembler* masm = this->masm();
+ __ Push(vector);
+ __ Push(slot);
+}
+
+
+void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) {
+ MacroAssembler* masm = this->masm();
+ __ Pop(slot);
+ __ Pop(vector);
+}
+
+
+void PropertyHandlerCompiler::DiscardVectorAndSlot() {
+ MacroAssembler* masm = this->masm();
+ // Remove vector and slot.
+ __ addp(rsp, Immediate(2 * kPointerSize));
+}
+
+
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
MacroAssembler* masm, Label* miss_label, Register receiver,
Handle<Name> name, Register scratch0, Register scratch1) {
@@ -56,24 +78,16 @@
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
- MacroAssembler* masm, int index, Register prototype, Label* miss) {
- Isolate* isolate = masm->isolate();
- // Get the global function with the given index.
- Handle<JSFunction> function(
- JSFunction::cast(isolate->native_context()->get(index)));
-
- // Check we're still in the same context.
- Register scratch = prototype;
+ MacroAssembler* masm, int index, Register result, Label* miss) {
const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
- __ movp(scratch, Operand(rsi, offset));
- __ movp(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
- __ Cmp(Operand(scratch, Context::SlotOffset(index)), function);
- __ j(not_equal, miss);
-
+ __ movp(result, Operand(rsi, offset));
+ __ movp(result, FieldOperand(result, GlobalObject::kNativeContextOffset));
+ __ movp(result, Operand(result, Context::SlotOffset(index)));
// Load its initial map. The global functions all have initial maps.
- __ Move(prototype, Handle<Map>(function->initial_map()));
+ __ movp(result,
+ FieldOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
// Load the prototype from the initial map.
- __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
+ __ movp(result, FieldOperand(result, Map::kPrototypeOffset));
}
@@ -324,169 +338,60 @@
}
-// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
-// store is successful.
-void NamedStoreHandlerCompiler::GenerateStoreTransition(
- Handle<Map> transition, Handle<Name> name, Register receiver_reg,
- Register storage_reg, Register value_reg, Register scratch1,
- Register scratch2, Register unused, Label* miss_label, Label* slow) {
- int descriptor = transition->LastAdded();
- DescriptorArray* descriptors = transition->instance_descriptors();
- PropertyDetails details = descriptors->GetDetails(descriptor);
- Representation representation = details.representation();
- DCHECK(!representation.IsNone());
-
- if (details.type() == CONSTANT) {
- Handle<Object> constant(descriptors->GetValue(descriptor), isolate());
- __ Cmp(value_reg, constant);
- __ j(not_equal, miss_label);
- } else if (representation.IsSmi()) {
- __ JumpIfNotSmi(value_reg, miss_label);
- } else if (representation.IsHeapObject()) {
- __ JumpIfSmi(value_reg, miss_label);
- HeapType* field_type = descriptors->GetFieldType(descriptor);
- HeapType::Iterator<Map> it = field_type->Classes();
- if (!it.Done()) {
- Label do_store;
- while (true) {
- __ CompareMap(value_reg, it.Current());
- it.Advance();
- if (it.Done()) {
- __ j(not_equal, miss_label);
- break;
- }
- __ j(equal, &do_store, Label::kNear);
- }
- __ bind(&do_store);
- }
- } else if (representation.IsDouble()) {
- Label do_store, heap_number;
- __ AllocateHeapNumber(storage_reg, scratch1, slow, MUTABLE);
-
- __ JumpIfNotSmi(value_reg, &heap_number);
- __ SmiToInteger32(scratch1, value_reg);
- __ Cvtlsi2sd(xmm0, scratch1);
- __ jmp(&do_store);
-
- __ bind(&heap_number);
- __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label,
- DONT_DO_SMI_CHECK);
- __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
-
- __ bind(&do_store);
- __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
- }
-
- // Stub never generated for objects that require access checks.
- DCHECK(!transition->is_access_check_needed());
-
- // Perform map transition for the receiver if necessary.
- if (details.type() == FIELD &&
- Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
- // The properties must be extended before we can store the value.
- // We jump to a runtime call that extends the properties array.
- __ PopReturnAddressTo(scratch1);
- __ Push(receiver_reg);
- __ Push(transition);
- __ Push(value_reg);
- __ PushReturnAddressFrom(scratch1);
- __ TailCallExternalReference(
- ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
- isolate()),
- 3, 1);
- return;
- }
-
- // Update the map of the object.
- __ Move(scratch1, transition);
- __ movp(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1);
-
- // Update the write barrier for the map field.
- __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2,
- kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-
- if (details.type() == CONSTANT) {
- DCHECK(value_reg.is(rax));
- __ ret(0);
- return;
- }
-
- int index = transition->instance_descriptors()->GetFieldIndex(
- transition->LastAdded());
-
- // Adjust for the number of properties stored in the object. Even in the
- // face of a transition we can use the old map here because the size of the
- // object and the number of in-object properties is not going to change.
- index -= transition->inobject_properties();
-
- // TODO(verwaest): Share this code as a code stub.
- SmiCheck smi_check =
- representation.IsTagged() ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
- if (index < 0) {
- // Set the property straight into the object.
- int offset = transition->instance_size() + (index * kPointerSize);
- if (representation.IsDouble()) {
- __ movp(FieldOperand(receiver_reg, offset), storage_reg);
- } else {
- __ movp(FieldOperand(receiver_reg, offset), value_reg);
- }
-
- if (!representation.IsSmi()) {
- // Update the write barrier for the array address.
- if (!representation.IsDouble()) {
- __ movp(storage_reg, value_reg);
- }
- __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1,
- kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check);
- }
- } else {
- // Write to the properties array.
- int offset = index * kPointerSize + FixedArray::kHeaderSize;
- // Get the properties array (optimistically).
- __ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
- if (representation.IsDouble()) {
- __ movp(FieldOperand(scratch1, offset), storage_reg);
- } else {
- __ movp(FieldOperand(scratch1, offset), value_reg);
- }
-
- if (!representation.IsSmi()) {
- // Update the write barrier for the array address.
- if (!representation.IsDouble()) {
- __ movp(storage_reg, value_reg);
- }
- __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg,
- kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check);
- }
- }
-
- // Return the value (register rax).
- DCHECK(value_reg.is(rax));
- __ ret(0);
+void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
+ __ Move(this->name(), name);
}
-void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup,
- Register value_reg,
- Label* miss_label) {
- DCHECK(lookup->representation().IsHeapObject());
- __ JumpIfSmi(value_reg, miss_label);
- HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes();
- Label do_store;
- while (true) {
- __ CompareMap(value_reg, it.Current());
- it.Advance();
- if (it.Done()) {
- __ j(not_equal, miss_label);
- break;
- }
- __ j(equal, &do_store, Label::kNear);
+void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
+ Register scratch,
+ Label* miss) {
+ Handle<WeakCell> cell = Map::WeakCellForMap(transition);
+ Register map_reg = StoreTransitionDescriptor::MapRegister();
+ DCHECK(!map_reg.is(scratch));
+ __ LoadWeakValue(map_reg, cell, miss);
+ if (transition->CanBeDeprecated()) {
+ __ movl(scratch, FieldOperand(map_reg, Map::kBitField3Offset));
+ __ andl(scratch, Immediate(Map::Deprecated::kMask));
+ __ j(not_zero, miss);
}
- __ bind(&do_store);
+}
- StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
- lookup->representation());
- GenerateTailCall(masm(), stub.GetCode());
+
+void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
+ int descriptor,
+ Register value_reg,
+ Register scratch,
+ Label* miss_label) {
+ DCHECK(!map_reg.is(scratch));
+ DCHECK(!map_reg.is(value_reg));
+ DCHECK(!value_reg.is(scratch));
+ __ LoadInstanceDescriptors(map_reg, scratch);
+ __ movp(scratch,
+ FieldOperand(scratch, DescriptorArray::GetValueOffset(descriptor)));
+ __ cmpp(value_reg, scratch);
+ __ j(not_equal, miss_label);
+}
+
+
+void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(HeapType* field_type,
+ Register value_reg,
+ Label* miss_label) {
+ __ JumpIfSmi(value_reg, miss_label);
+ HeapType::Iterator<Map> it = field_type->Classes();
+ if (!it.Done()) {
+ Label do_store;
+ while (true) {
+ __ CompareMap(value_reg, it.Current());
+ it.Advance();
+ if (it.Done()) {
+ __ j(not_equal, miss_label);
+ break;
+ }
+ __ j(equal, &do_store, Label::kNear);
+ }
+ __ bind(&do_store);
+ }
}
@@ -543,18 +448,13 @@
reg = holder_reg; // From now on the object will be in holder_reg.
__ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
} else {
- bool in_new_space = heap()->InNewSpace(*prototype);
- // Two possible reasons for loading the prototype from the map:
- // (1) Can't store references to new space in code.
- // (2) Handler is shared for all receivers with the same prototype
- // map (but not necessarily the same prototype instance).
- bool load_prototype_from_map = in_new_space || depth == 1;
- if (load_prototype_from_map) {
- // Save the map in scratch1 for later.
- __ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
- }
+ Register map_reg = scratch1;
+ __ movp(map_reg, FieldOperand(reg, HeapObject::kMapOffset));
+
if (depth != 1 || check == CHECK_ALL_MAPS) {
- __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
+ Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
+ __ CmpWeakValue(map_reg, cell, scratch2);
+ __ j(not_equal, miss);
}
// Check access rights to the global object. This has to happen after
@@ -571,11 +471,7 @@
}
reg = holder_reg; // From now on the object will be in holder_reg.
- if (load_prototype_from_map) {
- __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
- } else {
- __ Move(reg, prototype);
- }
+ __ movp(reg, FieldOperand(map_reg, Map::kPrototypeOffset));
}
// Go to the next object in the prototype chain.
@@ -587,8 +483,10 @@
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
if (depth != 0 || check == CHECK_ALL_MAPS) {
- // Check the holder map.
- __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
+ __ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
+ __ CmpWeakValue(scratch1, cell, scratch2);
+ __ j(not_equal, miss);
}
// Perform security check for access to the global object.
@@ -608,6 +506,10 @@
Label success;
__ jmp(&success);
__ bind(miss);
+ if (IC::ICUseVector(kind())) {
+ DCHECK(kind() == Code::LOAD_IC);
+ PopVectorAndSlot();
+ }
TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
}
@@ -706,6 +608,7 @@
}
__ Push(holder_reg);
__ Push(this->name());
+ InterceptorVectorSlotPush(holder_reg);
// Invoke an interceptor. Note: map checks from receiver to
// interceptor's holder has been compiled before (see a caller
@@ -723,6 +626,7 @@
__ ret(0);
__ bind(&interceptor_failed);
+ InterceptorVectorSlotPop(holder_reg);
__ Pop(this->name());
__ Pop(holder_reg);
if (must_preserve_receiver_reg) {
@@ -755,7 +659,7 @@
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Register holder_reg = Frontend(receiver(), name);
+ Register holder_reg = Frontend(name);
__ PopReturnAddressTo(scratch1());
__ Push(receiver());
@@ -801,11 +705,15 @@
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
+ if (IC::ICUseVector(kind())) {
+ PushVectorAndSlot();
+ }
FrontendHeader(receiver(), name, &miss);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
- __ Move(result, cell);
+ Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
+ __ LoadWeakValue(result, weak_cell, &miss);
__ movp(result, FieldOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
@@ -819,6 +727,9 @@
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1);
+ if (IC::ICUseVector(kind())) {
+ DiscardVectorAndSlot();
+ }
__ ret(0);
FrontendFooter(name, &miss);