Simplify stack check instruction in Crankshaft.

So far we had two types of stack checks: one used for function entries
and one used at loop back edges which uses a deferred code object to
avoid spilling of registers in the loop.

After refactoring lazy deoptimization the first stack check can also
use deferred code. This change removes the first type of stack check
instruction in Crankshaft and uses a deferred stack check in all
places.
Review URL: http://codereview.chromium.org/8775002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10118 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d9dc9104
...@@ -2202,12 +2202,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { ...@@ -2202,12 +2202,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
if (instr->is_function_entry()) { return AssignEnvironment(AssignPointerMap(new LStackCheck));
return MarkAsCall(new LStackCheck, instr);
} else {
ASSERT(instr->is_backwards_branch());
return AssignEnvironment(AssignPointerMap(new LStackCheck));
}
} }
......
...@@ -4649,38 +4649,22 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) { ...@@ -4649,38 +4649,22 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
LStackCheck* instr_; LStackCheck* instr_;
}; };
ASSERT(instr->HasEnvironment()); DeferredStackCheck* deferred_stack_check =
LEnvironment* env = instr->environment(); new DeferredStackCheck(this, instr);
__ LoadRoot(ip, Heap::kStackLimitRootIndex);
__ cmp(sp, Operand(ip));
__ b(lo, deferred_stack_check->entry());
EnsureSpaceForLazyDeopt();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
// There is no LLazyBailout instruction for stack-checks. We have to // There is no LLazyBailout instruction for stack-checks. We have to
// prepare for lazy deoptimization explicitly here. // prepare for lazy deoptimization explicitly here.
if (instr->hydrogen()->is_function_entry()) { ASSERT(instr->HasEnvironment());
// Perform stack overflow check. LEnvironment* env = instr->environment();
Label done; RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
__ LoadRoot(ip, Heap::kStackLimitRootIndex); // Don't record a deoptimization index for the safepoint here.
__ cmp(sp, Operand(ip)); // This will be done explicitly when emitting call and the safepoint in
__ b(hs, &done); // the deferred code.
StackCheckStub stub;
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
EnsureSpaceForLazyDeopt();
__ bind(&done);
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
} else {
ASSERT(instr->hydrogen()->is_backwards_branch());
// Perform stack overflow check if this goto needs it before jumping.
DeferredStackCheck* deferred_stack_check =
new DeferredStackCheck(this, instr);
__ LoadRoot(ip, Heap::kStackLimitRootIndex);
__ cmp(sp, Operand(ip));
__ b(lo, deferred_stack_check->entry());
EnsureSpaceForLazyDeopt();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
// Don't record a deoptimization index for the safepoint here.
// This will be done explicitly when emitting call and the safepoint in
// the deferred code.
}
} }
......
...@@ -1271,12 +1271,7 @@ class HSimulate: public HInstruction { ...@@ -1271,12 +1271,7 @@ class HSimulate: public HInstruction {
class HStackCheck: public HTemplateInstruction<1> { class HStackCheck: public HTemplateInstruction<1> {
public: public:
enum Type { explicit HStackCheck(HValue* context) {
kFunctionEntry,
kBackwardsBranch
};
HStackCheck(HValue* context, Type type) : type_(type) {
SetOperandAt(0, context); SetOperandAt(0, context);
} }
...@@ -1294,13 +1289,7 @@ class HStackCheck: public HTemplateInstruction<1> { ...@@ -1294,13 +1289,7 @@ class HStackCheck: public HTemplateInstruction<1> {
} }
} }
bool is_function_entry() { return type_ == kFunctionEntry; }
bool is_backwards_branch() { return type_ == kBackwardsBranch; }
DECLARE_CONCRETE_INSTRUCTION(StackCheck) DECLARE_CONCRETE_INSTRUCTION(StackCheck)
private:
Type type_;
}; };
......
...@@ -2333,8 +2333,7 @@ HGraph* HGraphBuilder::CreateGraph() { ...@@ -2333,8 +2333,7 @@ HGraph* HGraphBuilder::CreateGraph() {
AddSimulate(AstNode::kDeclarationsId); AddSimulate(AstNode::kDeclarationsId);
HValue* context = environment()->LookupContext(); HValue* context = environment()->LookupContext();
AddInstruction( AddInstruction(new(zone()) HStackCheck(context));
new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
VisitStatements(info()->function()->body()); VisitStatements(info()->function()->body());
if (HasStackOverflow()) return NULL; if (HasStackOverflow()) return NULL;
...@@ -2922,8 +2921,7 @@ void HGraphBuilder::VisitLoopBody(IterationStatement* stmt, ...@@ -2922,8 +2921,7 @@ void HGraphBuilder::VisitLoopBody(IterationStatement* stmt,
BreakAndContinueScope push(break_info, this); BreakAndContinueScope push(break_info, this);
AddSimulate(stmt->StackCheckId()); AddSimulate(stmt->StackCheckId());
HValue* context = environment()->LookupContext(); HValue* context = environment()->LookupContext();
HStackCheck* stack_check = HStackCheck* stack_check = new(zone()) HStackCheck(context);
new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch);
AddInstruction(stack_check); AddInstruction(stack_check);
ASSERT(loop_entry->IsLoopHeader()); ASSERT(loop_entry->IsLoopHeader());
loop_entry->loop_information()->set_stack_check(stack_check); loop_entry->loop_information()->set_stack_check(stack_check);
......
...@@ -4554,43 +4554,23 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) { ...@@ -4554,43 +4554,23 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
LStackCheck* instr_; LStackCheck* instr_;
}; };
ASSERT(instr->HasEnvironment()); DeferredStackCheck* deferred_stack_check =
LEnvironment* env = instr->environment(); new DeferredStackCheck(this, instr);
ExternalReference stack_limit =
ExternalReference::address_of_stack_limit(isolate());
__ cmp(esp, Operand::StaticVariable(stack_limit));
__ j(below, deferred_stack_check->entry());
EnsureSpaceForLazyDeopt();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
// There is no LLazyBailout instruction for stack-checks. We have to // There is no LLazyBailout instruction for stack-checks. We have to
// prepare for lazy deoptimization explicitly here. // prepare for lazy deoptimization explicitly here.
if (instr->hydrogen()->is_function_entry()) { ASSERT(instr->HasEnvironment());
// Perform stack overflow check. LEnvironment* env = instr->environment();
Label done; RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
ExternalReference stack_limit = // Don't record a deoptimization index for the safepoint here.
ExternalReference::address_of_stack_limit(isolate()); // This will be done explicitly when emitting call and the safepoint in
__ cmp(esp, Operand::StaticVariable(stack_limit)); // the deferred code.
__ j(above_equal, &done, Label::kNear);
ASSERT(instr->context()->IsRegister());
ASSERT(ToRegister(instr->context()).is(esi));
StackCheckStub stub;
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
EnsureSpaceForLazyDeopt();
__ bind(&done);
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
} else {
ASSERT(instr->hydrogen()->is_backwards_branch());
// Perform stack overflow check if this goto needs it before jumping.
DeferredStackCheck* deferred_stack_check =
new DeferredStackCheck(this, instr);
ExternalReference stack_limit =
ExternalReference::address_of_stack_limit(isolate());
__ cmp(esp, Operand::StaticVariable(stack_limit));
__ j(below, deferred_stack_check->entry());
EnsureSpaceForLazyDeopt();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
// Don't record a deoptimization index for the safepoint here.
// This will be done explicitly when emitting call and the safepoint in
// the deferred code.
}
} }
......
...@@ -2328,15 +2328,9 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { ...@@ -2328,15 +2328,9 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
if (instr->is_function_entry()) { LOperand* context = UseAny(instr->context());
LOperand* context = UseFixed(instr->context(), esi); return AssignEnvironment(
return MarkAsCall(new(zone()) LStackCheck(context), instr); AssignPointerMap(new(zone()) LStackCheck(context)));
} else {
ASSERT(instr->is_backwards_branch());
LOperand* context = UseAny(instr->context());
return AssignEnvironment(
AssignPointerMap(new(zone()) LStackCheck(context)));
}
} }
......
...@@ -228,7 +228,6 @@ class LInstruction: public ZoneObject { ...@@ -228,7 +228,6 @@ class LInstruction: public ZoneObject {
LPointerMap* pointer_map() const { return pointer_map_.get(); } LPointerMap* pointer_map() const { return pointer_map_.get(); }
bool HasPointerMap() const { return pointer_map_.is_set(); } bool HasPointerMap() const { return pointer_map_.is_set(); }
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; } void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
HValue* hydrogen_value() const { return hydrogen_value_; } HValue* hydrogen_value() const { return hydrogen_value_; }
......
...@@ -4261,36 +4261,21 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) { ...@@ -4261,36 +4261,21 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
LStackCheck* instr_; LStackCheck* instr_;
}; };
ASSERT(instr->HasEnvironment()); DeferredStackCheck* deferred_stack_check =
LEnvironment* env = instr->environment(); new DeferredStackCheck(this, instr);
__ CompareRoot(rsp, Heap::kStackLimitRootIndex);
__ j(below, deferred_stack_check->entry());
EnsureSpaceForLazyDeopt();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
// There is no LLazyBailout instruction for stack-checks. We have to // There is no LLazyBailout instruction for stack-checks. We have to
// prepare for lazy deoptimization explicitly here. // prepare for lazy deoptimization explicitly here.
if (instr->hydrogen()->is_function_entry()) { ASSERT(instr->HasEnvironment());
// Perform stack overflow check. LEnvironment* env = instr->environment();
Label done; RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
__ CompareRoot(rsp, Heap::kStackLimitRootIndex); // Don't record a deoptimization index for the safepoint here.
__ j(above_equal, &done, Label::kNear); // This will be done explicitly when emitting call and the safepoint in
StackCheckStub stub; // the deferred code.
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
EnsureSpaceForLazyDeopt();
__ bind(&done);
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
} else {
ASSERT(instr->hydrogen()->is_backwards_branch());
// Perform stack overflow check if this goto needs it before jumping.
DeferredStackCheck* deferred_stack_check =
new DeferredStackCheck(this, instr);
__ CompareRoot(rsp, Heap::kStackLimitRootIndex);
__ j(below, deferred_stack_check->entry());
EnsureSpaceForLazyDeopt();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
// Don't record a deoptimization index for the safepoint here.
// This will be done explicitly when emitting call and the safepoint in
// the deferred code.
}
} }
......
...@@ -2203,12 +2203,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { ...@@ -2203,12 +2203,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
if (instr->is_function_entry()) { return AssignEnvironment(AssignPointerMap(new LStackCheck));
return MarkAsCall(new LStackCheck, instr);
} else {
ASSERT(instr->is_backwards_branch());
return AssignEnvironment(AssignPointerMap(new LStackCheck));
}
} }
......
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