Chromium Code Reviews| Index: src/ic/arm/handler-compiler-arm.cc |
| diff --git a/src/ic/arm/handler-compiler-arm.cc b/src/ic/arm/handler-compiler-arm.cc |
| index 7f857ca5d965871bf9c66ef1c571556b594957bd..aa6c14235fb9432c4c414a404949973fcef148b0 100644 |
| --- a/src/ic/arm/handler-compiler-arm.cc |
| +++ b/src/ic/arm/handler-compiler-arm.cc |
| @@ -411,8 +411,8 @@ void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(HeapType* field_type, |
| Register PropertyHandlerCompiler::CheckPrototypes( |
| Register object_reg, Register holder_reg, Register scratch1, |
| - Register scratch2, Handle<Name> name, Label* miss, |
| - PrototypeCheckType check) { |
| + Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, |
| + ReturnHolder return_what) { |
| Handle<Map> receiver_map = map(); |
| // Make sure there's no overlap between holder and object registers. |
| @@ -420,6 +420,29 @@ Register PropertyHandlerCompiler::CheckPrototypes( |
| DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && |
| !scratch2.is(scratch1)); |
| + if (FLAG_eliminate_prototype_chain_checks) { |
| + Handle<Cell> validity_cell = |
| + Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
| + if (!validity_cell.is_null()) { |
| + DCHECK(validity_cell->value() == Smi::FromInt(Map::kPrototypeChainValid)); |
|
Toon Verwaest
2015/04/07 09:28:37
DCHECK_EQ
Jakob Kummerow
2015/04/14 09:41:57
Done.
|
| + __ mov(scratch1, Operand(validity_cell)); |
| + __ ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); |
| + __ cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid))); |
| + __ b(ne, miss); |
| + } |
| + |
| + // The prototype chain of primitives (and their JSValue wrappers) depends |
| + // on the native context, which can't be guarded by validity cells. |
| + // |object_reg| holds the native context specific prototype in this case; |
| + // we need to check its map. |
| + if (check == CHECK_ALL_MAPS) { |
| + __ ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
|
Toon Verwaest
2015/04/07 09:28:38
I think you just want to rewrite this code (and it
Jakob Kummerow
2015/04/14 09:41:57
Acknowledged.
|
| + Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| + __ CmpWeakValue(scratch1, cell, scratch2); |
| + __ b(ne, miss); |
| + } |
| + } |
| + |
| // Keep track of the current object in register reg. |
| Register reg = object_reg; |
| int depth = 0; |
| @@ -464,30 +487,36 @@ Register PropertyHandlerCompiler::CheckPrototypes( |
| current->property_dictionary()->FindEntry(name) == |
| NameDictionary::kNotFound); |
| + if (FLAG_eliminate_prototype_chain_checks && depth > 1) { |
| + // TODO(jkummerow): Cache and re-use weak cell. |
| + __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
|
Toon Verwaest
2015/04/07 09:28:37
In the (near) future we should just drop support f
Jakob Kummerow
2015/04/14 09:41:57
Acknowledged.
|
| + } |
| GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
| scratch2); |
| - |
| - __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| - reg = holder_reg; // From now on the object will be in holder_reg. |
| - __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
| + if (!FLAG_eliminate_prototype_chain_checks) { |
| + __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| + __ ldr(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
| + } |
| } else { |
| Register map_reg = scratch1; |
| - __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| - |
| + if (!FLAG_eliminate_prototype_chain_checks) { |
| + __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| + } |
| if (current_map->IsJSGlobalObjectMap()) { |
| GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
| name, scratch2, miss); |
| - } else if (depth != 1 || check == CHECK_ALL_MAPS) { |
| + } else if (!FLAG_eliminate_prototype_chain_checks && |
| + (depth != 1 || check == CHECK_ALL_MAPS)) { |
| Handle<WeakCell> cell = Map::WeakCellForMap(current_map); |
| __ CmpWeakValue(map_reg, cell, scratch2); |
| __ b(ne, miss); |
| } |
| - |
| - reg = holder_reg; // From now on the object will be in holder_reg. |
| - |
| - __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
| + if (!FLAG_eliminate_prototype_chain_checks) { |
| + __ ldr(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
| + } |
| } |
| + reg = holder_reg; // From now on the object will be in holder_reg. |
| // Go to the next object in the prototype chain. |
| current = prototype; |
| current_map = handle(current->map()); |
| @@ -498,7 +527,8 @@ Register PropertyHandlerCompiler::CheckPrototypes( |
| // Log the check depth. |
| LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| - if (depth != 0 || check == CHECK_ALL_MAPS) { |
| + if (!FLAG_eliminate_prototype_chain_checks && |
| + (depth != 0 || check == CHECK_ALL_MAPS)) { |
| // Check the holder map. |
| __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| Handle<WeakCell> cell = Map::WeakCellForMap(current_map); |
| @@ -506,8 +536,13 @@ Register PropertyHandlerCompiler::CheckPrototypes( |
| __ b(ne, miss); |
| } |
| + bool return_holder = return_what == RETURN_HOLDER; |
| + if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) { |
| + __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
| + } |
| + |
| // Return the register containing the holder. |
| - return reg; |
| + return return_holder ? reg : no_reg; |
| } |
| @@ -722,7 +757,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
| if (IC::ICUseVector(kind())) { |
| PushVectorAndSlot(); |
| } |
| - FrontendHeader(receiver(), name, &miss); |
| + FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); |
| // Get the value from the cell. |
| Register result = StoreDescriptor::ValueRegister(); |