From 09753b4a81f73c0a08f37da33c35b26f405c7214 Mon Sep 17 00:00:00 2001 From: "svenpanne@chromium.org" Date: Tue, 25 Mar 2014 10:17:02 +0000 Subject: [PATCH] Only assign environments when they are actually needed. (ia32 only) R=yangguo@chromium.org Review URL: https://codereview.chromium.org/210783003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20231 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ia32/lithium-ia32.cc | 115 ++++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 47 deletions(-) diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index de3bf9e..696c6be 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -1005,30 +1005,22 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { LInstruction* goto_instr = CheckElideControlInstruction(instr); if (goto_instr != NULL) return goto_instr; - ToBooleanStub::Types expected = instr->expected_input_types(); - - // Tagged values that are not known smis or booleans require a - // deoptimization environment. If the instruction is generic no - // environment is needed since all cases are handled. HValue* value = instr->value(); - Representation rep = value->representation(); + Representation r = value->representation(); HType type = value->type(); - if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) { - return new(zone()) LBranch(UseRegister(value), NULL); - } - - bool needs_temp = expected.NeedsMap() || expected.IsEmpty(); - LOperand* temp = needs_temp ? TempRegister() : NULL; + ToBooleanStub::Types expected = instr->expected_input_types(); + if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); - // The Generic stub does not have a deopt, so we need no environment. - if (expected.IsGeneric()) { - return new(zone()) LBranch(UseRegister(value), temp); + bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() || + type.IsJSArray() || type.IsHeapNumber() || type.IsString(); + LOperand* temp = !easy_case && expected.NeedsMap() ? TempRegister() : NULL; + LInstruction* branch = new(zone()) LBranch(UseRegister(value), temp); + if (!easy_case && + ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) || + !expected.IsGeneric())) { + branch = AssignEnvironment(branch); } - - // We need a temporary register when we have to access the map *or* we have - // no type info yet, in which case we handle all cases (including the ones - // involving maps). - return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp)); + return branch; } @@ -1221,8 +1213,12 @@ LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { LOperand* context = UseAny(instr->context()); // Deferred use. LOperand* input = UseRegisterAtStart(instr->value()); - LMathAbs* result = new(zone()) LMathAbs(context, input); - return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); + LInstruction* result = + DefineSameAsFirst(new(zone()) LMathAbs(context, input)); + Representation r = instr->value()->representation(); + if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); + if (!r.IsDouble()) result = AssignEnvironment(result); + return result; } @@ -1901,8 +1897,12 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { LOperand* value = UseRegister(instr->value()); // Temp register only necessary for minus zero check. LOperand* temp = TempRegister(); - LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); - return AssignEnvironment(DefineAsRegister(res)); + LInstruction* result = DefineAsRegister( + new(zone()) LNumberUntagD(value, temp)); + if (!instr->value()->representation().IsSmi()) { + result = AssignEnvironment(result); + } + return result; } else if (to.IsSmi()) { HValue* val = instr->value(); LOperand* value = UseRegister(val); @@ -1921,8 +1921,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { LOperand* xmm_temp = (CpuFeatures::IsSafeForSnapshot(SSE2) && !truncating) ? FixedTemp(xmm1) : NULL; - LTaggedToI* res = new(zone()) LTaggedToI(UseRegister(val), xmm_temp); - return AssignEnvironment(DefineSameAsFirst(res)); + LInstruction* result = DefineSameAsFirst( + new(zone()) LTaggedToI(UseRegister(val), xmm_temp)); + if (!instr->value()->representation().IsSmi()) { + // Note: Only deopts in deferred code. + result = AssignEnvironment(result); + } + return result; } } } else if (from.IsDouble()) { @@ -1946,8 +1951,10 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { LOperand* value = needs_temp ? UseTempRegister(instr->value()) : UseRegister(instr->value()); LOperand* temp = needs_temp ? TempRegister() : NULL; - return AssignEnvironment( - DefineAsRegister(new(zone()) LDoubleToI(value, temp))); + LInstruction* result = + DefineAsRegister(new(zone()) LDoubleToI(value, temp)); + if (!truncating) result = AssignEnvironment(result); + return result; } } else if (from.IsInteger32()) { info()->MarkAsDeferredCalling(); @@ -1961,11 +1968,11 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { LOperand* temp2 = CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1) : NULL; LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); - return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); + return AssignPointerMap(DefineSameAsFirst(result)); } else { LOperand* temp = TempRegister(); LNumberTagI* result = new(zone()) LNumberTagI(value, temp); - return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); + return AssignPointerMap(DefineSameAsFirst(result)); } } else if (to.IsSmi()) { HValue* val = instr->value(); @@ -2031,6 +2038,7 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { } LCheckMaps* result = new(zone()) LCheckMaps(value); if (!instr->CanOmitMapChecks()) { + // Note: Only deopts in deferred code. AssignEnvironment(result); if (instr->has_migration_target()) return AssignPointerMap(result); } @@ -2139,7 +2147,10 @@ LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { LOperand* context = UseRegisterAtStart(instr->value()); LInstruction* result = DefineAsRegister(new(zone()) LLoadContextSlot(context)); - return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; + if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { + result = AssignEnvironment(result); + } + return result; } @@ -2155,7 +2166,10 @@ LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { temp = NULL; } LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp); - return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; + if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { + result = AssignEnvironment(result); + } + return result; } @@ -2197,11 +2211,11 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { LOperand* key = clobbers_key ? UseTempRegister(instr->key()) : UseRegisterOrConstantAtStart(instr->key()); - LLoadKeyed* result = NULL; + LInstruction* result = NULL; if (!instr->is_typed_elements()) { LOperand* obj = UseRegisterAtStart(instr->elements()); - result = new(zone()) LLoadKeyed(obj, key); + result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key)); } else { ASSERT( (instr->representation().IsInteger32() && @@ -2209,15 +2223,20 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { (instr->representation().IsDouble() && (IsDoubleOrFloatElementsKind(instr->elements_kind())))); LOperand* backing_store = UseRegister(instr->elements()); - result = new(zone()) LLoadKeyed(backing_store, key); + result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key)); } - DefineAsRegister(result); - bool can_deoptimize = instr->RequiresHoleCheck() || - (elements_kind == EXTERNAL_UINT32_ELEMENTS); - // An unsigned int array load might overflow and cause a deopt, make sure it - // has an environment. - return can_deoptimize ? AssignEnvironment(result) : result; + if ((instr->is_external() || instr->is_fixed_typed_array()) ? + // see LCodeGen::DoLoadKeyedExternalArray + ((instr->elements_kind() == EXTERNAL_UINT32_ELEMENTS || + instr->elements_kind() == UINT32_ELEMENTS) && + !instr->CheckFlag(HInstruction::kUint32)) : + // see LCodeGen::DoLoadKeyedFixedDoubleArray and + // LCodeGen::DoLoadKeyedFixedArray + instr->RequiresHoleCheck()) { + result = AssignEnvironment(result); + } + return result; } @@ -2408,12 +2427,14 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { // We need a temporary register for write barrier of the map field. LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() : NULL; - LStoreNamedField* result = + LInstruction* result = new(zone()) LStoreNamedField(obj, val, temp, temp_map); - if (instr->field_representation().IsHeapObject()) { - if (!instr->value()->type().IsHeapObject()) { - return AssignEnvironment(result); - } + if (!instr->access().IsExternalMemory() && + instr->field_representation().IsHeapObject() && + (val->IsConstantOperand() + ? HConstant::cast(instr->value())->HasSmiValue() + : !instr->value()->type().IsHeapObject())) { + result = AssignEnvironment(result); } return result; } @@ -2445,7 +2466,7 @@ LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { LOperand* context = UseAny(instr->context()); LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(context, string, index); - return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); + return AssignPointerMap(DefineAsRegister(result)); } -- 2.7.4