Implement inlined stack-check guards in TurboFan.

R=bmeurer@chromium.org
TEST=cctest/test-run-stackcheck/TerminateAtMethodEntry

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24367 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1bb52d0d
...@@ -204,6 +204,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -204,6 +204,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
AssembleReturn(); AssembleReturn();
DCHECK_EQ(LeaveCC, i.OutputSBit()); DCHECK_EQ(LeaveCC, i.OutputSBit());
break; break;
case kArchStackPointer:
__ mov(i.OutputRegister(), sp);
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
case kArchTruncateDoubleToI: case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputFloat64Register(0)); __ TruncateDoubleToI(i.OutputRegister(), i.InputFloat64Register(0));
DCHECK_EQ(LeaveCC, i.OutputSBit()); DCHECK_EQ(LeaveCC, i.OutputSBit());
......
...@@ -73,6 +73,7 @@ class ArmOperandGenerator : public OperandGenerator { ...@@ -73,6 +73,7 @@ class ArmOperandGenerator : public OperandGenerator {
case kArchJmp: case kArchJmp:
case kArchNop: case kArchNop:
case kArchRet: case kArchRet:
case kArchStackPointer:
case kArchTruncateDoubleToI: case kArchTruncateDoubleToI:
case kArmMul: case kArmMul:
case kArmMla: case kArmMla:
......
...@@ -172,6 +172,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -172,6 +172,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchRet: case kArchRet:
AssembleReturn(); AssembleReturn();
break; break;
case kArchStackPointer:
__ mov(i.OutputRegister(), masm()->StackPointer());
break;
case kArchTruncateDoubleToI: case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
break; break;
......
...@@ -86,8 +86,8 @@ bool AstGraphBuilder::CreateGraph() { ...@@ -86,8 +86,8 @@ bool AstGraphBuilder::CreateGraph() {
// Visit declarations within the function scope. // Visit declarations within the function scope.
VisitDeclarations(scope->declarations()); VisitDeclarations(scope->declarations());
// TODO(mstarzinger): This should do an inlined stack check. // Build a stack-check before the body.
Node* node = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0)); Node* node = BuildStackCheck();
PrepareFrameState(node, BailoutId::FunctionEntry()); PrepareFrameState(node, BailoutId::FunctionEntry());
// Visit statements in the function body. // Visit statements in the function body.
...@@ -2059,6 +2059,24 @@ Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { ...@@ -2059,6 +2059,24 @@ Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
} }
Node* AstGraphBuilder::BuildStackCheck() {
IfBuilder stack_check(this);
Node* limit =
NewNode(jsgraph()->machine()->Load(kMachPtr),
jsgraph()->ExternalConstant(
ExternalReference::address_of_stack_limit(isolate())),
jsgraph()->ZeroConstant());
Node* stack = NewNode(jsgraph()->machine()->LoadStackPointer());
Node* tag = NewNode(jsgraph()->machine()->UintLessThan(), limit, stack);
stack_check.If(tag);
stack_check.Then();
stack_check.Else();
Node* guard = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0));
stack_check.End();
return guard;
}
void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id, void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
OutputFrameStateCombine combine) { OutputFrameStateCombine combine) {
if (OperatorProperties::HasFrameStateInput(node->op())) { if (OperatorProperties::HasFrameStateInput(node->op())) {
......
...@@ -105,6 +105,9 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor { ...@@ -105,6 +105,9 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
// Builders for binary operations. // Builders for binary operations.
Node* BuildBinaryOp(Node* left, Node* right, Token::Value op); Node* BuildBinaryOp(Node* left, Node* right, Token::Value op);
// Builder for stack-check guards.
Node* BuildStackCheck();
#define DECLARE_VISIT(type) virtual void Visit##type(type* node); #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
// Visiting functions for AST nodes make this an AstVisitor. // Visiting functions for AST nodes make this an AstVisitor.
AST_NODE_LIST(DECLARE_VISIT) AST_NODE_LIST(DECLARE_VISIT)
......
...@@ -205,6 +205,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -205,6 +205,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchRet: case kArchRet:
AssembleReturn(); AssembleReturn();
break; break;
case kArchStackPointer:
__ mov(i.OutputRegister(), esp);
break;
case kArchTruncateDoubleToI: case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
break; break;
......
...@@ -33,6 +33,7 @@ namespace compiler { ...@@ -33,6 +33,7 @@ namespace compiler {
V(ArchJmp) \ V(ArchJmp) \
V(ArchNop) \ V(ArchNop) \
V(ArchRet) \ V(ArchRet) \
V(ArchStackPointer) \
V(ArchTruncateDoubleToI) \ V(ArchTruncateDoubleToI) \
TARGET_ARCH_OPCODE_LIST(V) TARGET_ARCH_OPCODE_LIST(V)
......
...@@ -612,6 +612,8 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -612,6 +612,8 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitFloat64LessThan(node); return VisitFloat64LessThan(node);
case IrOpcode::kFloat64LessThanOrEqual: case IrOpcode::kFloat64LessThanOrEqual:
return VisitFloat64LessThanOrEqual(node); return VisitFloat64LessThanOrEqual(node);
case IrOpcode::kLoadStackPointer:
return VisitLoadStackPointer(node);
default: default:
V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d", V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
node->opcode(), node->op()->mnemonic(), node->id()); node->opcode(), node->op()->mnemonic(), node->id());
...@@ -727,6 +729,12 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { ...@@ -727,6 +729,12 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
VisitFloat64Compare(node, &cont); VisitFloat64Compare(node, &cont);
} }
void InstructionSelector::VisitLoadStackPointer(Node* node) {
OperandGenerator g(this);
Emit(kArchStackPointer, g.DefineAsRegister(node));
}
#endif // V8_TURBOFAN_BACKEND #endif // V8_TURBOFAN_BACKEND
// 32 bit targets do not implement the following instructions. // 32 bit targets do not implement the following instructions.
......
...@@ -119,7 +119,8 @@ struct StaticParameterTraits<LoadRepresentation> { ...@@ -119,7 +119,8 @@ struct StaticParameterTraits<LoadRepresentation> {
V(Float64Sqrt, Operator::kNoProperties, 1, 1) \ V(Float64Sqrt, Operator::kNoProperties, 1, 1) \
V(Float64Equal, Operator::kCommutative, 2, 1) \ V(Float64Equal, Operator::kCommutative, 2, 1) \
V(Float64LessThan, Operator::kNoProperties, 2, 1) \ V(Float64LessThan, Operator::kNoProperties, 2, 1) \
V(Float64LessThanOrEqual, Operator::kNoProperties, 2, 1) V(Float64LessThanOrEqual, Operator::kNoProperties, 2, 1) \
V(LoadStackPointer, Operator::kNoProperties, 0, 1)
#define MACHINE_TYPE_LIST(V) \ #define MACHINE_TYPE_LIST(V) \
......
...@@ -144,6 +144,9 @@ class MachineOperatorBuilder FINAL { ...@@ -144,6 +144,9 @@ class MachineOperatorBuilder FINAL {
// store [base + index], value // store [base + index], value
const Operator* Store(StoreRepresentation rep); const Operator* Store(StoreRepresentation rep);
// Access to the machine stack.
const Operator* LoadStackPointer();
// Target machine word-size assumed by this builder. // Target machine word-size assumed by this builder.
bool Is32() const { return word() == kRepWord32; } bool Is32() const { return word() == kRepWord32; }
bool Is64() const { return word() == kRepWord64; } bool Is64() const { return word() == kRepWord64; }
......
...@@ -221,7 +221,8 @@ ...@@ -221,7 +221,8 @@
V(Float64Sqrt) \ V(Float64Sqrt) \
V(Float64Equal) \ V(Float64Equal) \
V(Float64LessThan) \ V(Float64LessThan) \
V(Float64LessThanOrEqual) V(Float64LessThanOrEqual) \
V(LoadStackPointer)
#define VALUE_OP_LIST(V) \ #define VALUE_OP_LIST(V) \
COMMON_OP_LIST(V) \ COMMON_OP_LIST(V) \
......
...@@ -612,7 +612,7 @@ class RepresentationSelector { ...@@ -612,7 +612,7 @@ class RepresentationSelector {
//------------------------------------------------------------------ //------------------------------------------------------------------
case IrOpcode::kLoad: { case IrOpcode::kLoad: {
// TODO(titzer): machine loads/stores need to know BaseTaggedness!? // TODO(titzer): machine loads/stores need to know BaseTaggedness!?
MachineType tBase = kRepTagged; MachineTypeUnion tBase = kRepTagged | kMachPtr;
LoadRepresentation rep = OpParameter<LoadRepresentation>(node); LoadRepresentation rep = OpParameter<LoadRepresentation>(node);
ProcessInput(node, 0, tBase); // pointer or object ProcessInput(node, 0, tBase); // pointer or object
ProcessInput(node, 1, kMachInt32); // index ProcessInput(node, 1, kMachInt32); // index
...@@ -622,7 +622,7 @@ class RepresentationSelector { ...@@ -622,7 +622,7 @@ class RepresentationSelector {
} }
case IrOpcode::kStore: { case IrOpcode::kStore: {
// TODO(titzer): machine loads/stores need to know BaseTaggedness!? // TODO(titzer): machine loads/stores need to know BaseTaggedness!?
MachineType tBase = kRepTagged; MachineTypeUnion tBase = kRepTagged | kMachPtr;
StoreRepresentation rep = OpParameter<StoreRepresentation>(node); StoreRepresentation rep = OpParameter<StoreRepresentation>(node);
ProcessInput(node, 0, tBase); // pointer or object ProcessInput(node, 0, tBase); // pointer or object
ProcessInput(node, 1, kMachInt32); // index ProcessInput(node, 1, kMachInt32); // index
...@@ -732,6 +732,8 @@ class RepresentationSelector { ...@@ -732,6 +732,8 @@ class RepresentationSelector {
case IrOpcode::kFloat64LessThan: case IrOpcode::kFloat64LessThan:
case IrOpcode::kFloat64LessThanOrEqual: case IrOpcode::kFloat64LessThanOrEqual:
return VisitFloat64Cmp(node); return VisitFloat64Cmp(node);
case IrOpcode::kLoadStackPointer:
return VisitLeaf(node, kMachPtr);
default: default:
VisitInputs(node); VisitInputs(node);
break; break;
......
...@@ -233,6 +233,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -233,6 +233,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchRet: case kArchRet:
AssembleReturn(); AssembleReturn();
break; break;
case kArchStackPointer:
__ movq(i.OutputRegister(), rsp);
break;
case kArchTruncateDoubleToI: case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
break; break;
......
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
'compiler/test-run-jsops.cc', 'compiler/test-run-jsops.cc',
'compiler/test-run-machops.cc', 'compiler/test-run-machops.cc',
'compiler/test-run-properties.cc', 'compiler/test-run-properties.cc',
'compiler/test-run-stackcheck.cc',
'compiler/test-run-variables.cc', 'compiler/test-run-variables.cc',
'compiler/test-schedule.cc', 'compiler/test-schedule.cc',
'compiler/test-scheduler.cc', 'compiler/test-scheduler.cc',
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/v8.h"
#include "test/cctest/compiler/function-tester.h"
using namespace v8::internal;
using namespace v8::internal::compiler;
TEST(TerminateAtMethodEntry) {
FunctionTester T("(function(a,b) { return 23; })");
T.CheckCall(T.Val(23));
T.isolate->stack_guard()->RequestTerminateExecution();
T.CheckThrows(T.undefined(), T.undefined());
}
...@@ -201,7 +201,7 @@ const PureOperator kPureOperators[] = { ...@@ -201,7 +201,7 @@ const PureOperator kPureOperators[] = {
PURE(Float64Mul, 2, 1), PURE(Float64Div, 2, 1), PURE(Float64Mul, 2, 1), PURE(Float64Div, 2, 1),
PURE(Float64Mod, 2, 1), PURE(Float64Sqrt, 1, 1), PURE(Float64Mod, 2, 1), PURE(Float64Sqrt, 1, 1),
PURE(Float64Equal, 2, 1), PURE(Float64LessThan, 2, 1), PURE(Float64Equal, 2, 1), PURE(Float64LessThan, 2, 1),
PURE(Float64LessThanOrEqual, 2, 1) PURE(Float64LessThanOrEqual, 2, 1), PURE(LoadStackPointer, 0, 1)
#undef PURE #undef PURE
}; };
......
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