411c5b7fb0
Also remove the ResultMode from ToBooleanStub and always return true or false and use the same mechanism in fullcodegen. This is in preparation for adding ToBoolean hints to TurboFan. Drive-by-fix: We can use the power of the ToBooleanIC in TurboFan now that the ResultMode is gone (and the runtime always returns true or false from the miss handler). R=mstarzinger@chromium.org BUG=v8:4583 LOG=n Review URL: https://codereview.chromium.org/1491223002 Cr-Commit-Position: refs/heads/master@{#32524}
272 lines
9.6 KiB
C++
272 lines
9.6 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(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, 1, 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, 2, 1, 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),
|
|
#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
|