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:
parent
325a56cdd1
commit
47a81f0bd2
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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) \
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user