From 47a81f0bd2a29099c107bb157f66a52d6f950ce6 Mon Sep 17 00:00:00 2001 From: Sigurd Schneider Date: Fri, 8 Dec 2017 15:07:56 +0100 Subject: [PATCH] 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 Reviewed-by: Michael Starzinger Cr-Commit-Position: refs/heads/master@{#49965} --- src/compiler/bytecode-graph-builder.cc | 8 +++++++- src/compiler/bytecode-graph-builder.h | 4 ++++ src/compiler/js-operator.cc | 11 +++++++---- src/compiler/js-operator.h | 17 +++++++++++++---- src/feedback-vector.cc | 2 +- src/feedback-vector.h | 2 +- src/globals.h | 14 ++++++++++++++ test/cctest/test-feedback-vector.cc | 14 +++++++------- 8 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc index 7e0700b599..188ea45586 100644 --- a/src/compiler/bytecode-graph-builder.cc +++ b/src/compiler/bytecode-graph-builder.cc @@ -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(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()); } diff --git a/src/compiler/bytecode-graph-builder.h b/src/compiler/bytecode-graph-builder.h index 82eb4c0780..8f11cd7a80 100644 --- a/src/compiler/bytecode-graph-builder.h +++ b/src/compiler/bytecode-graph-builder.h @@ -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); diff --git a/src/compiler/js-operator.cc b/src/compiler/js-operator.cc index 6a310f7e52..d29b00b98c 100644 --- a/src/compiler/js-operator.cc +++ b/src/compiler/js-operator.cc @@ -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( // -- 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( // -- IrOpcode::kJSCallWithSpread, Operator::kNoProperties, // opcode "JSCallWithSpread", // name diff --git a/src/compiler/js-operator.h b/src/compiler/js-operator.h index 7996c6944c..3829c73b97 100644 --- a/src/compiler/js-operator.h +++ b/src/compiler/js-operator.h @@ -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 ArityField; + typedef BitField ArityField; + typedef BitField SpeculationModeField; typedef BitField 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); diff --git a/src/feedback-vector.cc b/src/feedback-vector.cc index 0589577ee6..4d3cea5bec 100644 --- a/src/feedback-vector.cc +++ b/src/feedback-vector.cc @@ -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(Smi::ToInt(call_count)); diff --git a/src/feedback-vector.h b/src/feedback-vector.h index 952ec40c9e..c97a6870bc 100644 --- a/src/feedback-vector.h +++ b/src/feedback-vector.h @@ -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 vector, FeedbackSlot slot) : FeedbackNexus(vector, slot) { DCHECK(vector->IsCallIC(slot)); diff --git a/src/globals.h b/src/globals.h index 1df891edb9..4159834581 100644 --- a/src/globals.h +++ b/src/globals.h @@ -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) \ diff --git a/test/cctest/test-feedback-vector.cc b/test/cctest/test-feedback-vector.cc index 7d4cecd057..e590b60649 100644 --- a/test/cctest/test-feedback-vector.cc +++ b/test/cctest/test-feedback-vector.cc @@ -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) {