v8/test/unittests/compiler/js-operator-unittest.cc
mstarzinger ea26401266 [turbofan] Call FastNewContextStub for function context.
This lowers JSCreateFunctionContext nodes to call the above stub for
help with allocating function contexts when possible. It also contains
an implementation for inlined allocations of such contexts, which is
still behind a flag until inlined allocations are ready for prime time.

TEST=unittests/JSTypedLoweringTest.JSCreateFunctionContext
R=mvstanton@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#31068}
2015-10-02 09:30:21 +00:00

284 lines
10 KiB
C++

// 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/compiler/js-operator.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
#include "src/compiler/operator-properties.h"
#include "test/unittests/test-utils.h"
namespace v8 {
namespace internal {
namespace compiler {
namespace {
const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};
#if GTEST_HAS_COMBINE
template <typename T>
class JSOperatorTestWithLanguageModeAndParam
: public TestWithZone,
public ::testing::WithParamInterface<::testing::tuple<LanguageMode, T>> {
protected:
LanguageMode language_mode() const {
return ::testing::get<0>(B::GetParam());
}
const T& GetParam() const { return ::testing::get<1>(B::GetParam()); }
private:
typedef ::testing::WithParamInterface<::testing::tuple<LanguageMode, T>> B;
};
#endif // GTEST_HAS_COMBINE
} // namespace
// -----------------------------------------------------------------------------
// Shared operators without language mode.
namespace {
struct SharedOperator {
const Operator* (JSOperatorBuilder::*constructor)();
IrOpcode::Value opcode;
Operator::Properties properties;
int value_input_count;
int frame_state_input_count;
int effect_input_count;
int control_input_count;
int value_output_count;
int effect_output_count;
int control_output_count;
};
const SharedOperator kSharedOperators[] = {
#define SHARED(Name, properties, value_input_count, frame_state_input_count, \
effect_input_count, control_input_count, value_output_count, \
effect_output_count, control_output_count) \
{ \
&JSOperatorBuilder::Name, IrOpcode::kJS##Name, properties, \
value_input_count, frame_state_input_count, effect_input_count, \
control_input_count, value_output_count, effect_output_count, \
control_output_count \
}
SHARED(Equal, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(NotEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(StrictEqual, Operator::kNoThrow, 2, 0, 1, 1, 1, 1, 0),
SHARED(StrictNotEqual, Operator::kNoThrow, 2, 0, 1, 1, 1, 1, 0),
SHARED(UnaryNot, Operator::kEliminatable, 1, 0, 1, 0, 1, 1, 0),
SHARED(ToBoolean, Operator::kEliminatable, 1, 0, 1, 0, 1, 1, 0),
SHARED(ToNumber, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
SHARED(ToString, Operator::kNoProperties, 1, 0, 1, 1, 1, 1, 2),
SHARED(ToName, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
SHARED(ToObject, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1, 2),
SHARED(Create, Operator::kEliminatable, 0, 0, 1, 0, 1, 1, 0),
SHARED(HasProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(TypeOf, Operator::kEliminatable, 1, 0, 1, 0, 1, 1, 0),
SHARED(InstanceOf, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(CreateWithContext, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(CreateModuleContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
#undef SHARED
};
std::ostream& operator<<(std::ostream& os, const SharedOperator& sop) {
return os << IrOpcode::Mnemonic(sop.opcode);
}
} // namespace
class JSSharedOperatorTest
: public TestWithZone,
public ::testing::WithParamInterface<SharedOperator> {};
TEST_P(JSSharedOperatorTest, InstancesAreGloballyShared) {
const SharedOperator& sop = GetParam();
JSOperatorBuilder javascript1(zone());
JSOperatorBuilder javascript2(zone());
EXPECT_EQ((javascript1.*sop.constructor)(), (javascript2.*sop.constructor)());
}
TEST_P(JSSharedOperatorTest, NumberOfInputsAndOutputs) {
JSOperatorBuilder javascript(zone());
const SharedOperator& sop = GetParam();
const Operator* op = (javascript.*sop.constructor)();
const int context_input_count = 1;
EXPECT_EQ(sop.value_input_count, op->ValueInputCount());
EXPECT_EQ(context_input_count, OperatorProperties::GetContextInputCount(op));
EXPECT_EQ(sop.frame_state_input_count,
OperatorProperties::GetFrameStateInputCount(op));
EXPECT_EQ(sop.effect_input_count, op->EffectInputCount());
EXPECT_EQ(sop.control_input_count, op->ControlInputCount());
EXPECT_EQ(sop.value_input_count + context_input_count +
sop.frame_state_input_count + sop.effect_input_count +
sop.control_input_count,
OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
}
TEST_P(JSSharedOperatorTest, OpcodeIsCorrect) {
JSOperatorBuilder javascript(zone());
const SharedOperator& sop = GetParam();
const Operator* op = (javascript.*sop.constructor)();
EXPECT_EQ(sop.opcode, op->opcode());
}
TEST_P(JSSharedOperatorTest, Properties) {
JSOperatorBuilder javascript(zone());
const SharedOperator& sop = GetParam();
const Operator* op = (javascript.*sop.constructor)();
EXPECT_EQ(sop.properties, op->properties());
}
INSTANTIATE_TEST_CASE_P(JSOperatorTest, JSSharedOperatorTest,
::testing::ValuesIn(kSharedOperators));
// -----------------------------------------------------------------------------
// Shared operators with language mode.
#if GTEST_HAS_COMBINE
namespace {
struct SharedOperatorWithLanguageMode {
const Operator* (JSOperatorBuilder::*constructor)(LanguageMode);
IrOpcode::Value opcode;
Operator::Properties properties;
int value_input_count;
int frame_state_input_count;
int effect_input_count;
int control_input_count;
int value_output_count;
int effect_output_count;
int control_output_count;
};
const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = {
#define SHARED(Name, properties, value_input_count, frame_state_input_count, \
effect_input_count, control_input_count, value_output_count, \
effect_output_count, control_output_count) \
{ \
&JSOperatorBuilder::Name, IrOpcode::kJS##Name, properties, \
value_input_count, frame_state_input_count, effect_input_count, \
control_input_count, value_output_count, effect_output_count, \
control_output_count \
}
SHARED(LessThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(GreaterThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(BitwiseOr, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(BitwiseXor, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(BitwiseAnd, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(ShiftLeft, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(ShiftRight, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(ShiftRightLogical, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(Add, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(Subtract, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(Multiply, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(Divide, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(Modulus, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
#undef SHARED
};
std::ostream& operator<<(std::ostream& os,
const SharedOperatorWithLanguageMode& sop) {
return os << IrOpcode::Mnemonic(sop.opcode);
}
} // namespace
class JSSharedOperatorWithLanguageModeTest
: public JSOperatorTestWithLanguageModeAndParam<
SharedOperatorWithLanguageMode> {};
TEST_P(JSSharedOperatorWithLanguageModeTest, InstancesAreGloballyShared) {
const SharedOperatorWithLanguageMode& sop = GetParam();
JSOperatorBuilder javascript1(zone());
JSOperatorBuilder javascript2(zone());
EXPECT_EQ((javascript1.*sop.constructor)(language_mode()),
(javascript2.*sop.constructor)(language_mode()));
}
TEST_P(JSSharedOperatorWithLanguageModeTest, NumberOfInputsAndOutputs) {
JSOperatorBuilder javascript(zone());
const SharedOperatorWithLanguageMode& sop = GetParam();
const Operator* op = (javascript.*sop.constructor)(language_mode());
const int context_input_count = 1;
EXPECT_EQ(sop.value_input_count, op->ValueInputCount());
EXPECT_EQ(context_input_count, OperatorProperties::GetContextInputCount(op));
EXPECT_EQ(sop.frame_state_input_count,
OperatorProperties::GetFrameStateInputCount(op));
EXPECT_EQ(sop.effect_input_count, op->EffectInputCount());
EXPECT_EQ(sop.control_input_count, op->ControlInputCount());
EXPECT_EQ(sop.value_input_count + context_input_count +
sop.frame_state_input_count + sop.effect_input_count +
sop.control_input_count,
OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
}
TEST_P(JSSharedOperatorWithLanguageModeTest, OpcodeIsCorrect) {
JSOperatorBuilder javascript(zone());
const SharedOperatorWithLanguageMode& sop = GetParam();
const Operator* op = (javascript.*sop.constructor)(language_mode());
EXPECT_EQ(sop.opcode, op->opcode());
}
TEST_P(JSSharedOperatorWithLanguageModeTest, Parameter) {
JSOperatorBuilder javascript(zone());
const SharedOperatorWithLanguageMode& sop = GetParam();
const Operator* op = (javascript.*sop.constructor)(language_mode());
EXPECT_EQ(language_mode(), OpParameter<LanguageMode>(op));
}
TEST_P(JSSharedOperatorWithLanguageModeTest, Properties) {
JSOperatorBuilder javascript(zone());
const SharedOperatorWithLanguageMode& sop = GetParam();
const Operator* op = (javascript.*sop.constructor)(language_mode());
EXPECT_EQ(sop.properties, op->properties());
}
INSTANTIATE_TEST_CASE_P(
JSOperatorTest, JSSharedOperatorWithLanguageModeTest,
::testing::Combine(::testing::ValuesIn(kLanguageModes),
::testing::ValuesIn(kSharedOperatorsWithLanguageMode)));
#endif // GTEST_HAS_COMBINE
} // namespace compiler
} // namespace internal
} // namespace v8