Reviewers: Benedikt Meurer,
Description:
Implement inlined stack-check guards in TurboFan.
[email protected]
TEST=cctest/test-run-stackcheck/TerminateAtMethodEntry
Please review this at https://codereview.chromium.org/621833003/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files (+77, -7 lines):
M src/compiler/arm/code-generator-arm.cc
M src/compiler/arm/instruction-selector-arm.cc
M src/compiler/arm64/code-generator-arm64.cc
M src/compiler/ast-graph-builder.h
M src/compiler/ast-graph-builder.cc
M src/compiler/ia32/code-generator-ia32.cc
M src/compiler/instruction-codes.h
M src/compiler/instruction-selector.cc
M src/compiler/machine-operator.h
M src/compiler/machine-operator.cc
M src/compiler/opcodes.h
M src/compiler/simplified-lowering.cc
M src/compiler/x64/code-generator-x64.cc
M test/cctest/cctest.gyp
A test/cctest/compiler/test-run-stackcheck.cc
M test/unittests/compiler/machine-operator-unittest.cc
Index: src/compiler/arm/code-generator-arm.cc
diff --git a/src/compiler/arm/code-generator-arm.cc
b/src/compiler/arm/code-generator-arm.cc
index
fabcfdcdc5f769ad7eafa59e07f6b6c0a289f2bd..f278326cf7bbd52648a850aba271c11361b4e5cc
100644
--- a/src/compiler/arm/code-generator-arm.cc
+++ b/src/compiler/arm/code-generator-arm.cc
@@ -204,6 +204,10 @@ void
CodeGenerator::AssembleArchInstruction(Instruction* instr) {
AssembleReturn();
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
+ case kArchStackPointer:
+ __ mov(i.OutputRegister(), sp);
+ DCHECK_EQ(LeaveCC, i.OutputSBit());
+ break;
case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputFloat64Register(0));
DCHECK_EQ(LeaveCC, i.OutputSBit());
Index: src/compiler/arm/instruction-selector-arm.cc
diff --git a/src/compiler/arm/instruction-selector-arm.cc
b/src/compiler/arm/instruction-selector-arm.cc
index
e83d1e54afda27035f8590d2e63f5f1b8da4d471..c3efad52fd9679236c1b31c58dcf90e27f269792
100644
--- a/src/compiler/arm/instruction-selector-arm.cc
+++ b/src/compiler/arm/instruction-selector-arm.cc
@@ -73,6 +73,7 @@ class ArmOperandGenerator : public OperandGenerator {
case kArchJmp:
case kArchNop:
case kArchRet:
+ case kArchStackPointer:
case kArchTruncateDoubleToI:
case kArmMul:
case kArmMla:
Index: src/compiler/arm64/code-generator-arm64.cc
diff --git a/src/compiler/arm64/code-generator-arm64.cc
b/src/compiler/arm64/code-generator-arm64.cc
index
a56de204b7163776172db42b9b1ace442001c59a..c041e15366db11a50b7b98b98fc4aeed27795f66
100644
--- a/src/compiler/arm64/code-generator-arm64.cc
+++ b/src/compiler/arm64/code-generator-arm64.cc
@@ -172,6 +172,9 @@ void
CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchRet:
AssembleReturn();
break;
+ case kArchStackPointer:
+ __ mov(i.OutputRegister(), masm()->StackPointer());
+ break;
case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
break;
Index: src/compiler/ast-graph-builder.cc
diff --git a/src/compiler/ast-graph-builder.cc
b/src/compiler/ast-graph-builder.cc
index
d33b05ac18fcd74b2ffe485b6bdc120659e18e95..570a220e7ddeeff428646d720de48afce7774623
100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -86,8 +86,8 @@ bool AstGraphBuilder::CreateGraph() {
// Visit declarations within the function scope.
VisitDeclarations(scope->declarations());
- // TODO(mstarzinger): This should do an inlined stack check.
- Node* node = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0));
+ // Build a stack-check before the body.
+ Node* node = BuildStackCheck();
PrepareFrameState(node, BailoutId::FunctionEntry());
// Visit statements in the function body.
@@ -2060,6 +2060,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,
OutputFrameStateCombine combine) {
if (OperatorProperties::HasFrameStateInput(node->op())) {
Index: src/compiler/ast-graph-builder.h
diff --git a/src/compiler/ast-graph-builder.h
b/src/compiler/ast-graph-builder.h
index
feded98b4e9b0f20a0b87bdc08b3bb0703848d64..967b24bda13d32f33101068e2a2429fdd775b89c
100644
--- a/src/compiler/ast-graph-builder.h
+++ b/src/compiler/ast-graph-builder.h
@@ -105,6 +105,9 @@ class AstGraphBuilder : public StructuredGraphBuilder,
public AstVisitor {
// Builders for binary operations.
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);
// Visiting functions for AST nodes make this an AstVisitor.
AST_NODE_LIST(DECLARE_VISIT)
Index: src/compiler/ia32/code-generator-ia32.cc
diff --git a/src/compiler/ia32/code-generator-ia32.cc
b/src/compiler/ia32/code-generator-ia32.cc
index
4bb75006640969a48f5fab52f9856e5290848b6e..2b51b6fb92dc8cb8960b3c6f81fd7e360dc1c27c
100644
--- a/src/compiler/ia32/code-generator-ia32.cc
+++ b/src/compiler/ia32/code-generator-ia32.cc
@@ -205,6 +205,9 @@ void
CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchRet:
AssembleReturn();
break;
+ case kArchStackPointer:
+ __ mov(i.OutputRegister(), esp);
+ break;
case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
break;
Index: src/compiler/instruction-codes.h
diff --git a/src/compiler/instruction-codes.h
b/src/compiler/instruction-codes.h
index
0abed6c32181217e7d636d6dcee67b040297fce2..fd7c53078f9bb2bed8f836cc916ebb6a6063cab0
100644
--- a/src/compiler/instruction-codes.h
+++ b/src/compiler/instruction-codes.h
@@ -33,6 +33,7 @@ namespace compiler {
V(ArchJmp) \
V(ArchNop) \
V(ArchRet) \
+ V(ArchStackPointer) \
V(ArchTruncateDoubleToI) \
TARGET_ARCH_OPCODE_LIST(V)
Index: src/compiler/instruction-selector.cc
diff --git a/src/compiler/instruction-selector.cc
b/src/compiler/instruction-selector.cc
index
d0be3fecd113852c39879086d76a2fcbe78c48ab..09a8e018eb20a309e93bce003b0cd8ddfaf5a2d6
100644
--- a/src/compiler/instruction-selector.cc
+++ b/src/compiler/instruction-selector.cc
@@ -612,6 +612,8 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitFloat64LessThan(node);
case IrOpcode::kFloat64LessThanOrEqual:
return VisitFloat64LessThanOrEqual(node);
+ case IrOpcode::kLoadStackPointer:
+ return VisitLoadStackPointer(node);
default:
V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
node->opcode(), node->op()->mnemonic(), node->id());
@@ -727,6 +729,12 @@ void
InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
VisitFloat64Compare(node, &cont);
}
+
+void InstructionSelector::VisitLoadStackPointer(Node* node) {
+ OperandGenerator g(this);
+ Emit(kArchStackPointer, g.DefineAsRegister(node));
+}
+
#endif // V8_TURBOFAN_BACKEND
// 32 bit targets do not implement the following instructions.
Index: src/compiler/machine-operator.cc
diff --git a/src/compiler/machine-operator.cc
b/src/compiler/machine-operator.cc
index
35e0e5419a2d7840458407e0ea187d204ed3694c..e88c792ec1d0b4934633c264b77943367486f8b9
100644
--- a/src/compiler/machine-operator.cc
+++ b/src/compiler/machine-operator.cc
@@ -119,7 +119,8 @@ struct StaticParameterTraits<LoadRepresentation> {
V(Float64Sqrt, Operator::kNoProperties, 1,
1) \
V(Float64Equal, Operator::kCommutative, 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) \
Index: src/compiler/machine-operator.h
diff --git a/src/compiler/machine-operator.h
b/src/compiler/machine-operator.h
index
622f863929ab01eb4ff2485d45129d17a6456246..ad54f98fa9acf7cb24d994f5542608d321794abd
100644
--- a/src/compiler/machine-operator.h
+++ b/src/compiler/machine-operator.h
@@ -144,6 +144,9 @@ class MachineOperatorBuilder FINAL {
// store [base + index], value
const Operator* Store(StoreRepresentation rep);
+ // Access to the machine stack.
+ const Operator* LoadStackPointer();
+
// Target machine word-size assumed by this builder.
bool Is32() const { return word() == kRepWord32; }
bool Is64() const { return word() == kRepWord64; }
Index: src/compiler/opcodes.h
diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h
index
2d9819c9c953be3ac645ae71071a4855fb80abab..e45299419f4b44197b461b2dc6417df6ed3f0c25
100644
--- a/src/compiler/opcodes.h
+++ b/src/compiler/opcodes.h
@@ -222,7 +222,8 @@
V(Float64Sqrt) \
V(Float64Equal) \
V(Float64LessThan) \
- V(Float64LessThanOrEqual)
+ V(Float64LessThanOrEqual) \
+ V(LoadStackPointer)
#define VALUE_OP_LIST(V) \
COMMON_OP_LIST(V) \
Index: src/compiler/simplified-lowering.cc
diff --git a/src/compiler/simplified-lowering.cc
b/src/compiler/simplified-lowering.cc
index
c4709898a51e8ec966602caa71ab382692de2529..583fc86af4c7f84c1a8c0e4fe7e6a8f408c10826
100644
--- a/src/compiler/simplified-lowering.cc
+++ b/src/compiler/simplified-lowering.cc
@@ -612,7 +612,7 @@ class RepresentationSelector {
//------------------------------------------------------------------
case IrOpcode::kLoad: {
// TODO(titzer): machine loads/stores need to know BaseTaggedness!?
- MachineType tBase = kRepTagged;
+ MachineTypeUnion tBase = kRepTagged | kMachPtr;
LoadRepresentation rep = OpParameter<LoadRepresentation>(node);
ProcessInput(node, 0, tBase); // pointer or object
ProcessInput(node, 1, kMachInt32); // index
@@ -622,7 +622,7 @@ class RepresentationSelector {
}
case IrOpcode::kStore: {
// TODO(titzer): machine loads/stores need to know BaseTaggedness!?
- MachineType tBase = kRepTagged;
+ MachineTypeUnion tBase = kRepTagged | kMachPtr;
StoreRepresentation rep = OpParameter<StoreRepresentation>(node);
ProcessInput(node, 0, tBase); // pointer or object
ProcessInput(node, 1, kMachInt32); // index
@@ -732,6 +732,8 @@ class RepresentationSelector {
case IrOpcode::kFloat64LessThan:
case IrOpcode::kFloat64LessThanOrEqual:
return VisitFloat64Cmp(node);
+ case IrOpcode::kLoadStackPointer:
+ return VisitLeaf(node, kMachPtr);
default:
VisitInputs(node);
break;
Index: src/compiler/x64/code-generator-x64.cc
diff --git a/src/compiler/x64/code-generator-x64.cc
b/src/compiler/x64/code-generator-x64.cc
index
2c8783322ef2dbc7e2f60d7d576db378cb8c09b2..37aca107a2320a224fb3c0f55f7fd78e35858080
100644
--- a/src/compiler/x64/code-generator-x64.cc
+++ b/src/compiler/x64/code-generator-x64.cc
@@ -233,6 +233,9 @@ void
CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchRet:
AssembleReturn();
break;
+ case kArchStackPointer:
+ __ movq(i.OutputRegister(), rsp);
+ break;
case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
break;
Index: test/cctest/cctest.gyp
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index
eecadd62be27b52323c23b99d44a6cb58d3f1889..fdcffba974d98f0061028b7df33830ae34aa3f1e
100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -81,6 +81,7 @@
'compiler/test-run-jsops.cc',
'compiler/test-run-machops.cc',
'compiler/test-run-properties.cc',
+ 'compiler/test-run-stackcheck.cc',
'compiler/test-run-variables.cc',
'compiler/test-schedule.cc',
'compiler/test-scheduler.cc',
Index: test/cctest/compiler/test-run-stackcheck.cc
diff --git a/test/cctest/compiler/test-run-stackcheck.cc
b/test/cctest/compiler/test-run-stackcheck.cc
new file mode 100644
index
0000000000000000000000000000000000000000..8c1664bc832fe83633f109851bea35df2877e6f8
--- /dev/null
+++ b/test/cctest/compiler/test-run-stackcheck.cc
@@ -0,0 +1,18 @@
+// 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());
+}
Index: test/unittests/compiler/machine-operator-unittest.cc
diff --git a/test/unittests/compiler/machine-operator-unittest.cc
b/test/unittests/compiler/machine-operator-unittest.cc
index
db73a8155c1277c333180cfdc1de8b44c4a01bf5..4f56181242aec936e3e00840aaaab948852101dd
100644
--- a/test/unittests/compiler/machine-operator-unittest.cc
+++ b/test/unittests/compiler/machine-operator-unittest.cc
@@ -201,7 +201,7 @@ const PureOperator kPureOperators[] = {
PURE(Float64Mul, 2, 1), PURE(Float64Div, 2, 1),
PURE(Float64Mod, 2, 1), PURE(Float64Sqrt, 1, 1),
PURE(Float64Equal, 2, 1), PURE(Float64LessThan, 2, 1),
- PURE(Float64LessThanOrEqual, 2, 1)
+ PURE(Float64LessThanOrEqual, 2, 1), PURE(LoadStackPointer, 0, 1)
#undef PURE
};
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.