Index: src/crankshaft/hydrogen-instructions.h |
diff --git a/src/crankshaft/hydrogen-instructions.h b/src/crankshaft/hydrogen-instructions.h |
index 1cc0820785e785057e7915e789ba005ebd0b8b79..ea9be601a771760bd2fdd4e4fcbcf115d02bbebe 100644 |
--- a/src/crankshaft/hydrogen-instructions.h |
+++ b/src/crankshaft/hydrogen-instructions.h |
@@ -2214,19 +2214,17 @@ class HBinaryCall : public HCall<2> { |
}; |
-enum CallMode { NORMAL_CALL, TAIL_CALL }; |
- |
- |
class HCallWithDescriptor final : public HInstruction { |
public: |
- static HCallWithDescriptor* New(Isolate* isolate, Zone* zone, HValue* context, |
- HValue* target, int argument_count, |
- CallInterfaceDescriptor descriptor, |
- const Vector<HValue*>& operands, |
- CallMode call_mode = NORMAL_CALL) { |
- HCallWithDescriptor* res = new (zone) HCallWithDescriptor( |
- target, argument_count, descriptor, operands, call_mode, zone); |
- DCHECK_EQ(operands.length(), res->GetParameterCount()); |
+ static HCallWithDescriptor* New( |
+ Isolate* isolate, Zone* zone, HValue* context, HValue* target, |
+ int argument_count, CallInterfaceDescriptor descriptor, |
+ const Vector<HValue*>& operands, |
+ TailCallMode syntactic_tail_call_mode = TailCallMode::kDisallow, |
+ TailCallMode tail_call_mode = TailCallMode::kDisallow) { |
+ HCallWithDescriptor* res = new (zone) |
+ HCallWithDescriptor(target, argument_count, descriptor, operands, |
+ syntactic_tail_call_mode, tail_call_mode, zone); |
return res; |
} |
@@ -2248,7 +2246,16 @@ class HCallWithDescriptor final : public HInstruction { |
HType CalculateInferredType() final { return HType::Tagged(); } |
- bool IsTailCall() const { return call_mode_ == TAIL_CALL; } |
+ // Defines whether this instruction corresponds to a JS call at tail position. |
+ TailCallMode syntactic_tail_call_mode() const { |
+ return SyntacticTailCallModeField::decode(bit_field_); |
+ } |
+ |
+ // Defines whether this call should be generated as a tail call. |
+ TailCallMode tail_call_mode() const { |
+ return TailCallModeField::decode(bit_field_); |
+ } |
+ bool IsTailCall() const { return tail_call_mode() == TailCallMode::kAllow; } |
virtual int argument_count() const { |
return argument_count_; |
@@ -2268,14 +2275,18 @@ class HCallWithDescriptor final : public HInstruction { |
// The argument count includes the receiver. |
HCallWithDescriptor(HValue* target, int argument_count, |
CallInterfaceDescriptor descriptor, |
- const Vector<HValue*>& operands, CallMode call_mode, |
- Zone* zone) |
+ const Vector<HValue*>& operands, |
+ TailCallMode syntactic_tail_call_mode, |
+ TailCallMode tail_call_mode, Zone* zone) |
: descriptor_(descriptor), |
values_(GetParameterCount() + 1, zone), |
argument_count_(argument_count), |
- call_mode_(call_mode) { |
+ bit_field_( |
+ TailCallModeField::encode(tail_call_mode) | |
+ SyntacticTailCallModeField::encode(syntactic_tail_call_mode)) { |
+ DCHECK_EQ(operands.length(), GetParameterCount()); |
// We can only tail call without any stack arguments. |
- DCHECK(call_mode != TAIL_CALL || argument_count == 0); |
+ DCHECK(tail_call_mode != TailCallMode::kAllow || argument_count == 0); |
AddOperand(target, zone); |
for (int i = 0; i < operands.length(); i++) { |
AddOperand(operands[i], zone); |
@@ -2300,15 +2311,18 @@ class HCallWithDescriptor final : public HInstruction { |
CallInterfaceDescriptor descriptor_; |
ZoneList<HValue*> values_; |
int argument_count_; |
- CallMode call_mode_; |
+ class TailCallModeField : public BitField<TailCallMode, 0, 1> {}; |
+ class SyntacticTailCallModeField |
+ : public BitField<TailCallMode, TailCallModeField::kNext, 1> {}; |
+ uint32_t bit_field_; |
}; |
class HInvokeFunction final : public HBinaryCall { |
public: |
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HInvokeFunction, HValue*, |
+ DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HInvokeFunction, HValue*, |
Handle<JSFunction>, int, |
- TailCallMode); |
+ TailCallMode, TailCallMode); |
HValue* context() { return first(); } |
HValue* function() { return second(); } |
@@ -2316,12 +2330,22 @@ class HInvokeFunction final : public HBinaryCall { |
int formal_parameter_count() const { return formal_parameter_count_; } |
bool HasStackCheck() final { return HasStackCheckField::decode(bit_field_); } |
+ |
+ // Defines whether this instruction corresponds to a JS call at tail position. |
+ TailCallMode syntactic_tail_call_mode() const { |
+ return SyntacticTailCallModeField::decode(bit_field_); |
+ } |
+ |
+ // Defines whether this call should be generated as a tail call. |
TailCallMode tail_call_mode() const { |
return TailCallModeField::decode(bit_field_); |
} |
DECLARE_CONCRETE_INSTRUCTION(InvokeFunction) |
+ std::ostream& PrintTo(std::ostream& os) const override; // NOLINT |
+ std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT |
+ |
private: |
void set_has_stack_check(bool has_stack_check) { |
bit_field_ = HasStackCheckField::update(bit_field_, has_stack_check); |
@@ -2329,10 +2353,15 @@ class HInvokeFunction final : public HBinaryCall { |
HInvokeFunction(HValue* context, HValue* function, |
Handle<JSFunction> known_function, int argument_count, |
+ TailCallMode syntactic_tail_call_mode, |
TailCallMode tail_call_mode) |
: HBinaryCall(context, function, argument_count), |
known_function_(known_function), |
- bit_field_(TailCallModeField::encode(tail_call_mode)) { |
+ bit_field_( |
+ TailCallModeField::encode(tail_call_mode) | |
+ SyntacticTailCallModeField::encode(syntactic_tail_call_mode)) { |
+ DCHECK(tail_call_mode != TailCallMode::kAllow || |
+ syntactic_tail_call_mode == TailCallMode::kAllow); |
formal_parameter_count_ = |
known_function.is_null() |
? 0 |
@@ -2349,6 +2378,8 @@ class HInvokeFunction final : public HBinaryCall { |
class HasStackCheckField : public BitField<bool, 0, 1> {}; |
class TailCallModeField |
: public BitField<TailCallMode, HasStackCheckField::kNext, 1> {}; |
+ class SyntacticTailCallModeField |
+ : public BitField<TailCallMode, TailCallModeField::kNext, 1> {}; |
uint32_t bit_field_; |
}; |