Add speculation mode to Call node

This patch adds a field for the speculation mode to Call
nodes, and passes the speculation mode from the CallIC
to the Call node in the byte code graph builder.

Bug: v8:7127
Change-Id: I89fa10643b46143b36776de1d5ba6ebe3fa2c878
Reviewed-on: https://chromium-review.googlesource.com/814537
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49965}
This commit is contained in:
Sigurd Schneider 2017-12-08 15:07:56 +01:00 committed by Commit Bot
parent 325a56cdd1
commit 47a81f0bd2
8 changed files with 54 additions and 18 deletions

View File

@ -1610,7 +1610,8 @@ void BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode,
CallFrequency frequency = ComputeCallFrequency(slot_id);
const Operator* op =
javascript()->Call(arg_count, frequency, feedback, receiver_mode);
javascript()->Call(arg_count, frequency, feedback, receiver_mode,
GetSpeculationMode(slot_id));
JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall(
op, args, static_cast<int>(arg_count), feedback.slot());
if (lowering.IsExit()) return;
@ -2105,6 +2106,11 @@ CallFrequency BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const {
invocation_frequency_.value());
}
SpeculationMode BytecodeGraphBuilder::GetSpeculationMode(int slot_id) const {
CallICNexus nexus(feedback_vector(), feedback_vector()->ToSlot(slot_id));
return nexus.GetSpeculationMode();
}
void BytecodeGraphBuilder::VisitBitwiseNot() {
BuildUnaryOp(javascript()->BitwiseNot());
}

View File

@ -235,6 +235,10 @@ class BytecodeGraphBuilder {
// feedback.
CallFrequency ComputeCallFrequency(int slot_id) const;
// Helper function to extract the speulcation mode from the recorded type
// feedback.
SpeculationMode GetSpeculationMode(int slot_id) const;
// Control flow plumbing.
void BuildJump();
void BuildJumpIf(Node* condition);

View File

@ -740,8 +740,10 @@ const Operator* JSOperatorBuilder::CallForwardVarargs(size_t arity,
const Operator* JSOperatorBuilder::Call(size_t arity, CallFrequency frequency,
VectorSlotPair const& feedback,
ConvertReceiverMode convert_mode) {
CallParameters parameters(arity, frequency, feedback, convert_mode);
ConvertReceiverMode convert_mode,
SpeculationMode speculation_mode) {
CallParameters parameters(arity, frequency, feedback, convert_mode,
speculation_mode);
return new (zone()) Operator1<CallParameters>( // --
IrOpcode::kJSCall, Operator::kNoProperties, // opcode
"JSCall", // name
@ -758,9 +760,10 @@ const Operator* JSOperatorBuilder::CallWithArrayLike(CallFrequency frequency) {
}
const Operator* JSOperatorBuilder::CallWithSpread(
uint32_t arity, CallFrequency frequency, VectorSlotPair const& feedback) {
uint32_t arity, CallFrequency frequency, VectorSlotPair const& feedback,
SpeculationMode speculation_mode) {
CallParameters parameters(arity, frequency, feedback,
ConvertReceiverMode::kAny);
ConvertReceiverMode::kAny, speculation_mode);
return new (zone()) Operator1<CallParameters>( // --
IrOpcode::kJSCallWithSpread, Operator::kNoProperties, // opcode
"JSCallWithSpread", // name

View File

@ -161,8 +161,10 @@ class CallParameters final {
public:
CallParameters(size_t arity, CallFrequency frequency,
VectorSlotPair const& feedback,
ConvertReceiverMode convert_mode)
ConvertReceiverMode convert_mode,
SpeculationMode speculation_mode)
: bit_field_(ArityField::encode(arity) |
SpeculationModeField::encode(speculation_mode) |
ConvertReceiverModeField::encode(convert_mode)),
frequency_(frequency),
feedback_(feedback) {}
@ -174,6 +176,10 @@ class CallParameters final {
}
VectorSlotPair const& feedback() const { return feedback_; }
SpeculationMode speculation_mode() const {
return SpeculationModeField::decode(bit_field_);
}
bool operator==(CallParameters const& that) const {
return this->bit_field_ == that.bit_field_ &&
this->frequency_ == that.frequency_ &&
@ -186,7 +192,8 @@ class CallParameters final {
return base::hash_combine(p.bit_field_, p.frequency_, p.feedback_);
}
typedef BitField<size_t, 0, 29> ArityField;
typedef BitField<size_t, 0, 28> ArityField;
typedef BitField<SpeculationMode, 28, 1> SpeculationModeField;
typedef BitField<ConvertReceiverMode, 29, 2> ConvertReceiverModeField;
uint32_t const bit_field_;
@ -667,11 +674,13 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* Call(
size_t arity, CallFrequency frequency = CallFrequency(),
VectorSlotPair const& feedback = VectorSlotPair(),
ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny);
ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny,
SpeculationMode speculation_mode = SpeculationMode::kAllowSpeculation);
const Operator* CallWithArrayLike(CallFrequency frequency);
const Operator* CallWithSpread(
uint32_t arity, CallFrequency frequency = CallFrequency(),
VectorSlotPair const& feedback = VectorSlotPair());
VectorSlotPair const& feedback = VectorSlotPair(),
SpeculationMode speculation_mode = SpeculationMode::kAllowSpeculation);
const Operator* CallRuntime(Runtime::FunctionId id);
const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
const Operator* CallRuntime(const Runtime::Function* function, size_t arity);

View File

@ -691,7 +691,7 @@ void CallICNexus::SetSpeculationMode(SpeculationMode mode) {
SetFeedbackExtra(Smi::FromInt(result), SKIP_WRITE_BARRIER);
}
CallICNexus::SpeculationMode CallICNexus::GetSpeculationMode() {
SpeculationMode CallICNexus::GetSpeculationMode() {
Object* call_count = GetFeedbackExtra();
CHECK(call_count->IsSmi());
uint32_t value = static_cast<uint32_t>(Smi::ToInt(call_count));

View File

@ -10,6 +10,7 @@
#include "src/base/logging.h"
#include "src/base/macros.h"
#include "src/elements-kind.h"
#include "src/globals.h"
#include "src/objects/map.h"
#include "src/objects/name.h"
#include "src/objects/object-macros.h"
@ -623,7 +624,6 @@ class FeedbackNexus {
class CallICNexus final : public FeedbackNexus {
public:
enum SpeculationMode { kAllowSpeculation, kDisallowSpeculation };
CallICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
: FeedbackNexus(vector, slot) {
DCHECK(vector->IsCallIC(slot));

View File

@ -1445,6 +1445,20 @@ inline std::ostream& operator<<(std::ostream& os,
return os;
}
enum class SpeculationMode { kAllowSpeculation, kDisallowSpeculation };
inline std::ostream& operator<<(std::ostream& os,
SpeculationMode speculation_mode) {
switch (speculation_mode) {
case SpeculationMode::kAllowSpeculation:
return os << "SpeculationMode::kAllowSpeculation";
case SpeculationMode::kDisallowSpeculation:
return os << "SpeculationMode::kDisallowSpeculation";
}
UNREACHABLE();
return os;
}
enum class ConcurrencyMode { kNotConcurrent, kConcurrent };
#define FOR_EACH_ISOLATE_ADDRESS_NAME(C) \

View File

@ -313,17 +313,17 @@ TEST(VectorSpeculationMode) {
FeedbackSlot slot(0);
CallICNexus nexus(feedback_vector, slot);
CHECK_EQ(CallICNexus::kAllowSpeculation, nexus.GetSpeculationMode());
CHECK_EQ(SpeculationMode::kAllowSpeculation, nexus.GetSpeculationMode());
CompileRun("f(Foo); f(Foo);");
CHECK_EQ(3, nexus.GetCallCount());
CHECK_EQ(CallICNexus::kAllowSpeculation, nexus.GetSpeculationMode());
CHECK_EQ(SpeculationMode::kAllowSpeculation, nexus.GetSpeculationMode());
nexus.SetSpeculationMode(CallICNexus::kAllowSpeculation);
nexus.SetSpeculationMode(CallICNexus::kDisallowSpeculation);
CHECK_EQ(CallICNexus::kDisallowSpeculation, nexus.GetSpeculationMode());
nexus.SetSpeculationMode(CallICNexus::kAllowSpeculation);
CHECK_EQ(CallICNexus::kAllowSpeculation, nexus.GetSpeculationMode());
nexus.SetSpeculationMode(SpeculationMode::kAllowSpeculation);
nexus.SetSpeculationMode(SpeculationMode::kDisallowSpeculation);
CHECK_EQ(SpeculationMode::kDisallowSpeculation, nexus.GetSpeculationMode());
nexus.SetSpeculationMode(SpeculationMode::kAllowSpeculation);
CHECK_EQ(SpeculationMode::kAllowSpeculation, nexus.GetSpeculationMode());
}
TEST(VectorLoadICStates) {