Check that environments assigned via AssignEnvironment are actually used.

Removed some temporary marker comments on the way.

R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/218403006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20430 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 923fbafc
...@@ -623,6 +623,8 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, ...@@ -623,6 +623,8 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
!hinstr->HasObservableSideEffects(); !hinstr->HasObservableSideEffects();
if (needs_environment && !instr->HasEnvironment()) { if (needs_environment && !instr->HasEnvironment()) {
instr = AssignEnvironment(instr); instr = AssignEnvironment(instr);
// We can't really figure out if the environment is needed or not.
instr->environment()->set_has_been_used();
} }
return instr; return instr;
...@@ -1895,10 +1897,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ...@@ -1895,10 +1897,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
LOperand* temp2 = FixedTemp(d11); LOperand* temp2 = FixedTemp(d11);
LInstruction* result = LInstruction* result =
DefineSameAsFirst(new(zone()) LTaggedToI(value, temp1, temp2)); DefineSameAsFirst(new(zone()) LTaggedToI(value, temp1, temp2));
if (!val->representation().IsSmi()) { if (!val->representation().IsSmi()) result = AssignEnvironment(result);
// Note: Only deopts in deferred code.
result = AssignEnvironment(result);
}
return result; return result;
} }
} }
...@@ -1993,11 +1992,10 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { ...@@ -1993,11 +1992,10 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
value = UseRegisterAtStart(instr->value()); value = UseRegisterAtStart(instr->value());
if (instr->has_migration_target()) info()->MarkAsDeferredCalling(); if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
} }
LCheckMaps* result = new(zone()) LCheckMaps(value); LInstruction* result = new(zone()) LCheckMaps(value);
if (!instr->CanOmitMapChecks()) { if (!instr->CanOmitMapChecks()) {
// Note: Only deopts in deferred code. result = AssignEnvironment(result);
AssignEnvironment(result); if (instr->has_migration_target()) result = AssignPointerMap(result);
if (instr->has_migration_target()) return AssignPointerMap(result);
} }
return result; return result;
} }
......
...@@ -783,6 +783,7 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, ...@@ -783,6 +783,7 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
Safepoint::DeoptMode mode) { Safepoint::DeoptMode mode) {
environment->set_has_been_used();
if (!environment->HasBeenRegistered()) { if (!environment->HasBeenRegistered()) {
// Physical stack frame layout: // Physical stack frame layout:
// -x ............. -4 0 ..................................... y // -x ............. -4 0 ..................................... y
......
...@@ -515,6 +515,8 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, ...@@ -515,6 +515,8 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
!hinstr->HasObservableSideEffects(); !hinstr->HasObservableSideEffects();
if (needs_environment && !instr->HasEnvironment()) { if (needs_environment && !instr->HasEnvironment()) {
instr = AssignEnvironment(instr); instr = AssignEnvironment(instr);
// We can't really figure out if the environment is needed or not.
instr->environment()->set_has_been_used();
} }
return instr; return instr;
...@@ -1107,10 +1109,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ...@@ -1107,10 +1109,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
LOperand* temp2 = instr->CanTruncateToInt32() ? NULL : FixedTemp(d24); LOperand* temp2 = instr->CanTruncateToInt32() ? NULL : FixedTemp(d24);
LInstruction* result = LInstruction* result =
DefineAsRegister(new(zone()) LTaggedToI(value, temp1, temp2)); DefineAsRegister(new(zone()) LTaggedToI(value, temp1, temp2));
if (!val->representation().IsSmi()) { if (!val->representation().IsSmi()) result = AssignEnvironment(result);
// Note: Only deopts in deferred code.
result = AssignEnvironment(result);
}
return result; return result;
} }
} }
...@@ -1194,9 +1193,8 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { ...@@ -1194,9 +1193,8 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
} }
LInstruction* result = new(zone()) LCheckMaps(value, temp); LInstruction* result = new(zone()) LCheckMaps(value, temp);
if (!instr->CanOmitMapChecks()) { if (!instr->CanOmitMapChecks()) {
// Note: Only deopts in deferred code.
result = AssignEnvironment(result); result = AssignEnvironment(result);
if (instr->has_migration_target()) return AssignPointerMap(result); if (instr->has_migration_target()) result = AssignPointerMap(result);
} }
return result; return result;
} }
...@@ -2432,7 +2430,6 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { ...@@ -2432,7 +2430,6 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
LOperand* temp3 = TempRegister(); LOperand* temp3 = TempRegister();
LInstruction* result = DefineAsRegister( LInstruction* result = DefineAsRegister(
new(zone()) LMathAbsTagged(context, input, temp1, temp2, temp3)); new(zone()) LMathAbsTagged(context, input, temp1, temp2, temp3));
// Note: Only deopts in deferred code.
return AssignEnvironment(AssignPointerMap(result)); return AssignEnvironment(AssignPointerMap(result));
} else { } else {
LOperand* input = UseRegisterAtStart(instr->value()); LOperand* input = UseRegisterAtStart(instr->value());
......
...@@ -376,6 +376,7 @@ int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) { ...@@ -376,6 +376,7 @@ int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) {
void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
Safepoint::DeoptMode mode) { Safepoint::DeoptMode mode) {
environment->set_has_been_used();
if (!environment->HasBeenRegistered()) { if (!environment->HasBeenRegistered()) {
int frame_count = 0; int frame_count = 0;
int jsframe_count = 0; int jsframe_count = 0;
......
...@@ -1051,6 +1051,7 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, ...@@ -1051,6 +1051,7 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
void LCodeGen::RegisterEnvironmentForDeoptimization( void LCodeGen::RegisterEnvironmentForDeoptimization(
LEnvironment* environment, Safepoint::DeoptMode mode) { LEnvironment* environment, Safepoint::DeoptMode mode) {
environment->set_has_been_used();
if (!environment->HasBeenRegistered()) { if (!environment->HasBeenRegistered()) {
// Physical stack frame layout: // Physical stack frame layout:
// -x ............. -4 0 ..................................... y // -x ............. -4 0 ..................................... y
......
...@@ -688,6 +688,8 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, ...@@ -688,6 +688,8 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
!hinstr->HasObservableSideEffects(); !hinstr->HasObservableSideEffects();
if (needs_environment && !instr->HasEnvironment()) { if (needs_environment && !instr->HasEnvironment()) {
instr = AssignEnvironment(instr); instr = AssignEnvironment(instr);
// We can't really figure out if the environment is needed or not.
instr->environment()->set_has_been_used();
} }
return instr; return instr;
...@@ -1934,10 +1936,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ...@@ -1934,10 +1936,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
? FixedTemp(xmm1) : NULL; ? FixedTemp(xmm1) : NULL;
LInstruction* result = LInstruction* result =
DefineSameAsFirst(new(zone()) LTaggedToI(value, xmm_temp)); DefineSameAsFirst(new(zone()) LTaggedToI(value, xmm_temp));
if (!val->representation().IsSmi()) { if (!val->representation().IsSmi()) result = AssignEnvironment(result);
// Note: Only deopts in deferred code.
result = AssignEnvironment(result);
}
return result; return result;
} }
} }
...@@ -2043,11 +2042,10 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { ...@@ -2043,11 +2042,10 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
value = UseRegisterAtStart(instr->value()); value = UseRegisterAtStart(instr->value());
if (instr->has_migration_target()) info()->MarkAsDeferredCalling(); if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
} }
LCheckMaps* result = new(zone()) LCheckMaps(value); LInstruction* result = new(zone()) LCheckMaps(value);
if (!instr->CanOmitMapChecks()) { if (!instr->CanOmitMapChecks()) {
// Note: Only deopts in deferred code. result = AssignEnvironment(result);
AssignEnvironment(result); if (instr->has_migration_target()) result = AssignPointerMap(result);
if (instr->has_migration_target()) return AssignPointerMap(result);
} }
return result; return result;
} }
......
...@@ -122,6 +122,26 @@ bool LCodeGenBase::GenerateBody() { ...@@ -122,6 +122,26 @@ bool LCodeGenBase::GenerateBody() {
} }
void LCodeGenBase::CheckEnvironmentUsage() {
#ifdef DEBUG
bool live_block = true;
for (int i = 0; i < instructions_->length(); i++) {
LInstruction* instr = instructions_->at(i);
if (instr->IsLabel()) live_block = !LLabel::cast(instr)->HasReplacement();
if (live_block &&
instr->hydrogen_value()->block()->IsReachable() &&
instr->HasEnvironment() &&
!instr->environment()->has_been_used()) {
FunctionLiteral* lit = info_->function();
V8_Fatal(__FILE__, __LINE__, "unused environment in %s <@%d,#%d> %s\n",
lit == NULL ? "<UNKNOWN>" : lit->name()->ToCString().get(),
i, instr->hydrogen_value()->id(), instr->Mnemonic());
}
}
#endif
}
void LCodeGenBase::Comment(const char* format, ...) { void LCodeGenBase::Comment(const char* format, ...) {
if (!FLAG_code_comments) return; if (!FLAG_code_comments) return;
char buffer[4 * KB]; char buffer[4 * KB];
......
...@@ -68,6 +68,11 @@ class LCodeGenBase BASE_EMBEDDED { ...@@ -68,6 +68,11 @@ class LCodeGenBase BASE_EMBEDDED {
void RegisterWeakObjectsInOptimizedCode(Handle<Code> code); void RegisterWeakObjectsInOptimizedCode(Handle<Code> code);
// Check that an environment assigned via AssignEnvironment is actually being
// used. Redundant assignments keep things alive longer than necessary, and
// consequently lead to worse code, so it's important to minimize this.
void CheckEnvironmentUsage();
protected: protected:
enum Status { enum Status {
UNUSED, UNUSED,
......
...@@ -432,6 +432,7 @@ Handle<Code> LChunk::Codegen() { ...@@ -432,6 +432,7 @@ Handle<Code> LChunk::Codegen() {
MarkEmptyBlocks(); MarkEmptyBlocks();
if (generator.GenerateCode()) { if (generator.GenerateCode()) {
generator.CheckEnvironmentUsage();
CodeGenerator::MakeCodePrologue(info(), "optimized"); CodeGenerator::MakeCodePrologue(info(), "optimized");
Code::Flags flags = info()->flags(); Code::Flags flags = info()->flags();
Handle<Code> code = Handle<Code> code =
......
...@@ -426,7 +426,8 @@ class LEnvironment V8_FINAL : public ZoneObject { ...@@ -426,7 +426,8 @@ class LEnvironment V8_FINAL : public ZoneObject {
object_mapping_(0, zone), object_mapping_(0, zone),
outer_(outer), outer_(outer),
entry_(entry), entry_(entry),
zone_(zone) { } zone_(zone),
has_been_used_(false) { }
Handle<JSFunction> closure() const { return closure_; } Handle<JSFunction> closure() const { return closure_; }
FrameType frame_type() const { return frame_type_; } FrameType frame_type() const { return frame_type_; }
...@@ -442,6 +443,9 @@ class LEnvironment V8_FINAL : public ZoneObject { ...@@ -442,6 +443,9 @@ class LEnvironment V8_FINAL : public ZoneObject {
HEnterInlined* entry() { return entry_; } HEnterInlined* entry() { return entry_; }
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
bool has_been_used() const { return has_been_used_; }
void set_has_been_used() { has_been_used_ = true; }
void AddValue(LOperand* operand, void AddValue(LOperand* operand,
Representation representation, Representation representation,
bool is_uint32) { bool is_uint32) {
...@@ -541,6 +545,7 @@ class LEnvironment V8_FINAL : public ZoneObject { ...@@ -541,6 +545,7 @@ class LEnvironment V8_FINAL : public ZoneObject {
LEnvironment* outer_; LEnvironment* outer_;
HEnterInlined* entry_; HEnterInlined* entry_;
Zone* zone_; Zone* zone_;
bool has_been_used_;
}; };
......
...@@ -687,6 +687,7 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, ...@@ -687,6 +687,7 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
Safepoint::DeoptMode mode) { Safepoint::DeoptMode mode) {
environment->set_has_been_used();
if (!environment->HasBeenRegistered()) { if (!environment->HasBeenRegistered()) {
// Physical stack frame layout: // Physical stack frame layout:
// -x ............. -4 0 ..................................... y // -x ............. -4 0 ..................................... y
......
...@@ -652,6 +652,8 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, ...@@ -652,6 +652,8 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
!hinstr->HasObservableSideEffects(); !hinstr->HasObservableSideEffects();
if (needs_environment && !instr->HasEnvironment()) { if (needs_environment && !instr->HasEnvironment()) {
instr = AssignEnvironment(instr); instr = AssignEnvironment(instr);
// We can't really figure out if the environment is needed or not.
instr->environment()->set_has_been_used();
} }
return instr; return instr;
...@@ -1857,10 +1859,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ...@@ -1857,10 +1859,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1); LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1);
LInstruction* result = LInstruction* result =
DefineSameAsFirst(new(zone()) LTaggedToI(value, xmm_temp)); DefineSameAsFirst(new(zone()) LTaggedToI(value, xmm_temp));
if (!val->representation().IsSmi()) { if (!val->representation().IsSmi()) result = AssignEnvironment(result);
// Note: Only deopts in deferred code.
result = AssignEnvironment(result);
}
return result; return result;
} }
} }
...@@ -1955,11 +1954,10 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { ...@@ -1955,11 +1954,10 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
value = UseRegisterAtStart(instr->value()); value = UseRegisterAtStart(instr->value());
if (instr->has_migration_target()) info()->MarkAsDeferredCalling(); if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
} }
LCheckMaps* result = new(zone()) LCheckMaps(value); LInstruction* result = new(zone()) LCheckMaps(value);
if (!instr->CanOmitMapChecks()) { if (!instr->CanOmitMapChecks()) {
// Note: Only deopts in deferred code. result = AssignEnvironment(result);
AssignEnvironment(result); if (instr->has_migration_target()) result = AssignPointerMap(result);
if (instr->has_migration_target()) return AssignPointerMap(result);
} }
return result; return result;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment